blob: d12f99bcc4e14a3e615a16c44b33e91fcc37f336 [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 Allegrettaa8c22572002-02-15 19:17:02 +000067int fill = 0;/* Fill - where to wrap lines, basically */
Chris Allegretta7e65d2f2002-02-15 21:12:52 +000068int wrap_at = 0;/* Right justified fill value, allows resize */
Chris Allegretta6fe61492001-05-21 12:56:25 +000069#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
Chris Allegrettaf5de33a2002-02-27 04:14:16 +0000103 thanks_for_all_the_fish();
104
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000105 exit(sigage);
106}
107
108/* Die (gracefully?) */
109void die(char *msg, ...)
110{
111 va_list ap;
112
113 va_start(ap, msg);
114 vfprintf(stderr, msg, ap);
115 va_end(ap);
116
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000117 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000118 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000119
120 clear();
121 refresh();
122 resetty();
123 endwin();
124
125 fprintf(stderr, msg);
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000126
Chris Allegretta32da4562002-01-02 15:12:21 +0000127 /* save the currently loaded file if it's been modified */
128 if (ISSET(MODIFIED))
129 die_save_file(filename);
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000130
Chris Allegretta355fbe52001-07-14 19:32:47 +0000131#ifdef ENABLE_MULTIBUFFER
Chris Allegretta32da4562002-01-02 15:12:21 +0000132 /* then save all of the other modified loaded files, if any */
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000133 if (open_files) {
134 filestruct *tmp;
135
136 tmp = open_files;
137
138 while (open_files->prev)
139 open_files = open_files->prev;
140
141 while (open_files->next) {
142
143 /* if we already saved the file above (i. e. if it was the
144 currently loaded file), don't save it again */
145 if (tmp != open_files) {
146 fileage = open_files->file;
Chris Allegretta32da4562002-01-02 15:12:21 +0000147 /* save the file if it's been modified */
148 if (open_files->file_modified)
149 die_save_file(open_files->data);
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000150 }
151
152 open_files = open_files->next;
153 }
154
155 }
156#endif
157
158 exit(1); /* We have a problem: exit w/ errorlevel(1) */
159}
160
161void die_save_file(char *die_filename)
162{
Chris Allegretta48b06702002-02-22 04:30:50 +0000163 char *name, *ret;
164 int i = -1;
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000165
166 /* if we can't save we have REAL bad problems,
167 * but we might as well TRY. */
168 if (die_filename[0] == '\0') {
169 name = "nano.save";
Chris Allegretta48b06702002-02-22 04:30:50 +0000170 ret = get_next_filename(name);
171 if (strcmp(ret, ""))
172 i = write_file(ret, 1, 0, 0);
173 name = ret;
174 }
175 else {
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000176 char *buf = charalloc(strlen(die_filename) + 6);
177 strcpy(buf, die_filename);
178 strcat(buf, ".save");
Chris Allegretta48b06702002-02-22 04:30:50 +0000179 ret = get_next_filename(buf);
180 if (strcmp(ret, ""))
181 i = write_file(ret, 1, 0, 0);
182 name = ret;
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000183 }
184
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000185 if (i != -1)
186 fprintf(stderr, _("\nBuffer written to %s\n"), name);
187 else
Chris Allegretta48b06702002-02-22 04:30:50 +0000188 fprintf(stderr, _("\nNo %s written (too many backup files?)\n"), name);
189
190 free(ret);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000191}
192
Chris Allegrettae61e8302001-01-14 05:18:27 +0000193/* Die with an error message that the screen was too small if, well, the
194 screen is too small */
195void die_too_small(void)
196{
197 char *too_small_msg = _("Window size is too small for Nano...");
198
199 die(too_small_msg);
200
201}
202
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000203void print_view_warning(void)
204{
205 statusbar(_("Key illegal in VIEW mode"));
206}
207
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000208void clear_filename(void)
209{
210 if (filename != NULL)
211 free(filename);
Chris Allegretta88b09152001-05-17 11:35:43 +0000212 filename = charalloc(1);
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000213 filename[0] = 0;
214}
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +0000215
Chris Allegretta56214c62001-09-27 02:46:53 +0000216/* Initialize global variables - no better way for now. If
217 save_cutbuffer is nonzero, don't set cutbuffer to NULL. */
218void global_init(int save_cutbuffer)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000219{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000220 current_x = 0;
221 current_y = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000222
223 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
224 die_too_small();
225
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000226 fileage = NULL;
Chris Allegretta56214c62001-09-27 02:46:53 +0000227 if (!save_cutbuffer)
228 cutbuffer = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000229 current = NULL;
230 edittop = NULL;
231 editbot = NULL;
232 totlines = 0;
Chris Allegretta56214c62001-09-27 02:46:53 +0000233 totsize = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000234 placewewant = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000235
Chris Allegretta6fe61492001-05-21 12:56:25 +0000236#ifndef DISABLE_WRAPJUSTIFY
237 if (wrap_at)
238 fill = COLS + wrap_at;
239 else if (!fill)
Chris Allegrettae61e8302001-01-14 05:18:27 +0000240 fill = COLS - CHARS_FROM_EOL;
241
242 if (fill < MIN_FILL_LENGTH)
243 die_too_small();
Chris Allegretta6fe61492001-05-21 12:56:25 +0000244#endif
Chris Allegrettae61e8302001-01-14 05:18:27 +0000245
Chris Allegretta88b09152001-05-17 11:35:43 +0000246 hblank = charalloc(COLS + 1);
Chris Allegretta0a06e072001-01-23 02:35:04 +0000247 memset(hblank, ' ', COLS);
248 hblank[COLS] = 0;
Chris Allegretta76e291b2001-10-14 19:05:10 +0000249
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000250}
251
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000252#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000253void init_help_msg(void)
254{
255
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000256 help_text_init =
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000257 _(" nano help text\n\n "
258 "The nano editor is designed to emulate the functionality and "
259 "ease-of-use of the UW Pico text editor. There are four main "
260 "sections of the editor: The top line shows the program "
261 "version, the current filename being edited, and whether "
262 "or not the file has been modified. Next is the main editor "
263 "window showing the file being edited. The status line is "
264 "the third line from the bottom and shows important messages. "
265 "The bottom two lines show the most commonly used shortcuts "
266 "in the editor.\n\n "
267 "The notation for shortcuts is as follows: Control-key "
Chris Allegrettae49f1232000-09-02 07:20:39 +0000268 "sequences are notated with a caret (^) symbol and are entered "
Chris Allegrettad56bd792000-09-02 07:27:10 +0000269 "with the Control (Ctrl) key. Escape-key sequences are notated "
270 "with the Meta (M) symbol and can be entered using either the "
271 "Esc, Alt or Meta key depending on your keyboard setup. The "
272 "following keystrokes are available in the main editor window. "
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000273 "Optional keys are shown in parentheses:\n\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000274}
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000275#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000276
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000277/* Make a copy of a node to a pointer (space will be malloc()ed). This
278 does NOT copy the data members used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000279filestruct *copy_node(filestruct * src)
280{
281 filestruct *dst;
282
283 dst = nmalloc(sizeof(filestruct));
Chris Allegretta88b09152001-05-17 11:35:43 +0000284 dst->data = charalloc(strlen(src->data) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000285
286 dst->next = src->next;
287 dst->prev = src->prev;
288
289 strcpy(dst->data, src->data);
290 dst->lineno = src->lineno;
291
292 return dst;
293}
294
295/* Unlink a node from the rest of the struct */
296void unlink_node(filestruct * fileptr)
297{
298 if (fileptr->prev != NULL)
299 fileptr->prev->next = fileptr->next;
300
301 if (fileptr->next != NULL)
302 fileptr->next->prev = fileptr->prev;
303}
304
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000305/* Delete a node from the struct. This does NOT delete the data members
306 used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000307void delete_node(filestruct * fileptr)
308{
Chris Allegretta17dcb722001-01-20 21:40:07 +0000309 if (fileptr == NULL)
310 return;
311
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000312 if (fileptr->data != NULL)
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000313 free(fileptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000314 free(fileptr);
315}
316
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000317/* Okay, now let's duplicate a whole struct! This does NOT duplicate the
318 data members used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000319filestruct *copy_filestruct(filestruct * src)
320{
321 filestruct *dst, *tmp, *head, *prev;
322
323 head = copy_node(src);
324 dst = head; /* Else we barf on copying just one line */
325 head->prev = NULL;
326 tmp = src->next;
327 prev = head;
328
329 while (tmp != NULL) {
330 dst = copy_node(tmp);
331 dst->prev = prev;
332 prev->next = dst;
333
334 prev = dst;
335 tmp = tmp->next;
336 }
337
338 dst->next = NULL;
339 return head;
340}
341
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000342/* Frees a struct. This does NOT free the data members used only by
343 open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000344int free_filestruct(filestruct * src)
345{
346 filestruct *fileptr = src;
347
348 if (src == NULL)
349 return 0;
350
351 while (fileptr->next != NULL) {
352 fileptr = fileptr->next;
Chris Allegretta17dcb722001-01-20 21:40:07 +0000353 delete_node(fileptr->prev);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000354
355#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000356 fprintf(stderr, _("delete_node(): free'd a node, YAY!\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000357#endif
358 }
Chris Allegretta17dcb722001-01-20 21:40:07 +0000359 delete_node(fileptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000360#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000361 fprintf(stderr, _("delete_node(): free'd last node.\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000362#endif
363
364 return 1;
365}
366
367int renumber_all(void)
368{
369 filestruct *temp;
370 long i = 1;
371
372 for (temp = fileage; temp != NULL; temp = temp->next) {
373 temp->lineno = i++;
374 }
375
376 return 0;
377}
378
379int renumber(filestruct * fileptr)
380{
381 filestruct *temp;
382
383 if (fileptr == NULL || fileptr->prev == NULL || fileptr == fileage) {
384 renumber_all();
385 return 0;
386 }
387 for (temp = fileptr; temp != NULL; temp = temp->next) {
Chris Allegretta5146fec2000-12-10 05:44:02 +0000388 if (temp->prev != NULL)
389 temp->lineno = temp->prev->lineno + 1;
390 else
391 temp->lineno = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000392 }
393
394 return 0;
395}
396
397/* Fix the memory allocation for a string */
398void align(char **strp)
399{
400 /* There was a serious bug here: the new address was never
401 stored anywhere... */
402
403 *strp = nrealloc(*strp, strlen(*strp) + 1);
404}
405
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000406/* Null a string at a certain index and align it */
Chris Allegrettafa0c6962001-10-22 23:22:19 +0000407void null_at(char **data, int index)
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000408{
Chris Allegrettafa0c6962001-10-22 23:22:19 +0000409
410 /* Ahh! Damn dereferencing */
411 (*data)[index] = 0;
412 align(data);
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000413}
414
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000415void usage(void)
416{
417#ifdef HAVE_GETOPT_LONG
418 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
419 printf(_("Option Long option Meaning\n"));
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000420
Chris Allegretta7004c282001-09-22 00:42:10 +0000421#ifndef NANO_SMALL
422 printf
423 (_
424 (" -D --dos Write file in DOS format\n"));
425#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000426#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000427 printf
428 (_
Chris Allegretta355fbe52001-07-14 19:32:47 +0000429 (" -F --multibuffer Enable multiple file buffers\n"));
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000430#endif
Chris Allegretta48bd3782002-01-03 21:26:34 +0000431 printf(_
432 (" -K --keypad Use alternate keypad routines\n"));
Chris Allegretta8fa1e282001-09-22 04:20:25 +0000433#ifndef NANO_SMALL
434 printf
435 (_
436 (" -M --mac Write file in Mac format\n"));
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000437 printf
438 (_
439 (" -N --noconvert Don't convert files from DOS/Mac format\n"));
Chris Allegretta47805612000-07-07 02:35:34 +0000440#endif
Chris Allegrettae4f940d2002-03-03 22:36:36 +0000441#ifndef DISABLE_JUSTIFY
442 printf
443 (_
Chris Allegretta309aa502002-03-04 12:15:44 +0000444 (" -Q [str] --quotestr [str] Quoting string, default \"> \"\n"));
Chris Allegrettae4f940d2002-03-03 22:36:36 +0000445#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +0000446#ifndef NANO_SMALL
447 printf(_
448 (" -S --smooth Smooth scrolling\n"));
449#endif
Chris Allegretta7004c282001-09-22 00:42:10 +0000450 printf(_
451 (" -T [num] --tabsize=[num] Set width of a tab to num\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000452 printf
453 (_
454 (" -V --version Print version information and exit\n"));
455 printf(_
456 (" -c --const Constantly show cursor position\n"));
457 printf(_
458 (" -h --help Show this message\n"));
Chris Allegrettaff989832001-09-17 13:48:00 +0000459#ifndef NANO_SMALL
Chris Allegrettad55655f2000-12-27 03:36:47 +0000460 printf(_
461 (" -i --autoindent Automatically indent new lines\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000462 printf(_
Chris Allegretta627de192000-07-12 02:09:17 +0000463 (" -k --cut Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000464#endif
Chris Allegretta627de192000-07-12 02:09:17 +0000465 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000466 (" -l --nofollow Don't follow symbolic links, overwrite\n"));
Chris Allegretta84de5522001-04-12 14:51:48 +0000467#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000468#ifdef NCURSES_MOUSE_VERSION
469 printf(_(" -m --mouse Enable mouse\n"));
470#endif
471#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000472#ifndef DISABLE_OPERATINGDIR
Chris Allegrettad55655f2000-12-27 03:36:47 +0000473 printf(_
Chris Allegretta56214c62001-09-27 02:46:53 +0000474 (" -o [dir] --operatingdir=[dir] Set operating directory\n"));
Chris Allegrettae1f14522001-09-19 03:19:43 +0000475#endif
476 printf(_
477 (" -p --pico Emulate Pico as closely as possible\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000478
479#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000480 printf
481 (_
482 (" -r [#cols] --fill=[#cols] Set fill cols to (wrap lines at) #cols\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000483#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000484#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000485 printf(_
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000486 (" -s [prog] --speller=[prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000487#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000488 printf(_
489 (" -t --tempfile Auto save on exit, don't prompt\n"));
490 printf(_
491 (" -v --view View (read only) mode\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000492#ifndef DISABLE_WRAPPING
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000493 printf(_
494 (" -w --nowrap Don't wrap long lines\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000495#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000496 printf(_
497 (" -x --nohelp Don't show help window\n"));
498 printf(_
499 (" -z --suspend Enable suspend\n"));
500 printf(_
501 (" +LINE Start at line number LINE\n"));
502#else
503 printf(_("Usage: nano [option] +LINE <file>\n\n"));
504 printf(_("Option Meaning\n"));
Chris Allegretta7004c282001-09-22 00:42:10 +0000505#ifndef NANO_SMALL
506 printf(_(" -D Write file in DOS format\n"));
507#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000508#ifdef ENABLE_MULTIBUFFER
509 printf(_(" -F Enable multiple file buffers\n"));
510#endif
Jordi Mallach345a8462002-01-07 11:35:16 +0000511 printf(_(" -K Use alternate keypad routines\n"));
Chris Allegretta8fa1e282001-09-22 04:20:25 +0000512#ifndef NANO_SMALL
513 printf(_(" -M Write file in Mac format\n"));
514#endif
Chris Allegrettae4f940d2002-03-03 22:36:36 +0000515#ifndef DISABLE_JUSTIFY
516 printf(_(" -Q [str] Quoting string, default \"> \"\n"));
517#endif
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000518 printf(_(" -R Use regular expressions for search\n"));
Chris Allegretta3e3ae942001-09-22 19:02:04 +0000519#ifndef NANO_SMALL
520 printf(_(" -S Smooth scrolling\n"));
521#endif
Chris Allegretta48bd3782002-01-03 21:26:34 +0000522 printf(_(" -T [num] Set width of a tab to num\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000523 printf(_(" -V Print version information and exit\n"));
524 printf(_(" -c Constantly show cursor position\n"));
525 printf(_(" -h Show this message\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000526#ifndef NANO_SMALL
Chris Allegrettaff989832001-09-17 13:48:00 +0000527 printf(_(" -i Automatically indent new lines\n"));
Chris Allegretta627de192000-07-12 02:09:17 +0000528 printf(_(" -k Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000529#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000530 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000531 (" -l Don't follow symbolic links, overwrite\n"));
Chris Allegretta84de5522001-04-12 14:51:48 +0000532#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000533#ifdef NCURSES_MOUSE_VERSION
534 printf(_(" -m Enable mouse\n"));
535#endif
536#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000537#ifndef DISABLE_OPERATINGDIR
538 printf(_(" -o [dir] Set operating directory\n"));
539#endif
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +0000540 printf(_(" -p Emulate Pico as closely as possible\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000541
542#ifndef DISABLE_WRAPJUSTIFY
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000543 printf(_
544 (" -r [#cols] Set fill cols to (wrap lines at) #cols\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000545#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000546#ifndef DISABLE_SPELLER
Chris Allegrettad55655f2000-12-27 03:36:47 +0000547 printf(_(" -s [prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000548#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000549 printf(_(" -t Auto save on exit, don't prompt\n"));
550 printf(_(" -v View (read only) mode\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000551#ifndef DISABLE_WRAPPING
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000552 printf(_(" -w Don't wrap long lines\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000553#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000554 printf(_(" -x Don't show help window\n"));
555 printf(_(" -z Enable suspend\n"));
556 printf(_(" +LINE Start at line number LINE\n"));
557#endif
558 exit(0);
559}
560
561void version(void)
562{
Chris Allegrettac46dd812001-02-14 14:28:27 +0000563 printf(_(" GNU nano version %s (compiled %s, %s)\n"),
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000564 VERSION, __TIME__, __DATE__);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000565 printf(_
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000566 (" Email: nano@nano-editor.org Web: http://www.nano-editor.org"));
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000567 printf(_("\n Compiled options:"));
Chris Allegrettaff269f82000-12-01 18:46:01 +0000568
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000569#ifdef NANO_EXTRA
570 printf(" --enable-extra");
Jordi Mallach5285ca92002-01-17 12:40:33 +0000571#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000572#ifdef ENABLE_MULTIBUFFER
573 printf(" --enable-multibuffer");
Jordi Mallach5285ca92002-01-17 12:40:33 +0000574#endif
Chris Allegrettab881d3e2001-04-18 04:34:43 +0000575#ifdef ENABLE_NANORC
576 printf(" --enable-nanorc");
577#endif
Chris Allegretta8ce24132001-04-30 11:28:46 +0000578#ifdef ENABLE_COLOR
579 printf(" --enable-color");
580#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000581
582#ifdef NANO_SMALL
583 printf(" --enable-tiny");
584#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000585#ifdef DISABLE_BROWSER
Chris Allegretta6636dc32001-01-05 05:41:07 +0000586 printf(" --disable-browser");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000587#endif
588#ifdef DISABLE_TABCOMP
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000589 printf(" --disable-tabcomp");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000590#endif
591#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +0000592 printf(" --disable-justify");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000593#endif
594#ifdef DISABLE_SPELLER
Chris Allegretta7b36c522000-12-06 01:08:10 +0000595 printf(" --disable-speller");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000596#endif
597#ifdef DISABLE_HELP
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000598 printf(" --disable-help");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000599#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000600#ifdef DISABLE_MOUSE
601 printf(" --disable-mouse");
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000602#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000603#ifdef DISABLE_OPERATINGDIR
604 printf(" --disable-operatingdir");
605#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000606#endif /* NANO_SMALL */
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000607
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000608#ifdef DISABLE_WRAPPING
609 printf(" --disable-wrapping");
610#endif
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000611#ifdef USE_SLANG
612 printf(" --with-slang");
613#endif
614 printf("\n");
615
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000616}
617
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000618/* Create a new node. This does NOT initialize the data members used
619 only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000620filestruct *make_new_node(filestruct * prevnode)
621{
622 filestruct *newnode;
623
624 newnode = nmalloc(sizeof(filestruct));
625 newnode->data = NULL;
626
627 newnode->prev = prevnode;
628 newnode->next = NULL;
629
630 if (prevnode != NULL)
631 newnode->lineno = prevnode->lineno + 1;
632
633 return newnode;
634}
635
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000636/* Splice a node into an existing filestruct. This does NOT set the data
637 members used only by open_files. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000638void splice_node(filestruct * begin, filestruct * newnode,
639 filestruct * end)
Chris Allegretta7975ed82000-07-28 00:58:35 +0000640{
Chris Allegrettae3167732001-03-18 16:59:34 +0000641 newnode->next = end;
642 newnode->prev = begin;
643 begin->next = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000644 if (end != NULL)
Chris Allegrettae3167732001-03-18 16:59:34 +0000645 end->prev = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000646}
647
Chris Allegrettae3167732001-03-18 16:59:34 +0000648int do_mark(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000649{
650#ifdef NANO_SMALL
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000651 nano_disabled_msg();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000652#else
653 if (!ISSET(MARK_ISSET)) {
654 statusbar(_("Mark Set"));
655 SET(MARK_ISSET);
656 mark_beginbuf = current;
657 mark_beginx = current_x;
658 } else {
659 statusbar(_("Mark UNset"));
660 UNSET(MARK_ISSET);
661 mark_beginbuf = NULL;
662 mark_beginx = 0;
663
664 edit_refresh();
665 }
666#endif
667 return 1;
668}
669
670int no_help(void)
671{
672 if ISSET
673 (NO_HELP)
674 return 2;
675 else
676 return 0;
677}
678
Chris Allegretta3bc8c722000-12-10 17:03:25 +0000679#if defined(DISABLE_JUSTIFY) || defined(DISABLE_SPELLER) || defined(DISABLE_HELP)
Chris Allegrettaff269f82000-12-01 18:46:01 +0000680void nano_disabled_msg(void)
681{
682 statusbar("Sorry, support for this function has been disabled");
683}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000684#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000685
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000686/* The user typed a printable character; add it to the edit buffer */
687void do_char(char ch)
688{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000689 /* magic-line: when a character is inserted on the current magic line,
690 * it means we need a new one! */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000691 if (filebot == current && current->data[0] == '\0') {
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000692 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000693 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000694 }
695
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000696 /* More dangerousness fun =) */
697 current->data = nrealloc(current->data, strlen(current->data) + 2);
698 memmove(&current->data[current_x + 1],
699 &current->data[current_x],
700 strlen(current->data) - current_x + 1);
701 current->data[current_x] = ch;
702 do_right();
703
Chris Allegrettab2cd10d2002-01-20 00:54:42 +0000704#ifdef ENABLE_COLOR
705 edit_refresh();
706#endif
707
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000708#ifndef DISABLE_WRAPPING
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000709 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000710 check_wrap(current, ch);
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000711#endif
712
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000713 set_modified();
714 check_statblank();
715 UNSET(KEEP_CUTBUFFER);
716 totsize++;
717
718}
719
720/* Someone hits return *gasp!* */
721int do_enter(filestruct * inptr)
722{
Chris Allegrettae3167732001-03-18 16:59:34 +0000723 filestruct *newnode;
Chris Allegretta68532c32001-09-17 13:49:33 +0000724 char *tmp;
725#ifndef NANO_SMALL
726 char *spc;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000727 int extra = 0;
Chris Allegretta68532c32001-09-17 13:49:33 +0000728#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000729
Chris Allegrettae3167732001-03-18 16:59:34 +0000730 newnode = make_new_node(inptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000731 tmp = &current->data[current_x];
732 current_x = 0;
733
Chris Allegrettaff989832001-09-17 13:48:00 +0000734#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000735 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
736 if (ISSET(AUTOINDENT)) {
737 spc = current->data;
738 if (spc) {
739 while ((*spc == ' ') || (*spc == '\t')) {
740 extra++;
741 spc++;
742 current_x++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +0000743 totsize++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000744 }
Chris Allegretta88b09152001-05-17 11:35:43 +0000745 newnode->data = charalloc(strlen(tmp) + extra + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000746 strncpy(newnode->data, current->data, extra);
747 strcpy(&newnode->data[extra], tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000748 }
Chris Allegrettaff989832001-09-17 13:48:00 +0000749 } else
750#endif
751 {
Chris Allegretta88b09152001-05-17 11:35:43 +0000752 newnode->data = charalloc(strlen(tmp) + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000753 strcpy(newnode->data, tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000754 }
755 *tmp = 0;
756
Chris Allegrettada721be2000-07-31 01:26:42 +0000757 if (inptr->next == NULL) {
Chris Allegrettae3167732001-03-18 16:59:34 +0000758 filebot = newnode;
759 editbot = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000760 }
Chris Allegrettae3167732001-03-18 16:59:34 +0000761 splice_node(inptr, newnode, inptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000762
763 totsize++;
764 renumber(current);
Chris Allegrettae3167732001-03-18 16:59:34 +0000765 current = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000766 align(&current->data);
767
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000768 /* The logic here is as follows:
769 * -> If we are at the bottom of the buffer, we want to recenter
Chris Allegretta88520c92001-05-05 17:45:54 +0000770 * (read: rebuild) the screen and forcibly move the cursor.
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000771 * -> otherwise, we want simply to redraw the screen and update
772 * where we think the cursor is.
773 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000774 if (current_y == editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +0000775 edit_update(current, CENTER);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000776 reset_cursor();
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000777 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000778 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000779 edit_refresh();
780 update_cursor();
781 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000782
783 totlines++;
784 set_modified();
785
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000786 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000787 return 1;
788}
789
790int do_enter_void(void)
791{
792 return do_enter(current);
793}
794
Chris Allegrettaad3f4782001-10-02 03:54:13 +0000795#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000796void do_next_word(void)
797{
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000798 filestruct *fileptr, *old;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000799 int i;
800
801 if (current == NULL)
802 return;
803
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000804 old = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000805 i = current_x;
806 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
807 if (fileptr == current) {
808 while (isalnum((int) fileptr->data[i])
809 && fileptr->data[i] != 0)
810 i++;
811
812 if (fileptr->data[i] == 0) {
813 i = 0;
814 continue;
815 }
816 }
817 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
818 i++;
819
820 if (fileptr->data[i] != 0)
821 break;
822
823 i = 0;
824 }
825 if (fileptr == NULL)
826 current = filebot;
827 else
828 current = fileptr;
829
830 current_x = i;
831 placewewant = xplustabs();
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000832
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000833 if (current->lineno >= editbot->lineno)
Chris Allegretta234a34d2000-07-29 04:33:38 +0000834 edit_update(current, CENTER);
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000835 else {
836 /* If we've jumped lines, refresh the old line. We can't just use
837 * current->prev here, because we may have skipped over some blank
838 * lines, in which case the previous line is the wrong one.
839 */
840 if (current != old)
841 update_line(old, 0);
842
843 update_line(current, current_x);
844 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000845}
846
847/* the same thing for backwards */
848void do_prev_word(void)
849{
850 filestruct *fileptr, *old;
851 int i;
852
853 if (current == NULL)
854 return;
855
856 old = current;
857 i = current_x;
858 for (fileptr = current; fileptr != NULL; fileptr = fileptr->prev) {
859 if (fileptr == current) {
860 while (isalnum((int) fileptr->data[i])
861 && i != 0)
862 i--;
863
864 if (i == 0) {
865 if (fileptr->prev != NULL)
Chris Allegrettae59fc822001-10-24 18:07:58 +0000866 i = strlen(fileptr->prev->data);
Chris Allegretta878ced32001-10-22 20:05:34 +0000867 else if (fileptr == fileage && filebot != NULL) {
868 current_x = 0;
869 return;
870 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000871 continue;
872 }
873 }
874
875 while (!isalnum((int) fileptr->data[i]) && i != 0)
876 i--;
877
878 if (i > 0) {
879 i--;
880
881 while (isalnum((int) fileptr->data[i]) && i != 0)
882 i--;
883
Chris Allegretta6d0aa9f2001-10-26 15:21:41 +0000884 if (!isalnum((int) fileptr->data[i]))
885 i++;
886
887 if (i != 0 || i != current_x)
Chris Allegretta76e291b2001-10-14 19:05:10 +0000888 break;
889
890 }
891 if (fileptr->prev != NULL)
Chris Allegrettae59fc822001-10-24 18:07:58 +0000892 i = strlen(fileptr->prev->data);
Chris Allegretta878ced32001-10-22 20:05:34 +0000893 else if (fileptr == fileage && filebot != NULL) {
894 current_x = 0;
895 return;
896 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000897 }
898 if (fileptr == NULL)
899 current = fileage;
900 else
901 current = fileptr;
902
903 current_x = i;
904 placewewant = xplustabs();
905
906 if (current->lineno <= edittop->lineno)
907 edit_update(current, CENTER);
908 else {
909 /* If we've jumped lines, refresh the old line. We can't just use
910 * current->prev here, because we may have skipped over some blank
911 * lines, in which case the previous line is the wrong one.
912 */
913 if (current != old)
914 update_line(old, 0);
915
916 update_line(current, current_x);
917 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000918
919}
Chris Allegrettaad3f4782001-10-02 03:54:13 +0000920#endif /* NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000921
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000922#ifndef DISABLE_WRAPPING
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000923void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000924{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000925 int i = 0; /* Index into ->data for line. */
926 int i_tabs = 0; /* Screen position of ->data[i]. */
927 int last_word_end = -1; /* Location of end of last word found. */
928 int current_word_start = -1; /* Location of start of current word. */
929 int current_word_start_t = -1; /* Location of start of current word screen position. */
930 int current_word_end = -1; /* Location of end of current word */
931 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000932 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000933
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000934 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000935 int right = 0;
936 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000937
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000938 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000939
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000940 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000941 if (!isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000942 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000943
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000944 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000945 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000946
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000947 while (!isspace((int) inptr->data[i])
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000948 && inptr->data[i]) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000949 i++;
950 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000951 if (inptr->data[i] < 32)
952 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000953 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000954
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000955 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000956 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000957 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000958 } else {
959 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000960 current_word_end_t = i_tabs - 1;
961 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000962 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000963
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000964 if (inptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000965 if (i_tabs % tabsize != 0);
966 i_tabs += tabsize - (i_tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000967 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000968
Adam Rogoyski09f97962000-06-20 02:50:33 +0000969 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000970 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000971 }
972
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000973 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000974 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000975 * a) one word takes up the whole line with no starting spaces.
976 * - do nothing and return.
977 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000978 * - word starts new line.
979 * - keep white space on original line up to the cursor.
980 * *) cursor is after word at wrap point
981 * - either it's all white space after word, and this routine isn't called.
982 * - or we are actually in case 2 (2 words).
983 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000984 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000985 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000986 * - white space at end of original line is cleared, unless
987 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000988 * b) cursor is at the word at the wrap point.
989 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000990 * - white space on original line is kept to where cursor was.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000991 * c) cursor is past the word at the wrap point.
992 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000993 * - white space at end of original line is cleared
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000994 */
995
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000996 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000997
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000998 /* Category 1a: one word taking up the whole line with no beginning spaces. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000999 if ((last_word_end == -1) && (!isspace((int) inptr->data[0]))) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001000 for (i = current_word_end; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001001 if (!isspace((int) inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001002 current_word_start = i;
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001003 while (!isspace((int) inptr->data[i]) && (i < len)) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001004 i++;
1005 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001006 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001007 current_word_end = i;
1008 break;
1009 }
1010 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001011
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001012 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001013 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001014 return;
1015 }
1016 if (current_x >= last_word_end) {
1017 right = (current_x - current_word_start) + 1;
1018 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001019 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001020 }
1021
Chris Allegretta2084acc2001-11-29 03:43:08 +00001022 /* Subtract length of original line, plus one for the newline, from
1023 totsize. */
1024 totsize -= (strlen(inptr->data) + 1);
1025
Chris Allegretta88b09152001-05-17 11:35:43 +00001026 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001027 strcpy(temp->data, &inptr->data[current_word_start]);
1028 inptr->data = nrealloc(inptr->data, last_word_end + 2);
1029 inptr->data[last_word_end + 1] = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001030
1031 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1032 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
1033
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001034 } else
1035 /* Category 1b: one word on the line and word not taking up whole line
1036 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001037 if (last_word_end == -1) {
Chris Allegretta88b09152001-05-17 11:35:43 +00001038 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001039 strcpy(temp->data, &inptr->data[current_word_start]);
1040
1041 /* Inside word, remove it from original, and move cursor to right spot. */
1042 if (current_x >= current_word_start) {
1043 right = current_x - current_word_start;
Chris Allegretta56214c62001-09-27 02:46:53 +00001044
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001045 current_x = 0;
Chris Allegrettaff989832001-09-17 13:48:00 +00001046#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001047 if (ISSET(AUTOINDENT)) {
1048 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001049 while ((inptr->next->data[i] == ' '
1050 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001051 i++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001052 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001053 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001054#endif
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001055 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001056 }
1057
Chris Allegretta2084acc2001-11-29 03:43:08 +00001058 /* Subtract length of original line, plus one for the newline, from
1059 totsize. */
1060 totsize -= (strlen(inptr->data) + 1);
1061
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001062 null_at(&inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001063
Chris Allegretta2084acc2001-11-29 03:43:08 +00001064 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1065 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
1066
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001067 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
1068 mark_beginbuf = temp;
1069 mark_beginx = 0;
1070 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001071 }
1072
1073 /* Category 2: two or more words on the line. */
1074 else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001075 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001076 if (current_x < current_word_start) {
1077 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001078 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001079 strcpy(temp->data, &inptr->data[current_word_start]);
1080
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001081 if (!isspace((int) input_char)) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001082 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001083
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001084 while (isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001085 i--;
1086 assert(i >= 0);
1087 }
1088 } else if (current_x <= last_word_end)
1089 i = last_word_end - 1;
1090 else
1091 i = current_x;
1092
Chris Allegretta2084acc2001-11-29 03:43:08 +00001093 /* Subtract length of original line, plus one for the newline, from
1094 totsize. */
1095 totsize -= (strlen(inptr->data) + 1);
1096
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001097 inptr->data = nrealloc(inptr->data, i + 2);
1098 inptr->data[i + 1] = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001099
1100 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1101 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
1102
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001103 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001104
1105
1106 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001107 else if ((current_x >= current_word_start)
1108 && (current_x <= (current_word_end + 1))) {
1109 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001110 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001111 strcpy(temp->data, &inptr->data[current_word_start]);
1112
1113 down = 1;
1114
1115 right = current_x - current_word_start;
Chris Allegrettaff989832001-09-17 13:48:00 +00001116#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001117 if (ISSET(AUTOINDENT)) {
1118 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001119 while ((inptr->next->data[i] == ' '
1120 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001121 i++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001122 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001123 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001124#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001125 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001126 current_x = current_word_start;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001127
Chris Allegretta2084acc2001-11-29 03:43:08 +00001128 /* Subtract length of original line, plus one for the newline, from
1129 totsize. */
1130 totsize -= (strlen(inptr->data) + 1);
1131
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001132 null_at(&inptr->data, current_word_start);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001133
Chris Allegretta2084acc2001-11-29 03:43:08 +00001134 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1135 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001136 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001137
1138
1139 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001140 else {
1141 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001142 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001143 strcpy(temp->data, &inptr->data[current_word_start]);
1144
1145 down = 1;
1146 right = current_x - current_word_start;
1147
1148 current_x = current_word_start;
1149 i = current_word_start - 1;
1150
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001151 while (isspace((int) inptr->data[i])) {
Adam Rogoyski3d449b42000-06-19 17:30:14 +00001152 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001153 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001154 }
Chris Allegretta2084acc2001-11-29 03:43:08 +00001155
1156 /* Subtract length of original line, plus one for the newline, from
1157 totsize. */
1158 totsize -= (strlen(inptr->data) + 1);
1159
1160 inptr->data = nrealloc(inptr->data, i + 2);
1161 inptr->data[i + 1] = 0;
1162
1163 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1164 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001165 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001166 }
1167
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001168 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001169 if (ISSET(SAMELINEWRAP) && inptr->next) {
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001170 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001171
Chris Allegretta94a78b82001-03-14 08:28:48 +00001172 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001173 char *p =
Chris Allegretta88b09152001-05-17 11:35:43 +00001174 charalloc((strlen(temp->data) + strlen(inptr->next->data) + 2));
Chris Allegretta94a78b82001-03-14 08:28:48 +00001175
Chris Allegretta56214c62001-09-27 02:46:53 +00001176 /* We're adding to an existing line instead of creating a new
1177 one; decrement totlines here so that when it gets incremented
1178 below, it won't end up being high by one. */
1179 totlines--;
1180
Chris Allegrettaff989832001-09-17 13:48:00 +00001181#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001182 if (ISSET(AUTOINDENT)) {
1183 int non = 0;
1184
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001185 /* Grab the beginning of the next line until it's not a
1186 space or tab, then null terminate it so we can strcat it
1187 to hell */
1188 while ((inptr->next->data[non] == ' '
Chris Allegretta355fbe52001-07-14 19:32:47 +00001189 || inptr->next->data[non] == '\t')) {
1190 p[non] = inptr->next->data[non];
1191 non++;
1192 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001193 p[non] = 0;
1194 strcat(p, temp->data);
1195 strcat(p, " ");
1196
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001197 /* Now tack on the rest of the next line after the spaces and
1198 tabs */
Chris Allegretta94a78b82001-03-14 08:28:48 +00001199 strcat(p, &inptr->next->data[non]);
Chris Allegrettaff989832001-09-17 13:48:00 +00001200 } else
1201#endif
1202 {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001203 strcpy(p, temp->data);
1204 strcat(p, " ");
1205 strcat(p, inptr->next->data);
1206 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001207
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001208 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001209 inptr->next->data = p;
1210
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001211 free(temp->data);
1212 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001213
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001214 current_x = old_x;
1215 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001216 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001217 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001218 else {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001219
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001220 temp->prev = inptr;
1221 temp->next = inptr->next;
1222
1223 if (inptr->next)
1224 inptr->next->prev = temp;
1225 inptr->next = temp;
1226
1227 if (!temp->next)
1228 filebot = temp;
1229
1230 SET(SAMELINEWRAP);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001231
Chris Allegrettaff989832001-09-17 13:48:00 +00001232#ifndef NANO_SMALL
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001233 if (ISSET(AUTOINDENT)) {
1234 char *spc = inptr->data;
1235 char *t = NULL;
1236 int extra = 0;
1237 if (spc) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001238 while ((*spc == ' ') || (*spc == '\t')) {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001239 extra++;
1240 spc++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001241 totsize++;
Chris Allegretta438f7132002-01-16 00:54:47 +00001242 right++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001243 }
Chris Allegretta88b09152001-05-17 11:35:43 +00001244 t = charalloc(strlen(temp->data) + extra + 1);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001245 strncpy(t, inptr->data, extra);
1246 strcpy(t + extra, temp->data);
1247 free(temp->data);
1248 temp->data = t;
1249 }
1250 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001251#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001252 }
1253
1254
1255 totlines++;
Chris Allegretta88520c92001-05-05 17:45:54 +00001256 /* Everything about it makes me want this line here, but it causes
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001257 * totsize to be high by one for some reason. Sigh. (Rob) */
1258 /* totsize++; */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001259
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001260 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001261 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001262
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001263
1264 /* Move the cursor to the new line if appropriate. */
1265 if (down) {
1266 do_right();
1267 }
1268
1269 /* Move the cursor to the correct spot in the line if appropriate. */
1270 while (right--) {
1271 do_right();
1272 }
1273
Chris Allegretta234a34d2000-07-29 04:33:38 +00001274 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001275 reset_cursor();
1276 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001277}
1278
1279/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001280void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001281{
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001282 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001283#ifdef DEBUG
1284 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
1285 inptr->data);
1286#endif
1287
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001288 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001289 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001290 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001291 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001292
1293 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001294 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001295
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001296 while (isspace((int) inptr->data[i]) && inptr->data[i])
Adam Rogoyski09f97962000-06-20 02:50:33 +00001297 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001298
Adam Rogoyski09f97962000-06-20 02:50:33 +00001299 if (!inptr->data[i])
1300 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001301
Adam Rogoyski09f97962000-06-20 02:50:33 +00001302 /* String must be at least 1 character long. */
1303 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001304 if (isspace((int) inptr->data[i])) {
Adam Rogoyski09f97962000-06-20 02:50:33 +00001305 if (!char_found)
1306 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001307 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001308 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001309 } else
1310 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001311 }
Adam Rogoyski09f97962000-06-20 02:50:33 +00001312
1313 if (char_found == 2)
1314 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001315 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001316}
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001317#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001318
1319/* Stuff we do when we abort from programs and want to clean up the
Chris Allegretta88520c92001-05-05 17:45:54 +00001320 * screen. This doesn't do much right now.
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001321 */
1322void do_early_abort(void)
1323{
1324 blank_statusbar_refresh();
1325}
1326
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001327int do_backspace(void)
1328{
1329 filestruct *previous, *tmp;
1330
1331 if (current_x != 0) {
1332 /* Let's get dangerous */
1333 memmove(&current->data[current_x - 1], &current->data[current_x],
1334 strlen(current->data) - current_x + 1);
1335#ifdef DEBUG
1336 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
1337#endif
1338 align(&current->data);
1339 do_left();
1340 } else {
1341 if (current == fileage)
1342 return 0; /* Can't delete past top of file */
1343
1344 previous = current->prev;
1345 current_x = strlen(previous->data);
1346 previous->data = nrealloc(previous->data,
1347 strlen(previous->data) +
1348 strlen(current->data) + 1);
1349 strcat(previous->data, current->data);
1350
1351 tmp = current;
1352 unlink_node(current);
1353 delete_node(current);
1354 if (current == edittop) {
1355 if (previous->next)
1356 current = previous->next;
1357 else
1358 current = previous;
Chris Allegretta3e3ae942001-09-22 19:02:04 +00001359 page_up();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001360 } else {
1361 if (previous->next)
1362 current = previous->next;
1363 else
1364 current = previous;
1365 update_line(current, current_x);
1366 }
1367
1368 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001369 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001370 filebot = current;
1371 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001372
1373 /* Recreate the magic line if we're deleting it AND if the
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001374 line we're on now is NOT blank. if it is blank we
1375 can just use IT for the magic line. This is how Pico
1376 appears to do it, in any case */
Chris Allegretta28a0f892000-07-05 22:47:54 +00001377 if (strcmp(current->data, "")) {
1378 new_magicline();
1379 fix_editbot();
1380 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001381 }
1382
1383 current = previous;
1384 renumber(current);
1385 previous_line();
1386 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001387#ifdef DEBUG
1388 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
1389#endif
1390
1391 }
1392
1393 totsize--;
1394 set_modified();
1395 UNSET(KEEP_CUTBUFFER);
1396 edit_refresh();
1397 return 1;
1398}
1399
1400int do_delete(void)
1401{
1402 filestruct *foo;
1403
Chris Allegretta2084acc2001-11-29 03:43:08 +00001404 /* blbf -> blank line before filebot (see below) */
1405 int blbf = 0;
1406
1407 if (current->next == filebot && !strcmp(current->data, ""))
1408 blbf = 1;
1409
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001410 if (current_x != strlen(current->data)) {
1411 /* Let's get dangerous */
1412 memmove(&current->data[current_x], &current->data[current_x + 1],
1413 strlen(current->data) - current_x);
1414
1415 align(&current->data);
1416
Chris Allegretta2084acc2001-11-29 03:43:08 +00001417 /* Now that we have a magic line again, we can check for both being
1418 on the line before filebot as well as at filebot; it's a special
1419 case if we're on the line before filebot and it's blank, since we
1420 should be able to delete it */
1421 } else if (current->next != NULL && (current->next != filebot || blbf)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001422 current->data = nrealloc(current->data,
1423 strlen(current->data) +
1424 strlen(current->next->data) + 1);
1425 strcat(current->data, current->next->data);
1426
1427 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001428 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001429 filebot = current;
1430 editbot = current;
1431 }
1432
1433 unlink_node(foo);
1434 delete_node(foo);
1435 update_line(current, current_x);
1436
Chris Allegretta4ed13152001-02-10 17:50:50 +00001437 /* Please see the comment in do_backspace if you don't understand
Chris Allegretta28a0f892000-07-05 22:47:54 +00001438 this test */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001439 if (current == filebot && strcmp(current->data, "")) {
Chris Allegretta28a0f892000-07-05 22:47:54 +00001440 new_magicline();
1441 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001442 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001443 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001444 renumber(current);
1445 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001446 } else
1447 return 0;
1448
1449 totsize--;
1450 set_modified();
1451 UNSET(KEEP_CUTBUFFER);
1452 edit_refresh();
1453 return 1;
1454}
1455
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001456void wrap_reset(void)
1457{
1458 UNSET(SAMELINEWRAP);
1459}
1460
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001461#ifndef DISABLE_SPELLER
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001462
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001463int do_int_spell_fix(char *word)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001464{
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001465 char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001466 filestruct *begin;
Chris Allegretta23b74b22002-01-21 20:32:22 +00001467 int i = 0, j = 0, beginx, beginx_top, reverse_search_set;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001468
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001469 /* save where we are */
1470 begin = current;
1471 beginx = current_x + 1;
1472
Chris Allegretta23b74b22002-01-21 20:32:22 +00001473 /* Make sure Spell Check goes forward only */
1474 reverse_search_set = ISSET(REVERSE_SEARCH);
1475 UNSET(REVERSE_SEARCH);
1476
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001477 /* save the current search/replace strings */
1478 search_init_globals();
1479 save_search = mallocstrcpy(save_search, last_search);
1480 save_replace = mallocstrcpy(save_replace, last_replace);
1481
1482 /* set search/replace strings to mis-spelt word */
1483 prevanswer = mallocstrcpy(prevanswer, word);
1484 last_search = mallocstrcpy(last_search, word);
1485 last_replace = mallocstrcpy(last_replace, word);
1486
1487 /* start from the top of file */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001488 current = fileage;
1489 current_x = beginx_top = -1;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001490
1491 search_last_line = FALSE;
1492
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001493 edit_update(fileage, TOP);
1494
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001495 while (1) {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001496
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001497 /* make sure word is still mis-spelt (i.e. when multi-errors) */
1498 if (findnextstr(TRUE, FALSE, fileage, beginx_top, prevanswer) != NULL) {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001499
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001500 /* find wholewords only */
1501 if (!is_whole_word(current_x, current, prevanswer))
1502 continue;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001503
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001504 do_replace_highlight(TRUE, prevanswer);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001505
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001506 /* allow replace word to be corrected */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001507 i = statusq(0, spell_list, last_replace, _("Edit a replacement"));
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001508
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001509 do_replace_highlight(FALSE, prevanswer);
1510
1511 /* start from the start of this line again */
1512 current = fileage;
1513 current_x = beginx_top;
1514
1515 search_last_line = FALSE;
1516
1517 if (strcmp(prevanswer,answer) != 0) {
1518 j = i;
1519 do_replace_loop(prevanswer, fileage, &beginx_top, TRUE, &j);
1520 }
Chris Allegretta80838272001-12-02 06:03:22 +00001521 }
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001522
1523 break;
Rocco Corsi562964d2002-01-13 03:18:03 +00001524 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001525
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001526 /* restore the search/replace strings */
1527 last_search = mallocstrcpy(last_search, save_search);
1528 last_replace = mallocstrcpy(last_replace, save_replace);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001529
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001530 /* restore where we were */
1531 current = begin;
1532 current_x = beginx - 1;
1533
Chris Allegretta23b74b22002-01-21 20:32:22 +00001534 /* restore Search/Replace direction */
1535 if (reverse_search_set)
1536 SET(REVERSE_SEARCH);
1537
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001538 edit_update(current, CENTER);
1539
1540 if (i == -1)
1541 return FALSE;
1542
1543 return TRUE;
1544}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001545
1546/* Integrated spell checking using 'spell' program */
Chris Allegretta271e9722000-11-10 18:15:43 +00001547int do_int_speller(char *tempfile_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001548{
Chris Allegretta271e9722000-11-10 18:15:43 +00001549 char *read_buff, *read_buff_ptr, *read_buff_word;
1550 long pipe_buff_size;
1551 int in_fd[2], tempfile_fd;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001552 int spell_status;
1553 pid_t pid_spell;
1554 ssize_t bytesread;
1555
Chris Allegretta271e9722000-11-10 18:15:43 +00001556 /* Create a pipe to spell program */
1557
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001558 if (pipe(in_fd) == -1)
1559 return FALSE;
1560
Chris Allegretta271e9722000-11-10 18:15:43 +00001561 /* A new process to run spell in */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001562
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001563 if ((pid_spell = fork()) == 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001564
1565 /* Child continues, (i.e. future spell process) */
1566
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001567 close(in_fd[0]);
1568
Chris Allegretta271e9722000-11-10 18:15:43 +00001569 /* replace the standard in with the tempfile */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001570
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001571 if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001572
1573 close(in_fd[1]);
1574 exit(1);
1575 }
1576
1577 if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
1578
1579 close(tempfile_fd);
1580 close(in_fd[1]);
1581 exit(1);
1582 }
1583 close(tempfile_fd);
1584
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001585
Chris Allegretta271e9722000-11-10 18:15:43 +00001586 /* send spell's standard out to the pipe */
1587
1588 if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1589
1590 close(in_fd[1]);
1591 exit(1);
1592 }
1593 close(in_fd[1]);
1594
1595 /* Start spell program, we are using the PATH here!?!? */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001596 execlp("spell", "spell", NULL);
1597
Chris Allegretta271e9722000-11-10 18:15:43 +00001598 /* Should not be reached, if spell is found!!! */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001599
Chris Allegretta271e9722000-11-10 18:15:43 +00001600 exit(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001601 }
1602
1603 /* Parent continues here */
1604
Chris Allegretta271e9722000-11-10 18:15:43 +00001605 close(in_fd[1]);
1606
1607 /* Child process was not forked successfully */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001608
1609 if (pid_spell < 0) {
1610
Chris Allegretta271e9722000-11-10 18:15:43 +00001611 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001612 return FALSE;
1613 }
1614
Chris Allegretta271e9722000-11-10 18:15:43 +00001615 /* Get system pipe buffer size */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001616
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001617 if ((pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001618
Chris Allegretta271e9722000-11-10 18:15:43 +00001619 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001620 return FALSE;
Chris Allegretta271e9722000-11-10 18:15:43 +00001621 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001622
Chris Allegretta88b09152001-05-17 11:35:43 +00001623 read_buff = charalloc(pipe_buff_size + 1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001624
Chris Allegretta271e9722000-11-10 18:15:43 +00001625 /* Process the returned spelling errors */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001626
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001627 while ((bytesread = read(in_fd[0], read_buff, pipe_buff_size)) > 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001628
Chris Allegretta271e9722000-11-10 18:15:43 +00001629 read_buff[bytesread] = (char) NULL;
1630 read_buff_word = read_buff_ptr = read_buff;
1631
1632 while (*read_buff_ptr != (char) NULL) {
1633
1634 /* Windows version may need to process additional char '\r' */
1635
1636 /* Possible problem here if last word not followed by '\n' */
1637
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001638 if (*read_buff_ptr == '\n') {
Chris Allegretta271e9722000-11-10 18:15:43 +00001639 *read_buff_ptr = (char) NULL;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001640 if (!do_int_spell_fix(read_buff_word)) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001641
1642 close(in_fd[0]);
1643 free(read_buff);
1644 replace_abort();
1645
1646 return TRUE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001647 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001648 read_buff_word = read_buff_ptr;
1649 read_buff_word++;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001650 }
1651
1652 read_buff_ptr++;
1653 }
1654 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001655
1656 close(in_fd[0]);
1657 free(read_buff);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001658 replace_abort();
1659
Chris Allegretta271e9722000-11-10 18:15:43 +00001660 /* Process end of spell process */
1661
1662 wait(&spell_status);
1663 if (WIFEXITED(spell_status)) {
1664 if (WEXITSTATUS(spell_status) != 0)
1665 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001666 } else
Chris Allegretta271e9722000-11-10 18:15:43 +00001667 return FALSE;
1668
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001669 return TRUE;
1670}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001671
1672/* External spell checking */
Chris Allegretta271e9722000-11-10 18:15:43 +00001673int do_alt_speller(char *file_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001674{
Chris Allegrettab3655b42001-10-22 03:15:31 +00001675 int alt_spell_status, lineno_cur = current->lineno;
1676 int x_cur = current_x, y_cur = current_y, pww_cur = placewewant;
1677
Chris Allegretta271e9722000-11-10 18:15:43 +00001678 pid_t pid_spell;
Chris Allegretta169ee842001-01-26 01:57:32 +00001679 char *ptr;
1680 static int arglen = 3;
1681 static char **spellargs = (char **) NULL;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001682
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001683 endwin();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001684
Chris Allegrettae434b452001-01-27 19:25:00 +00001685 /* Set up an argument list to pass the execvp function */
1686 if (spellargs == NULL) {
1687 spellargs = nmalloc(arglen * sizeof(char *));
Chris Allegretta271e9722000-11-10 18:15:43 +00001688
Chris Allegrettae434b452001-01-27 19:25:00 +00001689 spellargs[0] = strtok(alt_speller, " ");
1690 while ((ptr = strtok(NULL, " ")) != NULL) {
1691 arglen++;
1692 spellargs = nrealloc(spellargs, arglen * sizeof(char *));
1693 spellargs[arglen - 3] = ptr;
Chris Allegretta169ee842001-01-26 01:57:32 +00001694 }
Chris Allegrettae434b452001-01-27 19:25:00 +00001695 spellargs[arglen - 1] = NULL;
1696 }
1697 spellargs[arglen - 2] = file_name;
1698
1699 /* Start a new process for the alternate speller */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001700 if ((pid_spell = fork()) == 0) {
Chris Allegretta169ee842001-01-26 01:57:32 +00001701
Chris Allegretta88520c92001-05-05 17:45:54 +00001702 /* Start alternate spell program; we are using the PATH here!?!? */
Chris Allegretta169ee842001-01-26 01:57:32 +00001703 execvp(spellargs[0], spellargs);
Chris Allegretta271e9722000-11-10 18:15:43 +00001704
1705 /* Should not be reached, if alternate speller is found!!! */
1706
1707 exit(1);
1708 }
1709
1710 /* Could not fork?? */
1711
1712 if (pid_spell < 0)
1713 return FALSE;
1714
1715 /* Wait for alternate speller to complete */
1716
1717 wait(&alt_spell_status);
1718 if (WIFEXITED(alt_spell_status)) {
1719 if (WEXITSTATUS(alt_spell_status) != 0)
1720 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001721 } else
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001722 return FALSE;
1723
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001724 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001725 free_filestruct(fileage);
Chris Allegretta56214c62001-09-27 02:46:53 +00001726 global_init(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001727 open_file(file_name, 0, 1);
Rocco Corsi4dfaf932001-04-20 01:59:55 +00001728
Chris Allegretta1b3381b2001-09-28 21:59:01 +00001729 /* go back to the old position, mark the file as modified, and make
1730 sure that the titlebar is refreshed */
1731 do_gotopos(lineno_cur, x_cur, y_cur, pww_cur);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001732 set_modified();
Chris Allegrettae1f14522001-09-19 03:19:43 +00001733 clearok(topwin, FALSE);
1734 titlebar(NULL);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001735
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001736 return TRUE;
1737}
1738#endif
1739
1740int do_spell(void)
1741{
1742
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001743#ifdef DISABLE_SPELLER
Chris Allegrettaff269f82000-12-01 18:46:01 +00001744 nano_disabled_msg();
1745 return (TRUE);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001746#else
Chris Allegretta271e9722000-11-10 18:15:43 +00001747 char *temp;
1748 int spell_res;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001749
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001750 if ((temp = safe_tempnam(0, "nano.")) == NULL) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001751 statusbar(_("Could not create a temporary filename: %s"),
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001752 strerror(errno));
Chris Allegretta271e9722000-11-10 18:15:43 +00001753 return 0;
1754 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001755
Chris Allegrettaecc3d7f2001-06-05 23:24:55 +00001756 if (write_file(temp, 1, 0, 0) == -1) {
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001757 statusbar(_("Spell checking failed: unable to write temp file!"));
Chris Allegretta271e9722000-11-10 18:15:43 +00001758 return 0;
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001759 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001760
Chris Allegrettae1f14522001-09-19 03:19:43 +00001761#ifdef ENABLE_MULTIBUFFER
1762 /* update the current open_files entry before spell-checking, in case
1763 any problems occur; the case of there being no open_files entries
Chris Allegretta48b06702002-02-22 04:30:50 +00001764 is handled elsewhere (before we reach this point) */
1765 add_open_file(1);
Chris Allegrettae1f14522001-09-19 03:19:43 +00001766#endif
1767
Chris Allegretta271e9722000-11-10 18:15:43 +00001768 if (alt_speller)
1769 spell_res = do_alt_speller(temp);
1770 else
1771 spell_res = do_int_speller(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001772
Chris Allegretta271e9722000-11-10 18:15:43 +00001773 remove(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001774
1775 if (spell_res)
1776 statusbar(_("Finished checking spelling"));
1777 else
1778 statusbar(_("Spell checking failed"));
1779
1780 return spell_res;
1781
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001782#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001783}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001784
1785int do_exit(void)
1786{
1787 int i;
1788
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001789 if (!ISSET(MODIFIED)) {
1790
Chris Allegretta355fbe52001-07-14 19:32:47 +00001791#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001792 if (!close_open_file()) {
1793 display_main_list();
1794 return 1;
1795 }
1796 else
1797#endif
1798
1799 finish(0);
1800 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001801
Chris Allegretta30885552000-07-14 01:20:12 +00001802 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001803 i = 1;
1804 } else {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001805 i = do_yesno(0, 0,
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001806 _
1807 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1808 }
1809
1810#ifdef DEBUG
1811 dump_buffer(fileage);
1812#endif
1813
1814 if (i == 1) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001815 if (do_writeout(filename, 1, 0) > 0) {
1816
Chris Allegretta355fbe52001-07-14 19:32:47 +00001817#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001818 if (!close_open_file()) {
1819 display_main_list();
1820 return 1;
1821 }
1822 else
1823#endif
1824
1825 finish(0);
1826 }
1827 } else if (i == 0) {
1828
Chris Allegretta355fbe52001-07-14 19:32:47 +00001829#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001830 if (!close_open_file()) {
1831 display_main_list();
1832 return 1;
1833 }
1834 else
1835#endif
1836
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001837 finish(0);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001838 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001839 statusbar(_("Cancelled"));
1840
1841 display_main_list();
1842 return 1;
1843}
1844
Chris Allegretta84de5522001-04-12 14:51:48 +00001845#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001846#ifdef NCURSES_MOUSE_VERSION
1847void do_mouse(void)
1848{
1849 MEVENT mevent;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001850 int foo = 0, tab_found = 0;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001851 int currslen;
Chris Allegretta40639dd2002-03-04 12:25:34 +00001852 shortcut *s = currshortcut;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001853
1854 if (getmouse(&mevent) == ERR)
1855 return;
1856
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001857 /* If mouse not in edit or bottom window, return */
1858 if (wenclose(edit, mevent.y, mevent.x)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001859
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001860 /* Don't let people screw with the marker when they're in a
1861 subfunction */
1862 if (currshortcut != main_list)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001863 return;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001864
1865 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1866 mevent.y -= 2;
1867
1868 /* Selecting where the cursor is sets the mark.
1869 * Selecting beyond the line length with the cursor at the end of the
1870 * line sets the mark as well.
1871 */
1872 if ((mevent.y == current_y) &&
1873 ((mevent.x == current_x) || (current_x == strlen(current->data)
1874 && (mevent.x >
1875 strlen(current->data))))) {
1876 if (ISSET(VIEW_MODE)) {
1877 print_view_warning();
1878 return;
1879 }
1880 do_mark();
1881 } else if (mevent.y > current_y) {
1882 while (mevent.y > current_y) {
1883 if (current->next != NULL)
1884 current = current->next;
1885 else
1886 break;
1887 current_y++;
1888 }
1889 } else if (mevent.y < current_y) {
1890 while (mevent.y < current_y) {
1891 if (current->prev != NULL)
1892 current = current->prev;
1893 else
1894 break;
1895 current_y--;
1896 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001897 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001898 current_x = mevent.x;
1899 placewewant = current_x;
1900 while (foo < current_x) {
1901 if (current->data[foo] == NANO_CONTROL_I) {
1902 current_x -= tabsize - (foo % tabsize);
1903 tab_found = 1;
1904 } else if (current->data[foo] & 0x80);
1905 else if (current->data[foo] < 32)
1906 current_x--;
1907 foo++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001908 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001909 /* This is where tab_found comes in. I can't figure out why,
1910 * but without it any line with a tab will place the cursor
1911 * one character behind. Whatever, this fixes it. */
1912 if (tab_found == 1)
1913 current_x++;
1914
1915 if (current_x > strlen(current->data))
1916 current_x = strlen(current->data);
1917
1918 update_cursor();
1919 edit_refresh();
1920 } else if (wenclose(bottomwin, mevent.y, mevent.x) && !ISSET(NO_HELP)) {
Chris Allegrettaa951f212001-09-27 21:07:39 +00001921
Chris Allegretta40639dd2002-03-04 12:25:34 +00001922 int i, k;
Chris Allegrettaa951f212001-09-27 21:07:39 +00001923
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001924 if (currshortcut == main_list)
1925 currslen = MAIN_VISIBLE;
1926 else
1927 currslen = length_of_list(currshortcut);
1928
Chris Allegrettaa951f212001-09-27 21:07:39 +00001929 if (currslen < 2)
1930 k = COLS / 6;
1931 else
1932 k = COLS / ((currslen + (currslen %2)) / 2);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001933
1934 /* Determine what shortcut list was clicked */
1935 mevent.y -= (editwinrows + 3);
1936
1937 if (mevent.y < 0) /* They clicked on the statusbar */
1938 return;
1939
1940 /* Don't select stuff beyond list length */
1941 if (mevent.x / k >= currslen)
1942 return;
1943
Chris Allegretta40639dd2002-03-04 12:25:34 +00001944 for (i = 0; i < (mevent.x / k) * 2 + mevent.y; i++)
1945 s = s->next;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001946
1947 /* And ungetch that value */
Chris Allegretta40639dd2002-03-04 12:25:34 +00001948 ungetch(s->val);
Chris Allegretta6414b402001-09-21 03:21:11 +00001949
1950 /* And if it's an alt-key sequence, we should probably send alt
1951 too ;-) */
Chris Allegretta40639dd2002-03-04 12:25:34 +00001952 if (s->val >= 'a' && s->val <= 'z')
Chris Allegretta6414b402001-09-21 03:21:11 +00001953 ungetch(27);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001954 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001955}
1956#endif
1957#endif
1958
1959/* Handler for SIGHUP */
1960RETSIGTYPE handle_hup(int signal)
1961{
Chris Allegrettae7a58932000-12-02 02:36:22 +00001962 die(_("Received SIGHUP"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001963}
1964
Chris Allegretta18f8be02000-09-04 03:20:38 +00001965/* What do we do when we catch the suspend signal */
1966RETSIGTYPE do_suspend(int signal)
1967{
Chris Allegretta18f8be02000-09-04 03:20:38 +00001968 endwin();
Chris Allegretta521e00d2001-06-28 16:52:52 +00001969 printf("\n\n\n\n\nUse \"fg\" to return to nano\n");
1970 fflush(stdout);
1971
Chris Allegretta7b0667f2002-01-10 12:44:21 +00001972 /* Restore the terminal settings for the disabled keys */
1973 tcsetattr(0, TCSANOW, &oldterm);
1974
Chris Allegretta521e00d2001-06-28 16:52:52 +00001975 /* We used to re-enable the default SIG_DFL and raise SIGTSTP, but
1976 then we could be (and were) interrupted in the middle of the call.
1977 So we do it the mutt way instead */
1978 kill(0, SIGSTOP);
Chris Allegretta18f8be02000-09-04 03:20:38 +00001979}
1980
1981/* Restore the suspend handler when we come back into the prog */
1982RETSIGTYPE do_cont(int signal)
1983{
1984
Chris Allegretta521e00d2001-06-28 16:52:52 +00001985 /* Now we just update the screen instead of having to reenable the
1986 SIGTSTP handler */
1987
Chris Allegretta521e00d2001-06-28 16:52:52 +00001988 doupdate();
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00001989 /* The Hurd seems to need this, otherwise a ^Y after a ^Z will
1990 start suspending again */
1991 signal_init();
Chris Allegretta18f8be02000-09-04 03:20:38 +00001992}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001993
1994void handle_sigwinch(int s)
1995{
1996#ifndef NANO_SMALL
1997 char *tty = NULL;
1998 int fd = 0;
1999 int result = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002000 struct winsize win;
2001
2002 tty = ttyname(0);
2003 if (!tty)
2004 return;
2005 fd = open(tty, O_RDWR);
2006 if (fd == -1)
2007 return;
2008 result = ioctl(fd, TIOCGWINSZ, &win);
2009 if (result == -1)
2010 return;
2011
2012
2013 COLS = win.ws_col;
2014 LINES = win.ws_row;
2015
Chris Allegrettae61e8302001-01-14 05:18:27 +00002016 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
2017 die_too_small();
2018
Chris Allegretta6fe61492001-05-21 12:56:25 +00002019#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettae61e8302001-01-14 05:18:27 +00002020 if ((fill = COLS - CHARS_FROM_EOL) < MIN_FILL_LENGTH)
2021 die_too_small();
Chris Allegretta6fe61492001-05-21 12:56:25 +00002022#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002023
Chris Allegretta0a06e072001-01-23 02:35:04 +00002024 hblank = nrealloc(hblank, COLS + 1);
2025 memset(hblank, ' ', COLS);
2026 hblank[COLS] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002027
Chris Allegretta618f5d72001-02-16 04:48:30 +00002028#ifdef HAVE_RESIZETERM
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002029 resizeterm(LINES, COLS);
2030#ifdef HAVE_WRESIZE
2031 if (wresize(topwin, 2, COLS) == ERR)
2032 die(_("Cannot resize top win"));
2033 if (mvwin(topwin, 0, 0) == ERR)
2034 die(_("Cannot move top win"));
2035 if (wresize(edit, editwinrows, COLS) == ERR)
2036 die(_("Cannot resize edit win"));
2037 if (mvwin(edit, 2, 0) == ERR)
2038 die(_("Cannot move edit win"));
2039 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
2040 die(_("Cannot resize bottom win"));
2041 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
2042 die(_("Cannot move bottom win"));
2043#endif /* HAVE_WRESIZE */
Chris Allegretta618f5d72001-02-16 04:48:30 +00002044#endif /* HAVE_RESIZETERM */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002045
Robert Siemborskidd53ec22000-07-04 02:35:19 +00002046 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002047
Chris Allegrettabceb1b22000-06-19 04:22:15 +00002048 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00002049 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002050 }
2051 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00002052
2053 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002054 refresh();
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002055 titlebar(NULL);
Chris Allegretta97accc62000-06-19 05:45:52 +00002056 edit_refresh();
2057 display_main_list();
Chris Allegretta08020882001-01-29 23:37:54 +00002058 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002059 total_refresh();
Chris Allegretta08020882001-01-29 23:37:54 +00002060
Chris Allegretta4e90c402001-01-29 23:40:43 +00002061 /* Turn cursor back on for sure */
2062 curs_set(1);
2063
Chris Allegretta08020882001-01-29 23:37:54 +00002064 /* Jump back to mainloop */
2065 siglongjmp(jmpbuf, 1);
2066
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002067#endif
2068}
2069
Chris Allegretta756f2202000-09-01 13:32:47 +00002070void signal_init(void)
2071{
Chris Allegrettaac899e52001-06-30 04:09:09 +00002072#ifdef _POSIX_VDISABLE
2073 struct termios term;
2074#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002075
Chris Allegretta88520c92001-05-05 17:45:54 +00002076 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
Chris Allegretta756f2202000-09-01 13:32:47 +00002077 memset(&act, 0, sizeof(struct sigaction));
2078 act.sa_handler = SIG_IGN;
2079 sigaction(SIGINT, &act, NULL);
Chris Allegretta756f2202000-09-01 13:32:47 +00002080
Chris Allegretta88520c92001-05-05 17:45:54 +00002081 /* Trap SIGHUP cuz we want to write the file out. */
Chris Allegretta756f2202000-09-01 13:32:47 +00002082 act.sa_handler = handle_hup;
2083 sigaction(SIGHUP, &act, NULL);
2084
2085 act.sa_handler = handle_sigwinch;
2086 sigaction(SIGWINCH, &act, NULL);
2087
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002088
2089#ifdef _POSIX_VDISABLE
2090 tcgetattr(0, &term);
2091
2092#ifdef VDSUSP
2093 term.c_cc[VDSUSP] = _POSIX_VDISABLE;
2094#endif /* VDSUSP */
2095
2096#endif /* _POSIX_VDISABLE */
2097
Chris Allegretta521e00d2001-06-28 16:52:52 +00002098 if (!ISSET(SUSPEND)) {
Chris Allegrettaac899e52001-06-30 04:09:09 +00002099
2100/* Insane! */
2101#ifdef _POSIX_VDISABLE
Chris Allegrettaac899e52001-06-30 04:09:09 +00002102 term.c_cc[VSUSP] = _POSIX_VDISABLE;
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002103#else
Chris Allegrettaac899e52001-06-30 04:09:09 +00002104 act.sa_handler = SIG_IGN;
Chris Allegretta521e00d2001-06-28 16:52:52 +00002105 sigaction(SIGTSTP, &act, NULL);
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002106#endif
Chris Allegrettaac899e52001-06-30 04:09:09 +00002107
Chris Allegretta521e00d2001-06-28 16:52:52 +00002108 } else {
2109 /* if we don't do this, it seems other stuff interrupts the
2110 suspend handler! Try using nano with mutt without this line */
2111 sigfillset(&act.sa_mask);
2112
2113 act.sa_handler = do_suspend;
2114 sigaction(SIGTSTP, &act, NULL);
2115
2116 act.sa_handler = do_cont;
2117 sigaction(SIGCONT, &act, NULL);
2118 }
2119
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002120
2121#ifdef _POSIX_VDISABLE
2122 tcsetattr(0, TCSANOW, &term);
2123#endif
2124
2125
Chris Allegretta756f2202000-09-01 13:32:47 +00002126}
2127
Chris Allegretta2a42af12000-09-12 23:02:49 +00002128void window_init(void)
2129{
Chris Allegrettae61e8302001-01-14 05:18:27 +00002130 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
2131 die_too_small();
Chris Allegretta92c9dd22000-09-13 14:03:27 +00002132
Chris Allegretta88520c92001-05-05 17:45:54 +00002133 /* Set up the main text window */
Chris Allegretta2a42af12000-09-12 23:02:49 +00002134 edit = newwin(editwinrows, COLS, 2, 0);
2135
2136 /* And the other windows */
2137 topwin = newwin(2, COLS, 0, 0);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002138 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002139
Chris Allegretta155d6202001-01-08 01:50:37 +00002140#ifdef PDCURSES
2141 /* Oops, I guess we need this again.
2142 Moved here so the keypad still works after a Meta-X, for example */
2143 keypad(edit, TRUE);
2144 keypad(bottomwin, TRUE);
2145#endif
2146
Chris Allegretta2a42af12000-09-12 23:02:49 +00002147}
2148
Chris Allegretta756f2202000-09-01 13:32:47 +00002149void mouse_init(void)
2150{
Chris Allegretta84de5522001-04-12 14:51:48 +00002151#ifndef DISABLE_MOUSE
Chris Allegretta756f2202000-09-01 13:32:47 +00002152#ifdef NCURSES_MOUSE_VERSION
2153 if (ISSET(USE_MOUSE)) {
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002154 keypad_on(edit, 1);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002155 keypad_on(bottomwin, 1);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002156
Chris Allegretta756f2202000-09-01 13:32:47 +00002157 mousemask(BUTTON1_RELEASED, NULL);
2158 mouseinterval(50);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00002159
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002160 } else
Chris Allegretta756f2202000-09-01 13:32:47 +00002161 mousemask(0, NULL);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002162
Chris Allegretta756f2202000-09-01 13:32:47 +00002163#endif
2164#endif
2165
2166}
2167
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002168int do_tab(void)
2169{
2170 do_char('\t');
2171 return 1;
2172}
2173
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002174#ifndef DISABLE_JUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002175int empty_line(const char *data)
2176{
2177 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002178 if (!isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002179 return 0;
2180
2181 data++;
2182 }
2183
2184 return 1;
2185}
2186
2187int no_spaces(const char *data)
2188{
2189 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002190 if (isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002191 return 0;
2192
2193 data++;
2194 }
2195
2196 return 1;
2197}
2198
2199void justify_format(char *data)
2200{
2201 int i = 0;
2202 int len = strlen(data);
2203
2204 /* Skip first character regardless and leading whitespace. */
2205 for (i = 1; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002206 if (!isspace((int) data[i]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002207 break;
2208 }
2209
2210 i++; /* (i) is now at least 2. */
2211
2212 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
2213 for (; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002214 if (isspace((int) data[i]) && isspace((int) data[i - 1])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002215 && (data[i - 2] != '.')) {
2216 memmove(data + i, data + i + 1, len - i);
2217 len--;
2218 i--;
2219 }
2220 }
2221}
2222#endif
2223
2224int do_justify(void)
2225{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002226#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +00002227 nano_disabled_msg();
2228 return 1;
2229#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002230 int slen = 0; /* length of combined lines on one line. */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002231 int initial_y, kbinput = 0, totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002232 filestruct *initial = NULL, *tmpjust = NULL, *cutbak, *tmptop, *tmpbot;
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002233 filestruct *samecheck = current;
2234 int qdepth = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002235
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002236 /* Compute quote depth level */
2237 while (!strncmp(&current->data[qdepth], quotestr, strlen(quotestr)))
2238 qdepth += strlen(quotestr);
2239
2240 if (empty_line(&current->data[qdepth])) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002241 /* Justify starting at first non-empty line. */
2242 do {
2243 if (!current->next)
2244 return 1;
2245
2246 current = current->next;
2247 current_y++;
2248 }
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002249 while (strlen(current->data) >= qdepth
2250 && !strncmp(current->data, samecheck->data, qdepth)
2251 && empty_line(&current->data[qdepth]));
2252
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002253 } else {
2254 /* Search back for the beginning of the paragraph, where
2255 * Paragraph is 1) A line with leading whitespace
2256 * or 2) A line following an empty line.
2257 */
2258 while (current->prev != NULL) {
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002259 if (strncmp(current->data, samecheck->data, qdepth)
2260
2261 /* Don't keep going back if the previous line is more
2262 intented quotestr-wise than samecheck */
2263 || !strncmp(&current->data[qdepth], quotestr, strlen(quotestr))
2264 || isspace((int) current->data[qdepth])
2265 || empty_line(&current->data[qdepth]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002266 break;
2267
2268 current = current->prev;
2269 current_y--;
2270 }
2271
2272 /* First line with leading whitespace may be empty. */
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002273 if (strncmp(current->data, samecheck->data, qdepth)
2274 || !strncmp(&current->data[qdepth], quotestr, strlen(quotestr))
2275 || empty_line(&current->data[qdepth])) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002276 if (current->next) {
2277 current = current->next;
2278 current_y++;
2279 } else
2280 return 1;
2281 }
2282 }
2283 initial = current;
2284 initial_y = current_y;
2285
2286 set_modified();
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002287 cutbak = cutbuffer; /* Got to like cutbak ;) */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002288 totbak = totsize;
Chris Allegretta9149e612000-11-27 00:23:41 +00002289 cutbuffer = NULL;
2290
2291 tmptop = current;
2292 tmpjust = copy_node(current);
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002293 samecheck = tmpjust;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002294
2295 /* This is annoying because it mucks with totsize */
Chris Allegretta9149e612000-11-27 00:23:41 +00002296 add_to_cutbuffer(tmpjust);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002297
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002298 /* Put the whole paragraph into one big line. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002299 while (current->next && !isspace((int) current->next->data[0])
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002300 && !strncmp(current->next->data, samecheck->data, qdepth)
2301 && !empty_line(&current->next->data[qdepth])) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002302 filestruct *tmpnode = current->next;
2303 int len = strlen(current->data);
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002304 int len2 = strlen(current->next->data) - qdepth;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002305
Chris Allegretta9149e612000-11-27 00:23:41 +00002306 tmpjust = NULL;
Chris Allegretta9149e612000-11-27 00:23:41 +00002307 tmpjust = copy_node(current->next);
2308 add_to_cutbuffer(tmpjust);
2309
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002310 /* Wiping out a newline */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002311 totsize--;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002312
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002313 /* length of both strings plus space between strings and ending \0. */
2314 current->data = nrealloc(current->data, len + len2 + 2);
2315 current->data[len++] = ' ';
2316 current->data[len] = '\0';
2317
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002318 strncat(current->data, &current->next->data[qdepth], len2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002319
2320 unlink_node(tmpnode);
2321 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002322 }
2323
2324 justify_format(current->data);
2325
2326 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002327 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002328
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002329 if ((strlenpt(current->data) > (fill))
2330 && !no_spaces(current->data)) {
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002331 do {
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002332 int i = 0, j = 0;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002333 int len2 = 0;
2334 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002335
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002336 /* Start at fill , unless line isn't that long (but it
2337 * appears at least fill long with tabs.
2338 */
2339 if (slen > fill)
2340 i = fill;
2341 else
2342 i = slen;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002343
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002344 for (; i > 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002345 if (isspace((int) current->data[i]) &&
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002346 ((strlenpt(current->data) - strlen(current->data + i))
2347 <= fill))
2348 break;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002349 }
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002350
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002351 if (!i)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002352 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002353
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002354 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002355
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002356 len2 = strlen(current->data + i + 1);
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002357 tmpline->data = charalloc(len2 + 1 + qdepth);
2358
2359 tmpline->data[0] = '\0';
2360 for (j = 0; j < qdepth; j += strlen(quotestr))
2361 strcpy(&tmpline->data[j], quotestr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002362
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002363 /* Skip the white space in current. */
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002364 memcpy(&tmpline->data[j], current->data + i + 1, len2);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002365 tmpline->data[len2] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002366
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002367 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002368
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002369 tmpline->prev = current;
2370 tmpline->next = current->next;
2371 if (current->next != NULL)
2372 current->next->prev = tmpline;
2373
2374 current->next = tmpline;
2375 current = tmpline;
2376 slen -= i + 1;
2377 current_y++;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002378 } while ((strlenpt(current->data) > (fill))
2379 && !no_spaces(current->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002380 }
Chris Allegretta9149e612000-11-27 00:23:41 +00002381 tmpbot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002382
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002383 if (current->next)
2384 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00002385 else
2386 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002387 current_x = 0;
2388 placewewant = 0;
2389
Adam Rogoyski09f97962000-06-20 02:50:33 +00002390 renumber(initial);
2391 totlines = filebot->lineno;
2392
2393 werase(edit);
2394
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002395 if ((current_y < 0) || (current_y >= editwinrows - 1)
2396 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00002397 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002398 center_cursor();
2399 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00002400 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002401 }
2402
Adam Rogoyski09f97962000-06-20 02:50:33 +00002403 edit_refresh();
Chris Allegretta9149e612000-11-27 00:23:41 +00002404 statusbar(_("Can now UnJustify!"));
Chris Allegretta07798352000-11-27 22:58:23 +00002405 /* Change the shortcut list to display the unjustify code */
2406 shortcut_init(1);
2407 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002408 reset_cursor();
2409
Chris Allegretta88520c92001-05-05 17:45:54 +00002410 /* Now get a keystroke and see if it's unjustify; if not, unget the keystroke
Chris Allegretta9149e612000-11-27 00:23:41 +00002411 and return */
Chris Allegretta5f071802001-05-06 02:34:31 +00002412
2413#ifndef DISABLE_MOUSE
2414#ifdef NCURSES_MOUSE_VERSION
2415
2416 /* If it was a mouse click, parse it with do_mouse and it might become
2417 the unjustify key. Else give it back to the input stream. */
2418 if ((kbinput = wgetch(edit)) == KEY_MOUSE)
2419 do_mouse();
2420 else
2421 ungetch(kbinput);
2422#endif
2423#endif
2424
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002425 if ((kbinput = wgetch(edit)) != NANO_UNJUSTIFY_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002426 ungetch(kbinput);
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002427 blank_statusbar_refresh();
2428 } else {
Chris Allegretta9149e612000-11-27 00:23:41 +00002429 /* Else restore the justify we just did (ungrateful user!) */
2430 if (tmptop->prev != NULL)
2431 tmptop->prev->next = tmpbot->next;
Chris Allegrettad022eac2000-11-27 02:50:49 +00002432 else
2433 fileage = current;
Chris Allegretta9149e612000-11-27 00:23:41 +00002434 tmpbot->next->prev = tmptop->prev;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002435 current = tmpbot->next;
Chris Allegretta9149e612000-11-27 00:23:41 +00002436 tmpbot->next = NULL;
2437 do_uncut_text();
Chris Allegrettad022eac2000-11-27 02:50:49 +00002438 if (tmptop->prev == NULL)
2439 edit_refresh();
2440
Chris Allegretta88520c92001-05-05 17:45:54 +00002441 /* Restore totsize from before justify */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002442 totsize = totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002443 free_filestruct(tmptop);
2444 blank_statusbar_refresh();
2445 }
Chris Allegretta4a9c8582000-11-27 22:59:40 +00002446 shortcut_init(0);
2447 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002448 free_filestruct(cutbuffer);
2449 cutbuffer = cutbak;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002450
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002451 return 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002452#endif
2453}
2454
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002455#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002456void help_init(void)
2457{
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002458 int i, sofar = 0, meta_shortcut = 0, helplen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002459 long allocsize = 1; /* How much space we're gonna need for the help text */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002460 char buf[BUFSIZ] = "", *ptr = NULL;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002461 toggle *t;
2462 shortcut *s;
Chris Allegrettab3655b42001-10-22 03:15:31 +00002463
Chris Allegretta7e65d2f2002-02-15 21:12:52 +00002464 helplen = length_of_list(currshortcut);
Chris Allegretta13fd44b2002-01-02 13:59:11 +00002465
Chris Allegrettab3655b42001-10-22 03:15:31 +00002466 /* First set up the initial help text for the current function */
2467 if (currshortcut == whereis_list || currshortcut == replace_list
2468 || currshortcut == replace_list_2)
2469 ptr = _("Search Command Help Text\n\n "
2470 "Enter the words or characters you would like to search "
2471 "for, then hit enter. If there is a match for the text you "
2472 "entered, the screen will be updated to the location of the "
Jordi Mallach773623c2001-10-28 21:00:49 +00002473 "nearest match for the search string.\n\n "
2474 "If using Pico Mode via the -p or --pico flags, using the "
2475 "Meta-P toggle or using a nanorc file, the previous search "
2476 "string will be shown in brackets after the Search: prompt. "
Jordi Mallachf4e57292001-12-26 00:16:40 +00002477 "Hitting enter without entering any text will perform the "
Jordi Mallach773623c2001-10-28 21:00:49 +00002478 "previous search. Otherwise, the previous string will be "
2479 "placed in front of the cursor, and can be edited or deleted "
2480 "before hitting enter.\n\n The following functions keys are "
2481 "available in Search mode:\n\n");
Chris Allegrettab3655b42001-10-22 03:15:31 +00002482 else if (currshortcut == goto_list)
2483 ptr = _("Goto Line Help Text\n\n "
2484 "Enter the line number that you wish to go to and hit "
Jordi Mallach773623c2001-10-28 21:00:49 +00002485 "Enter. If there are fewer lines of text than the "
Chris Allegrettab3655b42001-10-22 03:15:31 +00002486 "number you entered, you will be brought to the last line "
2487 "of the file.\n\n The following functions keys are "
2488 "available in Goto Line mode:\n\n");
2489 else if (currshortcut == insertfile_list)
2490 ptr = _("Insert File Help Text\n\n "
2491 "Type in the name of a file to be inserted into the current "
2492 "file buffer at the current cursor location.\n\n "
2493 "If you have compiled nano with multiple file buffer "
2494 "support, and enable multiple buffers with the -F "
Jordi Mallach773623c2001-10-28 21:00:49 +00002495 "or --multibuffer command line flags, the Meta-F toggle or "
2496 "using a nanorc file, inserting a file will cause it to be "
Chris Allegretta180a5692002-01-02 14:30:33 +00002497 "loaded into a separate buffer (use Meta-< and > to switch "
Chris Allegretta48b06702002-02-22 04:30:50 +00002498 "between file buffers).\n\n If you need another blank "
2499 "buffer, just press Enter at the prompt without typing in a "
2500 "filename, or type in a nonexistent filename at the prompt "
2501 "and press Enter.\n\n The following function keys are "
2502 "available in Insert File mode:\n\n");
Chris Allegrettab3655b42001-10-22 03:15:31 +00002503 else if (currshortcut == writefile_list)
2504 ptr = _("Write File Help Text\n\n "
2505 "Type the name that you wish to save the current file "
2506 "as and hit enter to save the file.\n\n "
2507 "If you are using the marker code with Ctrl-^ and have "
2508 "selected text, you will be prompted to save only the "
2509 "selected portion to a separate file. To reduce the "
2510 "chance of overwriting the current file with just a portion "
2511 "of it, the current filename is not the default in this "
2512 "mode.\n\n The following function keys are available in "
2513 "Write File mode:\n\n");
2514#ifndef DISABLE_BROWSER
2515 else if (currshortcut == browser_list)
2516 ptr = _("File Browser Help Text\n\n "
2517 "The file browser is used to visually browse the "
2518 "directory structure to select a file for reading "
2519 "or writing. You may use the arrow keys or Page Up/"
2520 "Down to browse through the files, and S or Enter to "
2521 "choose the selected file or enter the selected "
2522 "directory. To move up one level, select the directory "
2523 "called \"..\" at the top of the file list.\n\n The "
2524 "following functions keys are available in the file "
2525 "browser:\n\n");
2526 else if (currshortcut == gotodir_list)
2527 ptr = _("Browser Goto Directory Help Text\n\n "
2528 "Enter the name of the directory you would like to "
2529 "browse to.\n\n If tab completion has not been disabled, "
2530 "you can use the TAB key to (attempt to) automatically "
2531 "complete the directory name. The following function "
2532 "keys are available in Browser GotoDir mode:\n\n");
2533#endif
2534 else if (currshortcut == spell_list)
2535 ptr = _("Spell Check Help Text\n\n "
2536 "The spell checker checks the spelling of all text "
2537 "in the current file. When an unknown word is "
2538 "encountered, it is highlighted and a replacement can "
2539 "be edited. It will then prompt to replace every "
2540 "instance of the given misspelled word in the "
2541 "current file.\n\n The following other functions are "
2542 "available in Spell Check mode:\n\n");
2543 else /* Default to the main help list */
2544 ptr = help_text_init;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002545
2546 /* Compute the space needed for the shortcut lists - we add 15 to
2547 have room for the shortcut abbrev and its possible alternate keys */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002548 s = currshortcut;
2549 for (i = 0; i <= helplen - 1; i++) {
2550 if (s->help != NULL)
2551 allocsize += strlen(s->help) + 15;
2552 s = s->next;
2553 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002554
Chris Allegrettab3655b42001-10-22 03:15:31 +00002555 /* If we're on the main list, we also allocate space for toggle help text. */
2556 if (currshortcut == main_list) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002557 for (t = toggles; t != NULL; t = t->next)
2558 if (t->desc != NULL)
2559 allocsize += strlen(t->desc) + 30;
Chris Allegrettab3655b42001-10-22 03:15:31 +00002560 }
2561
2562 allocsize += strlen(ptr);
2563
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002564 if (help_text != NULL)
2565 free(help_text);
2566
2567 /* Allocate space for the help text */
Chris Allegretta88b09152001-05-17 11:35:43 +00002568 help_text = charalloc(allocsize);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002569
2570 /* Now add the text we want */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002571 strcpy(help_text, ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002572
2573 /* Now add our shortcut info */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002574 s = currshortcut;
Chris Allegretta13fd44b2002-01-02 13:59:11 +00002575 for (i = 0; i <= helplen - 1; i++) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002576 if (s->val > 0 && s->val < 'a')
2577 sofar = snprintf(buf, BUFSIZ, "^%c ", s->val + 64);
2578 else {
2579 if (s->altval > 0) {
2580 sofar = 0;
2581 meta_shortcut = 1;
2582 }
2583 else
2584 sofar = snprintf(buf, BUFSIZ, " ");
2585 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002586
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002587 if (!meta_shortcut) {
2588 if (s->misc1 > KEY_F0 && s->misc1 <= KEY_F(64))
2589 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
2590 s->misc1 - KEY_F0);
2591 else
2592 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
2593 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002594
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002595 if (s->altval > 0 && s->altval < 91
2596 && (s->altval - 32) > 32)
2597 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2598 (meta_shortcut ? "M-%c " : "(M-%c) "),
2599 s->altval - 32);
2600 else if (s->altval > 0)
2601 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2602 (meta_shortcut ? "M-%c " : "(M-%c) "),
2603 s->altval);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002604 /* Hack */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002605 else if (s->val >= 'a')
2606 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2607 (meta_shortcut ? "(M-%c) " : "M-%c "),
2608 s->val - 32);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002609 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002610 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002611
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002612 if (meta_shortcut) {
2613 if (s->misc1 > KEY_F0 && s->misc1 <= KEY_F(64))
2614 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2615 "(F%d) ", s->misc1 - KEY_F0);
2616 else
2617 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2618 " ");
2619 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002620
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002621 if (s->help != NULL)
2622 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", s->help);
Chris Allegretta756f2202000-09-01 13:32:47 +00002623
2624 strcat(help_text, buf);
2625 strcat(help_text, "\n");
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002626
2627 s = s->next;
Chris Allegretta756f2202000-09-01 13:32:47 +00002628 }
2629
2630 /* And the toggles... */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002631 if (currshortcut == main_list)
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002632 for (t = toggles; t != NULL; t = t->next) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00002633 sofar = snprintf(buf, BUFSIZ,
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002634 "M-%c ", t->val - 32);
2635 if (t->desc != NULL) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00002636 snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002637 t->desc);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002638 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002639 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00002640 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002641 }
2642
2643}
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002644#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002645
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002646void do_toggle(toggle *which)
Chris Allegretta756f2202000-09-01 13:32:47 +00002647{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002648#ifdef NANO_SMALL
2649 nano_disabled_msg();
2650#else
Jordi Mallach2dc0f6b2000-09-07 10:48:00 +00002651 char *enabled = _("enabled");
2652 char *disabled = _("disabled");
Chris Allegrettaf0f63a82000-09-02 18:44:21 +00002653
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002654 switch (which->val) {
Chris Allegretta8d990b52001-09-22 22:14:25 +00002655 case TOGGLE_BACKWARDS_KEY:
2656 case TOGGLE_CASE_KEY:
2657 case TOGGLE_REGEXP_KEY:
2658 return;
2659 }
Chris Allegretta8d990b52001-09-22 22:14:25 +00002660
Chris Allegretta658399a2001-06-14 02:54:22 +00002661 /* Even easier! */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002662 TOGGLE(which->flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002663
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002664 switch (which->val) {
Chris Allegretta756f2202000-09-01 13:32:47 +00002665 case TOGGLE_PICOMODE_KEY:
Chris Allegretta07798352000-11-27 22:58:23 +00002666 shortcut_init(0);
Chris Allegrettac1049ac2001-08-17 00:03:46 +00002667 SET(CLEAR_BACKUPSTRING);
Chris Allegretta756f2202000-09-01 13:32:47 +00002668 display_main_list();
2669 break;
2670 case TOGGLE_SUSPEND_KEY:
2671 signal_init();
2672 break;
2673 case TOGGLE_MOUSE_KEY:
2674 mouse_init();
2675 break;
2676 case TOGGLE_NOHELP_KEY:
Chris Allegretta2a42af12000-09-12 23:02:49 +00002677 wclear(bottomwin);
2678 wrefresh(bottomwin);
2679 window_init();
Chris Allegrettaaffeda82000-12-18 04:03:48 +00002680 fix_editbot();
Chris Allegretta2a42af12000-09-12 23:02:49 +00002681 edit_refresh();
2682 display_main_list();
Chris Allegretta756f2202000-09-01 13:32:47 +00002683 break;
Chris Allegretta99e30e12001-09-23 02:45:27 +00002684 case TOGGLE_DOS_KEY:
2685 UNSET(MAC_FILE);
2686 break;
2687 case TOGGLE_MAC_KEY:
2688 UNSET(DOS_FILE);
2689 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002690 }
Chris Allegretta2a42af12000-09-12 23:02:49 +00002691
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002692 if (!ISSET(which->flag)) {
2693 if (which->val == TOGGLE_NOHELP_KEY ||
2694 which->val == TOGGLE_WRAP_KEY)
2695 statusbar("%s %s", which->desc, enabled);
Chris Allegretta819e3db2001-07-11 02:37:19 +00002696 else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002697 statusbar("%s %s", which->desc, disabled);
Chris Allegretta819e3db2001-07-11 02:37:19 +00002698 } else {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002699 if (which->val == TOGGLE_NOHELP_KEY ||
2700 which->val == TOGGLE_WRAP_KEY)
2701 statusbar("%s %s", which->desc, disabled);
Chris Allegretta819e3db2001-07-11 02:37:19 +00002702 else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002703 statusbar("%s %s", which->desc, enabled);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002704 }
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002705
Chris Allegretta756f2202000-09-01 13:32:47 +00002706#endif
2707}
2708
Chris Allegretta88520c92001-05-05 17:45:54 +00002709/* If the NumLock key has made the keypad go awry, print an error
2710 message; hopefully we can address it later. */
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002711void print_numlock_warning(void)
2712{
2713 static int didmsg = 0;
2714 if (!didmsg) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002715 statusbar(_
2716 ("NumLock glitch detected. Keypad will malfunction with NumLock off"));
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002717 didmsg = 1;
2718 }
2719}
2720
Chris Allegretta1748cd12001-01-13 17:22:54 +00002721/* This function returns the correct keystroke, given the A,B,C or D
2722 input key. This is a common sequence of many terms which send
2723 Esc-O-[A-D] or Esc-[-[A-D]. */
2724int ABCD(int input)
2725{
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002726 switch (input) {
2727 case 'A':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002728 case 'a':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002729 return (KEY_UP);
2730 case 'B':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002731 case 'b':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002732 return (KEY_DOWN);
2733 case 'C':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002734 case 'c':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002735 return (KEY_RIGHT);
2736 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002737 case 'd':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002738 return (KEY_LEFT);
2739 default:
2740 return 0;
Chris Allegretta1748cd12001-01-13 17:22:54 +00002741 }
2742}
2743
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002744int main(int argc, char *argv[])
2745{
2746 int optchr;
2747 int kbinput; /* Input from keyboard */
2748 long startline = 0; /* Line to try and start at */
Chris Allegretta08020882001-01-29 23:37:54 +00002749 int keyhandled; /* Have we handled the keystroke yet? */
Chris Allegretta9caa1932002-02-15 20:08:05 +00002750 int modify_control_seq;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002751 char *argv0;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002752 shortcut *s;
2753 toggle *t;
Chris Allegretta0357c4d2001-09-19 02:59:25 +00002754
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002755#ifdef _POSIX_VDISABLE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002756 struct termios term;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002757#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002758
2759#ifdef HAVE_GETOPT_LONG
2760 int option_index = 0;
2761 struct option long_options[] = {
Chris Allegretta805c26d2000-09-06 13:39:17 +00002762#ifdef HAVE_REGEX_H
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002763 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00002764#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002765 {"version", 0, 0, 'V'},
2766 {"const", 0, 0, 'c'},
2767 {"suspend", 0, 0, 'z'},
2768 {"nowrap", 0, 0, 'w'},
2769 {"nohelp", 0, 0, 'x'},
2770 {"help", 0, 0, 'h'},
Chris Allegretta7492cec2000-12-18 04:55:21 +00002771 {"view", 0, 0, 'v'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002772#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002773 {"cut", 0, 0, 'k'},
Chris Allegretta7004c282001-09-22 00:42:10 +00002774 {"dos", 0, 0, 'D'},
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002775 {"mac", 0, 0, 'M'},
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002776 {"noconvert", 0, 0, 'N'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002777 {"autoindent", 0, 0, 'i'},
Chris Allegrettaff989832001-09-17 13:48:00 +00002778#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002779 {"tempfile", 0, 0, 't'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002780#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002781 {"speller", 1, 0, 's'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002782#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00002783
2784#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002785 {"fill", 1, 0, 'r'},
Chris Allegretta6fe61492001-05-21 12:56:25 +00002786#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002787 {"mouse", 0, 0, 'm'},
Chris Allegrettae1f14522001-09-19 03:19:43 +00002788#ifndef DISABLE_OPERATINGDIR
2789 {"operatingdir", 1, 0, 'o'},
2790#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002791 {"pico", 0, 0, 'p'},
2792 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00002793 {"tabsize", 1, 0, 'T'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002794
Chris Allegretta355fbe52001-07-14 19:32:47 +00002795#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002796 {"multibuffer", 0, 0, 'F'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002797#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002798#ifndef NANO_SMALL
2799 {"smooth", 0, 0, 'S'},
2800#endif
Chris Allegretta48bd3782002-01-03 21:26:34 +00002801 {"keypad", 0, 0, 'K'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002802 {0, 0, 0, 0}
2803 };
2804#endif
2805
2806 /* Flag inits... */
2807 SET(FOLLOW_SYMLINKS);
2808
2809#ifndef NANO_SMALL
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002810#ifdef ENABLE_NLS
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002811 setlocale(LC_ALL, "");
2812 bindtextdomain(PACKAGE, LOCALEDIR);
2813 textdomain(PACKAGE);
2814#endif
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002815#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002816
Chris Allegretta8d8e0122001-04-18 04:28:54 +00002817#ifdef ENABLE_NANORC
2818 do_rcfile();
2819#endif /* ENABLE_NANORC */
2820
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002821#ifdef HAVE_GETOPT_LONG
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002822 while ((optchr = getopt_long(argc, argv, "h?DFKMNQ:RST:Vabcefgijklmo:pr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002823 long_options, &option_index)) != EOF) {
2824#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002825 while ((optchr =
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002826 getopt(argc, argv, "h?DFKMNQ:RST:Vabcefgijklmo:pr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002827#endif
2828
2829 switch (optchr) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002830
Chris Allegretta7004c282001-09-22 00:42:10 +00002831#ifndef NANO_SMALL
2832 case 'D':
2833 SET(DOS_FILE);
2834 break;
2835#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +00002836#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002837 case 'F':
Chris Allegretta355fbe52001-07-14 19:32:47 +00002838 SET(MULTIBUFFER);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002839 break;
2840#endif
Chris Allegretta48bd3782002-01-03 21:26:34 +00002841 case 'K':
2842 SET(ALT_KEYPAD);
2843 break;
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002844#ifndef NANO_SMALL
2845 case 'M':
2846 SET(MAC_FILE);
2847 break;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002848 case 'N':
2849 SET(NO_CONVERT);
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002850 break;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002851#endif
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002852 case 'Q':
2853#ifndef DISABLE_JUSTIFY
2854 quotestr = optarg;
2855 break;
2856#else
2857 usage(); /* To stop bogus data for tab width */
2858 finish(1);
2859#endif
Chris Allegretta805c26d2000-09-06 13:39:17 +00002860#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +00002861 case 'R':
2862 SET(USE_REGEXP);
2863 break;
Chris Allegretta47805612000-07-07 02:35:34 +00002864#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002865#ifndef NANO_SMALL
2866 case 'S':
2867 SET(SMOOTHSCROLL);
2868 break;
2869#endif
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002870 case 'T':
2871 tabsize = atoi(optarg);
2872 if (tabsize <= 0) {
2873 usage(); /* To stop bogus data for tab width */
2874 finish(1);
2875 }
2876 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002877 case 'V':
2878 version();
2879 exit(0);
Chris Allegrettae1f14522001-09-19 03:19:43 +00002880 case 'a':
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002881 case 'b':
2882 case 'e':
2883 case 'f':
Rocco Corsi12f294c2001-04-14 06:50:24 +00002884 case 'g':
2885 case 'j':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002886 /* Pico compatibility flags */
2887 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002888 case 'c':
2889 SET(CONSTUPDATE);
2890 break;
2891 case 'h':
2892 case '?':
2893 usage();
2894 exit(0);
Chris Allegrettaff989832001-09-17 13:48:00 +00002895#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002896 case 'i':
2897 SET(AUTOINDENT);
2898 break;
Chris Allegretta627de192000-07-12 02:09:17 +00002899 case 'k':
2900 SET(CUT_TO_END);
2901 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002902#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002903 case 'l':
2904 UNSET(FOLLOW_SYMLINKS);
2905 break;
2906 case 'm':
2907 SET(USE_MOUSE);
2908 break;
Chris Allegrettae1f14522001-09-19 03:19:43 +00002909#ifndef DISABLE_OPERATINGDIR
2910 case 'o':
2911 operating_dir = charalloc(strlen(optarg) + 1);
2912 strcpy(operating_dir, optarg);
2913
2914 /* make sure we're inside the operating directory */
2915 if (check_operating_dir(".", 0)) {
2916 if (chdir(operating_dir) == -1) {
2917 free(operating_dir);
2918 operating_dir = NULL;
2919 }
2920 }
2921 break;
2922#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002923 case 'p':
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002924 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002925 break;
2926 case 'r':
Chris Allegretta6fe61492001-05-21 12:56:25 +00002927#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002928 fill = atoi(optarg);
Chris Allegretta6fe61492001-05-21 12:56:25 +00002929 if (fill < 0)
2930 wrap_at = fill;
2931 else if (fill == 0) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002932 usage(); /* To stop bogus data (like a string) */
2933 finish(1);
2934 }
2935 break;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002936#else
2937 usage();
2938 exit(0);
2939
2940#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002941#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002942 case 's':
Chris Allegretta88b09152001-05-17 11:35:43 +00002943 alt_speller = charalloc(strlen(optarg) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002944 strcpy(alt_speller, optarg);
2945 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002946#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002947 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00002948 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002949 break;
2950 case 'v':
2951 SET(VIEW_MODE);
2952 break;
2953 case 'w':
Chris Allegrettacef7fbb2001-04-02 05:36:08 +00002954#ifdef DISABLE_WRAPPING
2955 usage();
2956 exit(0);
2957#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002958 SET(NO_WRAP);
2959 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002960#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002961 case 'x':
2962 SET(NO_HELP);
2963 break;
2964 case 'z':
2965 SET(SUSPEND);
2966 break;
2967 default:
2968 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002969 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002970 }
2971
2972 }
2973
2974 argv0 = strrchr(argv[0], '/');
2975 if ((argv0 && strstr(argv0, "pico"))
2976 || (!argv0 && strstr(argv[0], "pico")))
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002977 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002978
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002979 /* See if there's a non-option in argv (first non-option is the
2980 filename, if +LINE is not given) */
2981 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002982 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002983 else {
2984 /* Look for the +line flag... */
2985 if (argv[optind][0] == '+') {
2986 startline = atoi(&argv[optind][1]);
2987 optind++;
2988 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002989 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002990 else
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002991 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002992
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002993 } else
2994 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002995 }
2996
2997
2998 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002999 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003000
Chris Allegretta9239d742000-09-06 15:19:18 +00003001#ifdef _POSIX_VDISABLE
Chris Allegretta8f6c0692000-07-19 01:16:18 +00003002 term = oldterm;
3003 term.c_cc[VINTR] = _POSIX_VDISABLE;
3004 term.c_cc[VQUIT] = _POSIX_VDISABLE;
3005 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003006 tcsetattr(0, TCSANOW, &term);
Chris Allegretta9239d742000-09-06 15:19:18 +00003007#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003008
3009 /* now ncurses init stuff... */
3010 initscr();
3011 savetty();
3012 nonl();
3013 cbreak();
3014 noecho();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003015
3016 /* Set up some global variables */
Chris Allegretta56214c62001-09-27 02:46:53 +00003017 global_init(0);
Chris Allegretta07798352000-11-27 22:58:23 +00003018 shortcut_init(0);
Rocco Corsiaf5c3022001-01-12 07:51:05 +00003019#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003020 init_help_msg();
3021 help_init();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00003022#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00003023 signal_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003024
3025#ifdef DEBUG
3026 fprintf(stderr, _("Main: set up windows\n"));
3027#endif
3028
Chris Allegretta2a42af12000-09-12 23:02:49 +00003029 window_init();
Chris Allegretta756f2202000-09-01 13:32:47 +00003030 mouse_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003031
Chris Allegretta48bd3782002-01-03 21:26:34 +00003032 if (!ISSET(ALT_KEYPAD)) {
3033 keypad(edit, TRUE);
3034 keypad(bottomwin, TRUE);
3035 }
3036
Chris Allegretta08893e02001-11-29 02:42:27 +00003037#ifdef ENABLE_COLOR
3038 do_colorinit();
3039
Chris Allegretta08893e02001-11-29 02:42:27 +00003040#endif /* ENABLE_COLOR */
3041
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003042#ifdef DEBUG
3043 fprintf(stderr, _("Main: bottom win\n"));
3044#endif
Chris Allegretta88520c92001-05-05 17:45:54 +00003045 /* Set up bottom of window */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003046 display_main_list();
3047
3048#ifdef DEBUG
3049 fprintf(stderr, _("Main: open file\n"));
3050#endif
3051
Chris Allegrettaf4b96012001-01-03 07:11:47 +00003052 titlebar(NULL);
Chris Allegretta31c76662000-11-21 06:20:20 +00003053
3054 /* Now we check to see if argv[optind] is non-null to determine if
3055 we're dealing with a new file or not, not argc == 1... */
3056 if (argv[optind] == NULL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003057 new_file();
3058 else
3059 open_file(filename, 0, 0);
3060
3061 if (startline > 0)
Chris Allegretta2d7893d2001-07-11 02:08:33 +00003062 do_gotoline(startline, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003063 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00003064 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003065
Chris Allegretta08020882001-01-29 23:37:54 +00003066 /* return here after a sigwinch */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003067 sigsetjmp(jmpbuf, 1);
Chris Allegretta08020882001-01-29 23:37:54 +00003068
3069 /* Fix clobber-age */
3070 kbinput = 0;
3071 keyhandled = 0;
3072 modify_control_seq = 0;
3073
Robert Siemborski6967eec2000-07-08 14:23:32 +00003074 edit_refresh();
3075 reset_cursor();
3076
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003077 while (1) {
Chris Allegretta9239d742000-09-06 15:19:18 +00003078
Chris Allegretta6fe61492001-05-21 12:56:25 +00003079#ifndef DISABLE_MOUSE
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003080 currshortcut = main_list;
Chris Allegretta6fe61492001-05-21 12:56:25 +00003081#endif
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003082
Chris Allegretta9239d742000-09-06 15:19:18 +00003083#ifndef _POSIX_VDISABLE
3084 /* We're going to have to do it the old way, i.e. on cygwin */
3085 raw();
3086#endif
3087
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003088 kbinput = wgetch(edit);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003089#ifdef DEBUG
3090 fprintf(stderr, "AHA! %c (%d)\n", kbinput, kbinput);
3091#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003092
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003093 if (kbinput == 27) { /* Grab Alt-key stuff first */
3094 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003095 /* Alt-O, suddenly very important ;) */
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003096 case 'O':
Chris Allegretta16e41682000-09-11 22:33:54 +00003097 kbinput = wgetch(edit);
Chris Allegretta316e4d92001-04-28 16:31:19 +00003098 if ((kbinput <= 'D' && kbinput >= 'A') ||
3099 (kbinput <= 'd' && kbinput >= 'a'))
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003100 kbinput = ABCD(kbinput);
Chris Allegretta201d9bf2001-01-14 03:17:53 +00003101 else if (kbinput <= 'z' && kbinput >= 'j')
3102 print_numlock_warning();
3103 else if (kbinput <= 'S' && kbinput >= 'P')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003104 kbinput = KEY_F(kbinput - 79);
Chris Allegretta16e41682000-09-11 22:33:54 +00003105#ifdef DEBUG
3106 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003107 fprintf(stderr, _("I got Alt-O-%c! (%d)\n"),
3108 kbinput, kbinput);
3109 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003110 }
3111#endif
3112 break;
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003113 case 27:
3114 /* If we get Alt-Alt, the next keystroke should be the same as a
3115 control sequence */
3116 modify_control_seq = 1;
3117 keyhandled = 1;
3118 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00003119#ifndef NANO_SMALL
Chris Allegretta76e291b2001-10-14 19:05:10 +00003120 case ' ':
3121 /* If control-space is next word, Alt-space should be previous word */
3122 do_prev_word();
3123 keyhandled = 1;
3124 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00003125#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003126 case '[':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003127 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003128 case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */
Chris Allegretta16e41682000-09-11 22:33:54 +00003129 kbinput = wgetch(edit);
3130 if (kbinput >= '1' && kbinput <= '5') {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003131 kbinput = KEY_F(kbinput - 48);
3132 wgetch(edit);
3133 } else if (kbinput >= '7' && kbinput <= '9') {
3134 kbinput = KEY_F(kbinput - 49);
3135 wgetch(edit);
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003136 } else if (kbinput == '~')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003137 kbinput = KEY_HOME;
Chris Allegretta16e41682000-09-11 22:33:54 +00003138
3139#ifdef DEBUG
3140 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003141 fprintf(stderr, _("I got Alt-[-1-%c! (%d)\n"),
3142 kbinput, kbinput);
3143 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003144 }
3145#endif
3146
3147 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003148 case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */
Chris Allegretta16e41682000-09-11 22:33:54 +00003149 kbinput = wgetch(edit);
Chris Allegretta16e41682000-09-11 22:33:54 +00003150 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003151 case '0':
3152 kbinput = KEY_F(9);
3153 wgetch(edit);
3154 break;
3155 case '1':
3156 kbinput = KEY_F(10);
3157 wgetch(edit);
3158 break;
3159 case '3':
3160 kbinput = KEY_F(11);
3161 wgetch(edit);
3162 break;
3163 case '4':
3164 kbinput = KEY_F(12);
3165 wgetch(edit);
3166 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003167 case '~':
3168 goto do_insertkey;
Chris Allegretta16e41682000-09-11 22:33:54 +00003169#ifdef DEBUG
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003170 default:
3171 fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"),
3172 kbinput, kbinput);
3173 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003174#endif
3175
3176 }
3177 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003178 case '3': /* Alt-[-3 = Delete? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003179 kbinput = NANO_DELETE_KEY;
3180 wgetch(edit);
3181 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003182 case '4': /* Alt-[-4 = End? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003183 kbinput = NANO_END_KEY;
3184 wgetch(edit);
3185 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003186 case '5': /* Alt-[-5 = Page Up */
Chris Allegretta16e41682000-09-11 22:33:54 +00003187 kbinput = KEY_PPAGE;
3188 wgetch(edit);
3189 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003190 case 'V': /* Alt-[-V = Page Up in Hurd Console */
Chris Allegretta7bf72742001-10-28 04:29:55 +00003191 case 'I': /* Alt-[-I = Page Up - FreeBSD Console */
3192 kbinput = KEY_PPAGE;
3193 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003194 case '6': /* Alt-[-6 = Page Down */
Chris Allegretta16e41682000-09-11 22:33:54 +00003195 kbinput = KEY_NPAGE;
3196 wgetch(edit);
3197 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003198 case 'U': /* Alt-[-U = Page Down in Hurd Console */
Chris Allegretta7bf72742001-10-28 04:29:55 +00003199 case 'G': /* Alt-[-G = Page Down - FreeBSD Console */
3200 kbinput = KEY_NPAGE;
3201 break;
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003202 case '7':
3203 kbinput = KEY_HOME;
3204 wgetch(edit);
3205 break;
3206 case '8':
3207 kbinput = KEY_END;
3208 wgetch(edit);
3209 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003210 case '9': /* Alt-[-9 = Delete in Hurd Console */
3211 kbinput = KEY_DC;
3212 break;
Chris Allegretta32da4562002-01-02 15:12:21 +00003213 case '@': /* Alt-[-@ = Insert in Hurd Console */
3214 case 'L': /* Alt-[-L = Insert - FreeBSD Console */
3215 goto do_insertkey;
3216 case '[': /* Alt-[-[-[A-E], F1-F5 in Linux console */
Chris Allegretta16e41682000-09-11 22:33:54 +00003217 kbinput = wgetch(edit);
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003218 if (kbinput >= 'A' && kbinput <= 'E')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003219 kbinput = KEY_F(kbinput - 64);
Chris Allegretta16e41682000-09-11 22:33:54 +00003220 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003221 case 'A':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003222 case 'B':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003223 case 'C':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003224 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00003225 case 'a':
3226 case 'b':
3227 case 'c':
3228 case 'd':
Chris Allegretta1748cd12001-01-13 17:22:54 +00003229 kbinput = ABCD(kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003230 break;
3231 case 'H':
3232 kbinput = KEY_HOME;
3233 break;
3234 case 'F':
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003235 case 'Y': /* End Key in Hurd Console */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003236 kbinput = KEY_END;
3237 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003238 default:
3239#ifdef DEBUG
3240 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
3241 kbinput, kbinput);
3242#endif
3243 break;
3244 }
3245 break;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003246
Chris Allegretta355fbe52001-07-14 19:32:47 +00003247#ifdef ENABLE_MULTIBUFFER
Chris Allegretta819e3db2001-07-11 02:37:19 +00003248 case NANO_OPENPREV_KEY:
Chris Allegretta180a5692002-01-02 14:30:33 +00003249 case NANO_OPENPREV_ALTKEY:
Chris Allegretta819e3db2001-07-11 02:37:19 +00003250 open_prevfile(0);
3251 keyhandled = 1;
3252 break;
3253 case NANO_OPENNEXT_KEY:
Chris Allegretta180a5692002-01-02 14:30:33 +00003254 case NANO_OPENNEXT_ALTKEY:
Chris Allegretta819e3db2001-07-11 02:37:19 +00003255 open_nextfile(0);
3256 keyhandled = 1;
3257 break;
Chris Allegretta9cf9e062001-07-11 12:06:13 +00003258#endif
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003259
3260#if !defined (NANO_SMALL) && defined (HAVE_REGEX_H)
3261 case NANO_BRACKET_KEY:
3262 do_find_bracket();
3263 keyhandled = 1;
3264 break;
3265#endif
3266
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003267 default:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003268 /* Check for the altkey defs.... */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003269 for (s = main_list; s != NULL; s = s->next)
3270 if (kbinput == s->altval ||
3271 kbinput == s->altval - 32) {
3272 kbinput = s->val;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003273 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003274 }
Chris Allegretta756f2202000-09-01 13:32:47 +00003275#ifndef NANO_SMALL
3276 /* And for toggle switches */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003277 for (t = toggles; t != NULL && !keyhandled; t = t->next)
3278 if (kbinput == t->val ||
3279 (t->val > 'a' &&
3280 kbinput == t->val - 32)) {
3281 do_toggle(t);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003282 keyhandled = 1;
3283 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00003284 }
3285#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003286#ifdef DEBUG
3287 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
3288 kbinput);
3289#endif
3290 break;
3291 }
3292 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003293 /* If the modify_control_seq is set, we received an Alt-Alt
3294 sequence before this, so we make this key a control sequence
3295 by subtracting 64 or 96, depending on its value. */
3296 if (!keyhandled && modify_control_seq) {
3297 if (kbinput >= 'A' && kbinput < 'a')
3298 kbinput -= 64;
3299 else if (kbinput >= 'a' && kbinput <= 'z')
3300 kbinput -= 96;
3301
3302 modify_control_seq = 0;
3303 }
3304
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003305 /* Look through the main shortcut list to see if we've hit a
3306 shortcut key */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003307
Chris Allegrettaf5de33a2002-02-27 04:14:16 +00003308#if !defined(DISABLE_BROWSER) || !defined(DISABLE_MOUSE) || !defined (DISABLE_HELP)
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003309 for (s = currshortcut; s != NULL && !keyhandled; s = s->next) {
Chris Allegrettaf5de33a2002-02-27 04:14:16 +00003310#else
3311 for (s = main_list; s != NULL && !keyhandled; s = s->next) {
3312#endif
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003313 if (kbinput == s->val ||
3314 (s->misc1 && kbinput == s->misc1) ||
3315 (s->misc2 && kbinput == s->misc2)) {
3316 if (ISSET(VIEW_MODE) && !s->viewok)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003317 print_view_warning();
3318 else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003319 s->func();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003320 keyhandled = 1;
3321 }
3322 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003323 /* If we're in raw mode or using Alt-Alt-x, we have to catch
3324 Control-S and Control-Q */
Chris Allegretta9239d742000-09-06 15:19:18 +00003325 if (kbinput == 17 || kbinput == 19)
3326 keyhandled = 1;
3327
Chris Allegretta9caa1932002-02-15 20:08:05 +00003328 /* Catch ^Z by hand when triggered also
3329 407 == ^Z in Linux console when keypad() is used? */
3330 if (kbinput == 26 || kbinput == 407) {
Chris Allegretta9239d742000-09-06 15:19:18 +00003331 if (ISSET(SUSPEND))
3332 do_suspend(0);
3333 keyhandled = 1;
3334 }
Chris Allegretta9239d742000-09-06 15:19:18 +00003335
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003336
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003337#ifndef USE_SLANG
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003338 /* Hack, make insert key do something useful, like insert file */
3339 if (kbinput == KEY_IC) {
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003340#else
3341 if (0) {
3342#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003343 do_insertkey:
3344
3345#ifdef ENABLE_MULTIBUFFER
Chris Allegretta32da4562002-01-02 15:12:21 +00003346 /* do_insertfile_void() contains the logic needed to
3347 handle view mode with the view mode/multibuffer
3348 exception, so use it here */
3349 do_insertfile_void();
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003350#else
Chris Allegretta32da4562002-01-02 15:12:21 +00003351 print_view_warning();
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003352#endif
3353
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003354 keyhandled = 1;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003355 }
3356
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003357 /* Last gasp, stuff that's not in the main lists */
3358 if (!keyhandled)
3359 switch (kbinput) {
Chris Allegretta84de5522001-04-12 14:51:48 +00003360#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003361#ifdef NCURSES_MOUSE_VERSION
3362 case KEY_MOUSE:
3363 do_mouse();
3364 break;
3365#endif
3366#endif
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003367
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003368 case 0: /* Erg */
Chris Allegretta48ebb812001-10-24 01:34:15 +00003369#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003370 do_next_word();
3371 break;
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003372#endif
Chris Allegrettaf4f7e042001-01-04 16:56:15 +00003373
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003374 case -1: /* Stuff that we don't want to do squat */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003375 case 410: /* Must ignore this, it gets sent when we resize */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003376 case 29: /* Ctrl-] */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003377#ifdef PDCURSES
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003378 case 541: /* ???? */
3379 case 542: /* Control and alt in Windows *shrug* */
Chris Allegretta72623582000-11-29 23:43:28 +00003380 case 543: /* Right ctrl key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003381 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +00003382 case 545: /* Right alt key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003383#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003384
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003385 break;
3386 default:
3387#ifdef DEBUG
3388 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
3389#endif
3390 /* We no longer stop unhandled sequences so that people with
3391 odd character sets can type... */
3392
3393 if (ISSET(VIEW_MODE)) {
3394 print_view_warning();
3395 break;
3396 }
3397 do_char(kbinput);
3398 }
Chris Allegretta7fdbd052001-10-02 00:55:38 +00003399 if (ISSET(DISABLE_CURPOS))
3400 UNSET(DISABLE_CURPOS);
3401 else if (ISSET(CONSTUPDATE))
Chris Allegretta2084acc2001-11-29 03:43:08 +00003402 do_cursorpos(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003403
3404 reset_cursor();
3405 wrefresh(edit);
3406 keyhandled = 0;
3407 }
3408
3409 getchar();
3410 finish(0);
3411
3412}