blob: 8ccd580d00fcf774852d0e35bd05b64c92362180 [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * nano.c *
4 * *
Jordi Mallach8ae57892002-01-04 17:57:40 +00005 * Copyright (C) 1999-2002 Chris Allegretta *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00006 * 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
Chris Allegretta32da4562002-01-02 15:12:21 +0000125 /* save the currently loaded file if it's been modified */
126 if (ISSET(MODIFIED))
127 die_save_file(filename);
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000128
Chris Allegretta355fbe52001-07-14 19:32:47 +0000129#ifdef ENABLE_MULTIBUFFER
Chris Allegretta32da4562002-01-02 15:12:21 +0000130 /* then save all of the other modified loaded files, if any */
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000131 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;
Chris Allegretta32da4562002-01-02 15:12:21 +0000145 /* save the file if it's been modified */
146 if (open_files->file_modified)
147 die_save_file(open_files->data);
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000148 }
149
150 open_files = open_files->next;
151 }
152
153 }
154#endif
155
156 exit(1); /* We have a problem: exit w/ errorlevel(1) */
157}
158
159void die_save_file(char *die_filename)
160{
161 char *name;
162 int i;
163
164 /* if we can't save we have REAL bad problems,
165 * but we might as well TRY. */
166 if (die_filename[0] == '\0') {
167 name = "nano.save";
168 i = write_file(name, 1, 0, 0);
169 } else {
170
171 char *buf = charalloc(strlen(die_filename) + 6);
172 strcpy(buf, die_filename);
173 strcat(buf, ".save");
174 i = write_file(buf, 1, 0, 0);
175 name = buf;
176 }
177
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000178 if (i != -1)
179 fprintf(stderr, _("\nBuffer written to %s\n"), name);
180 else
Chris Allegretta9756d622000-12-03 03:06:45 +0000181 fprintf(stderr, _("\nNo %s written (file exists?)\n"), name);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000182}
183
Chris Allegrettae61e8302001-01-14 05:18:27 +0000184/* Die with an error message that the screen was too small if, well, the
185 screen is too small */
186void die_too_small(void)
187{
188 char *too_small_msg = _("Window size is too small for Nano...");
189
190 die(too_small_msg);
191
192}
193
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000194void print_view_warning(void)
195{
196 statusbar(_("Key illegal in VIEW mode"));
197}
198
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000199void clear_filename(void)
200{
201 if (filename != NULL)
202 free(filename);
Chris Allegretta88b09152001-05-17 11:35:43 +0000203 filename = charalloc(1);
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000204 filename[0] = 0;
205}
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +0000206
Chris Allegretta56214c62001-09-27 02:46:53 +0000207/* Initialize global variables - no better way for now. If
208 save_cutbuffer is nonzero, don't set cutbuffer to NULL. */
209void global_init(int save_cutbuffer)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000210{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000211 current_x = 0;
212 current_y = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000213
214 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
215 die_too_small();
216
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000217 fileage = NULL;
Chris Allegretta56214c62001-09-27 02:46:53 +0000218 if (!save_cutbuffer)
219 cutbuffer = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000220 current = NULL;
221 edittop = NULL;
222 editbot = NULL;
223 totlines = 0;
Chris Allegretta56214c62001-09-27 02:46:53 +0000224 totsize = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000225 placewewant = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000226
Chris Allegretta6fe61492001-05-21 12:56:25 +0000227#ifndef DISABLE_WRAPJUSTIFY
228 if (wrap_at)
229 fill = COLS + wrap_at;
230 else if (!fill)
Chris Allegrettae61e8302001-01-14 05:18:27 +0000231 fill = COLS - CHARS_FROM_EOL;
232
233 if (fill < MIN_FILL_LENGTH)
234 die_too_small();
Chris Allegretta6fe61492001-05-21 12:56:25 +0000235#endif
Chris Allegrettae61e8302001-01-14 05:18:27 +0000236
Chris Allegretta88b09152001-05-17 11:35:43 +0000237 hblank = charalloc(COLS + 1);
Chris Allegretta0a06e072001-01-23 02:35:04 +0000238 memset(hblank, ' ', COLS);
239 hblank[COLS] = 0;
Chris Allegretta76e291b2001-10-14 19:05:10 +0000240
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000241}
242
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000243#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000244void init_help_msg(void)
245{
246
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000247 help_text_init =
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000248 _(" nano help text\n\n "
249 "The nano editor is designed to emulate the functionality and "
250 "ease-of-use of the UW Pico text editor. There are four main "
251 "sections of the editor: The top line shows the program "
252 "version, the current filename being edited, and whether "
253 "or not the file has been modified. Next is the main editor "
254 "window showing the file being edited. The status line is "
255 "the third line from the bottom and shows important messages. "
256 "The bottom two lines show the most commonly used shortcuts "
257 "in the editor.\n\n "
258 "The notation for shortcuts is as follows: Control-key "
Chris Allegrettae49f1232000-09-02 07:20:39 +0000259 "sequences are notated with a caret (^) symbol and are entered "
Chris Allegrettad56bd792000-09-02 07:27:10 +0000260 "with the Control (Ctrl) key. Escape-key sequences are notated "
261 "with the Meta (M) symbol and can be entered using either the "
262 "Esc, Alt or Meta key depending on your keyboard setup. The "
263 "following keystrokes are available in the main editor window. "
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000264 "Optional keys are shown in parentheses:\n\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000265}
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000266#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000267
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000268/* Make a copy of a node to a pointer (space will be malloc()ed). This
269 does NOT copy the data members used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000270filestruct *copy_node(filestruct * src)
271{
272 filestruct *dst;
273
274 dst = nmalloc(sizeof(filestruct));
Chris Allegretta88b09152001-05-17 11:35:43 +0000275 dst->data = charalloc(strlen(src->data) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000276
277 dst->next = src->next;
278 dst->prev = src->prev;
279
280 strcpy(dst->data, src->data);
281 dst->lineno = src->lineno;
282
283 return dst;
284}
285
286/* Unlink a node from the rest of the struct */
287void unlink_node(filestruct * fileptr)
288{
289 if (fileptr->prev != NULL)
290 fileptr->prev->next = fileptr->next;
291
292 if (fileptr->next != NULL)
293 fileptr->next->prev = fileptr->prev;
294}
295
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000296/* Delete a node from the struct. This does NOT delete the data members
297 used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000298void delete_node(filestruct * fileptr)
299{
Chris Allegretta17dcb722001-01-20 21:40:07 +0000300 if (fileptr == NULL)
301 return;
302
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000303 if (fileptr->data != NULL)
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000304 free(fileptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000305 free(fileptr);
306}
307
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000308/* Okay, now let's duplicate a whole struct! This does NOT duplicate the
309 data members used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000310filestruct *copy_filestruct(filestruct * src)
311{
312 filestruct *dst, *tmp, *head, *prev;
313
314 head = copy_node(src);
315 dst = head; /* Else we barf on copying just one line */
316 head->prev = NULL;
317 tmp = src->next;
318 prev = head;
319
320 while (tmp != NULL) {
321 dst = copy_node(tmp);
322 dst->prev = prev;
323 prev->next = dst;
324
325 prev = dst;
326 tmp = tmp->next;
327 }
328
329 dst->next = NULL;
330 return head;
331}
332
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000333/* Frees a struct. This does NOT free the data members used only by
334 open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000335int free_filestruct(filestruct * src)
336{
337 filestruct *fileptr = src;
338
339 if (src == NULL)
340 return 0;
341
342 while (fileptr->next != NULL) {
343 fileptr = fileptr->next;
Chris Allegretta17dcb722001-01-20 21:40:07 +0000344 delete_node(fileptr->prev);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000345
346#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000347 fprintf(stderr, _("delete_node(): free'd a node, YAY!\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000348#endif
349 }
Chris Allegretta17dcb722001-01-20 21:40:07 +0000350 delete_node(fileptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000351#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000352 fprintf(stderr, _("delete_node(): free'd last node.\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000353#endif
354
355 return 1;
356}
357
358int renumber_all(void)
359{
360 filestruct *temp;
361 long i = 1;
362
363 for (temp = fileage; temp != NULL; temp = temp->next) {
364 temp->lineno = i++;
365 }
366
367 return 0;
368}
369
370int renumber(filestruct * fileptr)
371{
372 filestruct *temp;
373
374 if (fileptr == NULL || fileptr->prev == NULL || fileptr == fileage) {
375 renumber_all();
376 return 0;
377 }
378 for (temp = fileptr; temp != NULL; temp = temp->next) {
Chris Allegretta5146fec2000-12-10 05:44:02 +0000379 if (temp->prev != NULL)
380 temp->lineno = temp->prev->lineno + 1;
381 else
382 temp->lineno = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000383 }
384
385 return 0;
386}
387
388/* Fix the memory allocation for a string */
389void align(char **strp)
390{
391 /* There was a serious bug here: the new address was never
392 stored anywhere... */
393
394 *strp = nrealloc(*strp, strlen(*strp) + 1);
395}
396
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000397/* Null a string at a certain index and align it */
Chris Allegrettafa0c6962001-10-22 23:22:19 +0000398void null_at(char **data, int index)
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000399{
Chris Allegrettafa0c6962001-10-22 23:22:19 +0000400
401 /* Ahh! Damn dereferencing */
402 (*data)[index] = 0;
403 align(data);
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000404}
405
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000406void usage(void)
407{
408#ifdef HAVE_GETOPT_LONG
409 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
410 printf(_("Option Long option Meaning\n"));
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000411
Chris Allegretta7004c282001-09-22 00:42:10 +0000412#ifndef NANO_SMALL
413 printf
414 (_
415 (" -D --dos Write file in DOS format\n"));
416#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000417#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000418 printf
419 (_
Chris Allegretta355fbe52001-07-14 19:32:47 +0000420 (" -F --multibuffer Enable multiple file buffers\n"));
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000421#endif
Chris Allegretta48bd3782002-01-03 21:26:34 +0000422 printf(_
423 (" -K --keypad Use alternate keypad routines\n"));
Chris Allegretta8fa1e282001-09-22 04:20:25 +0000424#ifndef NANO_SMALL
425 printf
426 (_
427 (" -M --mac Write file in Mac format\n"));
428#endif
Chris Allegretta805c26d2000-09-06 13:39:17 +0000429#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000430 printf(_
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000431 (" -R --regexp Use regular expressions for search\n"));
Chris Allegretta47805612000-07-07 02:35:34 +0000432#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +0000433#ifndef NANO_SMALL
434 printf(_
435 (" -S --smooth Smooth scrolling\n"));
436#endif
Chris Allegretta7004c282001-09-22 00:42:10 +0000437 printf(_
438 (" -T [num] --tabsize=[num] Set width of a tab to num\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000439 printf
440 (_
441 (" -V --version Print version information and exit\n"));
442 printf(_
443 (" -c --const Constantly show cursor position\n"));
444 printf(_
445 (" -h --help Show this message\n"));
Chris Allegrettaff989832001-09-17 13:48:00 +0000446#ifndef NANO_SMALL
Chris Allegrettad55655f2000-12-27 03:36:47 +0000447 printf(_
448 (" -i --autoindent Automatically indent new lines\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000449 printf(_
Chris Allegretta627de192000-07-12 02:09:17 +0000450 (" -k --cut Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000451#endif
Chris Allegretta627de192000-07-12 02:09:17 +0000452 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000453 (" -l --nofollow Don't follow symbolic links, overwrite\n"));
Chris Allegretta84de5522001-04-12 14:51:48 +0000454#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000455#ifdef NCURSES_MOUSE_VERSION
456 printf(_(" -m --mouse Enable mouse\n"));
457#endif
458#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000459#ifndef DISABLE_OPERATINGDIR
Chris Allegrettad55655f2000-12-27 03:36:47 +0000460 printf(_
Chris Allegretta56214c62001-09-27 02:46:53 +0000461 (" -o [dir] --operatingdir=[dir] Set operating directory\n"));
Chris Allegrettae1f14522001-09-19 03:19:43 +0000462#endif
463 printf(_
464 (" -p --pico Emulate Pico as closely as possible\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000465
466#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000467 printf
468 (_
469 (" -r [#cols] --fill=[#cols] Set fill cols to (wrap lines at) #cols\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000470#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000471#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000472 printf(_
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000473 (" -s [prog] --speller=[prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000474#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000475 printf(_
476 (" -t --tempfile Auto save on exit, don't prompt\n"));
477 printf(_
478 (" -v --view View (read only) mode\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000479#ifndef DISABLE_WRAPPING
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000480 printf(_
481 (" -w --nowrap Don't wrap long lines\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000482#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000483 printf(_
484 (" -x --nohelp Don't show help window\n"));
485 printf(_
486 (" -z --suspend Enable suspend\n"));
487 printf(_
488 (" +LINE Start at line number LINE\n"));
489#else
490 printf(_("Usage: nano [option] +LINE <file>\n\n"));
491 printf(_("Option Meaning\n"));
Chris Allegretta7004c282001-09-22 00:42:10 +0000492#ifndef NANO_SMALL
493 printf(_(" -D Write file in DOS format\n"));
494#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000495#ifdef ENABLE_MULTIBUFFER
496 printf(_(" -F Enable multiple file buffers\n"));
497#endif
Jordi Mallach345a8462002-01-07 11:35:16 +0000498 printf(_(" -K Use alternate keypad routines\n"));
Chris Allegretta8fa1e282001-09-22 04:20:25 +0000499#ifndef NANO_SMALL
500 printf(_(" -M Write file in Mac format\n"));
501#endif
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000502 printf(_(" -R Use regular expressions for search\n"));
Chris Allegretta3e3ae942001-09-22 19:02:04 +0000503#ifndef NANO_SMALL
504 printf(_(" -S Smooth scrolling\n"));
505#endif
Chris Allegretta48bd3782002-01-03 21:26:34 +0000506 printf(_(" -T [num] Set width of a tab to num\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000507 printf(_(" -V Print version information and exit\n"));
508 printf(_(" -c Constantly show cursor position\n"));
509 printf(_(" -h Show this message\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000510#ifndef NANO_SMALL
Chris Allegrettaff989832001-09-17 13:48:00 +0000511 printf(_(" -i Automatically indent new lines\n"));
Chris Allegretta627de192000-07-12 02:09:17 +0000512 printf(_(" -k Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000513#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000514 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000515 (" -l Don't follow symbolic links, overwrite\n"));
Chris Allegretta84de5522001-04-12 14:51:48 +0000516#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000517#ifdef NCURSES_MOUSE_VERSION
518 printf(_(" -m Enable mouse\n"));
519#endif
520#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000521#ifndef DISABLE_OPERATINGDIR
522 printf(_(" -o [dir] Set operating directory\n"));
523#endif
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +0000524 printf(_(" -p Emulate Pico as closely as possible\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000525
526#ifndef DISABLE_WRAPJUSTIFY
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000527 printf(_
528 (" -r [#cols] Set fill cols to (wrap lines at) #cols\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000529#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000530#ifndef DISABLE_SPELLER
Chris Allegrettad55655f2000-12-27 03:36:47 +0000531 printf(_(" -s [prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000532#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000533 printf(_(" -t Auto save on exit, don't prompt\n"));
534 printf(_(" -v View (read only) mode\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000535#ifndef DISABLE_WRAPPING
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000536 printf(_(" -w Don't wrap long lines\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000537#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000538 printf(_(" -x Don't show help window\n"));
539 printf(_(" -z Enable suspend\n"));
540 printf(_(" +LINE Start at line number LINE\n"));
541#endif
542 exit(0);
543}
544
545void version(void)
546{
Chris Allegrettac46dd812001-02-14 14:28:27 +0000547 printf(_(" GNU nano version %s (compiled %s, %s)\n"),
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000548 VERSION, __TIME__, __DATE__);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000549 printf(_
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000550 (" Email: nano@nano-editor.org Web: http://www.nano-editor.org"));
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000551 printf(_("\n Compiled options:"));
Chris Allegrettaff269f82000-12-01 18:46:01 +0000552
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000553#ifdef NANO_EXTRA
554 printf(" --enable-extra");
Chris Allegretta355fbe52001-07-14 19:32:47 +0000555#else
556#ifdef ENABLE_MULTIBUFFER
557 printf(" --enable-multibuffer");
558#endif /* ENABLE_MULTIBUFFER */
559#endif /* NANO_EXTRA */
560
Chris Allegrettab881d3e2001-04-18 04:34:43 +0000561#ifdef ENABLE_NANORC
562 printf(" --enable-nanorc");
563#endif
Chris Allegretta8ce24132001-04-30 11:28:46 +0000564#ifdef ENABLE_COLOR
565 printf(" --enable-color");
566#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000567
568#ifdef NANO_SMALL
569 printf(" --enable-tiny");
570#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000571#ifdef DISABLE_BROWSER
Chris Allegretta6636dc32001-01-05 05:41:07 +0000572 printf(" --disable-browser");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000573#endif
574#ifdef DISABLE_TABCOMP
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000575 printf(" --disable-tabcomp");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000576#endif
577#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +0000578 printf(" --disable-justify");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000579#endif
580#ifdef DISABLE_SPELLER
Chris Allegretta7b36c522000-12-06 01:08:10 +0000581 printf(" --disable-speller");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000582#endif
583#ifdef DISABLE_HELP
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000584 printf(" --disable-help");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000585#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000586#ifdef DISABLE_MOUSE
587 printf(" --disable-mouse");
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000588#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000589#ifdef DISABLE_OPERATINGDIR
590 printf(" --disable-operatingdir");
591#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000592#endif /* NANO_SMALL */
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000593
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000594#ifdef DISABLE_WRAPPING
595 printf(" --disable-wrapping");
596#endif
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000597#ifdef USE_SLANG
598 printf(" --with-slang");
599#endif
600 printf("\n");
601
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000602}
603
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000604/* Create a new node. This does NOT initialize the data members used
605 only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000606filestruct *make_new_node(filestruct * prevnode)
607{
608 filestruct *newnode;
609
610 newnode = nmalloc(sizeof(filestruct));
611 newnode->data = NULL;
612
613 newnode->prev = prevnode;
614 newnode->next = NULL;
615
616 if (prevnode != NULL)
617 newnode->lineno = prevnode->lineno + 1;
618
619 return newnode;
620}
621
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000622/* Splice a node into an existing filestruct. This does NOT set the data
623 members used only by open_files. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000624void splice_node(filestruct * begin, filestruct * newnode,
625 filestruct * end)
Chris Allegretta7975ed82000-07-28 00:58:35 +0000626{
Chris Allegrettae3167732001-03-18 16:59:34 +0000627 newnode->next = end;
628 newnode->prev = begin;
629 begin->next = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000630 if (end != NULL)
Chris Allegrettae3167732001-03-18 16:59:34 +0000631 end->prev = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000632}
633
Chris Allegrettae3167732001-03-18 16:59:34 +0000634int do_mark(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000635{
636#ifdef NANO_SMALL
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000637 nano_disabled_msg();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000638#else
639 if (!ISSET(MARK_ISSET)) {
640 statusbar(_("Mark Set"));
641 SET(MARK_ISSET);
642 mark_beginbuf = current;
643 mark_beginx = current_x;
644 } else {
645 statusbar(_("Mark UNset"));
646 UNSET(MARK_ISSET);
647 mark_beginbuf = NULL;
648 mark_beginx = 0;
649
650 edit_refresh();
651 }
652#endif
653 return 1;
654}
655
656int no_help(void)
657{
658 if ISSET
659 (NO_HELP)
660 return 2;
661 else
662 return 0;
663}
664
Chris Allegretta3bc8c722000-12-10 17:03:25 +0000665#if defined(DISABLE_JUSTIFY) || defined(DISABLE_SPELLER) || defined(DISABLE_HELP)
Chris Allegrettaff269f82000-12-01 18:46:01 +0000666void nano_disabled_msg(void)
667{
668 statusbar("Sorry, support for this function has been disabled");
669}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000670#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000671
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000672/* The user typed a printable character; add it to the edit buffer */
673void do_char(char ch)
674{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000675 /* magic-line: when a character is inserted on the current magic line,
676 * it means we need a new one! */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000677 if (filebot == current && current->data[0] == '\0') {
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000678 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000679 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000680 }
681
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000682 /* More dangerousness fun =) */
683 current->data = nrealloc(current->data, strlen(current->data) + 2);
684 memmove(&current->data[current_x + 1],
685 &current->data[current_x],
686 strlen(current->data) - current_x + 1);
687 current->data[current_x] = ch;
688 do_right();
689
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000690#ifndef DISABLE_WRAPPING
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000691 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000692 check_wrap(current, ch);
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000693#endif
694
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000695 set_modified();
696 check_statblank();
697 UNSET(KEEP_CUTBUFFER);
698 totsize++;
699
700}
701
702/* Someone hits return *gasp!* */
703int do_enter(filestruct * inptr)
704{
Chris Allegrettae3167732001-03-18 16:59:34 +0000705 filestruct *newnode;
Chris Allegretta68532c32001-09-17 13:49:33 +0000706 char *tmp;
707#ifndef NANO_SMALL
708 char *spc;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000709 int extra = 0;
Chris Allegretta68532c32001-09-17 13:49:33 +0000710#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000711
Chris Allegrettae3167732001-03-18 16:59:34 +0000712 newnode = make_new_node(inptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000713 tmp = &current->data[current_x];
714 current_x = 0;
715
Chris Allegrettaff989832001-09-17 13:48:00 +0000716#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000717 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
718 if (ISSET(AUTOINDENT)) {
719 spc = current->data;
720 if (spc) {
721 while ((*spc == ' ') || (*spc == '\t')) {
722 extra++;
723 spc++;
724 current_x++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +0000725 totsize++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000726 }
Chris Allegretta88b09152001-05-17 11:35:43 +0000727 newnode->data = charalloc(strlen(tmp) + extra + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000728 strncpy(newnode->data, current->data, extra);
729 strcpy(&newnode->data[extra], tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000730 }
Chris Allegrettaff989832001-09-17 13:48:00 +0000731 } else
732#endif
733 {
Chris Allegretta88b09152001-05-17 11:35:43 +0000734 newnode->data = charalloc(strlen(tmp) + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000735 strcpy(newnode->data, tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000736 }
737 *tmp = 0;
738
Chris Allegrettada721be2000-07-31 01:26:42 +0000739 if (inptr->next == NULL) {
Chris Allegrettae3167732001-03-18 16:59:34 +0000740 filebot = newnode;
741 editbot = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000742 }
Chris Allegrettae3167732001-03-18 16:59:34 +0000743 splice_node(inptr, newnode, inptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000744
745 totsize++;
746 renumber(current);
Chris Allegrettae3167732001-03-18 16:59:34 +0000747 current = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000748 align(&current->data);
749
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000750 /* The logic here is as follows:
751 * -> If we are at the bottom of the buffer, we want to recenter
Chris Allegretta88520c92001-05-05 17:45:54 +0000752 * (read: rebuild) the screen and forcibly move the cursor.
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000753 * -> otherwise, we want simply to redraw the screen and update
754 * where we think the cursor is.
755 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000756 if (current_y == editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +0000757 edit_update(current, CENTER);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000758 reset_cursor();
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000759 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000760 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000761 edit_refresh();
762 update_cursor();
763 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000764
765 totlines++;
766 set_modified();
767
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000768 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000769 return 1;
770}
771
772int do_enter_void(void)
773{
774 return do_enter(current);
775}
776
Chris Allegrettaad3f4782001-10-02 03:54:13 +0000777#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000778void do_next_word(void)
779{
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000780 filestruct *fileptr, *old;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000781 int i;
782
783 if (current == NULL)
784 return;
785
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000786 old = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000787 i = current_x;
788 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
789 if (fileptr == current) {
790 while (isalnum((int) fileptr->data[i])
791 && fileptr->data[i] != 0)
792 i++;
793
794 if (fileptr->data[i] == 0) {
795 i = 0;
796 continue;
797 }
798 }
799 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
800 i++;
801
802 if (fileptr->data[i] != 0)
803 break;
804
805 i = 0;
806 }
807 if (fileptr == NULL)
808 current = filebot;
809 else
810 current = fileptr;
811
812 current_x = i;
813 placewewant = xplustabs();
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000814
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000815 if (current->lineno >= editbot->lineno)
Chris Allegretta234a34d2000-07-29 04:33:38 +0000816 edit_update(current, CENTER);
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000817 else {
818 /* If we've jumped lines, refresh the old line. We can't just use
819 * current->prev here, because we may have skipped over some blank
820 * lines, in which case the previous line is the wrong one.
821 */
822 if (current != old)
823 update_line(old, 0);
824
825 update_line(current, current_x);
826 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000827}
828
829/* the same thing for backwards */
830void do_prev_word(void)
831{
832 filestruct *fileptr, *old;
833 int i;
834
835 if (current == NULL)
836 return;
837
838 old = current;
839 i = current_x;
840 for (fileptr = current; fileptr != NULL; fileptr = fileptr->prev) {
841 if (fileptr == current) {
842 while (isalnum((int) fileptr->data[i])
843 && i != 0)
844 i--;
845
846 if (i == 0) {
847 if (fileptr->prev != NULL)
Chris Allegrettae59fc822001-10-24 18:07:58 +0000848 i = strlen(fileptr->prev->data);
Chris Allegretta878ced32001-10-22 20:05:34 +0000849 else if (fileptr == fileage && filebot != NULL) {
850 current_x = 0;
851 return;
852 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000853 continue;
854 }
855 }
856
857 while (!isalnum((int) fileptr->data[i]) && i != 0)
858 i--;
859
860 if (i > 0) {
861 i--;
862
863 while (isalnum((int) fileptr->data[i]) && i != 0)
864 i--;
865
Chris Allegretta6d0aa9f2001-10-26 15:21:41 +0000866 if (!isalnum((int) fileptr->data[i]))
867 i++;
868
869 if (i != 0 || i != current_x)
Chris Allegretta76e291b2001-10-14 19:05:10 +0000870 break;
871
872 }
873 if (fileptr->prev != NULL)
Chris Allegrettae59fc822001-10-24 18:07:58 +0000874 i = strlen(fileptr->prev->data);
Chris Allegretta878ced32001-10-22 20:05:34 +0000875 else if (fileptr == fileage && filebot != NULL) {
876 current_x = 0;
877 return;
878 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000879 }
880 if (fileptr == NULL)
881 current = fileage;
882 else
883 current = fileptr;
884
885 current_x = i;
886 placewewant = xplustabs();
887
888 if (current->lineno <= edittop->lineno)
889 edit_update(current, CENTER);
890 else {
891 /* If we've jumped lines, refresh the old line. We can't just use
892 * current->prev here, because we may have skipped over some blank
893 * lines, in which case the previous line is the wrong one.
894 */
895 if (current != old)
896 update_line(old, 0);
897
898 update_line(current, current_x);
899 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000900
901}
Chris Allegrettaad3f4782001-10-02 03:54:13 +0000902#endif /* NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000903
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000904#ifndef DISABLE_WRAPPING
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000905void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000906{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000907 int i = 0; /* Index into ->data for line. */
908 int i_tabs = 0; /* Screen position of ->data[i]. */
909 int last_word_end = -1; /* Location of end of last word found. */
910 int current_word_start = -1; /* Location of start of current word. */
911 int current_word_start_t = -1; /* Location of start of current word screen position. */
912 int current_word_end = -1; /* Location of end of current word */
913 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000914 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000915
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000916 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000917 int right = 0;
918 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000919
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000920 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000921
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000922 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000923 if (!isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000924 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000925
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000926 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000927 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000928
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000929 while (!isspace((int) inptr->data[i])
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000930 && inptr->data[i]) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000931 i++;
932 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000933 if (inptr->data[i] < 32)
934 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000935 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000936
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000937 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000938 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000939 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000940 } else {
941 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000942 current_word_end_t = i_tabs - 1;
943 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000944 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000945
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000946 if (inptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000947 if (i_tabs % tabsize != 0);
948 i_tabs += tabsize - (i_tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000949 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000950
Adam Rogoyski09f97962000-06-20 02:50:33 +0000951 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000952 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000953 }
954
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000955 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000956 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000957 * a) one word takes up the whole line with no starting spaces.
958 * - do nothing and return.
959 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000960 * - word starts new line.
961 * - keep white space on original line up to the cursor.
962 * *) cursor is after word at wrap point
963 * - either it's all white space after word, and this routine isn't called.
964 * - or we are actually in case 2 (2 words).
965 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000966 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000967 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000968 * - white space at end of original line is cleared, unless
969 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000970 * b) cursor is at the word at the wrap point.
971 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000972 * - white space on original line is kept to where cursor was.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000973 * c) cursor is past the word at the wrap point.
974 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000975 * - white space at end of original line is cleared
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000976 */
977
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000978 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000979
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000980 /* Category 1a: one word taking up the whole line with no beginning spaces. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000981 if ((last_word_end == -1) && (!isspace((int) inptr->data[0]))) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000982 for (i = current_word_end; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000983 if (!isspace((int) inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000984 current_word_start = i;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000985 while (!isspace((int) inptr->data[i]) && (i < len)) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000986 i++;
987 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000988 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000989 current_word_end = i;
990 break;
991 }
992 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000993
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000994 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000995 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000996 return;
997 }
998 if (current_x >= last_word_end) {
999 right = (current_x - current_word_start) + 1;
1000 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001001 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001002 }
1003
Chris Allegretta2084acc2001-11-29 03:43:08 +00001004 /* Subtract length of original line, plus one for the newline, from
1005 totsize. */
1006 totsize -= (strlen(inptr->data) + 1);
1007
Chris Allegretta88b09152001-05-17 11:35:43 +00001008 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001009 strcpy(temp->data, &inptr->data[current_word_start]);
1010 inptr->data = nrealloc(inptr->data, last_word_end + 2);
1011 inptr->data[last_word_end + 1] = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001012
1013 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1014 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
1015
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001016 } else
1017 /* Category 1b: one word on the line and word not taking up whole line
1018 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001019 if (last_word_end == -1) {
Chris Allegretta88b09152001-05-17 11:35:43 +00001020 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001021 strcpy(temp->data, &inptr->data[current_word_start]);
1022
1023 /* Inside word, remove it from original, and move cursor to right spot. */
1024 if (current_x >= current_word_start) {
1025 right = current_x - current_word_start;
Chris Allegretta56214c62001-09-27 02:46:53 +00001026
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001027 current_x = 0;
Chris Allegrettaff989832001-09-17 13:48:00 +00001028#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001029 if (ISSET(AUTOINDENT)) {
1030 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001031 while ((inptr->next->data[i] == ' '
1032 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001033 i++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001034 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001035 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001036#endif
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001037 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001038 }
1039
Chris Allegretta2084acc2001-11-29 03:43:08 +00001040 /* Subtract length of original line, plus one for the newline, from
1041 totsize. */
1042 totsize -= (strlen(inptr->data) + 1);
1043
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001044 null_at(&inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001045
Chris Allegretta2084acc2001-11-29 03:43:08 +00001046 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1047 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
1048
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001049 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
1050 mark_beginbuf = temp;
1051 mark_beginx = 0;
1052 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001053 }
1054
1055 /* Category 2: two or more words on the line. */
1056 else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001057 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001058 if (current_x < current_word_start) {
1059 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001060 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001061 strcpy(temp->data, &inptr->data[current_word_start]);
1062
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001063 if (!isspace((int) input_char)) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001064 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001065
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001066 while (isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001067 i--;
1068 assert(i >= 0);
1069 }
1070 } else if (current_x <= last_word_end)
1071 i = last_word_end - 1;
1072 else
1073 i = current_x;
1074
Chris Allegretta2084acc2001-11-29 03:43:08 +00001075 /* Subtract length of original line, plus one for the newline, from
1076 totsize. */
1077 totsize -= (strlen(inptr->data) + 1);
1078
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001079 inptr->data = nrealloc(inptr->data, i + 2);
1080 inptr->data[i + 1] = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001081
1082 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1083 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
1084
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001085 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001086
1087
1088 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001089 else if ((current_x >= current_word_start)
1090 && (current_x <= (current_word_end + 1))) {
1091 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001092 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001093 strcpy(temp->data, &inptr->data[current_word_start]);
1094
1095 down = 1;
1096
1097 right = current_x - current_word_start;
Chris Allegrettaff989832001-09-17 13:48:00 +00001098#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001099 if (ISSET(AUTOINDENT)) {
1100 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001101 while ((inptr->next->data[i] == ' '
1102 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001103 i++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001104 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001105 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001106#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001107 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001108 current_x = current_word_start;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001109
Chris Allegretta2084acc2001-11-29 03:43:08 +00001110 /* Subtract length of original line, plus one for the newline, from
1111 totsize. */
1112 totsize -= (strlen(inptr->data) + 1);
1113
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001114 null_at(&inptr->data, current_word_start);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001115
Chris Allegretta2084acc2001-11-29 03:43:08 +00001116 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1117 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001118 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001119
1120
1121 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001122 else {
1123 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001124 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001125 strcpy(temp->data, &inptr->data[current_word_start]);
1126
1127 down = 1;
1128 right = current_x - current_word_start;
1129
1130 current_x = current_word_start;
1131 i = current_word_start - 1;
1132
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001133 while (isspace((int) inptr->data[i])) {
Adam Rogoyski3d449b42000-06-19 17:30:14 +00001134 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001135 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001136 }
Chris Allegretta2084acc2001-11-29 03:43:08 +00001137
1138 /* Subtract length of original line, plus one for the newline, from
1139 totsize. */
1140 totsize -= (strlen(inptr->data) + 1);
1141
1142 inptr->data = nrealloc(inptr->data, i + 2);
1143 inptr->data[i + 1] = 0;
1144
1145 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1146 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001147 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001148 }
1149
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001150 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001151 if (ISSET(SAMELINEWRAP) && inptr->next) {
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001152 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001153
Chris Allegretta94a78b82001-03-14 08:28:48 +00001154 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001155 char *p =
Chris Allegretta88b09152001-05-17 11:35:43 +00001156 charalloc((strlen(temp->data) + strlen(inptr->next->data) + 2));
Chris Allegretta94a78b82001-03-14 08:28:48 +00001157
Chris Allegretta56214c62001-09-27 02:46:53 +00001158 /* We're adding to an existing line instead of creating a new
1159 one; decrement totlines here so that when it gets incremented
1160 below, it won't end up being high by one. */
1161 totlines--;
1162
Chris Allegrettaff989832001-09-17 13:48:00 +00001163#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001164 if (ISSET(AUTOINDENT)) {
1165 int non = 0;
1166
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001167 /* Grab the beginning of the next line until it's not a
1168 space or tab, then null terminate it so we can strcat it
1169 to hell */
1170 while ((inptr->next->data[non] == ' '
Chris Allegretta355fbe52001-07-14 19:32:47 +00001171 || inptr->next->data[non] == '\t')) {
1172 p[non] = inptr->next->data[non];
1173 non++;
1174 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001175 p[non] = 0;
1176 strcat(p, temp->data);
1177 strcat(p, " ");
1178
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001179 /* Now tack on the rest of the next line after the spaces and
1180 tabs */
Chris Allegretta94a78b82001-03-14 08:28:48 +00001181 strcat(p, &inptr->next->data[non]);
Chris Allegrettaff989832001-09-17 13:48:00 +00001182 } else
1183#endif
1184 {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001185 strcpy(p, temp->data);
1186 strcat(p, " ");
1187 strcat(p, inptr->next->data);
1188 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001189
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001190 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001191 inptr->next->data = p;
1192
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001193 free(temp->data);
1194 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001195
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001196 current_x = old_x;
1197 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001198 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001199 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001200 else {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001201
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001202 temp->prev = inptr;
1203 temp->next = inptr->next;
1204
1205 if (inptr->next)
1206 inptr->next->prev = temp;
1207 inptr->next = temp;
1208
1209 if (!temp->next)
1210 filebot = temp;
1211
1212 SET(SAMELINEWRAP);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001213
Chris Allegrettaff989832001-09-17 13:48:00 +00001214#ifndef NANO_SMALL
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001215 if (ISSET(AUTOINDENT)) {
1216 char *spc = inptr->data;
1217 char *t = NULL;
1218 int extra = 0;
1219 if (spc) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001220 while ((*spc == ' ') || (*spc == '\t')) {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001221 extra++;
1222 spc++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001223 totsize++;
Chris Allegretta438f7132002-01-16 00:54:47 +00001224 right++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001225 }
Chris Allegretta88b09152001-05-17 11:35:43 +00001226 t = charalloc(strlen(temp->data) + extra + 1);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001227 strncpy(t, inptr->data, extra);
1228 strcpy(t + extra, temp->data);
1229 free(temp->data);
1230 temp->data = t;
1231 }
1232 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001233#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001234 }
1235
1236
1237 totlines++;
Chris Allegretta88520c92001-05-05 17:45:54 +00001238 /* Everything about it makes me want this line here, but it causes
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001239 * totsize to be high by one for some reason. Sigh. (Rob) */
1240 /* totsize++; */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001241
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001242 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001243 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001244
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001245
1246 /* Move the cursor to the new line if appropriate. */
1247 if (down) {
1248 do_right();
1249 }
1250
1251 /* Move the cursor to the correct spot in the line if appropriate. */
1252 while (right--) {
1253 do_right();
1254 }
1255
Chris Allegretta234a34d2000-07-29 04:33:38 +00001256 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001257 reset_cursor();
1258 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001259}
1260
1261/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001262void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001263{
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001264 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001265#ifdef DEBUG
1266 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
1267 inptr->data);
1268#endif
1269
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001270 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001271 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001272 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001273 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001274
1275 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001276 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001277
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001278 while (isspace((int) inptr->data[i]) && inptr->data[i])
Adam Rogoyski09f97962000-06-20 02:50:33 +00001279 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001280
Adam Rogoyski09f97962000-06-20 02:50:33 +00001281 if (!inptr->data[i])
1282 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001283
Adam Rogoyski09f97962000-06-20 02:50:33 +00001284 /* String must be at least 1 character long. */
1285 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001286 if (isspace((int) inptr->data[i])) {
Adam Rogoyski09f97962000-06-20 02:50:33 +00001287 if (!char_found)
1288 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001289 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001290 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001291 } else
1292 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001293 }
Adam Rogoyski09f97962000-06-20 02:50:33 +00001294
1295 if (char_found == 2)
1296 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001297 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001298}
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001299#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001300
1301/* Stuff we do when we abort from programs and want to clean up the
Chris Allegretta88520c92001-05-05 17:45:54 +00001302 * screen. This doesn't do much right now.
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001303 */
1304void do_early_abort(void)
1305{
1306 blank_statusbar_refresh();
1307}
1308
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001309int do_backspace(void)
1310{
1311 filestruct *previous, *tmp;
1312
1313 if (current_x != 0) {
1314 /* Let's get dangerous */
1315 memmove(&current->data[current_x - 1], &current->data[current_x],
1316 strlen(current->data) - current_x + 1);
1317#ifdef DEBUG
1318 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
1319#endif
1320 align(&current->data);
1321 do_left();
1322 } else {
1323 if (current == fileage)
1324 return 0; /* Can't delete past top of file */
1325
1326 previous = current->prev;
1327 current_x = strlen(previous->data);
1328 previous->data = nrealloc(previous->data,
1329 strlen(previous->data) +
1330 strlen(current->data) + 1);
1331 strcat(previous->data, current->data);
1332
1333 tmp = current;
1334 unlink_node(current);
1335 delete_node(current);
1336 if (current == edittop) {
1337 if (previous->next)
1338 current = previous->next;
1339 else
1340 current = previous;
Chris Allegretta3e3ae942001-09-22 19:02:04 +00001341 page_up();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001342 } else {
1343 if (previous->next)
1344 current = previous->next;
1345 else
1346 current = previous;
1347 update_line(current, current_x);
1348 }
1349
1350 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001351 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001352 filebot = current;
1353 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001354
1355 /* Recreate the magic line if we're deleting it AND if the
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001356 line we're on now is NOT blank. if it is blank we
1357 can just use IT for the magic line. This is how Pico
1358 appears to do it, in any case */
Chris Allegretta28a0f892000-07-05 22:47:54 +00001359 if (strcmp(current->data, "")) {
1360 new_magicline();
1361 fix_editbot();
1362 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001363 }
1364
1365 current = previous;
1366 renumber(current);
1367 previous_line();
1368 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001369#ifdef DEBUG
1370 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
1371#endif
1372
1373 }
1374
1375 totsize--;
1376 set_modified();
1377 UNSET(KEEP_CUTBUFFER);
1378 edit_refresh();
1379 return 1;
1380}
1381
1382int do_delete(void)
1383{
1384 filestruct *foo;
1385
Chris Allegretta2084acc2001-11-29 03:43:08 +00001386 /* blbf -> blank line before filebot (see below) */
1387 int blbf = 0;
1388
1389 if (current->next == filebot && !strcmp(current->data, ""))
1390 blbf = 1;
1391
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001392 if (current_x != strlen(current->data)) {
1393 /* Let's get dangerous */
1394 memmove(&current->data[current_x], &current->data[current_x + 1],
1395 strlen(current->data) - current_x);
1396
1397 align(&current->data);
1398
Chris Allegretta2084acc2001-11-29 03:43:08 +00001399 /* Now that we have a magic line again, we can check for both being
1400 on the line before filebot as well as at filebot; it's a special
1401 case if we're on the line before filebot and it's blank, since we
1402 should be able to delete it */
1403 } else if (current->next != NULL && (current->next != filebot || blbf)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001404 current->data = nrealloc(current->data,
1405 strlen(current->data) +
1406 strlen(current->next->data) + 1);
1407 strcat(current->data, current->next->data);
1408
1409 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001410 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001411 filebot = current;
1412 editbot = current;
1413 }
1414
1415 unlink_node(foo);
1416 delete_node(foo);
1417 update_line(current, current_x);
1418
Chris Allegretta4ed13152001-02-10 17:50:50 +00001419 /* Please see the comment in do_backspace if you don't understand
Chris Allegretta28a0f892000-07-05 22:47:54 +00001420 this test */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001421 if (current == filebot && strcmp(current->data, "")) {
Chris Allegretta28a0f892000-07-05 22:47:54 +00001422 new_magicline();
1423 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001424 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001425 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001426 renumber(current);
1427 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001428 } else
1429 return 0;
1430
1431 totsize--;
1432 set_modified();
1433 UNSET(KEEP_CUTBUFFER);
1434 edit_refresh();
1435 return 1;
1436}
1437
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001438void wrap_reset(void)
1439{
1440 UNSET(SAMELINEWRAP);
1441}
1442
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001443#ifndef DISABLE_SPELLER
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001444
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001445int do_int_spell_fix(char *word)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001446{
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001447 char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001448 filestruct *begin;
1449 int i = 0, j = 0, beginx, beginx_top;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001450
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001451 /* save where we are */
1452 begin = current;
1453 beginx = current_x + 1;
1454
1455 /* save the current search/replace strings */
1456 search_init_globals();
1457 save_search = mallocstrcpy(save_search, last_search);
1458 save_replace = mallocstrcpy(save_replace, last_replace);
1459
1460 /* set search/replace strings to mis-spelt word */
1461 prevanswer = mallocstrcpy(prevanswer, word);
1462 last_search = mallocstrcpy(last_search, word);
1463 last_replace = mallocstrcpy(last_replace, word);
1464
1465 /* start from the top of file */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001466 current = fileage;
1467 current_x = beginx_top = -1;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001468
1469 search_last_line = FALSE;
1470
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001471 edit_update(fileage, TOP);
1472
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001473 while (1) {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001474
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001475 /* make sure word is still mis-spelt (i.e. when multi-errors) */
1476 if (findnextstr(TRUE, FALSE, fileage, beginx_top, prevanswer) != NULL) {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001477
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001478 /* find wholewords only */
1479 if (!is_whole_word(current_x, current, prevanswer))
1480 continue;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001481
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001482 do_replace_highlight(TRUE, prevanswer);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001483
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001484 /* allow replace word to be corrected */
1485 i = statusq(0, spell_list, SPELL_LIST_LEN, last_replace,
1486 _("Edit a replacement"));
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001487
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001488 do_replace_highlight(FALSE, prevanswer);
1489
1490 /* start from the start of this line again */
1491 current = fileage;
1492 current_x = beginx_top;
1493
1494 search_last_line = FALSE;
1495
1496 if (strcmp(prevanswer,answer) != 0) {
1497 j = i;
1498 do_replace_loop(prevanswer, fileage, &beginx_top, TRUE, &j);
1499 }
Chris Allegretta80838272001-12-02 06:03:22 +00001500 }
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001501
1502 break;
Rocco Corsi562964d2002-01-13 03:18:03 +00001503 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001504
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001505 /* restore the search/replace strings */
1506 last_search = mallocstrcpy(last_search, save_search);
1507 last_replace = mallocstrcpy(last_replace, save_replace);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001508
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001509 /* restore where we were */
1510 current = begin;
1511 current_x = beginx - 1;
1512
1513 edit_update(current, CENTER);
1514
1515 if (i == -1)
1516 return FALSE;
1517
1518 return TRUE;
1519}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001520
1521/* Integrated spell checking using 'spell' program */
Chris Allegretta271e9722000-11-10 18:15:43 +00001522int do_int_speller(char *tempfile_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001523{
Chris Allegretta271e9722000-11-10 18:15:43 +00001524 char *read_buff, *read_buff_ptr, *read_buff_word;
1525 long pipe_buff_size;
1526 int in_fd[2], tempfile_fd;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001527 int spell_status;
1528 pid_t pid_spell;
1529 ssize_t bytesread;
1530
Chris Allegretta271e9722000-11-10 18:15:43 +00001531 /* Create a pipe to spell program */
1532
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001533 if (pipe(in_fd) == -1)
1534 return FALSE;
1535
Chris Allegretta271e9722000-11-10 18:15:43 +00001536 /* A new process to run spell in */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001537
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001538 if ((pid_spell = fork()) == 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001539
1540 /* Child continues, (i.e. future spell process) */
1541
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001542 close(in_fd[0]);
1543
Chris Allegretta271e9722000-11-10 18:15:43 +00001544 /* replace the standard in with the tempfile */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001545
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001546 if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001547
1548 close(in_fd[1]);
1549 exit(1);
1550 }
1551
1552 if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
1553
1554 close(tempfile_fd);
1555 close(in_fd[1]);
1556 exit(1);
1557 }
1558 close(tempfile_fd);
1559
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001560
Chris Allegretta271e9722000-11-10 18:15:43 +00001561 /* send spell's standard out to the pipe */
1562
1563 if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1564
1565 close(in_fd[1]);
1566 exit(1);
1567 }
1568 close(in_fd[1]);
1569
1570 /* Start spell program, we are using the PATH here!?!? */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001571 execlp("spell", "spell", NULL);
1572
Chris Allegretta271e9722000-11-10 18:15:43 +00001573 /* Should not be reached, if spell is found!!! */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001574
Chris Allegretta271e9722000-11-10 18:15:43 +00001575 exit(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001576 }
1577
1578 /* Parent continues here */
1579
Chris Allegretta271e9722000-11-10 18:15:43 +00001580 close(in_fd[1]);
1581
1582 /* Child process was not forked successfully */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001583
1584 if (pid_spell < 0) {
1585
Chris Allegretta271e9722000-11-10 18:15:43 +00001586 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001587 return FALSE;
1588 }
1589
Chris Allegretta271e9722000-11-10 18:15:43 +00001590 /* Get system pipe buffer size */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001591
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001592 if ((pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001593
Chris Allegretta271e9722000-11-10 18:15:43 +00001594 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001595 return FALSE;
Chris Allegretta271e9722000-11-10 18:15:43 +00001596 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001597
Chris Allegretta88b09152001-05-17 11:35:43 +00001598 read_buff = charalloc(pipe_buff_size + 1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001599
Chris Allegretta271e9722000-11-10 18:15:43 +00001600 /* Process the returned spelling errors */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001601
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001602 while ((bytesread = read(in_fd[0], read_buff, pipe_buff_size)) > 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001603
Chris Allegretta271e9722000-11-10 18:15:43 +00001604 read_buff[bytesread] = (char) NULL;
1605 read_buff_word = read_buff_ptr = read_buff;
1606
1607 while (*read_buff_ptr != (char) NULL) {
1608
1609 /* Windows version may need to process additional char '\r' */
1610
1611 /* Possible problem here if last word not followed by '\n' */
1612
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001613 if (*read_buff_ptr == '\n') {
Chris Allegretta271e9722000-11-10 18:15:43 +00001614 *read_buff_ptr = (char) NULL;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001615 if (!do_int_spell_fix(read_buff_word)) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001616
1617 close(in_fd[0]);
1618 free(read_buff);
1619 replace_abort();
1620
1621 return TRUE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001622 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001623 read_buff_word = read_buff_ptr;
1624 read_buff_word++;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001625 }
1626
1627 read_buff_ptr++;
1628 }
1629 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001630
1631 close(in_fd[0]);
1632 free(read_buff);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001633 replace_abort();
1634
Chris Allegretta271e9722000-11-10 18:15:43 +00001635 /* Process end of spell process */
1636
1637 wait(&spell_status);
1638 if (WIFEXITED(spell_status)) {
1639 if (WEXITSTATUS(spell_status) != 0)
1640 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001641 } else
Chris Allegretta271e9722000-11-10 18:15:43 +00001642 return FALSE;
1643
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001644 return TRUE;
1645}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001646
1647/* External spell checking */
Chris Allegretta271e9722000-11-10 18:15:43 +00001648int do_alt_speller(char *file_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001649{
Chris Allegrettab3655b42001-10-22 03:15:31 +00001650 int alt_spell_status, lineno_cur = current->lineno;
1651 int x_cur = current_x, y_cur = current_y, pww_cur = placewewant;
1652
Chris Allegretta271e9722000-11-10 18:15:43 +00001653 pid_t pid_spell;
Chris Allegretta169ee842001-01-26 01:57:32 +00001654 char *ptr;
1655 static int arglen = 3;
1656 static char **spellargs = (char **) NULL;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001657
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001658 endwin();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001659
Chris Allegrettae434b452001-01-27 19:25:00 +00001660 /* Set up an argument list to pass the execvp function */
1661 if (spellargs == NULL) {
1662 spellargs = nmalloc(arglen * sizeof(char *));
Chris Allegretta271e9722000-11-10 18:15:43 +00001663
Chris Allegrettae434b452001-01-27 19:25:00 +00001664 spellargs[0] = strtok(alt_speller, " ");
1665 while ((ptr = strtok(NULL, " ")) != NULL) {
1666 arglen++;
1667 spellargs = nrealloc(spellargs, arglen * sizeof(char *));
1668 spellargs[arglen - 3] = ptr;
Chris Allegretta169ee842001-01-26 01:57:32 +00001669 }
Chris Allegrettae434b452001-01-27 19:25:00 +00001670 spellargs[arglen - 1] = NULL;
1671 }
1672 spellargs[arglen - 2] = file_name;
1673
1674 /* Start a new process for the alternate speller */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001675 if ((pid_spell = fork()) == 0) {
Chris Allegretta169ee842001-01-26 01:57:32 +00001676
Chris Allegretta88520c92001-05-05 17:45:54 +00001677 /* Start alternate spell program; we are using the PATH here!?!? */
Chris Allegretta169ee842001-01-26 01:57:32 +00001678 execvp(spellargs[0], spellargs);
Chris Allegretta271e9722000-11-10 18:15:43 +00001679
1680 /* Should not be reached, if alternate speller is found!!! */
1681
1682 exit(1);
1683 }
1684
1685 /* Could not fork?? */
1686
1687 if (pid_spell < 0)
1688 return FALSE;
1689
1690 /* Wait for alternate speller to complete */
1691
1692 wait(&alt_spell_status);
1693 if (WIFEXITED(alt_spell_status)) {
1694 if (WEXITSTATUS(alt_spell_status) != 0)
1695 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001696 } else
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001697 return FALSE;
1698
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001699 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001700 free_filestruct(fileage);
Chris Allegretta56214c62001-09-27 02:46:53 +00001701 global_init(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001702 open_file(file_name, 0, 1);
Rocco Corsi4dfaf932001-04-20 01:59:55 +00001703
Chris Allegretta1b3381b2001-09-28 21:59:01 +00001704 /* go back to the old position, mark the file as modified, and make
1705 sure that the titlebar is refreshed */
1706 do_gotopos(lineno_cur, x_cur, y_cur, pww_cur);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001707 set_modified();
Chris Allegrettae1f14522001-09-19 03:19:43 +00001708 clearok(topwin, FALSE);
1709 titlebar(NULL);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001710
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001711 return TRUE;
1712}
1713#endif
1714
1715int do_spell(void)
1716{
1717
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001718#ifdef DISABLE_SPELLER
Chris Allegrettaff269f82000-12-01 18:46:01 +00001719 nano_disabled_msg();
1720 return (TRUE);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001721#else
Chris Allegretta271e9722000-11-10 18:15:43 +00001722 char *temp;
1723 int spell_res;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001724
Chris Allegretta271e9722000-11-10 18:15:43 +00001725 if ((temp = tempnam(0, "nano.")) == NULL) {
1726 statusbar(_("Could not create a temporary filename: %s"),
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001727 strerror(errno));
Chris Allegretta271e9722000-11-10 18:15:43 +00001728 return 0;
1729 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001730
Chris Allegrettaecc3d7f2001-06-05 23:24:55 +00001731 if (write_file(temp, 1, 0, 0) == -1) {
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001732 statusbar(_("Spell checking failed: unable to write temp file!"));
Chris Allegretta271e9722000-11-10 18:15:43 +00001733 return 0;
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001734 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001735
Chris Allegrettae1f14522001-09-19 03:19:43 +00001736#ifdef ENABLE_MULTIBUFFER
1737 /* update the current open_files entry before spell-checking, in case
1738 any problems occur; the case of there being no open_files entries
1739 is handled elsewhere (before we reach this point); no duplicate
1740 checking is needed here */
1741 add_open_file(1, 0);
1742#endif
1743
Chris Allegretta271e9722000-11-10 18:15:43 +00001744 if (alt_speller)
1745 spell_res = do_alt_speller(temp);
1746 else
1747 spell_res = do_int_speller(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001748
Chris Allegretta271e9722000-11-10 18:15:43 +00001749 remove(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001750
1751 if (spell_res)
1752 statusbar(_("Finished checking spelling"));
1753 else
1754 statusbar(_("Spell checking failed"));
1755
1756 return spell_res;
1757
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001758#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001759}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001760
1761int do_exit(void)
1762{
1763 int i;
1764
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001765 if (!ISSET(MODIFIED)) {
1766
Chris Allegretta355fbe52001-07-14 19:32:47 +00001767#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001768 if (!close_open_file()) {
1769 display_main_list();
1770 return 1;
1771 }
1772 else
1773#endif
1774
1775 finish(0);
1776 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001777
Chris Allegretta30885552000-07-14 01:20:12 +00001778 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001779 i = 1;
1780 } else {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001781 i = do_yesno(0, 0,
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001782 _
1783 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1784 }
1785
1786#ifdef DEBUG
1787 dump_buffer(fileage);
1788#endif
1789
1790 if (i == 1) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001791 if (do_writeout(filename, 1, 0) > 0) {
1792
Chris Allegretta355fbe52001-07-14 19:32:47 +00001793#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001794 if (!close_open_file()) {
1795 display_main_list();
1796 return 1;
1797 }
1798 else
1799#endif
1800
1801 finish(0);
1802 }
1803 } else if (i == 0) {
1804
Chris Allegretta355fbe52001-07-14 19:32:47 +00001805#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001806 if (!close_open_file()) {
1807 display_main_list();
1808 return 1;
1809 }
1810 else
1811#endif
1812
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001813 finish(0);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001814 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001815 statusbar(_("Cancelled"));
1816
1817 display_main_list();
1818 return 1;
1819}
1820
Chris Allegretta84de5522001-04-12 14:51:48 +00001821#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001822#ifdef NCURSES_MOUSE_VERSION
1823void do_mouse(void)
1824{
1825 MEVENT mevent;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001826 int foo = 0, tab_found = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001827
1828 if (getmouse(&mevent) == ERR)
1829 return;
1830
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001831 /* If mouse not in edit or bottom window, return */
1832 if (wenclose(edit, mevent.y, mevent.x)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001833
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001834 /* Don't let people screw with the marker when they're in a
1835 subfunction */
1836 if (currshortcut != main_list)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001837 return;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001838
1839 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1840 mevent.y -= 2;
1841
1842 /* Selecting where the cursor is sets the mark.
1843 * Selecting beyond the line length with the cursor at the end of the
1844 * line sets the mark as well.
1845 */
1846 if ((mevent.y == current_y) &&
1847 ((mevent.x == current_x) || (current_x == strlen(current->data)
1848 && (mevent.x >
1849 strlen(current->data))))) {
1850 if (ISSET(VIEW_MODE)) {
1851 print_view_warning();
1852 return;
1853 }
1854 do_mark();
1855 } else if (mevent.y > current_y) {
1856 while (mevent.y > current_y) {
1857 if (current->next != NULL)
1858 current = current->next;
1859 else
1860 break;
1861 current_y++;
1862 }
1863 } else if (mevent.y < current_y) {
1864 while (mevent.y < current_y) {
1865 if (current->prev != NULL)
1866 current = current->prev;
1867 else
1868 break;
1869 current_y--;
1870 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001871 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001872 current_x = mevent.x;
1873 placewewant = current_x;
1874 while (foo < current_x) {
1875 if (current->data[foo] == NANO_CONTROL_I) {
1876 current_x -= tabsize - (foo % tabsize);
1877 tab_found = 1;
1878 } else if (current->data[foo] & 0x80);
1879 else if (current->data[foo] < 32)
1880 current_x--;
1881 foo++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001882 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001883 /* This is where tab_found comes in. I can't figure out why,
1884 * but without it any line with a tab will place the cursor
1885 * one character behind. Whatever, this fixes it. */
1886 if (tab_found == 1)
1887 current_x++;
1888
1889 if (current_x > strlen(current->data))
1890 current_x = strlen(current->data);
1891
1892 update_cursor();
1893 edit_refresh();
1894 } else if (wenclose(bottomwin, mevent.y, mevent.x) && !ISSET(NO_HELP)) {
Chris Allegrettaa951f212001-09-27 21:07:39 +00001895
1896 int k, val = 0;
1897
1898 if (currslen < 2)
1899 k = COLS / 6;
1900 else
1901 k = COLS / ((currslen + (currslen %2)) / 2);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001902
1903 /* Determine what shortcut list was clicked */
1904 mevent.y -= (editwinrows + 3);
1905
1906 if (mevent.y < 0) /* They clicked on the statusbar */
1907 return;
1908
1909 /* Don't select stuff beyond list length */
1910 if (mevent.x / k >= currslen)
1911 return;
1912
1913 val = currshortcut[(mevent.x / k) * 2 + mevent.y].val;
1914
1915 /* And ungetch that value */
1916 ungetch(val);
Chris Allegretta6414b402001-09-21 03:21:11 +00001917
1918 /* And if it's an alt-key sequence, we should probably send alt
1919 too ;-) */
1920 if (val >= 'a' && val <= 'z')
1921 ungetch(27);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001922 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001923}
1924#endif
1925#endif
1926
1927/* Handler for SIGHUP */
1928RETSIGTYPE handle_hup(int signal)
1929{
Chris Allegrettae7a58932000-12-02 02:36:22 +00001930 die(_("Received SIGHUP"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001931}
1932
Chris Allegretta18f8be02000-09-04 03:20:38 +00001933/* What do we do when we catch the suspend signal */
1934RETSIGTYPE do_suspend(int signal)
1935{
Chris Allegretta18f8be02000-09-04 03:20:38 +00001936 endwin();
Chris Allegretta521e00d2001-06-28 16:52:52 +00001937 printf("\n\n\n\n\nUse \"fg\" to return to nano\n");
1938 fflush(stdout);
1939
Chris Allegretta7b0667f2002-01-10 12:44:21 +00001940 /* Restore the terminal settings for the disabled keys */
1941 tcsetattr(0, TCSANOW, &oldterm);
1942
Chris Allegretta521e00d2001-06-28 16:52:52 +00001943 /* We used to re-enable the default SIG_DFL and raise SIGTSTP, but
1944 then we could be (and were) interrupted in the middle of the call.
1945 So we do it the mutt way instead */
1946 kill(0, SIGSTOP);
Chris Allegretta18f8be02000-09-04 03:20:38 +00001947}
1948
1949/* Restore the suspend handler when we come back into the prog */
1950RETSIGTYPE do_cont(int signal)
1951{
1952
Chris Allegretta521e00d2001-06-28 16:52:52 +00001953 /* Now we just update the screen instead of having to reenable the
1954 SIGTSTP handler */
1955
Chris Allegretta521e00d2001-06-28 16:52:52 +00001956 doupdate();
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00001957 /* The Hurd seems to need this, otherwise a ^Y after a ^Z will
1958 start suspending again */
1959 signal_init();
Chris Allegretta18f8be02000-09-04 03:20:38 +00001960}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001961
1962void handle_sigwinch(int s)
1963{
1964#ifndef NANO_SMALL
1965 char *tty = NULL;
1966 int fd = 0;
1967 int result = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001968 struct winsize win;
1969
1970 tty = ttyname(0);
1971 if (!tty)
1972 return;
1973 fd = open(tty, O_RDWR);
1974 if (fd == -1)
1975 return;
1976 result = ioctl(fd, TIOCGWINSZ, &win);
1977 if (result == -1)
1978 return;
1979
1980
1981 COLS = win.ws_col;
1982 LINES = win.ws_row;
1983
Chris Allegrettae61e8302001-01-14 05:18:27 +00001984 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1985 die_too_small();
1986
Chris Allegretta6fe61492001-05-21 12:56:25 +00001987#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettae61e8302001-01-14 05:18:27 +00001988 if ((fill = COLS - CHARS_FROM_EOL) < MIN_FILL_LENGTH)
1989 die_too_small();
Chris Allegretta6fe61492001-05-21 12:56:25 +00001990#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001991
Chris Allegretta0a06e072001-01-23 02:35:04 +00001992 hblank = nrealloc(hblank, COLS + 1);
1993 memset(hblank, ' ', COLS);
1994 hblank[COLS] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001995
Chris Allegretta618f5d72001-02-16 04:48:30 +00001996#ifdef HAVE_RESIZETERM
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001997 resizeterm(LINES, COLS);
1998#ifdef HAVE_WRESIZE
1999 if (wresize(topwin, 2, COLS) == ERR)
2000 die(_("Cannot resize top win"));
2001 if (mvwin(topwin, 0, 0) == ERR)
2002 die(_("Cannot move top win"));
2003 if (wresize(edit, editwinrows, COLS) == ERR)
2004 die(_("Cannot resize edit win"));
2005 if (mvwin(edit, 2, 0) == ERR)
2006 die(_("Cannot move edit win"));
2007 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
2008 die(_("Cannot resize bottom win"));
2009 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
2010 die(_("Cannot move bottom win"));
2011#endif /* HAVE_WRESIZE */
Chris Allegretta618f5d72001-02-16 04:48:30 +00002012#endif /* HAVE_RESIZETERM */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002013
Robert Siemborskidd53ec22000-07-04 02:35:19 +00002014 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002015
Chris Allegrettabceb1b22000-06-19 04:22:15 +00002016 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00002017 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002018 }
2019 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00002020
2021 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002022 refresh();
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002023 titlebar(NULL);
Chris Allegretta97accc62000-06-19 05:45:52 +00002024 edit_refresh();
2025 display_main_list();
Chris Allegretta08020882001-01-29 23:37:54 +00002026 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002027 total_refresh();
Chris Allegretta08020882001-01-29 23:37:54 +00002028
Chris Allegretta4e90c402001-01-29 23:40:43 +00002029 /* Turn cursor back on for sure */
2030 curs_set(1);
2031
Chris Allegretta08020882001-01-29 23:37:54 +00002032 /* Jump back to mainloop */
2033 siglongjmp(jmpbuf, 1);
2034
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002035#endif
2036}
2037
Chris Allegretta756f2202000-09-01 13:32:47 +00002038void signal_init(void)
2039{
Chris Allegrettaac899e52001-06-30 04:09:09 +00002040#ifdef _POSIX_VDISABLE
2041 struct termios term;
2042#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002043
Chris Allegretta88520c92001-05-05 17:45:54 +00002044 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
Chris Allegretta756f2202000-09-01 13:32:47 +00002045 memset(&act, 0, sizeof(struct sigaction));
2046 act.sa_handler = SIG_IGN;
2047 sigaction(SIGINT, &act, NULL);
Chris Allegretta756f2202000-09-01 13:32:47 +00002048
Chris Allegretta88520c92001-05-05 17:45:54 +00002049 /* Trap SIGHUP cuz we want to write the file out. */
Chris Allegretta756f2202000-09-01 13:32:47 +00002050 act.sa_handler = handle_hup;
2051 sigaction(SIGHUP, &act, NULL);
2052
2053 act.sa_handler = handle_sigwinch;
2054 sigaction(SIGWINCH, &act, NULL);
2055
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002056
2057#ifdef _POSIX_VDISABLE
2058 tcgetattr(0, &term);
2059
2060#ifdef VDSUSP
2061 term.c_cc[VDSUSP] = _POSIX_VDISABLE;
2062#endif /* VDSUSP */
2063
2064#endif /* _POSIX_VDISABLE */
2065
Chris Allegretta521e00d2001-06-28 16:52:52 +00002066 if (!ISSET(SUSPEND)) {
Chris Allegrettaac899e52001-06-30 04:09:09 +00002067
2068/* Insane! */
2069#ifdef _POSIX_VDISABLE
Chris Allegrettaac899e52001-06-30 04:09:09 +00002070 term.c_cc[VSUSP] = _POSIX_VDISABLE;
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002071#else
Chris Allegrettaac899e52001-06-30 04:09:09 +00002072 act.sa_handler = SIG_IGN;
Chris Allegretta521e00d2001-06-28 16:52:52 +00002073 sigaction(SIGTSTP, &act, NULL);
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002074#endif
Chris Allegrettaac899e52001-06-30 04:09:09 +00002075
Chris Allegretta521e00d2001-06-28 16:52:52 +00002076 } else {
2077 /* if we don't do this, it seems other stuff interrupts the
2078 suspend handler! Try using nano with mutt without this line */
2079 sigfillset(&act.sa_mask);
2080
2081 act.sa_handler = do_suspend;
2082 sigaction(SIGTSTP, &act, NULL);
2083
2084 act.sa_handler = do_cont;
2085 sigaction(SIGCONT, &act, NULL);
2086 }
2087
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002088
2089#ifdef _POSIX_VDISABLE
2090 tcsetattr(0, TCSANOW, &term);
2091#endif
2092
2093
Chris Allegretta756f2202000-09-01 13:32:47 +00002094}
2095
Chris Allegretta2a42af12000-09-12 23:02:49 +00002096void window_init(void)
2097{
Chris Allegrettae61e8302001-01-14 05:18:27 +00002098 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
2099 die_too_small();
Chris Allegretta92c9dd22000-09-13 14:03:27 +00002100
Chris Allegretta88520c92001-05-05 17:45:54 +00002101 /* Set up the main text window */
Chris Allegretta2a42af12000-09-12 23:02:49 +00002102 edit = newwin(editwinrows, COLS, 2, 0);
2103
2104 /* And the other windows */
2105 topwin = newwin(2, COLS, 0, 0);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002106 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002107
Chris Allegretta155d6202001-01-08 01:50:37 +00002108#ifdef PDCURSES
2109 /* Oops, I guess we need this again.
2110 Moved here so the keypad still works after a Meta-X, for example */
2111 keypad(edit, TRUE);
2112 keypad(bottomwin, TRUE);
2113#endif
2114
Chris Allegretta2a42af12000-09-12 23:02:49 +00002115}
2116
Chris Allegretta756f2202000-09-01 13:32:47 +00002117void mouse_init(void)
2118{
Chris Allegretta84de5522001-04-12 14:51:48 +00002119#ifndef DISABLE_MOUSE
Chris Allegretta756f2202000-09-01 13:32:47 +00002120#ifdef NCURSES_MOUSE_VERSION
2121 if (ISSET(USE_MOUSE)) {
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002122 keypad_on(edit, 1);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002123 keypad_on(bottomwin, 1);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002124
Chris Allegretta756f2202000-09-01 13:32:47 +00002125 mousemask(BUTTON1_RELEASED, NULL);
2126 mouseinterval(50);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00002127
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002128 } else
Chris Allegretta756f2202000-09-01 13:32:47 +00002129 mousemask(0, NULL);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002130
Chris Allegretta756f2202000-09-01 13:32:47 +00002131#endif
2132#endif
2133
2134}
2135
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002136int do_tab(void)
2137{
2138 do_char('\t');
2139 return 1;
2140}
2141
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002142#ifndef DISABLE_JUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002143int empty_line(const char *data)
2144{
2145 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002146 if (!isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002147 return 0;
2148
2149 data++;
2150 }
2151
2152 return 1;
2153}
2154
2155int no_spaces(const char *data)
2156{
2157 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002158 if (isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002159 return 0;
2160
2161 data++;
2162 }
2163
2164 return 1;
2165}
2166
2167void justify_format(char *data)
2168{
2169 int i = 0;
2170 int len = strlen(data);
2171
2172 /* Skip first character regardless and leading whitespace. */
2173 for (i = 1; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002174 if (!isspace((int) data[i]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002175 break;
2176 }
2177
2178 i++; /* (i) is now at least 2. */
2179
2180 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
2181 for (; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002182 if (isspace((int) data[i]) && isspace((int) data[i - 1])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002183 && (data[i - 2] != '.')) {
2184 memmove(data + i, data + i + 1, len - i);
2185 len--;
2186 i--;
2187 }
2188 }
2189}
2190#endif
2191
2192int do_justify(void)
2193{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002194#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +00002195 nano_disabled_msg();
2196 return 1;
2197#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002198 int slen = 0; /* length of combined lines on one line. */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002199 int initial_y, kbinput = 0, totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002200 filestruct *initial = NULL, *tmpjust = NULL, *cutbak, *tmptop, *tmpbot;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002201
2202 if (empty_line(current->data)) {
2203 /* Justify starting at first non-empty line. */
2204 do {
2205 if (!current->next)
2206 return 1;
2207
2208 current = current->next;
2209 current_y++;
2210 }
2211 while (empty_line(current->data));
2212 } else {
2213 /* Search back for the beginning of the paragraph, where
2214 * Paragraph is 1) A line with leading whitespace
2215 * or 2) A line following an empty line.
2216 */
2217 while (current->prev != NULL) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002218 if (isspace((int) current->data[0]) || !current->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002219 break;
2220
2221 current = current->prev;
2222 current_y--;
2223 }
2224
2225 /* First line with leading whitespace may be empty. */
2226 if (empty_line(current->data)) {
2227 if (current->next) {
2228 current = current->next;
2229 current_y++;
2230 } else
2231 return 1;
2232 }
2233 }
2234 initial = current;
2235 initial_y = current_y;
2236
2237 set_modified();
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002238 cutbak = cutbuffer; /* Got to like cutbak ;) */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002239 totbak = totsize;
Chris Allegretta9149e612000-11-27 00:23:41 +00002240 cutbuffer = NULL;
2241
2242 tmptop = current;
2243 tmpjust = copy_node(current);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002244
2245 /* This is annoying because it mucks with totsize */
Chris Allegretta9149e612000-11-27 00:23:41 +00002246 add_to_cutbuffer(tmpjust);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002247
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002248 /* Put the whole paragraph into one big line. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002249 while (current->next && !isspace((int) current->next->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002250 && current->next->data[0]) {
2251 filestruct *tmpnode = current->next;
2252 int len = strlen(current->data);
2253 int len2 = strlen(current->next->data);
2254
Chris Allegretta9149e612000-11-27 00:23:41 +00002255 tmpjust = NULL;
Chris Allegretta9149e612000-11-27 00:23:41 +00002256 tmpjust = copy_node(current->next);
2257 add_to_cutbuffer(tmpjust);
2258
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002259 /* Wiping out a newline */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002260 totsize--;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002261
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002262 /* length of both strings plus space between strings and ending \0. */
2263 current->data = nrealloc(current->data, len + len2 + 2);
2264 current->data[len++] = ' ';
2265 current->data[len] = '\0';
2266
2267 strncat(current->data, current->next->data, len2);
2268
2269 unlink_node(tmpnode);
2270 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002271 }
2272
2273 justify_format(current->data);
2274
2275 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002276 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002277
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002278 if ((strlenpt(current->data) > (fill))
2279 && !no_spaces(current->data)) {
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002280 do {
2281 int i = 0;
2282 int len2 = 0;
2283 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002284
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002285 /* Start at fill , unless line isn't that long (but it
2286 * appears at least fill long with tabs.
2287 */
2288 if (slen > fill)
2289 i = fill;
2290 else
2291 i = slen;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002292
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002293 for (; i > 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002294 if (isspace((int) current->data[i]) &&
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002295 ((strlenpt(current->data) - strlen(current->data + i))
2296 <= fill))
2297 break;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002298 }
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002299
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002300 if (!i)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002301 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002302
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002303 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002304
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002305 len2 = strlen(current->data + i + 1);
Chris Allegretta88b09152001-05-17 11:35:43 +00002306 tmpline->data = charalloc(len2 + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002307
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002308 /* Skip the white space in current. */
2309 memcpy(tmpline->data, current->data + i + 1, len2);
2310 tmpline->data[len2] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002311
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002312 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002313
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002314 tmpline->prev = current;
2315 tmpline->next = current->next;
2316 if (current->next != NULL)
2317 current->next->prev = tmpline;
2318
2319 current->next = tmpline;
2320 current = tmpline;
2321 slen -= i + 1;
2322 current_y++;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002323 } while ((strlenpt(current->data) > (fill))
2324 && !no_spaces(current->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002325 }
Chris Allegretta9149e612000-11-27 00:23:41 +00002326 tmpbot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002327
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002328 if (current->next)
2329 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00002330 else
2331 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002332 current_x = 0;
2333 placewewant = 0;
2334
Adam Rogoyski09f97962000-06-20 02:50:33 +00002335 renumber(initial);
2336 totlines = filebot->lineno;
2337
2338 werase(edit);
2339
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002340 if ((current_y < 0) || (current_y >= editwinrows - 1)
2341 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00002342 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002343 center_cursor();
2344 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00002345 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002346 }
2347
Adam Rogoyski09f97962000-06-20 02:50:33 +00002348 edit_refresh();
Chris Allegretta9149e612000-11-27 00:23:41 +00002349 statusbar(_("Can now UnJustify!"));
Chris Allegretta07798352000-11-27 22:58:23 +00002350 /* Change the shortcut list to display the unjustify code */
2351 shortcut_init(1);
2352 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002353 reset_cursor();
2354
Chris Allegretta88520c92001-05-05 17:45:54 +00002355 /* Now get a keystroke and see if it's unjustify; if not, unget the keystroke
Chris Allegretta9149e612000-11-27 00:23:41 +00002356 and return */
Chris Allegretta5f071802001-05-06 02:34:31 +00002357
2358#ifndef DISABLE_MOUSE
2359#ifdef NCURSES_MOUSE_VERSION
2360
2361 /* If it was a mouse click, parse it with do_mouse and it might become
2362 the unjustify key. Else give it back to the input stream. */
2363 if ((kbinput = wgetch(edit)) == KEY_MOUSE)
2364 do_mouse();
2365 else
2366 ungetch(kbinput);
2367#endif
2368#endif
2369
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002370 if ((kbinput = wgetch(edit)) != NANO_UNJUSTIFY_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002371 ungetch(kbinput);
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002372 blank_statusbar_refresh();
2373 } else {
Chris Allegretta9149e612000-11-27 00:23:41 +00002374 /* Else restore the justify we just did (ungrateful user!) */
2375 if (tmptop->prev != NULL)
2376 tmptop->prev->next = tmpbot->next;
Chris Allegrettad022eac2000-11-27 02:50:49 +00002377 else
2378 fileage = current;
Chris Allegretta9149e612000-11-27 00:23:41 +00002379 tmpbot->next->prev = tmptop->prev;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002380 current = tmpbot->next;
Chris Allegretta9149e612000-11-27 00:23:41 +00002381 tmpbot->next = NULL;
2382 do_uncut_text();
Chris Allegrettad022eac2000-11-27 02:50:49 +00002383 if (tmptop->prev == NULL)
2384 edit_refresh();
2385
Chris Allegretta88520c92001-05-05 17:45:54 +00002386 /* Restore totsize from before justify */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002387 totsize = totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002388 free_filestruct(tmptop);
2389 blank_statusbar_refresh();
2390 }
Chris Allegretta4a9c8582000-11-27 22:59:40 +00002391 shortcut_init(0);
2392 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002393 free_filestruct(cutbuffer);
2394 cutbuffer = cutbak;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002395
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002396 return 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002397#endif
2398}
2399
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002400#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002401void help_init(void)
2402{
Chris Allegretta13fd44b2002-01-02 13:59:11 +00002403 int i, sofar = 0, helplen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002404 long allocsize = 1; /* How much space we're gonna need for the help text */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002405 char buf[BUFSIZ] = "", *ptr = NULL;
2406
Chris Allegretta13fd44b2002-01-02 13:59:11 +00002407 if (currslen == MAIN_VISIBLE)
2408 helplen = MAIN_LIST_LEN;
2409 else
2410 helplen = currslen;
2411
Chris Allegrettab3655b42001-10-22 03:15:31 +00002412 /* First set up the initial help text for the current function */
2413 if (currshortcut == whereis_list || currshortcut == replace_list
2414 || currshortcut == replace_list_2)
2415 ptr = _("Search Command Help Text\n\n "
2416 "Enter the words or characters you would like to search "
2417 "for, then hit enter. If there is a match for the text you "
2418 "entered, the screen will be updated to the location of the "
Jordi Mallach773623c2001-10-28 21:00:49 +00002419 "nearest match for the search string.\n\n "
2420 "If using Pico Mode via the -p or --pico flags, using the "
2421 "Meta-P toggle or using a nanorc file, the previous search "
2422 "string will be shown in brackets after the Search: prompt. "
Jordi Mallachf4e57292001-12-26 00:16:40 +00002423 "Hitting enter without entering any text will perform the "
Jordi Mallach773623c2001-10-28 21:00:49 +00002424 "previous search. Otherwise, the previous string will be "
2425 "placed in front of the cursor, and can be edited or deleted "
2426 "before hitting enter.\n\n The following functions keys are "
2427 "available in Search mode:\n\n");
Chris Allegrettab3655b42001-10-22 03:15:31 +00002428 else if (currshortcut == goto_list)
2429 ptr = _("Goto Line Help Text\n\n "
2430 "Enter the line number that you wish to go to and hit "
Jordi Mallach773623c2001-10-28 21:00:49 +00002431 "Enter. If there are fewer lines of text than the "
Chris Allegrettab3655b42001-10-22 03:15:31 +00002432 "number you entered, you will be brought to the last line "
2433 "of the file.\n\n The following functions keys are "
2434 "available in Goto Line mode:\n\n");
2435 else if (currshortcut == insertfile_list)
2436 ptr = _("Insert File Help Text\n\n "
2437 "Type in the name of a file to be inserted into the current "
2438 "file buffer at the current cursor location.\n\n "
2439 "If you have compiled nano with multiple file buffer "
2440 "support, and enable multiple buffers with the -F "
Jordi Mallach773623c2001-10-28 21:00:49 +00002441 "or --multibuffer command line flags, the Meta-F toggle or "
2442 "using a nanorc file, inserting a file will cause it to be "
Chris Allegretta180a5692002-01-02 14:30:33 +00002443 "loaded into a separate buffer (use Meta-< and > to switch "
Jordi Mallach773623c2001-10-28 21:00:49 +00002444 "between file buffers).\n\n The following function keys are "
Chris Allegrettab3655b42001-10-22 03:15:31 +00002445 "available in Insert File mode:\n\n");
2446 else if (currshortcut == writefile_list)
2447 ptr = _("Write File Help Text\n\n "
2448 "Type the name that you wish to save the current file "
2449 "as and hit enter to save the file.\n\n "
2450 "If you are using the marker code with Ctrl-^ and have "
2451 "selected text, you will be prompted to save only the "
2452 "selected portion to a separate file. To reduce the "
2453 "chance of overwriting the current file with just a portion "
2454 "of it, the current filename is not the default in this "
2455 "mode.\n\n The following function keys are available in "
2456 "Write File mode:\n\n");
2457#ifndef DISABLE_BROWSER
2458 else if (currshortcut == browser_list)
2459 ptr = _("File Browser Help Text\n\n "
2460 "The file browser is used to visually browse the "
2461 "directory structure to select a file for reading "
2462 "or writing. You may use the arrow keys or Page Up/"
2463 "Down to browse through the files, and S or Enter to "
2464 "choose the selected file or enter the selected "
2465 "directory. To move up one level, select the directory "
2466 "called \"..\" at the top of the file list.\n\n The "
2467 "following functions keys are available in the file "
2468 "browser:\n\n");
2469 else if (currshortcut == gotodir_list)
2470 ptr = _("Browser Goto Directory Help Text\n\n "
2471 "Enter the name of the directory you would like to "
2472 "browse to.\n\n If tab completion has not been disabled, "
2473 "you can use the TAB key to (attempt to) automatically "
2474 "complete the directory name. The following function "
2475 "keys are available in Browser GotoDir mode:\n\n");
2476#endif
2477 else if (currshortcut == spell_list)
2478 ptr = _("Spell Check Help Text\n\n "
2479 "The spell checker checks the spelling of all text "
2480 "in the current file. When an unknown word is "
2481 "encountered, it is highlighted and a replacement can "
2482 "be edited. It will then prompt to replace every "
2483 "instance of the given misspelled word in the "
2484 "current file.\n\n The following other functions are "
2485 "available in Spell Check mode:\n\n");
2486 else /* Default to the main help list */
2487 ptr = help_text_init;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002488
2489 /* Compute the space needed for the shortcut lists - we add 15 to
2490 have room for the shortcut abbrev and its possible alternate keys */
Chris Allegretta13fd44b2002-01-02 13:59:11 +00002491 for (i = 0; i <= helplen - 1; i++)
Chris Allegrettab3655b42001-10-22 03:15:31 +00002492 if (currshortcut[i].help != NULL)
2493 allocsize += strlen(currshortcut[i].help) + 15;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002494
Chris Allegrettab3655b42001-10-22 03:15:31 +00002495 /* If we're on the main list, we also allocate space for toggle help text. */
2496 if (currshortcut == main_list) {
2497 for (i = 0; i <= TOGGLE_LEN - 1; i++)
2498 if (toggles[i].desc != NULL)
2499 allocsize += strlen(toggles[i].desc) + 30;
Chris Allegretta756f2202000-09-01 13:32:47 +00002500
Chris Allegrettab3655b42001-10-22 03:15:31 +00002501 }
2502
2503 allocsize += strlen(ptr);
2504
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002505
2506 if (help_text != NULL)
2507 free(help_text);
2508
2509 /* Allocate space for the help text */
Chris Allegretta88b09152001-05-17 11:35:43 +00002510 help_text = charalloc(allocsize);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002511
2512 /* Now add the text we want */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002513 strcpy(help_text, ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002514
2515 /* Now add our shortcut info */
Chris Allegretta13fd44b2002-01-02 13:59:11 +00002516 for (i = 0; i <= helplen - 1; i++) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00002517 if (currshortcut[i].val > 0 && currshortcut[i].val < 'a')
2518 sofar = snprintf(buf, BUFSIZ, "^%c ", currshortcut[i].val + 64);
Chris Allegretta8d990b52001-09-22 22:14:25 +00002519 else
2520 sofar = snprintf(buf, BUFSIZ, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002521
Chris Allegrettab3655b42001-10-22 03:15:31 +00002522 if (currshortcut[i].misc1 > KEY_F0 && currshortcut[i].misc1 <= KEY_F(64))
Robert Siemborski6af14312000-07-01 21:34:26 +00002523 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
Chris Allegrettab3655b42001-10-22 03:15:31 +00002524 currshortcut[i].misc1 - KEY_F0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002525 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002526 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002527
Chris Allegrettab3655b42001-10-22 03:15:31 +00002528 if (currshortcut[i].altval > 0 && currshortcut[i].altval < 91)
Chris Allegrettae49f1232000-09-02 07:20:39 +00002529 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
Chris Allegrettab3655b42001-10-22 03:15:31 +00002530 currshortcut[i].altval - 32);
2531 else if (currshortcut[i].altval > 0)
Chris Allegretta8d990b52001-09-22 22:14:25 +00002532 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
Chris Allegrettab3655b42001-10-22 03:15:31 +00002533 currshortcut[i].altval);
2534 /* Hack */
2535 else if (currshortcut[i].val >= 'a')
2536 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
2537 currshortcut[i].val - 32);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002538 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002539 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002540
Chris Allegretta756f2202000-09-01 13:32:47 +00002541
Chris Allegrettab3655b42001-10-22 03:15:31 +00002542 if (currshortcut[i].help != NULL)
2543 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", currshortcut[i].help);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002544
Chris Allegretta756f2202000-09-01 13:32:47 +00002545
2546 strcat(help_text, buf);
2547 strcat(help_text, "\n");
2548 }
2549
2550 /* And the toggles... */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002551 if (currshortcut == main_list)
2552 for (i = 0; i <= TOGGLE_LEN - 1; i++) {
2553 if (toggles[i].override_ch != 0)
2554 sofar = snprintf(buf, BUFSIZ,
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002555 "M-%c ", toggles[i].override_ch);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002556 else
2557 sofar = snprintf(buf, BUFSIZ,
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002558 "M-%c ", toggles[i].val - 32);
Chris Allegretta756f2202000-09-01 13:32:47 +00002559
Chris Allegrettab3655b42001-10-22 03:15:31 +00002560 if (toggles[i].desc != NULL) {
2561 if (toggles[i].flag != 0)
2562 snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002563 toggles[i].desc);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002564 else
2565 snprintf(&buf[sofar], BUFSIZ - sofar, "%s",
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002566 toggles[i].desc);
2567 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002568
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002569 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00002570 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002571 }
2572
2573}
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002574#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002575
Chris Allegretta756f2202000-09-01 13:32:47 +00002576void do_toggle(int which)
2577{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002578#ifdef NANO_SMALL
2579 nano_disabled_msg();
2580#else
Jordi Mallach2dc0f6b2000-09-07 10:48:00 +00002581 char *enabled = _("enabled");
2582 char *disabled = _("disabled");
Chris Allegrettaf0f63a82000-09-02 18:44:21 +00002583
Chris Allegretta8d990b52001-09-22 22:14:25 +00002584 switch (toggles[which].val) {
2585 case TOGGLE_BACKWARDS_KEY:
2586 case TOGGLE_CASE_KEY:
2587 case TOGGLE_REGEXP_KEY:
2588 return;
2589 }
Chris Allegretta8d990b52001-09-22 22:14:25 +00002590
Chris Allegretta658399a2001-06-14 02:54:22 +00002591 /* Even easier! */
2592 TOGGLE(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002593
Chris Allegretta756f2202000-09-01 13:32:47 +00002594 switch (toggles[which].val) {
2595 case TOGGLE_PICOMODE_KEY:
Chris Allegretta07798352000-11-27 22:58:23 +00002596 shortcut_init(0);
Chris Allegrettac1049ac2001-08-17 00:03:46 +00002597 SET(CLEAR_BACKUPSTRING);
Chris Allegretta756f2202000-09-01 13:32:47 +00002598 display_main_list();
2599 break;
2600 case TOGGLE_SUSPEND_KEY:
2601 signal_init();
2602 break;
2603 case TOGGLE_MOUSE_KEY:
2604 mouse_init();
2605 break;
2606 case TOGGLE_NOHELP_KEY:
Chris Allegretta2a42af12000-09-12 23:02:49 +00002607 wclear(bottomwin);
2608 wrefresh(bottomwin);
2609 window_init();
Chris Allegrettaaffeda82000-12-18 04:03:48 +00002610 fix_editbot();
Chris Allegretta2a42af12000-09-12 23:02:49 +00002611 edit_refresh();
2612 display_main_list();
Chris Allegretta756f2202000-09-01 13:32:47 +00002613 break;
Chris Allegretta99e30e12001-09-23 02:45:27 +00002614 case TOGGLE_DOS_KEY:
2615 UNSET(MAC_FILE);
2616 break;
2617 case TOGGLE_MAC_KEY:
2618 UNSET(DOS_FILE);
2619 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002620 }
Chris Allegretta2a42af12000-09-12 23:02:49 +00002621
Chris Allegretta819e3db2001-07-11 02:37:19 +00002622 if (!ISSET(toggles[which].flag)) {
2623 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
2624 toggles[which].val == TOGGLE_WRAP_KEY)
2625 statusbar("%s %s", toggles[which].desc, enabled);
2626 else
2627 statusbar("%s %s", toggles[which].desc, disabled);
2628 } else {
2629 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
2630 toggles[which].val == TOGGLE_WRAP_KEY)
2631 statusbar("%s %s", toggles[which].desc, disabled);
2632 else
2633 statusbar("%s %s", toggles[which].desc, enabled);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002634 }
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002635
Chris Allegretta756f2202000-09-01 13:32:47 +00002636#endif
2637}
2638
Chris Allegretta88520c92001-05-05 17:45:54 +00002639/* If the NumLock key has made the keypad go awry, print an error
2640 message; hopefully we can address it later. */
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002641void print_numlock_warning(void)
2642{
2643 static int didmsg = 0;
2644 if (!didmsg) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002645 statusbar(_
2646 ("NumLock glitch detected. Keypad will malfunction with NumLock off"));
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002647 didmsg = 1;
2648 }
2649}
2650
Chris Allegretta1748cd12001-01-13 17:22:54 +00002651/* This function returns the correct keystroke, given the A,B,C or D
2652 input key. This is a common sequence of many terms which send
2653 Esc-O-[A-D] or Esc-[-[A-D]. */
2654int ABCD(int input)
2655{
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002656 switch (input) {
2657 case 'A':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002658 case 'a':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002659 return (KEY_UP);
2660 case 'B':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002661 case 'b':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002662 return (KEY_DOWN);
2663 case 'C':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002664 case 'c':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002665 return (KEY_RIGHT);
2666 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002667 case 'd':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002668 return (KEY_LEFT);
2669 default:
2670 return 0;
Chris Allegretta1748cd12001-01-13 17:22:54 +00002671 }
2672}
2673
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002674int main(int argc, char *argv[])
2675{
2676 int optchr;
2677 int kbinput; /* Input from keyboard */
2678 long startline = 0; /* Line to try and start at */
Chris Allegretta08020882001-01-29 23:37:54 +00002679 int keyhandled; /* Have we handled the keystroke yet? */
2680 int i, modify_control_seq;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002681 char *argv0;
Chris Allegretta0357c4d2001-09-19 02:59:25 +00002682
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002683#ifdef _POSIX_VDISABLE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002684 struct termios term;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002685#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002686
2687#ifdef HAVE_GETOPT_LONG
2688 int option_index = 0;
2689 struct option long_options[] = {
Chris Allegretta805c26d2000-09-06 13:39:17 +00002690#ifdef HAVE_REGEX_H
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002691 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00002692#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002693 {"version", 0, 0, 'V'},
2694 {"const", 0, 0, 'c'},
2695 {"suspend", 0, 0, 'z'},
2696 {"nowrap", 0, 0, 'w'},
2697 {"nohelp", 0, 0, 'x'},
2698 {"help", 0, 0, 'h'},
Chris Allegretta7492cec2000-12-18 04:55:21 +00002699 {"view", 0, 0, 'v'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002700#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002701 {"cut", 0, 0, 'k'},
Chris Allegretta7004c282001-09-22 00:42:10 +00002702 {"dos", 0, 0, 'D'},
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002703 {"mac", 0, 0, 'M'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002704 {"autoindent", 0, 0, 'i'},
Chris Allegrettaff989832001-09-17 13:48:00 +00002705#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002706 {"tempfile", 0, 0, 't'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002707#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002708 {"speller", 1, 0, 's'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002709#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00002710
2711#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002712 {"fill", 1, 0, 'r'},
Chris Allegretta6fe61492001-05-21 12:56:25 +00002713#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002714 {"mouse", 0, 0, 'm'},
Chris Allegrettae1f14522001-09-19 03:19:43 +00002715#ifndef DISABLE_OPERATINGDIR
2716 {"operatingdir", 1, 0, 'o'},
2717#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002718 {"pico", 0, 0, 'p'},
2719 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00002720 {"tabsize", 1, 0, 'T'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002721
Chris Allegretta355fbe52001-07-14 19:32:47 +00002722#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002723 {"multibuffer", 0, 0, 'F'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002724#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002725#ifndef NANO_SMALL
2726 {"smooth", 0, 0, 'S'},
2727#endif
Chris Allegretta48bd3782002-01-03 21:26:34 +00002728 {"keypad", 0, 0, 'K'},
2729
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002730 {0, 0, 0, 0}
2731 };
2732#endif
2733
2734 /* Flag inits... */
2735 SET(FOLLOW_SYMLINKS);
2736
2737#ifndef NANO_SMALL
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002738#ifdef ENABLE_NLS
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002739 setlocale(LC_ALL, "");
2740 bindtextdomain(PACKAGE, LOCALEDIR);
2741 textdomain(PACKAGE);
2742#endif
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002743#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002744
Chris Allegretta8d8e0122001-04-18 04:28:54 +00002745#ifdef ENABLE_NANORC
2746 do_rcfile();
2747#endif /* ENABLE_NANORC */
2748
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002749#ifdef HAVE_GETOPT_LONG
Chris Allegretta48bd3782002-01-03 21:26:34 +00002750 while ((optchr = getopt_long(argc, argv, "h?DFKMRST:Vabcefgijklmo:pr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002751 long_options, &option_index)) != EOF) {
2752#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002753 while ((optchr =
Chris Allegretta48bd3782002-01-03 21:26:34 +00002754 getopt(argc, argv, "h?DFKMRST:Vabcefgijklmo:pr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002755#endif
2756
2757 switch (optchr) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002758
Chris Allegretta7004c282001-09-22 00:42:10 +00002759#ifndef NANO_SMALL
2760 case 'D':
2761 SET(DOS_FILE);
2762 break;
2763#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +00002764#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002765 case 'F':
Chris Allegretta355fbe52001-07-14 19:32:47 +00002766 SET(MULTIBUFFER);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002767 break;
2768#endif
Chris Allegretta48bd3782002-01-03 21:26:34 +00002769 case 'K':
2770 SET(ALT_KEYPAD);
2771 break;
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002772#ifndef NANO_SMALL
2773 case 'M':
2774 SET(MAC_FILE);
2775 break;
2776#endif
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002777 case 'T':
Chris Allegretta99bf73f2000-08-04 00:22:08 +00002778 tabsize = atoi(optarg);
2779 if (tabsize <= 0) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002780 usage(); /* To stop bogus data for tab width */
2781 finish(1);
2782 }
2783 break;
Chris Allegretta805c26d2000-09-06 13:39:17 +00002784#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +00002785 case 'R':
2786 SET(USE_REGEXP);
2787 break;
Chris Allegretta47805612000-07-07 02:35:34 +00002788#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002789#ifndef NANO_SMALL
2790 case 'S':
2791 SET(SMOOTHSCROLL);
2792 break;
2793#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002794 case 'V':
2795 version();
2796 exit(0);
Chris Allegrettae1f14522001-09-19 03:19:43 +00002797 case 'a':
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002798 case 'b':
2799 case 'e':
2800 case 'f':
Rocco Corsi12f294c2001-04-14 06:50:24 +00002801 case 'g':
2802 case 'j':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002803 /* Pico compatibility flags */
2804 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002805 case 'c':
2806 SET(CONSTUPDATE);
2807 break;
2808 case 'h':
2809 case '?':
2810 usage();
2811 exit(0);
Chris Allegrettaff989832001-09-17 13:48:00 +00002812#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002813 case 'i':
2814 SET(AUTOINDENT);
2815 break;
Chris Allegretta627de192000-07-12 02:09:17 +00002816 case 'k':
2817 SET(CUT_TO_END);
2818 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002819#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002820 case 'l':
2821 UNSET(FOLLOW_SYMLINKS);
2822 break;
2823 case 'm':
2824 SET(USE_MOUSE);
2825 break;
Chris Allegrettae1f14522001-09-19 03:19:43 +00002826#ifndef DISABLE_OPERATINGDIR
2827 case 'o':
2828 operating_dir = charalloc(strlen(optarg) + 1);
2829 strcpy(operating_dir, optarg);
2830
2831 /* make sure we're inside the operating directory */
2832 if (check_operating_dir(".", 0)) {
2833 if (chdir(operating_dir) == -1) {
2834 free(operating_dir);
2835 operating_dir = NULL;
2836 }
2837 }
2838 break;
2839#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002840 case 'p':
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002841 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002842 break;
2843 case 'r':
Chris Allegretta6fe61492001-05-21 12:56:25 +00002844#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002845 fill = atoi(optarg);
Chris Allegretta6fe61492001-05-21 12:56:25 +00002846 if (fill < 0)
2847 wrap_at = fill;
2848 else if (fill == 0) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002849 usage(); /* To stop bogus data (like a string) */
2850 finish(1);
2851 }
2852 break;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002853#else
2854 usage();
2855 exit(0);
2856
2857#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002858#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002859 case 's':
Chris Allegretta88b09152001-05-17 11:35:43 +00002860 alt_speller = charalloc(strlen(optarg) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002861 strcpy(alt_speller, optarg);
2862 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002863#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002864 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00002865 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002866 break;
2867 case 'v':
2868 SET(VIEW_MODE);
2869 break;
2870 case 'w':
Chris Allegrettacef7fbb2001-04-02 05:36:08 +00002871#ifdef DISABLE_WRAPPING
2872 usage();
2873 exit(0);
2874#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002875 SET(NO_WRAP);
2876 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002877#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002878 case 'x':
2879 SET(NO_HELP);
2880 break;
2881 case 'z':
2882 SET(SUSPEND);
2883 break;
2884 default:
2885 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002886 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002887 }
2888
2889 }
2890
2891 argv0 = strrchr(argv[0], '/');
2892 if ((argv0 && strstr(argv0, "pico"))
2893 || (!argv0 && strstr(argv[0], "pico")))
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002894 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002895
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002896 /* See if there's a non-option in argv (first non-option is the
2897 filename, if +LINE is not given) */
2898 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002899 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002900 else {
2901 /* Look for the +line flag... */
2902 if (argv[optind][0] == '+') {
2903 startline = atoi(&argv[optind][1]);
2904 optind++;
2905 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002906 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002907 else
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002908 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002909
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002910 } else
2911 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002912 }
2913
2914
2915 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002916 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002917
Chris Allegretta9239d742000-09-06 15:19:18 +00002918#ifdef _POSIX_VDISABLE
Chris Allegretta8f6c0692000-07-19 01:16:18 +00002919 term = oldterm;
2920 term.c_cc[VINTR] = _POSIX_VDISABLE;
2921 term.c_cc[VQUIT] = _POSIX_VDISABLE;
2922 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002923 tcsetattr(0, TCSANOW, &term);
Chris Allegretta9239d742000-09-06 15:19:18 +00002924#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002925
2926 /* now ncurses init stuff... */
2927 initscr();
2928 savetty();
2929 nonl();
2930 cbreak();
2931 noecho();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002932
2933 /* Set up some global variables */
Chris Allegretta56214c62001-09-27 02:46:53 +00002934 global_init(0);
Chris Allegretta07798352000-11-27 22:58:23 +00002935 shortcut_init(0);
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002936#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002937 init_help_msg();
2938 help_init();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002939#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002940 signal_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002941
2942#ifdef DEBUG
2943 fprintf(stderr, _("Main: set up windows\n"));
2944#endif
2945
Chris Allegretta2a42af12000-09-12 23:02:49 +00002946 window_init();
Chris Allegretta756f2202000-09-01 13:32:47 +00002947 mouse_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002948
Chris Allegretta48bd3782002-01-03 21:26:34 +00002949 if (!ISSET(ALT_KEYPAD)) {
2950 keypad(edit, TRUE);
2951 keypad(bottomwin, TRUE);
2952 }
2953
Chris Allegretta08893e02001-11-29 02:42:27 +00002954#ifdef ENABLE_COLOR
2955 do_colorinit();
2956
Chris Allegretta08893e02001-11-29 02:42:27 +00002957#endif /* ENABLE_COLOR */
2958
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002959#ifdef DEBUG
2960 fprintf(stderr, _("Main: bottom win\n"));
2961#endif
Chris Allegretta88520c92001-05-05 17:45:54 +00002962 /* Set up bottom of window */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002963 display_main_list();
2964
2965#ifdef DEBUG
2966 fprintf(stderr, _("Main: open file\n"));
2967#endif
2968
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002969 titlebar(NULL);
Chris Allegretta31c76662000-11-21 06:20:20 +00002970
2971 /* Now we check to see if argv[optind] is non-null to determine if
2972 we're dealing with a new file or not, not argc == 1... */
2973 if (argv[optind] == NULL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002974 new_file();
2975 else
2976 open_file(filename, 0, 0);
2977
2978 if (startline > 0)
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002979 do_gotoline(startline, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002980 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00002981 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002982
Chris Allegretta08020882001-01-29 23:37:54 +00002983 /* return here after a sigwinch */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002984 sigsetjmp(jmpbuf, 1);
Chris Allegretta08020882001-01-29 23:37:54 +00002985
2986 /* Fix clobber-age */
2987 kbinput = 0;
2988 keyhandled = 0;
2989 modify_control_seq = 0;
2990
Robert Siemborski6967eec2000-07-08 14:23:32 +00002991 edit_refresh();
2992 reset_cursor();
2993
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002994 while (1) {
Chris Allegretta9239d742000-09-06 15:19:18 +00002995
Chris Allegretta6fe61492001-05-21 12:56:25 +00002996#ifndef DISABLE_MOUSE
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002997 currshortcut = main_list;
2998 currslen = MAIN_VISIBLE;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002999#endif
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003000
Chris Allegretta9239d742000-09-06 15:19:18 +00003001#ifndef _POSIX_VDISABLE
3002 /* We're going to have to do it the old way, i.e. on cygwin */
3003 raw();
3004#endif
3005
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003006 kbinput = wgetch(edit);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003007#ifdef DEBUG
3008 fprintf(stderr, "AHA! %c (%d)\n", kbinput, kbinput);
3009#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003010
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003011 if (kbinput == 27) { /* Grab Alt-key stuff first */
3012 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003013 /* Alt-O, suddenly very important ;) */
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003014 case 'O':
Chris Allegretta16e41682000-09-11 22:33:54 +00003015 kbinput = wgetch(edit);
Chris Allegretta316e4d92001-04-28 16:31:19 +00003016 if ((kbinput <= 'D' && kbinput >= 'A') ||
3017 (kbinput <= 'd' && kbinput >= 'a'))
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003018 kbinput = ABCD(kbinput);
Chris Allegretta201d9bf2001-01-14 03:17:53 +00003019 else if (kbinput <= 'z' && kbinput >= 'j')
3020 print_numlock_warning();
3021 else if (kbinput <= 'S' && kbinput >= 'P')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003022 kbinput = KEY_F(kbinput - 79);
Chris Allegretta16e41682000-09-11 22:33:54 +00003023#ifdef DEBUG
3024 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003025 fprintf(stderr, _("I got Alt-O-%c! (%d)\n"),
3026 kbinput, kbinput);
3027 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003028 }
3029#endif
3030 break;
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003031 case 27:
3032 /* If we get Alt-Alt, the next keystroke should be the same as a
3033 control sequence */
3034 modify_control_seq = 1;
3035 keyhandled = 1;
3036 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00003037#ifndef NANO_SMALL
Chris Allegretta76e291b2001-10-14 19:05:10 +00003038 case ' ':
3039 /* If control-space is next word, Alt-space should be previous word */
3040 do_prev_word();
3041 keyhandled = 1;
3042 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00003043#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003044 case '[':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003045 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003046 case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */
Chris Allegretta16e41682000-09-11 22:33:54 +00003047 kbinput = wgetch(edit);
3048 if (kbinput >= '1' && kbinput <= '5') {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003049 kbinput = KEY_F(kbinput - 48);
3050 wgetch(edit);
3051 } else if (kbinput >= '7' && kbinput <= '9') {
3052 kbinput = KEY_F(kbinput - 49);
3053 wgetch(edit);
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003054 } else if (kbinput == '~')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003055 kbinput = KEY_HOME;
Chris Allegretta16e41682000-09-11 22:33:54 +00003056
3057#ifdef DEBUG
3058 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003059 fprintf(stderr, _("I got Alt-[-1-%c! (%d)\n"),
3060 kbinput, kbinput);
3061 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003062 }
3063#endif
3064
3065 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003066 case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */
Chris Allegretta16e41682000-09-11 22:33:54 +00003067 kbinput = wgetch(edit);
Chris Allegretta16e41682000-09-11 22:33:54 +00003068 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003069 case '0':
3070 kbinput = KEY_F(9);
3071 wgetch(edit);
3072 break;
3073 case '1':
3074 kbinput = KEY_F(10);
3075 wgetch(edit);
3076 break;
3077 case '3':
3078 kbinput = KEY_F(11);
3079 wgetch(edit);
3080 break;
3081 case '4':
3082 kbinput = KEY_F(12);
3083 wgetch(edit);
3084 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003085 case '~':
3086 goto do_insertkey;
Chris Allegretta16e41682000-09-11 22:33:54 +00003087#ifdef DEBUG
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003088 default:
3089 fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"),
3090 kbinput, kbinput);
3091 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003092#endif
3093
3094 }
3095 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003096 case '3': /* Alt-[-3 = Delete? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003097 kbinput = NANO_DELETE_KEY;
3098 wgetch(edit);
3099 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003100 case '4': /* Alt-[-4 = End? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003101 kbinput = NANO_END_KEY;
3102 wgetch(edit);
3103 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003104 case '5': /* Alt-[-5 = Page Up */
Chris Allegretta16e41682000-09-11 22:33:54 +00003105 kbinput = KEY_PPAGE;
3106 wgetch(edit);
3107 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003108 case 'V': /* Alt-[-V = Page Up in Hurd Console */
Chris Allegretta7bf72742001-10-28 04:29:55 +00003109 case 'I': /* Alt-[-I = Page Up - FreeBSD Console */
3110 kbinput = KEY_PPAGE;
3111 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003112 case '6': /* Alt-[-6 = Page Down */
Chris Allegretta16e41682000-09-11 22:33:54 +00003113 kbinput = KEY_NPAGE;
3114 wgetch(edit);
3115 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003116 case 'U': /* Alt-[-U = Page Down in Hurd Console */
Chris Allegretta7bf72742001-10-28 04:29:55 +00003117 case 'G': /* Alt-[-G = Page Down - FreeBSD Console */
3118 kbinput = KEY_NPAGE;
3119 break;
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003120 case '7':
3121 kbinput = KEY_HOME;
3122 wgetch(edit);
3123 break;
3124 case '8':
3125 kbinput = KEY_END;
3126 wgetch(edit);
3127 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003128 case '9': /* Alt-[-9 = Delete in Hurd Console */
3129 kbinput = KEY_DC;
3130 break;
Chris Allegretta32da4562002-01-02 15:12:21 +00003131 case '@': /* Alt-[-@ = Insert in Hurd Console */
3132 case 'L': /* Alt-[-L = Insert - FreeBSD Console */
3133 goto do_insertkey;
3134 case '[': /* Alt-[-[-[A-E], F1-F5 in Linux console */
Chris Allegretta16e41682000-09-11 22:33:54 +00003135 kbinput = wgetch(edit);
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003136 if (kbinput >= 'A' && kbinput <= 'E')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003137 kbinput = KEY_F(kbinput - 64);
Chris Allegretta16e41682000-09-11 22:33:54 +00003138 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003139 case 'A':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003140 case 'B':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003141 case 'C':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003142 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00003143 case 'a':
3144 case 'b':
3145 case 'c':
3146 case 'd':
Chris Allegretta1748cd12001-01-13 17:22:54 +00003147 kbinput = ABCD(kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003148 break;
3149 case 'H':
3150 kbinput = KEY_HOME;
3151 break;
3152 case 'F':
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003153 case 'Y': /* End Key in Hurd Console */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003154 kbinput = KEY_END;
3155 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003156 default:
3157#ifdef DEBUG
3158 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
3159 kbinput, kbinput);
3160#endif
3161 break;
3162 }
3163 break;
Chris Allegretta355fbe52001-07-14 19:32:47 +00003164#ifdef ENABLE_MULTIBUFFER
Chris Allegretta819e3db2001-07-11 02:37:19 +00003165 case NANO_OPENPREV_KEY:
Chris Allegretta180a5692002-01-02 14:30:33 +00003166 case NANO_OPENPREV_ALTKEY:
Chris Allegretta819e3db2001-07-11 02:37:19 +00003167 open_prevfile(0);
3168 keyhandled = 1;
3169 break;
3170 case NANO_OPENNEXT_KEY:
Chris Allegretta180a5692002-01-02 14:30:33 +00003171 case NANO_OPENNEXT_ALTKEY:
Chris Allegretta819e3db2001-07-11 02:37:19 +00003172 open_nextfile(0);
3173 keyhandled = 1;
3174 break;
Chris Allegretta9cf9e062001-07-11 12:06:13 +00003175#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003176 default:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003177 /* Check for the altkey defs.... */
3178 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
3179 if (kbinput == main_list[i].altval ||
3180 kbinput == main_list[i].altval - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003181 kbinput = main_list[i].val;
3182 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003183 }
Chris Allegretta756f2202000-09-01 13:32:47 +00003184#ifndef NANO_SMALL
3185 /* And for toggle switches */
3186 for (i = 0; i <= TOGGLE_LEN - 1 && !keyhandled; i++)
3187 if (kbinput == toggles[i].val ||
Chris Allegrettaf7dee922002-01-07 16:43:25 +00003188 (toggles[i].val > 'a' &&
3189 kbinput == toggles[i].val - 32)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003190 do_toggle(i);
3191 keyhandled = 1;
3192 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00003193 }
3194#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003195#ifdef DEBUG
3196 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
3197 kbinput);
3198#endif
3199 break;
3200 }
3201 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003202 /* If the modify_control_seq is set, we received an Alt-Alt
3203 sequence before this, so we make this key a control sequence
3204 by subtracting 64 or 96, depending on its value. */
3205 if (!keyhandled && modify_control_seq) {
3206 if (kbinput >= 'A' && kbinput < 'a')
3207 kbinput -= 64;
3208 else if (kbinput >= 'a' && kbinput <= 'z')
3209 kbinput -= 96;
3210
3211 modify_control_seq = 0;
3212 }
3213
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003214 /* Look through the main shortcut list to see if we've hit a
3215 shortcut key */
Chris Allegretta2cd72b62001-10-24 17:25:36 +00003216 for (i = 0; i < MAIN_LIST_LEN && !keyhandled; i++) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003217 if (kbinput == main_list[i].val ||
3218 (main_list[i].misc1 && kbinput == main_list[i].misc1) ||
3219 (main_list[i].misc2 && kbinput == main_list[i].misc2)) {
3220 if (ISSET(VIEW_MODE) && !main_list[i].viewok)
3221 print_view_warning();
3222 else
3223 main_list[i].func();
3224 keyhandled = 1;
3225 }
3226 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003227 /* If we're in raw mode or using Alt-Alt-x, we have to catch
3228 Control-S and Control-Q */
Chris Allegretta9239d742000-09-06 15:19:18 +00003229 if (kbinput == 17 || kbinput == 19)
3230 keyhandled = 1;
3231
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003232 /* Catch ^Z by hand when triggered also */
Chris Allegretta9239d742000-09-06 15:19:18 +00003233 if (kbinput == 26) {
3234 if (ISSET(SUSPEND))
3235 do_suspend(0);
3236 keyhandled = 1;
3237 }
Chris Allegretta9239d742000-09-06 15:19:18 +00003238
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003239
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003240#ifndef USE_SLANG
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003241 /* Hack, make insert key do something useful, like insert file */
3242 if (kbinput == KEY_IC) {
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003243#else
3244 if (0) {
3245#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003246 do_insertkey:
3247
3248#ifdef ENABLE_MULTIBUFFER
Chris Allegretta32da4562002-01-02 15:12:21 +00003249 /* do_insertfile_void() contains the logic needed to
3250 handle view mode with the view mode/multibuffer
3251 exception, so use it here */
3252 do_insertfile_void();
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003253#else
Chris Allegretta32da4562002-01-02 15:12:21 +00003254 print_view_warning();
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003255#endif
3256
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003257 keyhandled = 1;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003258 }
3259
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003260 /* Last gasp, stuff that's not in the main lists */
3261 if (!keyhandled)
3262 switch (kbinput) {
Chris Allegretta84de5522001-04-12 14:51:48 +00003263#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003264#ifdef NCURSES_MOUSE_VERSION
3265 case KEY_MOUSE:
3266 do_mouse();
3267 break;
3268#endif
3269#endif
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003270
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003271 case 0: /* Erg */
Chris Allegretta48ebb812001-10-24 01:34:15 +00003272#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003273 do_next_word();
3274 break;
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003275#endif
Chris Allegrettaf4f7e042001-01-04 16:56:15 +00003276
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003277 case -1: /* Stuff that we don't want to do squat */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003278 case 410: /* Must ignore this, it gets sent when we resize */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003279 case 29: /* Ctrl-] */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003280#ifdef PDCURSES
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003281 case 541: /* ???? */
3282 case 542: /* Control and alt in Windows *shrug* */
Chris Allegretta72623582000-11-29 23:43:28 +00003283 case 543: /* Right ctrl key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003284 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +00003285 case 545: /* Right alt key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003286#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003287
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003288 break;
3289 default:
3290#ifdef DEBUG
3291 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
3292#endif
3293 /* We no longer stop unhandled sequences so that people with
3294 odd character sets can type... */
3295
3296 if (ISSET(VIEW_MODE)) {
3297 print_view_warning();
3298 break;
3299 }
3300 do_char(kbinput);
3301 }
Chris Allegretta7fdbd052001-10-02 00:55:38 +00003302 if (ISSET(DISABLE_CURPOS))
3303 UNSET(DISABLE_CURPOS);
3304 else if (ISSET(CONSTUPDATE))
Chris Allegretta2084acc2001-11-29 03:43:08 +00003305 do_cursorpos(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003306
3307 reset_cursor();
3308 wrefresh(edit);
3309 keyhandled = 0;
3310 }
3311
3312 getchar();
3313 finish(0);
3314
3315}