blob: 74adc877dcd5d0f063bc182b92665cebeb439793 [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 *
Chris Allegretta3a24f3f2001-10-24 11:33:54 +00008 * the Free Software Foundation; either version 2, or (at your option) *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00009 * 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
Chris Allegretta6efda542001-04-28 18:03:52 +000022#include "config.h"
23
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000024#include <stdio.h>
25#include <stdlib.h>
26#include <stdarg.h>
27#include <signal.h>
Chris Allegretta08020882001-01-29 23:37:54 +000028#include <setjmp.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000029#include <unistd.h>
30#include <string.h>
31#include <fcntl.h>
32#include <sys/stat.h>
33#include <sys/ioctl.h>
34#include <sys/param.h>
Chris Allegretta27eb13f2000-11-05 16:52:21 +000035#include <sys/types.h>
36#include <sys/wait.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000037#include <errno.h>
38#include <ctype.h>
39#include <locale.h>
40#include <limits.h>
Adam Rogoyski77f36de2000-06-07 03:56:54 +000041#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000042
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000043#include "proto.h"
44#include "nano.h"
45
46#ifndef NANO_SMALL
47#include <libintl.h>
48#define _(string) gettext(string)
49#else
50#define _(string) (string)
51#endif
52
53#ifdef HAVE_TERMIOS_H
54#include <termios.h>
55#endif
56
57#ifdef HAVE_TERMIO_H
58#include <termio.h>
59#endif
60
61#ifdef HAVE_GETOPT_H
62#include <getopt.h>
63#endif
64
Chris Allegretta6fe61492001-05-21 12:56:25 +000065#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000066/* Former globals, now static */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000067int fill = 0; /* Fill - where to wrap lines, basically */
Chris Allegretta6fe61492001-05-21 12:56:25 +000068int wrap_at = 0; /* Right justified fill value, allows resize */
69#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +000070
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000071struct termios oldterm; /* The user's original term settings */
Chris Allegretta88520c92001-05-05 17:45:54 +000072static struct sigaction act; /* For all our fun signal handlers */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000073
Rocco Corsiaf5c3022001-01-12 07:51:05 +000074#ifndef DISABLE_HELP
Chris Allegretta6b58acd2001-04-12 03:01:53 +000075static char *help_text_init = ""; /* Initial message, not including shortcuts */
Chris Allegretta65121632000-12-18 07:05:27 +000076#endif
77
Chris Allegretta27eb13f2000-11-05 16:52:21 +000078char *last_search = NULL; /* Last string we searched for */
79char *last_replace = NULL; /* Last replacement string */
80int search_last_line; /* Is this the last search line? */
81
Chris Allegretta08020882001-01-29 23:37:54 +000082static sigjmp_buf jmpbuf; /* Used to return to mainloop after SIGWINCH */
83
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000084/* What we do when we're all set to exit */
85RETSIGTYPE finish(int sigage)
86{
Chris Allegrettac08f50d2001-01-06 18:12:43 +000087
88 keypad(edit, TRUE);
89 keypad(bottomwin, TRUE);
90
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000091 if (!ISSET(NO_HELP)) {
92 mvwaddstr(bottomwin, 1, 0, hblank);
93 mvwaddstr(bottomwin, 2, 0, hblank);
Chris Allegretta4da1fc62000-06-21 03:00:43 +000094 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000095 mvwaddstr(bottomwin, 0, 0, hblank);
Chris Allegretta6b58acd2001-04-12 03:01:53 +000096
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000097 wrefresh(bottomwin);
98 endwin();
99
100 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000101 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000102
103 exit(sigage);
104}
105
106/* Die (gracefully?) */
107void die(char *msg, ...)
108{
109 va_list ap;
110
111 va_start(ap, msg);
112 vfprintf(stderr, msg, ap);
113 va_end(ap);
114
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000115 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000116 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000117
118 clear();
119 refresh();
120 resetty();
121 endwin();
122
123 fprintf(stderr, msg);
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000124
125 /* save the currently loaded file (if modified, its open_files entry
126 isn't up to date) */
127 die_save_file(filename);
128
Chris Allegretta355fbe52001-07-14 19:32:47 +0000129#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000130 /* then save all of the other loaded files, if any */
131 if (open_files) {
132 filestruct *tmp;
133
134 tmp = open_files;
135
136 while (open_files->prev)
137 open_files = open_files->prev;
138
139 while (open_files->next) {
140
141 /* if we already saved the file above (i. e. if it was the
142 currently loaded file), don't save it again */
143 if (tmp != open_files) {
144 fileage = open_files->file;
145 die_save_file(open_files->data);
146 }
147
148 open_files = open_files->next;
149 }
150
151 }
152#endif
153
154 exit(1); /* We have a problem: exit w/ errorlevel(1) */
155}
156
157void die_save_file(char *die_filename)
158{
159 char *name;
160 int i;
161
162 /* if we can't save we have REAL bad problems,
163 * but we might as well TRY. */
164 if (die_filename[0] == '\0') {
165 name = "nano.save";
166 i = write_file(name, 1, 0, 0);
167 } else {
168
169 char *buf = charalloc(strlen(die_filename) + 6);
170 strcpy(buf, die_filename);
171 strcat(buf, ".save");
172 i = write_file(buf, 1, 0, 0);
173 name = buf;
174 }
175
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000176 if (i != -1)
177 fprintf(stderr, _("\nBuffer written to %s\n"), name);
178 else
Chris Allegretta9756d622000-12-03 03:06:45 +0000179 fprintf(stderr, _("\nNo %s written (file exists?)\n"), name);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000180}
181
Chris Allegrettae61e8302001-01-14 05:18:27 +0000182/* Die with an error message that the screen was too small if, well, the
183 screen is too small */
184void die_too_small(void)
185{
186 char *too_small_msg = _("Window size is too small for Nano...");
187
188 die(too_small_msg);
189
190}
191
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000192void print_view_warning(void)
193{
194 statusbar(_("Key illegal in VIEW mode"));
195}
196
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000197void clear_filename(void)
198{
199 if (filename != NULL)
200 free(filename);
Chris Allegretta88b09152001-05-17 11:35:43 +0000201 filename = charalloc(1);
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000202 filename[0] = 0;
203}
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +0000204
Chris Allegretta56214c62001-09-27 02:46:53 +0000205/* Initialize global variables - no better way for now. If
206 save_cutbuffer is nonzero, don't set cutbuffer to NULL. */
207void global_init(int save_cutbuffer)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000208{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000209 current_x = 0;
210 current_y = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000211
212 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
213 die_too_small();
214
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000215 fileage = NULL;
Chris Allegretta56214c62001-09-27 02:46:53 +0000216 if (!save_cutbuffer)
217 cutbuffer = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000218 current = NULL;
219 edittop = NULL;
220 editbot = NULL;
221 totlines = 0;
Chris Allegretta56214c62001-09-27 02:46:53 +0000222 totsize = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000223 placewewant = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000224
Chris Allegretta6fe61492001-05-21 12:56:25 +0000225#ifndef DISABLE_WRAPJUSTIFY
226 if (wrap_at)
227 fill = COLS + wrap_at;
228 else if (!fill)
Chris Allegrettae61e8302001-01-14 05:18:27 +0000229 fill = COLS - CHARS_FROM_EOL;
230
231 if (fill < MIN_FILL_LENGTH)
232 die_too_small();
Chris Allegretta6fe61492001-05-21 12:56:25 +0000233#endif
Chris Allegrettae61e8302001-01-14 05:18:27 +0000234
Chris Allegretta88b09152001-05-17 11:35:43 +0000235 hblank = charalloc(COLS + 1);
Chris Allegretta0a06e072001-01-23 02:35:04 +0000236 memset(hblank, ' ', COLS);
237 hblank[COLS] = 0;
Chris Allegretta76e291b2001-10-14 19:05:10 +0000238
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000239}
240
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000241#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000242void init_help_msg(void)
243{
244
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000245 help_text_init =
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000246 _(" nano help text\n\n "
247 "The nano editor is designed to emulate the functionality and "
248 "ease-of-use of the UW Pico text editor. There are four main "
249 "sections of the editor: The top line shows the program "
250 "version, the current filename being edited, and whether "
251 "or not the file has been modified. Next is the main editor "
252 "window showing the file being edited. The status line is "
253 "the third line from the bottom and shows important messages. "
254 "The bottom two lines show the most commonly used shortcuts "
255 "in the editor.\n\n "
256 "The notation for shortcuts is as follows: Control-key "
Chris Allegrettae49f1232000-09-02 07:20:39 +0000257 "sequences are notated with a caret (^) symbol and are entered "
Chris Allegrettad56bd792000-09-02 07:27:10 +0000258 "with the Control (Ctrl) key. Escape-key sequences are notated "
259 "with the Meta (M) symbol and can be entered using either the "
260 "Esc, Alt or Meta key depending on your keyboard setup. The "
261 "following keystrokes are available in the main editor window. "
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000262 "Optional keys are shown in parentheses:\n\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000263}
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000264#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000265
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000266/* Make a copy of a node to a pointer (space will be malloc()ed). This
267 does NOT copy the data members used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000268filestruct *copy_node(filestruct * src)
269{
270 filestruct *dst;
271
272 dst = nmalloc(sizeof(filestruct));
Chris Allegretta88b09152001-05-17 11:35:43 +0000273 dst->data = charalloc(strlen(src->data) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000274
275 dst->next = src->next;
276 dst->prev = src->prev;
277
278 strcpy(dst->data, src->data);
279 dst->lineno = src->lineno;
280
281 return dst;
282}
283
284/* Unlink a node from the rest of the struct */
285void unlink_node(filestruct * fileptr)
286{
287 if (fileptr->prev != NULL)
288 fileptr->prev->next = fileptr->next;
289
290 if (fileptr->next != NULL)
291 fileptr->next->prev = fileptr->prev;
292}
293
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000294/* Delete a node from the struct. This does NOT delete the data members
295 used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000296void delete_node(filestruct * fileptr)
297{
Chris Allegretta17dcb722001-01-20 21:40:07 +0000298 if (fileptr == NULL)
299 return;
300
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000301 if (fileptr->data != NULL)
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000302 free(fileptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000303 free(fileptr);
304}
305
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000306/* Okay, now let's duplicate a whole struct! This does NOT duplicate the
307 data members used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000308filestruct *copy_filestruct(filestruct * src)
309{
310 filestruct *dst, *tmp, *head, *prev;
311
312 head = copy_node(src);
313 dst = head; /* Else we barf on copying just one line */
314 head->prev = NULL;
315 tmp = src->next;
316 prev = head;
317
318 while (tmp != NULL) {
319 dst = copy_node(tmp);
320 dst->prev = prev;
321 prev->next = dst;
322
323 prev = dst;
324 tmp = tmp->next;
325 }
326
327 dst->next = NULL;
328 return head;
329}
330
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000331/* Frees a struct. This does NOT free the data members used only by
332 open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000333int free_filestruct(filestruct * src)
334{
335 filestruct *fileptr = src;
336
337 if (src == NULL)
338 return 0;
339
340 while (fileptr->next != NULL) {
341 fileptr = fileptr->next;
Chris Allegretta17dcb722001-01-20 21:40:07 +0000342 delete_node(fileptr->prev);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000343
344#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000345 fprintf(stderr, _("delete_node(): free'd a node, YAY!\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000346#endif
347 }
Chris Allegretta17dcb722001-01-20 21:40:07 +0000348 delete_node(fileptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000349#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000350 fprintf(stderr, _("delete_node(): free'd last node.\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000351#endif
352
353 return 1;
354}
355
356int renumber_all(void)
357{
358 filestruct *temp;
359 long i = 1;
360
361 for (temp = fileage; temp != NULL; temp = temp->next) {
362 temp->lineno = i++;
363 }
364
365 return 0;
366}
367
368int renumber(filestruct * fileptr)
369{
370 filestruct *temp;
371
372 if (fileptr == NULL || fileptr->prev == NULL || fileptr == fileage) {
373 renumber_all();
374 return 0;
375 }
376 for (temp = fileptr; temp != NULL; temp = temp->next) {
Chris Allegretta5146fec2000-12-10 05:44:02 +0000377 if (temp->prev != NULL)
378 temp->lineno = temp->prev->lineno + 1;
379 else
380 temp->lineno = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000381 }
382
383 return 0;
384}
385
386/* Fix the memory allocation for a string */
387void align(char **strp)
388{
389 /* There was a serious bug here: the new address was never
390 stored anywhere... */
391
392 *strp = nrealloc(*strp, strlen(*strp) + 1);
393}
394
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000395/* Null a string at a certain index and align it */
Chris Allegrettafa0c6962001-10-22 23:22:19 +0000396void null_at(char **data, int index)
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000397{
Chris Allegrettafa0c6962001-10-22 23:22:19 +0000398
399 /* Ahh! Damn dereferencing */
400 (*data)[index] = 0;
401 align(data);
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000402}
403
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000404void usage(void)
405{
406#ifdef HAVE_GETOPT_LONG
407 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
408 printf(_("Option Long option Meaning\n"));
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000409
Chris Allegretta7004c282001-09-22 00:42:10 +0000410#ifndef NANO_SMALL
411 printf
412 (_
413 (" -D --dos Write file in DOS format\n"));
414#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000415#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000416 printf
417 (_
Chris Allegretta355fbe52001-07-14 19:32:47 +0000418 (" -F --multibuffer Enable multiple file buffers\n"));
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000419#endif
Chris Allegretta8fa1e282001-09-22 04:20:25 +0000420#ifndef NANO_SMALL
421 printf
422 (_
423 (" -M --mac Write file in Mac format\n"));
424#endif
Chris Allegretta805c26d2000-09-06 13:39:17 +0000425#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000426 printf(_
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000427 (" -R --regexp Use regular expressions for search\n"));
Chris Allegretta47805612000-07-07 02:35:34 +0000428#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +0000429#ifndef NANO_SMALL
430 printf(_
431 (" -S --smooth Smooth scrolling\n"));
432#endif
Chris Allegretta7004c282001-09-22 00:42:10 +0000433 printf(_
434 (" -T [num] --tabsize=[num] Set width of a tab to num\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000435 printf
436 (_
437 (" -V --version Print version information and exit\n"));
438 printf(_
439 (" -c --const Constantly show cursor position\n"));
440 printf(_
441 (" -h --help Show this message\n"));
Chris Allegrettaff989832001-09-17 13:48:00 +0000442#ifndef NANO_SMALL
Chris Allegrettad55655f2000-12-27 03:36:47 +0000443 printf(_
444 (" -i --autoindent Automatically indent new lines\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000445 printf(_
Chris Allegretta627de192000-07-12 02:09:17 +0000446 (" -k --cut Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000447#endif
Chris Allegretta627de192000-07-12 02:09:17 +0000448 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000449 (" -l --nofollow Don't follow symbolic links, overwrite\n"));
Chris Allegretta84de5522001-04-12 14:51:48 +0000450#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000451#ifdef NCURSES_MOUSE_VERSION
452 printf(_(" -m --mouse Enable mouse\n"));
453#endif
454#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000455#ifndef DISABLE_OPERATINGDIR
Chris Allegrettad55655f2000-12-27 03:36:47 +0000456 printf(_
Chris Allegretta56214c62001-09-27 02:46:53 +0000457 (" -o [dir] --operatingdir=[dir] Set operating directory\n"));
Chris Allegrettae1f14522001-09-19 03:19:43 +0000458#endif
459 printf(_
460 (" -p --pico Emulate Pico as closely as possible\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000461
462#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000463 printf
464 (_
465 (" -r [#cols] --fill=[#cols] Set fill cols to (wrap lines at) #cols\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000466#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000467#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000468 printf(_
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000469 (" -s [prog] --speller=[prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000470#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000471 printf(_
472 (" -t --tempfile Auto save on exit, don't prompt\n"));
473 printf(_
474 (" -v --view View (read only) mode\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000475#ifndef DISABLE_WRAPPING
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000476 printf(_
477 (" -w --nowrap Don't wrap long lines\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000478#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000479 printf(_
480 (" -x --nohelp Don't show help window\n"));
481 printf(_
482 (" -z --suspend Enable suspend\n"));
483 printf(_
484 (" +LINE Start at line number LINE\n"));
485#else
486 printf(_("Usage: nano [option] +LINE <file>\n\n"));
487 printf(_("Option Meaning\n"));
Chris Allegretta7004c282001-09-22 00:42:10 +0000488#ifndef NANO_SMALL
489 printf(_(" -D Write file in DOS format\n"));
490#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000491#ifdef ENABLE_MULTIBUFFER
492 printf(_(" -F Enable multiple file buffers\n"));
493#endif
Chris Allegretta8fa1e282001-09-22 04:20:25 +0000494#ifndef NANO_SMALL
495 printf(_(" -M Write file in Mac format\n"));
496#endif
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000497 printf(_(" -T [num] Set width of a tab to num\n"));
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000498 printf(_(" -R Use regular expressions for search\n"));
Chris Allegretta3e3ae942001-09-22 19:02:04 +0000499#ifndef NANO_SMALL
500 printf(_(" -S Smooth scrolling\n"));
501#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000502 printf(_(" -V Print version information and exit\n"));
503 printf(_(" -c Constantly show cursor position\n"));
504 printf(_(" -h Show this message\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000505#ifndef NANO_SMALL
Chris Allegrettaff989832001-09-17 13:48:00 +0000506 printf(_(" -i Automatically indent new lines\n"));
Chris Allegretta627de192000-07-12 02:09:17 +0000507 printf(_(" -k Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000508#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000509 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000510 (" -l Don't follow symbolic links, overwrite\n"));
Chris Allegretta84de5522001-04-12 14:51:48 +0000511#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000512#ifdef NCURSES_MOUSE_VERSION
513 printf(_(" -m Enable mouse\n"));
514#endif
515#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000516#ifndef DISABLE_OPERATINGDIR
517 printf(_(" -o [dir] Set operating directory\n"));
518#endif
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +0000519 printf(_(" -p Emulate Pico as closely as possible\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000520
521#ifndef DISABLE_WRAPJUSTIFY
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000522 printf(_
523 (" -r [#cols] Set fill cols to (wrap lines at) #cols\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000524#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000525#ifndef DISABLE_SPELLER
Chris Allegrettad55655f2000-12-27 03:36:47 +0000526 printf(_(" -s [prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000527#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000528 printf(_(" -t Auto save on exit, don't prompt\n"));
529 printf(_(" -v View (read only) mode\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000530#ifndef DISABLE_WRAPPING
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000531 printf(_(" -w Don't wrap long lines\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000532#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000533 printf(_(" -x Don't show help window\n"));
534 printf(_(" -z Enable suspend\n"));
535 printf(_(" +LINE Start at line number LINE\n"));
536#endif
537 exit(0);
538}
539
540void version(void)
541{
Chris Allegrettac46dd812001-02-14 14:28:27 +0000542 printf(_(" GNU nano version %s (compiled %s, %s)\n"),
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000543 VERSION, __TIME__, __DATE__);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000544 printf(_
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000545 (" Email: nano@nano-editor.org Web: http://www.nano-editor.org"));
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000546 printf(_("\n Compiled options:"));
Chris Allegrettaff269f82000-12-01 18:46:01 +0000547
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000548#ifdef NANO_EXTRA
549 printf(" --enable-extra");
Chris Allegretta355fbe52001-07-14 19:32:47 +0000550#else
551#ifdef ENABLE_MULTIBUFFER
552 printf(" --enable-multibuffer");
553#endif /* ENABLE_MULTIBUFFER */
554#endif /* NANO_EXTRA */
555
Chris Allegrettab881d3e2001-04-18 04:34:43 +0000556#ifdef ENABLE_NANORC
557 printf(" --enable-nanorc");
558#endif
Chris Allegretta8ce24132001-04-30 11:28:46 +0000559#ifdef ENABLE_COLOR
560 printf(" --enable-color");
561#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000562
563#ifdef NANO_SMALL
564 printf(" --enable-tiny");
565#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000566#ifdef DISABLE_BROWSER
Chris Allegretta6636dc32001-01-05 05:41:07 +0000567 printf(" --disable-browser");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000568#endif
569#ifdef DISABLE_TABCOMP
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000570 printf(" --disable-tabcomp");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000571#endif
572#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +0000573 printf(" --disable-justify");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000574#endif
575#ifdef DISABLE_SPELLER
Chris Allegretta7b36c522000-12-06 01:08:10 +0000576 printf(" --disable-speller");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000577#endif
578#ifdef DISABLE_HELP
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000579 printf(" --disable-help");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000580#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000581#ifdef DISABLE_MOUSE
582 printf(" --disable-mouse");
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000583#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000584#ifdef DISABLE_OPERATINGDIR
585 printf(" --disable-operatingdir");
586#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000587#endif /* NANO_SMALL */
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000588
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000589#ifdef DISABLE_WRAPPING
590 printf(" --disable-wrapping");
591#endif
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000592#ifdef USE_SLANG
593 printf(" --with-slang");
594#endif
595 printf("\n");
596
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000597}
598
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000599/* Create a new node. This does NOT initialize the data members used
600 only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000601filestruct *make_new_node(filestruct * prevnode)
602{
603 filestruct *newnode;
604
605 newnode = nmalloc(sizeof(filestruct));
606 newnode->data = NULL;
607
608 newnode->prev = prevnode;
609 newnode->next = NULL;
610
611 if (prevnode != NULL)
612 newnode->lineno = prevnode->lineno + 1;
613
614 return newnode;
615}
616
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000617/* Splice a node into an existing filestruct. This does NOT set the data
618 members used only by open_files. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000619void splice_node(filestruct * begin, filestruct * newnode,
620 filestruct * end)
Chris Allegretta7975ed82000-07-28 00:58:35 +0000621{
Chris Allegrettae3167732001-03-18 16:59:34 +0000622 newnode->next = end;
623 newnode->prev = begin;
624 begin->next = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000625 if (end != NULL)
Chris Allegrettae3167732001-03-18 16:59:34 +0000626 end->prev = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000627}
628
Chris Allegrettae3167732001-03-18 16:59:34 +0000629int do_mark(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000630{
631#ifdef NANO_SMALL
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000632 nano_disabled_msg();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000633#else
634 if (!ISSET(MARK_ISSET)) {
635 statusbar(_("Mark Set"));
636 SET(MARK_ISSET);
637 mark_beginbuf = current;
638 mark_beginx = current_x;
639 } else {
640 statusbar(_("Mark UNset"));
641 UNSET(MARK_ISSET);
642 mark_beginbuf = NULL;
643 mark_beginx = 0;
644
645 edit_refresh();
646 }
647#endif
648 return 1;
649}
650
651int no_help(void)
652{
653 if ISSET
654 (NO_HELP)
655 return 2;
656 else
657 return 0;
658}
659
Chris Allegretta3bc8c722000-12-10 17:03:25 +0000660#if defined(DISABLE_JUSTIFY) || defined(DISABLE_SPELLER) || defined(DISABLE_HELP)
Chris Allegrettaff269f82000-12-01 18:46:01 +0000661void nano_disabled_msg(void)
662{
663 statusbar("Sorry, support for this function has been disabled");
664}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000665#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000666
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000667/* The user typed a printable character; add it to the edit buffer */
668void do_char(char ch)
669{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000670 /* magic-line: when a character is inserted on the current magic line,
671 * it means we need a new one! */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000672 if (filebot == current && current->data[0] == '\0') {
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000673 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000674 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000675 }
676
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000677 /* More dangerousness fun =) */
678 current->data = nrealloc(current->data, strlen(current->data) + 2);
679 memmove(&current->data[current_x + 1],
680 &current->data[current_x],
681 strlen(current->data) - current_x + 1);
682 current->data[current_x] = ch;
683 do_right();
684
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000685#ifndef DISABLE_WRAPPING
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000686 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000687 check_wrap(current, ch);
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000688#endif
689
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000690 set_modified();
691 check_statblank();
692 UNSET(KEEP_CUTBUFFER);
693 totsize++;
694
695}
696
697/* Someone hits return *gasp!* */
698int do_enter(filestruct * inptr)
699{
Chris Allegrettae3167732001-03-18 16:59:34 +0000700 filestruct *newnode;
Chris Allegretta68532c32001-09-17 13:49:33 +0000701 char *tmp;
702#ifndef NANO_SMALL
703 char *spc;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000704 int extra = 0;
Chris Allegretta68532c32001-09-17 13:49:33 +0000705#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000706
Chris Allegrettae3167732001-03-18 16:59:34 +0000707 newnode = make_new_node(inptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000708 tmp = &current->data[current_x];
709 current_x = 0;
710
Chris Allegrettaff989832001-09-17 13:48:00 +0000711#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000712 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
713 if (ISSET(AUTOINDENT)) {
714 spc = current->data;
715 if (spc) {
716 while ((*spc == ' ') || (*spc == '\t')) {
717 extra++;
718 spc++;
719 current_x++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +0000720 totsize++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000721 }
Chris Allegretta88b09152001-05-17 11:35:43 +0000722 newnode->data = charalloc(strlen(tmp) + extra + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000723 strncpy(newnode->data, current->data, extra);
724 strcpy(&newnode->data[extra], tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000725 }
Chris Allegrettaff989832001-09-17 13:48:00 +0000726 } else
727#endif
728 {
Chris Allegretta88b09152001-05-17 11:35:43 +0000729 newnode->data = charalloc(strlen(tmp) + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000730 strcpy(newnode->data, tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000731 }
732 *tmp = 0;
733
Chris Allegrettada721be2000-07-31 01:26:42 +0000734 if (inptr->next == NULL) {
Chris Allegrettae3167732001-03-18 16:59:34 +0000735 filebot = newnode;
736 editbot = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000737 }
Chris Allegrettae3167732001-03-18 16:59:34 +0000738 splice_node(inptr, newnode, inptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000739
740 totsize++;
741 renumber(current);
Chris Allegrettae3167732001-03-18 16:59:34 +0000742 current = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000743 align(&current->data);
744
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000745 /* The logic here is as follows:
746 * -> If we are at the bottom of the buffer, we want to recenter
Chris Allegretta88520c92001-05-05 17:45:54 +0000747 * (read: rebuild) the screen and forcibly move the cursor.
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000748 * -> otherwise, we want simply to redraw the screen and update
749 * where we think the cursor is.
750 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000751 if (current_y == editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +0000752 edit_update(current, CENTER);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000753 reset_cursor();
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000754 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000755 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000756 edit_refresh();
757 update_cursor();
758 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000759
760 totlines++;
761 set_modified();
762
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000763 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000764 return 1;
765}
766
767int do_enter_void(void)
768{
769 return do_enter(current);
770}
771
Chris Allegrettaad3f4782001-10-02 03:54:13 +0000772#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000773void do_next_word(void)
774{
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000775 filestruct *fileptr, *old;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000776 int i;
777
778 if (current == NULL)
779 return;
780
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000781 old = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000782 i = current_x;
783 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
784 if (fileptr == current) {
785 while (isalnum((int) fileptr->data[i])
786 && fileptr->data[i] != 0)
787 i++;
788
789 if (fileptr->data[i] == 0) {
790 i = 0;
791 continue;
792 }
793 }
794 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
795 i++;
796
797 if (fileptr->data[i] != 0)
798 break;
799
800 i = 0;
801 }
802 if (fileptr == NULL)
803 current = filebot;
804 else
805 current = fileptr;
806
807 current_x = i;
808 placewewant = xplustabs();
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000809
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000810 if (current->lineno >= editbot->lineno)
Chris Allegretta234a34d2000-07-29 04:33:38 +0000811 edit_update(current, CENTER);
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000812 else {
813 /* If we've jumped lines, refresh the old line. We can't just use
814 * current->prev here, because we may have skipped over some blank
815 * lines, in which case the previous line is the wrong one.
816 */
817 if (current != old)
818 update_line(old, 0);
819
820 update_line(current, current_x);
821 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000822}
823
824/* the same thing for backwards */
825void do_prev_word(void)
826{
827 filestruct *fileptr, *old;
828 int i;
829
830 if (current == NULL)
831 return;
832
833 old = current;
834 i = current_x;
835 for (fileptr = current; fileptr != NULL; fileptr = fileptr->prev) {
836 if (fileptr == current) {
837 while (isalnum((int) fileptr->data[i])
838 && i != 0)
839 i--;
840
841 if (i == 0) {
842 if (fileptr->prev != NULL)
Chris Allegrettae59fc822001-10-24 18:07:58 +0000843 i = strlen(fileptr->prev->data);
Chris Allegretta878ced32001-10-22 20:05:34 +0000844 else if (fileptr == fileage && filebot != NULL) {
845 current_x = 0;
846 return;
847 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000848 continue;
849 }
850 }
851
852 while (!isalnum((int) fileptr->data[i]) && i != 0)
853 i--;
854
855 if (i > 0) {
856 i--;
857
858 while (isalnum((int) fileptr->data[i]) && i != 0)
859 i--;
860
Chris Allegretta6d0aa9f2001-10-26 15:21:41 +0000861 if (!isalnum((int) fileptr->data[i]))
862 i++;
863
864 if (i != 0 || i != current_x)
Chris Allegretta76e291b2001-10-14 19:05:10 +0000865 break;
866
867 }
868 if (fileptr->prev != NULL)
Chris Allegrettae59fc822001-10-24 18:07:58 +0000869 i = strlen(fileptr->prev->data);
Chris Allegretta878ced32001-10-22 20:05:34 +0000870 else if (fileptr == fileage && filebot != NULL) {
871 current_x = 0;
872 return;
873 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000874 }
875 if (fileptr == NULL)
876 current = fileage;
877 else
878 current = fileptr;
879
880 current_x = i;
881 placewewant = xplustabs();
882
883 if (current->lineno <= edittop->lineno)
884 edit_update(current, CENTER);
885 else {
886 /* If we've jumped lines, refresh the old line. We can't just use
887 * current->prev here, because we may have skipped over some blank
888 * lines, in which case the previous line is the wrong one.
889 */
890 if (current != old)
891 update_line(old, 0);
892
893 update_line(current, current_x);
894 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000895
896}
Chris Allegrettaad3f4782001-10-02 03:54:13 +0000897#endif /* NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000898
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000899#ifndef DISABLE_WRAPPING
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000900void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000901{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000902 int i = 0; /* Index into ->data for line. */
903 int i_tabs = 0; /* Screen position of ->data[i]. */
904 int last_word_end = -1; /* Location of end of last word found. */
905 int current_word_start = -1; /* Location of start of current word. */
906 int current_word_start_t = -1; /* Location of start of current word screen position. */
907 int current_word_end = -1; /* Location of end of current word */
908 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000909 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000910
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000911 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000912 int right = 0;
913 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000914
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000915 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000916
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000917 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000918 if (!isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000919 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000920
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000921 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000922 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000923
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000924 while (!isspace((int) inptr->data[i])
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000925 && inptr->data[i]) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000926 i++;
927 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000928 if (inptr->data[i] < 32)
929 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000930 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000931
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000932 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000933 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000934 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000935 } else {
936 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000937 current_word_end_t = i_tabs - 1;
938 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000939 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000940
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000941 if (inptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000942 if (i_tabs % tabsize != 0);
943 i_tabs += tabsize - (i_tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000944 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000945
Adam Rogoyski09f97962000-06-20 02:50:33 +0000946 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000947 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000948 }
949
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000950 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000951 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000952 * a) one word takes up the whole line with no starting spaces.
953 * - do nothing and return.
954 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000955 * - word starts new line.
956 * - keep white space on original line up to the cursor.
957 * *) cursor is after word at wrap point
958 * - either it's all white space after word, and this routine isn't called.
959 * - or we are actually in case 2 (2 words).
960 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000961 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000962 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000963 * - white space at end of original line is cleared, unless
964 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000965 * b) cursor is at the word at the wrap point.
966 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000967 * - white space on original line is kept to where cursor was.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000968 * c) cursor is past the word at the wrap point.
969 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000970 * - white space at end of original line is cleared
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000971 */
972
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000973 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000974
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000975 /* Category 1a: one word taking up the whole line with no beginning spaces. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000976 if ((last_word_end == -1) && (!isspace((int) inptr->data[0]))) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000977 for (i = current_word_end; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000978 if (!isspace((int) inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000979 current_word_start = i;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000980 while (!isspace((int) inptr->data[i]) && (i < len)) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000981 i++;
982 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000983 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000984 current_word_end = i;
985 break;
986 }
987 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000988
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000989 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000990 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000991 return;
992 }
993 if (current_x >= last_word_end) {
994 right = (current_x - current_word_start) + 1;
995 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000996 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000997 }
998
Chris Allegretta2084acc2001-11-29 03:43:08 +0000999 /* Subtract length of original line, plus one for the newline, from
1000 totsize. */
1001 totsize -= (strlen(inptr->data) + 1);
1002
Chris Allegretta88b09152001-05-17 11:35:43 +00001003 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001004 strcpy(temp->data, &inptr->data[current_word_start]);
1005 inptr->data = nrealloc(inptr->data, last_word_end + 2);
1006 inptr->data[last_word_end + 1] = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001007
1008 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1009 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
1010
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001011 } else
1012 /* Category 1b: one word on the line and word not taking up whole line
1013 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001014 if (last_word_end == -1) {
Chris Allegretta88b09152001-05-17 11:35:43 +00001015 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001016 strcpy(temp->data, &inptr->data[current_word_start]);
1017
1018 /* Inside word, remove it from original, and move cursor to right spot. */
1019 if (current_x >= current_word_start) {
1020 right = current_x - current_word_start;
Chris Allegretta56214c62001-09-27 02:46:53 +00001021
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001022 current_x = 0;
Chris Allegrettaff989832001-09-17 13:48:00 +00001023#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001024 if (ISSET(AUTOINDENT)) {
1025 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001026 while ((inptr->next->data[i] == ' '
1027 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001028 i++;
1029 right++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001030 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001031 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001032#endif
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001033 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001034 }
1035
Chris Allegretta2084acc2001-11-29 03:43:08 +00001036 /* Subtract length of original line, plus one for the newline, from
1037 totsize. */
1038 totsize -= (strlen(inptr->data) + 1);
1039
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001040 null_at(&inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001041
Chris Allegretta2084acc2001-11-29 03:43:08 +00001042 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1043 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
1044
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001045 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
1046 mark_beginbuf = temp;
1047 mark_beginx = 0;
1048 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001049 }
1050
1051 /* Category 2: two or more words on the line. */
1052 else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001053 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001054 if (current_x < current_word_start) {
1055 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001056 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001057 strcpy(temp->data, &inptr->data[current_word_start]);
1058
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001059 if (!isspace((int) input_char)) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001060 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001061
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001062 while (isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001063 i--;
1064 assert(i >= 0);
1065 }
1066 } else if (current_x <= last_word_end)
1067 i = last_word_end - 1;
1068 else
1069 i = current_x;
1070
Chris Allegretta2084acc2001-11-29 03:43:08 +00001071 /* Subtract length of original line, plus one for the newline, from
1072 totsize. */
1073 totsize -= (strlen(inptr->data) + 1);
1074
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001075 inptr->data = nrealloc(inptr->data, i + 2);
1076 inptr->data[i + 1] = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001077
1078 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1079 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
1080
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001081 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001082
1083
1084 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001085 else if ((current_x >= current_word_start)
1086 && (current_x <= (current_word_end + 1))) {
1087 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001088 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001089 strcpy(temp->data, &inptr->data[current_word_start]);
1090
1091 down = 1;
1092
1093 right = current_x - current_word_start;
Chris Allegrettaff989832001-09-17 13:48:00 +00001094#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001095 if (ISSET(AUTOINDENT)) {
1096 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001097 while ((inptr->next->data[i] == ' '
1098 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001099 i++;
1100 right++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001101 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001102 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001103#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001104 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001105 current_x = current_word_start;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001106
Chris Allegretta2084acc2001-11-29 03:43:08 +00001107 /* Subtract length of original line, plus one for the newline, from
1108 totsize. */
1109 totsize -= (strlen(inptr->data) + 1);
1110
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001111 null_at(&inptr->data, current_word_start);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001112
Chris Allegretta2084acc2001-11-29 03:43:08 +00001113 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1114 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001115 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001116
1117
1118 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001119 else {
1120 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001121 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001122 strcpy(temp->data, &inptr->data[current_word_start]);
1123
1124 down = 1;
1125 right = current_x - current_word_start;
1126
1127 current_x = current_word_start;
1128 i = current_word_start - 1;
1129
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001130 while (isspace((int) inptr->data[i])) {
Adam Rogoyski3d449b42000-06-19 17:30:14 +00001131 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001132 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001133 }
Chris Allegretta2084acc2001-11-29 03:43:08 +00001134
1135 /* Subtract length of original line, plus one for the newline, from
1136 totsize. */
1137 totsize -= (strlen(inptr->data) + 1);
1138
1139 inptr->data = nrealloc(inptr->data, i + 2);
1140 inptr->data[i + 1] = 0;
1141
1142 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1143 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001144 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001145 }
1146
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001147 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001148 if (ISSET(SAMELINEWRAP) && inptr->next) {
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001149 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001150
Chris Allegretta94a78b82001-03-14 08:28:48 +00001151 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001152 char *p =
Chris Allegretta88b09152001-05-17 11:35:43 +00001153 charalloc((strlen(temp->data) + strlen(inptr->next->data) + 2));
Chris Allegretta94a78b82001-03-14 08:28:48 +00001154
Chris Allegretta56214c62001-09-27 02:46:53 +00001155 /* We're adding to an existing line instead of creating a new
1156 one; decrement totlines here so that when it gets incremented
1157 below, it won't end up being high by one. */
1158 totlines--;
1159
Chris Allegrettaff989832001-09-17 13:48:00 +00001160#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001161 if (ISSET(AUTOINDENT)) {
1162 int non = 0;
1163
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001164 /* Grab the beginning of the next line until it's not a
1165 space or tab, then null terminate it so we can strcat it
1166 to hell */
1167 while ((inptr->next->data[non] == ' '
Chris Allegretta355fbe52001-07-14 19:32:47 +00001168 || inptr->next->data[non] == '\t')) {
1169 p[non] = inptr->next->data[non];
1170 non++;
1171 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001172 p[non] = 0;
1173 strcat(p, temp->data);
1174 strcat(p, " ");
1175
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001176 /* Now tack on the rest of the next line after the spaces and
1177 tabs */
Chris Allegretta94a78b82001-03-14 08:28:48 +00001178 strcat(p, &inptr->next->data[non]);
Chris Allegrettaff989832001-09-17 13:48:00 +00001179 } else
1180#endif
1181 {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001182 strcpy(p, temp->data);
1183 strcat(p, " ");
1184 strcat(p, inptr->next->data);
1185 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001186
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001187 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001188 inptr->next->data = p;
1189
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001190 free(temp->data);
1191 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001192
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001193 current_x = old_x;
1194 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001195 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001196 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001197 else {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001198
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001199 temp->prev = inptr;
1200 temp->next = inptr->next;
1201
1202 if (inptr->next)
1203 inptr->next->prev = temp;
1204 inptr->next = temp;
1205
1206 if (!temp->next)
1207 filebot = temp;
1208
1209 SET(SAMELINEWRAP);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001210
Chris Allegrettaff989832001-09-17 13:48:00 +00001211#ifndef NANO_SMALL
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001212 if (ISSET(AUTOINDENT)) {
1213 char *spc = inptr->data;
1214 char *t = NULL;
1215 int extra = 0;
1216 if (spc) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001217 while ((*spc == ' ') || (*spc == '\t')) {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001218 extra++;
1219 spc++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001220 totsize++;
1221 }
Chris Allegretta88b09152001-05-17 11:35:43 +00001222 t = charalloc(strlen(temp->data) + extra + 1);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001223 strncpy(t, inptr->data, extra);
1224 strcpy(t + extra, temp->data);
1225 free(temp->data);
1226 temp->data = t;
1227 }
1228 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001229#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001230 }
1231
1232
1233 totlines++;
Chris Allegretta88520c92001-05-05 17:45:54 +00001234 /* Everything about it makes me want this line here, but it causes
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001235 * totsize to be high by one for some reason. Sigh. (Rob) */
1236 /* totsize++; */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001237
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001238 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001239 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001240
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001241
1242 /* Move the cursor to the new line if appropriate. */
1243 if (down) {
1244 do_right();
1245 }
1246
1247 /* Move the cursor to the correct spot in the line if appropriate. */
1248 while (right--) {
1249 do_right();
1250 }
1251
Chris Allegretta234a34d2000-07-29 04:33:38 +00001252 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001253 reset_cursor();
1254 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001255}
1256
1257/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001258void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001259{
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001260 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001261#ifdef DEBUG
1262 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
1263 inptr->data);
1264#endif
1265
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001266 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001267 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001268 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001269 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001270
1271 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001272 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001273
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001274 while (isspace((int) inptr->data[i]) && inptr->data[i])
Adam Rogoyski09f97962000-06-20 02:50:33 +00001275 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001276
Adam Rogoyski09f97962000-06-20 02:50:33 +00001277 if (!inptr->data[i])
1278 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001279
Adam Rogoyski09f97962000-06-20 02:50:33 +00001280 /* String must be at least 1 character long. */
1281 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001282 if (isspace((int) inptr->data[i])) {
Adam Rogoyski09f97962000-06-20 02:50:33 +00001283 if (!char_found)
1284 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001285 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001286 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001287 } else
1288 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001289 }
Adam Rogoyski09f97962000-06-20 02:50:33 +00001290
1291 if (char_found == 2)
1292 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001293 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001294}
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001295#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001296
1297/* Stuff we do when we abort from programs and want to clean up the
Chris Allegretta88520c92001-05-05 17:45:54 +00001298 * screen. This doesn't do much right now.
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001299 */
1300void do_early_abort(void)
1301{
1302 blank_statusbar_refresh();
1303}
1304
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001305int do_backspace(void)
1306{
1307 filestruct *previous, *tmp;
1308
1309 if (current_x != 0) {
1310 /* Let's get dangerous */
1311 memmove(&current->data[current_x - 1], &current->data[current_x],
1312 strlen(current->data) - current_x + 1);
1313#ifdef DEBUG
1314 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
1315#endif
1316 align(&current->data);
1317 do_left();
1318 } else {
1319 if (current == fileage)
1320 return 0; /* Can't delete past top of file */
1321
1322 previous = current->prev;
1323 current_x = strlen(previous->data);
1324 previous->data = nrealloc(previous->data,
1325 strlen(previous->data) +
1326 strlen(current->data) + 1);
1327 strcat(previous->data, current->data);
1328
1329 tmp = current;
1330 unlink_node(current);
1331 delete_node(current);
1332 if (current == edittop) {
1333 if (previous->next)
1334 current = previous->next;
1335 else
1336 current = previous;
Chris Allegretta3e3ae942001-09-22 19:02:04 +00001337 page_up();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001338 } else {
1339 if (previous->next)
1340 current = previous->next;
1341 else
1342 current = previous;
1343 update_line(current, current_x);
1344 }
1345
1346 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001347 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001348 filebot = current;
1349 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001350
1351 /* Recreate the magic line if we're deleting it AND if the
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001352 line we're on now is NOT blank. if it is blank we
1353 can just use IT for the magic line. This is how Pico
1354 appears to do it, in any case */
Chris Allegretta28a0f892000-07-05 22:47:54 +00001355 if (strcmp(current->data, "")) {
1356 new_magicline();
1357 fix_editbot();
1358 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001359 }
1360
1361 current = previous;
1362 renumber(current);
1363 previous_line();
1364 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001365#ifdef DEBUG
1366 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
1367#endif
1368
1369 }
1370
1371 totsize--;
1372 set_modified();
1373 UNSET(KEEP_CUTBUFFER);
1374 edit_refresh();
1375 return 1;
1376}
1377
1378int do_delete(void)
1379{
1380 filestruct *foo;
1381
Chris Allegretta2084acc2001-11-29 03:43:08 +00001382 /* blbf -> blank line before filebot (see below) */
1383 int blbf = 0;
1384
1385 if (current->next == filebot && !strcmp(current->data, ""))
1386 blbf = 1;
1387
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001388 if (current_x != strlen(current->data)) {
1389 /* Let's get dangerous */
1390 memmove(&current->data[current_x], &current->data[current_x + 1],
1391 strlen(current->data) - current_x);
1392
1393 align(&current->data);
1394
Chris Allegretta2084acc2001-11-29 03:43:08 +00001395 /* Now that we have a magic line again, we can check for both being
1396 on the line before filebot as well as at filebot; it's a special
1397 case if we're on the line before filebot and it's blank, since we
1398 should be able to delete it */
1399 } else if (current->next != NULL && (current->next != filebot || blbf)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001400 current->data = nrealloc(current->data,
1401 strlen(current->data) +
1402 strlen(current->next->data) + 1);
1403 strcat(current->data, current->next->data);
1404
1405 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001406 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001407 filebot = current;
1408 editbot = current;
1409 }
1410
1411 unlink_node(foo);
1412 delete_node(foo);
1413 update_line(current, current_x);
1414
Chris Allegretta4ed13152001-02-10 17:50:50 +00001415 /* Please see the comment in do_backspace if you don't understand
Chris Allegretta28a0f892000-07-05 22:47:54 +00001416 this test */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001417 if (current == filebot && strcmp(current->data, "")) {
Chris Allegretta28a0f892000-07-05 22:47:54 +00001418 new_magicline();
1419 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001420 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001421 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001422 renumber(current);
1423 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001424 } else
1425 return 0;
1426
1427 totsize--;
1428 set_modified();
1429 UNSET(KEEP_CUTBUFFER);
1430 edit_refresh();
1431 return 1;
1432}
1433
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001434void wrap_reset(void)
1435{
1436 UNSET(SAMELINEWRAP);
1437}
1438
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001439#ifndef DISABLE_SPELLER
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001440
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001441int do_int_spell_fix(char *word)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001442{
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001443 char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001444 filestruct *begin;
1445 int i = 0, j = 0, beginx, beginx_top;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001446
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001447 /* save where we are */
1448 begin = current;
1449 beginx = current_x + 1;
1450
1451 /* save the current search/replace strings */
1452 search_init_globals();
1453 save_search = mallocstrcpy(save_search, last_search);
1454 save_replace = mallocstrcpy(save_replace, last_replace);
1455
1456 /* set search/replace strings to mis-spelt word */
1457 prevanswer = mallocstrcpy(prevanswer, word);
1458 last_search = mallocstrcpy(last_search, word);
1459 last_replace = mallocstrcpy(last_replace, word);
1460
1461 /* start from the top of file */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001462 current = fileage;
1463 current_x = beginx_top = -1;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001464
1465 search_last_line = FALSE;
1466
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001467 edit_update(fileage, TOP);
1468
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001469 /* make sure word is still mis-spelt (i.e. when multi-errors) */
Chris Allegretta8d990b52001-09-22 22:14:25 +00001470 if (findnextstr(TRUE, FALSE, fileage, beginx_top, prevanswer) != NULL) {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001471 do_replace_highlight(TRUE, prevanswer);
1472
1473 /* allow replace word to be corrected */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001474 i = statusq(0, spell_list, SPELL_LIST_LEN, last_replace,
1475 _("Edit a replacement"));
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001476
1477 do_replace_highlight(FALSE, prevanswer);
1478
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001479 /* start from the start of this line again */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001480 current = fileage;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001481 current_x = beginx_top;
1482
1483 search_last_line = FALSE;
1484
Chris Allegretta80838272001-12-02 06:03:22 +00001485 if (strcmp(prevanswer,answer) != 0) {
1486 j = i;
1487 do_replace_loop(prevanswer, fileage, &beginx_top, TRUE, &j);
1488 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001489 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001490
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001491 /* restore the search/replace strings */
1492 last_search = mallocstrcpy(last_search, save_search);
1493 last_replace = mallocstrcpy(last_replace, save_replace);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001494
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001495 /* restore where we were */
1496 current = begin;
1497 current_x = beginx - 1;
1498
1499 edit_update(current, CENTER);
1500
1501 if (i == -1)
1502 return FALSE;
1503
1504 return TRUE;
1505}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001506
1507/* Integrated spell checking using 'spell' program */
Chris Allegretta271e9722000-11-10 18:15:43 +00001508int do_int_speller(char *tempfile_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001509{
Chris Allegretta271e9722000-11-10 18:15:43 +00001510 char *read_buff, *read_buff_ptr, *read_buff_word;
1511 long pipe_buff_size;
1512 int in_fd[2], tempfile_fd;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001513 int spell_status;
1514 pid_t pid_spell;
1515 ssize_t bytesread;
1516
Chris Allegretta271e9722000-11-10 18:15:43 +00001517 /* Create a pipe to spell program */
1518
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001519 if (pipe(in_fd) == -1)
1520 return FALSE;
1521
Chris Allegretta271e9722000-11-10 18:15:43 +00001522 /* A new process to run spell in */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001523
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001524 if ((pid_spell = fork()) == 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001525
1526 /* Child continues, (i.e. future spell process) */
1527
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001528 close(in_fd[0]);
1529
Chris Allegretta271e9722000-11-10 18:15:43 +00001530 /* replace the standard in with the tempfile */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001531
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001532 if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001533
1534 close(in_fd[1]);
1535 exit(1);
1536 }
1537
1538 if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
1539
1540 close(tempfile_fd);
1541 close(in_fd[1]);
1542 exit(1);
1543 }
1544 close(tempfile_fd);
1545
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001546
Chris Allegretta271e9722000-11-10 18:15:43 +00001547 /* send spell's standard out to the pipe */
1548
1549 if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1550
1551 close(in_fd[1]);
1552 exit(1);
1553 }
1554 close(in_fd[1]);
1555
1556 /* Start spell program, we are using the PATH here!?!? */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001557 execlp("spell", "spell", NULL);
1558
Chris Allegretta271e9722000-11-10 18:15:43 +00001559 /* Should not be reached, if spell is found!!! */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001560
Chris Allegretta271e9722000-11-10 18:15:43 +00001561 exit(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001562 }
1563
1564 /* Parent continues here */
1565
Chris Allegretta271e9722000-11-10 18:15:43 +00001566 close(in_fd[1]);
1567
1568 /* Child process was not forked successfully */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001569
1570 if (pid_spell < 0) {
1571
Chris Allegretta271e9722000-11-10 18:15:43 +00001572 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001573 return FALSE;
1574 }
1575
Chris Allegretta271e9722000-11-10 18:15:43 +00001576 /* Get system pipe buffer size */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001577
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001578 if ((pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001579
Chris Allegretta271e9722000-11-10 18:15:43 +00001580 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001581 return FALSE;
Chris Allegretta271e9722000-11-10 18:15:43 +00001582 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001583
Chris Allegretta88b09152001-05-17 11:35:43 +00001584 read_buff = charalloc(pipe_buff_size + 1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001585
Chris Allegretta271e9722000-11-10 18:15:43 +00001586 /* Process the returned spelling errors */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001587
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001588 while ((bytesread = read(in_fd[0], read_buff, pipe_buff_size)) > 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001589
Chris Allegretta271e9722000-11-10 18:15:43 +00001590 read_buff[bytesread] = (char) NULL;
1591 read_buff_word = read_buff_ptr = read_buff;
1592
1593 while (*read_buff_ptr != (char) NULL) {
1594
1595 /* Windows version may need to process additional char '\r' */
1596
1597 /* Possible problem here if last word not followed by '\n' */
1598
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001599 if (*read_buff_ptr == '\n') {
Chris Allegretta271e9722000-11-10 18:15:43 +00001600 *read_buff_ptr = (char) NULL;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001601 if (!do_int_spell_fix(read_buff_word)) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001602
1603 close(in_fd[0]);
1604 free(read_buff);
1605 replace_abort();
1606
1607 return TRUE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001608 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001609 read_buff_word = read_buff_ptr;
1610 read_buff_word++;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001611 }
1612
1613 read_buff_ptr++;
1614 }
1615 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001616
1617 close(in_fd[0]);
1618 free(read_buff);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001619 replace_abort();
1620
Chris Allegretta271e9722000-11-10 18:15:43 +00001621 /* Process end of spell process */
1622
1623 wait(&spell_status);
1624 if (WIFEXITED(spell_status)) {
1625 if (WEXITSTATUS(spell_status) != 0)
1626 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001627 } else
Chris Allegretta271e9722000-11-10 18:15:43 +00001628 return FALSE;
1629
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001630 return TRUE;
1631}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001632
1633/* External spell checking */
Chris Allegretta271e9722000-11-10 18:15:43 +00001634int do_alt_speller(char *file_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001635{
Chris Allegrettab3655b42001-10-22 03:15:31 +00001636 int alt_spell_status, lineno_cur = current->lineno;
1637 int x_cur = current_x, y_cur = current_y, pww_cur = placewewant;
1638
Chris Allegretta271e9722000-11-10 18:15:43 +00001639 pid_t pid_spell;
Chris Allegretta169ee842001-01-26 01:57:32 +00001640 char *ptr;
1641 static int arglen = 3;
1642 static char **spellargs = (char **) NULL;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001643
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001644 endwin();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001645
Chris Allegrettae434b452001-01-27 19:25:00 +00001646 /* Set up an argument list to pass the execvp function */
1647 if (spellargs == NULL) {
1648 spellargs = nmalloc(arglen * sizeof(char *));
Chris Allegretta271e9722000-11-10 18:15:43 +00001649
Chris Allegrettae434b452001-01-27 19:25:00 +00001650 spellargs[0] = strtok(alt_speller, " ");
1651 while ((ptr = strtok(NULL, " ")) != NULL) {
1652 arglen++;
1653 spellargs = nrealloc(spellargs, arglen * sizeof(char *));
1654 spellargs[arglen - 3] = ptr;
Chris Allegretta169ee842001-01-26 01:57:32 +00001655 }
Chris Allegrettae434b452001-01-27 19:25:00 +00001656 spellargs[arglen - 1] = NULL;
1657 }
1658 spellargs[arglen - 2] = file_name;
1659
1660 /* Start a new process for the alternate speller */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001661 if ((pid_spell = fork()) == 0) {
Chris Allegretta169ee842001-01-26 01:57:32 +00001662
Chris Allegretta88520c92001-05-05 17:45:54 +00001663 /* Start alternate spell program; we are using the PATH here!?!? */
Chris Allegretta169ee842001-01-26 01:57:32 +00001664 execvp(spellargs[0], spellargs);
Chris Allegretta271e9722000-11-10 18:15:43 +00001665
1666 /* Should not be reached, if alternate speller is found!!! */
1667
1668 exit(1);
1669 }
1670
1671 /* Could not fork?? */
1672
1673 if (pid_spell < 0)
1674 return FALSE;
1675
1676 /* Wait for alternate speller to complete */
1677
1678 wait(&alt_spell_status);
1679 if (WIFEXITED(alt_spell_status)) {
1680 if (WEXITSTATUS(alt_spell_status) != 0)
1681 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001682 } else
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001683 return FALSE;
1684
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001685 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001686 free_filestruct(fileage);
Chris Allegretta56214c62001-09-27 02:46:53 +00001687 global_init(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001688 open_file(file_name, 0, 1);
Rocco Corsi4dfaf932001-04-20 01:59:55 +00001689
Chris Allegretta1b3381b2001-09-28 21:59:01 +00001690 /* go back to the old position, mark the file as modified, and make
1691 sure that the titlebar is refreshed */
1692 do_gotopos(lineno_cur, x_cur, y_cur, pww_cur);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001693 set_modified();
Chris Allegrettae1f14522001-09-19 03:19:43 +00001694 clearok(topwin, FALSE);
1695 titlebar(NULL);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001696
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001697 return TRUE;
1698}
1699#endif
1700
1701int do_spell(void)
1702{
1703
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001704#ifdef DISABLE_SPELLER
Chris Allegrettaff269f82000-12-01 18:46:01 +00001705 nano_disabled_msg();
1706 return (TRUE);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001707#else
Chris Allegretta271e9722000-11-10 18:15:43 +00001708 char *temp;
1709 int spell_res;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001710
Chris Allegretta271e9722000-11-10 18:15:43 +00001711 if ((temp = tempnam(0, "nano.")) == NULL) {
1712 statusbar(_("Could not create a temporary filename: %s"),
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001713 strerror(errno));
Chris Allegretta271e9722000-11-10 18:15:43 +00001714 return 0;
1715 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001716
Chris Allegrettaecc3d7f2001-06-05 23:24:55 +00001717 if (write_file(temp, 1, 0, 0) == -1) {
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001718 statusbar(_("Spell checking failed: unable to write temp file!"));
Chris Allegretta271e9722000-11-10 18:15:43 +00001719 return 0;
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001720 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001721
Chris Allegrettae1f14522001-09-19 03:19:43 +00001722#ifdef ENABLE_MULTIBUFFER
1723 /* update the current open_files entry before spell-checking, in case
1724 any problems occur; the case of there being no open_files entries
1725 is handled elsewhere (before we reach this point); no duplicate
1726 checking is needed here */
1727 add_open_file(1, 0);
1728#endif
1729
Chris Allegretta271e9722000-11-10 18:15:43 +00001730 if (alt_speller)
1731 spell_res = do_alt_speller(temp);
1732 else
1733 spell_res = do_int_speller(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001734
Chris Allegretta271e9722000-11-10 18:15:43 +00001735 remove(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001736
1737 if (spell_res)
1738 statusbar(_("Finished checking spelling"));
1739 else
1740 statusbar(_("Spell checking failed"));
1741
1742 return spell_res;
1743
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001744#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001745}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001746
1747int do_exit(void)
1748{
1749 int i;
1750
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001751 if (!ISSET(MODIFIED)) {
1752
Chris Allegretta355fbe52001-07-14 19:32:47 +00001753#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001754 if (!close_open_file()) {
1755 display_main_list();
1756 return 1;
1757 }
1758 else
1759#endif
1760
1761 finish(0);
1762 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001763
Chris Allegretta30885552000-07-14 01:20:12 +00001764 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001765 i = 1;
1766 } else {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001767 i = do_yesno(0, 0,
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001768 _
1769 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1770 }
1771
1772#ifdef DEBUG
1773 dump_buffer(fileage);
1774#endif
1775
1776 if (i == 1) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001777 if (do_writeout(filename, 1, 0) > 0) {
1778
Chris Allegretta355fbe52001-07-14 19:32:47 +00001779#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001780 if (!close_open_file()) {
1781 display_main_list();
1782 return 1;
1783 }
1784 else
1785#endif
1786
1787 finish(0);
1788 }
1789 } else if (i == 0) {
1790
Chris Allegretta355fbe52001-07-14 19:32:47 +00001791#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001792 if (!close_open_file()) {
1793 display_main_list();
1794 return 1;
1795 }
1796 else
1797#endif
1798
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001799 finish(0);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001800 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001801 statusbar(_("Cancelled"));
1802
1803 display_main_list();
1804 return 1;
1805}
1806
Chris Allegretta84de5522001-04-12 14:51:48 +00001807#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001808#ifdef NCURSES_MOUSE_VERSION
1809void do_mouse(void)
1810{
1811 MEVENT mevent;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001812 int foo = 0, tab_found = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001813
1814 if (getmouse(&mevent) == ERR)
1815 return;
1816
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001817 /* If mouse not in edit or bottom window, return */
1818 if (wenclose(edit, mevent.y, mevent.x)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001819
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001820 /* Don't let people screw with the marker when they're in a
1821 subfunction */
1822 if (currshortcut != main_list)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001823 return;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001824
1825 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1826 mevent.y -= 2;
1827
1828 /* Selecting where the cursor is sets the mark.
1829 * Selecting beyond the line length with the cursor at the end of the
1830 * line sets the mark as well.
1831 */
1832 if ((mevent.y == current_y) &&
1833 ((mevent.x == current_x) || (current_x == strlen(current->data)
1834 && (mevent.x >
1835 strlen(current->data))))) {
1836 if (ISSET(VIEW_MODE)) {
1837 print_view_warning();
1838 return;
1839 }
1840 do_mark();
1841 } else if (mevent.y > current_y) {
1842 while (mevent.y > current_y) {
1843 if (current->next != NULL)
1844 current = current->next;
1845 else
1846 break;
1847 current_y++;
1848 }
1849 } else if (mevent.y < current_y) {
1850 while (mevent.y < current_y) {
1851 if (current->prev != NULL)
1852 current = current->prev;
1853 else
1854 break;
1855 current_y--;
1856 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001857 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001858 current_x = mevent.x;
1859 placewewant = current_x;
1860 while (foo < current_x) {
1861 if (current->data[foo] == NANO_CONTROL_I) {
1862 current_x -= tabsize - (foo % tabsize);
1863 tab_found = 1;
1864 } else if (current->data[foo] & 0x80);
1865 else if (current->data[foo] < 32)
1866 current_x--;
1867 foo++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001868 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001869 /* This is where tab_found comes in. I can't figure out why,
1870 * but without it any line with a tab will place the cursor
1871 * one character behind. Whatever, this fixes it. */
1872 if (tab_found == 1)
1873 current_x++;
1874
1875 if (current_x > strlen(current->data))
1876 current_x = strlen(current->data);
1877
1878 update_cursor();
1879 edit_refresh();
1880 } else if (wenclose(bottomwin, mevent.y, mevent.x) && !ISSET(NO_HELP)) {
Chris Allegrettaa951f212001-09-27 21:07:39 +00001881
1882 int k, val = 0;
1883
1884 if (currslen < 2)
1885 k = COLS / 6;
1886 else
1887 k = COLS / ((currslen + (currslen %2)) / 2);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001888
1889 /* Determine what shortcut list was clicked */
1890 mevent.y -= (editwinrows + 3);
1891
1892 if (mevent.y < 0) /* They clicked on the statusbar */
1893 return;
1894
1895 /* Don't select stuff beyond list length */
1896 if (mevent.x / k >= currslen)
1897 return;
1898
1899 val = currshortcut[(mevent.x / k) * 2 + mevent.y].val;
1900
1901 /* And ungetch that value */
1902 ungetch(val);
Chris Allegretta6414b402001-09-21 03:21:11 +00001903
1904 /* And if it's an alt-key sequence, we should probably send alt
1905 too ;-) */
1906 if (val >= 'a' && val <= 'z')
1907 ungetch(27);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001908 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001909}
1910#endif
1911#endif
1912
1913/* Handler for SIGHUP */
1914RETSIGTYPE handle_hup(int signal)
1915{
Chris Allegrettae7a58932000-12-02 02:36:22 +00001916 die(_("Received SIGHUP"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001917}
1918
Chris Allegretta18f8be02000-09-04 03:20:38 +00001919/* What do we do when we catch the suspend signal */
1920RETSIGTYPE do_suspend(int signal)
1921{
Chris Allegretta18f8be02000-09-04 03:20:38 +00001922 endwin();
Chris Allegretta521e00d2001-06-28 16:52:52 +00001923 printf("\n\n\n\n\nUse \"fg\" to return to nano\n");
1924 fflush(stdout);
1925
1926 /* We used to re-enable the default SIG_DFL and raise SIGTSTP, but
1927 then we could be (and were) interrupted in the middle of the call.
1928 So we do it the mutt way instead */
1929 kill(0, SIGSTOP);
Chris Allegretta18f8be02000-09-04 03:20:38 +00001930}
1931
1932/* Restore the suspend handler when we come back into the prog */
1933RETSIGTYPE do_cont(int signal)
1934{
1935
Chris Allegretta521e00d2001-06-28 16:52:52 +00001936 /* Now we just update the screen instead of having to reenable the
1937 SIGTSTP handler */
1938
Chris Allegretta521e00d2001-06-28 16:52:52 +00001939 doupdate();
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00001940 /* The Hurd seems to need this, otherwise a ^Y after a ^Z will
1941 start suspending again */
1942 signal_init();
Chris Allegretta18f8be02000-09-04 03:20:38 +00001943}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001944
1945void handle_sigwinch(int s)
1946{
1947#ifndef NANO_SMALL
1948 char *tty = NULL;
1949 int fd = 0;
1950 int result = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001951 struct winsize win;
1952
1953 tty = ttyname(0);
1954 if (!tty)
1955 return;
1956 fd = open(tty, O_RDWR);
1957 if (fd == -1)
1958 return;
1959 result = ioctl(fd, TIOCGWINSZ, &win);
1960 if (result == -1)
1961 return;
1962
1963
1964 COLS = win.ws_col;
1965 LINES = win.ws_row;
1966
Chris Allegrettae61e8302001-01-14 05:18:27 +00001967 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1968 die_too_small();
1969
Chris Allegretta6fe61492001-05-21 12:56:25 +00001970#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettae61e8302001-01-14 05:18:27 +00001971 if ((fill = COLS - CHARS_FROM_EOL) < MIN_FILL_LENGTH)
1972 die_too_small();
Chris Allegretta6fe61492001-05-21 12:56:25 +00001973#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001974
Chris Allegretta0a06e072001-01-23 02:35:04 +00001975 hblank = nrealloc(hblank, COLS + 1);
1976 memset(hblank, ' ', COLS);
1977 hblank[COLS] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001978
Chris Allegretta618f5d72001-02-16 04:48:30 +00001979#ifdef HAVE_RESIZETERM
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001980 resizeterm(LINES, COLS);
1981#ifdef HAVE_WRESIZE
1982 if (wresize(topwin, 2, COLS) == ERR)
1983 die(_("Cannot resize top win"));
1984 if (mvwin(topwin, 0, 0) == ERR)
1985 die(_("Cannot move top win"));
1986 if (wresize(edit, editwinrows, COLS) == ERR)
1987 die(_("Cannot resize edit win"));
1988 if (mvwin(edit, 2, 0) == ERR)
1989 die(_("Cannot move edit win"));
1990 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1991 die(_("Cannot resize bottom win"));
1992 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1993 die(_("Cannot move bottom win"));
1994#endif /* HAVE_WRESIZE */
Chris Allegretta618f5d72001-02-16 04:48:30 +00001995#endif /* HAVE_RESIZETERM */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001996
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001997 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001998
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001999 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00002000 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002001 }
2002 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00002003
2004 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002005 refresh();
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002006 titlebar(NULL);
Chris Allegretta97accc62000-06-19 05:45:52 +00002007 edit_refresh();
2008 display_main_list();
Chris Allegretta08020882001-01-29 23:37:54 +00002009 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002010 total_refresh();
Chris Allegretta08020882001-01-29 23:37:54 +00002011
Chris Allegretta4e90c402001-01-29 23:40:43 +00002012 /* Turn cursor back on for sure */
2013 curs_set(1);
2014
Chris Allegretta08020882001-01-29 23:37:54 +00002015 /* Jump back to mainloop */
2016 siglongjmp(jmpbuf, 1);
2017
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002018#endif
2019}
2020
Chris Allegretta756f2202000-09-01 13:32:47 +00002021void signal_init(void)
2022{
Chris Allegrettaac899e52001-06-30 04:09:09 +00002023#ifdef _POSIX_VDISABLE
2024 struct termios term;
2025#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002026
Chris Allegretta88520c92001-05-05 17:45:54 +00002027 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
Chris Allegretta756f2202000-09-01 13:32:47 +00002028 memset(&act, 0, sizeof(struct sigaction));
2029 act.sa_handler = SIG_IGN;
2030 sigaction(SIGINT, &act, NULL);
Chris Allegretta756f2202000-09-01 13:32:47 +00002031
Chris Allegretta88520c92001-05-05 17:45:54 +00002032 /* Trap SIGHUP cuz we want to write the file out. */
Chris Allegretta756f2202000-09-01 13:32:47 +00002033 act.sa_handler = handle_hup;
2034 sigaction(SIGHUP, &act, NULL);
2035
2036 act.sa_handler = handle_sigwinch;
2037 sigaction(SIGWINCH, &act, NULL);
2038
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002039
2040#ifdef _POSIX_VDISABLE
2041 tcgetattr(0, &term);
2042
2043#ifdef VDSUSP
2044 term.c_cc[VDSUSP] = _POSIX_VDISABLE;
2045#endif /* VDSUSP */
2046
2047#endif /* _POSIX_VDISABLE */
2048
Chris Allegretta521e00d2001-06-28 16:52:52 +00002049 if (!ISSET(SUSPEND)) {
Chris Allegrettaac899e52001-06-30 04:09:09 +00002050
2051/* Insane! */
2052#ifdef _POSIX_VDISABLE
Chris Allegrettaac899e52001-06-30 04:09:09 +00002053 term.c_cc[VSUSP] = _POSIX_VDISABLE;
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002054#else
Chris Allegrettaac899e52001-06-30 04:09:09 +00002055 act.sa_handler = SIG_IGN;
Chris Allegretta521e00d2001-06-28 16:52:52 +00002056 sigaction(SIGTSTP, &act, NULL);
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002057#endif
Chris Allegrettaac899e52001-06-30 04:09:09 +00002058
Chris Allegretta521e00d2001-06-28 16:52:52 +00002059 } else {
2060 /* if we don't do this, it seems other stuff interrupts the
2061 suspend handler! Try using nano with mutt without this line */
2062 sigfillset(&act.sa_mask);
2063
2064 act.sa_handler = do_suspend;
2065 sigaction(SIGTSTP, &act, NULL);
2066
2067 act.sa_handler = do_cont;
2068 sigaction(SIGCONT, &act, NULL);
2069 }
2070
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002071
2072#ifdef _POSIX_VDISABLE
2073 tcsetattr(0, TCSANOW, &term);
2074#endif
2075
2076
Chris Allegretta756f2202000-09-01 13:32:47 +00002077}
2078
Chris Allegretta2a42af12000-09-12 23:02:49 +00002079void window_init(void)
2080{
Chris Allegrettae61e8302001-01-14 05:18:27 +00002081 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
2082 die_too_small();
Chris Allegretta92c9dd22000-09-13 14:03:27 +00002083
Chris Allegretta88520c92001-05-05 17:45:54 +00002084 /* Set up the main text window */
Chris Allegretta2a42af12000-09-12 23:02:49 +00002085 edit = newwin(editwinrows, COLS, 2, 0);
2086
2087 /* And the other windows */
2088 topwin = newwin(2, COLS, 0, 0);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002089 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002090
Chris Allegretta155d6202001-01-08 01:50:37 +00002091#ifdef PDCURSES
2092 /* Oops, I guess we need this again.
2093 Moved here so the keypad still works after a Meta-X, for example */
2094 keypad(edit, TRUE);
2095 keypad(bottomwin, TRUE);
2096#endif
2097
Chris Allegretta2a42af12000-09-12 23:02:49 +00002098}
2099
Chris Allegretta756f2202000-09-01 13:32:47 +00002100void mouse_init(void)
2101{
Chris Allegretta84de5522001-04-12 14:51:48 +00002102#ifndef DISABLE_MOUSE
Chris Allegretta756f2202000-09-01 13:32:47 +00002103#ifdef NCURSES_MOUSE_VERSION
2104 if (ISSET(USE_MOUSE)) {
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002105 keypad_on(edit, 1);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002106 keypad_on(bottomwin, 1);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002107
Chris Allegretta756f2202000-09-01 13:32:47 +00002108 mousemask(BUTTON1_RELEASED, NULL);
2109 mouseinterval(50);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00002110
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002111 } else
Chris Allegretta756f2202000-09-01 13:32:47 +00002112 mousemask(0, NULL);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002113
Chris Allegretta756f2202000-09-01 13:32:47 +00002114#endif
2115#endif
2116
2117}
2118
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002119int do_tab(void)
2120{
2121 do_char('\t');
2122 return 1;
2123}
2124
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002125#ifndef DISABLE_JUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002126int empty_line(const char *data)
2127{
2128 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002129 if (!isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002130 return 0;
2131
2132 data++;
2133 }
2134
2135 return 1;
2136}
2137
2138int no_spaces(const char *data)
2139{
2140 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002141 if (isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002142 return 0;
2143
2144 data++;
2145 }
2146
2147 return 1;
2148}
2149
2150void justify_format(char *data)
2151{
2152 int i = 0;
2153 int len = strlen(data);
2154
2155 /* Skip first character regardless and leading whitespace. */
2156 for (i = 1; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002157 if (!isspace((int) data[i]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002158 break;
2159 }
2160
2161 i++; /* (i) is now at least 2. */
2162
2163 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
2164 for (; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002165 if (isspace((int) data[i]) && isspace((int) data[i - 1])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002166 && (data[i - 2] != '.')) {
2167 memmove(data + i, data + i + 1, len - i);
2168 len--;
2169 i--;
2170 }
2171 }
2172}
2173#endif
2174
2175int do_justify(void)
2176{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002177#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +00002178 nano_disabled_msg();
2179 return 1;
2180#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002181 int slen = 0; /* length of combined lines on one line. */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002182 int initial_y, kbinput = 0, totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002183 filestruct *initial = NULL, *tmpjust = NULL, *cutbak, *tmptop, *tmpbot;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002184
2185 if (empty_line(current->data)) {
2186 /* Justify starting at first non-empty line. */
2187 do {
2188 if (!current->next)
2189 return 1;
2190
2191 current = current->next;
2192 current_y++;
2193 }
2194 while (empty_line(current->data));
2195 } else {
2196 /* Search back for the beginning of the paragraph, where
2197 * Paragraph is 1) A line with leading whitespace
2198 * or 2) A line following an empty line.
2199 */
2200 while (current->prev != NULL) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002201 if (isspace((int) current->data[0]) || !current->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002202 break;
2203
2204 current = current->prev;
2205 current_y--;
2206 }
2207
2208 /* First line with leading whitespace may be empty. */
2209 if (empty_line(current->data)) {
2210 if (current->next) {
2211 current = current->next;
2212 current_y++;
2213 } else
2214 return 1;
2215 }
2216 }
2217 initial = current;
2218 initial_y = current_y;
2219
2220 set_modified();
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002221 cutbak = cutbuffer; /* Got to like cutbak ;) */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002222 totbak = totsize;
Chris Allegretta9149e612000-11-27 00:23:41 +00002223 cutbuffer = NULL;
2224
2225 tmptop = current;
2226 tmpjust = copy_node(current);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002227
2228 /* This is annoying because it mucks with totsize */
Chris Allegretta9149e612000-11-27 00:23:41 +00002229 add_to_cutbuffer(tmpjust);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002230
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002231 /* Put the whole paragraph into one big line. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002232 while (current->next && !isspace((int) current->next->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002233 && current->next->data[0]) {
2234 filestruct *tmpnode = current->next;
2235 int len = strlen(current->data);
2236 int len2 = strlen(current->next->data);
2237
Chris Allegretta9149e612000-11-27 00:23:41 +00002238 tmpjust = NULL;
Chris Allegretta9149e612000-11-27 00:23:41 +00002239 tmpjust = copy_node(current->next);
2240 add_to_cutbuffer(tmpjust);
2241
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002242 /* Wiping out a newline */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002243 totsize--;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002244
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002245 /* length of both strings plus space between strings and ending \0. */
2246 current->data = nrealloc(current->data, len + len2 + 2);
2247 current->data[len++] = ' ';
2248 current->data[len] = '\0';
2249
2250 strncat(current->data, current->next->data, len2);
2251
2252 unlink_node(tmpnode);
2253 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002254 }
2255
2256 justify_format(current->data);
2257
2258 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002259 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002260
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002261 if ((strlenpt(current->data) > (fill))
2262 && !no_spaces(current->data)) {
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002263 do {
2264 int i = 0;
2265 int len2 = 0;
2266 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002267
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002268 /* Start at fill , unless line isn't that long (but it
2269 * appears at least fill long with tabs.
2270 */
2271 if (slen > fill)
2272 i = fill;
2273 else
2274 i = slen;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002275
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002276 for (; i > 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002277 if (isspace((int) current->data[i]) &&
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002278 ((strlenpt(current->data) - strlen(current->data + i))
2279 <= fill))
2280 break;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002281 }
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002282
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002283 if (!i)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002284 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002285
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002286 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002287
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002288 len2 = strlen(current->data + i + 1);
Chris Allegretta88b09152001-05-17 11:35:43 +00002289 tmpline->data = charalloc(len2 + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002290
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002291 /* Skip the white space in current. */
2292 memcpy(tmpline->data, current->data + i + 1, len2);
2293 tmpline->data[len2] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002294
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002295 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002296
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002297 tmpline->prev = current;
2298 tmpline->next = current->next;
2299 if (current->next != NULL)
2300 current->next->prev = tmpline;
2301
2302 current->next = tmpline;
2303 current = tmpline;
2304 slen -= i + 1;
2305 current_y++;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002306 } while ((strlenpt(current->data) > (fill))
2307 && !no_spaces(current->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002308 }
Chris Allegretta9149e612000-11-27 00:23:41 +00002309 tmpbot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002310
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002311 if (current->next)
2312 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00002313 else
2314 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002315 current_x = 0;
2316 placewewant = 0;
2317
Adam Rogoyski09f97962000-06-20 02:50:33 +00002318 renumber(initial);
2319 totlines = filebot->lineno;
2320
2321 werase(edit);
2322
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002323 if ((current_y < 0) || (current_y >= editwinrows - 1)
2324 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00002325 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002326 center_cursor();
2327 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00002328 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002329 }
2330
Adam Rogoyski09f97962000-06-20 02:50:33 +00002331 edit_refresh();
Chris Allegretta9149e612000-11-27 00:23:41 +00002332 statusbar(_("Can now UnJustify!"));
Chris Allegretta07798352000-11-27 22:58:23 +00002333 /* Change the shortcut list to display the unjustify code */
2334 shortcut_init(1);
2335 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002336 reset_cursor();
2337
Chris Allegretta88520c92001-05-05 17:45:54 +00002338 /* Now get a keystroke and see if it's unjustify; if not, unget the keystroke
Chris Allegretta9149e612000-11-27 00:23:41 +00002339 and return */
Chris Allegretta5f071802001-05-06 02:34:31 +00002340
2341#ifndef DISABLE_MOUSE
2342#ifdef NCURSES_MOUSE_VERSION
2343
2344 /* If it was a mouse click, parse it with do_mouse and it might become
2345 the unjustify key. Else give it back to the input stream. */
2346 if ((kbinput = wgetch(edit)) == KEY_MOUSE)
2347 do_mouse();
2348 else
2349 ungetch(kbinput);
2350#endif
2351#endif
2352
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002353 if ((kbinput = wgetch(edit)) != NANO_UNJUSTIFY_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002354 ungetch(kbinput);
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002355 blank_statusbar_refresh();
2356 } else {
Chris Allegretta9149e612000-11-27 00:23:41 +00002357 /* Else restore the justify we just did (ungrateful user!) */
2358 if (tmptop->prev != NULL)
2359 tmptop->prev->next = tmpbot->next;
Chris Allegrettad022eac2000-11-27 02:50:49 +00002360 else
2361 fileage = current;
Chris Allegretta9149e612000-11-27 00:23:41 +00002362 tmpbot->next->prev = tmptop->prev;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002363 current = tmpbot->next;
Chris Allegretta9149e612000-11-27 00:23:41 +00002364 tmpbot->next = NULL;
2365 do_uncut_text();
Chris Allegrettad022eac2000-11-27 02:50:49 +00002366 if (tmptop->prev == NULL)
2367 edit_refresh();
2368
Chris Allegretta88520c92001-05-05 17:45:54 +00002369 /* Restore totsize from before justify */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002370 totsize = totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002371 free_filestruct(tmptop);
2372 blank_statusbar_refresh();
2373 }
Chris Allegretta4a9c8582000-11-27 22:59:40 +00002374 shortcut_init(0);
2375 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002376 free_filestruct(cutbuffer);
2377 cutbuffer = cutbak;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002378
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002379 return 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002380#endif
2381}
2382
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002383#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002384void help_init(void)
2385{
2386 int i, sofar = 0;
2387 long allocsize = 1; /* How much space we're gonna need for the help text */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002388 char buf[BUFSIZ] = "", *ptr = NULL;
2389
2390 /* First set up the initial help text for the current function */
2391 if (currshortcut == whereis_list || currshortcut == replace_list
2392 || currshortcut == replace_list_2)
2393 ptr = _("Search Command Help Text\n\n "
2394 "Enter the words or characters you would like to search "
2395 "for, then hit enter. If there is a match for the text you "
2396 "entered, the screen will be updated to the location of the "
Jordi Mallach773623c2001-10-28 21:00:49 +00002397 "nearest match for the search string.\n\n "
2398 "If using Pico Mode via the -p or --pico flags, using the "
2399 "Meta-P toggle or using a nanorc file, the previous search "
2400 "string will be shown in brackets after the Search: prompt. "
2401 "Hitting enter without entering any text will preform the "
2402 "previous search. Otherwise, the previous string will be "
2403 "placed in front of the cursor, and can be edited or deleted "
2404 "before hitting enter.\n\n The following functions keys are "
2405 "available in Search mode:\n\n");
Chris Allegrettab3655b42001-10-22 03:15:31 +00002406 else if (currshortcut == goto_list)
2407 ptr = _("Goto Line Help Text\n\n "
2408 "Enter the line number that you wish to go to and hit "
Jordi Mallach773623c2001-10-28 21:00:49 +00002409 "Enter. If there are fewer lines of text than the "
Chris Allegrettab3655b42001-10-22 03:15:31 +00002410 "number you entered, you will be brought to the last line "
2411 "of the file.\n\n The following functions keys are "
2412 "available in Goto Line mode:\n\n");
2413 else if (currshortcut == insertfile_list)
2414 ptr = _("Insert File Help Text\n\n "
2415 "Type in the name of a file to be inserted into the current "
2416 "file buffer at the current cursor location.\n\n "
2417 "If you have compiled nano with multiple file buffer "
2418 "support, and enable multiple buffers with the -F "
Jordi Mallach773623c2001-10-28 21:00:49 +00002419 "or --multibuffer command line flags, the Meta-F toggle or "
2420 "using a nanorc file, inserting a file will cause it to be "
2421 "loaded into a separate buffer (use Ctrl-< and > to switch "
2422 "between file buffers).\n\n The following function keys are "
Chris Allegrettab3655b42001-10-22 03:15:31 +00002423 "available in Insert File mode:\n\n");
2424 else if (currshortcut == writefile_list)
2425 ptr = _("Write File Help Text\n\n "
2426 "Type the name that you wish to save the current file "
2427 "as and hit enter to save the file.\n\n "
2428 "If you are using the marker code with Ctrl-^ and have "
2429 "selected text, you will be prompted to save only the "
2430 "selected portion to a separate file. To reduce the "
2431 "chance of overwriting the current file with just a portion "
2432 "of it, the current filename is not the default in this "
2433 "mode.\n\n The following function keys are available in "
2434 "Write File mode:\n\n");
2435#ifndef DISABLE_BROWSER
2436 else if (currshortcut == browser_list)
2437 ptr = _("File Browser Help Text\n\n "
2438 "The file browser is used to visually browse the "
2439 "directory structure to select a file for reading "
2440 "or writing. You may use the arrow keys or Page Up/"
2441 "Down to browse through the files, and S or Enter to "
2442 "choose the selected file or enter the selected "
2443 "directory. To move up one level, select the directory "
2444 "called \"..\" at the top of the file list.\n\n The "
2445 "following functions keys are available in the file "
2446 "browser:\n\n");
2447 else if (currshortcut == gotodir_list)
2448 ptr = _("Browser Goto Directory Help Text\n\n "
2449 "Enter the name of the directory you would like to "
2450 "browse to.\n\n If tab completion has not been disabled, "
2451 "you can use the TAB key to (attempt to) automatically "
2452 "complete the directory name. The following function "
2453 "keys are available in Browser GotoDir mode:\n\n");
2454#endif
2455 else if (currshortcut == spell_list)
2456 ptr = _("Spell Check Help Text\n\n "
2457 "The spell checker checks the spelling of all text "
2458 "in the current file. When an unknown word is "
2459 "encountered, it is highlighted and a replacement can "
2460 "be edited. It will then prompt to replace every "
2461 "instance of the given misspelled word in the "
2462 "current file.\n\n The following other functions are "
2463 "available in Spell Check mode:\n\n");
2464 else /* Default to the main help list */
2465 ptr = help_text_init;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002466
2467 /* Compute the space needed for the shortcut lists - we add 15 to
2468 have room for the shortcut abbrev and its possible alternate keys */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002469 for (i = 0; i <= currslen - 1; i++)
2470 if (currshortcut[i].help != NULL)
2471 allocsize += strlen(currshortcut[i].help) + 15;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002472
Chris Allegrettab3655b42001-10-22 03:15:31 +00002473 /* If we're on the main list, we also allocate space for toggle help text. */
2474 if (currshortcut == main_list) {
2475 for (i = 0; i <= TOGGLE_LEN - 1; i++)
2476 if (toggles[i].desc != NULL)
2477 allocsize += strlen(toggles[i].desc) + 30;
Chris Allegretta756f2202000-09-01 13:32:47 +00002478
Chris Allegrettab3655b42001-10-22 03:15:31 +00002479 }
2480
2481 allocsize += strlen(ptr);
2482
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002483
2484 if (help_text != NULL)
2485 free(help_text);
2486
2487 /* Allocate space for the help text */
Chris Allegretta88b09152001-05-17 11:35:43 +00002488 help_text = charalloc(allocsize);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002489
2490 /* Now add the text we want */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002491 strcpy(help_text, ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002492
2493 /* Now add our shortcut info */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002494 for (i = 0; i <= currslen - 1; i++) {
2495 if (currshortcut[i].val > 0 && currshortcut[i].val < 'a')
2496 sofar = snprintf(buf, BUFSIZ, "^%c ", currshortcut[i].val + 64);
Chris Allegretta8d990b52001-09-22 22:14:25 +00002497 else
2498 sofar = snprintf(buf, BUFSIZ, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002499
Chris Allegrettab3655b42001-10-22 03:15:31 +00002500 if (currshortcut[i].misc1 > KEY_F0 && currshortcut[i].misc1 <= KEY_F(64))
Robert Siemborski6af14312000-07-01 21:34:26 +00002501 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
Chris Allegrettab3655b42001-10-22 03:15:31 +00002502 currshortcut[i].misc1 - KEY_F0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002503 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002504 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002505
Chris Allegrettab3655b42001-10-22 03:15:31 +00002506 if (currshortcut[i].altval > 0 && currshortcut[i].altval < 91)
Chris Allegrettae49f1232000-09-02 07:20:39 +00002507 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
Chris Allegrettab3655b42001-10-22 03:15:31 +00002508 currshortcut[i].altval - 32);
2509 else if (currshortcut[i].altval > 0)
Chris Allegretta8d990b52001-09-22 22:14:25 +00002510 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
Chris Allegrettab3655b42001-10-22 03:15:31 +00002511 currshortcut[i].altval);
2512 /* Hack */
2513 else if (currshortcut[i].val >= 'a')
2514 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
2515 currshortcut[i].val - 32);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002516 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002517 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002518
Chris Allegretta756f2202000-09-01 13:32:47 +00002519
Chris Allegrettab3655b42001-10-22 03:15:31 +00002520 if (currshortcut[i].help != NULL)
2521 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", currshortcut[i].help);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002522
Chris Allegretta756f2202000-09-01 13:32:47 +00002523
2524 strcat(help_text, buf);
2525 strcat(help_text, "\n");
2526 }
2527
2528 /* And the toggles... */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002529 if (currshortcut == main_list)
2530 for (i = 0; i <= TOGGLE_LEN - 1; i++) {
2531 if (toggles[i].override_ch != 0)
2532 sofar = snprintf(buf, BUFSIZ,
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002533 "M-%c ", toggles[i].override_ch);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002534 else
2535 sofar = snprintf(buf, BUFSIZ,
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002536 "M-%c ", toggles[i].val - 32);
Chris Allegretta756f2202000-09-01 13:32:47 +00002537
Chris Allegrettab3655b42001-10-22 03:15:31 +00002538 if (toggles[i].desc != NULL) {
2539 if (toggles[i].flag != 0)
2540 snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002541 toggles[i].desc);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002542 else
2543 snprintf(&buf[sofar], BUFSIZ - sofar, "%s",
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002544 toggles[i].desc);
2545 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002546
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002547 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00002548 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002549 }
2550
2551}
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002552#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002553
Chris Allegretta756f2202000-09-01 13:32:47 +00002554void do_toggle(int which)
2555{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002556#ifdef NANO_SMALL
2557 nano_disabled_msg();
2558#else
Jordi Mallach2dc0f6b2000-09-07 10:48:00 +00002559 char *enabled = _("enabled");
2560 char *disabled = _("disabled");
Chris Allegrettaf0f63a82000-09-02 18:44:21 +00002561
Chris Allegretta8d990b52001-09-22 22:14:25 +00002562 switch (toggles[which].val) {
2563 case TOGGLE_BACKWARDS_KEY:
2564 case TOGGLE_CASE_KEY:
2565 case TOGGLE_REGEXP_KEY:
2566 return;
2567 }
Chris Allegretta8d990b52001-09-22 22:14:25 +00002568
Chris Allegretta658399a2001-06-14 02:54:22 +00002569 /* Even easier! */
2570 TOGGLE(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002571
Chris Allegretta756f2202000-09-01 13:32:47 +00002572 switch (toggles[which].val) {
2573 case TOGGLE_PICOMODE_KEY:
Chris Allegretta07798352000-11-27 22:58:23 +00002574 shortcut_init(0);
Chris Allegrettac1049ac2001-08-17 00:03:46 +00002575 SET(CLEAR_BACKUPSTRING);
Chris Allegretta756f2202000-09-01 13:32:47 +00002576 display_main_list();
2577 break;
2578 case TOGGLE_SUSPEND_KEY:
2579 signal_init();
2580 break;
2581 case TOGGLE_MOUSE_KEY:
2582 mouse_init();
2583 break;
2584 case TOGGLE_NOHELP_KEY:
Chris Allegretta2a42af12000-09-12 23:02:49 +00002585 wclear(bottomwin);
2586 wrefresh(bottomwin);
2587 window_init();
Chris Allegrettaaffeda82000-12-18 04:03:48 +00002588 fix_editbot();
Chris Allegretta2a42af12000-09-12 23:02:49 +00002589 edit_refresh();
2590 display_main_list();
Chris Allegretta756f2202000-09-01 13:32:47 +00002591 break;
Chris Allegretta99e30e12001-09-23 02:45:27 +00002592 case TOGGLE_DOS_KEY:
2593 UNSET(MAC_FILE);
2594 break;
2595 case TOGGLE_MAC_KEY:
2596 UNSET(DOS_FILE);
2597 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002598 }
Chris Allegretta2a42af12000-09-12 23:02:49 +00002599
Chris Allegretta819e3db2001-07-11 02:37:19 +00002600 if (!ISSET(toggles[which].flag)) {
2601 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
2602 toggles[which].val == TOGGLE_WRAP_KEY)
2603 statusbar("%s %s", toggles[which].desc, enabled);
2604 else
2605 statusbar("%s %s", toggles[which].desc, disabled);
2606 } else {
2607 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
2608 toggles[which].val == TOGGLE_WRAP_KEY)
2609 statusbar("%s %s", toggles[which].desc, disabled);
2610 else
2611 statusbar("%s %s", toggles[which].desc, enabled);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002612 }
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002613
Chris Allegretta756f2202000-09-01 13:32:47 +00002614#endif
2615}
2616
Chris Allegretta88520c92001-05-05 17:45:54 +00002617/* If the NumLock key has made the keypad go awry, print an error
2618 message; hopefully we can address it later. */
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002619void print_numlock_warning(void)
2620{
2621 static int didmsg = 0;
2622 if (!didmsg) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002623 statusbar(_
2624 ("NumLock glitch detected. Keypad will malfunction with NumLock off"));
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002625 didmsg = 1;
2626 }
2627}
2628
Chris Allegretta1748cd12001-01-13 17:22:54 +00002629/* This function returns the correct keystroke, given the A,B,C or D
2630 input key. This is a common sequence of many terms which send
2631 Esc-O-[A-D] or Esc-[-[A-D]. */
2632int ABCD(int input)
2633{
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002634 switch (input) {
2635 case 'A':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002636 case 'a':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002637 return (KEY_UP);
2638 case 'B':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002639 case 'b':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002640 return (KEY_DOWN);
2641 case 'C':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002642 case 'c':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002643 return (KEY_RIGHT);
2644 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002645 case 'd':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002646 return (KEY_LEFT);
2647 default:
2648 return 0;
Chris Allegretta1748cd12001-01-13 17:22:54 +00002649 }
2650}
2651
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002652int main(int argc, char *argv[])
2653{
2654 int optchr;
2655 int kbinput; /* Input from keyboard */
2656 long startline = 0; /* Line to try and start at */
Chris Allegretta08020882001-01-29 23:37:54 +00002657 int keyhandled; /* Have we handled the keystroke yet? */
2658 int i, modify_control_seq;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002659 char *argv0;
Chris Allegretta0357c4d2001-09-19 02:59:25 +00002660
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002661#ifdef _POSIX_VDISABLE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002662 struct termios term;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002663#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002664
2665#ifdef HAVE_GETOPT_LONG
2666 int option_index = 0;
2667 struct option long_options[] = {
Chris Allegretta805c26d2000-09-06 13:39:17 +00002668#ifdef HAVE_REGEX_H
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002669 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00002670#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002671 {"version", 0, 0, 'V'},
2672 {"const", 0, 0, 'c'},
2673 {"suspend", 0, 0, 'z'},
2674 {"nowrap", 0, 0, 'w'},
2675 {"nohelp", 0, 0, 'x'},
2676 {"help", 0, 0, 'h'},
Chris Allegretta7492cec2000-12-18 04:55:21 +00002677 {"view", 0, 0, 'v'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002678#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002679 {"cut", 0, 0, 'k'},
Chris Allegretta7004c282001-09-22 00:42:10 +00002680 {"dos", 0, 0, 'D'},
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002681 {"mac", 0, 0, 'M'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002682 {"autoindent", 0, 0, 'i'},
Chris Allegrettaff989832001-09-17 13:48:00 +00002683#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002684 {"tempfile", 0, 0, 't'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002685#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002686 {"speller", 1, 0, 's'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002687#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00002688
2689#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002690 {"fill", 1, 0, 'r'},
Chris Allegretta6fe61492001-05-21 12:56:25 +00002691#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002692 {"mouse", 0, 0, 'm'},
Chris Allegrettae1f14522001-09-19 03:19:43 +00002693#ifndef DISABLE_OPERATINGDIR
2694 {"operatingdir", 1, 0, 'o'},
2695#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002696 {"pico", 0, 0, 'p'},
2697 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00002698 {"tabsize", 1, 0, 'T'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002699
Chris Allegretta355fbe52001-07-14 19:32:47 +00002700#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002701 {"multibuffer", 0, 0, 'F'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002702#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002703#ifndef NANO_SMALL
2704 {"smooth", 0, 0, 'S'},
2705#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002706 {0, 0, 0, 0}
2707 };
2708#endif
2709
2710 /* Flag inits... */
2711 SET(FOLLOW_SYMLINKS);
2712
2713#ifndef NANO_SMALL
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002714#ifdef ENABLE_NLS
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002715 setlocale(LC_ALL, "");
2716 bindtextdomain(PACKAGE, LOCALEDIR);
2717 textdomain(PACKAGE);
2718#endif
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002719#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002720
Chris Allegretta8d8e0122001-04-18 04:28:54 +00002721#ifdef ENABLE_NANORC
2722 do_rcfile();
2723#endif /* ENABLE_NANORC */
2724
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002725#ifdef HAVE_GETOPT_LONG
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002726 while ((optchr = getopt_long(argc, argv, "h?DFMRST:Vabcefgijklmo:pr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002727 long_options, &option_index)) != EOF) {
2728#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002729 while ((optchr =
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002730 getopt(argc, argv, "h?DFMRST:Vabcefgijklmo:pr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002731#endif
2732
2733 switch (optchr) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002734
Chris Allegretta7004c282001-09-22 00:42:10 +00002735#ifndef NANO_SMALL
2736 case 'D':
2737 SET(DOS_FILE);
2738 break;
2739#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +00002740#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002741 case 'F':
Chris Allegretta355fbe52001-07-14 19:32:47 +00002742 SET(MULTIBUFFER);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002743 break;
2744#endif
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002745#ifndef NANO_SMALL
2746 case 'M':
2747 SET(MAC_FILE);
2748 break;
2749#endif
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002750 case 'T':
Chris Allegretta99bf73f2000-08-04 00:22:08 +00002751 tabsize = atoi(optarg);
2752 if (tabsize <= 0) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002753 usage(); /* To stop bogus data for tab width */
2754 finish(1);
2755 }
2756 break;
Chris Allegretta805c26d2000-09-06 13:39:17 +00002757#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +00002758 case 'R':
2759 SET(USE_REGEXP);
2760 break;
Chris Allegretta47805612000-07-07 02:35:34 +00002761#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002762#ifndef NANO_SMALL
2763 case 'S':
2764 SET(SMOOTHSCROLL);
2765 break;
2766#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002767 case 'V':
2768 version();
2769 exit(0);
Chris Allegrettae1f14522001-09-19 03:19:43 +00002770 case 'a':
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002771 case 'b':
2772 case 'e':
2773 case 'f':
Rocco Corsi12f294c2001-04-14 06:50:24 +00002774 case 'g':
2775 case 'j':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002776 /* Pico compatibility flags */
2777 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002778 case 'c':
2779 SET(CONSTUPDATE);
2780 break;
2781 case 'h':
2782 case '?':
2783 usage();
2784 exit(0);
Chris Allegrettaff989832001-09-17 13:48:00 +00002785#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002786 case 'i':
2787 SET(AUTOINDENT);
2788 break;
Chris Allegretta627de192000-07-12 02:09:17 +00002789 case 'k':
2790 SET(CUT_TO_END);
2791 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002792#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002793 case 'l':
2794 UNSET(FOLLOW_SYMLINKS);
2795 break;
2796 case 'm':
2797 SET(USE_MOUSE);
2798 break;
Chris Allegrettae1f14522001-09-19 03:19:43 +00002799#ifndef DISABLE_OPERATINGDIR
2800 case 'o':
2801 operating_dir = charalloc(strlen(optarg) + 1);
2802 strcpy(operating_dir, optarg);
2803
2804 /* make sure we're inside the operating directory */
2805 if (check_operating_dir(".", 0)) {
2806 if (chdir(operating_dir) == -1) {
2807 free(operating_dir);
2808 operating_dir = NULL;
2809 }
2810 }
2811 break;
2812#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002813 case 'p':
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002814 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002815 break;
2816 case 'r':
Chris Allegretta6fe61492001-05-21 12:56:25 +00002817#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002818 fill = atoi(optarg);
Chris Allegretta6fe61492001-05-21 12:56:25 +00002819 if (fill < 0)
2820 wrap_at = fill;
2821 else if (fill == 0) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002822 usage(); /* To stop bogus data (like a string) */
2823 finish(1);
2824 }
2825 break;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002826#else
2827 usage();
2828 exit(0);
2829
2830#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002831#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002832 case 's':
Chris Allegretta88b09152001-05-17 11:35:43 +00002833 alt_speller = charalloc(strlen(optarg) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002834 strcpy(alt_speller, optarg);
2835 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002836#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002837 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00002838 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002839 break;
2840 case 'v':
2841 SET(VIEW_MODE);
2842 break;
2843 case 'w':
Chris Allegrettacef7fbb2001-04-02 05:36:08 +00002844#ifdef DISABLE_WRAPPING
2845 usage();
2846 exit(0);
2847#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002848 SET(NO_WRAP);
2849 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002850#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002851 case 'x':
2852 SET(NO_HELP);
2853 break;
2854 case 'z':
2855 SET(SUSPEND);
2856 break;
2857 default:
2858 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002859 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002860 }
2861
2862 }
2863
2864 argv0 = strrchr(argv[0], '/');
2865 if ((argv0 && strstr(argv0, "pico"))
2866 || (!argv0 && strstr(argv[0], "pico")))
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002867 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002868
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002869 /* See if there's a non-option in argv (first non-option is the
2870 filename, if +LINE is not given) */
2871 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002872 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002873 else {
2874 /* Look for the +line flag... */
2875 if (argv[optind][0] == '+') {
2876 startline = atoi(&argv[optind][1]);
2877 optind++;
2878 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002879 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002880 else
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002881 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002882
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002883 } else
2884 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002885 }
2886
2887
2888 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002889 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002890
Chris Allegretta9239d742000-09-06 15:19:18 +00002891#ifdef _POSIX_VDISABLE
Chris Allegretta8f6c0692000-07-19 01:16:18 +00002892 term = oldterm;
2893 term.c_cc[VINTR] = _POSIX_VDISABLE;
2894 term.c_cc[VQUIT] = _POSIX_VDISABLE;
2895 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002896 tcsetattr(0, TCSANOW, &term);
Chris Allegretta9239d742000-09-06 15:19:18 +00002897#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002898
2899 /* now ncurses init stuff... */
2900 initscr();
2901 savetty();
2902 nonl();
2903 cbreak();
2904 noecho();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002905
2906 /* Set up some global variables */
Chris Allegretta56214c62001-09-27 02:46:53 +00002907 global_init(0);
Chris Allegretta07798352000-11-27 22:58:23 +00002908 shortcut_init(0);
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002909#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002910 init_help_msg();
2911 help_init();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002912#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002913 signal_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002914
2915#ifdef DEBUG
2916 fprintf(stderr, _("Main: set up windows\n"));
2917#endif
2918
Chris Allegretta2a42af12000-09-12 23:02:49 +00002919 window_init();
Chris Allegretta756f2202000-09-01 13:32:47 +00002920 mouse_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002921
Chris Allegretta08893e02001-11-29 02:42:27 +00002922#ifdef ENABLE_COLOR
2923 do_colorinit();
2924
Chris Allegretta08893e02001-11-29 02:42:27 +00002925#endif /* ENABLE_COLOR */
2926
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002927#ifdef DEBUG
2928 fprintf(stderr, _("Main: bottom win\n"));
2929#endif
Chris Allegretta88520c92001-05-05 17:45:54 +00002930 /* Set up bottom of window */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002931 display_main_list();
2932
2933#ifdef DEBUG
2934 fprintf(stderr, _("Main: open file\n"));
2935#endif
2936
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002937 titlebar(NULL);
Chris Allegretta31c76662000-11-21 06:20:20 +00002938
2939 /* Now we check to see if argv[optind] is non-null to determine if
2940 we're dealing with a new file or not, not argc == 1... */
2941 if (argv[optind] == NULL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002942 new_file();
2943 else
2944 open_file(filename, 0, 0);
2945
2946 if (startline > 0)
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002947 do_gotoline(startline, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002948 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00002949 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002950
Chris Allegretta08020882001-01-29 23:37:54 +00002951 /* return here after a sigwinch */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002952 sigsetjmp(jmpbuf, 1);
Chris Allegretta08020882001-01-29 23:37:54 +00002953
2954 /* Fix clobber-age */
2955 kbinput = 0;
2956 keyhandled = 0;
2957 modify_control_seq = 0;
2958
Robert Siemborski6967eec2000-07-08 14:23:32 +00002959 edit_refresh();
2960 reset_cursor();
2961
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002962 while (1) {
Chris Allegretta9239d742000-09-06 15:19:18 +00002963
Chris Allegretta6fe61492001-05-21 12:56:25 +00002964#ifndef DISABLE_MOUSE
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002965 currshortcut = main_list;
2966 currslen = MAIN_VISIBLE;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002967#endif
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002968
Chris Allegretta9239d742000-09-06 15:19:18 +00002969#ifndef _POSIX_VDISABLE
2970 /* We're going to have to do it the old way, i.e. on cygwin */
2971 raw();
2972#endif
2973
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002974 kbinput = wgetch(edit);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002975#ifdef DEBUG
2976 fprintf(stderr, "AHA! %c (%d)\n", kbinput, kbinput);
2977#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002978
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002979 if (kbinput == 27) { /* Grab Alt-key stuff first */
2980 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002981 /* Alt-O, suddenly very important ;) */
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002982 case 'O':
Chris Allegretta16e41682000-09-11 22:33:54 +00002983 kbinput = wgetch(edit);
Chris Allegretta316e4d92001-04-28 16:31:19 +00002984 if ((kbinput <= 'D' && kbinput >= 'A') ||
2985 (kbinput <= 'd' && kbinput >= 'a'))
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002986 kbinput = ABCD(kbinput);
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002987 else if (kbinput <= 'z' && kbinput >= 'j')
2988 print_numlock_warning();
2989 else if (kbinput <= 'S' && kbinput >= 'P')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002990 kbinput = KEY_F(kbinput - 79);
Chris Allegretta16e41682000-09-11 22:33:54 +00002991#ifdef DEBUG
2992 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002993 fprintf(stderr, _("I got Alt-O-%c! (%d)\n"),
2994 kbinput, kbinput);
2995 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002996 }
2997#endif
2998 break;
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002999 case 27:
3000 /* If we get Alt-Alt, the next keystroke should be the same as a
3001 control sequence */
3002 modify_control_seq = 1;
3003 keyhandled = 1;
3004 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00003005#ifndef NANO_SMALL
Chris Allegretta76e291b2001-10-14 19:05:10 +00003006 case ' ':
3007 /* If control-space is next word, Alt-space should be previous word */
3008 do_prev_word();
3009 keyhandled = 1;
3010 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00003011#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003012 case '[':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003013 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003014 case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */
Chris Allegretta16e41682000-09-11 22:33:54 +00003015 kbinput = wgetch(edit);
3016 if (kbinput >= '1' && kbinput <= '5') {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003017 kbinput = KEY_F(kbinput - 48);
3018 wgetch(edit);
3019 } else if (kbinput >= '7' && kbinput <= '9') {
3020 kbinput = KEY_F(kbinput - 49);
3021 wgetch(edit);
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003022 } else if (kbinput == '~')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003023 kbinput = KEY_HOME;
Chris Allegretta16e41682000-09-11 22:33:54 +00003024
3025#ifdef DEBUG
3026 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003027 fprintf(stderr, _("I got Alt-[-1-%c! (%d)\n"),
3028 kbinput, kbinput);
3029 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003030 }
3031#endif
3032
3033 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003034 case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */
Chris Allegretta16e41682000-09-11 22:33:54 +00003035 kbinput = wgetch(edit);
Chris Allegretta16e41682000-09-11 22:33:54 +00003036 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003037 case '0':
3038 kbinput = KEY_F(9);
3039 wgetch(edit);
3040 break;
3041 case '1':
3042 kbinput = KEY_F(10);
3043 wgetch(edit);
3044 break;
3045 case '3':
3046 kbinput = KEY_F(11);
3047 wgetch(edit);
3048 break;
3049 case '4':
3050 kbinput = KEY_F(12);
3051 wgetch(edit);
3052 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003053 case '~':
3054 goto do_insertkey;
Chris Allegretta16e41682000-09-11 22:33:54 +00003055#ifdef DEBUG
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003056 default:
3057 fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"),
3058 kbinput, kbinput);
3059 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003060#endif
3061
3062 }
3063 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003064 case '3': /* Alt-[-3 = Delete? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003065 kbinput = NANO_DELETE_KEY;
3066 wgetch(edit);
3067 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003068 case '4': /* Alt-[-4 = End? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003069 kbinput = NANO_END_KEY;
3070 wgetch(edit);
3071 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003072 case '5': /* Alt-[-5 = Page Up */
Chris Allegretta16e41682000-09-11 22:33:54 +00003073 kbinput = KEY_PPAGE;
3074 wgetch(edit);
3075 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003076 case 'V': /* Alt-[-V = Page Up in Hurd Console */
Chris Allegretta7bf72742001-10-28 04:29:55 +00003077 case 'I': /* Alt-[-I = Page Up - FreeBSD Console */
3078 kbinput = KEY_PPAGE;
3079 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003080 case '6': /* Alt-[-6 = Page Down */
Chris Allegretta16e41682000-09-11 22:33:54 +00003081 kbinput = KEY_NPAGE;
3082 wgetch(edit);
3083 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003084 case 'U': /* Alt-[-U = Page Down in Hurd Console */
Chris Allegretta7bf72742001-10-28 04:29:55 +00003085 case 'G': /* Alt-[-G = Page Down - FreeBSD Console */
3086 kbinput = KEY_NPAGE;
3087 break;
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003088 case '7':
3089 kbinput = KEY_HOME;
3090 wgetch(edit);
3091 break;
3092 case '8':
3093 kbinput = KEY_END;
3094 wgetch(edit);
3095 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003096 case '9': /* Alt-[-9 = Delete in Hurd Console */
3097 kbinput = KEY_DC;
3098 break;
3099 case '@': /* Alt-[-9 = Insert in Hurd Console */
Chris Allegretta7bf72742001-10-28 04:29:55 +00003100 case 'L': /* Insert Key - FreeBSD Console */
3101#ifdef ENABLE_MULTIBUFFER
3102 do_insertfile(ISSET(MULTIBUFFER));
3103#else
3104 do_insertfile(0);
3105#endif
3106 keyhandled = 1;
3107 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003108 case '[': /* Alt-[-[-[A-E], F1-F5 in linux console */
Chris Allegretta16e41682000-09-11 22:33:54 +00003109 kbinput = wgetch(edit);
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003110 if (kbinput >= 'A' && kbinput <= 'E')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003111 kbinput = KEY_F(kbinput - 64);
Chris Allegretta16e41682000-09-11 22:33:54 +00003112 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003113 case 'A':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003114 case 'B':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003115 case 'C':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003116 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00003117 case 'a':
3118 case 'b':
3119 case 'c':
3120 case 'd':
Chris Allegretta1748cd12001-01-13 17:22:54 +00003121 kbinput = ABCD(kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003122 break;
3123 case 'H':
3124 kbinput = KEY_HOME;
3125 break;
3126 case 'F':
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003127 case 'Y': /* End Key in Hurd Console */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003128 kbinput = KEY_END;
3129 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003130 default:
3131#ifdef DEBUG
3132 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
3133 kbinput, kbinput);
3134#endif
3135 break;
3136 }
3137 break;
Chris Allegretta355fbe52001-07-14 19:32:47 +00003138#ifdef ENABLE_MULTIBUFFER
Chris Allegretta819e3db2001-07-11 02:37:19 +00003139 case NANO_OPENPREV_KEY:
3140 open_prevfile(0);
3141 keyhandled = 1;
3142 break;
3143 case NANO_OPENNEXT_KEY:
3144 open_nextfile(0);
3145 keyhandled = 1;
3146 break;
Chris Allegretta9cf9e062001-07-11 12:06:13 +00003147#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003148 default:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003149 /* Check for the altkey defs.... */
3150 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
3151 if (kbinput == main_list[i].altval ||
3152 kbinput == main_list[i].altval - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003153 kbinput = main_list[i].val;
3154 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003155 }
Chris Allegretta756f2202000-09-01 13:32:47 +00003156#ifndef NANO_SMALL
3157 /* And for toggle switches */
3158 for (i = 0; i <= TOGGLE_LEN - 1 && !keyhandled; i++)
3159 if (kbinput == toggles[i].val ||
3160 kbinput == toggles[i].val - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003161 do_toggle(i);
3162 keyhandled = 1;
3163 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00003164 }
3165#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003166#ifdef DEBUG
3167 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
3168 kbinput);
3169#endif
3170 break;
3171 }
3172 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003173 /* If the modify_control_seq is set, we received an Alt-Alt
3174 sequence before this, so we make this key a control sequence
3175 by subtracting 64 or 96, depending on its value. */
3176 if (!keyhandled && modify_control_seq) {
3177 if (kbinput >= 'A' && kbinput < 'a')
3178 kbinput -= 64;
3179 else if (kbinput >= 'a' && kbinput <= 'z')
3180 kbinput -= 96;
3181
3182 modify_control_seq = 0;
3183 }
3184
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003185 /* Look through the main shortcut list to see if we've hit a
3186 shortcut key */
Chris Allegretta2cd72b62001-10-24 17:25:36 +00003187 for (i = 0; i < MAIN_LIST_LEN && !keyhandled; i++) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003188 if (kbinput == main_list[i].val ||
3189 (main_list[i].misc1 && kbinput == main_list[i].misc1) ||
3190 (main_list[i].misc2 && kbinput == main_list[i].misc2)) {
3191 if (ISSET(VIEW_MODE) && !main_list[i].viewok)
3192 print_view_warning();
3193 else
3194 main_list[i].func();
3195 keyhandled = 1;
3196 }
3197 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003198 /* If we're in raw mode or using Alt-Alt-x, we have to catch
3199 Control-S and Control-Q */
Chris Allegretta9239d742000-09-06 15:19:18 +00003200 if (kbinput == 17 || kbinput == 19)
3201 keyhandled = 1;
3202
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003203 /* Catch ^Z by hand when triggered also */
Chris Allegretta9239d742000-09-06 15:19:18 +00003204 if (kbinput == 26) {
3205 if (ISSET(SUSPEND))
3206 do_suspend(0);
3207 keyhandled = 1;
3208 }
Chris Allegretta9239d742000-09-06 15:19:18 +00003209
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003210
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003211#ifndef USE_SLANG
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003212 /* Hack, make insert key do something useful, like insert file */
3213 if (kbinput == KEY_IC) {
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003214#else
3215 if (0) {
3216#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003217 do_insertkey:
3218
3219#ifdef ENABLE_MULTIBUFFER
3220 do_insertfile(ISSET(MULTIBUFFER));
3221#else
3222 do_insertfile(0);
3223#endif
3224
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003225 keyhandled = 1;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003226 }
3227
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003228 /* Last gasp, stuff that's not in the main lists */
3229 if (!keyhandled)
3230 switch (kbinput) {
Chris Allegretta84de5522001-04-12 14:51:48 +00003231#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003232#ifdef NCURSES_MOUSE_VERSION
3233 case KEY_MOUSE:
3234 do_mouse();
3235 break;
3236#endif
3237#endif
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003238
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003239 case 0: /* Erg */
Chris Allegretta48ebb812001-10-24 01:34:15 +00003240#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003241 do_next_word();
3242 break;
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003243#endif
Chris Allegrettaf4f7e042001-01-04 16:56:15 +00003244
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003245 case -1: /* Stuff that we don't want to do squat */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003246 case 410: /* Must ignore this, it gets sent when we resize */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003247 case 29: /* Ctrl-] */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003248#ifdef PDCURSES
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003249 case 541: /* ???? */
3250 case 542: /* Control and alt in Windows *shrug* */
Chris Allegretta72623582000-11-29 23:43:28 +00003251 case 543: /* Right ctrl key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003252 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +00003253 case 545: /* Right alt key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003254#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003255
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003256 break;
3257 default:
3258#ifdef DEBUG
3259 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
3260#endif
3261 /* We no longer stop unhandled sequences so that people with
3262 odd character sets can type... */
3263
3264 if (ISSET(VIEW_MODE)) {
3265 print_view_warning();
3266 break;
3267 }
3268 do_char(kbinput);
3269 }
Chris Allegretta7fdbd052001-10-02 00:55:38 +00003270 if (ISSET(DISABLE_CURPOS))
3271 UNSET(DISABLE_CURPOS);
3272 else if (ISSET(CONSTUPDATE))
Chris Allegretta2084acc2001-11-29 03:43:08 +00003273 do_cursorpos(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003274
3275 reset_cursor();
3276 wrefresh(edit);
3277 keyhandled = 0;
3278 }
3279
3280 getchar();
3281 finish(0);
3282
3283}