blob: 2cd5ea3e91fe6cc3bd5450aaf255de177817d828 [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;
Chris Allegrettabef12972002-03-06 03:30:40 +0000370 int i = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000371
Chris Allegrettaf6cba642002-03-26 13:05:54 +0000372 assert(fileage==NULL || fileage!=fileage->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000373 for (temp = fileage; temp != NULL; temp = temp->next) {
374 temp->lineno = i++;
375 }
376
377 return 0;
378}
379
380int renumber(filestruct * fileptr)
381{
382 filestruct *temp;
383
384 if (fileptr == NULL || fileptr->prev == NULL || fileptr == fileage) {
385 renumber_all();
386 return 0;
387 }
Chris Allegrettaf6cba642002-03-26 13:05:54 +0000388 assert(fileptr==NULL || fileptr!=fileptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000389 for (temp = fileptr; temp != NULL; temp = temp->next) {
Chris Allegretta5146fec2000-12-10 05:44:02 +0000390 if (temp->prev != NULL)
391 temp->lineno = temp->prev->lineno + 1;
392 else
393 temp->lineno = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000394 }
395
396 return 0;
397}
398
399/* Fix the memory allocation for a string */
400void align(char **strp)
401{
402 /* There was a serious bug here: the new address was never
403 stored anywhere... */
404
405 *strp = nrealloc(*strp, strlen(*strp) + 1);
406}
407
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000408/* Null a string at a certain index and align it */
Chris Allegrettafa0c6962001-10-22 23:22:19 +0000409void null_at(char **data, int index)
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000410{
Chris Allegrettafa0c6962001-10-22 23:22:19 +0000411
412 /* Ahh! Damn dereferencing */
413 (*data)[index] = 0;
414 align(data);
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000415}
416
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000417
418/* Print one usage string to the screen, removes lots of duplicate
419 strings to translate and takes out the parts that shouldn't be
420 translatable (the flag names) */
421void print1opt(char *shortflag, char *longflag, char *desc)
422{
423 printf(" %s\t", shortflag);
424 if (strlen(shortflag) < 8)
425 printf("\t");
426
427#ifdef HAVE_GETOPT_LONG
428 printf("%s\t", longflag);
429 if (strlen(longflag) < 8)
430 printf("\t\t");
431 else if (strlen(longflag) < 16)
432 printf("\t");
433#endif
434
435 printf("%s\n", desc);
436}
437
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000438void usage(void)
439{
440#ifdef HAVE_GETOPT_LONG
441 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
442 printf(_("Option Long option Meaning\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000443#else
444 printf(_("Usage: nano [option] +LINE <file>\n\n"));
445 printf(_("Option Meaning\n"));
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000446#endif /* HAVE_GETOPT_LONG */
447
Chris Allegretta7004c282001-09-22 00:42:10 +0000448#ifndef NANO_SMALL
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000449 print1opt("-D", "--dos", _("Write file in DOS format"));
Chris Allegretta7004c282001-09-22 00:42:10 +0000450#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000451#ifdef ENABLE_MULTIBUFFER
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000452 print1opt("-F", "--multibuffer", _("Enable multiple file buffers"));
Chris Allegretta355fbe52001-07-14 19:32:47 +0000453#endif
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000454 print1opt("-K", "--keypad", _("Use alternate keypad routines"));
Chris Allegretta8fa1e282001-09-22 04:20:25 +0000455#ifndef NANO_SMALL
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000456 print1opt("-M", "--mac", _("Write file in Mac format"));
457 print1opt("-N", "--noconvert", _("Don't convert files from DOS/Mac format"));
Chris Allegretta8fa1e282001-09-22 04:20:25 +0000458#endif
Chris Allegrettae4f940d2002-03-03 22:36:36 +0000459#ifndef DISABLE_JUSTIFY
Chris Allegrettad1ec7b02002-03-09 20:05:26 +0000460 print1opt(_("-Q [str]"), _("--quotestr [str]"), _("Quoting string, default \"> \""));
Chris Allegrettae4f940d2002-03-03 22:36:36 +0000461#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +0000462#ifndef NANO_SMALL
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000463 print1opt("-S", "--smooth", _("Smooth scrolling"));
Chris Allegretta3e3ae942001-09-22 19:02:04 +0000464#endif
Chris Allegrettad1ec7b02002-03-09 20:05:26 +0000465 print1opt(_("-T [num]"), _("--tabsize=[num]"), _("Set width of a tab to num"));
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000466 print1opt("-V", "--version", _("Print version information and exit"));
467 print1opt("-c", "--const", _("Constantly show cursor position"));
468 print1opt("-h", "--help", _("Show this message"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000469#ifndef NANO_SMALL
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000470 print1opt("-i", "--autoindent", _("Automatically indent new lines"));
471 print1opt("-k", "--cut", _("Let ^K cut from cursor to end of line"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000472#endif
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000473 print1opt("-l", "--nofollow", _("Don't follow symbolic links, overwrite"));
Chris Allegretta84de5522001-04-12 14:51:48 +0000474#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000475#ifdef NCURSES_MOUSE_VERSION
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000476 print1opt("-m", "--mouse", _("Enable mouse"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000477#endif
478#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000479#ifndef DISABLE_OPERATINGDIR
Chris Allegrettad1ec7b02002-03-09 20:05:26 +0000480 print1opt(_("-o [dir]"), _("--operatingdir=[dir]"), _("Set operating directory"));
Chris Allegrettae1f14522001-09-19 03:19:43 +0000481#endif
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000482 print1opt("-p", "--pico", _("Emulate Pico as closely as possible"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000483
484#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettad1ec7b02002-03-09 20:05:26 +0000485 print1opt(_("-r [#cols]"), _("--fill=[#cols]"), _("Set fill cols to (wrap lines at) #cols"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000486#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000487#ifndef DISABLE_SPELLER
Chris Allegrettad1ec7b02002-03-09 20:05:26 +0000488 print1opt(_("-s [prog]"), _("--speller=[prog]"), _("Enable alternate speller"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000489#endif
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000490 print1opt("-t", "--tempfile", _("Auto save on exit, don't prompt"));
491 print1opt("-v", "--view", _("View (read only) mode"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000492#ifndef DISABLE_WRAPPING
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000493 print1opt("-w", "--nowrap", _("Don't wrap long lines"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000494#endif
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000495 print1opt("-x", "--nohelp", _("Don't show help window"));
496 print1opt("-z", "--suspend", _("Enable suspend"));
Chris Allegrettad1ec7b02002-03-09 20:05:26 +0000497 print1opt(_("+LINE"), "", _("Start at line number LINE"));
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000498
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000499 exit(0);
500}
501
502void version(void)
503{
Chris Allegrettac46dd812001-02-14 14:28:27 +0000504 printf(_(" GNU nano version %s (compiled %s, %s)\n"),
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000505 VERSION, __TIME__, __DATE__);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000506 printf(_
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000507 (" Email: nano@nano-editor.org Web: http://www.nano-editor.org"));
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000508 printf(_("\n Compiled options:"));
Chris Allegrettaff269f82000-12-01 18:46:01 +0000509
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000510#ifdef NANO_EXTRA
511 printf(" --enable-extra");
Jordi Mallach5285ca92002-01-17 12:40:33 +0000512#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000513#ifdef ENABLE_MULTIBUFFER
514 printf(" --enable-multibuffer");
Jordi Mallach5285ca92002-01-17 12:40:33 +0000515#endif
Chris Allegrettab881d3e2001-04-18 04:34:43 +0000516#ifdef ENABLE_NANORC
517 printf(" --enable-nanorc");
518#endif
Chris Allegretta8ce24132001-04-30 11:28:46 +0000519#ifdef ENABLE_COLOR
520 printf(" --enable-color");
521#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000522
523#ifdef NANO_SMALL
524 printf(" --enable-tiny");
525#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000526#ifdef DISABLE_BROWSER
Chris Allegretta6636dc32001-01-05 05:41:07 +0000527 printf(" --disable-browser");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000528#endif
529#ifdef DISABLE_TABCOMP
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000530 printf(" --disable-tabcomp");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000531#endif
532#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +0000533 printf(" --disable-justify");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000534#endif
535#ifdef DISABLE_SPELLER
Chris Allegretta7b36c522000-12-06 01:08:10 +0000536 printf(" --disable-speller");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000537#endif
538#ifdef DISABLE_HELP
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000539 printf(" --disable-help");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000540#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000541#ifdef DISABLE_MOUSE
542 printf(" --disable-mouse");
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000543#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000544#ifdef DISABLE_OPERATINGDIR
545 printf(" --disable-operatingdir");
546#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000547#endif /* NANO_SMALL */
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000548
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000549#ifdef DISABLE_WRAPPING
550 printf(" --disable-wrapping");
551#endif
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000552#ifdef USE_SLANG
553 printf(" --with-slang");
554#endif
555 printf("\n");
556
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000557}
558
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000559/* Create a new node. This does NOT initialize the data members used
560 only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000561filestruct *make_new_node(filestruct * prevnode)
562{
563 filestruct *newnode;
564
565 newnode = nmalloc(sizeof(filestruct));
566 newnode->data = NULL;
567
568 newnode->prev = prevnode;
569 newnode->next = NULL;
570
571 if (prevnode != NULL)
572 newnode->lineno = prevnode->lineno + 1;
573
574 return newnode;
575}
576
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000577/* Splice a node into an existing filestruct. This does NOT set the data
578 members used only by open_files. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000579void splice_node(filestruct * begin, filestruct * newnode,
580 filestruct * end)
Chris Allegretta7975ed82000-07-28 00:58:35 +0000581{
Chris Allegrettae3167732001-03-18 16:59:34 +0000582 newnode->next = end;
583 newnode->prev = begin;
584 begin->next = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000585 if (end != NULL)
Chris Allegrettae3167732001-03-18 16:59:34 +0000586 end->prev = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000587}
588
Chris Allegrettae3167732001-03-18 16:59:34 +0000589int do_mark(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000590{
591#ifdef NANO_SMALL
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000592 nano_disabled_msg();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000593#else
594 if (!ISSET(MARK_ISSET)) {
595 statusbar(_("Mark Set"));
596 SET(MARK_ISSET);
597 mark_beginbuf = current;
598 mark_beginx = current_x;
599 } else {
600 statusbar(_("Mark UNset"));
601 UNSET(MARK_ISSET);
602 mark_beginbuf = NULL;
603 mark_beginx = 0;
604
605 edit_refresh();
606 }
607#endif
608 return 1;
609}
610
611int no_help(void)
612{
613 if ISSET
614 (NO_HELP)
615 return 2;
616 else
617 return 0;
618}
619
Chris Allegretta3bc8c722000-12-10 17:03:25 +0000620#if defined(DISABLE_JUSTIFY) || defined(DISABLE_SPELLER) || defined(DISABLE_HELP)
Chris Allegrettaff269f82000-12-01 18:46:01 +0000621void nano_disabled_msg(void)
622{
623 statusbar("Sorry, support for this function has been disabled");
624}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000625#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000626
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000627/* The user typed a printable character; add it to the edit buffer */
628void do_char(char ch)
629{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000630 /* magic-line: when a character is inserted on the current magic line,
631 * it means we need a new one! */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000632 if (filebot == current && current->data[0] == '\0') {
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000633 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000634 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000635 }
636
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000637 /* More dangerousness fun =) */
638 current->data = nrealloc(current->data, strlen(current->data) + 2);
639 memmove(&current->data[current_x + 1],
640 &current->data[current_x],
641 strlen(current->data) - current_x + 1);
642 current->data[current_x] = ch;
643 do_right();
644
Chris Allegrettab2cd10d2002-01-20 00:54:42 +0000645#ifdef ENABLE_COLOR
646 edit_refresh();
647#endif
648
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000649#ifndef DISABLE_WRAPPING
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000650 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000651 check_wrap(current, ch);
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000652#endif
653
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000654 set_modified();
655 check_statblank();
656 UNSET(KEEP_CUTBUFFER);
657 totsize++;
658
659}
660
661/* Someone hits return *gasp!* */
662int do_enter(filestruct * inptr)
663{
Chris Allegrettae3167732001-03-18 16:59:34 +0000664 filestruct *newnode;
Chris Allegretta68532c32001-09-17 13:49:33 +0000665 char *tmp;
666#ifndef NANO_SMALL
667 char *spc;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000668 int extra = 0;
Chris Allegretta68532c32001-09-17 13:49:33 +0000669#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000670
Chris Allegrettae3167732001-03-18 16:59:34 +0000671 newnode = make_new_node(inptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000672 tmp = &current->data[current_x];
673 current_x = 0;
674
Chris Allegrettaff989832001-09-17 13:48:00 +0000675#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000676 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
677 if (ISSET(AUTOINDENT)) {
678 spc = current->data;
679 if (spc) {
680 while ((*spc == ' ') || (*spc == '\t')) {
681 extra++;
682 spc++;
683 current_x++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +0000684 totsize++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000685 }
Chris Allegretta88b09152001-05-17 11:35:43 +0000686 newnode->data = charalloc(strlen(tmp) + extra + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000687 strncpy(newnode->data, current->data, extra);
688 strcpy(&newnode->data[extra], tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000689 }
Chris Allegrettaff989832001-09-17 13:48:00 +0000690 } else
691#endif
692 {
Chris Allegretta88b09152001-05-17 11:35:43 +0000693 newnode->data = charalloc(strlen(tmp) + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000694 strcpy(newnode->data, tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000695 }
696 *tmp = 0;
697
Chris Allegrettada721be2000-07-31 01:26:42 +0000698 if (inptr->next == NULL) {
Chris Allegrettae3167732001-03-18 16:59:34 +0000699 filebot = newnode;
700 editbot = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000701 }
Chris Allegrettae3167732001-03-18 16:59:34 +0000702 splice_node(inptr, newnode, inptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000703
704 totsize++;
705 renumber(current);
Chris Allegrettae3167732001-03-18 16:59:34 +0000706 current = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000707 align(&current->data);
708
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000709 /* The logic here is as follows:
710 * -> If we are at the bottom of the buffer, we want to recenter
Chris Allegretta88520c92001-05-05 17:45:54 +0000711 * (read: rebuild) the screen and forcibly move the cursor.
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000712 * -> otherwise, we want simply to redraw the screen and update
713 * where we think the cursor is.
714 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000715 if (current_y == editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +0000716 edit_update(current, CENTER);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000717 reset_cursor();
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000718 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000719 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000720 edit_refresh();
721 update_cursor();
722 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000723
724 totlines++;
725 set_modified();
726
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000727 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000728 return 1;
729}
730
731int do_enter_void(void)
732{
733 return do_enter(current);
734}
735
Chris Allegrettaad3f4782001-10-02 03:54:13 +0000736#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000737void do_next_word(void)
738{
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000739 filestruct *fileptr, *old;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000740 int i;
741
742 if (current == NULL)
743 return;
744
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000745 old = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000746 i = current_x;
747 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
748 if (fileptr == current) {
749 while (isalnum((int) fileptr->data[i])
750 && fileptr->data[i] != 0)
751 i++;
752
753 if (fileptr->data[i] == 0) {
754 i = 0;
755 continue;
756 }
757 }
758 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
759 i++;
760
761 if (fileptr->data[i] != 0)
762 break;
763
764 i = 0;
765 }
766 if (fileptr == NULL)
767 current = filebot;
768 else
769 current = fileptr;
770
771 current_x = i;
772 placewewant = xplustabs();
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000773
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000774 if (current->lineno >= editbot->lineno)
Chris Allegretta234a34d2000-07-29 04:33:38 +0000775 edit_update(current, CENTER);
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000776 else {
777 /* If we've jumped lines, refresh the old line. We can't just use
778 * current->prev here, because we may have skipped over some blank
779 * lines, in which case the previous line is the wrong one.
780 */
781 if (current != old)
782 update_line(old, 0);
783
784 update_line(current, current_x);
785 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000786}
787
788/* the same thing for backwards */
789void do_prev_word(void)
790{
791 filestruct *fileptr, *old;
792 int i;
793
794 if (current == NULL)
795 return;
796
797 old = current;
798 i = current_x;
799 for (fileptr = current; fileptr != NULL; fileptr = fileptr->prev) {
800 if (fileptr == current) {
801 while (isalnum((int) fileptr->data[i])
802 && i != 0)
803 i--;
804
805 if (i == 0) {
806 if (fileptr->prev != NULL)
Chris Allegrettae59fc822001-10-24 18:07:58 +0000807 i = strlen(fileptr->prev->data);
Chris Allegretta878ced32001-10-22 20:05:34 +0000808 else if (fileptr == fileage && filebot != NULL) {
809 current_x = 0;
810 return;
811 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000812 continue;
813 }
814 }
815
816 while (!isalnum((int) fileptr->data[i]) && i != 0)
817 i--;
818
819 if (i > 0) {
820 i--;
821
822 while (isalnum((int) fileptr->data[i]) && i != 0)
823 i--;
824
Chris Allegretta6d0aa9f2001-10-26 15:21:41 +0000825 if (!isalnum((int) fileptr->data[i]))
826 i++;
827
828 if (i != 0 || i != current_x)
Chris Allegretta76e291b2001-10-14 19:05:10 +0000829 break;
830
831 }
832 if (fileptr->prev != NULL)
Chris Allegrettae59fc822001-10-24 18:07:58 +0000833 i = strlen(fileptr->prev->data);
Chris Allegretta878ced32001-10-22 20:05:34 +0000834 else if (fileptr == fileage && filebot != NULL) {
835 current_x = 0;
836 return;
837 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000838 }
839 if (fileptr == NULL)
840 current = fileage;
841 else
842 current = fileptr;
843
844 current_x = i;
845 placewewant = xplustabs();
846
847 if (current->lineno <= edittop->lineno)
848 edit_update(current, CENTER);
849 else {
850 /* If we've jumped lines, refresh the old line. We can't just use
851 * current->prev here, because we may have skipped over some blank
852 * lines, in which case the previous line is the wrong one.
853 */
854 if (current != old)
855 update_line(old, 0);
856
857 update_line(current, current_x);
858 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000859
860}
Chris Allegrettaad3f4782001-10-02 03:54:13 +0000861#endif /* NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000862
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000863#ifndef DISABLE_WRAPPING
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000864void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000865{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000866 int i = 0; /* Index into ->data for line. */
867 int i_tabs = 0; /* Screen position of ->data[i]. */
868 int last_word_end = -1; /* Location of end of last word found. */
869 int current_word_start = -1; /* Location of start of current word. */
870 int current_word_start_t = -1; /* Location of start of current word screen position. */
871 int current_word_end = -1; /* Location of end of current word */
872 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000873 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000874
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000875 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000876 int right = 0;
877 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000878
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000879 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000880
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000881 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000882 if (!isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000883 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000884
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000885 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000886 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000887
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000888 while (!isspace((int) inptr->data[i])
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000889 && inptr->data[i]) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000890 i++;
891 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000892 if (inptr->data[i] < 32)
893 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000894 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000895
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000896 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000897 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000898 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000899 } else {
900 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000901 current_word_end_t = i_tabs - 1;
902 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000903 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000904
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000905 if (inptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000906 if (i_tabs % tabsize != 0);
907 i_tabs += tabsize - (i_tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000908 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000909
Adam Rogoyski09f97962000-06-20 02:50:33 +0000910 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000911 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000912 }
913
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000914 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000915 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000916 * a) one word takes up the whole line with no starting spaces.
917 * - do nothing and return.
918 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000919 * - word starts new line.
920 * - keep white space on original line up to the cursor.
921 * *) cursor is after word at wrap point
922 * - either it's all white space after word, and this routine isn't called.
923 * - or we are actually in case 2 (2 words).
924 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000925 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000926 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000927 * - white space at end of original line is cleared, unless
928 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000929 * b) cursor is at the word at the wrap point.
930 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000931 * - white space on original line is kept to where cursor was.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000932 * c) cursor is past the word at the wrap point.
933 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000934 * - white space at end of original line is cleared
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000935 */
936
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000937 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000938
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000939 /* Category 1a: one word taking up the whole line with no beginning spaces. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000940 if ((last_word_end == -1) && (!isspace((int) inptr->data[0]))) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000941 for (i = current_word_end; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000942 if (!isspace((int) inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000943 current_word_start = i;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000944 while (!isspace((int) inptr->data[i]) && (i < len)) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000945 i++;
946 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000947 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000948 current_word_end = i;
949 break;
950 }
951 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000952
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000953 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000954 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000955 return;
956 }
957 if (current_x >= last_word_end) {
958 right = (current_x - current_word_start) + 1;
959 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000960 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000961 }
962
Chris Allegretta2084acc2001-11-29 03:43:08 +0000963 /* Subtract length of original line, plus one for the newline, from
964 totsize. */
965 totsize -= (strlen(inptr->data) + 1);
966
Chris Allegretta88b09152001-05-17 11:35:43 +0000967 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000968 strcpy(temp->data, &inptr->data[current_word_start]);
969 inptr->data = nrealloc(inptr->data, last_word_end + 2);
970 inptr->data[last_word_end + 1] = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +0000971
972 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
973 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
974
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000975 } else
976 /* Category 1b: one word on the line and word not taking up whole line
977 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000978 if (last_word_end == -1) {
Chris Allegretta88b09152001-05-17 11:35:43 +0000979 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000980 strcpy(temp->data, &inptr->data[current_word_start]);
981
982 /* Inside word, remove it from original, and move cursor to right spot. */
983 if (current_x >= current_word_start) {
984 right = current_x - current_word_start;
Chris Allegretta56214c62001-09-27 02:46:53 +0000985
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000986 current_x = 0;
Chris Allegrettaff989832001-09-17 13:48:00 +0000987#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +0000988 if (ISSET(AUTOINDENT)) {
989 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000990 while ((inptr->next->data[i] == ' '
991 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +0000992 i++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000993 }
Chris Allegretta94a78b82001-03-14 08:28:48 +0000994 }
Chris Allegrettaff989832001-09-17 13:48:00 +0000995#endif
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000996 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000997 }
998
Chris Allegretta2084acc2001-11-29 03:43:08 +0000999 /* Subtract length of original line, plus one for the newline, from
1000 totsize. */
1001 totsize -= (strlen(inptr->data) + 1);
1002
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001003 null_at(&inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001004
Chris Allegretta2084acc2001-11-29 03:43:08 +00001005 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1006 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
1007
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001008 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
1009 mark_beginbuf = temp;
1010 mark_beginx = 0;
1011 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001012 }
1013
1014 /* Category 2: two or more words on the line. */
1015 else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001016 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001017 if (current_x < current_word_start) {
1018 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001019 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001020 strcpy(temp->data, &inptr->data[current_word_start]);
1021
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001022 if (!isspace((int) input_char)) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001023 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001024
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001025 while (isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001026 i--;
1027 assert(i >= 0);
1028 }
1029 } else if (current_x <= last_word_end)
1030 i = last_word_end - 1;
1031 else
1032 i = current_x;
1033
Chris Allegretta2084acc2001-11-29 03:43:08 +00001034 /* Subtract length of original line, plus one for the newline, from
1035 totsize. */
1036 totsize -= (strlen(inptr->data) + 1);
1037
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001038 inptr->data = nrealloc(inptr->data, i + 2);
1039 inptr->data[i + 1] = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001040
1041 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1042 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
1043
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001044 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001045
1046
1047 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001048 else if ((current_x >= current_word_start)
1049 && (current_x <= (current_word_end + 1))) {
1050 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001051 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001052 strcpy(temp->data, &inptr->data[current_word_start]);
1053
1054 down = 1;
1055
1056 right = current_x - current_word_start;
Chris Allegrettaff989832001-09-17 13:48:00 +00001057#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001058 if (ISSET(AUTOINDENT)) {
1059 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001060 while ((inptr->next->data[i] == ' '
1061 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001062 i++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001063 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001064 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001065#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001066 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001067 current_x = current_word_start;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001068
Chris Allegretta2084acc2001-11-29 03:43:08 +00001069 /* Subtract length of original line, plus one for the newline, from
1070 totsize. */
1071 totsize -= (strlen(inptr->data) + 1);
1072
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001073 null_at(&inptr->data, current_word_start);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001074
Chris Allegretta2084acc2001-11-29 03:43:08 +00001075 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1076 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001077 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001078
1079
1080 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001081 else {
1082 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001083 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001084 strcpy(temp->data, &inptr->data[current_word_start]);
1085
1086 down = 1;
1087 right = current_x - current_word_start;
1088
1089 current_x = current_word_start;
1090 i = current_word_start - 1;
1091
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001092 while (isspace((int) inptr->data[i])) {
Adam Rogoyski3d449b42000-06-19 17:30:14 +00001093 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001094 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001095 }
Chris Allegretta2084acc2001-11-29 03:43:08 +00001096
1097 /* Subtract length of original line, plus one for the newline, from
1098 totsize. */
1099 totsize -= (strlen(inptr->data) + 1);
1100
1101 inptr->data = nrealloc(inptr->data, i + 2);
1102 inptr->data[i + 1] = 0;
1103
1104 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1105 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001106 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001107 }
1108
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001109 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001110 if (ISSET(SAMELINEWRAP) && inptr->next) {
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001111 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001112
Chris Allegretta94a78b82001-03-14 08:28:48 +00001113 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001114 char *p =
Chris Allegretta88b09152001-05-17 11:35:43 +00001115 charalloc((strlen(temp->data) + strlen(inptr->next->data) + 2));
Chris Allegretta94a78b82001-03-14 08:28:48 +00001116
Chris Allegretta56214c62001-09-27 02:46:53 +00001117 /* We're adding to an existing line instead of creating a new
1118 one; decrement totlines here so that when it gets incremented
1119 below, it won't end up being high by one. */
1120 totlines--;
1121
Chris Allegrettaff989832001-09-17 13:48:00 +00001122#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001123 if (ISSET(AUTOINDENT)) {
1124 int non = 0;
1125
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001126 /* Grab the beginning of the next line until it's not a
1127 space or tab, then null terminate it so we can strcat it
1128 to hell */
1129 while ((inptr->next->data[non] == ' '
Chris Allegretta355fbe52001-07-14 19:32:47 +00001130 || inptr->next->data[non] == '\t')) {
1131 p[non] = inptr->next->data[non];
1132 non++;
1133 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001134 p[non] = 0;
1135 strcat(p, temp->data);
1136 strcat(p, " ");
1137
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001138 /* Now tack on the rest of the next line after the spaces and
1139 tabs */
Chris Allegretta94a78b82001-03-14 08:28:48 +00001140 strcat(p, &inptr->next->data[non]);
Chris Allegrettaff989832001-09-17 13:48:00 +00001141 } else
1142#endif
1143 {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001144 strcpy(p, temp->data);
1145 strcat(p, " ");
1146 strcat(p, inptr->next->data);
1147 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001148
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001149 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001150 inptr->next->data = p;
1151
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001152 free(temp->data);
1153 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001154
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001155 current_x = old_x;
1156 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001157 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001158 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001159 else {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001160
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001161 temp->prev = inptr;
1162 temp->next = inptr->next;
1163
1164 if (inptr->next)
1165 inptr->next->prev = temp;
1166 inptr->next = temp;
1167
1168 if (!temp->next)
1169 filebot = temp;
1170
1171 SET(SAMELINEWRAP);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001172
Chris Allegrettaff989832001-09-17 13:48:00 +00001173#ifndef NANO_SMALL
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001174 if (ISSET(AUTOINDENT)) {
1175 char *spc = inptr->data;
1176 char *t = NULL;
1177 int extra = 0;
1178 if (spc) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001179 while ((*spc == ' ') || (*spc == '\t')) {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001180 extra++;
1181 spc++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001182 totsize++;
Chris Allegretta438f7132002-01-16 00:54:47 +00001183 right++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001184 }
Chris Allegretta88b09152001-05-17 11:35:43 +00001185 t = charalloc(strlen(temp->data) + extra + 1);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001186 strncpy(t, inptr->data, extra);
1187 strcpy(t + extra, temp->data);
1188 free(temp->data);
1189 temp->data = t;
1190 }
1191 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001192#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001193 }
1194
1195
1196 totlines++;
Chris Allegretta88520c92001-05-05 17:45:54 +00001197 /* Everything about it makes me want this line here, but it causes
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001198 * totsize to be high by one for some reason. Sigh. (Rob) */
1199 /* totsize++; */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001200
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001201 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001202 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001203
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001204
1205 /* Move the cursor to the new line if appropriate. */
1206 if (down) {
1207 do_right();
1208 }
1209
1210 /* Move the cursor to the correct spot in the line if appropriate. */
1211 while (right--) {
1212 do_right();
1213 }
1214
Chris Allegretta234a34d2000-07-29 04:33:38 +00001215 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001216 reset_cursor();
1217 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001218}
1219
1220/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001221void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001222{
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001223 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001224#ifdef DEBUG
1225 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
1226 inptr->data);
1227#endif
1228
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001229 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001230 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001231 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001232 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001233
1234 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001235 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001236
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001237 while (isspace((int) inptr->data[i]) && inptr->data[i])
Adam Rogoyski09f97962000-06-20 02:50:33 +00001238 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001239
Adam Rogoyski09f97962000-06-20 02:50:33 +00001240 if (!inptr->data[i])
1241 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001242
Adam Rogoyski09f97962000-06-20 02:50:33 +00001243 /* String must be at least 1 character long. */
1244 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001245 if (isspace((int) inptr->data[i])) {
Adam Rogoyski09f97962000-06-20 02:50:33 +00001246 if (!char_found)
1247 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001248 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001249 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001250 } else
1251 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001252 }
Adam Rogoyski09f97962000-06-20 02:50:33 +00001253
1254 if (char_found == 2)
1255 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001256 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001257}
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001258#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001259
1260/* Stuff we do when we abort from programs and want to clean up the
Chris Allegretta88520c92001-05-05 17:45:54 +00001261 * screen. This doesn't do much right now.
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001262 */
1263void do_early_abort(void)
1264{
1265 blank_statusbar_refresh();
1266}
1267
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001268int do_backspace(void)
1269{
1270 filestruct *previous, *tmp;
1271
1272 if (current_x != 0) {
1273 /* Let's get dangerous */
1274 memmove(&current->data[current_x - 1], &current->data[current_x],
1275 strlen(current->data) - current_x + 1);
1276#ifdef DEBUG
1277 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
1278#endif
1279 align(&current->data);
1280 do_left();
1281 } else {
1282 if (current == fileage)
1283 return 0; /* Can't delete past top of file */
1284
1285 previous = current->prev;
1286 current_x = strlen(previous->data);
1287 previous->data = nrealloc(previous->data,
1288 strlen(previous->data) +
1289 strlen(current->data) + 1);
1290 strcat(previous->data, current->data);
1291
1292 tmp = current;
1293 unlink_node(current);
1294 delete_node(current);
1295 if (current == edittop) {
1296 if (previous->next)
1297 current = previous->next;
1298 else
1299 current = previous;
Chris Allegretta3e3ae942001-09-22 19:02:04 +00001300 page_up();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001301 } else {
1302 if (previous->next)
1303 current = previous->next;
1304 else
1305 current = previous;
1306 update_line(current, current_x);
1307 }
1308
1309 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001310 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001311 filebot = current;
1312 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001313
1314 /* Recreate the magic line if we're deleting it AND if the
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001315 line we're on now is NOT blank. if it is blank we
1316 can just use IT for the magic line. This is how Pico
1317 appears to do it, in any case */
Chris Allegretta28a0f892000-07-05 22:47:54 +00001318 if (strcmp(current->data, "")) {
1319 new_magicline();
1320 fix_editbot();
1321 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001322 }
1323
1324 current = previous;
1325 renumber(current);
1326 previous_line();
1327 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001328#ifdef DEBUG
1329 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
1330#endif
1331
1332 }
1333
1334 totsize--;
1335 set_modified();
1336 UNSET(KEEP_CUTBUFFER);
1337 edit_refresh();
1338 return 1;
1339}
1340
1341int do_delete(void)
1342{
1343 filestruct *foo;
1344
Chris Allegretta2084acc2001-11-29 03:43:08 +00001345 /* blbf -> blank line before filebot (see below) */
1346 int blbf = 0;
1347
1348 if (current->next == filebot && !strcmp(current->data, ""))
1349 blbf = 1;
1350
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001351 if (current_x != strlen(current->data)) {
1352 /* Let's get dangerous */
1353 memmove(&current->data[current_x], &current->data[current_x + 1],
1354 strlen(current->data) - current_x);
1355
1356 align(&current->data);
1357
Chris Allegretta2084acc2001-11-29 03:43:08 +00001358 /* Now that we have a magic line again, we can check for both being
1359 on the line before filebot as well as at filebot; it's a special
1360 case if we're on the line before filebot and it's blank, since we
1361 should be able to delete it */
1362 } else if (current->next != NULL && (current->next != filebot || blbf)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001363 current->data = nrealloc(current->data,
1364 strlen(current->data) +
1365 strlen(current->next->data) + 1);
1366 strcat(current->data, current->next->data);
1367
1368 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001369 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001370 filebot = current;
1371 editbot = current;
1372 }
1373
1374 unlink_node(foo);
1375 delete_node(foo);
1376 update_line(current, current_x);
1377
Chris Allegretta4ed13152001-02-10 17:50:50 +00001378 /* Please see the comment in do_backspace if you don't understand
Chris Allegretta28a0f892000-07-05 22:47:54 +00001379 this test */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001380 if (current == filebot && strcmp(current->data, "")) {
Chris Allegretta28a0f892000-07-05 22:47:54 +00001381 new_magicline();
1382 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001383 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001384 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001385 renumber(current);
1386 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001387 } else
1388 return 0;
1389
1390 totsize--;
1391 set_modified();
1392 UNSET(KEEP_CUTBUFFER);
1393 edit_refresh();
1394 return 1;
1395}
1396
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001397void wrap_reset(void)
1398{
1399 UNSET(SAMELINEWRAP);
1400}
1401
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001402#ifndef DISABLE_SPELLER
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001403
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001404int do_int_spell_fix(char *word)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001405{
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001406 char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001407 filestruct *begin;
Chris Allegretta23b74b22002-01-21 20:32:22 +00001408 int i = 0, j = 0, beginx, beginx_top, reverse_search_set;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001409
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001410 /* save where we are */
1411 begin = current;
1412 beginx = current_x + 1;
1413
Chris Allegretta23b74b22002-01-21 20:32:22 +00001414 /* Make sure Spell Check goes forward only */
1415 reverse_search_set = ISSET(REVERSE_SEARCH);
1416 UNSET(REVERSE_SEARCH);
1417
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001418 /* save the current search/replace strings */
1419 search_init_globals();
1420 save_search = mallocstrcpy(save_search, last_search);
1421 save_replace = mallocstrcpy(save_replace, last_replace);
1422
1423 /* set search/replace strings to mis-spelt word */
1424 prevanswer = mallocstrcpy(prevanswer, word);
1425 last_search = mallocstrcpy(last_search, word);
1426 last_replace = mallocstrcpy(last_replace, word);
1427
1428 /* start from the top of file */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001429 current = fileage;
1430 current_x = beginx_top = -1;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001431
1432 search_last_line = FALSE;
1433
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001434 edit_update(fileage, TOP);
1435
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001436 while (1) {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001437
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001438 /* make sure word is still mis-spelt (i.e. when multi-errors) */
1439 if (findnextstr(TRUE, FALSE, fileage, beginx_top, prevanswer) != NULL) {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001440
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001441 /* find wholewords only */
1442 if (!is_whole_word(current_x, current, prevanswer))
1443 continue;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001444
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001445 do_replace_highlight(TRUE, prevanswer);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001446
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001447 /* allow replace word to be corrected */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001448 i = statusq(0, spell_list, last_replace, _("Edit a replacement"));
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001449
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001450 do_replace_highlight(FALSE, prevanswer);
1451
1452 /* start from the start of this line again */
1453 current = fileage;
1454 current_x = beginx_top;
1455
1456 search_last_line = FALSE;
1457
1458 if (strcmp(prevanswer,answer) != 0) {
1459 j = i;
1460 do_replace_loop(prevanswer, fileage, &beginx_top, TRUE, &j);
1461 }
Chris Allegretta80838272001-12-02 06:03:22 +00001462 }
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001463
1464 break;
Rocco Corsi562964d2002-01-13 03:18:03 +00001465 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001466
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001467 /* restore the search/replace strings */
Chris Allegrettabef12972002-03-06 03:30:40 +00001468 free(last_search); last_search=save_search;
1469 free(last_replace); last_replace=save_replace;
1470 free(prevanswer);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001471
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001472 /* restore where we were */
1473 current = begin;
1474 current_x = beginx - 1;
1475
Chris Allegretta23b74b22002-01-21 20:32:22 +00001476 /* restore Search/Replace direction */
1477 if (reverse_search_set)
1478 SET(REVERSE_SEARCH);
1479
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001480 edit_update(current, CENTER);
1481
1482 if (i == -1)
1483 return FALSE;
1484
1485 return TRUE;
1486}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001487
1488/* Integrated spell checking using 'spell' program */
Chris Allegretta271e9722000-11-10 18:15:43 +00001489int do_int_speller(char *tempfile_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001490{
Chris Allegretta271e9722000-11-10 18:15:43 +00001491 char *read_buff, *read_buff_ptr, *read_buff_word;
Chris Allegrettaf21f3fc2002-03-25 03:26:27 +00001492 size_t pipe_buff_size, read_buff_size, read_buff_read, bytesread;
Chris Allegretta271e9722000-11-10 18:15:43 +00001493 int in_fd[2], tempfile_fd;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001494 int spell_status;
1495 pid_t pid_spell;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001496
Chris Allegretta271e9722000-11-10 18:15:43 +00001497 /* Create a pipe to spell program */
1498
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001499 if (pipe(in_fd) == -1)
1500 return FALSE;
1501
Chris Allegretta271e9722000-11-10 18:15:43 +00001502 /* A new process to run spell in */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001503
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001504 if ((pid_spell = fork()) == 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001505
1506 /* Child continues, (i.e. future spell process) */
1507
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001508 close(in_fd[0]);
1509
Chris Allegretta271e9722000-11-10 18:15:43 +00001510 /* replace the standard in with the tempfile */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001511
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001512 if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001513
1514 close(in_fd[1]);
1515 exit(1);
1516 }
1517
1518 if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
1519
1520 close(tempfile_fd);
1521 close(in_fd[1]);
1522 exit(1);
1523 }
1524 close(tempfile_fd);
1525
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001526
Chris Allegretta271e9722000-11-10 18:15:43 +00001527 /* send spell's standard out to the pipe */
1528
1529 if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1530
1531 close(in_fd[1]);
1532 exit(1);
1533 }
1534 close(in_fd[1]);
1535
1536 /* Start spell program, we are using the PATH here!?!? */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001537 execlp("spell", "spell", NULL);
1538
Chris Allegretta271e9722000-11-10 18:15:43 +00001539 /* Should not be reached, if spell is found!!! */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001540
Chris Allegretta271e9722000-11-10 18:15:43 +00001541 exit(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001542 }
1543
1544 /* Parent continues here */
1545
Chris Allegretta271e9722000-11-10 18:15:43 +00001546 close(in_fd[1]);
1547
1548 /* Child process was not forked successfully */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001549
1550 if (pid_spell < 0) {
1551
Chris Allegretta271e9722000-11-10 18:15:43 +00001552 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001553 return FALSE;
1554 }
1555
Chris Allegretta271e9722000-11-10 18:15:43 +00001556 /* Get system pipe buffer size */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001557
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001558 if ((pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001559
Chris Allegretta271e9722000-11-10 18:15:43 +00001560 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001561 return FALSE;
Chris Allegretta271e9722000-11-10 18:15:43 +00001562 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001563
Chris Allegrettaf21f3fc2002-03-25 03:26:27 +00001564 /* Read-in the returned spelling errors */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001565
Chris Allegrettaf21f3fc2002-03-25 03:26:27 +00001566 read_buff_read = 0;
1567 read_buff_size = pipe_buff_size + 1;
1568 read_buff = read_buff_ptr = charalloc(read_buff_size);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001569
Chris Allegrettaf21f3fc2002-03-25 03:26:27 +00001570 while ((bytesread = read(in_fd[0], read_buff_ptr, pipe_buff_size)) > 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001571
Chris Allegrettaf21f3fc2002-03-25 03:26:27 +00001572 read_buff_read += bytesread;
1573 read_buff_size += pipe_buff_size;
1574 read_buff = read_buff_ptr = nrealloc(read_buff, read_buff_size);
1575 read_buff_ptr += read_buff_read;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001576 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001577
Chris Allegrettaf21f3fc2002-03-25 03:26:27 +00001578 *read_buff_ptr = (char) NULL;
Chris Allegretta271e9722000-11-10 18:15:43 +00001579 close(in_fd[0]);
Chris Allegrettaf21f3fc2002-03-25 03:26:27 +00001580
1581 /* Process the spelling errors */
1582
1583 read_buff_word = read_buff_ptr = read_buff;
1584
1585 while (*read_buff_ptr) {
1586
1587 if ((*read_buff_ptr == '\n') || (*read_buff_ptr == '\r')) {
1588 *read_buff_ptr = (char) NULL;
1589 if (read_buff_word != read_buff_ptr) {
1590 if (!do_int_spell_fix(read_buff_word)) {
1591 read_buff_word = read_buff_ptr;
1592 break;
1593 }
1594 }
1595
1596 read_buff_word = read_buff_ptr + 1;
1597 }
1598
1599 read_buff_ptr++;
1600 }
1601
1602 /* special case where last word doesn't end with \n or \r */
1603 if (read_buff_word != read_buff_ptr)
1604 do_int_spell_fix(read_buff_word);
1605
Chris Allegretta271e9722000-11-10 18:15:43 +00001606 free(read_buff);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001607 replace_abort();
1608
Chris Allegretta271e9722000-11-10 18:15:43 +00001609 /* Process end of spell process */
1610
1611 wait(&spell_status);
1612 if (WIFEXITED(spell_status)) {
1613 if (WEXITSTATUS(spell_status) != 0)
1614 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001615 } else
Chris Allegretta271e9722000-11-10 18:15:43 +00001616 return FALSE;
1617
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001618 return TRUE;
1619}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001620
1621/* External spell checking */
Chris Allegretta271e9722000-11-10 18:15:43 +00001622int do_alt_speller(char *file_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001623{
Chris Allegrettab3655b42001-10-22 03:15:31 +00001624 int alt_spell_status, lineno_cur = current->lineno;
1625 int x_cur = current_x, y_cur = current_y, pww_cur = placewewant;
1626
Chris Allegretta271e9722000-11-10 18:15:43 +00001627 pid_t pid_spell;
Chris Allegretta169ee842001-01-26 01:57:32 +00001628 char *ptr;
1629 static int arglen = 3;
1630 static char **spellargs = (char **) NULL;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001631
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001632 endwin();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001633
Chris Allegrettae434b452001-01-27 19:25:00 +00001634 /* Set up an argument list to pass the execvp function */
1635 if (spellargs == NULL) {
1636 spellargs = nmalloc(arglen * sizeof(char *));
Chris Allegretta271e9722000-11-10 18:15:43 +00001637
Chris Allegrettae434b452001-01-27 19:25:00 +00001638 spellargs[0] = strtok(alt_speller, " ");
1639 while ((ptr = strtok(NULL, " ")) != NULL) {
1640 arglen++;
1641 spellargs = nrealloc(spellargs, arglen * sizeof(char *));
1642 spellargs[arglen - 3] = ptr;
Chris Allegretta169ee842001-01-26 01:57:32 +00001643 }
Chris Allegrettae434b452001-01-27 19:25:00 +00001644 spellargs[arglen - 1] = NULL;
1645 }
1646 spellargs[arglen - 2] = file_name;
1647
1648 /* Start a new process for the alternate speller */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001649 if ((pid_spell = fork()) == 0) {
Chris Allegretta169ee842001-01-26 01:57:32 +00001650
Chris Allegretta88520c92001-05-05 17:45:54 +00001651 /* Start alternate spell program; we are using the PATH here!?!? */
Chris Allegretta169ee842001-01-26 01:57:32 +00001652 execvp(spellargs[0], spellargs);
Chris Allegretta271e9722000-11-10 18:15:43 +00001653
1654 /* Should not be reached, if alternate speller is found!!! */
1655
1656 exit(1);
1657 }
1658
1659 /* Could not fork?? */
1660
1661 if (pid_spell < 0)
1662 return FALSE;
1663
1664 /* Wait for alternate speller to complete */
1665
1666 wait(&alt_spell_status);
1667 if (WIFEXITED(alt_spell_status)) {
1668 if (WEXITSTATUS(alt_spell_status) != 0)
1669 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001670 } else
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001671 return FALSE;
1672
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001673 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001674 free_filestruct(fileage);
Chris Allegretta56214c62001-09-27 02:46:53 +00001675 global_init(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001676 open_file(file_name, 0, 1);
Rocco Corsi4dfaf932001-04-20 01:59:55 +00001677
Chris Allegretta1b3381b2001-09-28 21:59:01 +00001678 /* go back to the old position, mark the file as modified, and make
1679 sure that the titlebar is refreshed */
1680 do_gotopos(lineno_cur, x_cur, y_cur, pww_cur);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001681 set_modified();
Chris Allegrettae1f14522001-09-19 03:19:43 +00001682 clearok(topwin, FALSE);
1683 titlebar(NULL);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001684
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001685 return TRUE;
1686}
1687#endif
1688
1689int do_spell(void)
1690{
1691
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001692#ifdef DISABLE_SPELLER
Chris Allegrettaff269f82000-12-01 18:46:01 +00001693 nano_disabled_msg();
1694 return (TRUE);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001695#else
Chris Allegretta271e9722000-11-10 18:15:43 +00001696 char *temp;
1697 int spell_res;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001698
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001699 if ((temp = safe_tempnam(0, "nano.")) == NULL) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001700 statusbar(_("Could not create a temporary filename: %s"),
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001701 strerror(errno));
Chris Allegretta271e9722000-11-10 18:15:43 +00001702 return 0;
1703 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001704
Chris Allegrettaecc3d7f2001-06-05 23:24:55 +00001705 if (write_file(temp, 1, 0, 0) == -1) {
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001706 statusbar(_("Spell checking failed: unable to write temp file!"));
Chris Allegrettabef12972002-03-06 03:30:40 +00001707 free(temp);
Chris Allegretta271e9722000-11-10 18:15:43 +00001708 return 0;
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001709 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001710
Chris Allegrettae1f14522001-09-19 03:19:43 +00001711#ifdef ENABLE_MULTIBUFFER
1712 /* update the current open_files entry before spell-checking, in case
1713 any problems occur; the case of there being no open_files entries
Chris Allegretta48b06702002-02-22 04:30:50 +00001714 is handled elsewhere (before we reach this point) */
1715 add_open_file(1);
Chris Allegrettae1f14522001-09-19 03:19:43 +00001716#endif
1717
Chris Allegretta271e9722000-11-10 18:15:43 +00001718 if (alt_speller)
1719 spell_res = do_alt_speller(temp);
1720 else
1721 spell_res = do_int_speller(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001722
Chris Allegretta271e9722000-11-10 18:15:43 +00001723 remove(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001724
1725 if (spell_res)
1726 statusbar(_("Finished checking spelling"));
1727 else
1728 statusbar(_("Spell checking failed"));
1729
Chris Allegrettabef12972002-03-06 03:30:40 +00001730 free(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001731 return spell_res;
1732
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001733#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001734}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001735
1736int do_exit(void)
1737{
1738 int i;
1739
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001740 if (!ISSET(MODIFIED)) {
1741
Chris Allegretta355fbe52001-07-14 19:32:47 +00001742#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001743 if (!close_open_file()) {
1744 display_main_list();
1745 return 1;
1746 }
1747 else
1748#endif
1749
1750 finish(0);
1751 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001752
Chris Allegretta30885552000-07-14 01:20:12 +00001753 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001754 i = 1;
1755 } else {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001756 i = do_yesno(0, 0,
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001757 _
1758 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1759 }
1760
1761#ifdef DEBUG
1762 dump_buffer(fileage);
1763#endif
1764
1765 if (i == 1) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001766 if (do_writeout(filename, 1, 0) > 0) {
1767
Chris Allegretta355fbe52001-07-14 19:32:47 +00001768#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001769 if (!close_open_file()) {
1770 display_main_list();
1771 return 1;
1772 }
1773 else
1774#endif
1775
1776 finish(0);
1777 }
1778 } else if (i == 0) {
1779
Chris Allegretta355fbe52001-07-14 19:32:47 +00001780#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001781 if (!close_open_file()) {
1782 display_main_list();
1783 return 1;
1784 }
1785 else
1786#endif
1787
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001788 finish(0);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001789 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001790 statusbar(_("Cancelled"));
1791
1792 display_main_list();
1793 return 1;
1794}
1795
Chris Allegretta84de5522001-04-12 14:51:48 +00001796#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001797#ifdef NCURSES_MOUSE_VERSION
1798void do_mouse(void)
1799{
1800 MEVENT mevent;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001801 int foo = 0, tab_found = 0;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001802 int currslen;
Chris Allegretta40639dd2002-03-04 12:25:34 +00001803 shortcut *s = currshortcut;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001804
1805 if (getmouse(&mevent) == ERR)
1806 return;
1807
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001808 /* If mouse not in edit or bottom window, return */
1809 if (wenclose(edit, mevent.y, mevent.x)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001810
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001811 /* Don't let people screw with the marker when they're in a
1812 subfunction */
1813 if (currshortcut != main_list)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001814 return;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001815
1816 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1817 mevent.y -= 2;
1818
1819 /* Selecting where the cursor is sets the mark.
1820 * Selecting beyond the line length with the cursor at the end of the
1821 * line sets the mark as well.
1822 */
1823 if ((mevent.y == current_y) &&
1824 ((mevent.x == current_x) || (current_x == strlen(current->data)
1825 && (mevent.x >
1826 strlen(current->data))))) {
1827 if (ISSET(VIEW_MODE)) {
1828 print_view_warning();
1829 return;
1830 }
1831 do_mark();
1832 } else if (mevent.y > current_y) {
1833 while (mevent.y > current_y) {
1834 if (current->next != NULL)
1835 current = current->next;
1836 else
1837 break;
1838 current_y++;
1839 }
1840 } else if (mevent.y < current_y) {
1841 while (mevent.y < current_y) {
1842 if (current->prev != NULL)
1843 current = current->prev;
1844 else
1845 break;
1846 current_y--;
1847 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001848 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001849 current_x = mevent.x;
1850 placewewant = current_x;
1851 while (foo < current_x) {
1852 if (current->data[foo] == NANO_CONTROL_I) {
1853 current_x -= tabsize - (foo % tabsize);
1854 tab_found = 1;
1855 } else if (current->data[foo] & 0x80);
1856 else if (current->data[foo] < 32)
1857 current_x--;
1858 foo++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001859 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001860 /* This is where tab_found comes in. I can't figure out why,
1861 * but without it any line with a tab will place the cursor
1862 * one character behind. Whatever, this fixes it. */
1863 if (tab_found == 1)
1864 current_x++;
1865
1866 if (current_x > strlen(current->data))
1867 current_x = strlen(current->data);
1868
1869 update_cursor();
1870 edit_refresh();
1871 } else if (wenclose(bottomwin, mevent.y, mevent.x) && !ISSET(NO_HELP)) {
Chris Allegrettaa951f212001-09-27 21:07:39 +00001872
Chris Allegretta40639dd2002-03-04 12:25:34 +00001873 int i, k;
Chris Allegrettaa951f212001-09-27 21:07:39 +00001874
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001875 if (currshortcut == main_list)
1876 currslen = MAIN_VISIBLE;
1877 else
1878 currslen = length_of_list(currshortcut);
1879
Chris Allegrettaa951f212001-09-27 21:07:39 +00001880 if (currslen < 2)
1881 k = COLS / 6;
1882 else
1883 k = COLS / ((currslen + (currslen %2)) / 2);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001884
1885 /* Determine what shortcut list was clicked */
1886 mevent.y -= (editwinrows + 3);
1887
1888 if (mevent.y < 0) /* They clicked on the statusbar */
1889 return;
1890
1891 /* Don't select stuff beyond list length */
1892 if (mevent.x / k >= currslen)
1893 return;
1894
Chris Allegretta40639dd2002-03-04 12:25:34 +00001895 for (i = 0; i < (mevent.x / k) * 2 + mevent.y; i++)
1896 s = s->next;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001897
1898 /* And ungetch that value */
Chris Allegretta40639dd2002-03-04 12:25:34 +00001899 ungetch(s->val);
Chris Allegretta6414b402001-09-21 03:21:11 +00001900
1901 /* And if it's an alt-key sequence, we should probably send alt
1902 too ;-) */
Chris Allegretta40639dd2002-03-04 12:25:34 +00001903 if (s->val >= 'a' && s->val <= 'z')
Chris Allegretta6414b402001-09-21 03:21:11 +00001904 ungetch(27);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001905 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001906}
1907#endif
1908#endif
1909
1910/* Handler for SIGHUP */
1911RETSIGTYPE handle_hup(int signal)
1912{
Chris Allegrettae7a58932000-12-02 02:36:22 +00001913 die(_("Received SIGHUP"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001914}
1915
Chris Allegretta18f8be02000-09-04 03:20:38 +00001916/* What do we do when we catch the suspend signal */
1917RETSIGTYPE do_suspend(int signal)
1918{
Chris Allegretta18f8be02000-09-04 03:20:38 +00001919 endwin();
Chris Allegretta521e00d2001-06-28 16:52:52 +00001920 printf("\n\n\n\n\nUse \"fg\" to return to nano\n");
1921 fflush(stdout);
1922
Chris Allegretta7b0667f2002-01-10 12:44:21 +00001923 /* Restore the terminal settings for the disabled keys */
1924 tcsetattr(0, TCSANOW, &oldterm);
1925
Chris Allegretta521e00d2001-06-28 16:52:52 +00001926 /* We used to re-enable the default SIG_DFL and raise SIGTSTP, but
1927 then we could be (and were) interrupted in the middle of the call.
1928 So we do it the mutt way instead */
1929 kill(0, SIGSTOP);
Chris Allegretta18f8be02000-09-04 03:20:38 +00001930}
1931
1932/* Restore the suspend handler when we come back into the prog */
1933RETSIGTYPE do_cont(int signal)
1934{
1935
Chris Allegretta521e00d2001-06-28 16:52:52 +00001936 /* Now we just update the screen instead of having to reenable the
1937 SIGTSTP handler */
1938
Chris Allegretta521e00d2001-06-28 16:52:52 +00001939 doupdate();
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00001940 /* The Hurd seems to need this, otherwise a ^Y after a ^Z will
1941 start suspending again */
1942 signal_init();
Chris Allegretta18f8be02000-09-04 03:20:38 +00001943}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001944
1945void handle_sigwinch(int s)
1946{
1947#ifndef NANO_SMALL
1948 char *tty = NULL;
1949 int fd = 0;
1950 int result = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001951 struct winsize win;
1952
1953 tty = ttyname(0);
1954 if (!tty)
1955 return;
1956 fd = open(tty, O_RDWR);
1957 if (fd == -1)
1958 return;
1959 result = ioctl(fd, TIOCGWINSZ, &win);
1960 if (result == -1)
1961 return;
1962
1963
1964 COLS = win.ws_col;
1965 LINES = win.ws_row;
1966
Chris Allegrettae61e8302001-01-14 05:18:27 +00001967 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1968 die_too_small();
1969
Chris Allegretta6fe61492001-05-21 12:56:25 +00001970#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettae61e8302001-01-14 05:18:27 +00001971 if ((fill = COLS - CHARS_FROM_EOL) < MIN_FILL_LENGTH)
1972 die_too_small();
Chris Allegretta6fe61492001-05-21 12:56:25 +00001973#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001974
Chris Allegretta0a06e072001-01-23 02:35:04 +00001975 hblank = nrealloc(hblank, COLS + 1);
1976 memset(hblank, ' ', COLS);
1977 hblank[COLS] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001978
Chris Allegretta618f5d72001-02-16 04:48:30 +00001979#ifdef HAVE_RESIZETERM
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001980 resizeterm(LINES, COLS);
1981#ifdef HAVE_WRESIZE
1982 if (wresize(topwin, 2, COLS) == ERR)
1983 die(_("Cannot resize top win"));
1984 if (mvwin(topwin, 0, 0) == ERR)
1985 die(_("Cannot move top win"));
1986 if (wresize(edit, editwinrows, COLS) == ERR)
1987 die(_("Cannot resize edit win"));
1988 if (mvwin(edit, 2, 0) == ERR)
1989 die(_("Cannot move edit win"));
1990 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1991 die(_("Cannot resize bottom win"));
1992 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1993 die(_("Cannot move bottom win"));
1994#endif /* HAVE_WRESIZE */
Chris Allegretta618f5d72001-02-16 04:48:30 +00001995#endif /* HAVE_RESIZETERM */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001996
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001997 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001998
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001999 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00002000 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002001 }
2002 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00002003
2004 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002005 refresh();
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002006 titlebar(NULL);
Chris Allegretta97accc62000-06-19 05:45:52 +00002007 edit_refresh();
2008 display_main_list();
Chris Allegretta08020882001-01-29 23:37:54 +00002009 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002010 total_refresh();
Chris Allegretta08020882001-01-29 23:37:54 +00002011
Chris Allegretta4e90c402001-01-29 23:40:43 +00002012 /* Turn cursor back on for sure */
2013 curs_set(1);
2014
Chris Allegretta08020882001-01-29 23:37:54 +00002015 /* Jump back to mainloop */
2016 siglongjmp(jmpbuf, 1);
2017
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002018#endif
2019}
2020
Chris Allegretta756f2202000-09-01 13:32:47 +00002021void signal_init(void)
2022{
Chris Allegrettaac899e52001-06-30 04:09:09 +00002023#ifdef _POSIX_VDISABLE
2024 struct termios term;
2025#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002026
Chris Allegretta88520c92001-05-05 17:45:54 +00002027 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
Chris Allegretta756f2202000-09-01 13:32:47 +00002028 memset(&act, 0, sizeof(struct sigaction));
2029 act.sa_handler = SIG_IGN;
2030 sigaction(SIGINT, &act, NULL);
Chris Allegretta756f2202000-09-01 13:32:47 +00002031
Chris Allegretta88520c92001-05-05 17:45:54 +00002032 /* Trap SIGHUP cuz we want to write the file out. */
Chris Allegretta756f2202000-09-01 13:32:47 +00002033 act.sa_handler = handle_hup;
2034 sigaction(SIGHUP, &act, NULL);
2035
2036 act.sa_handler = handle_sigwinch;
2037 sigaction(SIGWINCH, &act, NULL);
2038
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002039
2040#ifdef _POSIX_VDISABLE
Chris Allegretta8e207bf2002-03-29 15:31:54 +00002041 tcgetattr(0, &oldterm);
2042
2043 term = oldterm;
2044 term.c_cc[VINTR] = _POSIX_VDISABLE;
2045 term.c_cc[VQUIT] = _POSIX_VDISABLE;
2046 term.c_lflag &= ~IEXTEN;
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002047
2048#ifdef VDSUSP
2049 term.c_cc[VDSUSP] = _POSIX_VDISABLE;
2050#endif /* VDSUSP */
2051
2052#endif /* _POSIX_VDISABLE */
2053
Chris Allegretta521e00d2001-06-28 16:52:52 +00002054 if (!ISSET(SUSPEND)) {
Chris Allegrettaac899e52001-06-30 04:09:09 +00002055
2056/* Insane! */
2057#ifdef _POSIX_VDISABLE
Chris Allegrettaac899e52001-06-30 04:09:09 +00002058 term.c_cc[VSUSP] = _POSIX_VDISABLE;
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002059#else
Chris Allegrettaac899e52001-06-30 04:09:09 +00002060 act.sa_handler = SIG_IGN;
Chris Allegretta521e00d2001-06-28 16:52:52 +00002061 sigaction(SIGTSTP, &act, NULL);
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002062#endif
Chris Allegrettaac899e52001-06-30 04:09:09 +00002063
Chris Allegretta521e00d2001-06-28 16:52:52 +00002064 } else {
2065 /* if we don't do this, it seems other stuff interrupts the
2066 suspend handler! Try using nano with mutt without this line */
2067 sigfillset(&act.sa_mask);
2068
2069 act.sa_handler = do_suspend;
2070 sigaction(SIGTSTP, &act, NULL);
2071
2072 act.sa_handler = do_cont;
2073 sigaction(SIGCONT, &act, NULL);
2074 }
2075
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002076
2077#ifdef _POSIX_VDISABLE
2078 tcsetattr(0, TCSANOW, &term);
2079#endif
2080
2081
Chris Allegretta756f2202000-09-01 13:32:47 +00002082}
2083
Chris Allegretta2a42af12000-09-12 23:02:49 +00002084void window_init(void)
2085{
Chris Allegrettae61e8302001-01-14 05:18:27 +00002086 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
2087 die_too_small();
Chris Allegretta92c9dd22000-09-13 14:03:27 +00002088
Chris Allegretta88520c92001-05-05 17:45:54 +00002089 /* Set up the main text window */
Chris Allegretta2a42af12000-09-12 23:02:49 +00002090 edit = newwin(editwinrows, COLS, 2, 0);
2091
2092 /* And the other windows */
2093 topwin = newwin(2, COLS, 0, 0);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002094 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002095
Chris Allegretta155d6202001-01-08 01:50:37 +00002096#ifdef PDCURSES
2097 /* Oops, I guess we need this again.
2098 Moved here so the keypad still works after a Meta-X, for example */
2099 keypad(edit, TRUE);
2100 keypad(bottomwin, TRUE);
2101#endif
2102
Chris Allegretta2a42af12000-09-12 23:02:49 +00002103}
2104
Chris Allegretta756f2202000-09-01 13:32:47 +00002105void mouse_init(void)
2106{
Chris Allegretta84de5522001-04-12 14:51:48 +00002107#ifndef DISABLE_MOUSE
Chris Allegretta756f2202000-09-01 13:32:47 +00002108#ifdef NCURSES_MOUSE_VERSION
2109 if (ISSET(USE_MOUSE)) {
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002110 keypad_on(edit, 1);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002111 keypad_on(bottomwin, 1);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002112
Chris Allegretta756f2202000-09-01 13:32:47 +00002113 mousemask(BUTTON1_RELEASED, NULL);
2114 mouseinterval(50);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00002115
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002116 } else
Chris Allegretta756f2202000-09-01 13:32:47 +00002117 mousemask(0, NULL);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002118
Chris Allegretta756f2202000-09-01 13:32:47 +00002119#endif
2120#endif
2121
2122}
2123
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002124int do_tab(void)
2125{
2126 do_char('\t');
2127 return 1;
2128}
2129
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002130#ifndef DISABLE_JUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002131int empty_line(const char *data)
2132{
2133 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002134 if (!isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002135 return 0;
2136
2137 data++;
2138 }
2139
2140 return 1;
2141}
2142
2143int no_spaces(const char *data)
2144{
2145 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002146 if (isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002147 return 0;
2148
2149 data++;
2150 }
2151
2152 return 1;
2153}
2154
2155void justify_format(char *data)
2156{
2157 int i = 0;
2158 int len = strlen(data);
2159
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002160 /* Skip leading whitespace. */
2161 for (i = 0; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002162 if (!isspace((int) data[i]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002163 break;
2164 }
2165
2166 i++; /* (i) is now at least 2. */
2167
2168 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
2169 for (; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002170 if (isspace((int) data[i]) && isspace((int) data[i - 1])
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002171 && (data[i - 2] != '.')
2172 && (data[i-2]!='!') && (data[i-2]!='?')) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002173 memmove(data + i, data + i + 1, len - i);
2174 len--;
2175 i--;
2176 }
2177 }
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002178 /* Skip trailing whitespace.
2179 * i<=len iff there was a non-space in the line. In that case, we
2180 * strip spaces from the end of the line. Note that "line" means the
2181 * whole paragraph. */
2182 if (i<=len) {
2183 for(i=len-1; i>0 && isspace((int) data[i]); i--);
2184 data[i+1] = '\0';
2185 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002186}
2187#endif
2188
2189int do_justify(void)
2190{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002191#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +00002192 nano_disabled_msg();
2193 return 1;
2194#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002195 int slen = 0; /* length of combined lines on one line. */
Chris Allegrettabef12972002-03-06 03:30:40 +00002196 int initial_y, kbinput = 0;
2197 long totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002198 filestruct *initial = NULL, *tmpjust = NULL, *cutbak, *tmptop, *tmpbot;
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002199 filestruct *samecheck = current;
2200 int qdepth = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002201
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002202 /* Compute quote depth level */
2203 while (!strncmp(&current->data[qdepth], quotestr, strlen(quotestr)))
2204 qdepth += strlen(quotestr);
2205
2206 if (empty_line(&current->data[qdepth])) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002207 /* Justify starting at first non-empty line. */
2208 do {
2209 if (!current->next)
2210 return 1;
2211
2212 current = current->next;
2213 current_y++;
2214 }
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002215 while (strlen(current->data) >= qdepth
2216 && !strncmp(current->data, samecheck->data, qdepth)
2217 && empty_line(&current->data[qdepth]));
2218
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002219 } else {
2220 /* Search back for the beginning of the paragraph, where
2221 * Paragraph is 1) A line with leading whitespace
2222 * or 2) A line following an empty line.
2223 */
2224 while (current->prev != NULL) {
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002225 if (strncmp(current->data, samecheck->data, qdepth)
2226
2227 /* Don't keep going back if the previous line is more
2228 intented quotestr-wise than samecheck */
2229 || !strncmp(&current->data[qdepth], quotestr, strlen(quotestr))
2230 || isspace((int) current->data[qdepth])
2231 || empty_line(&current->data[qdepth]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002232 break;
2233
2234 current = current->prev;
2235 current_y--;
2236 }
2237
2238 /* First line with leading whitespace may be empty. */
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002239 if (strncmp(current->data, samecheck->data, qdepth)
2240 || !strncmp(&current->data[qdepth], quotestr, strlen(quotestr))
2241 || empty_line(&current->data[qdepth])) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002242 if (current->next) {
2243 current = current->next;
2244 current_y++;
2245 } else
2246 return 1;
2247 }
2248 }
2249 initial = current;
2250 initial_y = current_y;
2251
2252 set_modified();
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002253 cutbak = cutbuffer; /* Got to like cutbak ;) */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002254 totbak = totsize;
Chris Allegretta9149e612000-11-27 00:23:41 +00002255 cutbuffer = NULL;
2256
2257 tmptop = current;
2258 tmpjust = copy_node(current);
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002259 samecheck = tmpjust;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002260
2261 /* This is annoying because it mucks with totsize */
Chris Allegretta9149e612000-11-27 00:23:41 +00002262 add_to_cutbuffer(tmpjust);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002263
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002264 /* Put the whole paragraph into one big line. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002265 while (current->next && !isspace((int) current->next->data[0])
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002266 && !strncmp(current->next->data, samecheck->data, qdepth)
Chris Allegretta46c1b9e2002-03-05 19:58:45 +00002267
2268 /* Don't continue if current->next is indented more! */
2269 && strncmp(&current->next->data[qdepth], quotestr, strlen(quotestr))
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002270 && !empty_line(&current->next->data[qdepth])) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002271 filestruct *tmpnode = current->next;
2272 int len = strlen(current->data);
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002273 int len2 = strlen(current->next->data) - qdepth;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002274
Chris Allegretta9149e612000-11-27 00:23:41 +00002275 tmpjust = NULL;
Chris Allegretta9149e612000-11-27 00:23:41 +00002276 tmpjust = copy_node(current->next);
2277 add_to_cutbuffer(tmpjust);
2278
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002279 /* Wiping out a newline */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002280 totsize--;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002281
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002282 /* length of both strings plus space between strings and ending \0. */
2283 current->data = nrealloc(current->data, len + len2 + 2);
2284 current->data[len++] = ' ';
2285 current->data[len] = '\0';
2286
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002287 strncat(current->data, &current->next->data[qdepth], len2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002288
2289 unlink_node(tmpnode);
2290 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002291 }
2292
2293 justify_format(current->data);
2294
2295 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002296 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002297
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002298 if ((strlenpt(current->data) > (fill))
Chris Allegrettacf1d8122002-03-21 19:53:36 +00002299 && !no_spaces(current->data + qdepth)) {
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002300 do {
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002301 int i = 0, j = 0;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002302 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002303
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002304
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002305/* The following code maybe could be better. In particular, can we
2306 * merely increment instead of calling strnlenpt for each new character?
2307 * In fact, can we assume the only tabs are at the beginning of the line?
2308 */
2309/* Note that we CAN break before the first word, since that is how
2310 * pico does it. */
2311 int last_space = -1; /* index of the last breakpoint */
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002312
Chris Allegrettacf1d8122002-03-21 19:53:36 +00002313 for(i=qdepth; i<slen; i++) {
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002314 if (isspace((int) current->data[i])) last_space = i;
2315 if (last_space!=-1 &&
Chris Allegrettacf1d8122002-03-21 19:53:36 +00002316 /* ARGH! We must look at the length of the first i+1 characters. */
2317 strnlenpt(current->data,i+1) > fill) {
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002318 i = last_space;
2319 break;
2320 }
2321 }
2322/* Now data[i] is a space. We want to break at the LAST space in this
2323 * group. Probably, the only possibility is two in a row, but let's be
2324 * generic. Note that we actually replace this final space with \0. Is
2325 * this okay? It seems to work fine. */
2326 for(; i<slen-1 && isspace((int) current->data[i+1]); i++) ;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002327
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002328 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002329
Chris Allegrettacf1d8122002-03-21 19:53:36 +00002330 slen -= i + 1 - qdepth; /* note i > qdepth */
2331 tmpline->data = charalloc(slen + 1);
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002332
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002333 for (j = 0; j < qdepth; j += strlen(quotestr))
2334 strcpy(&tmpline->data[j], quotestr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002335
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002336 /* Skip the white space in current. */
Chris Allegrettacf1d8122002-03-21 19:53:36 +00002337 memcpy(&tmpline->data[qdepth], current->data + i + 1, slen-qdepth);
2338 tmpline->data[slen] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002339
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002340 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002341
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002342 tmpline->prev = current;
2343 tmpline->next = current->next;
2344 if (current->next != NULL)
2345 current->next->prev = tmpline;
2346
2347 current->next = tmpline;
2348 current = tmpline;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002349 current_y++;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002350 } while ((strlenpt(current->data) > (fill))
Chris Allegrettacf1d8122002-03-21 19:53:36 +00002351 && !no_spaces(current->data + qdepth));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002352 }
Chris Allegretta9149e612000-11-27 00:23:41 +00002353 tmpbot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002354
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002355 if (current->next)
2356 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00002357 else
2358 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002359 current_x = 0;
2360 placewewant = 0;
2361
Adam Rogoyski09f97962000-06-20 02:50:33 +00002362 renumber(initial);
2363 totlines = filebot->lineno;
2364
2365 werase(edit);
2366
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002367 if ((current_y < 0) || (current_y >= editwinrows - 1)
2368 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00002369 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002370 center_cursor();
2371 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00002372 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002373 }
2374
Adam Rogoyski09f97962000-06-20 02:50:33 +00002375 edit_refresh();
Chris Allegretta9149e612000-11-27 00:23:41 +00002376 statusbar(_("Can now UnJustify!"));
Chris Allegretta07798352000-11-27 22:58:23 +00002377 /* Change the shortcut list to display the unjustify code */
2378 shortcut_init(1);
2379 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002380 reset_cursor();
2381
Chris Allegretta88520c92001-05-05 17:45:54 +00002382 /* Now get a keystroke and see if it's unjustify; if not, unget the keystroke
Chris Allegretta9149e612000-11-27 00:23:41 +00002383 and return */
Chris Allegretta5f071802001-05-06 02:34:31 +00002384
2385#ifndef DISABLE_MOUSE
2386#ifdef NCURSES_MOUSE_VERSION
2387
2388 /* If it was a mouse click, parse it with do_mouse and it might become
2389 the unjustify key. Else give it back to the input stream. */
2390 if ((kbinput = wgetch(edit)) == KEY_MOUSE)
2391 do_mouse();
2392 else
2393 ungetch(kbinput);
2394#endif
2395#endif
2396
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002397 if ((kbinput = wgetch(edit)) != NANO_UNJUSTIFY_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002398 ungetch(kbinput);
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002399 blank_statusbar_refresh();
2400 } else {
Chris Allegretta9149e612000-11-27 00:23:41 +00002401 /* Else restore the justify we just did (ungrateful user!) */
2402 if (tmptop->prev != NULL)
2403 tmptop->prev->next = tmpbot->next;
Chris Allegrettad022eac2000-11-27 02:50:49 +00002404 else
2405 fileage = current;
Chris Allegretta9149e612000-11-27 00:23:41 +00002406 tmpbot->next->prev = tmptop->prev;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002407 current = tmpbot->next;
Chris Allegretta9149e612000-11-27 00:23:41 +00002408 tmpbot->next = NULL;
2409 do_uncut_text();
Chris Allegrettad022eac2000-11-27 02:50:49 +00002410 if (tmptop->prev == NULL)
2411 edit_refresh();
2412
Chris Allegretta88520c92001-05-05 17:45:54 +00002413 /* Restore totsize from before justify */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002414 totsize = totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002415 free_filestruct(tmptop);
2416 blank_statusbar_refresh();
2417 }
Chris Allegretta4a9c8582000-11-27 22:59:40 +00002418 shortcut_init(0);
2419 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002420 free_filestruct(cutbuffer);
2421 cutbuffer = cutbak;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002422
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002423 return 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002424#endif
2425}
2426
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002427#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002428void help_init(void)
2429{
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002430 int i, sofar = 0, meta_shortcut = 0, helplen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002431 long allocsize = 1; /* How much space we're gonna need for the help text */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002432 char buf[BUFSIZ] = "", *ptr = NULL;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002433 toggle *t;
2434 shortcut *s;
Chris Allegrettab3655b42001-10-22 03:15:31 +00002435
Chris Allegretta7e65d2f2002-02-15 21:12:52 +00002436 helplen = length_of_list(currshortcut);
Chris Allegretta13fd44b2002-01-02 13:59:11 +00002437
Chris Allegrettab3655b42001-10-22 03:15:31 +00002438 /* First set up the initial help text for the current function */
2439 if (currshortcut == whereis_list || currshortcut == replace_list
2440 || currshortcut == replace_list_2)
2441 ptr = _("Search Command Help Text\n\n "
2442 "Enter the words or characters you would like to search "
2443 "for, then hit enter. If there is a match for the text you "
2444 "entered, the screen will be updated to the location of the "
Jordi Mallach773623c2001-10-28 21:00:49 +00002445 "nearest match for the search string.\n\n "
2446 "If using Pico Mode via the -p or --pico flags, using the "
2447 "Meta-P toggle or using a nanorc file, the previous search "
2448 "string will be shown in brackets after the Search: prompt. "
Jordi Mallachf4e57292001-12-26 00:16:40 +00002449 "Hitting enter without entering any text will perform the "
Jordi Mallach773623c2001-10-28 21:00:49 +00002450 "previous search. Otherwise, the previous string will be "
2451 "placed in front of the cursor, and can be edited or deleted "
2452 "before hitting enter.\n\n The following functions keys are "
2453 "available in Search mode:\n\n");
Chris Allegrettab3655b42001-10-22 03:15:31 +00002454 else if (currshortcut == goto_list)
2455 ptr = _("Goto Line Help Text\n\n "
2456 "Enter the line number that you wish to go to and hit "
Jordi Mallach773623c2001-10-28 21:00:49 +00002457 "Enter. If there are fewer lines of text than the "
Chris Allegrettab3655b42001-10-22 03:15:31 +00002458 "number you entered, you will be brought to the last line "
2459 "of the file.\n\n The following functions keys are "
2460 "available in Goto Line mode:\n\n");
2461 else if (currshortcut == insertfile_list)
2462 ptr = _("Insert File Help Text\n\n "
2463 "Type in the name of a file to be inserted into the current "
2464 "file buffer at the current cursor location.\n\n "
2465 "If you have compiled nano with multiple file buffer "
2466 "support, and enable multiple buffers with the -F "
Jordi Mallach773623c2001-10-28 21:00:49 +00002467 "or --multibuffer command line flags, the Meta-F toggle or "
2468 "using a nanorc file, inserting a file will cause it to be "
Chris Allegretta180a5692002-01-02 14:30:33 +00002469 "loaded into a separate buffer (use Meta-< and > to switch "
Chris Allegretta48b06702002-02-22 04:30:50 +00002470 "between file buffers).\n\n If you need another blank "
Chris Allegrettab479c892002-03-09 20:03:10 +00002471 "buffer, do not enter any filename, or type in a "
2472 "nonexistent filename at the prompt and press "
2473 "Enter.\n\n The following function keys are "
Chris Allegretta48b06702002-02-22 04:30:50 +00002474 "available in Insert File mode:\n\n");
Chris Allegrettab3655b42001-10-22 03:15:31 +00002475 else if (currshortcut == writefile_list)
2476 ptr = _("Write File Help Text\n\n "
2477 "Type the name that you wish to save the current file "
2478 "as and hit enter to save the file.\n\n "
2479 "If you are using the marker code with Ctrl-^ and have "
2480 "selected text, you will be prompted to save only the "
2481 "selected portion to a separate file. To reduce the "
2482 "chance of overwriting the current file with just a portion "
2483 "of it, the current filename is not the default in this "
2484 "mode.\n\n The following function keys are available in "
2485 "Write File mode:\n\n");
2486#ifndef DISABLE_BROWSER
2487 else if (currshortcut == browser_list)
2488 ptr = _("File Browser Help Text\n\n "
2489 "The file browser is used to visually browse the "
2490 "directory structure to select a file for reading "
2491 "or writing. You may use the arrow keys or Page Up/"
2492 "Down to browse through the files, and S or Enter to "
2493 "choose the selected file or enter the selected "
2494 "directory. To move up one level, select the directory "
2495 "called \"..\" at the top of the file list.\n\n The "
2496 "following functions keys are available in the file "
2497 "browser:\n\n");
2498 else if (currshortcut == gotodir_list)
2499 ptr = _("Browser Goto Directory Help Text\n\n "
2500 "Enter the name of the directory you would like to "
2501 "browse to.\n\n If tab completion has not been disabled, "
2502 "you can use the TAB key to (attempt to) automatically "
Chris Allegretta1f8394d2002-03-09 19:58:18 +00002503 "complete the directory name.\n\n The following function "
Chris Allegrettab3655b42001-10-22 03:15:31 +00002504 "keys are available in Browser GotoDir mode:\n\n");
2505#endif
2506 else if (currshortcut == spell_list)
2507 ptr = _("Spell Check Help Text\n\n "
2508 "The spell checker checks the spelling of all text "
2509 "in the current file. When an unknown word is "
2510 "encountered, it is highlighted and a replacement can "
2511 "be edited. It will then prompt to replace every "
2512 "instance of the given misspelled word in the "
2513 "current file.\n\n The following other functions are "
2514 "available in Spell Check mode:\n\n");
Chris Allegretta52c5a6e2002-03-21 05:07:28 +00002515#ifndef NANO_SMALL
2516 else if (currshortcut == extcmd_list)
2517 ptr = _("External Command Help Text\n\n "
2518 "This menu allows you to insert the output of a command "
2519 "run by the shell into the current buffer (or a new "
2520 "buffer in multibuffer mode).\n\n The following keys are "
2521 "available in this mode:\n\n");
2522#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00002523 else /* Default to the main help list */
2524 ptr = help_text_init;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002525
2526 /* Compute the space needed for the shortcut lists - we add 15 to
2527 have room for the shortcut abbrev and its possible alternate keys */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002528 s = currshortcut;
2529 for (i = 0; i <= helplen - 1; i++) {
2530 if (s->help != NULL)
2531 allocsize += strlen(s->help) + 15;
2532 s = s->next;
2533 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002534
Chris Allegrettab3655b42001-10-22 03:15:31 +00002535 /* If we're on the main list, we also allocate space for toggle help text. */
2536 if (currshortcut == main_list) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002537 for (t = toggles; t != NULL; t = t->next)
2538 if (t->desc != NULL)
2539 allocsize += strlen(t->desc) + 30;
Chris Allegrettab3655b42001-10-22 03:15:31 +00002540 }
2541
2542 allocsize += strlen(ptr);
2543
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002544 if (help_text != NULL)
2545 free(help_text);
2546
2547 /* Allocate space for the help text */
Chris Allegretta88b09152001-05-17 11:35:43 +00002548 help_text = charalloc(allocsize);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002549
2550 /* Now add the text we want */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002551 strcpy(help_text, ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002552
2553 /* Now add our shortcut info */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002554 s = currshortcut;
Chris Allegretta13fd44b2002-01-02 13:59:11 +00002555 for (i = 0; i <= helplen - 1; i++) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002556 if (s->val > 0 && s->val < 'a')
2557 sofar = snprintf(buf, BUFSIZ, "^%c ", s->val + 64);
2558 else {
2559 if (s->altval > 0) {
2560 sofar = 0;
2561 meta_shortcut = 1;
2562 }
2563 else
2564 sofar = snprintf(buf, BUFSIZ, " ");
2565 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002566
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002567 if (!meta_shortcut) {
2568 if (s->misc1 > KEY_F0 && s->misc1 <= KEY_F(64))
2569 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
2570 s->misc1 - KEY_F0);
2571 else
2572 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
2573 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002574
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002575 if (s->altval > 0 && s->altval < 91
2576 && (s->altval - 32) > 32)
2577 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2578 (meta_shortcut ? "M-%c " : "(M-%c) "),
2579 s->altval - 32);
Chris Allegretta5902f962002-03-07 12:40:39 +00002580 else if (s->altval >= 'a')
2581 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2582 (meta_shortcut ? "M-%c " : "(M-%c) "),
2583 s->altval - 32);
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002584 else if (s->altval > 0)
2585 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2586 (meta_shortcut ? "M-%c " : "(M-%c) "),
2587 s->altval);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002588 /* Hack */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002589 else if (s->val >= 'a')
2590 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2591 (meta_shortcut ? "(M-%c) " : "M-%c "),
2592 s->val - 32);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002593 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002594 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002595
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002596 if (meta_shortcut) {
2597 if (s->misc1 > KEY_F0 && s->misc1 <= KEY_F(64))
2598 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2599 "(F%d) ", s->misc1 - KEY_F0);
2600 else
2601 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2602 " ");
2603 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002604
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002605 if (s->help != NULL)
2606 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", s->help);
Chris Allegretta756f2202000-09-01 13:32:47 +00002607
2608 strcat(help_text, buf);
2609 strcat(help_text, "\n");
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002610
2611 s = s->next;
Chris Allegretta756f2202000-09-01 13:32:47 +00002612 }
2613
2614 /* And the toggles... */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002615 if (currshortcut == main_list)
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002616 for (t = toggles; t != NULL; t = t->next) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00002617 sofar = snprintf(buf, BUFSIZ,
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002618 "M-%c ", t->val - 32);
2619 if (t->desc != NULL) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00002620 snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002621 t->desc);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002622 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002623 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00002624 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002625 }
2626
2627}
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002628#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002629
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002630void do_toggle(toggle *which)
Chris Allegretta756f2202000-09-01 13:32:47 +00002631{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002632#ifdef NANO_SMALL
2633 nano_disabled_msg();
2634#else
Jordi Mallach2dc0f6b2000-09-07 10:48:00 +00002635 char *enabled = _("enabled");
2636 char *disabled = _("disabled");
Chris Allegrettaf0f63a82000-09-02 18:44:21 +00002637
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002638 switch (which->val) {
Chris Allegretta8d990b52001-09-22 22:14:25 +00002639 case TOGGLE_BACKWARDS_KEY:
2640 case TOGGLE_CASE_KEY:
2641 case TOGGLE_REGEXP_KEY:
2642 return;
2643 }
Chris Allegretta8d990b52001-09-22 22:14:25 +00002644
Chris Allegretta658399a2001-06-14 02:54:22 +00002645 /* Even easier! */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002646 TOGGLE(which->flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002647
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002648 switch (which->val) {
Chris Allegretta756f2202000-09-01 13:32:47 +00002649 case TOGGLE_PICOMODE_KEY:
Chris Allegretta07798352000-11-27 22:58:23 +00002650 shortcut_init(0);
Chris Allegrettac1049ac2001-08-17 00:03:46 +00002651 SET(CLEAR_BACKUPSTRING);
Chris Allegretta756f2202000-09-01 13:32:47 +00002652 display_main_list();
2653 break;
2654 case TOGGLE_SUSPEND_KEY:
2655 signal_init();
2656 break;
2657 case TOGGLE_MOUSE_KEY:
2658 mouse_init();
2659 break;
2660 case TOGGLE_NOHELP_KEY:
Chris Allegretta2a42af12000-09-12 23:02:49 +00002661 wclear(bottomwin);
2662 wrefresh(bottomwin);
2663 window_init();
Chris Allegrettaaffeda82000-12-18 04:03:48 +00002664 fix_editbot();
Chris Allegretta2a42af12000-09-12 23:02:49 +00002665 edit_refresh();
2666 display_main_list();
Chris Allegretta756f2202000-09-01 13:32:47 +00002667 break;
Chris Allegretta99e30e12001-09-23 02:45:27 +00002668 case TOGGLE_DOS_KEY:
2669 UNSET(MAC_FILE);
2670 break;
2671 case TOGGLE_MAC_KEY:
2672 UNSET(DOS_FILE);
2673 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002674 }
Chris Allegretta2a42af12000-09-12 23:02:49 +00002675
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002676 if (!ISSET(which->flag)) {
2677 if (which->val == TOGGLE_NOHELP_KEY ||
2678 which->val == TOGGLE_WRAP_KEY)
2679 statusbar("%s %s", which->desc, enabled);
Chris Allegretta819e3db2001-07-11 02:37:19 +00002680 else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002681 statusbar("%s %s", which->desc, disabled);
Chris Allegretta819e3db2001-07-11 02:37:19 +00002682 } else {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002683 if (which->val == TOGGLE_NOHELP_KEY ||
2684 which->val == TOGGLE_WRAP_KEY)
2685 statusbar("%s %s", which->desc, disabled);
Chris Allegretta819e3db2001-07-11 02:37:19 +00002686 else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002687 statusbar("%s %s", which->desc, enabled);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002688 }
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002689
Chris Allegretta756f2202000-09-01 13:32:47 +00002690#endif
2691}
2692
Chris Allegretta88520c92001-05-05 17:45:54 +00002693/* If the NumLock key has made the keypad go awry, print an error
2694 message; hopefully we can address it later. */
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002695void print_numlock_warning(void)
2696{
2697 static int didmsg = 0;
2698 if (!didmsg) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002699 statusbar(_
2700 ("NumLock glitch detected. Keypad will malfunction with NumLock off"));
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002701 didmsg = 1;
2702 }
2703}
2704
Chris Allegretta1748cd12001-01-13 17:22:54 +00002705/* This function returns the correct keystroke, given the A,B,C or D
2706 input key. This is a common sequence of many terms which send
2707 Esc-O-[A-D] or Esc-[-[A-D]. */
2708int ABCD(int input)
2709{
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002710 switch (input) {
2711 case 'A':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002712 case 'a':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002713 return (KEY_UP);
2714 case 'B':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002715 case 'b':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002716 return (KEY_DOWN);
2717 case 'C':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002718 case 'c':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002719 return (KEY_RIGHT);
2720 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002721 case 'd':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002722 return (KEY_LEFT);
2723 default:
2724 return 0;
Chris Allegretta1748cd12001-01-13 17:22:54 +00002725 }
2726}
2727
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002728int main(int argc, char *argv[])
2729{
2730 int optchr;
2731 int kbinput; /* Input from keyboard */
2732 long startline = 0; /* Line to try and start at */
Chris Allegretta08020882001-01-29 23:37:54 +00002733 int keyhandled; /* Have we handled the keystroke yet? */
Chris Allegretta9caa1932002-02-15 20:08:05 +00002734 int modify_control_seq;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002735 char *argv0;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002736 shortcut *s;
Chris Allegretta40ecbad2002-03-06 15:27:44 +00002737#ifndef NANO_SMALL
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002738 toggle *t;
Chris Allegretta40ecbad2002-03-06 15:27:44 +00002739#endif
Chris Allegretta0357c4d2001-09-19 02:59:25 +00002740
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002741#ifdef HAVE_GETOPT_LONG
2742 int option_index = 0;
2743 struct option long_options[] = {
Chris Allegretta805c26d2000-09-06 13:39:17 +00002744#ifdef HAVE_REGEX_H
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002745 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00002746#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002747 {"version", 0, 0, 'V'},
2748 {"const", 0, 0, 'c'},
2749 {"suspend", 0, 0, 'z'},
2750 {"nowrap", 0, 0, 'w'},
2751 {"nohelp", 0, 0, 'x'},
2752 {"help", 0, 0, 'h'},
Chris Allegretta7492cec2000-12-18 04:55:21 +00002753 {"view", 0, 0, 'v'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002754#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002755 {"cut", 0, 0, 'k'},
Chris Allegretta7004c282001-09-22 00:42:10 +00002756 {"dos", 0, 0, 'D'},
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002757 {"mac", 0, 0, 'M'},
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002758 {"noconvert", 0, 0, 'N'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002759 {"autoindent", 0, 0, 'i'},
Chris Allegrettaff989832001-09-17 13:48:00 +00002760#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002761 {"tempfile", 0, 0, 't'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002762#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002763 {"speller", 1, 0, 's'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002764#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00002765
2766#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002767 {"fill", 1, 0, 'r'},
Chris Allegretta6fe61492001-05-21 12:56:25 +00002768#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002769 {"mouse", 0, 0, 'm'},
Chris Allegrettae1f14522001-09-19 03:19:43 +00002770#ifndef DISABLE_OPERATINGDIR
2771 {"operatingdir", 1, 0, 'o'},
2772#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002773 {"pico", 0, 0, 'p'},
2774 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00002775 {"tabsize", 1, 0, 'T'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002776
Chris Allegretta355fbe52001-07-14 19:32:47 +00002777#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002778 {"multibuffer", 0, 0, 'F'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002779#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002780#ifndef NANO_SMALL
2781 {"smooth", 0, 0, 'S'},
2782#endif
Chris Allegretta48bd3782002-01-03 21:26:34 +00002783 {"keypad", 0, 0, 'K'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002784 {0, 0, 0, 0}
2785 };
2786#endif
2787
2788 /* Flag inits... */
2789 SET(FOLLOW_SYMLINKS);
2790
2791#ifndef NANO_SMALL
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002792#ifdef ENABLE_NLS
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002793 setlocale(LC_ALL, "");
2794 bindtextdomain(PACKAGE, LOCALEDIR);
2795 textdomain(PACKAGE);
2796#endif
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002797#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002798
Chris Allegretta8d8e0122001-04-18 04:28:54 +00002799#ifdef ENABLE_NANORC
2800 do_rcfile();
2801#endif /* ENABLE_NANORC */
2802
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002803#ifdef HAVE_GETOPT_LONG
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002804 while ((optchr = getopt_long(argc, argv, "h?DFKMNQ:RST:Vabcefgijklmo:pr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002805 long_options, &option_index)) != EOF) {
2806#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002807 while ((optchr =
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002808 getopt(argc, argv, "h?DFKMNQ:RST:Vabcefgijklmo:pr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002809#endif
2810
2811 switch (optchr) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002812
Chris Allegretta7004c282001-09-22 00:42:10 +00002813#ifndef NANO_SMALL
2814 case 'D':
2815 SET(DOS_FILE);
2816 break;
2817#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +00002818#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002819 case 'F':
Chris Allegretta355fbe52001-07-14 19:32:47 +00002820 SET(MULTIBUFFER);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002821 break;
2822#endif
Chris Allegretta48bd3782002-01-03 21:26:34 +00002823 case 'K':
2824 SET(ALT_KEYPAD);
2825 break;
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002826#ifndef NANO_SMALL
2827 case 'M':
2828 SET(MAC_FILE);
2829 break;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002830 case 'N':
2831 SET(NO_CONVERT);
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002832 break;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002833#endif
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002834 case 'Q':
2835#ifndef DISABLE_JUSTIFY
2836 quotestr = optarg;
2837 break;
2838#else
2839 usage(); /* To stop bogus data for tab width */
2840 finish(1);
2841#endif
Chris Allegretta805c26d2000-09-06 13:39:17 +00002842#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +00002843 case 'R':
2844 SET(USE_REGEXP);
2845 break;
Chris Allegretta47805612000-07-07 02:35:34 +00002846#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002847#ifndef NANO_SMALL
2848 case 'S':
2849 SET(SMOOTHSCROLL);
2850 break;
2851#endif
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002852 case 'T':
2853 tabsize = atoi(optarg);
2854 if (tabsize <= 0) {
2855 usage(); /* To stop bogus data for tab width */
2856 finish(1);
2857 }
2858 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002859 case 'V':
2860 version();
2861 exit(0);
Chris Allegrettae1f14522001-09-19 03:19:43 +00002862 case 'a':
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002863 case 'b':
2864 case 'e':
2865 case 'f':
Rocco Corsi12f294c2001-04-14 06:50:24 +00002866 case 'g':
2867 case 'j':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002868 /* Pico compatibility flags */
2869 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002870 case 'c':
2871 SET(CONSTUPDATE);
2872 break;
2873 case 'h':
2874 case '?':
2875 usage();
2876 exit(0);
Chris Allegrettaff989832001-09-17 13:48:00 +00002877#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002878 case 'i':
2879 SET(AUTOINDENT);
2880 break;
Chris Allegretta627de192000-07-12 02:09:17 +00002881 case 'k':
2882 SET(CUT_TO_END);
2883 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002884#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002885 case 'l':
2886 UNSET(FOLLOW_SYMLINKS);
2887 break;
2888 case 'm':
2889 SET(USE_MOUSE);
2890 break;
Chris Allegrettae1f14522001-09-19 03:19:43 +00002891#ifndef DISABLE_OPERATINGDIR
2892 case 'o':
2893 operating_dir = charalloc(strlen(optarg) + 1);
2894 strcpy(operating_dir, optarg);
2895
2896 /* make sure we're inside the operating directory */
2897 if (check_operating_dir(".", 0)) {
2898 if (chdir(operating_dir) == -1) {
2899 free(operating_dir);
2900 operating_dir = NULL;
2901 }
2902 }
2903 break;
2904#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002905 case 'p':
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002906 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002907 break;
2908 case 'r':
Chris Allegretta6fe61492001-05-21 12:56:25 +00002909#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002910 fill = atoi(optarg);
Chris Allegretta6fe61492001-05-21 12:56:25 +00002911 if (fill < 0)
2912 wrap_at = fill;
2913 else if (fill == 0) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002914 usage(); /* To stop bogus data (like a string) */
2915 finish(1);
2916 }
2917 break;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002918#else
2919 usage();
2920 exit(0);
2921
2922#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002923#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002924 case 's':
Chris Allegretta88b09152001-05-17 11:35:43 +00002925 alt_speller = charalloc(strlen(optarg) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002926 strcpy(alt_speller, optarg);
2927 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002928#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002929 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00002930 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002931 break;
2932 case 'v':
2933 SET(VIEW_MODE);
2934 break;
2935 case 'w':
Chris Allegrettacef7fbb2001-04-02 05:36:08 +00002936#ifdef DISABLE_WRAPPING
2937 usage();
2938 exit(0);
2939#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002940 SET(NO_WRAP);
2941 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002942#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002943 case 'x':
2944 SET(NO_HELP);
2945 break;
2946 case 'z':
2947 SET(SUSPEND);
2948 break;
2949 default:
2950 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002951 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002952 }
2953
2954 }
2955
2956 argv0 = strrchr(argv[0], '/');
2957 if ((argv0 && strstr(argv0, "pico"))
2958 || (!argv0 && strstr(argv[0], "pico")))
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002959 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002960
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002961 /* See if there's a non-option in argv (first non-option is the
2962 filename, if +LINE is not given) */
2963 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002964 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002965 else {
2966 /* Look for the +line flag... */
2967 if (argv[optind][0] == '+') {
2968 startline = atoi(&argv[optind][1]);
2969 optind++;
2970 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002971 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002972 else
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002973 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002974
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002975 } else
2976 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002977 }
2978
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002979 /* now ncurses init stuff... */
2980 initscr();
2981 savetty();
2982 nonl();
2983 cbreak();
2984 noecho();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002985
2986 /* Set up some global variables */
Chris Allegretta56214c62001-09-27 02:46:53 +00002987 global_init(0);
Chris Allegretta07798352000-11-27 22:58:23 +00002988 shortcut_init(0);
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002989#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002990 init_help_msg();
2991 help_init();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002992#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002993 signal_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002994
2995#ifdef DEBUG
2996 fprintf(stderr, _("Main: set up windows\n"));
2997#endif
2998
Chris Allegretta2a42af12000-09-12 23:02:49 +00002999 window_init();
Chris Allegretta756f2202000-09-01 13:32:47 +00003000 mouse_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003001
Chris Allegretta48bd3782002-01-03 21:26:34 +00003002 if (!ISSET(ALT_KEYPAD)) {
3003 keypad(edit, TRUE);
3004 keypad(bottomwin, TRUE);
3005 }
3006
Chris Allegretta08893e02001-11-29 02:42:27 +00003007#ifdef ENABLE_COLOR
3008 do_colorinit();
3009
Chris Allegretta08893e02001-11-29 02:42:27 +00003010#endif /* ENABLE_COLOR */
3011
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003012#ifdef DEBUG
3013 fprintf(stderr, _("Main: bottom win\n"));
3014#endif
Chris Allegretta88520c92001-05-05 17:45:54 +00003015 /* Set up bottom of window */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003016 display_main_list();
3017
3018#ifdef DEBUG
3019 fprintf(stderr, _("Main: open file\n"));
3020#endif
3021
Chris Allegrettaf4b96012001-01-03 07:11:47 +00003022 titlebar(NULL);
Chris Allegretta31c76662000-11-21 06:20:20 +00003023
3024 /* Now we check to see if argv[optind] is non-null to determine if
3025 we're dealing with a new file or not, not argc == 1... */
3026 if (argv[optind] == NULL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003027 new_file();
3028 else
3029 open_file(filename, 0, 0);
3030
3031 if (startline > 0)
Chris Allegretta2d7893d2001-07-11 02:08:33 +00003032 do_gotoline(startline, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003033 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00003034 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003035
Chris Allegretta08020882001-01-29 23:37:54 +00003036 /* return here after a sigwinch */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003037 sigsetjmp(jmpbuf, 1);
Chris Allegretta08020882001-01-29 23:37:54 +00003038
3039 /* Fix clobber-age */
3040 kbinput = 0;
3041 keyhandled = 0;
3042 modify_control_seq = 0;
3043
Robert Siemborski6967eec2000-07-08 14:23:32 +00003044 edit_refresh();
3045 reset_cursor();
3046
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003047 while (1) {
Chris Allegretta9239d742000-09-06 15:19:18 +00003048
Chris Allegretta6fe61492001-05-21 12:56:25 +00003049#ifndef DISABLE_MOUSE
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003050 currshortcut = main_list;
Chris Allegretta6fe61492001-05-21 12:56:25 +00003051#endif
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003052
Chris Allegretta9239d742000-09-06 15:19:18 +00003053#ifndef _POSIX_VDISABLE
3054 /* We're going to have to do it the old way, i.e. on cygwin */
3055 raw();
3056#endif
3057
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003058 kbinput = wgetch(edit);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003059#ifdef DEBUG
3060 fprintf(stderr, "AHA! %c (%d)\n", kbinput, kbinput);
3061#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003062
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003063 if (kbinput == 27) { /* Grab Alt-key stuff first */
3064 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003065 /* Alt-O, suddenly very important ;) */
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003066 case 'O':
Chris Allegretta16e41682000-09-11 22:33:54 +00003067 kbinput = wgetch(edit);
Chris Allegretta316e4d92001-04-28 16:31:19 +00003068 if ((kbinput <= 'D' && kbinput >= 'A') ||
3069 (kbinput <= 'd' && kbinput >= 'a'))
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003070 kbinput = ABCD(kbinput);
Chris Allegretta201d9bf2001-01-14 03:17:53 +00003071 else if (kbinput <= 'z' && kbinput >= 'j')
3072 print_numlock_warning();
3073 else if (kbinput <= 'S' && kbinput >= 'P')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003074 kbinput = KEY_F(kbinput - 79);
Chris Allegretta16e41682000-09-11 22:33:54 +00003075#ifdef DEBUG
3076 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003077 fprintf(stderr, _("I got Alt-O-%c! (%d)\n"),
3078 kbinput, kbinput);
3079 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003080 }
3081#endif
3082 break;
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003083 case 27:
3084 /* If we get Alt-Alt, the next keystroke should be the same as a
3085 control sequence */
3086 modify_control_seq = 1;
3087 keyhandled = 1;
3088 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00003089#ifndef NANO_SMALL
Chris Allegretta76e291b2001-10-14 19:05:10 +00003090 case ' ':
3091 /* If control-space is next word, Alt-space should be previous word */
3092 do_prev_word();
3093 keyhandled = 1;
3094 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00003095#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003096 case '[':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003097 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003098 case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */
Chris Allegretta16e41682000-09-11 22:33:54 +00003099 kbinput = wgetch(edit);
3100 if (kbinput >= '1' && kbinput <= '5') {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003101 kbinput = KEY_F(kbinput - 48);
3102 wgetch(edit);
3103 } else if (kbinput >= '7' && kbinput <= '9') {
3104 kbinput = KEY_F(kbinput - 49);
3105 wgetch(edit);
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003106 } else if (kbinput == '~')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003107 kbinput = KEY_HOME;
Chris Allegretta16e41682000-09-11 22:33:54 +00003108
3109#ifdef DEBUG
3110 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003111 fprintf(stderr, _("I got Alt-[-1-%c! (%d)\n"),
3112 kbinput, kbinput);
3113 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003114 }
3115#endif
3116
3117 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003118 case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */
Chris Allegretta16e41682000-09-11 22:33:54 +00003119 kbinput = wgetch(edit);
Chris Allegretta16e41682000-09-11 22:33:54 +00003120 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003121 case '0':
3122 kbinput = KEY_F(9);
3123 wgetch(edit);
3124 break;
3125 case '1':
3126 kbinput = KEY_F(10);
3127 wgetch(edit);
3128 break;
3129 case '3':
3130 kbinput = KEY_F(11);
3131 wgetch(edit);
3132 break;
3133 case '4':
3134 kbinput = KEY_F(12);
3135 wgetch(edit);
3136 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003137 case '~':
3138 goto do_insertkey;
Chris Allegretta16e41682000-09-11 22:33:54 +00003139#ifdef DEBUG
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003140 default:
3141 fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"),
3142 kbinput, kbinput);
3143 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003144#endif
3145
3146 }
3147 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003148 case '3': /* Alt-[-3 = Delete? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003149 kbinput = NANO_DELETE_KEY;
3150 wgetch(edit);
3151 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003152 case '4': /* Alt-[-4 = End? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003153 kbinput = NANO_END_KEY;
3154 wgetch(edit);
3155 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003156 case '5': /* Alt-[-5 = Page Up */
Chris Allegretta16e41682000-09-11 22:33:54 +00003157 kbinput = KEY_PPAGE;
3158 wgetch(edit);
3159 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003160 case 'V': /* Alt-[-V = Page Up in Hurd Console */
Chris Allegretta7bf72742001-10-28 04:29:55 +00003161 case 'I': /* Alt-[-I = Page Up - FreeBSD Console */
3162 kbinput = KEY_PPAGE;
3163 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003164 case '6': /* Alt-[-6 = Page Down */
Chris Allegretta16e41682000-09-11 22:33:54 +00003165 kbinput = KEY_NPAGE;
3166 wgetch(edit);
3167 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003168 case 'U': /* Alt-[-U = Page Down in Hurd Console */
Chris Allegretta7bf72742001-10-28 04:29:55 +00003169 case 'G': /* Alt-[-G = Page Down - FreeBSD Console */
3170 kbinput = KEY_NPAGE;
3171 break;
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003172 case '7':
3173 kbinput = KEY_HOME;
3174 wgetch(edit);
3175 break;
3176 case '8':
3177 kbinput = KEY_END;
3178 wgetch(edit);
3179 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003180 case '9': /* Alt-[-9 = Delete in Hurd Console */
3181 kbinput = KEY_DC;
3182 break;
Chris Allegretta32da4562002-01-02 15:12:21 +00003183 case '@': /* Alt-[-@ = Insert in Hurd Console */
3184 case 'L': /* Alt-[-L = Insert - FreeBSD Console */
3185 goto do_insertkey;
3186 case '[': /* Alt-[-[-[A-E], F1-F5 in Linux console */
Chris Allegretta16e41682000-09-11 22:33:54 +00003187 kbinput = wgetch(edit);
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003188 if (kbinput >= 'A' && kbinput <= 'E')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003189 kbinput = KEY_F(kbinput - 64);
Chris Allegretta16e41682000-09-11 22:33:54 +00003190 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003191 case 'A':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003192 case 'B':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003193 case 'C':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003194 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00003195 case 'a':
3196 case 'b':
3197 case 'c':
3198 case 'd':
Chris Allegretta1748cd12001-01-13 17:22:54 +00003199 kbinput = ABCD(kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003200 break;
3201 case 'H':
3202 kbinput = KEY_HOME;
3203 break;
3204 case 'F':
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003205 case 'Y': /* End Key in Hurd Console */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003206 kbinput = KEY_END;
3207 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003208 default:
3209#ifdef DEBUG
3210 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
3211 kbinput, kbinput);
3212#endif
3213 break;
3214 }
3215 break;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003216
Chris Allegretta355fbe52001-07-14 19:32:47 +00003217#ifdef ENABLE_MULTIBUFFER
Chris Allegretta819e3db2001-07-11 02:37:19 +00003218 case NANO_OPENPREV_KEY:
Chris Allegretta180a5692002-01-02 14:30:33 +00003219 case NANO_OPENPREV_ALTKEY:
Chris Allegretta819e3db2001-07-11 02:37:19 +00003220 open_prevfile(0);
3221 keyhandled = 1;
3222 break;
3223 case NANO_OPENNEXT_KEY:
Chris Allegretta180a5692002-01-02 14:30:33 +00003224 case NANO_OPENNEXT_ALTKEY:
Chris Allegretta819e3db2001-07-11 02:37:19 +00003225 open_nextfile(0);
3226 keyhandled = 1;
3227 break;
Chris Allegretta9cf9e062001-07-11 12:06:13 +00003228#endif
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003229
3230#if !defined (NANO_SMALL) && defined (HAVE_REGEX_H)
3231 case NANO_BRACKET_KEY:
3232 do_find_bracket();
3233 keyhandled = 1;
3234 break;
3235#endif
3236
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003237 default:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003238 /* Check for the altkey defs.... */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003239 for (s = main_list; s != NULL; s = s->next)
3240 if (kbinput == s->altval ||
3241 kbinput == s->altval - 32) {
3242 kbinput = s->val;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003243 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003244 }
Chris Allegretta756f2202000-09-01 13:32:47 +00003245#ifndef NANO_SMALL
3246 /* And for toggle switches */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003247 for (t = toggles; t != NULL && !keyhandled; t = t->next)
3248 if (kbinput == t->val ||
3249 (t->val > 'a' &&
3250 kbinput == t->val - 32)) {
3251 do_toggle(t);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003252 keyhandled = 1;
3253 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00003254 }
3255#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003256#ifdef DEBUG
3257 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
3258 kbinput);
3259#endif
3260 break;
3261 }
3262 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003263 /* If the modify_control_seq is set, we received an Alt-Alt
3264 sequence before this, so we make this key a control sequence
3265 by subtracting 64 or 96, depending on its value. */
3266 if (!keyhandled && modify_control_seq) {
3267 if (kbinput >= 'A' && kbinput < 'a')
3268 kbinput -= 64;
3269 else if (kbinput >= 'a' && kbinput <= 'z')
3270 kbinput -= 96;
3271
3272 modify_control_seq = 0;
3273 }
3274
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003275 /* Look through the main shortcut list to see if we've hit a
3276 shortcut key */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003277
Chris Allegrettaf5de33a2002-02-27 04:14:16 +00003278#if !defined(DISABLE_BROWSER) || !defined(DISABLE_MOUSE) || !defined (DISABLE_HELP)
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003279 for (s = currshortcut; s != NULL && !keyhandled; s = s->next) {
Chris Allegrettaf5de33a2002-02-27 04:14:16 +00003280#else
3281 for (s = main_list; s != NULL && !keyhandled; s = s->next) {
3282#endif
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003283 if (kbinput == s->val ||
3284 (s->misc1 && kbinput == s->misc1) ||
3285 (s->misc2 && kbinput == s->misc2)) {
3286 if (ISSET(VIEW_MODE) && !s->viewok)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003287 print_view_warning();
3288 else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003289 s->func();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003290 keyhandled = 1;
3291 }
3292 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003293 /* If we're in raw mode or using Alt-Alt-x, we have to catch
3294 Control-S and Control-Q */
Chris Allegretta9239d742000-09-06 15:19:18 +00003295 if (kbinput == 17 || kbinput == 19)
3296 keyhandled = 1;
3297
Chris Allegretta9caa1932002-02-15 20:08:05 +00003298 /* Catch ^Z by hand when triggered also
3299 407 == ^Z in Linux console when keypad() is used? */
3300 if (kbinput == 26 || kbinput == 407) {
Chris Allegretta9239d742000-09-06 15:19:18 +00003301 if (ISSET(SUSPEND))
3302 do_suspend(0);
3303 keyhandled = 1;
3304 }
Chris Allegretta9239d742000-09-06 15:19:18 +00003305
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003306
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003307#ifndef USE_SLANG
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003308 /* Hack, make insert key do something useful, like insert file */
3309 if (kbinput == KEY_IC) {
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003310#else
3311 if (0) {
3312#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003313 do_insertkey:
3314
3315#ifdef ENABLE_MULTIBUFFER
Chris Allegretta32da4562002-01-02 15:12:21 +00003316 /* do_insertfile_void() contains the logic needed to
3317 handle view mode with the view mode/multibuffer
3318 exception, so use it here */
3319 do_insertfile_void();
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003320#else
Chris Allegretta32da4562002-01-02 15:12:21 +00003321 print_view_warning();
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003322#endif
3323
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003324 keyhandled = 1;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003325 }
3326
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003327 /* Last gasp, stuff that's not in the main lists */
3328 if (!keyhandled)
3329 switch (kbinput) {
Chris Allegretta84de5522001-04-12 14:51:48 +00003330#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003331#ifdef NCURSES_MOUSE_VERSION
3332 case KEY_MOUSE:
3333 do_mouse();
3334 break;
3335#endif
3336#endif
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003337
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003338 case 0: /* Erg */
Chris Allegretta48ebb812001-10-24 01:34:15 +00003339#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003340 do_next_word();
3341 break;
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003342#endif
Chris Allegrettaf4f7e042001-01-04 16:56:15 +00003343
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003344 case -1: /* Stuff that we don't want to do squat */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003345 case 410: /* Must ignore this, it gets sent when we resize */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003346 case 29: /* Ctrl-] */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003347#ifdef PDCURSES
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003348 case 541: /* ???? */
3349 case 542: /* Control and alt in Windows *shrug* */
Chris Allegretta72623582000-11-29 23:43:28 +00003350 case 543: /* Right ctrl key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003351 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +00003352 case 545: /* Right alt key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003353#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003354
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003355 break;
3356 default:
3357#ifdef DEBUG
3358 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
3359#endif
3360 /* We no longer stop unhandled sequences so that people with
3361 odd character sets can type... */
3362
3363 if (ISSET(VIEW_MODE)) {
3364 print_view_warning();
3365 break;
3366 }
3367 do_char(kbinput);
3368 }
Chris Allegretta7fdbd052001-10-02 00:55:38 +00003369 if (ISSET(DISABLE_CURPOS))
3370 UNSET(DISABLE_CURPOS);
3371 else if (ISSET(CONSTUPDATE))
Chris Allegretta2084acc2001-11-29 03:43:08 +00003372 do_cursorpos(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003373
3374 reset_cursor();
3375 wrefresh(edit);
3376 keyhandled = 0;
3377 }
3378
3379 getchar();
3380 finish(0);
3381
3382}