blob: 4685129b2c12f3cf3e5afb48d2c00b6371fbeadc [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
372 for (temp = fileage; temp != NULL; temp = temp->next) {
373 temp->lineno = i++;
374 }
375
376 return 0;
377}
378
379int renumber(filestruct * fileptr)
380{
381 filestruct *temp;
382
383 if (fileptr == NULL || fileptr->prev == NULL || fileptr == fileage) {
384 renumber_all();
385 return 0;
386 }
387 for (temp = fileptr; temp != NULL; temp = temp->next) {
Chris Allegretta5146fec2000-12-10 05:44:02 +0000388 if (temp->prev != NULL)
389 temp->lineno = temp->prev->lineno + 1;
390 else
391 temp->lineno = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000392 }
393
394 return 0;
395}
396
397/* Fix the memory allocation for a string */
398void align(char **strp)
399{
400 /* There was a serious bug here: the new address was never
401 stored anywhere... */
402
403 *strp = nrealloc(*strp, strlen(*strp) + 1);
404}
405
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000406/* Null a string at a certain index and align it */
Chris Allegrettafa0c6962001-10-22 23:22:19 +0000407void null_at(char **data, int index)
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000408{
Chris Allegrettafa0c6962001-10-22 23:22:19 +0000409
410 /* Ahh! Damn dereferencing */
411 (*data)[index] = 0;
412 align(data);
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000413}
414
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000415
416/* Print one usage string to the screen, removes lots of duplicate
417 strings to translate and takes out the parts that shouldn't be
418 translatable (the flag names) */
419void print1opt(char *shortflag, char *longflag, char *desc)
420{
421 printf(" %s\t", shortflag);
422 if (strlen(shortflag) < 8)
423 printf("\t");
424
425#ifdef HAVE_GETOPT_LONG
426 printf("%s\t", longflag);
427 if (strlen(longflag) < 8)
428 printf("\t\t");
429 else if (strlen(longflag) < 16)
430 printf("\t");
431#endif
432
433 printf("%s\n", desc);
434}
435
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000436void usage(void)
437{
438#ifdef HAVE_GETOPT_LONG
439 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
440 printf(_("Option Long option Meaning\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000441#else
442 printf(_("Usage: nano [option] +LINE <file>\n\n"));
443 printf(_("Option Meaning\n"));
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000444#endif /* HAVE_GETOPT_LONG */
445
Chris Allegretta7004c282001-09-22 00:42:10 +0000446#ifndef NANO_SMALL
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000447 print1opt("-D", "--dos", _("Write file in DOS format"));
Chris Allegretta7004c282001-09-22 00:42:10 +0000448#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000449#ifdef ENABLE_MULTIBUFFER
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000450 print1opt("-F", "--multibuffer", _("Enable multiple file buffers"));
Chris Allegretta355fbe52001-07-14 19:32:47 +0000451#endif
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000452 print1opt("-K", "--keypad", _("Use alternate keypad routines"));
Chris Allegretta8fa1e282001-09-22 04:20:25 +0000453#ifndef NANO_SMALL
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000454 print1opt("-M", "--mac", _("Write file in Mac format"));
455 print1opt("-N", "--noconvert", _("Don't convert files from DOS/Mac format"));
Chris Allegretta8fa1e282001-09-22 04:20:25 +0000456#endif
Chris Allegrettae4f940d2002-03-03 22:36:36 +0000457#ifndef DISABLE_JUSTIFY
Chris Allegrettad1ec7b02002-03-09 20:05:26 +0000458 print1opt(_("-Q [str]"), _("--quotestr [str]"), _("Quoting string, default \"> \""));
Chris Allegrettae4f940d2002-03-03 22:36:36 +0000459#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +0000460#ifndef NANO_SMALL
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000461 print1opt("-S", "--smooth", _("Smooth scrolling"));
Chris Allegretta3e3ae942001-09-22 19:02:04 +0000462#endif
Chris Allegrettad1ec7b02002-03-09 20:05:26 +0000463 print1opt(_("-T [num]"), _("--tabsize=[num]"), _("Set width of a tab to num"));
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000464 print1opt("-V", "--version", _("Print version information and exit"));
465 print1opt("-c", "--const", _("Constantly show cursor position"));
466 print1opt("-h", "--help", _("Show this message"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000467#ifndef NANO_SMALL
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000468 print1opt("-i", "--autoindent", _("Automatically indent new lines"));
469 print1opt("-k", "--cut", _("Let ^K cut from cursor to end of line"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000470#endif
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000471 print1opt("-l", "--nofollow", _("Don't follow symbolic links, overwrite"));
Chris Allegretta84de5522001-04-12 14:51:48 +0000472#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000473#ifdef NCURSES_MOUSE_VERSION
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000474 print1opt("-m", "--mouse", _("Enable mouse"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000475#endif
476#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000477#ifndef DISABLE_OPERATINGDIR
Chris Allegrettad1ec7b02002-03-09 20:05:26 +0000478 print1opt(_("-o [dir]"), _("--operatingdir=[dir]"), _("Set operating directory"));
Chris Allegrettae1f14522001-09-19 03:19:43 +0000479#endif
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000480 print1opt("-p", "--pico", _("Emulate Pico as closely as possible"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000481
482#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettad1ec7b02002-03-09 20:05:26 +0000483 print1opt(_("-r [#cols]"), _("--fill=[#cols]"), _("Set fill cols to (wrap lines at) #cols"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000484#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000485#ifndef DISABLE_SPELLER
Chris Allegrettad1ec7b02002-03-09 20:05:26 +0000486 print1opt(_("-s [prog]"), _("--speller=[prog]"), _("Enable alternate speller"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000487#endif
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000488 print1opt("-t", "--tempfile", _("Auto save on exit, don't prompt"));
489 print1opt("-v", "--view", _("View (read only) mode"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000490#ifndef DISABLE_WRAPPING
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000491 print1opt("-w", "--nowrap", _("Don't wrap long lines"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000492#endif
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000493 print1opt("-x", "--nohelp", _("Don't show help window"));
494 print1opt("-z", "--suspend", _("Enable suspend"));
Chris Allegrettad1ec7b02002-03-09 20:05:26 +0000495 print1opt(_("+LINE"), "", _("Start at line number LINE"));
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000496
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000497 exit(0);
498}
499
500void version(void)
501{
Chris Allegrettac46dd812001-02-14 14:28:27 +0000502 printf(_(" GNU nano version %s (compiled %s, %s)\n"),
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000503 VERSION, __TIME__, __DATE__);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000504 printf(_
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000505 (" Email: nano@nano-editor.org Web: http://www.nano-editor.org"));
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000506 printf(_("\n Compiled options:"));
Chris Allegrettaff269f82000-12-01 18:46:01 +0000507
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000508#ifdef NANO_EXTRA
509 printf(" --enable-extra");
Jordi Mallach5285ca92002-01-17 12:40:33 +0000510#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000511#ifdef ENABLE_MULTIBUFFER
512 printf(" --enable-multibuffer");
Jordi Mallach5285ca92002-01-17 12:40:33 +0000513#endif
Chris Allegrettab881d3e2001-04-18 04:34:43 +0000514#ifdef ENABLE_NANORC
515 printf(" --enable-nanorc");
516#endif
Chris Allegretta8ce24132001-04-30 11:28:46 +0000517#ifdef ENABLE_COLOR
518 printf(" --enable-color");
519#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000520
521#ifdef NANO_SMALL
522 printf(" --enable-tiny");
523#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000524#ifdef DISABLE_BROWSER
Chris Allegretta6636dc32001-01-05 05:41:07 +0000525 printf(" --disable-browser");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000526#endif
527#ifdef DISABLE_TABCOMP
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000528 printf(" --disable-tabcomp");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000529#endif
530#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +0000531 printf(" --disable-justify");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000532#endif
533#ifdef DISABLE_SPELLER
Chris Allegretta7b36c522000-12-06 01:08:10 +0000534 printf(" --disable-speller");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000535#endif
536#ifdef DISABLE_HELP
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000537 printf(" --disable-help");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000538#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000539#ifdef DISABLE_MOUSE
540 printf(" --disable-mouse");
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000541#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000542#ifdef DISABLE_OPERATINGDIR
543 printf(" --disable-operatingdir");
544#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000545#endif /* NANO_SMALL */
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000546
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000547#ifdef DISABLE_WRAPPING
548 printf(" --disable-wrapping");
549#endif
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000550#ifdef USE_SLANG
551 printf(" --with-slang");
552#endif
553 printf("\n");
554
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000555}
556
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000557/* Create a new node. This does NOT initialize the data members used
558 only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000559filestruct *make_new_node(filestruct * prevnode)
560{
561 filestruct *newnode;
562
563 newnode = nmalloc(sizeof(filestruct));
564 newnode->data = NULL;
565
566 newnode->prev = prevnode;
567 newnode->next = NULL;
568
569 if (prevnode != NULL)
570 newnode->lineno = prevnode->lineno + 1;
571
572 return newnode;
573}
574
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000575/* Splice a node into an existing filestruct. This does NOT set the data
576 members used only by open_files. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000577void splice_node(filestruct * begin, filestruct * newnode,
578 filestruct * end)
Chris Allegretta7975ed82000-07-28 00:58:35 +0000579{
Chris Allegrettae3167732001-03-18 16:59:34 +0000580 newnode->next = end;
581 newnode->prev = begin;
582 begin->next = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000583 if (end != NULL)
Chris Allegrettae3167732001-03-18 16:59:34 +0000584 end->prev = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000585}
586
Chris Allegrettae3167732001-03-18 16:59:34 +0000587int do_mark(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000588{
589#ifdef NANO_SMALL
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000590 nano_disabled_msg();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000591#else
592 if (!ISSET(MARK_ISSET)) {
593 statusbar(_("Mark Set"));
594 SET(MARK_ISSET);
595 mark_beginbuf = current;
596 mark_beginx = current_x;
597 } else {
598 statusbar(_("Mark UNset"));
599 UNSET(MARK_ISSET);
600 mark_beginbuf = NULL;
601 mark_beginx = 0;
602
603 edit_refresh();
604 }
605#endif
606 return 1;
607}
608
609int no_help(void)
610{
611 if ISSET
612 (NO_HELP)
613 return 2;
614 else
615 return 0;
616}
617
Chris Allegretta3bc8c722000-12-10 17:03:25 +0000618#if defined(DISABLE_JUSTIFY) || defined(DISABLE_SPELLER) || defined(DISABLE_HELP)
Chris Allegrettaff269f82000-12-01 18:46:01 +0000619void nano_disabled_msg(void)
620{
621 statusbar("Sorry, support for this function has been disabled");
622}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000623#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000624
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000625/* The user typed a printable character; add it to the edit buffer */
626void do_char(char ch)
627{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000628 /* magic-line: when a character is inserted on the current magic line,
629 * it means we need a new one! */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000630 if (filebot == current && current->data[0] == '\0') {
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000631 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000632 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000633 }
634
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000635 /* More dangerousness fun =) */
636 current->data = nrealloc(current->data, strlen(current->data) + 2);
637 memmove(&current->data[current_x + 1],
638 &current->data[current_x],
639 strlen(current->data) - current_x + 1);
640 current->data[current_x] = ch;
641 do_right();
642
Chris Allegrettab2cd10d2002-01-20 00:54:42 +0000643#ifdef ENABLE_COLOR
644 edit_refresh();
645#endif
646
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000647#ifndef DISABLE_WRAPPING
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000648 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000649 check_wrap(current, ch);
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000650#endif
651
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000652 set_modified();
653 check_statblank();
654 UNSET(KEEP_CUTBUFFER);
655 totsize++;
656
657}
658
659/* Someone hits return *gasp!* */
660int do_enter(filestruct * inptr)
661{
Chris Allegrettae3167732001-03-18 16:59:34 +0000662 filestruct *newnode;
Chris Allegretta68532c32001-09-17 13:49:33 +0000663 char *tmp;
664#ifndef NANO_SMALL
665 char *spc;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000666 int extra = 0;
Chris Allegretta68532c32001-09-17 13:49:33 +0000667#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000668
Chris Allegrettae3167732001-03-18 16:59:34 +0000669 newnode = make_new_node(inptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000670 tmp = &current->data[current_x];
671 current_x = 0;
672
Chris Allegrettaff989832001-09-17 13:48:00 +0000673#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000674 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
675 if (ISSET(AUTOINDENT)) {
676 spc = current->data;
677 if (spc) {
678 while ((*spc == ' ') || (*spc == '\t')) {
679 extra++;
680 spc++;
681 current_x++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +0000682 totsize++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000683 }
Chris Allegretta88b09152001-05-17 11:35:43 +0000684 newnode->data = charalloc(strlen(tmp) + extra + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000685 strncpy(newnode->data, current->data, extra);
686 strcpy(&newnode->data[extra], tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000687 }
Chris Allegrettaff989832001-09-17 13:48:00 +0000688 } else
689#endif
690 {
Chris Allegretta88b09152001-05-17 11:35:43 +0000691 newnode->data = charalloc(strlen(tmp) + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000692 strcpy(newnode->data, tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000693 }
694 *tmp = 0;
695
Chris Allegrettada721be2000-07-31 01:26:42 +0000696 if (inptr->next == NULL) {
Chris Allegrettae3167732001-03-18 16:59:34 +0000697 filebot = newnode;
698 editbot = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000699 }
Chris Allegrettae3167732001-03-18 16:59:34 +0000700 splice_node(inptr, newnode, inptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000701
702 totsize++;
703 renumber(current);
Chris Allegrettae3167732001-03-18 16:59:34 +0000704 current = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000705 align(&current->data);
706
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000707 /* The logic here is as follows:
708 * -> If we are at the bottom of the buffer, we want to recenter
Chris Allegretta88520c92001-05-05 17:45:54 +0000709 * (read: rebuild) the screen and forcibly move the cursor.
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000710 * -> otherwise, we want simply to redraw the screen and update
711 * where we think the cursor is.
712 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000713 if (current_y == editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +0000714 edit_update(current, CENTER);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000715 reset_cursor();
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000716 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000717 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000718 edit_refresh();
719 update_cursor();
720 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000721
722 totlines++;
723 set_modified();
724
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000725 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000726 return 1;
727}
728
729int do_enter_void(void)
730{
731 return do_enter(current);
732}
733
Chris Allegrettaad3f4782001-10-02 03:54:13 +0000734#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000735void do_next_word(void)
736{
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000737 filestruct *fileptr, *old;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000738 int i;
739
740 if (current == NULL)
741 return;
742
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000743 old = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000744 i = current_x;
745 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
746 if (fileptr == current) {
747 while (isalnum((int) fileptr->data[i])
748 && fileptr->data[i] != 0)
749 i++;
750
751 if (fileptr->data[i] == 0) {
752 i = 0;
753 continue;
754 }
755 }
756 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
757 i++;
758
759 if (fileptr->data[i] != 0)
760 break;
761
762 i = 0;
763 }
764 if (fileptr == NULL)
765 current = filebot;
766 else
767 current = fileptr;
768
769 current_x = i;
770 placewewant = xplustabs();
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000771
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000772 if (current->lineno >= editbot->lineno)
Chris Allegretta234a34d2000-07-29 04:33:38 +0000773 edit_update(current, CENTER);
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000774 else {
775 /* If we've jumped lines, refresh the old line. We can't just use
776 * current->prev here, because we may have skipped over some blank
777 * lines, in which case the previous line is the wrong one.
778 */
779 if (current != old)
780 update_line(old, 0);
781
782 update_line(current, current_x);
783 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000784}
785
786/* the same thing for backwards */
787void do_prev_word(void)
788{
789 filestruct *fileptr, *old;
790 int i;
791
792 if (current == NULL)
793 return;
794
795 old = current;
796 i = current_x;
797 for (fileptr = current; fileptr != NULL; fileptr = fileptr->prev) {
798 if (fileptr == current) {
799 while (isalnum((int) fileptr->data[i])
800 && i != 0)
801 i--;
802
803 if (i == 0) {
804 if (fileptr->prev != NULL)
Chris Allegrettae59fc822001-10-24 18:07:58 +0000805 i = strlen(fileptr->prev->data);
Chris Allegretta878ced32001-10-22 20:05:34 +0000806 else if (fileptr == fileage && filebot != NULL) {
807 current_x = 0;
808 return;
809 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000810 continue;
811 }
812 }
813
814 while (!isalnum((int) fileptr->data[i]) && i != 0)
815 i--;
816
817 if (i > 0) {
818 i--;
819
820 while (isalnum((int) fileptr->data[i]) && i != 0)
821 i--;
822
Chris Allegretta6d0aa9f2001-10-26 15:21:41 +0000823 if (!isalnum((int) fileptr->data[i]))
824 i++;
825
826 if (i != 0 || i != current_x)
Chris Allegretta76e291b2001-10-14 19:05:10 +0000827 break;
828
829 }
830 if (fileptr->prev != NULL)
Chris Allegrettae59fc822001-10-24 18:07:58 +0000831 i = strlen(fileptr->prev->data);
Chris Allegretta878ced32001-10-22 20:05:34 +0000832 else if (fileptr == fileage && filebot != NULL) {
833 current_x = 0;
834 return;
835 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000836 }
837 if (fileptr == NULL)
838 current = fileage;
839 else
840 current = fileptr;
841
842 current_x = i;
843 placewewant = xplustabs();
844
845 if (current->lineno <= edittop->lineno)
846 edit_update(current, CENTER);
847 else {
848 /* If we've jumped lines, refresh the old line. We can't just use
849 * current->prev here, because we may have skipped over some blank
850 * lines, in which case the previous line is the wrong one.
851 */
852 if (current != old)
853 update_line(old, 0);
854
855 update_line(current, current_x);
856 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000857
858}
Chris Allegrettaad3f4782001-10-02 03:54:13 +0000859#endif /* NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000860
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000861#ifndef DISABLE_WRAPPING
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000862void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000863{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000864 int i = 0; /* Index into ->data for line. */
865 int i_tabs = 0; /* Screen position of ->data[i]. */
866 int last_word_end = -1; /* Location of end of last word found. */
867 int current_word_start = -1; /* Location of start of current word. */
868 int current_word_start_t = -1; /* Location of start of current word screen position. */
869 int current_word_end = -1; /* Location of end of current word */
870 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000871 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000872
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000873 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000874 int right = 0;
875 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000876
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000877 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000878
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000879 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000880 if (!isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000881 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000882
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000883 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000884 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000885
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000886 while (!isspace((int) inptr->data[i])
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000887 && inptr->data[i]) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000888 i++;
889 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000890 if (inptr->data[i] < 32)
891 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000892 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000893
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000894 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000895 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000896 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000897 } else {
898 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000899 current_word_end_t = i_tabs - 1;
900 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000901 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000902
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000903 if (inptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000904 if (i_tabs % tabsize != 0);
905 i_tabs += tabsize - (i_tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000906 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000907
Adam Rogoyski09f97962000-06-20 02:50:33 +0000908 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000909 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000910 }
911
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000912 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000913 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000914 * a) one word takes up the whole line with no starting spaces.
915 * - do nothing and return.
916 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000917 * - word starts new line.
918 * - keep white space on original line up to the cursor.
919 * *) cursor is after word at wrap point
920 * - either it's all white space after word, and this routine isn't called.
921 * - or we are actually in case 2 (2 words).
922 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000923 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000924 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000925 * - white space at end of original line is cleared, unless
926 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000927 * b) cursor is at the word at the wrap point.
928 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000929 * - white space on original line is kept to where cursor was.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000930 * c) cursor is past the word at the wrap point.
931 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000932 * - white space at end of original line is cleared
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000933 */
934
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000935 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000936
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000937 /* Category 1a: one word taking up the whole line with no beginning spaces. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000938 if ((last_word_end == -1) && (!isspace((int) inptr->data[0]))) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000939 for (i = current_word_end; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000940 if (!isspace((int) inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000941 current_word_start = i;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000942 while (!isspace((int) inptr->data[i]) && (i < len)) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000943 i++;
944 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000945 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000946 current_word_end = i;
947 break;
948 }
949 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000950
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000951 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000952 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000953 return;
954 }
955 if (current_x >= last_word_end) {
956 right = (current_x - current_word_start) + 1;
957 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000958 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000959 }
960
Chris Allegretta2084acc2001-11-29 03:43:08 +0000961 /* Subtract length of original line, plus one for the newline, from
962 totsize. */
963 totsize -= (strlen(inptr->data) + 1);
964
Chris Allegretta88b09152001-05-17 11:35:43 +0000965 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000966 strcpy(temp->data, &inptr->data[current_word_start]);
967 inptr->data = nrealloc(inptr->data, last_word_end + 2);
968 inptr->data[last_word_end + 1] = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +0000969
970 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
971 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
972
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000973 } else
974 /* Category 1b: one word on the line and word not taking up whole line
975 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000976 if (last_word_end == -1) {
Chris Allegretta88b09152001-05-17 11:35:43 +0000977 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000978 strcpy(temp->data, &inptr->data[current_word_start]);
979
980 /* Inside word, remove it from original, and move cursor to right spot. */
981 if (current_x >= current_word_start) {
982 right = current_x - current_word_start;
Chris Allegretta56214c62001-09-27 02:46:53 +0000983
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000984 current_x = 0;
Chris Allegrettaff989832001-09-17 13:48:00 +0000985#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +0000986 if (ISSET(AUTOINDENT)) {
987 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000988 while ((inptr->next->data[i] == ' '
989 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +0000990 i++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000991 }
Chris Allegretta94a78b82001-03-14 08:28:48 +0000992 }
Chris Allegrettaff989832001-09-17 13:48:00 +0000993#endif
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000994 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000995 }
996
Chris Allegretta2084acc2001-11-29 03:43:08 +0000997 /* Subtract length of original line, plus one for the newline, from
998 totsize. */
999 totsize -= (strlen(inptr->data) + 1);
1000
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001001 null_at(&inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001002
Chris Allegretta2084acc2001-11-29 03:43:08 +00001003 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1004 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
1005
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001006 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
1007 mark_beginbuf = temp;
1008 mark_beginx = 0;
1009 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001010 }
1011
1012 /* Category 2: two or more words on the line. */
1013 else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001014 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001015 if (current_x < current_word_start) {
1016 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001017 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001018 strcpy(temp->data, &inptr->data[current_word_start]);
1019
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001020 if (!isspace((int) input_char)) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001021 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001022
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001023 while (isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001024 i--;
1025 assert(i >= 0);
1026 }
1027 } else if (current_x <= last_word_end)
1028 i = last_word_end - 1;
1029 else
1030 i = current_x;
1031
Chris Allegretta2084acc2001-11-29 03:43:08 +00001032 /* Subtract length of original line, plus one for the newline, from
1033 totsize. */
1034 totsize -= (strlen(inptr->data) + 1);
1035
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001036 inptr->data = nrealloc(inptr->data, i + 2);
1037 inptr->data[i + 1] = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001038
1039 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1040 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
1041
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001042 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001043
1044
1045 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001046 else if ((current_x >= current_word_start)
1047 && (current_x <= (current_word_end + 1))) {
1048 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001049 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001050 strcpy(temp->data, &inptr->data[current_word_start]);
1051
1052 down = 1;
1053
1054 right = current_x - current_word_start;
Chris Allegrettaff989832001-09-17 13:48:00 +00001055#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001056 if (ISSET(AUTOINDENT)) {
1057 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001058 while ((inptr->next->data[i] == ' '
1059 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001060 i++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001061 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001062 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001063#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001064 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001065 current_x = current_word_start;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001066
Chris Allegretta2084acc2001-11-29 03:43:08 +00001067 /* Subtract length of original line, plus one for the newline, from
1068 totsize. */
1069 totsize -= (strlen(inptr->data) + 1);
1070
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001071 null_at(&inptr->data, current_word_start);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001072
Chris Allegretta2084acc2001-11-29 03:43:08 +00001073 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1074 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001075 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001076
1077
1078 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001079 else {
1080 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001081 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001082 strcpy(temp->data, &inptr->data[current_word_start]);
1083
1084 down = 1;
1085 right = current_x - current_word_start;
1086
1087 current_x = current_word_start;
1088 i = current_word_start - 1;
1089
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001090 while (isspace((int) inptr->data[i])) {
Adam Rogoyski3d449b42000-06-19 17:30:14 +00001091 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001092 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001093 }
Chris Allegretta2084acc2001-11-29 03:43:08 +00001094
1095 /* Subtract length of original line, plus one for the newline, from
1096 totsize. */
1097 totsize -= (strlen(inptr->data) + 1);
1098
1099 inptr->data = nrealloc(inptr->data, i + 2);
1100 inptr->data[i + 1] = 0;
1101
1102 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1103 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001104 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001105 }
1106
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001107 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001108 if (ISSET(SAMELINEWRAP) && inptr->next) {
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001109 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001110
Chris Allegretta94a78b82001-03-14 08:28:48 +00001111 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001112 char *p =
Chris Allegretta88b09152001-05-17 11:35:43 +00001113 charalloc((strlen(temp->data) + strlen(inptr->next->data) + 2));
Chris Allegretta94a78b82001-03-14 08:28:48 +00001114
Chris Allegretta56214c62001-09-27 02:46:53 +00001115 /* We're adding to an existing line instead of creating a new
1116 one; decrement totlines here so that when it gets incremented
1117 below, it won't end up being high by one. */
1118 totlines--;
1119
Chris Allegrettaff989832001-09-17 13:48:00 +00001120#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001121 if (ISSET(AUTOINDENT)) {
1122 int non = 0;
1123
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001124 /* Grab the beginning of the next line until it's not a
1125 space or tab, then null terminate it so we can strcat it
1126 to hell */
1127 while ((inptr->next->data[non] == ' '
Chris Allegretta355fbe52001-07-14 19:32:47 +00001128 || inptr->next->data[non] == '\t')) {
1129 p[non] = inptr->next->data[non];
1130 non++;
1131 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001132 p[non] = 0;
1133 strcat(p, temp->data);
1134 strcat(p, " ");
1135
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001136 /* Now tack on the rest of the next line after the spaces and
1137 tabs */
Chris Allegretta94a78b82001-03-14 08:28:48 +00001138 strcat(p, &inptr->next->data[non]);
Chris Allegrettaff989832001-09-17 13:48:00 +00001139 } else
1140#endif
1141 {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001142 strcpy(p, temp->data);
1143 strcat(p, " ");
1144 strcat(p, inptr->next->data);
1145 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001146
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001147 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001148 inptr->next->data = p;
1149
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001150 free(temp->data);
1151 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001152
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001153 current_x = old_x;
1154 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001155 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001156 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001157 else {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001158
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001159 temp->prev = inptr;
1160 temp->next = inptr->next;
1161
1162 if (inptr->next)
1163 inptr->next->prev = temp;
1164 inptr->next = temp;
1165
1166 if (!temp->next)
1167 filebot = temp;
1168
1169 SET(SAMELINEWRAP);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001170
Chris Allegrettaff989832001-09-17 13:48:00 +00001171#ifndef NANO_SMALL
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001172 if (ISSET(AUTOINDENT)) {
1173 char *spc = inptr->data;
1174 char *t = NULL;
1175 int extra = 0;
1176 if (spc) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001177 while ((*spc == ' ') || (*spc == '\t')) {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001178 extra++;
1179 spc++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001180 totsize++;
Chris Allegretta438f7132002-01-16 00:54:47 +00001181 right++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001182 }
Chris Allegretta88b09152001-05-17 11:35:43 +00001183 t = charalloc(strlen(temp->data) + extra + 1);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001184 strncpy(t, inptr->data, extra);
1185 strcpy(t + extra, temp->data);
1186 free(temp->data);
1187 temp->data = t;
1188 }
1189 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001190#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001191 }
1192
1193
1194 totlines++;
Chris Allegretta88520c92001-05-05 17:45:54 +00001195 /* Everything about it makes me want this line here, but it causes
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001196 * totsize to be high by one for some reason. Sigh. (Rob) */
1197 /* totsize++; */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001198
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001199 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001200 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001201
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001202
1203 /* Move the cursor to the new line if appropriate. */
1204 if (down) {
1205 do_right();
1206 }
1207
1208 /* Move the cursor to the correct spot in the line if appropriate. */
1209 while (right--) {
1210 do_right();
1211 }
1212
Chris Allegretta234a34d2000-07-29 04:33:38 +00001213 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001214 reset_cursor();
1215 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001216}
1217
1218/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001219void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001220{
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001221 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001222#ifdef DEBUG
1223 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
1224 inptr->data);
1225#endif
1226
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001227 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001228 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001229 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001230 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001231
1232 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001233 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001234
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001235 while (isspace((int) inptr->data[i]) && inptr->data[i])
Adam Rogoyski09f97962000-06-20 02:50:33 +00001236 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001237
Adam Rogoyski09f97962000-06-20 02:50:33 +00001238 if (!inptr->data[i])
1239 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001240
Adam Rogoyski09f97962000-06-20 02:50:33 +00001241 /* String must be at least 1 character long. */
1242 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001243 if (isspace((int) inptr->data[i])) {
Adam Rogoyski09f97962000-06-20 02:50:33 +00001244 if (!char_found)
1245 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001246 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001247 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001248 } else
1249 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001250 }
Adam Rogoyski09f97962000-06-20 02:50:33 +00001251
1252 if (char_found == 2)
1253 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001254 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001255}
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001256#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001257
1258/* Stuff we do when we abort from programs and want to clean up the
Chris Allegretta88520c92001-05-05 17:45:54 +00001259 * screen. This doesn't do much right now.
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001260 */
1261void do_early_abort(void)
1262{
1263 blank_statusbar_refresh();
1264}
1265
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001266int do_backspace(void)
1267{
1268 filestruct *previous, *tmp;
1269
1270 if (current_x != 0) {
1271 /* Let's get dangerous */
1272 memmove(&current->data[current_x - 1], &current->data[current_x],
1273 strlen(current->data) - current_x + 1);
1274#ifdef DEBUG
1275 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
1276#endif
1277 align(&current->data);
1278 do_left();
1279 } else {
1280 if (current == fileage)
1281 return 0; /* Can't delete past top of file */
1282
1283 previous = current->prev;
1284 current_x = strlen(previous->data);
1285 previous->data = nrealloc(previous->data,
1286 strlen(previous->data) +
1287 strlen(current->data) + 1);
1288 strcat(previous->data, current->data);
1289
1290 tmp = current;
1291 unlink_node(current);
1292 delete_node(current);
1293 if (current == edittop) {
1294 if (previous->next)
1295 current = previous->next;
1296 else
1297 current = previous;
Chris Allegretta3e3ae942001-09-22 19:02:04 +00001298 page_up();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001299 } else {
1300 if (previous->next)
1301 current = previous->next;
1302 else
1303 current = previous;
1304 update_line(current, current_x);
1305 }
1306
1307 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001308 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001309 filebot = current;
1310 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001311
1312 /* Recreate the magic line if we're deleting it AND if the
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001313 line we're on now is NOT blank. if it is blank we
1314 can just use IT for the magic line. This is how Pico
1315 appears to do it, in any case */
Chris Allegretta28a0f892000-07-05 22:47:54 +00001316 if (strcmp(current->data, "")) {
1317 new_magicline();
1318 fix_editbot();
1319 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001320 }
1321
1322 current = previous;
1323 renumber(current);
1324 previous_line();
1325 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001326#ifdef DEBUG
1327 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
1328#endif
1329
1330 }
1331
1332 totsize--;
1333 set_modified();
1334 UNSET(KEEP_CUTBUFFER);
1335 edit_refresh();
1336 return 1;
1337}
1338
1339int do_delete(void)
1340{
1341 filestruct *foo;
1342
Chris Allegretta2084acc2001-11-29 03:43:08 +00001343 /* blbf -> blank line before filebot (see below) */
1344 int blbf = 0;
1345
1346 if (current->next == filebot && !strcmp(current->data, ""))
1347 blbf = 1;
1348
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001349 if (current_x != strlen(current->data)) {
1350 /* Let's get dangerous */
1351 memmove(&current->data[current_x], &current->data[current_x + 1],
1352 strlen(current->data) - current_x);
1353
1354 align(&current->data);
1355
Chris Allegretta2084acc2001-11-29 03:43:08 +00001356 /* Now that we have a magic line again, we can check for both being
1357 on the line before filebot as well as at filebot; it's a special
1358 case if we're on the line before filebot and it's blank, since we
1359 should be able to delete it */
1360 } else if (current->next != NULL && (current->next != filebot || blbf)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001361 current->data = nrealloc(current->data,
1362 strlen(current->data) +
1363 strlen(current->next->data) + 1);
1364 strcat(current->data, current->next->data);
1365
1366 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001367 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001368 filebot = current;
1369 editbot = current;
1370 }
1371
1372 unlink_node(foo);
1373 delete_node(foo);
1374 update_line(current, current_x);
1375
Chris Allegretta4ed13152001-02-10 17:50:50 +00001376 /* Please see the comment in do_backspace if you don't understand
Chris Allegretta28a0f892000-07-05 22:47:54 +00001377 this test */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001378 if (current == filebot && strcmp(current->data, "")) {
Chris Allegretta28a0f892000-07-05 22:47:54 +00001379 new_magicline();
1380 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001381 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001382 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001383 renumber(current);
1384 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001385 } else
1386 return 0;
1387
1388 totsize--;
1389 set_modified();
1390 UNSET(KEEP_CUTBUFFER);
1391 edit_refresh();
1392 return 1;
1393}
1394
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001395void wrap_reset(void)
1396{
1397 UNSET(SAMELINEWRAP);
1398}
1399
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001400#ifndef DISABLE_SPELLER
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001401
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001402int do_int_spell_fix(char *word)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001403{
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001404 char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001405 filestruct *begin;
Chris Allegretta23b74b22002-01-21 20:32:22 +00001406 int i = 0, j = 0, beginx, beginx_top, reverse_search_set;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001407
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001408 /* save where we are */
1409 begin = current;
1410 beginx = current_x + 1;
1411
Chris Allegretta23b74b22002-01-21 20:32:22 +00001412 /* Make sure Spell Check goes forward only */
1413 reverse_search_set = ISSET(REVERSE_SEARCH);
1414 UNSET(REVERSE_SEARCH);
1415
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001416 /* save the current search/replace strings */
1417 search_init_globals();
1418 save_search = mallocstrcpy(save_search, last_search);
1419 save_replace = mallocstrcpy(save_replace, last_replace);
1420
1421 /* set search/replace strings to mis-spelt word */
1422 prevanswer = mallocstrcpy(prevanswer, word);
1423 last_search = mallocstrcpy(last_search, word);
1424 last_replace = mallocstrcpy(last_replace, word);
1425
1426 /* start from the top of file */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001427 current = fileage;
1428 current_x = beginx_top = -1;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001429
1430 search_last_line = FALSE;
1431
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001432 edit_update(fileage, TOP);
1433
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001434 while (1) {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001435
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001436 /* make sure word is still mis-spelt (i.e. when multi-errors) */
1437 if (findnextstr(TRUE, FALSE, fileage, beginx_top, prevanswer) != NULL) {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001438
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001439 /* find wholewords only */
1440 if (!is_whole_word(current_x, current, prevanswer))
1441 continue;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001442
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001443 do_replace_highlight(TRUE, prevanswer);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001444
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001445 /* allow replace word to be corrected */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001446 i = statusq(0, spell_list, last_replace, _("Edit a replacement"));
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001447
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001448 do_replace_highlight(FALSE, prevanswer);
1449
1450 /* start from the start of this line again */
1451 current = fileage;
1452 current_x = beginx_top;
1453
1454 search_last_line = FALSE;
1455
1456 if (strcmp(prevanswer,answer) != 0) {
1457 j = i;
1458 do_replace_loop(prevanswer, fileage, &beginx_top, TRUE, &j);
1459 }
Chris Allegretta80838272001-12-02 06:03:22 +00001460 }
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001461
1462 break;
Rocco Corsi562964d2002-01-13 03:18:03 +00001463 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001464
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001465 /* restore the search/replace strings */
Chris Allegrettabef12972002-03-06 03:30:40 +00001466 free(last_search); last_search=save_search;
1467 free(last_replace); last_replace=save_replace;
1468 free(prevanswer);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001469
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001470 /* restore where we were */
1471 current = begin;
1472 current_x = beginx - 1;
1473
Chris Allegretta23b74b22002-01-21 20:32:22 +00001474 /* restore Search/Replace direction */
1475 if (reverse_search_set)
1476 SET(REVERSE_SEARCH);
1477
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001478 edit_update(current, CENTER);
1479
1480 if (i == -1)
1481 return FALSE;
1482
1483 return TRUE;
1484}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001485
1486/* Integrated spell checking using 'spell' program */
Chris Allegretta271e9722000-11-10 18:15:43 +00001487int do_int_speller(char *tempfile_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001488{
Chris Allegretta271e9722000-11-10 18:15:43 +00001489 char *read_buff, *read_buff_ptr, *read_buff_word;
1490 long pipe_buff_size;
1491 int in_fd[2], tempfile_fd;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001492 int spell_status;
1493 pid_t pid_spell;
1494 ssize_t bytesread;
1495
Chris Allegretta271e9722000-11-10 18:15:43 +00001496 /* Create a pipe to spell program */
1497
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001498 if (pipe(in_fd) == -1)
1499 return FALSE;
1500
Chris Allegretta271e9722000-11-10 18:15:43 +00001501 /* A new process to run spell in */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001502
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001503 if ((pid_spell = fork()) == 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001504
1505 /* Child continues, (i.e. future spell process) */
1506
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001507 close(in_fd[0]);
1508
Chris Allegretta271e9722000-11-10 18:15:43 +00001509 /* replace the standard in with the tempfile */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001510
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001511 if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001512
1513 close(in_fd[1]);
1514 exit(1);
1515 }
1516
1517 if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
1518
1519 close(tempfile_fd);
1520 close(in_fd[1]);
1521 exit(1);
1522 }
1523 close(tempfile_fd);
1524
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001525
Chris Allegretta271e9722000-11-10 18:15:43 +00001526 /* send spell's standard out to the pipe */
1527
1528 if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1529
1530 close(in_fd[1]);
1531 exit(1);
1532 }
1533 close(in_fd[1]);
1534
1535 /* Start spell program, we are using the PATH here!?!? */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001536 execlp("spell", "spell", NULL);
1537
Chris Allegretta271e9722000-11-10 18:15:43 +00001538 /* Should not be reached, if spell is found!!! */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001539
Chris Allegretta271e9722000-11-10 18:15:43 +00001540 exit(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001541 }
1542
1543 /* Parent continues here */
1544
Chris Allegretta271e9722000-11-10 18:15:43 +00001545 close(in_fd[1]);
1546
1547 /* Child process was not forked successfully */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001548
1549 if (pid_spell < 0) {
1550
Chris Allegretta271e9722000-11-10 18:15:43 +00001551 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001552 return FALSE;
1553 }
1554
Chris Allegretta271e9722000-11-10 18:15:43 +00001555 /* Get system pipe buffer size */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001556
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001557 if ((pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001558
Chris Allegretta271e9722000-11-10 18:15:43 +00001559 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001560 return FALSE;
Chris Allegretta271e9722000-11-10 18:15:43 +00001561 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001562
Chris Allegretta88b09152001-05-17 11:35:43 +00001563 read_buff = charalloc(pipe_buff_size + 1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001564
Chris Allegretta271e9722000-11-10 18:15:43 +00001565 /* Process the returned spelling errors */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001566
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001567 while ((bytesread = read(in_fd[0], read_buff, pipe_buff_size)) > 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001568
Chris Allegretta271e9722000-11-10 18:15:43 +00001569 read_buff[bytesread] = (char) NULL;
1570 read_buff_word = read_buff_ptr = read_buff;
1571
1572 while (*read_buff_ptr != (char) NULL) {
1573
1574 /* Windows version may need to process additional char '\r' */
1575
1576 /* Possible problem here if last word not followed by '\n' */
1577
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001578 if (*read_buff_ptr == '\n') {
Chris Allegretta271e9722000-11-10 18:15:43 +00001579 *read_buff_ptr = (char) NULL;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001580 if (!do_int_spell_fix(read_buff_word)) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001581
1582 close(in_fd[0]);
1583 free(read_buff);
1584 replace_abort();
1585
1586 return TRUE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001587 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001588 read_buff_word = read_buff_ptr;
1589 read_buff_word++;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001590 }
1591
1592 read_buff_ptr++;
1593 }
1594 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001595
1596 close(in_fd[0]);
1597 free(read_buff);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001598 replace_abort();
1599
Chris Allegretta271e9722000-11-10 18:15:43 +00001600 /* Process end of spell process */
1601
1602 wait(&spell_status);
1603 if (WIFEXITED(spell_status)) {
1604 if (WEXITSTATUS(spell_status) != 0)
1605 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001606 } else
Chris Allegretta271e9722000-11-10 18:15:43 +00001607 return FALSE;
1608
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001609 return TRUE;
1610}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001611
1612/* External spell checking */
Chris Allegretta271e9722000-11-10 18:15:43 +00001613int do_alt_speller(char *file_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001614{
Chris Allegrettab3655b42001-10-22 03:15:31 +00001615 int alt_spell_status, lineno_cur = current->lineno;
1616 int x_cur = current_x, y_cur = current_y, pww_cur = placewewant;
1617
Chris Allegretta271e9722000-11-10 18:15:43 +00001618 pid_t pid_spell;
Chris Allegretta169ee842001-01-26 01:57:32 +00001619 char *ptr;
1620 static int arglen = 3;
1621 static char **spellargs = (char **) NULL;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001622
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001623 endwin();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001624
Chris Allegrettae434b452001-01-27 19:25:00 +00001625 /* Set up an argument list to pass the execvp function */
1626 if (spellargs == NULL) {
1627 spellargs = nmalloc(arglen * sizeof(char *));
Chris Allegretta271e9722000-11-10 18:15:43 +00001628
Chris Allegrettae434b452001-01-27 19:25:00 +00001629 spellargs[0] = strtok(alt_speller, " ");
1630 while ((ptr = strtok(NULL, " ")) != NULL) {
1631 arglen++;
1632 spellargs = nrealloc(spellargs, arglen * sizeof(char *));
1633 spellargs[arglen - 3] = ptr;
Chris Allegretta169ee842001-01-26 01:57:32 +00001634 }
Chris Allegrettae434b452001-01-27 19:25:00 +00001635 spellargs[arglen - 1] = NULL;
1636 }
1637 spellargs[arglen - 2] = file_name;
1638
1639 /* Start a new process for the alternate speller */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001640 if ((pid_spell = fork()) == 0) {
Chris Allegretta169ee842001-01-26 01:57:32 +00001641
Chris Allegretta88520c92001-05-05 17:45:54 +00001642 /* Start alternate spell program; we are using the PATH here!?!? */
Chris Allegretta169ee842001-01-26 01:57:32 +00001643 execvp(spellargs[0], spellargs);
Chris Allegretta271e9722000-11-10 18:15:43 +00001644
1645 /* Should not be reached, if alternate speller is found!!! */
1646
1647 exit(1);
1648 }
1649
1650 /* Could not fork?? */
1651
1652 if (pid_spell < 0)
1653 return FALSE;
1654
1655 /* Wait for alternate speller to complete */
1656
1657 wait(&alt_spell_status);
1658 if (WIFEXITED(alt_spell_status)) {
1659 if (WEXITSTATUS(alt_spell_status) != 0)
1660 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001661 } else
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001662 return FALSE;
1663
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001664 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001665 free_filestruct(fileage);
Chris Allegretta56214c62001-09-27 02:46:53 +00001666 global_init(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001667 open_file(file_name, 0, 1);
Rocco Corsi4dfaf932001-04-20 01:59:55 +00001668
Chris Allegretta1b3381b2001-09-28 21:59:01 +00001669 /* go back to the old position, mark the file as modified, and make
1670 sure that the titlebar is refreshed */
1671 do_gotopos(lineno_cur, x_cur, y_cur, pww_cur);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001672 set_modified();
Chris Allegrettae1f14522001-09-19 03:19:43 +00001673 clearok(topwin, FALSE);
1674 titlebar(NULL);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001675
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001676 return TRUE;
1677}
1678#endif
1679
1680int do_spell(void)
1681{
1682
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001683#ifdef DISABLE_SPELLER
Chris Allegrettaff269f82000-12-01 18:46:01 +00001684 nano_disabled_msg();
1685 return (TRUE);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001686#else
Chris Allegretta271e9722000-11-10 18:15:43 +00001687 char *temp;
1688 int spell_res;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001689
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001690 if ((temp = safe_tempnam(0, "nano.")) == NULL) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001691 statusbar(_("Could not create a temporary filename: %s"),
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001692 strerror(errno));
Chris Allegretta271e9722000-11-10 18:15:43 +00001693 return 0;
1694 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001695
Chris Allegrettaecc3d7f2001-06-05 23:24:55 +00001696 if (write_file(temp, 1, 0, 0) == -1) {
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001697 statusbar(_("Spell checking failed: unable to write temp file!"));
Chris Allegrettabef12972002-03-06 03:30:40 +00001698 free(temp);
Chris Allegretta271e9722000-11-10 18:15:43 +00001699 return 0;
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001700 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001701
Chris Allegrettae1f14522001-09-19 03:19:43 +00001702#ifdef ENABLE_MULTIBUFFER
1703 /* update the current open_files entry before spell-checking, in case
1704 any problems occur; the case of there being no open_files entries
Chris Allegretta48b06702002-02-22 04:30:50 +00001705 is handled elsewhere (before we reach this point) */
1706 add_open_file(1);
Chris Allegrettae1f14522001-09-19 03:19:43 +00001707#endif
1708
Chris Allegretta271e9722000-11-10 18:15:43 +00001709 if (alt_speller)
1710 spell_res = do_alt_speller(temp);
1711 else
1712 spell_res = do_int_speller(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001713
Chris Allegretta271e9722000-11-10 18:15:43 +00001714 remove(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001715
1716 if (spell_res)
1717 statusbar(_("Finished checking spelling"));
1718 else
1719 statusbar(_("Spell checking failed"));
1720
Chris Allegrettabef12972002-03-06 03:30:40 +00001721 free(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001722 return spell_res;
1723
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001724#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001725}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001726
1727int do_exit(void)
1728{
1729 int i;
1730
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001731 if (!ISSET(MODIFIED)) {
1732
Chris Allegretta355fbe52001-07-14 19:32:47 +00001733#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001734 if (!close_open_file()) {
1735 display_main_list();
1736 return 1;
1737 }
1738 else
1739#endif
1740
1741 finish(0);
1742 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001743
Chris Allegretta30885552000-07-14 01:20:12 +00001744 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001745 i = 1;
1746 } else {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001747 i = do_yesno(0, 0,
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001748 _
1749 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1750 }
1751
1752#ifdef DEBUG
1753 dump_buffer(fileage);
1754#endif
1755
1756 if (i == 1) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001757 if (do_writeout(filename, 1, 0) > 0) {
1758
Chris Allegretta355fbe52001-07-14 19:32:47 +00001759#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001760 if (!close_open_file()) {
1761 display_main_list();
1762 return 1;
1763 }
1764 else
1765#endif
1766
1767 finish(0);
1768 }
1769 } else if (i == 0) {
1770
Chris Allegretta355fbe52001-07-14 19:32:47 +00001771#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001772 if (!close_open_file()) {
1773 display_main_list();
1774 return 1;
1775 }
1776 else
1777#endif
1778
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001779 finish(0);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001780 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001781 statusbar(_("Cancelled"));
1782
1783 display_main_list();
1784 return 1;
1785}
1786
Chris Allegretta84de5522001-04-12 14:51:48 +00001787#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001788#ifdef NCURSES_MOUSE_VERSION
1789void do_mouse(void)
1790{
1791 MEVENT mevent;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001792 int foo = 0, tab_found = 0;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001793 int currslen;
Chris Allegretta40639dd2002-03-04 12:25:34 +00001794 shortcut *s = currshortcut;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001795
1796 if (getmouse(&mevent) == ERR)
1797 return;
1798
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001799 /* If mouse not in edit or bottom window, return */
1800 if (wenclose(edit, mevent.y, mevent.x)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001801
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001802 /* Don't let people screw with the marker when they're in a
1803 subfunction */
1804 if (currshortcut != main_list)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001805 return;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001806
1807 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1808 mevent.y -= 2;
1809
1810 /* Selecting where the cursor is sets the mark.
1811 * Selecting beyond the line length with the cursor at the end of the
1812 * line sets the mark as well.
1813 */
1814 if ((mevent.y == current_y) &&
1815 ((mevent.x == current_x) || (current_x == strlen(current->data)
1816 && (mevent.x >
1817 strlen(current->data))))) {
1818 if (ISSET(VIEW_MODE)) {
1819 print_view_warning();
1820 return;
1821 }
1822 do_mark();
1823 } else if (mevent.y > current_y) {
1824 while (mevent.y > current_y) {
1825 if (current->next != NULL)
1826 current = current->next;
1827 else
1828 break;
1829 current_y++;
1830 }
1831 } else if (mevent.y < current_y) {
1832 while (mevent.y < current_y) {
1833 if (current->prev != NULL)
1834 current = current->prev;
1835 else
1836 break;
1837 current_y--;
1838 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001839 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001840 current_x = mevent.x;
1841 placewewant = current_x;
1842 while (foo < current_x) {
1843 if (current->data[foo] == NANO_CONTROL_I) {
1844 current_x -= tabsize - (foo % tabsize);
1845 tab_found = 1;
1846 } else if (current->data[foo] & 0x80);
1847 else if (current->data[foo] < 32)
1848 current_x--;
1849 foo++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001850 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001851 /* This is where tab_found comes in. I can't figure out why,
1852 * but without it any line with a tab will place the cursor
1853 * one character behind. Whatever, this fixes it. */
1854 if (tab_found == 1)
1855 current_x++;
1856
1857 if (current_x > strlen(current->data))
1858 current_x = strlen(current->data);
1859
1860 update_cursor();
1861 edit_refresh();
1862 } else if (wenclose(bottomwin, mevent.y, mevent.x) && !ISSET(NO_HELP)) {
Chris Allegrettaa951f212001-09-27 21:07:39 +00001863
Chris Allegretta40639dd2002-03-04 12:25:34 +00001864 int i, k;
Chris Allegrettaa951f212001-09-27 21:07:39 +00001865
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001866 if (currshortcut == main_list)
1867 currslen = MAIN_VISIBLE;
1868 else
1869 currslen = length_of_list(currshortcut);
1870
Chris Allegrettaa951f212001-09-27 21:07:39 +00001871 if (currslen < 2)
1872 k = COLS / 6;
1873 else
1874 k = COLS / ((currslen + (currslen %2)) / 2);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001875
1876 /* Determine what shortcut list was clicked */
1877 mevent.y -= (editwinrows + 3);
1878
1879 if (mevent.y < 0) /* They clicked on the statusbar */
1880 return;
1881
1882 /* Don't select stuff beyond list length */
1883 if (mevent.x / k >= currslen)
1884 return;
1885
Chris Allegretta40639dd2002-03-04 12:25:34 +00001886 for (i = 0; i < (mevent.x / k) * 2 + mevent.y; i++)
1887 s = s->next;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001888
1889 /* And ungetch that value */
Chris Allegretta40639dd2002-03-04 12:25:34 +00001890 ungetch(s->val);
Chris Allegretta6414b402001-09-21 03:21:11 +00001891
1892 /* And if it's an alt-key sequence, we should probably send alt
1893 too ;-) */
Chris Allegretta40639dd2002-03-04 12:25:34 +00001894 if (s->val >= 'a' && s->val <= 'z')
Chris Allegretta6414b402001-09-21 03:21:11 +00001895 ungetch(27);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001896 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001897}
1898#endif
1899#endif
1900
1901/* Handler for SIGHUP */
1902RETSIGTYPE handle_hup(int signal)
1903{
Chris Allegrettae7a58932000-12-02 02:36:22 +00001904 die(_("Received SIGHUP"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001905}
1906
Chris Allegretta18f8be02000-09-04 03:20:38 +00001907/* What do we do when we catch the suspend signal */
1908RETSIGTYPE do_suspend(int signal)
1909{
Chris Allegretta18f8be02000-09-04 03:20:38 +00001910 endwin();
Chris Allegretta521e00d2001-06-28 16:52:52 +00001911 printf("\n\n\n\n\nUse \"fg\" to return to nano\n");
1912 fflush(stdout);
1913
Chris Allegretta7b0667f2002-01-10 12:44:21 +00001914 /* Restore the terminal settings for the disabled keys */
1915 tcsetattr(0, TCSANOW, &oldterm);
1916
Chris Allegretta521e00d2001-06-28 16:52:52 +00001917 /* We used to re-enable the default SIG_DFL and raise SIGTSTP, but
1918 then we could be (and were) interrupted in the middle of the call.
1919 So we do it the mutt way instead */
1920 kill(0, SIGSTOP);
Chris Allegretta18f8be02000-09-04 03:20:38 +00001921}
1922
1923/* Restore the suspend handler when we come back into the prog */
1924RETSIGTYPE do_cont(int signal)
1925{
1926
Chris Allegretta521e00d2001-06-28 16:52:52 +00001927 /* Now we just update the screen instead of having to reenable the
1928 SIGTSTP handler */
1929
Chris Allegretta521e00d2001-06-28 16:52:52 +00001930 doupdate();
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00001931 /* The Hurd seems to need this, otherwise a ^Y after a ^Z will
1932 start suspending again */
1933 signal_init();
Chris Allegretta18f8be02000-09-04 03:20:38 +00001934}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001935
1936void handle_sigwinch(int s)
1937{
1938#ifndef NANO_SMALL
1939 char *tty = NULL;
1940 int fd = 0;
1941 int result = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001942 struct winsize win;
1943
1944 tty = ttyname(0);
1945 if (!tty)
1946 return;
1947 fd = open(tty, O_RDWR);
1948 if (fd == -1)
1949 return;
1950 result = ioctl(fd, TIOCGWINSZ, &win);
1951 if (result == -1)
1952 return;
1953
1954
1955 COLS = win.ws_col;
1956 LINES = win.ws_row;
1957
Chris Allegrettae61e8302001-01-14 05:18:27 +00001958 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1959 die_too_small();
1960
Chris Allegretta6fe61492001-05-21 12:56:25 +00001961#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettae61e8302001-01-14 05:18:27 +00001962 if ((fill = COLS - CHARS_FROM_EOL) < MIN_FILL_LENGTH)
1963 die_too_small();
Chris Allegretta6fe61492001-05-21 12:56:25 +00001964#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001965
Chris Allegretta0a06e072001-01-23 02:35:04 +00001966 hblank = nrealloc(hblank, COLS + 1);
1967 memset(hblank, ' ', COLS);
1968 hblank[COLS] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001969
Chris Allegretta618f5d72001-02-16 04:48:30 +00001970#ifdef HAVE_RESIZETERM
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001971 resizeterm(LINES, COLS);
1972#ifdef HAVE_WRESIZE
1973 if (wresize(topwin, 2, COLS) == ERR)
1974 die(_("Cannot resize top win"));
1975 if (mvwin(topwin, 0, 0) == ERR)
1976 die(_("Cannot move top win"));
1977 if (wresize(edit, editwinrows, COLS) == ERR)
1978 die(_("Cannot resize edit win"));
1979 if (mvwin(edit, 2, 0) == ERR)
1980 die(_("Cannot move edit win"));
1981 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1982 die(_("Cannot resize bottom win"));
1983 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1984 die(_("Cannot move bottom win"));
1985#endif /* HAVE_WRESIZE */
Chris Allegretta618f5d72001-02-16 04:48:30 +00001986#endif /* HAVE_RESIZETERM */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001987
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001988 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001989
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001990 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001991 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001992 }
1993 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00001994
1995 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001996 refresh();
Chris Allegrettaf4b96012001-01-03 07:11:47 +00001997 titlebar(NULL);
Chris Allegretta97accc62000-06-19 05:45:52 +00001998 edit_refresh();
1999 display_main_list();
Chris Allegretta08020882001-01-29 23:37:54 +00002000 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002001 total_refresh();
Chris Allegretta08020882001-01-29 23:37:54 +00002002
Chris Allegretta4e90c402001-01-29 23:40:43 +00002003 /* Turn cursor back on for sure */
2004 curs_set(1);
2005
Chris Allegretta08020882001-01-29 23:37:54 +00002006 /* Jump back to mainloop */
2007 siglongjmp(jmpbuf, 1);
2008
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002009#endif
2010}
2011
Chris Allegretta756f2202000-09-01 13:32:47 +00002012void signal_init(void)
2013{
Chris Allegrettaac899e52001-06-30 04:09:09 +00002014#ifdef _POSIX_VDISABLE
2015 struct termios term;
2016#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002017
Chris Allegretta88520c92001-05-05 17:45:54 +00002018 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
Chris Allegretta756f2202000-09-01 13:32:47 +00002019 memset(&act, 0, sizeof(struct sigaction));
2020 act.sa_handler = SIG_IGN;
2021 sigaction(SIGINT, &act, NULL);
Chris Allegretta756f2202000-09-01 13:32:47 +00002022
Chris Allegretta88520c92001-05-05 17:45:54 +00002023 /* Trap SIGHUP cuz we want to write the file out. */
Chris Allegretta756f2202000-09-01 13:32:47 +00002024 act.sa_handler = handle_hup;
2025 sigaction(SIGHUP, &act, NULL);
2026
2027 act.sa_handler = handle_sigwinch;
2028 sigaction(SIGWINCH, &act, NULL);
2029
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002030
2031#ifdef _POSIX_VDISABLE
2032 tcgetattr(0, &term);
2033
2034#ifdef VDSUSP
2035 term.c_cc[VDSUSP] = _POSIX_VDISABLE;
2036#endif /* VDSUSP */
2037
2038#endif /* _POSIX_VDISABLE */
2039
Chris Allegretta521e00d2001-06-28 16:52:52 +00002040 if (!ISSET(SUSPEND)) {
Chris Allegrettaac899e52001-06-30 04:09:09 +00002041
2042/* Insane! */
2043#ifdef _POSIX_VDISABLE
Chris Allegrettaac899e52001-06-30 04:09:09 +00002044 term.c_cc[VSUSP] = _POSIX_VDISABLE;
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002045#else
Chris Allegrettaac899e52001-06-30 04:09:09 +00002046 act.sa_handler = SIG_IGN;
Chris Allegretta521e00d2001-06-28 16:52:52 +00002047 sigaction(SIGTSTP, &act, NULL);
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002048#endif
Chris Allegrettaac899e52001-06-30 04:09:09 +00002049
Chris Allegretta521e00d2001-06-28 16:52:52 +00002050 } else {
2051 /* if we don't do this, it seems other stuff interrupts the
2052 suspend handler! Try using nano with mutt without this line */
2053 sigfillset(&act.sa_mask);
2054
2055 act.sa_handler = do_suspend;
2056 sigaction(SIGTSTP, &act, NULL);
2057
2058 act.sa_handler = do_cont;
2059 sigaction(SIGCONT, &act, NULL);
2060 }
2061
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002062
2063#ifdef _POSIX_VDISABLE
2064 tcsetattr(0, TCSANOW, &term);
2065#endif
2066
2067
Chris Allegretta756f2202000-09-01 13:32:47 +00002068}
2069
Chris Allegretta2a42af12000-09-12 23:02:49 +00002070void window_init(void)
2071{
Chris Allegrettae61e8302001-01-14 05:18:27 +00002072 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
2073 die_too_small();
Chris Allegretta92c9dd22000-09-13 14:03:27 +00002074
Chris Allegretta88520c92001-05-05 17:45:54 +00002075 /* Set up the main text window */
Chris Allegretta2a42af12000-09-12 23:02:49 +00002076 edit = newwin(editwinrows, COLS, 2, 0);
2077
2078 /* And the other windows */
2079 topwin = newwin(2, COLS, 0, 0);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002080 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002081
Chris Allegretta155d6202001-01-08 01:50:37 +00002082#ifdef PDCURSES
2083 /* Oops, I guess we need this again.
2084 Moved here so the keypad still works after a Meta-X, for example */
2085 keypad(edit, TRUE);
2086 keypad(bottomwin, TRUE);
2087#endif
2088
Chris Allegretta2a42af12000-09-12 23:02:49 +00002089}
2090
Chris Allegretta756f2202000-09-01 13:32:47 +00002091void mouse_init(void)
2092{
Chris Allegretta84de5522001-04-12 14:51:48 +00002093#ifndef DISABLE_MOUSE
Chris Allegretta756f2202000-09-01 13:32:47 +00002094#ifdef NCURSES_MOUSE_VERSION
2095 if (ISSET(USE_MOUSE)) {
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002096 keypad_on(edit, 1);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002097 keypad_on(bottomwin, 1);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002098
Chris Allegretta756f2202000-09-01 13:32:47 +00002099 mousemask(BUTTON1_RELEASED, NULL);
2100 mouseinterval(50);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00002101
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002102 } else
Chris Allegretta756f2202000-09-01 13:32:47 +00002103 mousemask(0, NULL);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002104
Chris Allegretta756f2202000-09-01 13:32:47 +00002105#endif
2106#endif
2107
2108}
2109
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002110int do_tab(void)
2111{
2112 do_char('\t');
2113 return 1;
2114}
2115
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002116#ifndef DISABLE_JUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002117int empty_line(const char *data)
2118{
2119 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002120 if (!isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002121 return 0;
2122
2123 data++;
2124 }
2125
2126 return 1;
2127}
2128
2129int no_spaces(const char *data)
2130{
2131 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002132 if (isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002133 return 0;
2134
2135 data++;
2136 }
2137
2138 return 1;
2139}
2140
2141void justify_format(char *data)
2142{
2143 int i = 0;
2144 int len = strlen(data);
2145
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002146 /* Skip leading whitespace. */
2147 for (i = 0; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002148 if (!isspace((int) data[i]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002149 break;
2150 }
2151
2152 i++; /* (i) is now at least 2. */
2153
2154 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
2155 for (; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002156 if (isspace((int) data[i]) && isspace((int) data[i - 1])
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002157 && (data[i - 2] != '.')
2158 && (data[i-2]!='!') && (data[i-2]!='?')) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002159 memmove(data + i, data + i + 1, len - i);
2160 len--;
2161 i--;
2162 }
2163 }
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002164 /* Skip trailing whitespace.
2165 * i<=len iff there was a non-space in the line. In that case, we
2166 * strip spaces from the end of the line. Note that "line" means the
2167 * whole paragraph. */
2168 if (i<=len) {
2169 for(i=len-1; i>0 && isspace((int) data[i]); i--);
2170 data[i+1] = '\0';
2171 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002172}
2173#endif
2174
2175int do_justify(void)
2176{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002177#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +00002178 nano_disabled_msg();
2179 return 1;
2180#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002181 int slen = 0; /* length of combined lines on one line. */
Chris Allegrettabef12972002-03-06 03:30:40 +00002182 int initial_y, kbinput = 0;
2183 long totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002184 filestruct *initial = NULL, *tmpjust = NULL, *cutbak, *tmptop, *tmpbot;
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002185 filestruct *samecheck = current;
2186 int qdepth = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002187
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002188 /* Compute quote depth level */
2189 while (!strncmp(&current->data[qdepth], quotestr, strlen(quotestr)))
2190 qdepth += strlen(quotestr);
2191
2192 if (empty_line(&current->data[qdepth])) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002193 /* Justify starting at first non-empty line. */
2194 do {
2195 if (!current->next)
2196 return 1;
2197
2198 current = current->next;
2199 current_y++;
2200 }
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002201 while (strlen(current->data) >= qdepth
2202 && !strncmp(current->data, samecheck->data, qdepth)
2203 && empty_line(&current->data[qdepth]));
2204
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002205 } else {
2206 /* Search back for the beginning of the paragraph, where
2207 * Paragraph is 1) A line with leading whitespace
2208 * or 2) A line following an empty line.
2209 */
2210 while (current->prev != NULL) {
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002211 if (strncmp(current->data, samecheck->data, qdepth)
2212
2213 /* Don't keep going back if the previous line is more
2214 intented quotestr-wise than samecheck */
2215 || !strncmp(&current->data[qdepth], quotestr, strlen(quotestr))
2216 || isspace((int) current->data[qdepth])
2217 || empty_line(&current->data[qdepth]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002218 break;
2219
2220 current = current->prev;
2221 current_y--;
2222 }
2223
2224 /* First line with leading whitespace may be empty. */
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002225 if (strncmp(current->data, samecheck->data, qdepth)
2226 || !strncmp(&current->data[qdepth], quotestr, strlen(quotestr))
2227 || empty_line(&current->data[qdepth])) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002228 if (current->next) {
2229 current = current->next;
2230 current_y++;
2231 } else
2232 return 1;
2233 }
2234 }
2235 initial = current;
2236 initial_y = current_y;
2237
2238 set_modified();
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002239 cutbak = cutbuffer; /* Got to like cutbak ;) */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002240 totbak = totsize;
Chris Allegretta9149e612000-11-27 00:23:41 +00002241 cutbuffer = NULL;
2242
2243 tmptop = current;
2244 tmpjust = copy_node(current);
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002245 samecheck = tmpjust;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002246
2247 /* This is annoying because it mucks with totsize */
Chris Allegretta9149e612000-11-27 00:23:41 +00002248 add_to_cutbuffer(tmpjust);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002249
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002250 /* Put the whole paragraph into one big line. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002251 while (current->next && !isspace((int) current->next->data[0])
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002252 && !strncmp(current->next->data, samecheck->data, qdepth)
Chris Allegretta46c1b9e2002-03-05 19:58:45 +00002253
2254 /* Don't continue if current->next is indented more! */
2255 && strncmp(&current->next->data[qdepth], quotestr, strlen(quotestr))
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002256 && !empty_line(&current->next->data[qdepth])) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002257 filestruct *tmpnode = current->next;
2258 int len = strlen(current->data);
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002259 int len2 = strlen(current->next->data) - qdepth;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002260
Chris Allegretta9149e612000-11-27 00:23:41 +00002261 tmpjust = NULL;
Chris Allegretta9149e612000-11-27 00:23:41 +00002262 tmpjust = copy_node(current->next);
2263 add_to_cutbuffer(tmpjust);
2264
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002265 /* Wiping out a newline */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002266 totsize--;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002267
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002268 /* length of both strings plus space between strings and ending \0. */
2269 current->data = nrealloc(current->data, len + len2 + 2);
2270 current->data[len++] = ' ';
2271 current->data[len] = '\0';
2272
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002273 strncat(current->data, &current->next->data[qdepth], len2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002274
2275 unlink_node(tmpnode);
2276 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002277 }
2278
2279 justify_format(current->data);
2280
2281 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002282 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002283
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002284 if ((strlenpt(current->data) > (fill))
2285 && !no_spaces(current->data)) {
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002286 do {
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002287 int i = 0, j = 0;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002288 int len2 = 0;
2289 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002290
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002291
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002292/* The following code maybe could be better. In particular, can we
2293 * merely increment instead of calling strnlenpt for each new character?
2294 * In fact, can we assume the only tabs are at the beginning of the line?
2295 */
2296/* Note that we CAN break before the first word, since that is how
2297 * pico does it. */
2298 int last_space = -1; /* index of the last breakpoint */
2299 int allowed_width;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002300
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002301 i = qdepth * strlen(quotestr); /* the line starts with
2302 indentation, so we must skip it! */
2303 allowed_width = fill - i; /* how wide can our lines be? */
2304
2305 for(; i<slen; i++) {
2306 if (isspace((int) current->data[i])) last_space = i;
2307 if (last_space!=-1 &&
2308 strnlenpt(current->data,i) >= allowed_width) {
2309 i = last_space;
2310 break;
2311 }
2312 }
2313/* Now data[i] is a space. We want to break at the LAST space in this
2314 * group. Probably, the only possibility is two in a row, but let's be
2315 * generic. Note that we actually replace this final space with \0. Is
2316 * this okay? It seems to work fine. */
2317 for(; i<slen-1 && isspace((int) current->data[i+1]); i++) ;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002318
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002319 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002320
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002321 len2 = strlen(current->data + i + 1);
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002322 tmpline->data = charalloc(len2 + 1 + qdepth);
2323
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002324 for (j = 0; j < qdepth; j += strlen(quotestr))
2325 strcpy(&tmpline->data[j], quotestr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002326
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002327 /* Skip the white space in current. */
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002328 memcpy(&tmpline->data[j], current->data + i + 1, len2);
Chris Allegretta63245302002-03-04 18:12:28 +00002329 tmpline->data[len2 + qdepth] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002330
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002331 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002332
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002333 tmpline->prev = current;
2334 tmpline->next = current->next;
2335 if (current->next != NULL)
2336 current->next->prev = tmpline;
2337
2338 current->next = tmpline;
2339 current = tmpline;
2340 slen -= i + 1;
2341 current_y++;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002342 } while ((strlenpt(current->data) > (fill))
2343 && !no_spaces(current->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002344 }
Chris Allegretta9149e612000-11-27 00:23:41 +00002345 tmpbot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002346
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002347 if (current->next)
2348 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00002349 else
2350 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002351 current_x = 0;
2352 placewewant = 0;
2353
Adam Rogoyski09f97962000-06-20 02:50:33 +00002354 renumber(initial);
2355 totlines = filebot->lineno;
2356
2357 werase(edit);
2358
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002359 if ((current_y < 0) || (current_y >= editwinrows - 1)
2360 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00002361 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002362 center_cursor();
2363 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00002364 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002365 }
2366
Adam Rogoyski09f97962000-06-20 02:50:33 +00002367 edit_refresh();
Chris Allegretta9149e612000-11-27 00:23:41 +00002368 statusbar(_("Can now UnJustify!"));
Chris Allegretta07798352000-11-27 22:58:23 +00002369 /* Change the shortcut list to display the unjustify code */
2370 shortcut_init(1);
2371 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002372 reset_cursor();
2373
Chris Allegretta88520c92001-05-05 17:45:54 +00002374 /* Now get a keystroke and see if it's unjustify; if not, unget the keystroke
Chris Allegretta9149e612000-11-27 00:23:41 +00002375 and return */
Chris Allegretta5f071802001-05-06 02:34:31 +00002376
2377#ifndef DISABLE_MOUSE
2378#ifdef NCURSES_MOUSE_VERSION
2379
2380 /* If it was a mouse click, parse it with do_mouse and it might become
2381 the unjustify key. Else give it back to the input stream. */
2382 if ((kbinput = wgetch(edit)) == KEY_MOUSE)
2383 do_mouse();
2384 else
2385 ungetch(kbinput);
2386#endif
2387#endif
2388
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002389 if ((kbinput = wgetch(edit)) != NANO_UNJUSTIFY_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002390 ungetch(kbinput);
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002391 blank_statusbar_refresh();
2392 } else {
Chris Allegretta9149e612000-11-27 00:23:41 +00002393 /* Else restore the justify we just did (ungrateful user!) */
2394 if (tmptop->prev != NULL)
2395 tmptop->prev->next = tmpbot->next;
Chris Allegrettad022eac2000-11-27 02:50:49 +00002396 else
2397 fileage = current;
Chris Allegretta9149e612000-11-27 00:23:41 +00002398 tmpbot->next->prev = tmptop->prev;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002399 current = tmpbot->next;
Chris Allegretta9149e612000-11-27 00:23:41 +00002400 tmpbot->next = NULL;
2401 do_uncut_text();
Chris Allegrettad022eac2000-11-27 02:50:49 +00002402 if (tmptop->prev == NULL)
2403 edit_refresh();
2404
Chris Allegretta88520c92001-05-05 17:45:54 +00002405 /* Restore totsize from before justify */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002406 totsize = totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002407 free_filestruct(tmptop);
2408 blank_statusbar_refresh();
2409 }
Chris Allegretta4a9c8582000-11-27 22:59:40 +00002410 shortcut_init(0);
2411 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002412 free_filestruct(cutbuffer);
2413 cutbuffer = cutbak;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002414
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002415 return 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002416#endif
2417}
2418
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002419#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002420void help_init(void)
2421{
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002422 int i, sofar = 0, meta_shortcut = 0, helplen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002423 long allocsize = 1; /* How much space we're gonna need for the help text */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002424 char buf[BUFSIZ] = "", *ptr = NULL;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002425 toggle *t;
2426 shortcut *s;
Chris Allegrettab3655b42001-10-22 03:15:31 +00002427
Chris Allegretta7e65d2f2002-02-15 21:12:52 +00002428 helplen = length_of_list(currshortcut);
Chris Allegretta13fd44b2002-01-02 13:59:11 +00002429
Chris Allegrettab3655b42001-10-22 03:15:31 +00002430 /* First set up the initial help text for the current function */
2431 if (currshortcut == whereis_list || currshortcut == replace_list
2432 || currshortcut == replace_list_2)
2433 ptr = _("Search Command Help Text\n\n "
2434 "Enter the words or characters you would like to search "
2435 "for, then hit enter. If there is a match for the text you "
2436 "entered, the screen will be updated to the location of the "
Jordi Mallach773623c2001-10-28 21:00:49 +00002437 "nearest match for the search string.\n\n "
2438 "If using Pico Mode via the -p or --pico flags, using the "
2439 "Meta-P toggle or using a nanorc file, the previous search "
2440 "string will be shown in brackets after the Search: prompt. "
Jordi Mallachf4e57292001-12-26 00:16:40 +00002441 "Hitting enter without entering any text will perform the "
Jordi Mallach773623c2001-10-28 21:00:49 +00002442 "previous search. Otherwise, the previous string will be "
2443 "placed in front of the cursor, and can be edited or deleted "
2444 "before hitting enter.\n\n The following functions keys are "
2445 "available in Search mode:\n\n");
Chris Allegrettab3655b42001-10-22 03:15:31 +00002446 else if (currshortcut == goto_list)
2447 ptr = _("Goto Line Help Text\n\n "
2448 "Enter the line number that you wish to go to and hit "
Jordi Mallach773623c2001-10-28 21:00:49 +00002449 "Enter. If there are fewer lines of text than the "
Chris Allegrettab3655b42001-10-22 03:15:31 +00002450 "number you entered, you will be brought to the last line "
2451 "of the file.\n\n The following functions keys are "
2452 "available in Goto Line mode:\n\n");
2453 else if (currshortcut == insertfile_list)
2454 ptr = _("Insert File Help Text\n\n "
2455 "Type in the name of a file to be inserted into the current "
2456 "file buffer at the current cursor location.\n\n "
2457 "If you have compiled nano with multiple file buffer "
2458 "support, and enable multiple buffers with the -F "
Jordi Mallach773623c2001-10-28 21:00:49 +00002459 "or --multibuffer command line flags, the Meta-F toggle or "
2460 "using a nanorc file, inserting a file will cause it to be "
Chris Allegretta180a5692002-01-02 14:30:33 +00002461 "loaded into a separate buffer (use Meta-< and > to switch "
Chris Allegretta48b06702002-02-22 04:30:50 +00002462 "between file buffers).\n\n If you need another blank "
Chris Allegrettab479c892002-03-09 20:03:10 +00002463 "buffer, do not enter any filename, or type in a "
2464 "nonexistent filename at the prompt and press "
2465 "Enter.\n\n The following function keys are "
Chris Allegretta48b06702002-02-22 04:30:50 +00002466 "available in Insert File mode:\n\n");
Chris Allegrettab3655b42001-10-22 03:15:31 +00002467 else if (currshortcut == writefile_list)
2468 ptr = _("Write File Help Text\n\n "
2469 "Type the name that you wish to save the current file "
2470 "as and hit enter to save the file.\n\n "
2471 "If you are using the marker code with Ctrl-^ and have "
2472 "selected text, you will be prompted to save only the "
2473 "selected portion to a separate file. To reduce the "
2474 "chance of overwriting the current file with just a portion "
2475 "of it, the current filename is not the default in this "
2476 "mode.\n\n The following function keys are available in "
2477 "Write File mode:\n\n");
2478#ifndef DISABLE_BROWSER
2479 else if (currshortcut == browser_list)
2480 ptr = _("File Browser Help Text\n\n "
2481 "The file browser is used to visually browse the "
2482 "directory structure to select a file for reading "
2483 "or writing. You may use the arrow keys or Page Up/"
2484 "Down to browse through the files, and S or Enter to "
2485 "choose the selected file or enter the selected "
2486 "directory. To move up one level, select the directory "
2487 "called \"..\" at the top of the file list.\n\n The "
2488 "following functions keys are available in the file "
2489 "browser:\n\n");
2490 else if (currshortcut == gotodir_list)
2491 ptr = _("Browser Goto Directory Help Text\n\n "
2492 "Enter the name of the directory you would like to "
2493 "browse to.\n\n If tab completion has not been disabled, "
2494 "you can use the TAB key to (attempt to) automatically "
Chris Allegretta1f8394d2002-03-09 19:58:18 +00002495 "complete the directory name.\n\n The following function "
Chris Allegrettab3655b42001-10-22 03:15:31 +00002496 "keys are available in Browser GotoDir mode:\n\n");
2497#endif
2498 else if (currshortcut == spell_list)
2499 ptr = _("Spell Check Help Text\n\n "
2500 "The spell checker checks the spelling of all text "
2501 "in the current file. When an unknown word is "
2502 "encountered, it is highlighted and a replacement can "
2503 "be edited. It will then prompt to replace every "
2504 "instance of the given misspelled word in the "
2505 "current file.\n\n The following other functions are "
2506 "available in Spell Check mode:\n\n");
Chris Allegretta52c5a6e2002-03-21 05:07:28 +00002507#ifndef NANO_SMALL
2508 else if (currshortcut == extcmd_list)
2509 ptr = _("External Command Help Text\n\n "
2510 "This menu allows you to insert the output of a command "
2511 "run by the shell into the current buffer (or a new "
2512 "buffer in multibuffer mode).\n\n The following keys are "
2513 "available in this mode:\n\n");
2514#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00002515 else /* Default to the main help list */
2516 ptr = help_text_init;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002517
2518 /* Compute the space needed for the shortcut lists - we add 15 to
2519 have room for the shortcut abbrev and its possible alternate keys */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002520 s = currshortcut;
2521 for (i = 0; i <= helplen - 1; i++) {
2522 if (s->help != NULL)
2523 allocsize += strlen(s->help) + 15;
2524 s = s->next;
2525 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002526
Chris Allegrettab3655b42001-10-22 03:15:31 +00002527 /* If we're on the main list, we also allocate space for toggle help text. */
2528 if (currshortcut == main_list) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002529 for (t = toggles; t != NULL; t = t->next)
2530 if (t->desc != NULL)
2531 allocsize += strlen(t->desc) + 30;
Chris Allegrettab3655b42001-10-22 03:15:31 +00002532 }
2533
2534 allocsize += strlen(ptr);
2535
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002536 if (help_text != NULL)
2537 free(help_text);
2538
2539 /* Allocate space for the help text */
Chris Allegretta88b09152001-05-17 11:35:43 +00002540 help_text = charalloc(allocsize);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002541
2542 /* Now add the text we want */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002543 strcpy(help_text, ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002544
2545 /* Now add our shortcut info */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002546 s = currshortcut;
Chris Allegretta13fd44b2002-01-02 13:59:11 +00002547 for (i = 0; i <= helplen - 1; i++) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002548 if (s->val > 0 && s->val < 'a')
2549 sofar = snprintf(buf, BUFSIZ, "^%c ", s->val + 64);
2550 else {
2551 if (s->altval > 0) {
2552 sofar = 0;
2553 meta_shortcut = 1;
2554 }
2555 else
2556 sofar = snprintf(buf, BUFSIZ, " ");
2557 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002558
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002559 if (!meta_shortcut) {
2560 if (s->misc1 > KEY_F0 && s->misc1 <= KEY_F(64))
2561 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
2562 s->misc1 - KEY_F0);
2563 else
2564 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
2565 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002566
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002567 if (s->altval > 0 && s->altval < 91
2568 && (s->altval - 32) > 32)
2569 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2570 (meta_shortcut ? "M-%c " : "(M-%c) "),
2571 s->altval - 32);
Chris Allegretta5902f962002-03-07 12:40:39 +00002572 else if (s->altval >= 'a')
2573 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2574 (meta_shortcut ? "M-%c " : "(M-%c) "),
2575 s->altval - 32);
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002576 else if (s->altval > 0)
2577 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2578 (meta_shortcut ? "M-%c " : "(M-%c) "),
2579 s->altval);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002580 /* Hack */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002581 else if (s->val >= 'a')
2582 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2583 (meta_shortcut ? "(M-%c) " : "M-%c "),
2584 s->val - 32);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002585 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002586 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002587
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002588 if (meta_shortcut) {
2589 if (s->misc1 > KEY_F0 && s->misc1 <= KEY_F(64))
2590 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2591 "(F%d) ", s->misc1 - KEY_F0);
2592 else
2593 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2594 " ");
2595 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002596
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002597 if (s->help != NULL)
2598 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", s->help);
Chris Allegretta756f2202000-09-01 13:32:47 +00002599
2600 strcat(help_text, buf);
2601 strcat(help_text, "\n");
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002602
2603 s = s->next;
Chris Allegretta756f2202000-09-01 13:32:47 +00002604 }
2605
2606 /* And the toggles... */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002607 if (currshortcut == main_list)
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002608 for (t = toggles; t != NULL; t = t->next) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00002609 sofar = snprintf(buf, BUFSIZ,
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002610 "M-%c ", t->val - 32);
2611 if (t->desc != NULL) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00002612 snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002613 t->desc);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002614 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002615 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00002616 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002617 }
2618
2619}
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002620#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002621
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002622void do_toggle(toggle *which)
Chris Allegretta756f2202000-09-01 13:32:47 +00002623{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002624#ifdef NANO_SMALL
2625 nano_disabled_msg();
2626#else
Jordi Mallach2dc0f6b2000-09-07 10:48:00 +00002627 char *enabled = _("enabled");
2628 char *disabled = _("disabled");
Chris Allegrettaf0f63a82000-09-02 18:44:21 +00002629
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002630 switch (which->val) {
Chris Allegretta8d990b52001-09-22 22:14:25 +00002631 case TOGGLE_BACKWARDS_KEY:
2632 case TOGGLE_CASE_KEY:
2633 case TOGGLE_REGEXP_KEY:
2634 return;
2635 }
Chris Allegretta8d990b52001-09-22 22:14:25 +00002636
Chris Allegretta658399a2001-06-14 02:54:22 +00002637 /* Even easier! */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002638 TOGGLE(which->flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002639
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002640 switch (which->val) {
Chris Allegretta756f2202000-09-01 13:32:47 +00002641 case TOGGLE_PICOMODE_KEY:
Chris Allegretta07798352000-11-27 22:58:23 +00002642 shortcut_init(0);
Chris Allegrettac1049ac2001-08-17 00:03:46 +00002643 SET(CLEAR_BACKUPSTRING);
Chris Allegretta756f2202000-09-01 13:32:47 +00002644 display_main_list();
2645 break;
2646 case TOGGLE_SUSPEND_KEY:
2647 signal_init();
2648 break;
2649 case TOGGLE_MOUSE_KEY:
2650 mouse_init();
2651 break;
2652 case TOGGLE_NOHELP_KEY:
Chris Allegretta2a42af12000-09-12 23:02:49 +00002653 wclear(bottomwin);
2654 wrefresh(bottomwin);
2655 window_init();
Chris Allegrettaaffeda82000-12-18 04:03:48 +00002656 fix_editbot();
Chris Allegretta2a42af12000-09-12 23:02:49 +00002657 edit_refresh();
2658 display_main_list();
Chris Allegretta756f2202000-09-01 13:32:47 +00002659 break;
Chris Allegretta99e30e12001-09-23 02:45:27 +00002660 case TOGGLE_DOS_KEY:
2661 UNSET(MAC_FILE);
2662 break;
2663 case TOGGLE_MAC_KEY:
2664 UNSET(DOS_FILE);
2665 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002666 }
Chris Allegretta2a42af12000-09-12 23:02:49 +00002667
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002668 if (!ISSET(which->flag)) {
2669 if (which->val == TOGGLE_NOHELP_KEY ||
2670 which->val == TOGGLE_WRAP_KEY)
2671 statusbar("%s %s", which->desc, enabled);
Chris Allegretta819e3db2001-07-11 02:37:19 +00002672 else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002673 statusbar("%s %s", which->desc, disabled);
Chris Allegretta819e3db2001-07-11 02:37:19 +00002674 } else {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002675 if (which->val == TOGGLE_NOHELP_KEY ||
2676 which->val == TOGGLE_WRAP_KEY)
2677 statusbar("%s %s", which->desc, disabled);
Chris Allegretta819e3db2001-07-11 02:37:19 +00002678 else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002679 statusbar("%s %s", which->desc, enabled);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002680 }
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002681
Chris Allegretta756f2202000-09-01 13:32:47 +00002682#endif
2683}
2684
Chris Allegretta88520c92001-05-05 17:45:54 +00002685/* If the NumLock key has made the keypad go awry, print an error
2686 message; hopefully we can address it later. */
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002687void print_numlock_warning(void)
2688{
2689 static int didmsg = 0;
2690 if (!didmsg) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002691 statusbar(_
2692 ("NumLock glitch detected. Keypad will malfunction with NumLock off"));
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002693 didmsg = 1;
2694 }
2695}
2696
Chris Allegretta1748cd12001-01-13 17:22:54 +00002697/* This function returns the correct keystroke, given the A,B,C or D
2698 input key. This is a common sequence of many terms which send
2699 Esc-O-[A-D] or Esc-[-[A-D]. */
2700int ABCD(int input)
2701{
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002702 switch (input) {
2703 case 'A':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002704 case 'a':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002705 return (KEY_UP);
2706 case 'B':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002707 case 'b':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002708 return (KEY_DOWN);
2709 case 'C':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002710 case 'c':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002711 return (KEY_RIGHT);
2712 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002713 case 'd':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002714 return (KEY_LEFT);
2715 default:
2716 return 0;
Chris Allegretta1748cd12001-01-13 17:22:54 +00002717 }
2718}
2719
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002720int main(int argc, char *argv[])
2721{
2722 int optchr;
2723 int kbinput; /* Input from keyboard */
2724 long startline = 0; /* Line to try and start at */
Chris Allegretta08020882001-01-29 23:37:54 +00002725 int keyhandled; /* Have we handled the keystroke yet? */
Chris Allegretta9caa1932002-02-15 20:08:05 +00002726 int modify_control_seq;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002727 char *argv0;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002728 shortcut *s;
Chris Allegretta40ecbad2002-03-06 15:27:44 +00002729#ifndef NANO_SMALL
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002730 toggle *t;
Chris Allegretta40ecbad2002-03-06 15:27:44 +00002731#endif
Chris Allegretta0357c4d2001-09-19 02:59:25 +00002732
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002733#ifdef _POSIX_VDISABLE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002734 struct termios term;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002735#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002736
2737#ifdef HAVE_GETOPT_LONG
2738 int option_index = 0;
2739 struct option long_options[] = {
Chris Allegretta805c26d2000-09-06 13:39:17 +00002740#ifdef HAVE_REGEX_H
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002741 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00002742#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002743 {"version", 0, 0, 'V'},
2744 {"const", 0, 0, 'c'},
2745 {"suspend", 0, 0, 'z'},
2746 {"nowrap", 0, 0, 'w'},
2747 {"nohelp", 0, 0, 'x'},
2748 {"help", 0, 0, 'h'},
Chris Allegretta7492cec2000-12-18 04:55:21 +00002749 {"view", 0, 0, 'v'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002750#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002751 {"cut", 0, 0, 'k'},
Chris Allegretta7004c282001-09-22 00:42:10 +00002752 {"dos", 0, 0, 'D'},
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002753 {"mac", 0, 0, 'M'},
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002754 {"noconvert", 0, 0, 'N'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002755 {"autoindent", 0, 0, 'i'},
Chris Allegrettaff989832001-09-17 13:48:00 +00002756#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002757 {"tempfile", 0, 0, 't'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002758#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002759 {"speller", 1, 0, 's'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002760#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00002761
2762#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002763 {"fill", 1, 0, 'r'},
Chris Allegretta6fe61492001-05-21 12:56:25 +00002764#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002765 {"mouse", 0, 0, 'm'},
Chris Allegrettae1f14522001-09-19 03:19:43 +00002766#ifndef DISABLE_OPERATINGDIR
2767 {"operatingdir", 1, 0, 'o'},
2768#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002769 {"pico", 0, 0, 'p'},
2770 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00002771 {"tabsize", 1, 0, 'T'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002772
Chris Allegretta355fbe52001-07-14 19:32:47 +00002773#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002774 {"multibuffer", 0, 0, 'F'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002775#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002776#ifndef NANO_SMALL
2777 {"smooth", 0, 0, 'S'},
2778#endif
Chris Allegretta48bd3782002-01-03 21:26:34 +00002779 {"keypad", 0, 0, 'K'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002780 {0, 0, 0, 0}
2781 };
2782#endif
2783
2784 /* Flag inits... */
2785 SET(FOLLOW_SYMLINKS);
2786
2787#ifndef NANO_SMALL
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002788#ifdef ENABLE_NLS
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002789 setlocale(LC_ALL, "");
2790 bindtextdomain(PACKAGE, LOCALEDIR);
2791 textdomain(PACKAGE);
2792#endif
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002793#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002794
Chris Allegretta8d8e0122001-04-18 04:28:54 +00002795#ifdef ENABLE_NANORC
2796 do_rcfile();
2797#endif /* ENABLE_NANORC */
2798
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002799#ifdef HAVE_GETOPT_LONG
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002800 while ((optchr = getopt_long(argc, argv, "h?DFKMNQ:RST:Vabcefgijklmo:pr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002801 long_options, &option_index)) != EOF) {
2802#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002803 while ((optchr =
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002804 getopt(argc, argv, "h?DFKMNQ:RST:Vabcefgijklmo:pr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002805#endif
2806
2807 switch (optchr) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002808
Chris Allegretta7004c282001-09-22 00:42:10 +00002809#ifndef NANO_SMALL
2810 case 'D':
2811 SET(DOS_FILE);
2812 break;
2813#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +00002814#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002815 case 'F':
Chris Allegretta355fbe52001-07-14 19:32:47 +00002816 SET(MULTIBUFFER);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002817 break;
2818#endif
Chris Allegretta48bd3782002-01-03 21:26:34 +00002819 case 'K':
2820 SET(ALT_KEYPAD);
2821 break;
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002822#ifndef NANO_SMALL
2823 case 'M':
2824 SET(MAC_FILE);
2825 break;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002826 case 'N':
2827 SET(NO_CONVERT);
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002828 break;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002829#endif
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002830 case 'Q':
2831#ifndef DISABLE_JUSTIFY
2832 quotestr = optarg;
2833 break;
2834#else
2835 usage(); /* To stop bogus data for tab width */
2836 finish(1);
2837#endif
Chris Allegretta805c26d2000-09-06 13:39:17 +00002838#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +00002839 case 'R':
2840 SET(USE_REGEXP);
2841 break;
Chris Allegretta47805612000-07-07 02:35:34 +00002842#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002843#ifndef NANO_SMALL
2844 case 'S':
2845 SET(SMOOTHSCROLL);
2846 break;
2847#endif
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002848 case 'T':
2849 tabsize = atoi(optarg);
2850 if (tabsize <= 0) {
2851 usage(); /* To stop bogus data for tab width */
2852 finish(1);
2853 }
2854 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002855 case 'V':
2856 version();
2857 exit(0);
Chris Allegrettae1f14522001-09-19 03:19:43 +00002858 case 'a':
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002859 case 'b':
2860 case 'e':
2861 case 'f':
Rocco Corsi12f294c2001-04-14 06:50:24 +00002862 case 'g':
2863 case 'j':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002864 /* Pico compatibility flags */
2865 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002866 case 'c':
2867 SET(CONSTUPDATE);
2868 break;
2869 case 'h':
2870 case '?':
2871 usage();
2872 exit(0);
Chris Allegrettaff989832001-09-17 13:48:00 +00002873#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002874 case 'i':
2875 SET(AUTOINDENT);
2876 break;
Chris Allegretta627de192000-07-12 02:09:17 +00002877 case 'k':
2878 SET(CUT_TO_END);
2879 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002880#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002881 case 'l':
2882 UNSET(FOLLOW_SYMLINKS);
2883 break;
2884 case 'm':
2885 SET(USE_MOUSE);
2886 break;
Chris Allegrettae1f14522001-09-19 03:19:43 +00002887#ifndef DISABLE_OPERATINGDIR
2888 case 'o':
2889 operating_dir = charalloc(strlen(optarg) + 1);
2890 strcpy(operating_dir, optarg);
2891
2892 /* make sure we're inside the operating directory */
2893 if (check_operating_dir(".", 0)) {
2894 if (chdir(operating_dir) == -1) {
2895 free(operating_dir);
2896 operating_dir = NULL;
2897 }
2898 }
2899 break;
2900#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002901 case 'p':
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002902 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002903 break;
2904 case 'r':
Chris Allegretta6fe61492001-05-21 12:56:25 +00002905#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002906 fill = atoi(optarg);
Chris Allegretta6fe61492001-05-21 12:56:25 +00002907 if (fill < 0)
2908 wrap_at = fill;
2909 else if (fill == 0) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002910 usage(); /* To stop bogus data (like a string) */
2911 finish(1);
2912 }
2913 break;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002914#else
2915 usage();
2916 exit(0);
2917
2918#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002919#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002920 case 's':
Chris Allegretta88b09152001-05-17 11:35:43 +00002921 alt_speller = charalloc(strlen(optarg) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002922 strcpy(alt_speller, optarg);
2923 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002924#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002925 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00002926 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002927 break;
2928 case 'v':
2929 SET(VIEW_MODE);
2930 break;
2931 case 'w':
Chris Allegrettacef7fbb2001-04-02 05:36:08 +00002932#ifdef DISABLE_WRAPPING
2933 usage();
2934 exit(0);
2935#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002936 SET(NO_WRAP);
2937 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002938#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002939 case 'x':
2940 SET(NO_HELP);
2941 break;
2942 case 'z':
2943 SET(SUSPEND);
2944 break;
2945 default:
2946 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002947 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002948 }
2949
2950 }
2951
2952 argv0 = strrchr(argv[0], '/');
2953 if ((argv0 && strstr(argv0, "pico"))
2954 || (!argv0 && strstr(argv[0], "pico")))
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002955 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002956
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002957 /* See if there's a non-option in argv (first non-option is the
2958 filename, if +LINE is not given) */
2959 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002960 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002961 else {
2962 /* Look for the +line flag... */
2963 if (argv[optind][0] == '+') {
2964 startline = atoi(&argv[optind][1]);
2965 optind++;
2966 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002967 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002968 else
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002969 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002970
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002971 } else
2972 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002973 }
2974
2975
2976 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002977 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002978
Chris Allegretta9239d742000-09-06 15:19:18 +00002979#ifdef _POSIX_VDISABLE
Chris Allegretta8f6c0692000-07-19 01:16:18 +00002980 term = oldterm;
2981 term.c_cc[VINTR] = _POSIX_VDISABLE;
2982 term.c_cc[VQUIT] = _POSIX_VDISABLE;
2983 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002984 tcsetattr(0, TCSANOW, &term);
Chris Allegretta9239d742000-09-06 15:19:18 +00002985#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002986
2987 /* now ncurses init stuff... */
2988 initscr();
2989 savetty();
2990 nonl();
2991 cbreak();
2992 noecho();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002993
2994 /* Set up some global variables */
Chris Allegretta56214c62001-09-27 02:46:53 +00002995 global_init(0);
Chris Allegretta07798352000-11-27 22:58:23 +00002996 shortcut_init(0);
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002997#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002998 init_help_msg();
2999 help_init();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00003000#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00003001 signal_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003002
3003#ifdef DEBUG
3004 fprintf(stderr, _("Main: set up windows\n"));
3005#endif
3006
Chris Allegretta2a42af12000-09-12 23:02:49 +00003007 window_init();
Chris Allegretta756f2202000-09-01 13:32:47 +00003008 mouse_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003009
Chris Allegretta48bd3782002-01-03 21:26:34 +00003010 if (!ISSET(ALT_KEYPAD)) {
3011 keypad(edit, TRUE);
3012 keypad(bottomwin, TRUE);
3013 }
3014
Chris Allegretta08893e02001-11-29 02:42:27 +00003015#ifdef ENABLE_COLOR
3016 do_colorinit();
3017
Chris Allegretta08893e02001-11-29 02:42:27 +00003018#endif /* ENABLE_COLOR */
3019
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003020#ifdef DEBUG
3021 fprintf(stderr, _("Main: bottom win\n"));
3022#endif
Chris Allegretta88520c92001-05-05 17:45:54 +00003023 /* Set up bottom of window */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003024 display_main_list();
3025
3026#ifdef DEBUG
3027 fprintf(stderr, _("Main: open file\n"));
3028#endif
3029
Chris Allegrettaf4b96012001-01-03 07:11:47 +00003030 titlebar(NULL);
Chris Allegretta31c76662000-11-21 06:20:20 +00003031
3032 /* Now we check to see if argv[optind] is non-null to determine if
3033 we're dealing with a new file or not, not argc == 1... */
3034 if (argv[optind] == NULL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003035 new_file();
3036 else
3037 open_file(filename, 0, 0);
3038
3039 if (startline > 0)
Chris Allegretta2d7893d2001-07-11 02:08:33 +00003040 do_gotoline(startline, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003041 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00003042 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003043
Chris Allegretta08020882001-01-29 23:37:54 +00003044 /* return here after a sigwinch */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003045 sigsetjmp(jmpbuf, 1);
Chris Allegretta08020882001-01-29 23:37:54 +00003046
3047 /* Fix clobber-age */
3048 kbinput = 0;
3049 keyhandled = 0;
3050 modify_control_seq = 0;
3051
Robert Siemborski6967eec2000-07-08 14:23:32 +00003052 edit_refresh();
3053 reset_cursor();
3054
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003055 while (1) {
Chris Allegretta9239d742000-09-06 15:19:18 +00003056
Chris Allegretta6fe61492001-05-21 12:56:25 +00003057#ifndef DISABLE_MOUSE
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003058 currshortcut = main_list;
Chris Allegretta6fe61492001-05-21 12:56:25 +00003059#endif
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003060
Chris Allegretta9239d742000-09-06 15:19:18 +00003061#ifndef _POSIX_VDISABLE
3062 /* We're going to have to do it the old way, i.e. on cygwin */
3063 raw();
3064#endif
3065
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003066 kbinput = wgetch(edit);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003067#ifdef DEBUG
3068 fprintf(stderr, "AHA! %c (%d)\n", kbinput, kbinput);
3069#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003070
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003071 if (kbinput == 27) { /* Grab Alt-key stuff first */
3072 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003073 /* Alt-O, suddenly very important ;) */
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003074 case 'O':
Chris Allegretta16e41682000-09-11 22:33:54 +00003075 kbinput = wgetch(edit);
Chris Allegretta316e4d92001-04-28 16:31:19 +00003076 if ((kbinput <= 'D' && kbinput >= 'A') ||
3077 (kbinput <= 'd' && kbinput >= 'a'))
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003078 kbinput = ABCD(kbinput);
Chris Allegretta201d9bf2001-01-14 03:17:53 +00003079 else if (kbinput <= 'z' && kbinput >= 'j')
3080 print_numlock_warning();
3081 else if (kbinput <= 'S' && kbinput >= 'P')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003082 kbinput = KEY_F(kbinput - 79);
Chris Allegretta16e41682000-09-11 22:33:54 +00003083#ifdef DEBUG
3084 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003085 fprintf(stderr, _("I got Alt-O-%c! (%d)\n"),
3086 kbinput, kbinput);
3087 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003088 }
3089#endif
3090 break;
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003091 case 27:
3092 /* If we get Alt-Alt, the next keystroke should be the same as a
3093 control sequence */
3094 modify_control_seq = 1;
3095 keyhandled = 1;
3096 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00003097#ifndef NANO_SMALL
Chris Allegretta76e291b2001-10-14 19:05:10 +00003098 case ' ':
3099 /* If control-space is next word, Alt-space should be previous word */
3100 do_prev_word();
3101 keyhandled = 1;
3102 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00003103#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003104 case '[':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003105 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003106 case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */
Chris Allegretta16e41682000-09-11 22:33:54 +00003107 kbinput = wgetch(edit);
3108 if (kbinput >= '1' && kbinput <= '5') {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003109 kbinput = KEY_F(kbinput - 48);
3110 wgetch(edit);
3111 } else if (kbinput >= '7' && kbinput <= '9') {
3112 kbinput = KEY_F(kbinput - 49);
3113 wgetch(edit);
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003114 } else if (kbinput == '~')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003115 kbinput = KEY_HOME;
Chris Allegretta16e41682000-09-11 22:33:54 +00003116
3117#ifdef DEBUG
3118 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003119 fprintf(stderr, _("I got Alt-[-1-%c! (%d)\n"),
3120 kbinput, kbinput);
3121 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003122 }
3123#endif
3124
3125 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003126 case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */
Chris Allegretta16e41682000-09-11 22:33:54 +00003127 kbinput = wgetch(edit);
Chris Allegretta16e41682000-09-11 22:33:54 +00003128 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003129 case '0':
3130 kbinput = KEY_F(9);
3131 wgetch(edit);
3132 break;
3133 case '1':
3134 kbinput = KEY_F(10);
3135 wgetch(edit);
3136 break;
3137 case '3':
3138 kbinput = KEY_F(11);
3139 wgetch(edit);
3140 break;
3141 case '4':
3142 kbinput = KEY_F(12);
3143 wgetch(edit);
3144 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003145 case '~':
3146 goto do_insertkey;
Chris Allegretta16e41682000-09-11 22:33:54 +00003147#ifdef DEBUG
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003148 default:
3149 fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"),
3150 kbinput, kbinput);
3151 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003152#endif
3153
3154 }
3155 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003156 case '3': /* Alt-[-3 = Delete? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003157 kbinput = NANO_DELETE_KEY;
3158 wgetch(edit);
3159 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003160 case '4': /* Alt-[-4 = End? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003161 kbinput = NANO_END_KEY;
3162 wgetch(edit);
3163 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003164 case '5': /* Alt-[-5 = Page Up */
Chris Allegretta16e41682000-09-11 22:33:54 +00003165 kbinput = KEY_PPAGE;
3166 wgetch(edit);
3167 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003168 case 'V': /* Alt-[-V = Page Up in Hurd Console */
Chris Allegretta7bf72742001-10-28 04:29:55 +00003169 case 'I': /* Alt-[-I = Page Up - FreeBSD Console */
3170 kbinput = KEY_PPAGE;
3171 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003172 case '6': /* Alt-[-6 = Page Down */
Chris Allegretta16e41682000-09-11 22:33:54 +00003173 kbinput = KEY_NPAGE;
3174 wgetch(edit);
3175 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003176 case 'U': /* Alt-[-U = Page Down in Hurd Console */
Chris Allegretta7bf72742001-10-28 04:29:55 +00003177 case 'G': /* Alt-[-G = Page Down - FreeBSD Console */
3178 kbinput = KEY_NPAGE;
3179 break;
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003180 case '7':
3181 kbinput = KEY_HOME;
3182 wgetch(edit);
3183 break;
3184 case '8':
3185 kbinput = KEY_END;
3186 wgetch(edit);
3187 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003188 case '9': /* Alt-[-9 = Delete in Hurd Console */
3189 kbinput = KEY_DC;
3190 break;
Chris Allegretta32da4562002-01-02 15:12:21 +00003191 case '@': /* Alt-[-@ = Insert in Hurd Console */
3192 case 'L': /* Alt-[-L = Insert - FreeBSD Console */
3193 goto do_insertkey;
3194 case '[': /* Alt-[-[-[A-E], F1-F5 in Linux console */
Chris Allegretta16e41682000-09-11 22:33:54 +00003195 kbinput = wgetch(edit);
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003196 if (kbinput >= 'A' && kbinput <= 'E')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003197 kbinput = KEY_F(kbinput - 64);
Chris Allegretta16e41682000-09-11 22:33:54 +00003198 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003199 case 'A':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003200 case 'B':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003201 case 'C':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003202 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00003203 case 'a':
3204 case 'b':
3205 case 'c':
3206 case 'd':
Chris Allegretta1748cd12001-01-13 17:22:54 +00003207 kbinput = ABCD(kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003208 break;
3209 case 'H':
3210 kbinput = KEY_HOME;
3211 break;
3212 case 'F':
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003213 case 'Y': /* End Key in Hurd Console */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003214 kbinput = KEY_END;
3215 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003216 default:
3217#ifdef DEBUG
3218 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
3219 kbinput, kbinput);
3220#endif
3221 break;
3222 }
3223 break;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003224
Chris Allegretta355fbe52001-07-14 19:32:47 +00003225#ifdef ENABLE_MULTIBUFFER
Chris Allegretta819e3db2001-07-11 02:37:19 +00003226 case NANO_OPENPREV_KEY:
Chris Allegretta180a5692002-01-02 14:30:33 +00003227 case NANO_OPENPREV_ALTKEY:
Chris Allegretta819e3db2001-07-11 02:37:19 +00003228 open_prevfile(0);
3229 keyhandled = 1;
3230 break;
3231 case NANO_OPENNEXT_KEY:
Chris Allegretta180a5692002-01-02 14:30:33 +00003232 case NANO_OPENNEXT_ALTKEY:
Chris Allegretta819e3db2001-07-11 02:37:19 +00003233 open_nextfile(0);
3234 keyhandled = 1;
3235 break;
Chris Allegretta9cf9e062001-07-11 12:06:13 +00003236#endif
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003237
3238#if !defined (NANO_SMALL) && defined (HAVE_REGEX_H)
3239 case NANO_BRACKET_KEY:
3240 do_find_bracket();
3241 keyhandled = 1;
3242 break;
3243#endif
3244
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003245 default:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003246 /* Check for the altkey defs.... */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003247 for (s = main_list; s != NULL; s = s->next)
3248 if (kbinput == s->altval ||
3249 kbinput == s->altval - 32) {
3250 kbinput = s->val;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003251 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003252 }
Chris Allegretta756f2202000-09-01 13:32:47 +00003253#ifndef NANO_SMALL
3254 /* And for toggle switches */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003255 for (t = toggles; t != NULL && !keyhandled; t = t->next)
3256 if (kbinput == t->val ||
3257 (t->val > 'a' &&
3258 kbinput == t->val - 32)) {
3259 do_toggle(t);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003260 keyhandled = 1;
3261 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00003262 }
3263#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003264#ifdef DEBUG
3265 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
3266 kbinput);
3267#endif
3268 break;
3269 }
3270 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003271 /* If the modify_control_seq is set, we received an Alt-Alt
3272 sequence before this, so we make this key a control sequence
3273 by subtracting 64 or 96, depending on its value. */
3274 if (!keyhandled && modify_control_seq) {
3275 if (kbinput >= 'A' && kbinput < 'a')
3276 kbinput -= 64;
3277 else if (kbinput >= 'a' && kbinput <= 'z')
3278 kbinput -= 96;
3279
3280 modify_control_seq = 0;
3281 }
3282
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003283 /* Look through the main shortcut list to see if we've hit a
3284 shortcut key */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003285
Chris Allegrettaf5de33a2002-02-27 04:14:16 +00003286#if !defined(DISABLE_BROWSER) || !defined(DISABLE_MOUSE) || !defined (DISABLE_HELP)
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003287 for (s = currshortcut; s != NULL && !keyhandled; s = s->next) {
Chris Allegrettaf5de33a2002-02-27 04:14:16 +00003288#else
3289 for (s = main_list; s != NULL && !keyhandled; s = s->next) {
3290#endif
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003291 if (kbinput == s->val ||
3292 (s->misc1 && kbinput == s->misc1) ||
3293 (s->misc2 && kbinput == s->misc2)) {
3294 if (ISSET(VIEW_MODE) && !s->viewok)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003295 print_view_warning();
3296 else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003297 s->func();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003298 keyhandled = 1;
3299 }
3300 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003301 /* If we're in raw mode or using Alt-Alt-x, we have to catch
3302 Control-S and Control-Q */
Chris Allegretta9239d742000-09-06 15:19:18 +00003303 if (kbinput == 17 || kbinput == 19)
3304 keyhandled = 1;
3305
Chris Allegretta9caa1932002-02-15 20:08:05 +00003306 /* Catch ^Z by hand when triggered also
3307 407 == ^Z in Linux console when keypad() is used? */
3308 if (kbinput == 26 || kbinput == 407) {
Chris Allegretta9239d742000-09-06 15:19:18 +00003309 if (ISSET(SUSPEND))
3310 do_suspend(0);
3311 keyhandled = 1;
3312 }
Chris Allegretta9239d742000-09-06 15:19:18 +00003313
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003314
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003315#ifndef USE_SLANG
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003316 /* Hack, make insert key do something useful, like insert file */
3317 if (kbinput == KEY_IC) {
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003318#else
3319 if (0) {
3320#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003321 do_insertkey:
3322
3323#ifdef ENABLE_MULTIBUFFER
Chris Allegretta32da4562002-01-02 15:12:21 +00003324 /* do_insertfile_void() contains the logic needed to
3325 handle view mode with the view mode/multibuffer
3326 exception, so use it here */
3327 do_insertfile_void();
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003328#else
Chris Allegretta32da4562002-01-02 15:12:21 +00003329 print_view_warning();
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003330#endif
3331
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003332 keyhandled = 1;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003333 }
3334
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003335 /* Last gasp, stuff that's not in the main lists */
3336 if (!keyhandled)
3337 switch (kbinput) {
Chris Allegretta84de5522001-04-12 14:51:48 +00003338#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003339#ifdef NCURSES_MOUSE_VERSION
3340 case KEY_MOUSE:
3341 do_mouse();
3342 break;
3343#endif
3344#endif
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003345
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003346 case 0: /* Erg */
Chris Allegretta48ebb812001-10-24 01:34:15 +00003347#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003348 do_next_word();
3349 break;
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003350#endif
Chris Allegrettaf4f7e042001-01-04 16:56:15 +00003351
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003352 case -1: /* Stuff that we don't want to do squat */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003353 case 410: /* Must ignore this, it gets sent when we resize */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003354 case 29: /* Ctrl-] */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003355#ifdef PDCURSES
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003356 case 541: /* ???? */
3357 case 542: /* Control and alt in Windows *shrug* */
Chris Allegretta72623582000-11-29 23:43:28 +00003358 case 543: /* Right ctrl key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003359 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +00003360 case 545: /* Right alt key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003361#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003362
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003363 break;
3364 default:
3365#ifdef DEBUG
3366 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
3367#endif
3368 /* We no longer stop unhandled sequences so that people with
3369 odd character sets can type... */
3370
3371 if (ISSET(VIEW_MODE)) {
3372 print_view_warning();
3373 break;
3374 }
3375 do_char(kbinput);
3376 }
Chris Allegretta7fdbd052001-10-02 00:55:38 +00003377 if (ISSET(DISABLE_CURPOS))
3378 UNSET(DISABLE_CURPOS);
3379 else if (ISSET(CONSTUPDATE))
Chris Allegretta2084acc2001-11-29 03:43:08 +00003380 do_cursorpos(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003381
3382 reset_cursor();
3383 wrefresh(edit);
3384 keyhandled = 0;
3385 }
3386
3387 getchar();
3388 finish(0);
3389
3390}