blob: 81ef9cf19de5a89fa6bab9ab3881ad59141ca088 [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 Allegretta88b09152001-05-17 11:35:43 +0000999 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001000 strcpy(temp->data, &inptr->data[current_word_start]);
1001 inptr->data = nrealloc(inptr->data, last_word_end + 2);
1002 inptr->data[last_word_end + 1] = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001003 } else
1004 /* Category 1b: one word on the line and word not taking up whole line
1005 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001006 if (last_word_end == -1) {
Chris Allegretta88b09152001-05-17 11:35:43 +00001007 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001008 strcpy(temp->data, &inptr->data[current_word_start]);
1009
1010 /* Inside word, remove it from original, and move cursor to right spot. */
1011 if (current_x >= current_word_start) {
1012 right = current_x - current_word_start;
Chris Allegretta56214c62001-09-27 02:46:53 +00001013
1014 /* Decrease totsize by the number of spaces we removed, less
1015 one for the new line we're replacing the spaces with. */
1016 totsize -= (current_word_start - 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001017 current_x = 0;
Chris Allegrettaff989832001-09-17 13:48:00 +00001018#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001019 if (ISSET(AUTOINDENT)) {
1020 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001021 while ((inptr->next->data[i] == ' '
1022 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001023 i++;
1024 right++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001025 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001026 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001027#endif
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001028 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001029 }
1030
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001031 null_at(&inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001032
1033 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
1034 mark_beginbuf = temp;
1035 mark_beginx = 0;
1036 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001037 }
1038
1039 /* Category 2: two or more words on the line. */
1040 else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001041 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001042 if (current_x < current_word_start) {
1043 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001044 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001045 strcpy(temp->data, &inptr->data[current_word_start]);
1046
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001047 if (!isspace((int) input_char)) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001048 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001049
1050 /* Decrement totsize each time we remove a space. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001051 while (isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001052 i--;
Chris Allegretta56214c62001-09-27 02:46:53 +00001053 totsize--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001054 assert(i >= 0);
1055 }
Chris Allegretta56214c62001-09-27 02:46:53 +00001056 /* And increment it to account for the blank line we're
1057 replacing the spaces with. */
1058 totsize++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001059 } else if (current_x <= last_word_end)
1060 i = last_word_end - 1;
1061 else
1062 i = current_x;
1063
1064 inptr->data = nrealloc(inptr->data, i + 2);
1065 inptr->data[i + 1] = 0;
1066 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001067
1068
1069 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001070 else if ((current_x >= current_word_start)
1071 && (current_x <= (current_word_end + 1))) {
1072 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001073 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001074 strcpy(temp->data, &inptr->data[current_word_start]);
1075
1076 down = 1;
1077
1078 right = current_x - current_word_start;
Chris Allegrettaff989832001-09-17 13:48:00 +00001079#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001080 if (ISSET(AUTOINDENT)) {
1081 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001082 while ((inptr->next->data[i] == ' '
1083 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001084 i++;
1085 right++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001086 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001087 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001088#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001089 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001090 current_x = current_word_start;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001091
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001092 null_at(&inptr->data, current_word_start);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001093
Chris Allegretta56214c62001-09-27 02:46:53 +00001094 /* Increment totsize to account for the new line that
1095 will be added below, so that it won't end up being
1096 short by one. */
1097 totsize++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001098 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001099
1100
1101 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001102 else {
1103 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001104 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001105 strcpy(temp->data, &inptr->data[current_word_start]);
1106
1107 down = 1;
1108 right = current_x - current_word_start;
1109
1110 current_x = current_word_start;
1111 i = current_word_start - 1;
1112
Chris Allegretta56214c62001-09-27 02:46:53 +00001113 /* Decrement totsize each time we remove a space. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001114 while (isspace((int) inptr->data[i])) {
Adam Rogoyski3d449b42000-06-19 17:30:14 +00001115 i--;
Chris Allegretta56214c62001-09-27 02:46:53 +00001116 totsize--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001117 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001118 inptr->data = nrealloc(inptr->data, i + 2);
1119 inptr->data[i + 1] = 0;
1120 }
Chris Allegretta56214c62001-09-27 02:46:53 +00001121 /* And increment it to account for the blank line we're
1122 replacing the spaces with. */
1123 totsize++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001124 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001125 }
1126
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001127 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001128 if (ISSET(SAMELINEWRAP) && inptr->next) {
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001129 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001130
Chris Allegretta94a78b82001-03-14 08:28:48 +00001131 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001132 char *p =
Chris Allegretta88b09152001-05-17 11:35:43 +00001133 charalloc((strlen(temp->data) + strlen(inptr->next->data) + 2));
Chris Allegretta94a78b82001-03-14 08:28:48 +00001134
Chris Allegretta56214c62001-09-27 02:46:53 +00001135 /* We're adding to an existing line instead of creating a new
1136 one; decrement totlines here so that when it gets incremented
1137 below, it won't end up being high by one. */
1138 totlines--;
1139
Chris Allegrettaff989832001-09-17 13:48:00 +00001140#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001141 if (ISSET(AUTOINDENT)) {
1142 int non = 0;
1143
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001144 /* Grab the beginning of the next line until it's not a
1145 space or tab, then null terminate it so we can strcat it
1146 to hell */
1147 while ((inptr->next->data[non] == ' '
Chris Allegretta355fbe52001-07-14 19:32:47 +00001148 || inptr->next->data[non] == '\t')) {
1149 p[non] = inptr->next->data[non];
1150 non++;
1151 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001152 p[non] = 0;
1153 strcat(p, temp->data);
1154 strcat(p, " ");
1155
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001156 /* Now tack on the rest of the next line after the spaces and
1157 tabs */
Chris Allegretta94a78b82001-03-14 08:28:48 +00001158 strcat(p, &inptr->next->data[non]);
Chris Allegrettaff989832001-09-17 13:48:00 +00001159 } else
1160#endif
1161 {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001162 strcpy(p, temp->data);
1163 strcat(p, " ");
1164 strcat(p, inptr->next->data);
1165 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001166
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001167 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001168 inptr->next->data = p;
1169
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001170 free(temp->data);
1171 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001172
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001173 current_x = old_x;
1174 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001175 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001176 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001177 else {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001178
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001179 temp->prev = inptr;
1180 temp->next = inptr->next;
1181
1182 if (inptr->next)
1183 inptr->next->prev = temp;
1184 inptr->next = temp;
1185
1186 if (!temp->next)
1187 filebot = temp;
1188
1189 SET(SAMELINEWRAP);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001190
Chris Allegrettaff989832001-09-17 13:48:00 +00001191#ifndef NANO_SMALL
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001192 if (ISSET(AUTOINDENT)) {
1193 char *spc = inptr->data;
1194 char *t = NULL;
1195 int extra = 0;
1196 if (spc) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001197 while ((*spc == ' ') || (*spc == '\t')) {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001198 extra++;
1199 spc++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001200 totsize++;
1201 }
Chris Allegretta88b09152001-05-17 11:35:43 +00001202 t = charalloc(strlen(temp->data) + extra + 1);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001203 strncpy(t, inptr->data, extra);
1204 strcpy(t + extra, temp->data);
1205 free(temp->data);
1206 temp->data = t;
1207 }
1208 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001209#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001210 }
1211
1212
1213 totlines++;
Chris Allegretta88520c92001-05-05 17:45:54 +00001214 /* Everything about it makes me want this line here, but it causes
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001215 * totsize to be high by one for some reason. Sigh. (Rob) */
1216 /* totsize++; */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001217
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001218 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001219 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001220
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001221
1222 /* Move the cursor to the new line if appropriate. */
1223 if (down) {
1224 do_right();
1225 }
1226
1227 /* Move the cursor to the correct spot in the line if appropriate. */
1228 while (right--) {
1229 do_right();
1230 }
1231
Chris Allegretta234a34d2000-07-29 04:33:38 +00001232 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001233 reset_cursor();
1234 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001235}
1236
1237/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001238void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001239{
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001240 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001241#ifdef DEBUG
1242 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
1243 inptr->data);
1244#endif
1245
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001246 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001247 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001248 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001249 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001250
1251 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001252 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001253
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001254 while (isspace((int) inptr->data[i]) && inptr->data[i])
Adam Rogoyski09f97962000-06-20 02:50:33 +00001255 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001256
Adam Rogoyski09f97962000-06-20 02:50:33 +00001257 if (!inptr->data[i])
1258 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001259
Adam Rogoyski09f97962000-06-20 02:50:33 +00001260 /* String must be at least 1 character long. */
1261 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001262 if (isspace((int) inptr->data[i])) {
Adam Rogoyski09f97962000-06-20 02:50:33 +00001263 if (!char_found)
1264 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001265 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001266 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001267 } else
1268 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001269 }
Adam Rogoyski09f97962000-06-20 02:50:33 +00001270
1271 if (char_found == 2)
1272 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001273 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001274}
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001275#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001276
1277/* Stuff we do when we abort from programs and want to clean up the
Chris Allegretta88520c92001-05-05 17:45:54 +00001278 * screen. This doesn't do much right now.
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001279 */
1280void do_early_abort(void)
1281{
1282 blank_statusbar_refresh();
1283}
1284
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001285int do_backspace(void)
1286{
1287 filestruct *previous, *tmp;
1288
1289 if (current_x != 0) {
1290 /* Let's get dangerous */
1291 memmove(&current->data[current_x - 1], &current->data[current_x],
1292 strlen(current->data) - current_x + 1);
1293#ifdef DEBUG
1294 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
1295#endif
1296 align(&current->data);
1297 do_left();
1298 } else {
1299 if (current == fileage)
1300 return 0; /* Can't delete past top of file */
1301
1302 previous = current->prev;
1303 current_x = strlen(previous->data);
1304 previous->data = nrealloc(previous->data,
1305 strlen(previous->data) +
1306 strlen(current->data) + 1);
1307 strcat(previous->data, current->data);
1308
1309 tmp = current;
1310 unlink_node(current);
1311 delete_node(current);
1312 if (current == edittop) {
1313 if (previous->next)
1314 current = previous->next;
1315 else
1316 current = previous;
Chris Allegretta3e3ae942001-09-22 19:02:04 +00001317 page_up();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001318 } else {
1319 if (previous->next)
1320 current = previous->next;
1321 else
1322 current = previous;
1323 update_line(current, current_x);
1324 }
1325
1326 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001327 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001328 filebot = current;
1329 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001330
1331 /* Recreate the magic line if we're deleting it AND if the
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001332 line we're on now is NOT blank. if it is blank we
1333 can just use IT for the magic line. This is how Pico
1334 appears to do it, in any case */
Chris Allegretta28a0f892000-07-05 22:47:54 +00001335 if (strcmp(current->data, "")) {
1336 new_magicline();
1337 fix_editbot();
1338 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001339 }
1340
1341 current = previous;
1342 renumber(current);
1343 previous_line();
1344 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001345#ifdef DEBUG
1346 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
1347#endif
1348
1349 }
1350
1351 totsize--;
1352 set_modified();
1353 UNSET(KEEP_CUTBUFFER);
1354 edit_refresh();
1355 return 1;
1356}
1357
1358int do_delete(void)
1359{
1360 filestruct *foo;
1361
1362 if (current_x != strlen(current->data)) {
1363 /* Let's get dangerous */
1364 memmove(&current->data[current_x], &current->data[current_x + 1],
1365 strlen(current->data) - current_x);
1366
1367 align(&current->data);
1368
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001369 /* Now that we have a magic lnie again, we can check for both being
1370 on the line before filebot as well as at filebot */
Chris Allegretta4ed13152001-02-10 17:50:50 +00001371 } else if (current->next != NULL && current->next != filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001372 current->data = nrealloc(current->data,
1373 strlen(current->data) +
1374 strlen(current->next->data) + 1);
1375 strcat(current->data, current->next->data);
1376
1377 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001378 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001379 filebot = current;
1380 editbot = current;
1381 }
1382
1383 unlink_node(foo);
1384 delete_node(foo);
1385 update_line(current, current_x);
1386
Chris Allegretta4ed13152001-02-10 17:50:50 +00001387 /* Please see the comment in do_backspace if you don't understand
Chris Allegretta28a0f892000-07-05 22:47:54 +00001388 this test */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001389 if (current == filebot && strcmp(current->data, "")) {
Chris Allegretta28a0f892000-07-05 22:47:54 +00001390 new_magicline();
1391 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001392 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001393 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001394 renumber(current);
1395 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001396 } else
1397 return 0;
1398
1399 totsize--;
1400 set_modified();
1401 UNSET(KEEP_CUTBUFFER);
1402 edit_refresh();
1403 return 1;
1404}
1405
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001406void wrap_reset(void)
1407{
1408 UNSET(SAMELINEWRAP);
1409}
1410
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001411#ifndef DISABLE_SPELLER
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001412
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001413int do_int_spell_fix(char *word)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001414{
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001415 char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001416 filestruct *begin;
1417 int i = 0, j = 0, beginx, beginx_top;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001418
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001419 /* save where we are */
1420 begin = current;
1421 beginx = current_x + 1;
1422
1423 /* save the current search/replace strings */
1424 search_init_globals();
1425 save_search = mallocstrcpy(save_search, last_search);
1426 save_replace = mallocstrcpy(save_replace, last_replace);
1427
1428 /* set search/replace strings to mis-spelt word */
1429 prevanswer = mallocstrcpy(prevanswer, word);
1430 last_search = mallocstrcpy(last_search, word);
1431 last_replace = mallocstrcpy(last_replace, word);
1432
1433 /* start from the top of file */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001434 current = fileage;
1435 current_x = beginx_top = -1;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001436
1437 search_last_line = FALSE;
1438
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001439 edit_update(fileage, TOP);
1440
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001441 /* make sure word is still mis-spelt (i.e. when multi-errors) */
Chris Allegretta8d990b52001-09-22 22:14:25 +00001442 if (findnextstr(TRUE, FALSE, fileage, beginx_top, prevanswer) != NULL) {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001443 do_replace_highlight(TRUE, prevanswer);
1444
1445 /* allow replace word to be corrected */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001446 i = statusq(0, spell_list, SPELL_LIST_LEN, last_replace,
1447 _("Edit a replacement"));
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001448
1449 do_replace_highlight(FALSE, prevanswer);
1450
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001451 /* start from the start of this line again */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001452 current = fileage;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001453 current_x = beginx_top;
1454
1455 search_last_line = FALSE;
1456
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001457 j = i;
1458 do_replace_loop(prevanswer, fileage, &beginx_top, TRUE, &j);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001459 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001460
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001461 /* restore the search/replace strings */
1462 last_search = mallocstrcpy(last_search, save_search);
1463 last_replace = mallocstrcpy(last_replace, save_replace);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001464
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001465 /* restore where we were */
1466 current = begin;
1467 current_x = beginx - 1;
1468
1469 edit_update(current, CENTER);
1470
1471 if (i == -1)
1472 return FALSE;
1473
1474 return TRUE;
1475}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001476
1477/* Integrated spell checking using 'spell' program */
Chris Allegretta271e9722000-11-10 18:15:43 +00001478int do_int_speller(char *tempfile_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001479{
Chris Allegretta271e9722000-11-10 18:15:43 +00001480 char *read_buff, *read_buff_ptr, *read_buff_word;
1481 long pipe_buff_size;
1482 int in_fd[2], tempfile_fd;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001483 int spell_status;
1484 pid_t pid_spell;
1485 ssize_t bytesread;
1486
Chris Allegretta271e9722000-11-10 18:15:43 +00001487 /* Create a pipe to spell program */
1488
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001489 if (pipe(in_fd) == -1)
1490 return FALSE;
1491
Chris Allegretta271e9722000-11-10 18:15:43 +00001492 /* A new process to run spell in */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001493
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001494 if ((pid_spell = fork()) == 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001495
1496 /* Child continues, (i.e. future spell process) */
1497
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001498 close(in_fd[0]);
1499
Chris Allegretta271e9722000-11-10 18:15:43 +00001500 /* replace the standard in with the tempfile */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001501
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001502 if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001503
1504 close(in_fd[1]);
1505 exit(1);
1506 }
1507
1508 if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
1509
1510 close(tempfile_fd);
1511 close(in_fd[1]);
1512 exit(1);
1513 }
1514 close(tempfile_fd);
1515
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001516
Chris Allegretta271e9722000-11-10 18:15:43 +00001517 /* send spell's standard out to the pipe */
1518
1519 if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1520
1521 close(in_fd[1]);
1522 exit(1);
1523 }
1524 close(in_fd[1]);
1525
1526 /* Start spell program, we are using the PATH here!?!? */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001527 execlp("spell", "spell", NULL);
1528
Chris Allegretta271e9722000-11-10 18:15:43 +00001529 /* Should not be reached, if spell is found!!! */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001530
Chris Allegretta271e9722000-11-10 18:15:43 +00001531 exit(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001532 }
1533
1534 /* Parent continues here */
1535
Chris Allegretta271e9722000-11-10 18:15:43 +00001536 close(in_fd[1]);
1537
1538 /* Child process was not forked successfully */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001539
1540 if (pid_spell < 0) {
1541
Chris Allegretta271e9722000-11-10 18:15:43 +00001542 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001543 return FALSE;
1544 }
1545
Chris Allegretta271e9722000-11-10 18:15:43 +00001546 /* Get system pipe buffer size */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001547
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001548 if ((pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001549
Chris Allegretta271e9722000-11-10 18:15:43 +00001550 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001551 return FALSE;
Chris Allegretta271e9722000-11-10 18:15:43 +00001552 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001553
Chris Allegretta88b09152001-05-17 11:35:43 +00001554 read_buff = charalloc(pipe_buff_size + 1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001555
Chris Allegretta271e9722000-11-10 18:15:43 +00001556 /* Process the returned spelling errors */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001557
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001558 while ((bytesread = read(in_fd[0], read_buff, pipe_buff_size)) > 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001559
Chris Allegretta271e9722000-11-10 18:15:43 +00001560 read_buff[bytesread] = (char) NULL;
1561 read_buff_word = read_buff_ptr = read_buff;
1562
1563 while (*read_buff_ptr != (char) NULL) {
1564
1565 /* Windows version may need to process additional char '\r' */
1566
1567 /* Possible problem here if last word not followed by '\n' */
1568
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001569 if (*read_buff_ptr == '\n') {
Chris Allegretta271e9722000-11-10 18:15:43 +00001570 *read_buff_ptr = (char) NULL;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001571 if (!do_int_spell_fix(read_buff_word)) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001572
1573 close(in_fd[0]);
1574 free(read_buff);
1575 replace_abort();
1576
1577 return TRUE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001578 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001579 read_buff_word = read_buff_ptr;
1580 read_buff_word++;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001581 }
1582
1583 read_buff_ptr++;
1584 }
1585 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001586
1587 close(in_fd[0]);
1588 free(read_buff);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001589 replace_abort();
1590
Chris Allegretta271e9722000-11-10 18:15:43 +00001591 /* Process end of spell process */
1592
1593 wait(&spell_status);
1594 if (WIFEXITED(spell_status)) {
1595 if (WEXITSTATUS(spell_status) != 0)
1596 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001597 } else
Chris Allegretta271e9722000-11-10 18:15:43 +00001598 return FALSE;
1599
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001600 return TRUE;
1601}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001602
1603/* External spell checking */
Chris Allegretta271e9722000-11-10 18:15:43 +00001604int do_alt_speller(char *file_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001605{
Chris Allegrettab3655b42001-10-22 03:15:31 +00001606 int alt_spell_status, lineno_cur = current->lineno;
1607 int x_cur = current_x, y_cur = current_y, pww_cur = placewewant;
1608
Chris Allegretta271e9722000-11-10 18:15:43 +00001609 pid_t pid_spell;
Chris Allegretta169ee842001-01-26 01:57:32 +00001610 char *ptr;
1611 static int arglen = 3;
1612 static char **spellargs = (char **) NULL;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001613
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001614 endwin();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001615
Chris Allegrettae434b452001-01-27 19:25:00 +00001616 /* Set up an argument list to pass the execvp function */
1617 if (spellargs == NULL) {
1618 spellargs = nmalloc(arglen * sizeof(char *));
Chris Allegretta271e9722000-11-10 18:15:43 +00001619
Chris Allegrettae434b452001-01-27 19:25:00 +00001620 spellargs[0] = strtok(alt_speller, " ");
1621 while ((ptr = strtok(NULL, " ")) != NULL) {
1622 arglen++;
1623 spellargs = nrealloc(spellargs, arglen * sizeof(char *));
1624 spellargs[arglen - 3] = ptr;
Chris Allegretta169ee842001-01-26 01:57:32 +00001625 }
Chris Allegrettae434b452001-01-27 19:25:00 +00001626 spellargs[arglen - 1] = NULL;
1627 }
1628 spellargs[arglen - 2] = file_name;
1629
1630 /* Start a new process for the alternate speller */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001631 if ((pid_spell = fork()) == 0) {
Chris Allegretta169ee842001-01-26 01:57:32 +00001632
Chris Allegretta88520c92001-05-05 17:45:54 +00001633 /* Start alternate spell program; we are using the PATH here!?!? */
Chris Allegretta169ee842001-01-26 01:57:32 +00001634 execvp(spellargs[0], spellargs);
Chris Allegretta271e9722000-11-10 18:15:43 +00001635
1636 /* Should not be reached, if alternate speller is found!!! */
1637
1638 exit(1);
1639 }
1640
1641 /* Could not fork?? */
1642
1643 if (pid_spell < 0)
1644 return FALSE;
1645
1646 /* Wait for alternate speller to complete */
1647
1648 wait(&alt_spell_status);
1649 if (WIFEXITED(alt_spell_status)) {
1650 if (WEXITSTATUS(alt_spell_status) != 0)
1651 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001652 } else
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001653 return FALSE;
1654
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001655 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001656 free_filestruct(fileage);
Chris Allegretta56214c62001-09-27 02:46:53 +00001657 global_init(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001658 open_file(file_name, 0, 1);
Rocco Corsi4dfaf932001-04-20 01:59:55 +00001659
Chris Allegretta1b3381b2001-09-28 21:59:01 +00001660 /* go back to the old position, mark the file as modified, and make
1661 sure that the titlebar is refreshed */
1662 do_gotopos(lineno_cur, x_cur, y_cur, pww_cur);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001663 set_modified();
Chris Allegrettae1f14522001-09-19 03:19:43 +00001664 clearok(topwin, FALSE);
1665 titlebar(NULL);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001666
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001667 return TRUE;
1668}
1669#endif
1670
1671int do_spell(void)
1672{
1673
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001674#ifdef DISABLE_SPELLER
Chris Allegrettaff269f82000-12-01 18:46:01 +00001675 nano_disabled_msg();
1676 return (TRUE);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001677#else
Chris Allegretta271e9722000-11-10 18:15:43 +00001678 char *temp;
1679 int spell_res;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001680
Chris Allegretta271e9722000-11-10 18:15:43 +00001681 if ((temp = tempnam(0, "nano.")) == NULL) {
1682 statusbar(_("Could not create a temporary filename: %s"),
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001683 strerror(errno));
Chris Allegretta271e9722000-11-10 18:15:43 +00001684 return 0;
1685 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001686
Chris Allegrettaecc3d7f2001-06-05 23:24:55 +00001687 if (write_file(temp, 1, 0, 0) == -1) {
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001688 statusbar(_("Spell checking failed: unable to write temp file!"));
Chris Allegretta271e9722000-11-10 18:15:43 +00001689 return 0;
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001690 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001691
Chris Allegrettae1f14522001-09-19 03:19:43 +00001692#ifdef ENABLE_MULTIBUFFER
1693 /* update the current open_files entry before spell-checking, in case
1694 any problems occur; the case of there being no open_files entries
1695 is handled elsewhere (before we reach this point); no duplicate
1696 checking is needed here */
1697 add_open_file(1, 0);
1698#endif
1699
Chris Allegretta271e9722000-11-10 18:15:43 +00001700 if (alt_speller)
1701 spell_res = do_alt_speller(temp);
1702 else
1703 spell_res = do_int_speller(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001704
Chris Allegretta271e9722000-11-10 18:15:43 +00001705 remove(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001706
1707 if (spell_res)
1708 statusbar(_("Finished checking spelling"));
1709 else
1710 statusbar(_("Spell checking failed"));
1711
1712 return spell_res;
1713
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001714#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001715}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001716
1717int do_exit(void)
1718{
1719 int i;
1720
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001721 if (!ISSET(MODIFIED)) {
1722
Chris Allegretta355fbe52001-07-14 19:32:47 +00001723#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001724 if (!close_open_file()) {
1725 display_main_list();
1726 return 1;
1727 }
1728 else
1729#endif
1730
1731 finish(0);
1732 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001733
Chris Allegretta30885552000-07-14 01:20:12 +00001734 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001735 i = 1;
1736 } else {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001737 i = do_yesno(0, 0,
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001738 _
1739 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1740 }
1741
1742#ifdef DEBUG
1743 dump_buffer(fileage);
1744#endif
1745
1746 if (i == 1) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001747 if (do_writeout(filename, 1, 0) > 0) {
1748
Chris Allegretta355fbe52001-07-14 19:32:47 +00001749#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001750 if (!close_open_file()) {
1751 display_main_list();
1752 return 1;
1753 }
1754 else
1755#endif
1756
1757 finish(0);
1758 }
1759 } else if (i == 0) {
1760
Chris Allegretta355fbe52001-07-14 19:32:47 +00001761#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001762 if (!close_open_file()) {
1763 display_main_list();
1764 return 1;
1765 }
1766 else
1767#endif
1768
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001769 finish(0);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001770 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001771 statusbar(_("Cancelled"));
1772
1773 display_main_list();
1774 return 1;
1775}
1776
Chris Allegretta84de5522001-04-12 14:51:48 +00001777#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001778#ifdef NCURSES_MOUSE_VERSION
1779void do_mouse(void)
1780{
1781 MEVENT mevent;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001782 int foo = 0, tab_found = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001783
1784 if (getmouse(&mevent) == ERR)
1785 return;
1786
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001787 /* If mouse not in edit or bottom window, return */
1788 if (wenclose(edit, mevent.y, mevent.x)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001789
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001790 /* Don't let people screw with the marker when they're in a
1791 subfunction */
1792 if (currshortcut != main_list)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001793 return;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001794
1795 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1796 mevent.y -= 2;
1797
1798 /* Selecting where the cursor is sets the mark.
1799 * Selecting beyond the line length with the cursor at the end of the
1800 * line sets the mark as well.
1801 */
1802 if ((mevent.y == current_y) &&
1803 ((mevent.x == current_x) || (current_x == strlen(current->data)
1804 && (mevent.x >
1805 strlen(current->data))))) {
1806 if (ISSET(VIEW_MODE)) {
1807 print_view_warning();
1808 return;
1809 }
1810 do_mark();
1811 } else if (mevent.y > current_y) {
1812 while (mevent.y > current_y) {
1813 if (current->next != NULL)
1814 current = current->next;
1815 else
1816 break;
1817 current_y++;
1818 }
1819 } else if (mevent.y < current_y) {
1820 while (mevent.y < current_y) {
1821 if (current->prev != NULL)
1822 current = current->prev;
1823 else
1824 break;
1825 current_y--;
1826 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001827 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001828 current_x = mevent.x;
1829 placewewant = current_x;
1830 while (foo < current_x) {
1831 if (current->data[foo] == NANO_CONTROL_I) {
1832 current_x -= tabsize - (foo % tabsize);
1833 tab_found = 1;
1834 } else if (current->data[foo] & 0x80);
1835 else if (current->data[foo] < 32)
1836 current_x--;
1837 foo++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001838 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001839 /* This is where tab_found comes in. I can't figure out why,
1840 * but without it any line with a tab will place the cursor
1841 * one character behind. Whatever, this fixes it. */
1842 if (tab_found == 1)
1843 current_x++;
1844
1845 if (current_x > strlen(current->data))
1846 current_x = strlen(current->data);
1847
1848 update_cursor();
1849 edit_refresh();
1850 } else if (wenclose(bottomwin, mevent.y, mevent.x) && !ISSET(NO_HELP)) {
Chris Allegrettaa951f212001-09-27 21:07:39 +00001851
1852 int k, val = 0;
1853
1854 if (currslen < 2)
1855 k = COLS / 6;
1856 else
1857 k = COLS / ((currslen + (currslen %2)) / 2);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001858
1859 /* Determine what shortcut list was clicked */
1860 mevent.y -= (editwinrows + 3);
1861
1862 if (mevent.y < 0) /* They clicked on the statusbar */
1863 return;
1864
1865 /* Don't select stuff beyond list length */
1866 if (mevent.x / k >= currslen)
1867 return;
1868
1869 val = currshortcut[(mevent.x / k) * 2 + mevent.y].val;
1870
1871 /* And ungetch that value */
1872 ungetch(val);
Chris Allegretta6414b402001-09-21 03:21:11 +00001873
1874 /* And if it's an alt-key sequence, we should probably send alt
1875 too ;-) */
1876 if (val >= 'a' && val <= 'z')
1877 ungetch(27);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001878 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001879}
1880#endif
1881#endif
1882
1883/* Handler for SIGHUP */
1884RETSIGTYPE handle_hup(int signal)
1885{
Chris Allegrettae7a58932000-12-02 02:36:22 +00001886 die(_("Received SIGHUP"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001887}
1888
Chris Allegretta18f8be02000-09-04 03:20:38 +00001889/* What do we do when we catch the suspend signal */
1890RETSIGTYPE do_suspend(int signal)
1891{
Chris Allegretta18f8be02000-09-04 03:20:38 +00001892 endwin();
Chris Allegretta521e00d2001-06-28 16:52:52 +00001893 printf("\n\n\n\n\nUse \"fg\" to return to nano\n");
1894 fflush(stdout);
1895
1896 /* We used to re-enable the default SIG_DFL and raise SIGTSTP, but
1897 then we could be (and were) interrupted in the middle of the call.
1898 So we do it the mutt way instead */
1899 kill(0, SIGSTOP);
Chris Allegretta18f8be02000-09-04 03:20:38 +00001900}
1901
1902/* Restore the suspend handler when we come back into the prog */
1903RETSIGTYPE do_cont(int signal)
1904{
1905
Chris Allegretta521e00d2001-06-28 16:52:52 +00001906 /* Now we just update the screen instead of having to reenable the
1907 SIGTSTP handler */
1908
Chris Allegretta521e00d2001-06-28 16:52:52 +00001909 doupdate();
Chris Allegretta18f8be02000-09-04 03:20:38 +00001910}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001911
1912void handle_sigwinch(int s)
1913{
1914#ifndef NANO_SMALL
1915 char *tty = NULL;
1916 int fd = 0;
1917 int result = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001918 struct winsize win;
1919
1920 tty = ttyname(0);
1921 if (!tty)
1922 return;
1923 fd = open(tty, O_RDWR);
1924 if (fd == -1)
1925 return;
1926 result = ioctl(fd, TIOCGWINSZ, &win);
1927 if (result == -1)
1928 return;
1929
1930
1931 COLS = win.ws_col;
1932 LINES = win.ws_row;
1933
Chris Allegrettae61e8302001-01-14 05:18:27 +00001934 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1935 die_too_small();
1936
Chris Allegretta6fe61492001-05-21 12:56:25 +00001937#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettae61e8302001-01-14 05:18:27 +00001938 if ((fill = COLS - CHARS_FROM_EOL) < MIN_FILL_LENGTH)
1939 die_too_small();
Chris Allegretta6fe61492001-05-21 12:56:25 +00001940#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001941
Chris Allegretta0a06e072001-01-23 02:35:04 +00001942 hblank = nrealloc(hblank, COLS + 1);
1943 memset(hblank, ' ', COLS);
1944 hblank[COLS] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001945
Chris Allegretta618f5d72001-02-16 04:48:30 +00001946#ifdef HAVE_RESIZETERM
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001947 resizeterm(LINES, COLS);
1948#ifdef HAVE_WRESIZE
1949 if (wresize(topwin, 2, COLS) == ERR)
1950 die(_("Cannot resize top win"));
1951 if (mvwin(topwin, 0, 0) == ERR)
1952 die(_("Cannot move top win"));
1953 if (wresize(edit, editwinrows, COLS) == ERR)
1954 die(_("Cannot resize edit win"));
1955 if (mvwin(edit, 2, 0) == ERR)
1956 die(_("Cannot move edit win"));
1957 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1958 die(_("Cannot resize bottom win"));
1959 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1960 die(_("Cannot move bottom win"));
1961#endif /* HAVE_WRESIZE */
Chris Allegretta618f5d72001-02-16 04:48:30 +00001962#endif /* HAVE_RESIZETERM */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001963
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001964 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001965
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001966 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001967 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001968 }
1969 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00001970
1971 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001972 refresh();
Chris Allegrettaf4b96012001-01-03 07:11:47 +00001973 titlebar(NULL);
Chris Allegretta97accc62000-06-19 05:45:52 +00001974 edit_refresh();
1975 display_main_list();
Chris Allegretta08020882001-01-29 23:37:54 +00001976 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001977 total_refresh();
Chris Allegretta08020882001-01-29 23:37:54 +00001978
Chris Allegretta4e90c402001-01-29 23:40:43 +00001979 /* Turn cursor back on for sure */
1980 curs_set(1);
1981
Chris Allegretta08020882001-01-29 23:37:54 +00001982 /* Jump back to mainloop */
1983 siglongjmp(jmpbuf, 1);
1984
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001985#endif
1986}
1987
Chris Allegretta756f2202000-09-01 13:32:47 +00001988void signal_init(void)
1989{
Chris Allegrettaac899e52001-06-30 04:09:09 +00001990#ifdef _POSIX_VDISABLE
1991 struct termios term;
1992#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00001993
Chris Allegretta88520c92001-05-05 17:45:54 +00001994 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
Chris Allegretta756f2202000-09-01 13:32:47 +00001995 memset(&act, 0, sizeof(struct sigaction));
1996 act.sa_handler = SIG_IGN;
1997 sigaction(SIGINT, &act, NULL);
Chris Allegretta756f2202000-09-01 13:32:47 +00001998
Chris Allegretta88520c92001-05-05 17:45:54 +00001999 /* Trap SIGHUP cuz we want to write the file out. */
Chris Allegretta756f2202000-09-01 13:32:47 +00002000 act.sa_handler = handle_hup;
2001 sigaction(SIGHUP, &act, NULL);
2002
2003 act.sa_handler = handle_sigwinch;
2004 sigaction(SIGWINCH, &act, NULL);
2005
Chris Allegretta521e00d2001-06-28 16:52:52 +00002006 if (!ISSET(SUSPEND)) {
Chris Allegrettaac899e52001-06-30 04:09:09 +00002007
2008/* Insane! */
2009#ifdef _POSIX_VDISABLE
2010 tcgetattr(0, &term);
2011 term.c_cc[VSUSP] = _POSIX_VDISABLE;
2012 tcsetattr(0, TCSANOW, &term);
Chris Allegretta9b8b3702001-11-19 05:09:15 +00002013#endif
2014
2015 /* The HURD seems to need this anyway! */
Chris Allegrettaac899e52001-06-30 04:09:09 +00002016 act.sa_handler = SIG_IGN;
Chris Allegretta521e00d2001-06-28 16:52:52 +00002017 sigaction(SIGTSTP, &act, NULL);
Chris Allegrettaac899e52001-06-30 04:09:09 +00002018
Chris Allegretta521e00d2001-06-28 16:52:52 +00002019 } else {
2020 /* if we don't do this, it seems other stuff interrupts the
2021 suspend handler! Try using nano with mutt without this line */
2022 sigfillset(&act.sa_mask);
2023
2024 act.sa_handler = do_suspend;
2025 sigaction(SIGTSTP, &act, NULL);
2026
2027 act.sa_handler = do_cont;
2028 sigaction(SIGCONT, &act, NULL);
2029 }
2030
Chris Allegretta756f2202000-09-01 13:32:47 +00002031}
2032
Chris Allegretta2a42af12000-09-12 23:02:49 +00002033void window_init(void)
2034{
Chris Allegrettae61e8302001-01-14 05:18:27 +00002035 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
2036 die_too_small();
Chris Allegretta92c9dd22000-09-13 14:03:27 +00002037
Chris Allegretta88520c92001-05-05 17:45:54 +00002038 /* Set up the main text window */
Chris Allegretta2a42af12000-09-12 23:02:49 +00002039 edit = newwin(editwinrows, COLS, 2, 0);
2040
2041 /* And the other windows */
2042 topwin = newwin(2, COLS, 0, 0);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002043 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002044
Chris Allegretta155d6202001-01-08 01:50:37 +00002045#ifdef PDCURSES
2046 /* Oops, I guess we need this again.
2047 Moved here so the keypad still works after a Meta-X, for example */
2048 keypad(edit, TRUE);
2049 keypad(bottomwin, TRUE);
2050#endif
2051
Chris Allegretta2a42af12000-09-12 23:02:49 +00002052}
2053
Chris Allegretta756f2202000-09-01 13:32:47 +00002054void mouse_init(void)
2055{
Chris Allegretta84de5522001-04-12 14:51:48 +00002056#ifndef DISABLE_MOUSE
Chris Allegretta756f2202000-09-01 13:32:47 +00002057#ifdef NCURSES_MOUSE_VERSION
2058 if (ISSET(USE_MOUSE)) {
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002059 keypad_on(edit, 1);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002060 keypad_on(bottomwin, 1);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002061
Chris Allegretta756f2202000-09-01 13:32:47 +00002062 mousemask(BUTTON1_RELEASED, NULL);
2063 mouseinterval(50);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00002064
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002065 } else
Chris Allegretta756f2202000-09-01 13:32:47 +00002066 mousemask(0, NULL);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002067
Chris Allegretta756f2202000-09-01 13:32:47 +00002068#endif
2069#endif
2070
2071}
2072
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002073int do_tab(void)
2074{
2075 do_char('\t');
2076 return 1;
2077}
2078
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002079#ifndef DISABLE_JUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002080int empty_line(const char *data)
2081{
2082 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002083 if (!isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002084 return 0;
2085
2086 data++;
2087 }
2088
2089 return 1;
2090}
2091
2092int no_spaces(const char *data)
2093{
2094 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002095 if (isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002096 return 0;
2097
2098 data++;
2099 }
2100
2101 return 1;
2102}
2103
2104void justify_format(char *data)
2105{
2106 int i = 0;
2107 int len = strlen(data);
2108
2109 /* Skip first character regardless and leading whitespace. */
2110 for (i = 1; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002111 if (!isspace((int) data[i]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002112 break;
2113 }
2114
2115 i++; /* (i) is now at least 2. */
2116
2117 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
2118 for (; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002119 if (isspace((int) data[i]) && isspace((int) data[i - 1])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002120 && (data[i - 2] != '.')) {
2121 memmove(data + i, data + i + 1, len - i);
2122 len--;
2123 i--;
2124 }
2125 }
2126}
2127#endif
2128
2129int do_justify(void)
2130{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002131#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +00002132 nano_disabled_msg();
2133 return 1;
2134#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002135 int slen = 0; /* length of combined lines on one line. */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002136 int initial_y, kbinput = 0, totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002137 filestruct *initial = NULL, *tmpjust = NULL, *cutbak, *tmptop, *tmpbot;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002138
2139 if (empty_line(current->data)) {
2140 /* Justify starting at first non-empty line. */
2141 do {
2142 if (!current->next)
2143 return 1;
2144
2145 current = current->next;
2146 current_y++;
2147 }
2148 while (empty_line(current->data));
2149 } else {
2150 /* Search back for the beginning of the paragraph, where
2151 * Paragraph is 1) A line with leading whitespace
2152 * or 2) A line following an empty line.
2153 */
2154 while (current->prev != NULL) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002155 if (isspace((int) current->data[0]) || !current->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002156 break;
2157
2158 current = current->prev;
2159 current_y--;
2160 }
2161
2162 /* First line with leading whitespace may be empty. */
2163 if (empty_line(current->data)) {
2164 if (current->next) {
2165 current = current->next;
2166 current_y++;
2167 } else
2168 return 1;
2169 }
2170 }
2171 initial = current;
2172 initial_y = current_y;
2173
2174 set_modified();
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002175 cutbak = cutbuffer; /* Got to like cutbak ;) */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002176 totbak = totsize;
Chris Allegretta9149e612000-11-27 00:23:41 +00002177 cutbuffer = NULL;
2178
2179 tmptop = current;
2180 tmpjust = copy_node(current);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002181
2182 /* This is annoying because it mucks with totsize */
Chris Allegretta9149e612000-11-27 00:23:41 +00002183 add_to_cutbuffer(tmpjust);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002184
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002185 /* Put the whole paragraph into one big line. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002186 while (current->next && !isspace((int) current->next->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002187 && current->next->data[0]) {
2188 filestruct *tmpnode = current->next;
2189 int len = strlen(current->data);
2190 int len2 = strlen(current->next->data);
2191
Chris Allegretta9149e612000-11-27 00:23:41 +00002192 tmpjust = NULL;
Chris Allegretta9149e612000-11-27 00:23:41 +00002193 tmpjust = copy_node(current->next);
2194 add_to_cutbuffer(tmpjust);
2195
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002196 /* Wiping out a newline */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002197 totsize--;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002198
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002199 /* length of both strings plus space between strings and ending \0. */
2200 current->data = nrealloc(current->data, len + len2 + 2);
2201 current->data[len++] = ' ';
2202 current->data[len] = '\0';
2203
2204 strncat(current->data, current->next->data, len2);
2205
2206 unlink_node(tmpnode);
2207 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002208 }
2209
2210 justify_format(current->data);
2211
2212 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002213 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002214
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002215 if ((strlenpt(current->data) > (fill))
2216 && !no_spaces(current->data)) {
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002217 do {
2218 int i = 0;
2219 int len2 = 0;
2220 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002221
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002222 /* Start at fill , unless line isn't that long (but it
2223 * appears at least fill long with tabs.
2224 */
2225 if (slen > fill)
2226 i = fill;
2227 else
2228 i = slen;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002229
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002230 for (; i > 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002231 if (isspace((int) current->data[i]) &&
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002232 ((strlenpt(current->data) - strlen(current->data + i))
2233 <= fill))
2234 break;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002235 }
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002236
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002237 if (!i)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002238 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002239
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002240 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002241
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002242 len2 = strlen(current->data + i + 1);
Chris Allegretta88b09152001-05-17 11:35:43 +00002243 tmpline->data = charalloc(len2 + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002244
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002245 /* Skip the white space in current. */
2246 memcpy(tmpline->data, current->data + i + 1, len2);
2247 tmpline->data[len2] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002248
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002249 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002250
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002251 tmpline->prev = current;
2252 tmpline->next = current->next;
2253 if (current->next != NULL)
2254 current->next->prev = tmpline;
2255
2256 current->next = tmpline;
2257 current = tmpline;
2258 slen -= i + 1;
2259 current_y++;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002260 } while ((strlenpt(current->data) > (fill))
2261 && !no_spaces(current->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002262 }
Chris Allegretta9149e612000-11-27 00:23:41 +00002263 tmpbot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002264
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002265 if (current->next)
2266 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00002267 else
2268 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002269 current_x = 0;
2270 placewewant = 0;
2271
Adam Rogoyski09f97962000-06-20 02:50:33 +00002272 renumber(initial);
2273 totlines = filebot->lineno;
2274
2275 werase(edit);
2276
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002277 if ((current_y < 0) || (current_y >= editwinrows - 1)
2278 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00002279 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002280 center_cursor();
2281 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00002282 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002283 }
2284
Adam Rogoyski09f97962000-06-20 02:50:33 +00002285 edit_refresh();
Chris Allegretta9149e612000-11-27 00:23:41 +00002286 statusbar(_("Can now UnJustify!"));
Chris Allegretta07798352000-11-27 22:58:23 +00002287 /* Change the shortcut list to display the unjustify code */
2288 shortcut_init(1);
2289 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002290 reset_cursor();
2291
Chris Allegretta88520c92001-05-05 17:45:54 +00002292 /* Now get a keystroke and see if it's unjustify; if not, unget the keystroke
Chris Allegretta9149e612000-11-27 00:23:41 +00002293 and return */
Chris Allegretta5f071802001-05-06 02:34:31 +00002294
2295#ifndef DISABLE_MOUSE
2296#ifdef NCURSES_MOUSE_VERSION
2297
2298 /* If it was a mouse click, parse it with do_mouse and it might become
2299 the unjustify key. Else give it back to the input stream. */
2300 if ((kbinput = wgetch(edit)) == KEY_MOUSE)
2301 do_mouse();
2302 else
2303 ungetch(kbinput);
2304#endif
2305#endif
2306
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002307 if ((kbinput = wgetch(edit)) != NANO_UNJUSTIFY_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002308 ungetch(kbinput);
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002309 blank_statusbar_refresh();
2310 } else {
Chris Allegretta9149e612000-11-27 00:23:41 +00002311 /* Else restore the justify we just did (ungrateful user!) */
2312 if (tmptop->prev != NULL)
2313 tmptop->prev->next = tmpbot->next;
Chris Allegrettad022eac2000-11-27 02:50:49 +00002314 else
2315 fileage = current;
Chris Allegretta9149e612000-11-27 00:23:41 +00002316 tmpbot->next->prev = tmptop->prev;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002317 current = tmpbot->next;
Chris Allegretta9149e612000-11-27 00:23:41 +00002318 tmpbot->next = NULL;
2319 do_uncut_text();
Chris Allegrettad022eac2000-11-27 02:50:49 +00002320 if (tmptop->prev == NULL)
2321 edit_refresh();
2322
Chris Allegretta88520c92001-05-05 17:45:54 +00002323 /* Restore totsize from before justify */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002324 totsize = totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002325 free_filestruct(tmptop);
2326 blank_statusbar_refresh();
2327 }
Chris Allegretta4a9c8582000-11-27 22:59:40 +00002328 shortcut_init(0);
2329 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002330 free_filestruct(cutbuffer);
2331 cutbuffer = cutbak;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002332
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002333 return 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002334#endif
2335}
2336
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002337#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002338void help_init(void)
2339{
2340 int i, sofar = 0;
2341 long allocsize = 1; /* How much space we're gonna need for the help text */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002342 char buf[BUFSIZ] = "", *ptr = NULL;
2343
2344 /* First set up the initial help text for the current function */
2345 if (currshortcut == whereis_list || currshortcut == replace_list
2346 || currshortcut == replace_list_2)
2347 ptr = _("Search Command Help Text\n\n "
2348 "Enter the words or characters you would like to search "
2349 "for, then hit enter. If there is a match for the text you "
2350 "entered, the screen will be updated to the location of the "
Jordi Mallach773623c2001-10-28 21:00:49 +00002351 "nearest match for the search string.\n\n "
2352 "If using Pico Mode via the -p or --pico flags, using the "
2353 "Meta-P toggle or using a nanorc file, the previous search "
2354 "string will be shown in brackets after the Search: prompt. "
2355 "Hitting enter without entering any text will preform the "
2356 "previous search. Otherwise, the previous string will be "
2357 "placed in front of the cursor, and can be edited or deleted "
2358 "before hitting enter.\n\n The following functions keys are "
2359 "available in Search mode:\n\n");
Chris Allegrettab3655b42001-10-22 03:15:31 +00002360 else if (currshortcut == goto_list)
2361 ptr = _("Goto Line Help Text\n\n "
2362 "Enter the line number that you wish to go to and hit "
Jordi Mallach773623c2001-10-28 21:00:49 +00002363 "Enter. If there are fewer lines of text than the "
Chris Allegrettab3655b42001-10-22 03:15:31 +00002364 "number you entered, you will be brought to the last line "
2365 "of the file.\n\n The following functions keys are "
2366 "available in Goto Line mode:\n\n");
2367 else if (currshortcut == insertfile_list)
2368 ptr = _("Insert File Help Text\n\n "
2369 "Type in the name of a file to be inserted into the current "
2370 "file buffer at the current cursor location.\n\n "
2371 "If you have compiled nano with multiple file buffer "
2372 "support, and enable multiple buffers with the -F "
Jordi Mallach773623c2001-10-28 21:00:49 +00002373 "or --multibuffer command line flags, the Meta-F toggle or "
2374 "using a nanorc file, inserting a file will cause it to be "
2375 "loaded into a separate buffer (use Ctrl-< and > to switch "
2376 "between file buffers).\n\n The following function keys are "
Chris Allegrettab3655b42001-10-22 03:15:31 +00002377 "available in Insert File mode:\n\n");
2378 else if (currshortcut == writefile_list)
2379 ptr = _("Write File Help Text\n\n "
2380 "Type the name that you wish to save the current file "
2381 "as and hit enter to save the file.\n\n "
2382 "If you are using the marker code with Ctrl-^ and have "
2383 "selected text, you will be prompted to save only the "
2384 "selected portion to a separate file. To reduce the "
2385 "chance of overwriting the current file with just a portion "
2386 "of it, the current filename is not the default in this "
2387 "mode.\n\n The following function keys are available in "
2388 "Write File mode:\n\n");
2389#ifndef DISABLE_BROWSER
2390 else if (currshortcut == browser_list)
2391 ptr = _("File Browser Help Text\n\n "
2392 "The file browser is used to visually browse the "
2393 "directory structure to select a file for reading "
2394 "or writing. You may use the arrow keys or Page Up/"
2395 "Down to browse through the files, and S or Enter to "
2396 "choose the selected file or enter the selected "
2397 "directory. To move up one level, select the directory "
2398 "called \"..\" at the top of the file list.\n\n The "
2399 "following functions keys are available in the file "
2400 "browser:\n\n");
2401 else if (currshortcut == gotodir_list)
2402 ptr = _("Browser Goto Directory Help Text\n\n "
2403 "Enter the name of the directory you would like to "
2404 "browse to.\n\n If tab completion has not been disabled, "
2405 "you can use the TAB key to (attempt to) automatically "
2406 "complete the directory name. The following function "
2407 "keys are available in Browser GotoDir mode:\n\n");
2408#endif
2409 else if (currshortcut == spell_list)
2410 ptr = _("Spell Check Help Text\n\n "
2411 "The spell checker checks the spelling of all text "
2412 "in the current file. When an unknown word is "
2413 "encountered, it is highlighted and a replacement can "
2414 "be edited. It will then prompt to replace every "
2415 "instance of the given misspelled word in the "
2416 "current file.\n\n The following other functions are "
2417 "available in Spell Check mode:\n\n");
2418 else /* Default to the main help list */
2419 ptr = help_text_init;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002420
2421 /* Compute the space needed for the shortcut lists - we add 15 to
2422 have room for the shortcut abbrev and its possible alternate keys */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002423 for (i = 0; i <= currslen - 1; i++)
2424 if (currshortcut[i].help != NULL)
2425 allocsize += strlen(currshortcut[i].help) + 15;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002426
Chris Allegrettab3655b42001-10-22 03:15:31 +00002427 /* If we're on the main list, we also allocate space for toggle help text. */
2428 if (currshortcut == main_list) {
2429 for (i = 0; i <= TOGGLE_LEN - 1; i++)
2430 if (toggles[i].desc != NULL)
2431 allocsize += strlen(toggles[i].desc) + 30;
Chris Allegretta756f2202000-09-01 13:32:47 +00002432
Chris Allegrettab3655b42001-10-22 03:15:31 +00002433 }
2434
2435 allocsize += strlen(ptr);
2436
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002437
2438 if (help_text != NULL)
2439 free(help_text);
2440
2441 /* Allocate space for the help text */
Chris Allegretta88b09152001-05-17 11:35:43 +00002442 help_text = charalloc(allocsize);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002443
2444 /* Now add the text we want */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002445 strcpy(help_text, ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002446
2447 /* Now add our shortcut info */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002448 for (i = 0; i <= currslen - 1; i++) {
2449 if (currshortcut[i].val > 0 && currshortcut[i].val < 'a')
2450 sofar = snprintf(buf, BUFSIZ, "^%c ", currshortcut[i].val + 64);
Chris Allegretta8d990b52001-09-22 22:14:25 +00002451 else
2452 sofar = snprintf(buf, BUFSIZ, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002453
Chris Allegrettab3655b42001-10-22 03:15:31 +00002454 if (currshortcut[i].misc1 > KEY_F0 && currshortcut[i].misc1 <= KEY_F(64))
Robert Siemborski6af14312000-07-01 21:34:26 +00002455 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
Chris Allegrettab3655b42001-10-22 03:15:31 +00002456 currshortcut[i].misc1 - KEY_F0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002457 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002458 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002459
Chris Allegrettab3655b42001-10-22 03:15:31 +00002460 if (currshortcut[i].altval > 0 && currshortcut[i].altval < 91)
Chris Allegrettae49f1232000-09-02 07:20:39 +00002461 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
Chris Allegrettab3655b42001-10-22 03:15:31 +00002462 currshortcut[i].altval - 32);
2463 else if (currshortcut[i].altval > 0)
Chris Allegretta8d990b52001-09-22 22:14:25 +00002464 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
Chris Allegrettab3655b42001-10-22 03:15:31 +00002465 currshortcut[i].altval);
2466 /* Hack */
2467 else if (currshortcut[i].val >= 'a')
2468 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
2469 currshortcut[i].val - 32);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002470 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002471 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002472
Chris Allegretta756f2202000-09-01 13:32:47 +00002473
Chris Allegrettab3655b42001-10-22 03:15:31 +00002474 if (currshortcut[i].help != NULL)
2475 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", currshortcut[i].help);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002476
Chris Allegretta756f2202000-09-01 13:32:47 +00002477
2478 strcat(help_text, buf);
2479 strcat(help_text, "\n");
2480 }
2481
2482 /* And the toggles... */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002483 if (currshortcut == main_list)
2484 for (i = 0; i <= TOGGLE_LEN - 1; i++) {
2485 if (toggles[i].override_ch != 0)
2486 sofar = snprintf(buf, BUFSIZ,
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002487 "M-%c ", toggles[i].override_ch);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002488 else
2489 sofar = snprintf(buf, BUFSIZ,
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002490 "M-%c ", toggles[i].val - 32);
Chris Allegretta756f2202000-09-01 13:32:47 +00002491
Chris Allegrettab3655b42001-10-22 03:15:31 +00002492 if (toggles[i].desc != NULL) {
2493 if (toggles[i].flag != 0)
2494 snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002495 toggles[i].desc);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002496 else
2497 snprintf(&buf[sofar], BUFSIZ - sofar, "%s",
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002498 toggles[i].desc);
2499 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002500
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002501 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00002502 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002503 }
2504
2505}
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002506#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002507
Chris Allegretta756f2202000-09-01 13:32:47 +00002508void do_toggle(int which)
2509{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002510#ifdef NANO_SMALL
2511 nano_disabled_msg();
2512#else
Jordi Mallach2dc0f6b2000-09-07 10:48:00 +00002513 char *enabled = _("enabled");
2514 char *disabled = _("disabled");
Chris Allegrettaf0f63a82000-09-02 18:44:21 +00002515
Chris Allegretta8d990b52001-09-22 22:14:25 +00002516 switch (toggles[which].val) {
2517 case TOGGLE_BACKWARDS_KEY:
2518 case TOGGLE_CASE_KEY:
2519 case TOGGLE_REGEXP_KEY:
2520 return;
2521 }
Chris Allegretta8d990b52001-09-22 22:14:25 +00002522
Chris Allegretta658399a2001-06-14 02:54:22 +00002523 /* Even easier! */
2524 TOGGLE(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002525
Chris Allegretta756f2202000-09-01 13:32:47 +00002526 switch (toggles[which].val) {
2527 case TOGGLE_PICOMODE_KEY:
Chris Allegretta07798352000-11-27 22:58:23 +00002528 shortcut_init(0);
Chris Allegrettac1049ac2001-08-17 00:03:46 +00002529 SET(CLEAR_BACKUPSTRING);
Chris Allegretta756f2202000-09-01 13:32:47 +00002530 display_main_list();
2531 break;
2532 case TOGGLE_SUSPEND_KEY:
2533 signal_init();
2534 break;
2535 case TOGGLE_MOUSE_KEY:
2536 mouse_init();
2537 break;
2538 case TOGGLE_NOHELP_KEY:
Chris Allegretta2a42af12000-09-12 23:02:49 +00002539 wclear(bottomwin);
2540 wrefresh(bottomwin);
2541 window_init();
Chris Allegrettaaffeda82000-12-18 04:03:48 +00002542 fix_editbot();
Chris Allegretta2a42af12000-09-12 23:02:49 +00002543 edit_refresh();
2544 display_main_list();
Chris Allegretta756f2202000-09-01 13:32:47 +00002545 break;
Chris Allegretta99e30e12001-09-23 02:45:27 +00002546 case TOGGLE_DOS_KEY:
2547 UNSET(MAC_FILE);
2548 break;
2549 case TOGGLE_MAC_KEY:
2550 UNSET(DOS_FILE);
2551 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002552 }
Chris Allegretta2a42af12000-09-12 23:02:49 +00002553
Chris Allegretta819e3db2001-07-11 02:37:19 +00002554 if (!ISSET(toggles[which].flag)) {
2555 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
2556 toggles[which].val == TOGGLE_WRAP_KEY)
2557 statusbar("%s %s", toggles[which].desc, enabled);
2558 else
2559 statusbar("%s %s", toggles[which].desc, disabled);
2560 } else {
2561 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
2562 toggles[which].val == TOGGLE_WRAP_KEY)
2563 statusbar("%s %s", toggles[which].desc, disabled);
2564 else
2565 statusbar("%s %s", toggles[which].desc, enabled);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002566 }
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002567
Chris Allegretta756f2202000-09-01 13:32:47 +00002568#endif
2569}
2570
Chris Allegretta88520c92001-05-05 17:45:54 +00002571/* If the NumLock key has made the keypad go awry, print an error
2572 message; hopefully we can address it later. */
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002573void print_numlock_warning(void)
2574{
2575 static int didmsg = 0;
2576 if (!didmsg) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002577 statusbar(_
2578 ("NumLock glitch detected. Keypad will malfunction with NumLock off"));
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002579 didmsg = 1;
2580 }
2581}
2582
Chris Allegretta1748cd12001-01-13 17:22:54 +00002583/* This function returns the correct keystroke, given the A,B,C or D
2584 input key. This is a common sequence of many terms which send
2585 Esc-O-[A-D] or Esc-[-[A-D]. */
2586int ABCD(int input)
2587{
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002588 switch (input) {
2589 case 'A':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002590 case 'a':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002591 return (KEY_UP);
2592 case 'B':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002593 case 'b':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002594 return (KEY_DOWN);
2595 case 'C':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002596 case 'c':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002597 return (KEY_RIGHT);
2598 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002599 case 'd':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002600 return (KEY_LEFT);
2601 default:
2602 return 0;
Chris Allegretta1748cd12001-01-13 17:22:54 +00002603 }
2604}
2605
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002606int main(int argc, char *argv[])
2607{
2608 int optchr;
2609 int kbinput; /* Input from keyboard */
2610 long startline = 0; /* Line to try and start at */
Chris Allegretta08020882001-01-29 23:37:54 +00002611 int keyhandled; /* Have we handled the keystroke yet? */
2612 int i, modify_control_seq;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002613 char *argv0;
Chris Allegrettab516d8e2001-10-03 00:01:36 +00002614 long constcheck; /* Check to constantly update */
Chris Allegretta0357c4d2001-09-19 02:59:25 +00002615
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002616#ifdef _POSIX_VDISABLE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002617 struct termios term;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002618#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002619
2620#ifdef HAVE_GETOPT_LONG
2621 int option_index = 0;
2622 struct option long_options[] = {
Chris Allegretta805c26d2000-09-06 13:39:17 +00002623#ifdef HAVE_REGEX_H
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002624 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00002625#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002626 {"version", 0, 0, 'V'},
2627 {"const", 0, 0, 'c'},
2628 {"suspend", 0, 0, 'z'},
2629 {"nowrap", 0, 0, 'w'},
2630 {"nohelp", 0, 0, 'x'},
2631 {"help", 0, 0, 'h'},
Chris Allegretta7492cec2000-12-18 04:55:21 +00002632 {"view", 0, 0, 'v'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002633#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002634 {"cut", 0, 0, 'k'},
Chris Allegretta7004c282001-09-22 00:42:10 +00002635 {"dos", 0, 0, 'D'},
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002636 {"mac", 0, 0, 'M'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002637 {"autoindent", 0, 0, 'i'},
Chris Allegrettaff989832001-09-17 13:48:00 +00002638#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002639 {"tempfile", 0, 0, 't'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002640#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002641 {"speller", 1, 0, 's'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002642#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00002643
2644#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002645 {"fill", 1, 0, 'r'},
Chris Allegretta6fe61492001-05-21 12:56:25 +00002646#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002647 {"mouse", 0, 0, 'm'},
Chris Allegrettae1f14522001-09-19 03:19:43 +00002648#ifndef DISABLE_OPERATINGDIR
2649 {"operatingdir", 1, 0, 'o'},
2650#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002651 {"pico", 0, 0, 'p'},
2652 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00002653 {"tabsize", 1, 0, 'T'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002654
Chris Allegretta355fbe52001-07-14 19:32:47 +00002655#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002656 {"multibuffer", 0, 0, 'F'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002657#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002658#ifndef NANO_SMALL
2659 {"smooth", 0, 0, 'S'},
2660#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002661 {0, 0, 0, 0}
2662 };
2663#endif
2664
2665 /* Flag inits... */
2666 SET(FOLLOW_SYMLINKS);
2667
2668#ifndef NANO_SMALL
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002669#ifdef ENABLE_NLS
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002670 setlocale(LC_ALL, "");
2671 bindtextdomain(PACKAGE, LOCALEDIR);
2672 textdomain(PACKAGE);
2673#endif
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002674#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002675
Chris Allegretta8d8e0122001-04-18 04:28:54 +00002676#ifdef ENABLE_NANORC
2677 do_rcfile();
2678#endif /* ENABLE_NANORC */
2679
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002680#ifdef HAVE_GETOPT_LONG
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002681 while ((optchr = getopt_long(argc, argv, "h?DFMRST:Vabcefgijklmo:pr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002682 long_options, &option_index)) != EOF) {
2683#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002684 while ((optchr =
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002685 getopt(argc, argv, "h?DFMRST:Vabcefgijklmo:pr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002686#endif
2687
2688 switch (optchr) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002689
Chris Allegretta7004c282001-09-22 00:42:10 +00002690#ifndef NANO_SMALL
2691 case 'D':
2692 SET(DOS_FILE);
2693 break;
2694#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +00002695#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002696 case 'F':
Chris Allegretta355fbe52001-07-14 19:32:47 +00002697 SET(MULTIBUFFER);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002698 break;
2699#endif
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002700#ifndef NANO_SMALL
2701 case 'M':
2702 SET(MAC_FILE);
2703 break;
2704#endif
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002705 case 'T':
Chris Allegretta99bf73f2000-08-04 00:22:08 +00002706 tabsize = atoi(optarg);
2707 if (tabsize <= 0) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002708 usage(); /* To stop bogus data for tab width */
2709 finish(1);
2710 }
2711 break;
Chris Allegretta805c26d2000-09-06 13:39:17 +00002712#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +00002713 case 'R':
2714 SET(USE_REGEXP);
2715 break;
Chris Allegretta47805612000-07-07 02:35:34 +00002716#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002717#ifndef NANO_SMALL
2718 case 'S':
2719 SET(SMOOTHSCROLL);
2720 break;
2721#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002722 case 'V':
2723 version();
2724 exit(0);
Chris Allegrettae1f14522001-09-19 03:19:43 +00002725 case 'a':
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002726 case 'b':
2727 case 'e':
2728 case 'f':
Rocco Corsi12f294c2001-04-14 06:50:24 +00002729 case 'g':
2730 case 'j':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002731 /* Pico compatibility flags */
2732 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002733 case 'c':
2734 SET(CONSTUPDATE);
2735 break;
2736 case 'h':
2737 case '?':
2738 usage();
2739 exit(0);
Chris Allegrettaff989832001-09-17 13:48:00 +00002740#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002741 case 'i':
2742 SET(AUTOINDENT);
2743 break;
Chris Allegretta627de192000-07-12 02:09:17 +00002744 case 'k':
2745 SET(CUT_TO_END);
2746 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002747#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002748 case 'l':
2749 UNSET(FOLLOW_SYMLINKS);
2750 break;
2751 case 'm':
2752 SET(USE_MOUSE);
2753 break;
Chris Allegrettae1f14522001-09-19 03:19:43 +00002754#ifndef DISABLE_OPERATINGDIR
2755 case 'o':
2756 operating_dir = charalloc(strlen(optarg) + 1);
2757 strcpy(operating_dir, optarg);
2758
2759 /* make sure we're inside the operating directory */
2760 if (check_operating_dir(".", 0)) {
2761 if (chdir(operating_dir) == -1) {
2762 free(operating_dir);
2763 operating_dir = NULL;
2764 }
2765 }
2766 break;
2767#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002768 case 'p':
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002769 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002770 break;
2771 case 'r':
Chris Allegretta6fe61492001-05-21 12:56:25 +00002772#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002773 fill = atoi(optarg);
Chris Allegretta6fe61492001-05-21 12:56:25 +00002774 if (fill < 0)
2775 wrap_at = fill;
2776 else if (fill == 0) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002777 usage(); /* To stop bogus data (like a string) */
2778 finish(1);
2779 }
2780 break;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002781#else
2782 usage();
2783 exit(0);
2784
2785#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002786#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002787 case 's':
Chris Allegretta88b09152001-05-17 11:35:43 +00002788 alt_speller = charalloc(strlen(optarg) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002789 strcpy(alt_speller, optarg);
2790 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002791#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002792 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00002793 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002794 break;
2795 case 'v':
2796 SET(VIEW_MODE);
2797 break;
2798 case 'w':
Chris Allegrettacef7fbb2001-04-02 05:36:08 +00002799#ifdef DISABLE_WRAPPING
2800 usage();
2801 exit(0);
2802#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002803 SET(NO_WRAP);
2804 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002805#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002806 case 'x':
2807 SET(NO_HELP);
2808 break;
2809 case 'z':
2810 SET(SUSPEND);
2811 break;
2812 default:
2813 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002814 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002815 }
2816
2817 }
2818
2819 argv0 = strrchr(argv[0], '/');
2820 if ((argv0 && strstr(argv0, "pico"))
2821 || (!argv0 && strstr(argv[0], "pico")))
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002822 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002823
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002824 /* See if there's a non-option in argv (first non-option is the
2825 filename, if +LINE is not given) */
2826 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002827 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002828 else {
2829 /* Look for the +line flag... */
2830 if (argv[optind][0] == '+') {
2831 startline = atoi(&argv[optind][1]);
2832 optind++;
2833 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002834 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002835 else
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002836 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002837
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002838 } else
2839 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002840 }
2841
2842
2843 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002844 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002845
Chris Allegretta9239d742000-09-06 15:19:18 +00002846#ifdef _POSIX_VDISABLE
Chris Allegretta8f6c0692000-07-19 01:16:18 +00002847 term = oldterm;
2848 term.c_cc[VINTR] = _POSIX_VDISABLE;
2849 term.c_cc[VQUIT] = _POSIX_VDISABLE;
2850 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002851 tcsetattr(0, TCSANOW, &term);
Chris Allegretta9239d742000-09-06 15:19:18 +00002852#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002853
2854 /* now ncurses init stuff... */
2855 initscr();
2856 savetty();
2857 nonl();
2858 cbreak();
2859 noecho();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002860
2861 /* Set up some global variables */
Chris Allegretta56214c62001-09-27 02:46:53 +00002862 global_init(0);
Chris Allegretta07798352000-11-27 22:58:23 +00002863 shortcut_init(0);
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002864#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002865 init_help_msg();
2866 help_init();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002867#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002868 signal_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002869
2870#ifdef DEBUG
2871 fprintf(stderr, _("Main: set up windows\n"));
2872#endif
2873
Chris Allegretta2a42af12000-09-12 23:02:49 +00002874 window_init();
Chris Allegretta756f2202000-09-01 13:32:47 +00002875 mouse_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002876
Chris Allegretta08893e02001-11-29 02:42:27 +00002877#ifdef ENABLE_COLOR
2878 do_colorinit();
2879
2880 fprintf(stderr, "COLORS = %d, COLOR_PAIRS = %d\n", COLORS, COLOR_PAIRS);
2881#endif /* ENABLE_COLOR */
2882
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002883#ifdef DEBUG
2884 fprintf(stderr, _("Main: bottom win\n"));
2885#endif
Chris Allegretta88520c92001-05-05 17:45:54 +00002886 /* Set up bottom of window */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002887 display_main_list();
2888
2889#ifdef DEBUG
2890 fprintf(stderr, _("Main: open file\n"));
2891#endif
2892
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002893 titlebar(NULL);
Chris Allegretta31c76662000-11-21 06:20:20 +00002894
2895 /* Now we check to see if argv[optind] is non-null to determine if
2896 we're dealing with a new file or not, not argc == 1... */
2897 if (argv[optind] == NULL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002898 new_file();
2899 else
2900 open_file(filename, 0, 0);
2901
2902 if (startline > 0)
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002903 do_gotoline(startline, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002904 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00002905 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002906
Chris Allegretta08020882001-01-29 23:37:54 +00002907 /* return here after a sigwinch */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002908 sigsetjmp(jmpbuf, 1);
Chris Allegretta08020882001-01-29 23:37:54 +00002909
2910 /* Fix clobber-age */
2911 kbinput = 0;
2912 keyhandled = 0;
2913 modify_control_seq = 0;
2914
Robert Siemborski6967eec2000-07-08 14:23:32 +00002915 edit_refresh();
2916 reset_cursor();
2917
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002918 while (1) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00002919 constcheck = current->lineno + current_x + current_y + totsize;
Chris Allegretta9239d742000-09-06 15:19:18 +00002920
Chris Allegretta6fe61492001-05-21 12:56:25 +00002921#ifndef DISABLE_MOUSE
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002922 currshortcut = main_list;
2923 currslen = MAIN_VISIBLE;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002924#endif
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002925
Chris Allegretta9239d742000-09-06 15:19:18 +00002926#ifndef _POSIX_VDISABLE
2927 /* We're going to have to do it the old way, i.e. on cygwin */
2928 raw();
2929#endif
2930
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002931 kbinput = wgetch(edit);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002932#ifdef DEBUG
2933 fprintf(stderr, "AHA! %c (%d)\n", kbinput, kbinput);
2934#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002935
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002936 if (kbinput == 27) { /* Grab Alt-key stuff first */
2937 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002938 /* Alt-O, suddenly very important ;) */
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002939 case 'O':
Chris Allegretta16e41682000-09-11 22:33:54 +00002940 kbinput = wgetch(edit);
Chris Allegretta316e4d92001-04-28 16:31:19 +00002941 if ((kbinput <= 'D' && kbinput >= 'A') ||
2942 (kbinput <= 'd' && kbinput >= 'a'))
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002943 kbinput = ABCD(kbinput);
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002944 else if (kbinput <= 'z' && kbinput >= 'j')
2945 print_numlock_warning();
2946 else if (kbinput <= 'S' && kbinput >= 'P')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002947 kbinput = KEY_F(kbinput - 79);
Chris Allegretta16e41682000-09-11 22:33:54 +00002948#ifdef DEBUG
2949 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002950 fprintf(stderr, _("I got Alt-O-%c! (%d)\n"),
2951 kbinput, kbinput);
2952 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002953 }
2954#endif
2955 break;
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002956 case 27:
2957 /* If we get Alt-Alt, the next keystroke should be the same as a
2958 control sequence */
2959 modify_control_seq = 1;
2960 keyhandled = 1;
2961 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00002962#ifndef NANO_SMALL
Chris Allegretta76e291b2001-10-14 19:05:10 +00002963 case ' ':
2964 /* If control-space is next word, Alt-space should be previous word */
2965 do_prev_word();
2966 keyhandled = 1;
2967 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00002968#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002969 case '[':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002970 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002971 case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */
Chris Allegretta16e41682000-09-11 22:33:54 +00002972 kbinput = wgetch(edit);
2973 if (kbinput >= '1' && kbinput <= '5') {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002974 kbinput = KEY_F(kbinput - 48);
2975 wgetch(edit);
2976 } else if (kbinput >= '7' && kbinput <= '9') {
2977 kbinput = KEY_F(kbinput - 49);
2978 wgetch(edit);
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002979 } else if (kbinput == '~')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002980 kbinput = KEY_HOME;
Chris Allegretta16e41682000-09-11 22:33:54 +00002981
2982#ifdef DEBUG
2983 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002984 fprintf(stderr, _("I got Alt-[-1-%c! (%d)\n"),
2985 kbinput, kbinput);
2986 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002987 }
2988#endif
2989
2990 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002991 case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */
Chris Allegretta16e41682000-09-11 22:33:54 +00002992 kbinput = wgetch(edit);
Chris Allegretta16e41682000-09-11 22:33:54 +00002993 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002994 case '0':
2995 kbinput = KEY_F(9);
2996 wgetch(edit);
2997 break;
2998 case '1':
2999 kbinput = KEY_F(10);
3000 wgetch(edit);
3001 break;
3002 case '3':
3003 kbinput = KEY_F(11);
3004 wgetch(edit);
3005 break;
3006 case '4':
3007 kbinput = KEY_F(12);
3008 wgetch(edit);
3009 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003010 case '~':
3011 goto do_insertkey;
Chris Allegretta16e41682000-09-11 22:33:54 +00003012#ifdef DEBUG
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003013 default:
3014 fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"),
3015 kbinput, kbinput);
3016 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003017#endif
3018
3019 }
3020 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003021 case '3': /* Alt-[-3 = Delete? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003022 kbinput = NANO_DELETE_KEY;
3023 wgetch(edit);
3024 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003025 case '4': /* Alt-[-4 = End? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003026 kbinput = NANO_END_KEY;
3027 wgetch(edit);
3028 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003029 case '5': /* Alt-[-5 = Page Up */
Chris Allegretta16e41682000-09-11 22:33:54 +00003030 kbinput = KEY_PPAGE;
3031 wgetch(edit);
3032 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003033 case 'V': /* Alt-[-V = Page Up in Hurd Console */
Chris Allegretta7bf72742001-10-28 04:29:55 +00003034 case 'I': /* Alt-[-I = Page Up - FreeBSD Console */
3035 kbinput = KEY_PPAGE;
3036 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003037 case '6': /* Alt-[-6 = Page Down */
Chris Allegretta16e41682000-09-11 22:33:54 +00003038 kbinput = KEY_NPAGE;
3039 wgetch(edit);
3040 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003041 case 'U': /* Alt-[-U = Page Down in Hurd Console */
Chris Allegretta7bf72742001-10-28 04:29:55 +00003042 case 'G': /* Alt-[-G = Page Down - FreeBSD Console */
3043 kbinput = KEY_NPAGE;
3044 break;
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003045 case '7':
3046 kbinput = KEY_HOME;
3047 wgetch(edit);
3048 break;
3049 case '8':
3050 kbinput = KEY_END;
3051 wgetch(edit);
3052 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003053 case '9': /* Alt-[-9 = Delete in Hurd Console */
3054 kbinput = KEY_DC;
3055 break;
3056 case '@': /* Alt-[-9 = Insert in Hurd Console */
Chris Allegretta7bf72742001-10-28 04:29:55 +00003057 case 'L': /* Insert Key - FreeBSD Console */
3058#ifdef ENABLE_MULTIBUFFER
3059 do_insertfile(ISSET(MULTIBUFFER));
3060#else
3061 do_insertfile(0);
3062#endif
3063 keyhandled = 1;
3064 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003065 case '[': /* Alt-[-[-[A-E], F1-F5 in linux console */
Chris Allegretta16e41682000-09-11 22:33:54 +00003066 kbinput = wgetch(edit);
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003067 if (kbinput >= 'A' && kbinput <= 'E')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003068 kbinput = KEY_F(kbinput - 64);
Chris Allegretta16e41682000-09-11 22:33:54 +00003069 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003070 case 'A':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003071 case 'B':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003072 case 'C':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003073 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00003074 case 'a':
3075 case 'b':
3076 case 'c':
3077 case 'd':
Chris Allegretta1748cd12001-01-13 17:22:54 +00003078 kbinput = ABCD(kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003079 break;
3080 case 'H':
3081 kbinput = KEY_HOME;
3082 break;
3083 case 'F':
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003084 case 'Y': /* End Key in Hurd Console */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003085 kbinput = KEY_END;
3086 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003087 default:
3088#ifdef DEBUG
3089 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
3090 kbinput, kbinput);
3091#endif
3092 break;
3093 }
3094 break;
Chris Allegretta355fbe52001-07-14 19:32:47 +00003095#ifdef ENABLE_MULTIBUFFER
Chris Allegretta819e3db2001-07-11 02:37:19 +00003096 case NANO_OPENPREV_KEY:
3097 open_prevfile(0);
3098 keyhandled = 1;
3099 break;
3100 case NANO_OPENNEXT_KEY:
3101 open_nextfile(0);
3102 keyhandled = 1;
3103 break;
Chris Allegretta9cf9e062001-07-11 12:06:13 +00003104#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003105 default:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003106 /* Check for the altkey defs.... */
3107 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
3108 if (kbinput == main_list[i].altval ||
3109 kbinput == main_list[i].altval - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003110 kbinput = main_list[i].val;
3111 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003112 }
Chris Allegretta756f2202000-09-01 13:32:47 +00003113#ifndef NANO_SMALL
3114 /* And for toggle switches */
3115 for (i = 0; i <= TOGGLE_LEN - 1 && !keyhandled; i++)
3116 if (kbinput == toggles[i].val ||
3117 kbinput == toggles[i].val - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003118 do_toggle(i);
3119 keyhandled = 1;
3120 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00003121 }
3122#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003123#ifdef DEBUG
3124 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
3125 kbinput);
3126#endif
3127 break;
3128 }
3129 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003130 /* If the modify_control_seq is set, we received an Alt-Alt
3131 sequence before this, so we make this key a control sequence
3132 by subtracting 64 or 96, depending on its value. */
3133 if (!keyhandled && modify_control_seq) {
3134 if (kbinput >= 'A' && kbinput < 'a')
3135 kbinput -= 64;
3136 else if (kbinput >= 'a' && kbinput <= 'z')
3137 kbinput -= 96;
3138
3139 modify_control_seq = 0;
3140 }
3141
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003142 /* Look through the main shortcut list to see if we've hit a
3143 shortcut key */
Chris Allegretta2cd72b62001-10-24 17:25:36 +00003144 for (i = 0; i < MAIN_LIST_LEN && !keyhandled; i++) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003145 if (kbinput == main_list[i].val ||
3146 (main_list[i].misc1 && kbinput == main_list[i].misc1) ||
3147 (main_list[i].misc2 && kbinput == main_list[i].misc2)) {
3148 if (ISSET(VIEW_MODE) && !main_list[i].viewok)
3149 print_view_warning();
3150 else
3151 main_list[i].func();
3152 keyhandled = 1;
3153 }
3154 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003155 /* If we're in raw mode or using Alt-Alt-x, we have to catch
3156 Control-S and Control-Q */
Chris Allegretta9239d742000-09-06 15:19:18 +00003157 if (kbinput == 17 || kbinput == 19)
3158 keyhandled = 1;
3159
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003160 /* Catch ^Z by hand when triggered also */
Chris Allegretta9239d742000-09-06 15:19:18 +00003161 if (kbinput == 26) {
3162 if (ISSET(SUSPEND))
3163 do_suspend(0);
3164 keyhandled = 1;
3165 }
Chris Allegretta9239d742000-09-06 15:19:18 +00003166
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003167
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003168#ifndef USE_SLANG
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003169 /* Hack, make insert key do something useful, like insert file */
3170 if (kbinput == KEY_IC) {
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003171#else
3172 if (0) {
3173#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003174 do_insertkey:
3175
3176#ifdef ENABLE_MULTIBUFFER
3177 do_insertfile(ISSET(MULTIBUFFER));
3178#else
3179 do_insertfile(0);
3180#endif
3181
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003182 keyhandled = 1;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003183 }
3184
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003185 /* Last gasp, stuff that's not in the main lists */
3186 if (!keyhandled)
3187 switch (kbinput) {
Chris Allegretta84de5522001-04-12 14:51:48 +00003188#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003189#ifdef NCURSES_MOUSE_VERSION
3190 case KEY_MOUSE:
3191 do_mouse();
3192 break;
3193#endif
3194#endif
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003195
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003196 case 0: /* Erg */
Chris Allegretta48ebb812001-10-24 01:34:15 +00003197#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003198 do_next_word();
3199 break;
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003200#endif
Chris Allegrettaf4f7e042001-01-04 16:56:15 +00003201
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003202 case -1: /* Stuff that we don't want to do squat */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003203 case 410: /* Must ignore this, it gets sent when we resize */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003204 case 29: /* Ctrl-] */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003205#ifdef PDCURSES
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003206 case 541: /* ???? */
3207 case 542: /* Control and alt in Windows *shrug* */
Chris Allegretta72623582000-11-29 23:43:28 +00003208 case 543: /* Right ctrl key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003209 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +00003210 case 545: /* Right alt key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003211#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003212
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003213 break;
3214 default:
3215#ifdef DEBUG
3216 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
3217#endif
3218 /* We no longer stop unhandled sequences so that people with
3219 odd character sets can type... */
3220
3221 if (ISSET(VIEW_MODE)) {
3222 print_view_warning();
3223 break;
3224 }
3225 do_char(kbinput);
3226 }
Chris Allegretta7fdbd052001-10-02 00:55:38 +00003227 if (ISSET(DISABLE_CURPOS))
3228 UNSET(DISABLE_CURPOS);
3229 else if (ISSET(CONSTUPDATE))
Chris Allegrettab3655b42001-10-22 03:15:31 +00003230 if (constcheck != current->lineno + current_x + current_y + totsize)
Chris Allegretta756f2202000-09-01 13:32:47 +00003231 do_cursorpos();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003232
3233 reset_cursor();
3234 wrefresh(edit);
3235 keyhandled = 0;
3236 }
3237
3238 getchar();
3239 finish(0);
3240
3241}