blob: cfb666f358a1434e1771863deeb183c21f78fdd6 [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * nano.c *
4 * *
Jordi Mallach8ae57892002-01-04 17:57:40 +00005 * Copyright (C) 1999-2002 Chris Allegretta *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00006 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
Chris Allegretta3a24f3f2001-10-24 11:33:54 +00008 * the Free Software Foundation; either version 2, or (at your option) *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00009 * any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 * *
20 **************************************************************************/
21
Chris Allegretta6efda542001-04-28 18:03:52 +000022#include "config.h"
23
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000024#include <stdio.h>
25#include <stdlib.h>
26#include <stdarg.h>
27#include <signal.h>
Chris Allegretta08020882001-01-29 23:37:54 +000028#include <setjmp.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000029#include <unistd.h>
30#include <string.h>
31#include <fcntl.h>
32#include <sys/stat.h>
33#include <sys/ioctl.h>
34#include <sys/param.h>
Chris Allegretta27eb13f2000-11-05 16:52:21 +000035#include <sys/types.h>
36#include <sys/wait.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000037#include <errno.h>
38#include <ctype.h>
39#include <locale.h>
40#include <limits.h>
Adam Rogoyski77f36de2000-06-07 03:56:54 +000041#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000042
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000043#include "proto.h"
44#include "nano.h"
45
46#ifndef NANO_SMALL
47#include <libintl.h>
48#define _(string) gettext(string)
49#else
50#define _(string) (string)
51#endif
52
53#ifdef HAVE_TERMIOS_H
54#include <termios.h>
55#endif
56
57#ifdef HAVE_TERMIO_H
58#include <termio.h>
59#endif
60
61#ifdef HAVE_GETOPT_H
62#include <getopt.h>
63#endif
64
Chris Allegretta6fe61492001-05-21 12:56:25 +000065#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000066/* Former globals, now static */
Chris Allegrettaa8c22572002-02-15 19:17:02 +000067int fill = 0;/* Fill - where to wrap lines, basically */
Chris Allegretta7e65d2f2002-02-15 21:12:52 +000068int wrap_at = 0;/* Right justified fill value, allows resize */
Chris Allegretta6fe61492001-05-21 12:56:25 +000069#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +000070
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000071struct termios oldterm; /* The user's original term settings */
Chris Allegretta88520c92001-05-05 17:45:54 +000072static struct sigaction act; /* For all our fun signal handlers */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000073
Rocco Corsiaf5c3022001-01-12 07:51:05 +000074#ifndef DISABLE_HELP
Chris Allegretta6b58acd2001-04-12 03:01:53 +000075static char *help_text_init = ""; /* Initial message, not including shortcuts */
Chris Allegretta65121632000-12-18 07:05:27 +000076#endif
77
Chris Allegretta27eb13f2000-11-05 16:52:21 +000078char *last_search = NULL; /* Last string we searched for */
79char *last_replace = NULL; /* Last replacement string */
80int search_last_line; /* Is this the last search line? */
81
Chris Allegretta08020882001-01-29 23:37:54 +000082static sigjmp_buf jmpbuf; /* Used to return to mainloop after SIGWINCH */
83
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000084/* What we do when we're all set to exit */
85RETSIGTYPE finish(int sigage)
86{
Chris Allegrettac08f50d2001-01-06 18:12:43 +000087
88 keypad(edit, TRUE);
89 keypad(bottomwin, TRUE);
90
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000091 if (!ISSET(NO_HELP)) {
92 mvwaddstr(bottomwin, 1, 0, hblank);
93 mvwaddstr(bottomwin, 2, 0, hblank);
Chris Allegretta4da1fc62000-06-21 03:00:43 +000094 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000095 mvwaddstr(bottomwin, 0, 0, hblank);
Chris Allegretta6b58acd2001-04-12 03:01:53 +000096
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000097 wrefresh(bottomwin);
98 endwin();
99
100 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000101 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000102
Chris Allegrettaf5de33a2002-02-27 04:14:16 +0000103 thanks_for_all_the_fish();
104
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000105 exit(sigage);
106}
107
108/* Die (gracefully?) */
109void die(char *msg, ...)
110{
111 va_list ap;
112
113 va_start(ap, msg);
114 vfprintf(stderr, msg, ap);
115 va_end(ap);
116
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000117 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000118 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000119
120 clear();
121 refresh();
122 resetty();
123 endwin();
124
125 fprintf(stderr, msg);
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000126
Chris Allegretta32da4562002-01-02 15:12:21 +0000127 /* save the currently loaded file if it's been modified */
128 if (ISSET(MODIFIED))
129 die_save_file(filename);
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000130
Chris Allegretta355fbe52001-07-14 19:32:47 +0000131#ifdef ENABLE_MULTIBUFFER
Chris Allegretta32da4562002-01-02 15:12:21 +0000132 /* then save all of the other modified loaded files, if any */
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000133 if (open_files) {
134 filestruct *tmp;
135
136 tmp = open_files;
137
138 while (open_files->prev)
139 open_files = open_files->prev;
140
141 while (open_files->next) {
142
143 /* if we already saved the file above (i. e. if it was the
144 currently loaded file), don't save it again */
145 if (tmp != open_files) {
146 fileage = open_files->file;
Chris Allegretta32da4562002-01-02 15:12:21 +0000147 /* save the file if it's been modified */
148 if (open_files->file_modified)
149 die_save_file(open_files->data);
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000150 }
151
152 open_files = open_files->next;
153 }
154
155 }
156#endif
157
158 exit(1); /* We have a problem: exit w/ errorlevel(1) */
159}
160
161void die_save_file(char *die_filename)
162{
Chris Allegretta48b06702002-02-22 04:30:50 +0000163 char *name, *ret;
164 int i = -1;
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000165
166 /* if we can't save we have REAL bad problems,
167 * but we might as well TRY. */
168 if (die_filename[0] == '\0') {
169 name = "nano.save";
Chris Allegretta48b06702002-02-22 04:30:50 +0000170 ret = get_next_filename(name);
171 if (strcmp(ret, ""))
172 i = write_file(ret, 1, 0, 0);
173 name = ret;
174 }
175 else {
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000176 char *buf = charalloc(strlen(die_filename) + 6);
177 strcpy(buf, die_filename);
178 strcat(buf, ".save");
Chris Allegretta48b06702002-02-22 04:30:50 +0000179 ret = get_next_filename(buf);
180 if (strcmp(ret, ""))
181 i = write_file(ret, 1, 0, 0);
182 name = ret;
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000183 }
184
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000185 if (i != -1)
186 fprintf(stderr, _("\nBuffer written to %s\n"), name);
187 else
Chris Allegretta48b06702002-02-22 04:30:50 +0000188 fprintf(stderr, _("\nNo %s written (too many backup files?)\n"), name);
189
190 free(ret);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000191}
192
Chris Allegrettae61e8302001-01-14 05:18:27 +0000193/* Die with an error message that the screen was too small if, well, the
194 screen is too small */
195void die_too_small(void)
196{
197 char *too_small_msg = _("Window size is too small for Nano...");
198
199 die(too_small_msg);
200
201}
202
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000203void print_view_warning(void)
204{
205 statusbar(_("Key illegal in VIEW mode"));
206}
207
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000208void clear_filename(void)
209{
210 if (filename != NULL)
211 free(filename);
Chris Allegretta88b09152001-05-17 11:35:43 +0000212 filename = charalloc(1);
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000213 filename[0] = 0;
214}
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +0000215
Chris Allegretta56214c62001-09-27 02:46:53 +0000216/* Initialize global variables - no better way for now. If
217 save_cutbuffer is nonzero, don't set cutbuffer to NULL. */
218void global_init(int save_cutbuffer)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000219{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000220 current_x = 0;
221 current_y = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000222
223 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
224 die_too_small();
225
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000226 fileage = NULL;
Chris Allegretta56214c62001-09-27 02:46:53 +0000227 if (!save_cutbuffer)
228 cutbuffer = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000229 current = NULL;
230 edittop = NULL;
231 editbot = NULL;
232 totlines = 0;
Chris Allegretta56214c62001-09-27 02:46:53 +0000233 totsize = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000234 placewewant = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000235
Chris Allegretta6fe61492001-05-21 12:56:25 +0000236#ifndef DISABLE_WRAPJUSTIFY
237 if (wrap_at)
238 fill = COLS + wrap_at;
239 else if (!fill)
Chris Allegrettae61e8302001-01-14 05:18:27 +0000240 fill = COLS - CHARS_FROM_EOL;
241
242 if (fill < MIN_FILL_LENGTH)
243 die_too_small();
Chris Allegretta6fe61492001-05-21 12:56:25 +0000244#endif
Chris Allegrettae61e8302001-01-14 05:18:27 +0000245
Chris Allegretta88b09152001-05-17 11:35:43 +0000246 hblank = charalloc(COLS + 1);
Chris Allegretta0a06e072001-01-23 02:35:04 +0000247 memset(hblank, ' ', COLS);
248 hblank[COLS] = 0;
Chris Allegretta76e291b2001-10-14 19:05:10 +0000249
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000250}
251
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000252#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000253void init_help_msg(void)
254{
255
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000256 help_text_init =
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000257 _(" nano help text\n\n "
258 "The nano editor is designed to emulate the functionality and "
259 "ease-of-use of the UW Pico text editor. There are four main "
260 "sections of the editor: The top line shows the program "
261 "version, the current filename being edited, and whether "
262 "or not the file has been modified. Next is the main editor "
263 "window showing the file being edited. The status line is "
264 "the third line from the bottom and shows important messages. "
265 "The bottom two lines show the most commonly used shortcuts "
266 "in the editor.\n\n "
267 "The notation for shortcuts is as follows: Control-key "
Chris Allegrettae49f1232000-09-02 07:20:39 +0000268 "sequences are notated with a caret (^) symbol and are entered "
Chris Allegrettad56bd792000-09-02 07:27:10 +0000269 "with the Control (Ctrl) key. Escape-key sequences are notated "
270 "with the Meta (M) symbol and can be entered using either the "
271 "Esc, Alt or Meta key depending on your keyboard setup. The "
272 "following keystrokes are available in the main editor window. "
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000273 "Optional keys are shown in parentheses:\n\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000274}
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000275#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000276
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000277/* Make a copy of a node to a pointer (space will be malloc()ed). This
278 does NOT copy the data members used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000279filestruct *copy_node(filestruct * src)
280{
281 filestruct *dst;
282
283 dst = nmalloc(sizeof(filestruct));
Chris Allegretta88b09152001-05-17 11:35:43 +0000284 dst->data = charalloc(strlen(src->data) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000285
286 dst->next = src->next;
287 dst->prev = src->prev;
288
289 strcpy(dst->data, src->data);
290 dst->lineno = src->lineno;
291
292 return dst;
293}
294
295/* Unlink a node from the rest of the struct */
296void unlink_node(filestruct * fileptr)
297{
298 if (fileptr->prev != NULL)
299 fileptr->prev->next = fileptr->next;
300
301 if (fileptr->next != NULL)
302 fileptr->next->prev = fileptr->prev;
303}
304
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000305/* Delete a node from the struct. This does NOT delete the data members
306 used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000307void delete_node(filestruct * fileptr)
308{
Chris Allegretta17dcb722001-01-20 21:40:07 +0000309 if (fileptr == NULL)
310 return;
311
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000312 if (fileptr->data != NULL)
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000313 free(fileptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000314 free(fileptr);
315}
316
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000317/* Okay, now let's duplicate a whole struct! This does NOT duplicate the
318 data members used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000319filestruct *copy_filestruct(filestruct * src)
320{
321 filestruct *dst, *tmp, *head, *prev;
322
323 head = copy_node(src);
324 dst = head; /* Else we barf on copying just one line */
325 head->prev = NULL;
326 tmp = src->next;
327 prev = head;
328
329 while (tmp != NULL) {
330 dst = copy_node(tmp);
331 dst->prev = prev;
332 prev->next = dst;
333
334 prev = dst;
335 tmp = tmp->next;
336 }
337
338 dst->next = NULL;
339 return head;
340}
341
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000342/* Frees a struct. This does NOT free the data members used only by
343 open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000344int free_filestruct(filestruct * src)
345{
346 filestruct *fileptr = src;
347
348 if (src == NULL)
349 return 0;
350
351 while (fileptr->next != NULL) {
352 fileptr = fileptr->next;
Chris Allegretta17dcb722001-01-20 21:40:07 +0000353 delete_node(fileptr->prev);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000354
355#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000356 fprintf(stderr, _("delete_node(): free'd a node, YAY!\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000357#endif
358 }
Chris Allegretta17dcb722001-01-20 21:40:07 +0000359 delete_node(fileptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000360#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000361 fprintf(stderr, _("delete_node(): free'd last node.\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000362#endif
363
364 return 1;
365}
366
367int renumber_all(void)
368{
369 filestruct *temp;
Chris Allegrettabef12972002-03-06 03:30:40 +0000370 int i = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000371
Chris Allegrettaf6cba642002-03-26 13:05:54 +0000372 assert(fileage==NULL || fileage!=fileage->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000373 for (temp = fileage; temp != NULL; temp = temp->next) {
374 temp->lineno = i++;
375 }
376
377 return 0;
378}
379
380int renumber(filestruct * fileptr)
381{
382 filestruct *temp;
383
384 if (fileptr == NULL || fileptr->prev == NULL || fileptr == fileage) {
385 renumber_all();
386 return 0;
387 }
Chris Allegrettaf6cba642002-03-26 13:05:54 +0000388 assert(fileptr==NULL || fileptr!=fileptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000389 for (temp = fileptr; temp != NULL; temp = temp->next) {
Chris Allegretta5146fec2000-12-10 05:44:02 +0000390 if (temp->prev != NULL)
391 temp->lineno = temp->prev->lineno + 1;
392 else
393 temp->lineno = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000394 }
395
396 return 0;
397}
398
399/* Fix the memory allocation for a string */
400void align(char **strp)
401{
402 /* There was a serious bug here: the new address was never
403 stored anywhere... */
404
405 *strp = nrealloc(*strp, strlen(*strp) + 1);
406}
407
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000408/* Null a string at a certain index and align it */
Chris Allegrettafa0c6962001-10-22 23:22:19 +0000409void null_at(char **data, int index)
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000410{
Chris Allegrettafa0c6962001-10-22 23:22:19 +0000411
412 /* Ahh! Damn dereferencing */
413 (*data)[index] = 0;
414 align(data);
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000415}
416
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000417
418/* Print one usage string to the screen, removes lots of duplicate
419 strings to translate and takes out the parts that shouldn't be
420 translatable (the flag names) */
421void print1opt(char *shortflag, char *longflag, char *desc)
422{
423 printf(" %s\t", shortflag);
424 if (strlen(shortflag) < 8)
425 printf("\t");
426
427#ifdef HAVE_GETOPT_LONG
428 printf("%s\t", longflag);
429 if (strlen(longflag) < 8)
430 printf("\t\t");
431 else if (strlen(longflag) < 16)
432 printf("\t");
433#endif
434
435 printf("%s\n", desc);
436}
437
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000438void usage(void)
439{
440#ifdef HAVE_GETOPT_LONG
441 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
442 printf(_("Option Long option Meaning\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000443#else
444 printf(_("Usage: nano [option] +LINE <file>\n\n"));
445 printf(_("Option Meaning\n"));
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000446#endif /* HAVE_GETOPT_LONG */
447
Chris Allegretta7004c282001-09-22 00:42:10 +0000448#ifndef NANO_SMALL
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000449 print1opt("-D", "--dos", _("Write file in DOS format"));
Chris Allegretta7004c282001-09-22 00:42:10 +0000450#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000451#ifdef ENABLE_MULTIBUFFER
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000452 print1opt("-F", "--multibuffer", _("Enable multiple file buffers"));
Chris Allegretta355fbe52001-07-14 19:32:47 +0000453#endif
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000454 print1opt("-K", "--keypad", _("Use alternate keypad routines"));
Chris Allegretta8fa1e282001-09-22 04:20:25 +0000455#ifndef NANO_SMALL
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000456 print1opt("-M", "--mac", _("Write file in Mac format"));
457 print1opt("-N", "--noconvert", _("Don't convert files from DOS/Mac format"));
Chris Allegretta8fa1e282001-09-22 04:20:25 +0000458#endif
Chris Allegrettae4f940d2002-03-03 22:36:36 +0000459#ifndef DISABLE_JUSTIFY
Chris Allegrettad1ec7b02002-03-09 20:05:26 +0000460 print1opt(_("-Q [str]"), _("--quotestr [str]"), _("Quoting string, default \"> \""));
Chris Allegrettae4f940d2002-03-03 22:36:36 +0000461#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +0000462#ifndef NANO_SMALL
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000463 print1opt("-S", "--smooth", _("Smooth scrolling"));
Chris Allegretta3e3ae942001-09-22 19:02:04 +0000464#endif
Chris Allegrettad1ec7b02002-03-09 20:05:26 +0000465 print1opt(_("-T [num]"), _("--tabsize=[num]"), _("Set width of a tab to num"));
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000466 print1opt("-V", "--version", _("Print version information and exit"));
467 print1opt("-c", "--const", _("Constantly show cursor position"));
468 print1opt("-h", "--help", _("Show this message"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000469#ifndef NANO_SMALL
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000470 print1opt("-i", "--autoindent", _("Automatically indent new lines"));
471 print1opt("-k", "--cut", _("Let ^K cut from cursor to end of line"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000472#endif
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000473 print1opt("-l", "--nofollow", _("Don't follow symbolic links, overwrite"));
Chris Allegretta84de5522001-04-12 14:51:48 +0000474#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000475#ifdef NCURSES_MOUSE_VERSION
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000476 print1opt("-m", "--mouse", _("Enable mouse"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000477#endif
478#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000479#ifndef DISABLE_OPERATINGDIR
Chris Allegrettad1ec7b02002-03-09 20:05:26 +0000480 print1opt(_("-o [dir]"), _("--operatingdir=[dir]"), _("Set operating directory"));
Chris Allegrettae1f14522001-09-19 03:19:43 +0000481#endif
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000482 print1opt("-p", "--pico", _("Emulate Pico as closely as possible"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000483
484#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettad1ec7b02002-03-09 20:05:26 +0000485 print1opt(_("-r [#cols]"), _("--fill=[#cols]"), _("Set fill cols to (wrap lines at) #cols"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000486#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000487#ifndef DISABLE_SPELLER
Chris Allegrettad1ec7b02002-03-09 20:05:26 +0000488 print1opt(_("-s [prog]"), _("--speller=[prog]"), _("Enable alternate speller"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000489#endif
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000490 print1opt("-t", "--tempfile", _("Auto save on exit, don't prompt"));
491 print1opt("-v", "--view", _("View (read only) mode"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000492#ifndef DISABLE_WRAPPING
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000493 print1opt("-w", "--nowrap", _("Don't wrap long lines"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000494#endif
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000495 print1opt("-x", "--nohelp", _("Don't show help window"));
496 print1opt("-z", "--suspend", _("Enable suspend"));
Chris Allegrettad1ec7b02002-03-09 20:05:26 +0000497 print1opt(_("+LINE"), "", _("Start at line number LINE"));
Chris Allegretta3fc5d572002-03-09 18:51:58 +0000498
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000499 exit(0);
500}
501
502void version(void)
503{
Chris Allegrettac46dd812001-02-14 14:28:27 +0000504 printf(_(" GNU nano version %s (compiled %s, %s)\n"),
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000505 VERSION, __TIME__, __DATE__);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000506 printf(_
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000507 (" Email: nano@nano-editor.org Web: http://www.nano-editor.org"));
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000508 printf(_("\n Compiled options:"));
Chris Allegrettaff269f82000-12-01 18:46:01 +0000509
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000510#ifdef NANO_EXTRA
511 printf(" --enable-extra");
Jordi Mallach5285ca92002-01-17 12:40:33 +0000512#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000513#ifdef ENABLE_MULTIBUFFER
514 printf(" --enable-multibuffer");
Jordi Mallach5285ca92002-01-17 12:40:33 +0000515#endif
Chris Allegrettab881d3e2001-04-18 04:34:43 +0000516#ifdef ENABLE_NANORC
517 printf(" --enable-nanorc");
518#endif
Chris Allegretta8ce24132001-04-30 11:28:46 +0000519#ifdef ENABLE_COLOR
520 printf(" --enable-color");
521#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000522
523#ifdef NANO_SMALL
524 printf(" --enable-tiny");
525#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000526#ifdef DISABLE_BROWSER
Chris Allegretta6636dc32001-01-05 05:41:07 +0000527 printf(" --disable-browser");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000528#endif
529#ifdef DISABLE_TABCOMP
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000530 printf(" --disable-tabcomp");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000531#endif
532#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +0000533 printf(" --disable-justify");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000534#endif
535#ifdef DISABLE_SPELLER
Chris Allegretta7b36c522000-12-06 01:08:10 +0000536 printf(" --disable-speller");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000537#endif
538#ifdef DISABLE_HELP
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000539 printf(" --disable-help");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000540#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000541#ifdef DISABLE_MOUSE
542 printf(" --disable-mouse");
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000543#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000544#ifdef DISABLE_OPERATINGDIR
545 printf(" --disable-operatingdir");
546#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000547#endif /* NANO_SMALL */
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000548
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000549#ifdef DISABLE_WRAPPING
550 printf(" --disable-wrapping");
551#endif
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000552#ifdef USE_SLANG
553 printf(" --with-slang");
554#endif
555 printf("\n");
556
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000557}
558
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000559/* Create a new node. This does NOT initialize the data members used
560 only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000561filestruct *make_new_node(filestruct * prevnode)
562{
563 filestruct *newnode;
564
565 newnode = nmalloc(sizeof(filestruct));
566 newnode->data = NULL;
567
568 newnode->prev = prevnode;
569 newnode->next = NULL;
570
571 if (prevnode != NULL)
572 newnode->lineno = prevnode->lineno + 1;
573
574 return newnode;
575}
576
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000577/* Splice a node into an existing filestruct. This does NOT set the data
578 members used only by open_files. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000579void splice_node(filestruct * begin, filestruct * newnode,
580 filestruct * end)
Chris Allegretta7975ed82000-07-28 00:58:35 +0000581{
Chris Allegrettae3167732001-03-18 16:59:34 +0000582 newnode->next = end;
583 newnode->prev = begin;
584 begin->next = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000585 if (end != NULL)
Chris Allegrettae3167732001-03-18 16:59:34 +0000586 end->prev = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000587}
588
Chris Allegrettae3167732001-03-18 16:59:34 +0000589int do_mark(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000590{
591#ifdef NANO_SMALL
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000592 nano_disabled_msg();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000593#else
594 if (!ISSET(MARK_ISSET)) {
595 statusbar(_("Mark Set"));
596 SET(MARK_ISSET);
597 mark_beginbuf = current;
598 mark_beginx = current_x;
599 } else {
600 statusbar(_("Mark UNset"));
601 UNSET(MARK_ISSET);
602 mark_beginbuf = NULL;
603 mark_beginx = 0;
604
605 edit_refresh();
606 }
607#endif
608 return 1;
609}
610
611int no_help(void)
612{
613 if ISSET
614 (NO_HELP)
615 return 2;
616 else
617 return 0;
618}
619
Chris Allegretta3bc8c722000-12-10 17:03:25 +0000620#if defined(DISABLE_JUSTIFY) || defined(DISABLE_SPELLER) || defined(DISABLE_HELP)
Chris Allegrettaff269f82000-12-01 18:46:01 +0000621void nano_disabled_msg(void)
622{
623 statusbar("Sorry, support for this function has been disabled");
624}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000625#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000626
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000627/* The user typed a printable character; add it to the edit buffer */
628void do_char(char ch)
629{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000630 /* magic-line: when a character is inserted on the current magic line,
631 * it means we need a new one! */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000632 if (filebot == current && current->data[0] == '\0') {
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000633 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000634 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000635 }
636
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000637 /* More dangerousness fun =) */
638 current->data = nrealloc(current->data, strlen(current->data) + 2);
639 memmove(&current->data[current_x + 1],
640 &current->data[current_x],
641 strlen(current->data) - current_x + 1);
642 current->data[current_x] = ch;
643 do_right();
644
Chris Allegrettab2cd10d2002-01-20 00:54:42 +0000645#ifdef ENABLE_COLOR
646 edit_refresh();
647#endif
648
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000649#ifndef DISABLE_WRAPPING
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000650 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000651 check_wrap(current, ch);
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000652#endif
653
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000654 set_modified();
655 check_statblank();
656 UNSET(KEEP_CUTBUFFER);
657 totsize++;
658
659}
660
661/* Someone hits return *gasp!* */
662int do_enter(filestruct * inptr)
663{
Chris Allegrettae3167732001-03-18 16:59:34 +0000664 filestruct *newnode;
Chris Allegretta68532c32001-09-17 13:49:33 +0000665 char *tmp;
666#ifndef NANO_SMALL
667 char *spc;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000668 int extra = 0;
Chris Allegretta68532c32001-09-17 13:49:33 +0000669#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000670
Chris Allegrettae3167732001-03-18 16:59:34 +0000671 newnode = make_new_node(inptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000672 tmp = &current->data[current_x];
673 current_x = 0;
674
Chris Allegrettaff989832001-09-17 13:48:00 +0000675#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000676 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
677 if (ISSET(AUTOINDENT)) {
678 spc = current->data;
679 if (spc) {
680 while ((*spc == ' ') || (*spc == '\t')) {
681 extra++;
682 spc++;
683 current_x++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +0000684 totsize++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000685 }
Chris Allegretta88b09152001-05-17 11:35:43 +0000686 newnode->data = charalloc(strlen(tmp) + extra + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000687 strncpy(newnode->data, current->data, extra);
688 strcpy(&newnode->data[extra], tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000689 }
Chris Allegrettaff989832001-09-17 13:48:00 +0000690 } else
691#endif
692 {
Chris Allegretta88b09152001-05-17 11:35:43 +0000693 newnode->data = charalloc(strlen(tmp) + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000694 strcpy(newnode->data, tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000695 }
696 *tmp = 0;
697
Chris Allegrettada721be2000-07-31 01:26:42 +0000698 if (inptr->next == NULL) {
Chris Allegrettae3167732001-03-18 16:59:34 +0000699 filebot = newnode;
700 editbot = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000701 }
Chris Allegrettae3167732001-03-18 16:59:34 +0000702 splice_node(inptr, newnode, inptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000703
704 totsize++;
705 renumber(current);
Chris Allegrettae3167732001-03-18 16:59:34 +0000706 current = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000707 align(&current->data);
708
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000709 /* The logic here is as follows:
710 * -> If we are at the bottom of the buffer, we want to recenter
Chris Allegretta88520c92001-05-05 17:45:54 +0000711 * (read: rebuild) the screen and forcibly move the cursor.
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000712 * -> otherwise, we want simply to redraw the screen and update
713 * where we think the cursor is.
714 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000715 if (current_y == editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +0000716 edit_update(current, CENTER);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000717 reset_cursor();
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000718 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000719 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000720 edit_refresh();
721 update_cursor();
722 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000723
724 totlines++;
725 set_modified();
726
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000727 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000728 return 1;
729}
730
731int do_enter_void(void)
732{
733 return do_enter(current);
734}
735
Chris Allegrettaad3f4782001-10-02 03:54:13 +0000736#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000737void do_next_word(void)
738{
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000739 filestruct *fileptr, *old;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000740 int i;
741
742 if (current == NULL)
743 return;
744
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000745 old = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000746 i = current_x;
747 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
748 if (fileptr == current) {
749 while (isalnum((int) fileptr->data[i])
750 && fileptr->data[i] != 0)
751 i++;
752
753 if (fileptr->data[i] == 0) {
754 i = 0;
755 continue;
756 }
757 }
758 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
759 i++;
760
761 if (fileptr->data[i] != 0)
762 break;
763
764 i = 0;
765 }
766 if (fileptr == NULL)
767 current = filebot;
768 else
769 current = fileptr;
770
771 current_x = i;
772 placewewant = xplustabs();
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000773
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000774 if (current->lineno >= editbot->lineno)
Chris Allegretta234a34d2000-07-29 04:33:38 +0000775 edit_update(current, CENTER);
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000776 else {
777 /* If we've jumped lines, refresh the old line. We can't just use
778 * current->prev here, because we may have skipped over some blank
779 * lines, in which case the previous line is the wrong one.
780 */
781 if (current != old)
782 update_line(old, 0);
783
784 update_line(current, current_x);
785 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000786}
787
788/* the same thing for backwards */
789void do_prev_word(void)
790{
791 filestruct *fileptr, *old;
792 int i;
793
794 if (current == NULL)
795 return;
796
797 old = current;
798 i = current_x;
799 for (fileptr = current; fileptr != NULL; fileptr = fileptr->prev) {
800 if (fileptr == current) {
801 while (isalnum((int) fileptr->data[i])
802 && i != 0)
803 i--;
804
805 if (i == 0) {
806 if (fileptr->prev != NULL)
Chris Allegrettae59fc822001-10-24 18:07:58 +0000807 i = strlen(fileptr->prev->data);
Chris Allegretta878ced32001-10-22 20:05:34 +0000808 else if (fileptr == fileage && filebot != NULL) {
809 current_x = 0;
810 return;
811 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000812 continue;
813 }
814 }
815
816 while (!isalnum((int) fileptr->data[i]) && i != 0)
817 i--;
818
819 if (i > 0) {
820 i--;
821
822 while (isalnum((int) fileptr->data[i]) && i != 0)
823 i--;
824
Chris Allegretta6d0aa9f2001-10-26 15:21:41 +0000825 if (!isalnum((int) fileptr->data[i]))
826 i++;
827
828 if (i != 0 || i != current_x)
Chris Allegretta76e291b2001-10-14 19:05:10 +0000829 break;
830
831 }
832 if (fileptr->prev != NULL)
Chris Allegrettae59fc822001-10-24 18:07:58 +0000833 i = strlen(fileptr->prev->data);
Chris Allegretta878ced32001-10-22 20:05:34 +0000834 else if (fileptr == fileage && filebot != NULL) {
835 current_x = 0;
836 return;
837 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000838 }
839 if (fileptr == NULL)
840 current = fileage;
841 else
842 current = fileptr;
843
844 current_x = i;
845 placewewant = xplustabs();
846
847 if (current->lineno <= edittop->lineno)
848 edit_update(current, CENTER);
849 else {
850 /* If we've jumped lines, refresh the old line. We can't just use
851 * current->prev here, because we may have skipped over some blank
852 * lines, in which case the previous line is the wrong one.
853 */
854 if (current != old)
855 update_line(old, 0);
856
857 update_line(current, current_x);
858 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000859
860}
Chris Allegrettaad3f4782001-10-02 03:54:13 +0000861#endif /* NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000862
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000863#ifndef DISABLE_WRAPPING
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000864void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000865{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000866 int i = 0; /* Index into ->data for line. */
867 int i_tabs = 0; /* Screen position of ->data[i]. */
868 int last_word_end = -1; /* Location of end of last word found. */
869 int current_word_start = -1; /* Location of start of current word. */
870 int current_word_start_t = -1; /* Location of start of current word screen position. */
871 int current_word_end = -1; /* Location of end of current word */
872 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000873 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000874
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000875 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000876 int right = 0;
877 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000878
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000879 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000880
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000881 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000882 if (!isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000883 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000884
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000885 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000886 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000887
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000888 while (!isspace((int) inptr->data[i])
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000889 && inptr->data[i]) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000890 i++;
891 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000892 if (inptr->data[i] < 32)
893 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000894 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000895
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000896 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000897 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000898 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000899 } else {
900 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000901 current_word_end_t = i_tabs - 1;
902 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000903 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000904
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000905 if (inptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000906 if (i_tabs % tabsize != 0);
907 i_tabs += tabsize - (i_tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000908 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000909
Adam Rogoyski09f97962000-06-20 02:50:33 +0000910 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000911 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000912 }
913
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000914 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000915 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000916 * a) one word takes up the whole line with no starting spaces.
917 * - do nothing and return.
918 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000919 * - word starts new line.
920 * - keep white space on original line up to the cursor.
921 * *) cursor is after word at wrap point
922 * - either it's all white space after word, and this routine isn't called.
923 * - or we are actually in case 2 (2 words).
924 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000925 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000926 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000927 * - white space at end of original line is cleared, unless
928 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000929 * b) cursor is at the word at the wrap point.
930 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000931 * - white space on original line is kept to where cursor was.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000932 * c) cursor is past the word at the wrap point.
933 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000934 * - white space at end of original line is cleared
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000935 */
936
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000937 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000938
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000939 /* Category 1a: one word taking up the whole line with no beginning spaces. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000940 if ((last_word_end == -1) && (!isspace((int) inptr->data[0]))) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000941 for (i = current_word_end; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000942 if (!isspace((int) inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000943 current_word_start = i;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000944 while (!isspace((int) inptr->data[i]) && (i < len)) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000945 i++;
946 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000947 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000948 current_word_end = i;
949 break;
950 }
951 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000952
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000953 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000954 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000955 return;
956 }
957 if (current_x >= last_word_end) {
958 right = (current_x - current_word_start) + 1;
959 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000960 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000961 }
962
Chris Allegretta2084acc2001-11-29 03:43:08 +0000963 /* Subtract length of original line, plus one for the newline, from
964 totsize. */
965 totsize -= (strlen(inptr->data) + 1);
966
Chris Allegretta88b09152001-05-17 11:35:43 +0000967 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000968 strcpy(temp->data, &inptr->data[current_word_start]);
969 inptr->data = nrealloc(inptr->data, last_word_end + 2);
970 inptr->data[last_word_end + 1] = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +0000971
972 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
973 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
974
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000975 } else
976 /* Category 1b: one word on the line and word not taking up whole line
977 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000978 if (last_word_end == -1) {
Chris Allegretta88b09152001-05-17 11:35:43 +0000979 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000980 strcpy(temp->data, &inptr->data[current_word_start]);
981
982 /* Inside word, remove it from original, and move cursor to right spot. */
983 if (current_x >= current_word_start) {
984 right = current_x - current_word_start;
Chris Allegretta56214c62001-09-27 02:46:53 +0000985
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000986 current_x = 0;
Chris Allegrettaff989832001-09-17 13:48:00 +0000987#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +0000988 if (ISSET(AUTOINDENT)) {
989 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000990 while ((inptr->next->data[i] == ' '
991 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +0000992 i++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000993 }
Chris Allegretta94a78b82001-03-14 08:28:48 +0000994 }
Chris Allegrettaff989832001-09-17 13:48:00 +0000995#endif
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000996 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000997 }
998
Chris Allegretta2084acc2001-11-29 03:43:08 +0000999 /* Subtract length of original line, plus one for the newline, from
1000 totsize. */
1001 totsize -= (strlen(inptr->data) + 1);
1002
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001003 null_at(&inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001004
Chris Allegretta2084acc2001-11-29 03:43:08 +00001005 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1006 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
1007
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001008 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
1009 mark_beginbuf = temp;
1010 mark_beginx = 0;
1011 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001012 }
1013
1014 /* Category 2: two or more words on the line. */
1015 else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001016 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001017 if (current_x < current_word_start) {
1018 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001019 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001020 strcpy(temp->data, &inptr->data[current_word_start]);
1021
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001022 if (!isspace((int) input_char)) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001023 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001024
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001025 while (isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001026 i--;
1027 assert(i >= 0);
1028 }
1029 } else if (current_x <= last_word_end)
1030 i = last_word_end - 1;
1031 else
1032 i = current_x;
1033
Chris Allegretta2084acc2001-11-29 03:43:08 +00001034 /* Subtract length of original line, plus one for the newline, from
1035 totsize. */
1036 totsize -= (strlen(inptr->data) + 1);
1037
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001038 inptr->data = nrealloc(inptr->data, i + 2);
1039 inptr->data[i + 1] = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001040
1041 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1042 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
1043
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001044 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001045
1046
1047 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001048 else if ((current_x >= current_word_start)
1049 && (current_x <= (current_word_end + 1))) {
1050 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001051 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001052 strcpy(temp->data, &inptr->data[current_word_start]);
1053
1054 down = 1;
1055
1056 right = current_x - current_word_start;
Chris Allegrettaff989832001-09-17 13:48:00 +00001057#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001058 if (ISSET(AUTOINDENT)) {
1059 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001060 while ((inptr->next->data[i] == ' '
1061 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001062 i++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001063 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001064 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001065#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001066 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001067 current_x = current_word_start;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001068
Chris Allegretta2084acc2001-11-29 03:43:08 +00001069 /* Subtract length of original line, plus one for the newline, from
1070 totsize. */
1071 totsize -= (strlen(inptr->data) + 1);
1072
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001073 null_at(&inptr->data, current_word_start);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001074
Chris Allegretta2084acc2001-11-29 03:43:08 +00001075 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1076 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001077 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001078
1079
1080 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001081 else {
1082 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001083 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001084 strcpy(temp->data, &inptr->data[current_word_start]);
1085
1086 down = 1;
1087 right = current_x - current_word_start;
1088
1089 current_x = current_word_start;
1090 i = current_word_start - 1;
1091
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001092 while (isspace((int) inptr->data[i])) {
Adam Rogoyski3d449b42000-06-19 17:30:14 +00001093 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001094 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001095 }
Chris Allegretta2084acc2001-11-29 03:43:08 +00001096
1097 /* Subtract length of original line, plus one for the newline, from
1098 totsize. */
1099 totsize -= (strlen(inptr->data) + 1);
1100
1101 inptr->data = nrealloc(inptr->data, i + 2);
1102 inptr->data[i + 1] = 0;
1103
1104 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1105 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001106 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001107 }
1108
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001109 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001110 if (ISSET(SAMELINEWRAP) && inptr->next) {
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001111 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001112
Chris Allegretta94a78b82001-03-14 08:28:48 +00001113 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001114 char *p =
Chris Allegretta88b09152001-05-17 11:35:43 +00001115 charalloc((strlen(temp->data) + strlen(inptr->next->data) + 2));
Chris Allegretta94a78b82001-03-14 08:28:48 +00001116
Chris Allegretta56214c62001-09-27 02:46:53 +00001117 /* We're adding to an existing line instead of creating a new
1118 one; decrement totlines here so that when it gets incremented
1119 below, it won't end up being high by one. */
1120 totlines--;
1121
Chris Allegrettaff989832001-09-17 13:48:00 +00001122#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001123 if (ISSET(AUTOINDENT)) {
1124 int non = 0;
1125
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001126 /* Grab the beginning of the next line until it's not a
1127 space or tab, then null terminate it so we can strcat it
1128 to hell */
1129 while ((inptr->next->data[non] == ' '
Chris Allegretta355fbe52001-07-14 19:32:47 +00001130 || inptr->next->data[non] == '\t')) {
1131 p[non] = inptr->next->data[non];
1132 non++;
1133 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001134 p[non] = 0;
1135 strcat(p, temp->data);
1136 strcat(p, " ");
1137
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001138 /* Now tack on the rest of the next line after the spaces and
1139 tabs */
Chris Allegretta94a78b82001-03-14 08:28:48 +00001140 strcat(p, &inptr->next->data[non]);
Chris Allegrettaff989832001-09-17 13:48:00 +00001141 } else
1142#endif
1143 {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001144 strcpy(p, temp->data);
1145 strcat(p, " ");
1146 strcat(p, inptr->next->data);
1147 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001148
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001149 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001150 inptr->next->data = p;
1151
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001152 free(temp->data);
1153 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001154
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001155 current_x = old_x;
1156 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001157 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001158 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001159 else {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001160
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001161 temp->prev = inptr;
1162 temp->next = inptr->next;
1163
1164 if (inptr->next)
1165 inptr->next->prev = temp;
1166 inptr->next = temp;
1167
1168 if (!temp->next)
1169 filebot = temp;
1170
1171 SET(SAMELINEWRAP);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001172
Chris Allegrettaff989832001-09-17 13:48:00 +00001173#ifndef NANO_SMALL
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001174 if (ISSET(AUTOINDENT)) {
1175 char *spc = inptr->data;
1176 char *t = NULL;
1177 int extra = 0;
1178 if (spc) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001179 while ((*spc == ' ') || (*spc == '\t')) {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001180 extra++;
1181 spc++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001182 totsize++;
Chris Allegretta438f7132002-01-16 00:54:47 +00001183 right++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001184 }
Chris Allegretta88b09152001-05-17 11:35:43 +00001185 t = charalloc(strlen(temp->data) + extra + 1);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001186 strncpy(t, inptr->data, extra);
1187 strcpy(t + extra, temp->data);
1188 free(temp->data);
1189 temp->data = t;
1190 }
1191 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001192#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001193 }
1194
1195
1196 totlines++;
Chris Allegretta88520c92001-05-05 17:45:54 +00001197 /* Everything about it makes me want this line here, but it causes
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001198 * totsize to be high by one for some reason. Sigh. (Rob) */
1199 /* totsize++; */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001200
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001201 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001202 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001203
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001204
1205 /* Move the cursor to the new line if appropriate. */
1206 if (down) {
1207 do_right();
1208 }
1209
1210 /* Move the cursor to the correct spot in the line if appropriate. */
1211 while (right--) {
1212 do_right();
1213 }
1214
Chris Allegretta234a34d2000-07-29 04:33:38 +00001215 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001216 reset_cursor();
1217 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001218}
1219
1220/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001221void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001222{
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001223 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001224#ifdef DEBUG
1225 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
1226 inptr->data);
1227#endif
1228
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001229 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001230 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001231 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001232 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001233
1234 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001235 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001236
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001237 while (isspace((int) inptr->data[i]) && inptr->data[i])
Adam Rogoyski09f97962000-06-20 02:50:33 +00001238 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001239
Adam Rogoyski09f97962000-06-20 02:50:33 +00001240 if (!inptr->data[i])
1241 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001242
Adam Rogoyski09f97962000-06-20 02:50:33 +00001243 /* String must be at least 1 character long. */
1244 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001245 if (isspace((int) inptr->data[i])) {
Adam Rogoyski09f97962000-06-20 02:50:33 +00001246 if (!char_found)
1247 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001248 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001249 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001250 } else
1251 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001252 }
Adam Rogoyski09f97962000-06-20 02:50:33 +00001253
1254 if (char_found == 2)
1255 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001256 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001257}
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001258#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001259
1260/* Stuff we do when we abort from programs and want to clean up the
Chris Allegretta88520c92001-05-05 17:45:54 +00001261 * screen. This doesn't do much right now.
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001262 */
1263void do_early_abort(void)
1264{
1265 blank_statusbar_refresh();
1266}
1267
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001268int do_backspace(void)
1269{
1270 filestruct *previous, *tmp;
1271
1272 if (current_x != 0) {
1273 /* Let's get dangerous */
1274 memmove(&current->data[current_x - 1], &current->data[current_x],
1275 strlen(current->data) - current_x + 1);
1276#ifdef DEBUG
1277 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
1278#endif
1279 align(&current->data);
1280 do_left();
1281 } else {
1282 if (current == fileage)
1283 return 0; /* Can't delete past top of file */
1284
1285 previous = current->prev;
1286 current_x = strlen(previous->data);
1287 previous->data = nrealloc(previous->data,
1288 strlen(previous->data) +
1289 strlen(current->data) + 1);
1290 strcat(previous->data, current->data);
1291
1292 tmp = current;
1293 unlink_node(current);
1294 delete_node(current);
1295 if (current == edittop) {
1296 if (previous->next)
1297 current = previous->next;
1298 else
1299 current = previous;
Chris Allegretta3e3ae942001-09-22 19:02:04 +00001300 page_up();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001301 } else {
1302 if (previous->next)
1303 current = previous->next;
1304 else
1305 current = previous;
1306 update_line(current, current_x);
1307 }
1308
1309 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001310 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001311 filebot = current;
1312 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001313
1314 /* Recreate the magic line if we're deleting it AND if the
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001315 line we're on now is NOT blank. if it is blank we
1316 can just use IT for the magic line. This is how Pico
1317 appears to do it, in any case */
Chris Allegretta28a0f892000-07-05 22:47:54 +00001318 if (strcmp(current->data, "")) {
1319 new_magicline();
1320 fix_editbot();
1321 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001322 }
1323
1324 current = previous;
1325 renumber(current);
1326 previous_line();
1327 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001328#ifdef DEBUG
1329 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
1330#endif
1331
1332 }
1333
1334 totsize--;
1335 set_modified();
1336 UNSET(KEEP_CUTBUFFER);
1337 edit_refresh();
1338 return 1;
1339}
1340
1341int do_delete(void)
1342{
1343 filestruct *foo;
1344
Chris Allegretta2084acc2001-11-29 03:43:08 +00001345 /* blbf -> blank line before filebot (see below) */
1346 int blbf = 0;
1347
1348 if (current->next == filebot && !strcmp(current->data, ""))
1349 blbf = 1;
1350
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001351 if (current_x != strlen(current->data)) {
1352 /* Let's get dangerous */
1353 memmove(&current->data[current_x], &current->data[current_x + 1],
1354 strlen(current->data) - current_x);
1355
1356 align(&current->data);
1357
Chris Allegretta2084acc2001-11-29 03:43:08 +00001358 /* Now that we have a magic line again, we can check for both being
1359 on the line before filebot as well as at filebot; it's a special
1360 case if we're on the line before filebot and it's blank, since we
1361 should be able to delete it */
1362 } else if (current->next != NULL && (current->next != filebot || blbf)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001363 current->data = nrealloc(current->data,
1364 strlen(current->data) +
1365 strlen(current->next->data) + 1);
1366 strcat(current->data, current->next->data);
1367
1368 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001369 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001370 filebot = current;
1371 editbot = current;
1372 }
1373
1374 unlink_node(foo);
1375 delete_node(foo);
1376 update_line(current, current_x);
1377
Chris Allegretta4ed13152001-02-10 17:50:50 +00001378 /* Please see the comment in do_backspace if you don't understand
Chris Allegretta28a0f892000-07-05 22:47:54 +00001379 this test */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001380 if (current == filebot && strcmp(current->data, "")) {
Chris Allegretta28a0f892000-07-05 22:47:54 +00001381 new_magicline();
1382 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001383 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001384 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001385 renumber(current);
1386 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001387 } else
1388 return 0;
1389
1390 totsize--;
1391 set_modified();
1392 UNSET(KEEP_CUTBUFFER);
1393 edit_refresh();
1394 return 1;
1395}
1396
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001397void wrap_reset(void)
1398{
1399 UNSET(SAMELINEWRAP);
1400}
1401
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001402#ifndef DISABLE_SPELLER
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001403
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001404int do_int_spell_fix(char *word)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001405{
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001406 char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001407 filestruct *begin;
Chris Allegretta23b74b22002-01-21 20:32:22 +00001408 int i = 0, j = 0, beginx, beginx_top, reverse_search_set;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001409
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001410 /* save where we are */
1411 begin = current;
1412 beginx = current_x + 1;
1413
Chris Allegretta23b74b22002-01-21 20:32:22 +00001414 /* Make sure Spell Check goes forward only */
1415 reverse_search_set = ISSET(REVERSE_SEARCH);
1416 UNSET(REVERSE_SEARCH);
1417
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001418 /* save the current search/replace strings */
1419 search_init_globals();
1420 save_search = mallocstrcpy(save_search, last_search);
1421 save_replace = mallocstrcpy(save_replace, last_replace);
1422
1423 /* set search/replace strings to mis-spelt word */
1424 prevanswer = mallocstrcpy(prevanswer, word);
1425 last_search = mallocstrcpy(last_search, word);
1426 last_replace = mallocstrcpy(last_replace, word);
1427
1428 /* start from the top of file */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001429 current = fileage;
1430 current_x = beginx_top = -1;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001431
1432 search_last_line = FALSE;
1433
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001434 edit_update(fileage, TOP);
1435
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001436 while (1) {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001437
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001438 /* make sure word is still mis-spelt (i.e. when multi-errors) */
1439 if (findnextstr(TRUE, FALSE, fileage, beginx_top, prevanswer) != NULL) {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001440
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001441 /* find wholewords only */
1442 if (!is_whole_word(current_x, current, prevanswer))
1443 continue;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001444
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001445 do_replace_highlight(TRUE, prevanswer);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001446
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001447 /* allow replace word to be corrected */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001448 i = statusq(0, spell_list, last_replace, _("Edit a replacement"));
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001449
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001450 do_replace_highlight(FALSE, prevanswer);
1451
1452 /* start from the start of this line again */
1453 current = fileage;
1454 current_x = beginx_top;
1455
1456 search_last_line = FALSE;
1457
1458 if (strcmp(prevanswer,answer) != 0) {
1459 j = i;
1460 do_replace_loop(prevanswer, fileage, &beginx_top, TRUE, &j);
1461 }
Chris Allegretta80838272001-12-02 06:03:22 +00001462 }
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001463
1464 break;
Rocco Corsi562964d2002-01-13 03:18:03 +00001465 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001466
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001467 /* restore the search/replace strings */
Chris Allegrettabef12972002-03-06 03:30:40 +00001468 free(last_search); last_search=save_search;
1469 free(last_replace); last_replace=save_replace;
1470 free(prevanswer);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001471
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001472 /* restore where we were */
1473 current = begin;
1474 current_x = beginx - 1;
1475
Chris Allegretta23b74b22002-01-21 20:32:22 +00001476 /* restore Search/Replace direction */
1477 if (reverse_search_set)
1478 SET(REVERSE_SEARCH);
1479
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001480 edit_update(current, CENTER);
1481
1482 if (i == -1)
1483 return FALSE;
1484
1485 return TRUE;
1486}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001487
1488/* Integrated spell checking using 'spell' program */
Chris Allegretta271e9722000-11-10 18:15:43 +00001489int do_int_speller(char *tempfile_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001490{
Chris Allegretta271e9722000-11-10 18:15:43 +00001491 char *read_buff, *read_buff_ptr, *read_buff_word;
Chris Allegrettaf21f3fc2002-03-25 03:26:27 +00001492 size_t pipe_buff_size, read_buff_size, read_buff_read, bytesread;
Chris Allegretta271e9722000-11-10 18:15:43 +00001493 int in_fd[2], tempfile_fd;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001494 int spell_status;
1495 pid_t pid_spell;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001496
Chris Allegretta271e9722000-11-10 18:15:43 +00001497 /* Create a pipe to spell program */
1498
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001499 if (pipe(in_fd) == -1)
1500 return FALSE;
1501
Chris Allegretta271e9722000-11-10 18:15:43 +00001502 /* A new process to run spell in */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001503
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001504 if ((pid_spell = fork()) == 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001505
1506 /* Child continues, (i.e. future spell process) */
1507
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001508 close(in_fd[0]);
1509
Chris Allegretta271e9722000-11-10 18:15:43 +00001510 /* replace the standard in with the tempfile */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001511
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001512 if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001513
1514 close(in_fd[1]);
1515 exit(1);
1516 }
1517
1518 if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
1519
1520 close(tempfile_fd);
1521 close(in_fd[1]);
1522 exit(1);
1523 }
1524 close(tempfile_fd);
1525
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001526
Chris Allegretta271e9722000-11-10 18:15:43 +00001527 /* send spell's standard out to the pipe */
1528
1529 if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1530
1531 close(in_fd[1]);
1532 exit(1);
1533 }
1534 close(in_fd[1]);
1535
1536 /* Start spell program, we are using the PATH here!?!? */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001537 execlp("spell", "spell", NULL);
1538
Chris Allegretta271e9722000-11-10 18:15:43 +00001539 /* Should not be reached, if spell is found!!! */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001540
Chris Allegretta271e9722000-11-10 18:15:43 +00001541 exit(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001542 }
1543
1544 /* Parent continues here */
1545
Chris Allegretta271e9722000-11-10 18:15:43 +00001546 close(in_fd[1]);
1547
1548 /* Child process was not forked successfully */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001549
1550 if (pid_spell < 0) {
1551
Chris Allegretta271e9722000-11-10 18:15:43 +00001552 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001553 return FALSE;
1554 }
1555
Chris Allegretta271e9722000-11-10 18:15:43 +00001556 /* Get system pipe buffer size */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001557
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001558 if ((pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001559
Chris Allegretta271e9722000-11-10 18:15:43 +00001560 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001561 return FALSE;
Chris Allegretta271e9722000-11-10 18:15:43 +00001562 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001563
Chris Allegrettaf21f3fc2002-03-25 03:26:27 +00001564 /* Read-in the returned spelling errors */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001565
Chris Allegrettaf21f3fc2002-03-25 03:26:27 +00001566 read_buff_read = 0;
1567 read_buff_size = pipe_buff_size + 1;
1568 read_buff = read_buff_ptr = charalloc(read_buff_size);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001569
Chris Allegrettaf21f3fc2002-03-25 03:26:27 +00001570 while ((bytesread = read(in_fd[0], read_buff_ptr, pipe_buff_size)) > 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001571
Chris Allegrettaf21f3fc2002-03-25 03:26:27 +00001572 read_buff_read += bytesread;
1573 read_buff_size += pipe_buff_size;
1574 read_buff = read_buff_ptr = nrealloc(read_buff, read_buff_size);
1575 read_buff_ptr += read_buff_read;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001576 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001577
Chris Allegrettaf21f3fc2002-03-25 03:26:27 +00001578 *read_buff_ptr = (char) NULL;
Chris Allegretta271e9722000-11-10 18:15:43 +00001579 close(in_fd[0]);
Chris Allegrettaf21f3fc2002-03-25 03:26:27 +00001580
1581 /* Process the spelling errors */
1582
1583 read_buff_word = read_buff_ptr = read_buff;
1584
1585 while (*read_buff_ptr) {
1586
1587 if ((*read_buff_ptr == '\n') || (*read_buff_ptr == '\r')) {
1588 *read_buff_ptr = (char) NULL;
1589 if (read_buff_word != read_buff_ptr) {
1590 if (!do_int_spell_fix(read_buff_word)) {
1591 read_buff_word = read_buff_ptr;
1592 break;
1593 }
1594 }
1595
1596 read_buff_word = read_buff_ptr + 1;
1597 }
1598
1599 read_buff_ptr++;
1600 }
1601
1602 /* special case where last word doesn't end with \n or \r */
1603 if (read_buff_word != read_buff_ptr)
1604 do_int_spell_fix(read_buff_word);
1605
Chris Allegretta271e9722000-11-10 18:15:43 +00001606 free(read_buff);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001607 replace_abort();
1608
Chris Allegretta271e9722000-11-10 18:15:43 +00001609 /* Process end of spell process */
1610
1611 wait(&spell_status);
1612 if (WIFEXITED(spell_status)) {
1613 if (WEXITSTATUS(spell_status) != 0)
1614 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001615 } else
Chris Allegretta271e9722000-11-10 18:15:43 +00001616 return FALSE;
1617
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001618 return TRUE;
1619}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001620
1621/* External spell checking */
Chris Allegretta271e9722000-11-10 18:15:43 +00001622int do_alt_speller(char *file_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001623{
Chris Allegrettab3655b42001-10-22 03:15:31 +00001624 int alt_spell_status, lineno_cur = current->lineno;
1625 int x_cur = current_x, y_cur = current_y, pww_cur = placewewant;
1626
Chris Allegretta271e9722000-11-10 18:15:43 +00001627 pid_t pid_spell;
Chris Allegretta169ee842001-01-26 01:57:32 +00001628 char *ptr;
1629 static int arglen = 3;
1630 static char **spellargs = (char **) NULL;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001631
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001632 endwin();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001633
Chris Allegrettae434b452001-01-27 19:25:00 +00001634 /* Set up an argument list to pass the execvp function */
1635 if (spellargs == NULL) {
1636 spellargs = nmalloc(arglen * sizeof(char *));
Chris Allegretta271e9722000-11-10 18:15:43 +00001637
Chris Allegrettae434b452001-01-27 19:25:00 +00001638 spellargs[0] = strtok(alt_speller, " ");
1639 while ((ptr = strtok(NULL, " ")) != NULL) {
1640 arglen++;
1641 spellargs = nrealloc(spellargs, arglen * sizeof(char *));
1642 spellargs[arglen - 3] = ptr;
Chris Allegretta169ee842001-01-26 01:57:32 +00001643 }
Chris Allegrettae434b452001-01-27 19:25:00 +00001644 spellargs[arglen - 1] = NULL;
1645 }
1646 spellargs[arglen - 2] = file_name;
1647
1648 /* Start a new process for the alternate speller */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001649 if ((pid_spell = fork()) == 0) {
Chris Allegretta169ee842001-01-26 01:57:32 +00001650
Chris Allegretta88520c92001-05-05 17:45:54 +00001651 /* Start alternate spell program; we are using the PATH here!?!? */
Chris Allegretta169ee842001-01-26 01:57:32 +00001652 execvp(spellargs[0], spellargs);
Chris Allegretta271e9722000-11-10 18:15:43 +00001653
1654 /* Should not be reached, if alternate speller is found!!! */
1655
1656 exit(1);
1657 }
1658
1659 /* Could not fork?? */
1660
1661 if (pid_spell < 0)
1662 return FALSE;
1663
1664 /* Wait for alternate speller to complete */
1665
1666 wait(&alt_spell_status);
1667 if (WIFEXITED(alt_spell_status)) {
1668 if (WEXITSTATUS(alt_spell_status) != 0)
1669 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001670 } else
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001671 return FALSE;
1672
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001673 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001674 free_filestruct(fileage);
Chris Allegretta56214c62001-09-27 02:46:53 +00001675 global_init(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001676 open_file(file_name, 0, 1);
Rocco Corsi4dfaf932001-04-20 01:59:55 +00001677
Chris Allegretta1b3381b2001-09-28 21:59:01 +00001678 /* go back to the old position, mark the file as modified, and make
1679 sure that the titlebar is refreshed */
1680 do_gotopos(lineno_cur, x_cur, y_cur, pww_cur);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001681 set_modified();
Chris Allegrettae1f14522001-09-19 03:19:43 +00001682 clearok(topwin, FALSE);
1683 titlebar(NULL);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001684
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001685 return TRUE;
1686}
1687#endif
1688
1689int do_spell(void)
1690{
1691
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001692#ifdef DISABLE_SPELLER
Chris Allegrettaff269f82000-12-01 18:46:01 +00001693 nano_disabled_msg();
1694 return (TRUE);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001695#else
Chris Allegretta271e9722000-11-10 18:15:43 +00001696 char *temp;
1697 int spell_res;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001698
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001699 if ((temp = safe_tempnam(0, "nano.")) == NULL) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001700 statusbar(_("Could not create a temporary filename: %s"),
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001701 strerror(errno));
Chris Allegretta271e9722000-11-10 18:15:43 +00001702 return 0;
1703 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001704
Chris Allegrettaecc3d7f2001-06-05 23:24:55 +00001705 if (write_file(temp, 1, 0, 0) == -1) {
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001706 statusbar(_("Spell checking failed: unable to write temp file!"));
Chris Allegrettabef12972002-03-06 03:30:40 +00001707 free(temp);
Chris Allegretta271e9722000-11-10 18:15:43 +00001708 return 0;
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001709 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001710
Chris Allegrettae1f14522001-09-19 03:19:43 +00001711#ifdef ENABLE_MULTIBUFFER
1712 /* update the current open_files entry before spell-checking, in case
1713 any problems occur; the case of there being no open_files entries
Chris Allegretta48b06702002-02-22 04:30:50 +00001714 is handled elsewhere (before we reach this point) */
1715 add_open_file(1);
Chris Allegrettae1f14522001-09-19 03:19:43 +00001716#endif
1717
Chris Allegretta271e9722000-11-10 18:15:43 +00001718 if (alt_speller)
1719 spell_res = do_alt_speller(temp);
1720 else
1721 spell_res = do_int_speller(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001722
Chris Allegretta271e9722000-11-10 18:15:43 +00001723 remove(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001724
1725 if (spell_res)
1726 statusbar(_("Finished checking spelling"));
1727 else
1728 statusbar(_("Spell checking failed"));
1729
Chris Allegrettabef12972002-03-06 03:30:40 +00001730 free(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001731 return spell_res;
1732
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001733#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001734}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001735
1736int do_exit(void)
1737{
1738 int i;
1739
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001740 if (!ISSET(MODIFIED)) {
1741
Chris Allegretta355fbe52001-07-14 19:32:47 +00001742#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001743 if (!close_open_file()) {
1744 display_main_list();
1745 return 1;
1746 }
1747 else
1748#endif
1749
1750 finish(0);
1751 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001752
Chris Allegretta30885552000-07-14 01:20:12 +00001753 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001754 i = 1;
1755 } else {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001756 i = do_yesno(0, 0,
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001757 _
1758 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1759 }
1760
1761#ifdef DEBUG
1762 dump_buffer(fileage);
1763#endif
1764
1765 if (i == 1) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001766 if (do_writeout(filename, 1, 0) > 0) {
1767
Chris Allegretta355fbe52001-07-14 19:32:47 +00001768#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001769 if (!close_open_file()) {
1770 display_main_list();
1771 return 1;
1772 }
1773 else
1774#endif
1775
1776 finish(0);
1777 }
1778 } else if (i == 0) {
1779
Chris Allegretta355fbe52001-07-14 19:32:47 +00001780#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001781 if (!close_open_file()) {
1782 display_main_list();
1783 return 1;
1784 }
1785 else
1786#endif
1787
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001788 finish(0);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001789 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001790 statusbar(_("Cancelled"));
1791
1792 display_main_list();
1793 return 1;
1794}
1795
Chris Allegretta84de5522001-04-12 14:51:48 +00001796#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001797#ifdef NCURSES_MOUSE_VERSION
1798void do_mouse(void)
1799{
1800 MEVENT mevent;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001801 int foo = 0, tab_found = 0;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001802 int currslen;
Chris Allegretta40639dd2002-03-04 12:25:34 +00001803 shortcut *s = currshortcut;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001804
1805 if (getmouse(&mevent) == ERR)
1806 return;
1807
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001808 /* If mouse not in edit or bottom window, return */
1809 if (wenclose(edit, mevent.y, mevent.x)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001810
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001811 /* Don't let people screw with the marker when they're in a
1812 subfunction */
1813 if (currshortcut != main_list)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001814 return;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001815
1816 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1817 mevent.y -= 2;
1818
1819 /* Selecting where the cursor is sets the mark.
1820 * Selecting beyond the line length with the cursor at the end of the
1821 * line sets the mark as well.
1822 */
1823 if ((mevent.y == current_y) &&
1824 ((mevent.x == current_x) || (current_x == strlen(current->data)
1825 && (mevent.x >
1826 strlen(current->data))))) {
1827 if (ISSET(VIEW_MODE)) {
1828 print_view_warning();
1829 return;
1830 }
1831 do_mark();
1832 } else if (mevent.y > current_y) {
1833 while (mevent.y > current_y) {
1834 if (current->next != NULL)
1835 current = current->next;
1836 else
1837 break;
1838 current_y++;
1839 }
1840 } else if (mevent.y < current_y) {
1841 while (mevent.y < current_y) {
1842 if (current->prev != NULL)
1843 current = current->prev;
1844 else
1845 break;
1846 current_y--;
1847 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001848 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001849 current_x = mevent.x;
1850 placewewant = current_x;
1851 while (foo < current_x) {
1852 if (current->data[foo] == NANO_CONTROL_I) {
1853 current_x -= tabsize - (foo % tabsize);
1854 tab_found = 1;
1855 } else if (current->data[foo] & 0x80);
1856 else if (current->data[foo] < 32)
1857 current_x--;
1858 foo++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001859 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001860 /* This is where tab_found comes in. I can't figure out why,
1861 * but without it any line with a tab will place the cursor
1862 * one character behind. Whatever, this fixes it. */
1863 if (tab_found == 1)
1864 current_x++;
1865
1866 if (current_x > strlen(current->data))
1867 current_x = strlen(current->data);
1868
1869 update_cursor();
1870 edit_refresh();
1871 } else if (wenclose(bottomwin, mevent.y, mevent.x) && !ISSET(NO_HELP)) {
Chris Allegrettaa951f212001-09-27 21:07:39 +00001872
Chris Allegretta40639dd2002-03-04 12:25:34 +00001873 int i, k;
Chris Allegrettaa951f212001-09-27 21:07:39 +00001874
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001875 if (currshortcut == main_list)
1876 currslen = MAIN_VISIBLE;
1877 else
1878 currslen = length_of_list(currshortcut);
1879
Chris Allegrettaa951f212001-09-27 21:07:39 +00001880 if (currslen < 2)
1881 k = COLS / 6;
1882 else
1883 k = COLS / ((currslen + (currslen %2)) / 2);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001884
1885 /* Determine what shortcut list was clicked */
1886 mevent.y -= (editwinrows + 3);
1887
1888 if (mevent.y < 0) /* They clicked on the statusbar */
1889 return;
1890
1891 /* Don't select stuff beyond list length */
1892 if (mevent.x / k >= currslen)
1893 return;
1894
Chris Allegretta40639dd2002-03-04 12:25:34 +00001895 for (i = 0; i < (mevent.x / k) * 2 + mevent.y; i++)
1896 s = s->next;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001897
1898 /* And ungetch that value */
Chris Allegretta40639dd2002-03-04 12:25:34 +00001899 ungetch(s->val);
Chris Allegretta6414b402001-09-21 03:21:11 +00001900
1901 /* And if it's an alt-key sequence, we should probably send alt
1902 too ;-) */
Chris Allegretta40639dd2002-03-04 12:25:34 +00001903 if (s->val >= 'a' && s->val <= 'z')
Chris Allegretta6414b402001-09-21 03:21:11 +00001904 ungetch(27);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001905 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001906}
1907#endif
1908#endif
1909
1910/* Handler for SIGHUP */
1911RETSIGTYPE handle_hup(int signal)
1912{
Chris Allegrettae7a58932000-12-02 02:36:22 +00001913 die(_("Received SIGHUP"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001914}
1915
Chris Allegretta18f8be02000-09-04 03:20:38 +00001916/* What do we do when we catch the suspend signal */
1917RETSIGTYPE do_suspend(int signal)
1918{
Chris Allegretta18f8be02000-09-04 03:20:38 +00001919 endwin();
Chris Allegretta521e00d2001-06-28 16:52:52 +00001920 printf("\n\n\n\n\nUse \"fg\" to return to nano\n");
1921 fflush(stdout);
1922
Chris Allegretta7b0667f2002-01-10 12:44:21 +00001923 /* Restore the terminal settings for the disabled keys */
1924 tcsetattr(0, TCSANOW, &oldterm);
1925
Chris Allegretta521e00d2001-06-28 16:52:52 +00001926 /* We used to re-enable the default SIG_DFL and raise SIGTSTP, but
1927 then we could be (and were) interrupted in the middle of the call.
1928 So we do it the mutt way instead */
1929 kill(0, SIGSTOP);
Chris Allegretta18f8be02000-09-04 03:20:38 +00001930}
1931
1932/* Restore the suspend handler when we come back into the prog */
1933RETSIGTYPE do_cont(int signal)
1934{
1935
Chris Allegretta521e00d2001-06-28 16:52:52 +00001936 /* Now we just update the screen instead of having to reenable the
1937 SIGTSTP handler */
1938
Chris Allegretta521e00d2001-06-28 16:52:52 +00001939 doupdate();
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00001940 /* The Hurd seems to need this, otherwise a ^Y after a ^Z will
1941 start suspending again */
1942 signal_init();
Chris Allegretta18f8be02000-09-04 03:20:38 +00001943}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001944
1945void handle_sigwinch(int s)
1946{
1947#ifndef NANO_SMALL
1948 char *tty = NULL;
1949 int fd = 0;
1950 int result = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001951 struct winsize win;
1952
1953 tty = ttyname(0);
1954 if (!tty)
1955 return;
1956 fd = open(tty, O_RDWR);
1957 if (fd == -1)
1958 return;
1959 result = ioctl(fd, TIOCGWINSZ, &win);
1960 if (result == -1)
1961 return;
1962
1963
1964 COLS = win.ws_col;
1965 LINES = win.ws_row;
1966
Chris Allegrettae61e8302001-01-14 05:18:27 +00001967 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1968 die_too_small();
1969
Chris Allegretta6fe61492001-05-21 12:56:25 +00001970#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettae61e8302001-01-14 05:18:27 +00001971 if ((fill = COLS - CHARS_FROM_EOL) < MIN_FILL_LENGTH)
1972 die_too_small();
Chris Allegretta6fe61492001-05-21 12:56:25 +00001973#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001974
Chris Allegretta0a06e072001-01-23 02:35:04 +00001975 hblank = nrealloc(hblank, COLS + 1);
1976 memset(hblank, ' ', COLS);
1977 hblank[COLS] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001978
Chris Allegretta618f5d72001-02-16 04:48:30 +00001979#ifdef HAVE_RESIZETERM
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001980 resizeterm(LINES, COLS);
1981#ifdef HAVE_WRESIZE
1982 if (wresize(topwin, 2, COLS) == ERR)
1983 die(_("Cannot resize top win"));
1984 if (mvwin(topwin, 0, 0) == ERR)
1985 die(_("Cannot move top win"));
1986 if (wresize(edit, editwinrows, COLS) == ERR)
1987 die(_("Cannot resize edit win"));
1988 if (mvwin(edit, 2, 0) == ERR)
1989 die(_("Cannot move edit win"));
1990 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1991 die(_("Cannot resize bottom win"));
1992 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1993 die(_("Cannot move bottom win"));
1994#endif /* HAVE_WRESIZE */
Chris Allegretta618f5d72001-02-16 04:48:30 +00001995#endif /* HAVE_RESIZETERM */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001996
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001997 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001998
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001999 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00002000 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002001 }
2002 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00002003
2004 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002005 refresh();
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002006 titlebar(NULL);
Chris Allegretta97accc62000-06-19 05:45:52 +00002007 edit_refresh();
2008 display_main_list();
Chris Allegretta08020882001-01-29 23:37:54 +00002009 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002010 total_refresh();
Chris Allegretta08020882001-01-29 23:37:54 +00002011
Chris Allegretta4e90c402001-01-29 23:40:43 +00002012 /* Turn cursor back on for sure */
2013 curs_set(1);
2014
Chris Allegretta08020882001-01-29 23:37:54 +00002015 /* Jump back to mainloop */
2016 siglongjmp(jmpbuf, 1);
2017
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002018#endif
2019}
2020
Chris Allegretta756f2202000-09-01 13:32:47 +00002021void signal_init(void)
2022{
Chris Allegrettaac899e52001-06-30 04:09:09 +00002023#ifdef _POSIX_VDISABLE
2024 struct termios term;
2025#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002026
Chris Allegretta88520c92001-05-05 17:45:54 +00002027 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
Chris Allegretta756f2202000-09-01 13:32:47 +00002028 memset(&act, 0, sizeof(struct sigaction));
2029 act.sa_handler = SIG_IGN;
2030 sigaction(SIGINT, &act, NULL);
Chris Allegretta756f2202000-09-01 13:32:47 +00002031
Chris Allegretta88520c92001-05-05 17:45:54 +00002032 /* Trap SIGHUP cuz we want to write the file out. */
Chris Allegretta756f2202000-09-01 13:32:47 +00002033 act.sa_handler = handle_hup;
2034 sigaction(SIGHUP, &act, NULL);
2035
2036 act.sa_handler = handle_sigwinch;
2037 sigaction(SIGWINCH, &act, NULL);
2038
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002039
2040#ifdef _POSIX_VDISABLE
2041 tcgetattr(0, &term);
2042
2043#ifdef VDSUSP
2044 term.c_cc[VDSUSP] = _POSIX_VDISABLE;
2045#endif /* VDSUSP */
2046
2047#endif /* _POSIX_VDISABLE */
2048
Chris Allegretta521e00d2001-06-28 16:52:52 +00002049 if (!ISSET(SUSPEND)) {
Chris Allegrettaac899e52001-06-30 04:09:09 +00002050
2051/* Insane! */
2052#ifdef _POSIX_VDISABLE
Chris Allegrettaac899e52001-06-30 04:09:09 +00002053 term.c_cc[VSUSP] = _POSIX_VDISABLE;
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002054#else
Chris Allegrettaac899e52001-06-30 04:09:09 +00002055 act.sa_handler = SIG_IGN;
Chris Allegretta521e00d2001-06-28 16:52:52 +00002056 sigaction(SIGTSTP, &act, NULL);
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002057#endif
Chris Allegrettaac899e52001-06-30 04:09:09 +00002058
Chris Allegretta521e00d2001-06-28 16:52:52 +00002059 } else {
2060 /* if we don't do this, it seems other stuff interrupts the
2061 suspend handler! Try using nano with mutt without this line */
2062 sigfillset(&act.sa_mask);
2063
2064 act.sa_handler = do_suspend;
2065 sigaction(SIGTSTP, &act, NULL);
2066
2067 act.sa_handler = do_cont;
2068 sigaction(SIGCONT, &act, NULL);
2069 }
2070
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002071
2072#ifdef _POSIX_VDISABLE
2073 tcsetattr(0, TCSANOW, &term);
2074#endif
2075
2076
Chris Allegretta756f2202000-09-01 13:32:47 +00002077}
2078
Chris Allegretta2a42af12000-09-12 23:02:49 +00002079void window_init(void)
2080{
Chris Allegrettae61e8302001-01-14 05:18:27 +00002081 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
2082 die_too_small();
Chris Allegretta92c9dd22000-09-13 14:03:27 +00002083
Chris Allegretta88520c92001-05-05 17:45:54 +00002084 /* Set up the main text window */
Chris Allegretta2a42af12000-09-12 23:02:49 +00002085 edit = newwin(editwinrows, COLS, 2, 0);
2086
2087 /* And the other windows */
2088 topwin = newwin(2, COLS, 0, 0);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002089 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002090
Chris Allegretta155d6202001-01-08 01:50:37 +00002091#ifdef PDCURSES
2092 /* Oops, I guess we need this again.
2093 Moved here so the keypad still works after a Meta-X, for example */
2094 keypad(edit, TRUE);
2095 keypad(bottomwin, TRUE);
2096#endif
2097
Chris Allegretta2a42af12000-09-12 23:02:49 +00002098}
2099
Chris Allegretta756f2202000-09-01 13:32:47 +00002100void mouse_init(void)
2101{
Chris Allegretta84de5522001-04-12 14:51:48 +00002102#ifndef DISABLE_MOUSE
Chris Allegretta756f2202000-09-01 13:32:47 +00002103#ifdef NCURSES_MOUSE_VERSION
2104 if (ISSET(USE_MOUSE)) {
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002105 keypad_on(edit, 1);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002106 keypad_on(bottomwin, 1);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002107
Chris Allegretta756f2202000-09-01 13:32:47 +00002108 mousemask(BUTTON1_RELEASED, NULL);
2109 mouseinterval(50);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00002110
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002111 } else
Chris Allegretta756f2202000-09-01 13:32:47 +00002112 mousemask(0, NULL);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002113
Chris Allegretta756f2202000-09-01 13:32:47 +00002114#endif
2115#endif
2116
2117}
2118
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002119int do_tab(void)
2120{
2121 do_char('\t');
2122 return 1;
2123}
2124
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002125#ifndef DISABLE_JUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002126int empty_line(const char *data)
2127{
2128 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002129 if (!isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002130 return 0;
2131
2132 data++;
2133 }
2134
2135 return 1;
2136}
2137
2138int no_spaces(const char *data)
2139{
2140 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002141 if (isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002142 return 0;
2143
2144 data++;
2145 }
2146
2147 return 1;
2148}
2149
2150void justify_format(char *data)
2151{
2152 int i = 0;
2153 int len = strlen(data);
2154
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002155 /* Skip leading whitespace. */
2156 for (i = 0; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002157 if (!isspace((int) data[i]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002158 break;
2159 }
2160
2161 i++; /* (i) is now at least 2. */
2162
2163 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
2164 for (; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002165 if (isspace((int) data[i]) && isspace((int) data[i - 1])
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002166 && (data[i - 2] != '.')
2167 && (data[i-2]!='!') && (data[i-2]!='?')) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002168 memmove(data + i, data + i + 1, len - i);
2169 len--;
2170 i--;
2171 }
2172 }
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002173 /* Skip trailing whitespace.
2174 * i<=len iff there was a non-space in the line. In that case, we
2175 * strip spaces from the end of the line. Note that "line" means the
2176 * whole paragraph. */
2177 if (i<=len) {
2178 for(i=len-1; i>0 && isspace((int) data[i]); i--);
2179 data[i+1] = '\0';
2180 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002181}
2182#endif
2183
2184int do_justify(void)
2185{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002186#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +00002187 nano_disabled_msg();
2188 return 1;
2189#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002190 int slen = 0; /* length of combined lines on one line. */
Chris Allegrettabef12972002-03-06 03:30:40 +00002191 int initial_y, kbinput = 0;
2192 long totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002193 filestruct *initial = NULL, *tmpjust = NULL, *cutbak, *tmptop, *tmpbot;
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002194 filestruct *samecheck = current;
2195 int qdepth = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002196
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002197 /* Compute quote depth level */
2198 while (!strncmp(&current->data[qdepth], quotestr, strlen(quotestr)))
2199 qdepth += strlen(quotestr);
2200
2201 if (empty_line(&current->data[qdepth])) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002202 /* Justify starting at first non-empty line. */
2203 do {
2204 if (!current->next)
2205 return 1;
2206
2207 current = current->next;
2208 current_y++;
2209 }
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002210 while (strlen(current->data) >= qdepth
2211 && !strncmp(current->data, samecheck->data, qdepth)
2212 && empty_line(&current->data[qdepth]));
2213
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002214 } else {
2215 /* Search back for the beginning of the paragraph, where
2216 * Paragraph is 1) A line with leading whitespace
2217 * or 2) A line following an empty line.
2218 */
2219 while (current->prev != NULL) {
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002220 if (strncmp(current->data, samecheck->data, qdepth)
2221
2222 /* Don't keep going back if the previous line is more
2223 intented quotestr-wise than samecheck */
2224 || !strncmp(&current->data[qdepth], quotestr, strlen(quotestr))
2225 || isspace((int) current->data[qdepth])
2226 || empty_line(&current->data[qdepth]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002227 break;
2228
2229 current = current->prev;
2230 current_y--;
2231 }
2232
2233 /* First line with leading whitespace may be empty. */
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002234 if (strncmp(current->data, samecheck->data, qdepth)
2235 || !strncmp(&current->data[qdepth], quotestr, strlen(quotestr))
2236 || empty_line(&current->data[qdepth])) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002237 if (current->next) {
2238 current = current->next;
2239 current_y++;
2240 } else
2241 return 1;
2242 }
2243 }
2244 initial = current;
2245 initial_y = current_y;
2246
2247 set_modified();
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002248 cutbak = cutbuffer; /* Got to like cutbak ;) */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002249 totbak = totsize;
Chris Allegretta9149e612000-11-27 00:23:41 +00002250 cutbuffer = NULL;
2251
2252 tmptop = current;
2253 tmpjust = copy_node(current);
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002254 samecheck = tmpjust;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002255
2256 /* This is annoying because it mucks with totsize */
Chris Allegretta9149e612000-11-27 00:23:41 +00002257 add_to_cutbuffer(tmpjust);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002258
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002259 /* Put the whole paragraph into one big line. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002260 while (current->next && !isspace((int) current->next->data[0])
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002261 && !strncmp(current->next->data, samecheck->data, qdepth)
Chris Allegretta46c1b9e2002-03-05 19:58:45 +00002262
2263 /* Don't continue if current->next is indented more! */
2264 && strncmp(&current->next->data[qdepth], quotestr, strlen(quotestr))
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002265 && !empty_line(&current->next->data[qdepth])) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002266 filestruct *tmpnode = current->next;
2267 int len = strlen(current->data);
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002268 int len2 = strlen(current->next->data) - qdepth;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002269
Chris Allegretta9149e612000-11-27 00:23:41 +00002270 tmpjust = NULL;
Chris Allegretta9149e612000-11-27 00:23:41 +00002271 tmpjust = copy_node(current->next);
2272 add_to_cutbuffer(tmpjust);
2273
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002274 /* Wiping out a newline */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002275 totsize--;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002276
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002277 /* length of both strings plus space between strings and ending \0. */
2278 current->data = nrealloc(current->data, len + len2 + 2);
2279 current->data[len++] = ' ';
2280 current->data[len] = '\0';
2281
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002282 strncat(current->data, &current->next->data[qdepth], len2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002283
2284 unlink_node(tmpnode);
2285 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002286 }
2287
2288 justify_format(current->data);
2289
2290 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002291 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002292
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002293 if ((strlenpt(current->data) > (fill))
Chris Allegrettacf1d8122002-03-21 19:53:36 +00002294 && !no_spaces(current->data + qdepth)) {
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002295 do {
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002296 int i = 0, j = 0;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002297 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002298
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002299
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002300/* The following code maybe could be better. In particular, can we
2301 * merely increment instead of calling strnlenpt for each new character?
2302 * In fact, can we assume the only tabs are at the beginning of the line?
2303 */
2304/* Note that we CAN break before the first word, since that is how
2305 * pico does it. */
2306 int last_space = -1; /* index of the last breakpoint */
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002307
Chris Allegrettacf1d8122002-03-21 19:53:36 +00002308 for(i=qdepth; i<slen; i++) {
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002309 if (isspace((int) current->data[i])) last_space = i;
2310 if (last_space!=-1 &&
Chris Allegrettacf1d8122002-03-21 19:53:36 +00002311 /* ARGH! We must look at the length of the first i+1 characters. */
2312 strnlenpt(current->data,i+1) > fill) {
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002313 i = last_space;
2314 break;
2315 }
2316 }
2317/* Now data[i] is a space. We want to break at the LAST space in this
2318 * group. Probably, the only possibility is two in a row, but let's be
2319 * generic. Note that we actually replace this final space with \0. Is
2320 * this okay? It seems to work fine. */
2321 for(; i<slen-1 && isspace((int) current->data[i+1]); i++) ;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002322
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002323 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002324
Chris Allegrettacf1d8122002-03-21 19:53:36 +00002325 slen -= i + 1 - qdepth; /* note i > qdepth */
2326 tmpline->data = charalloc(slen + 1);
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002327
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002328 for (j = 0; j < qdepth; j += strlen(quotestr))
2329 strcpy(&tmpline->data[j], quotestr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002330
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002331 /* Skip the white space in current. */
Chris Allegrettacf1d8122002-03-21 19:53:36 +00002332 memcpy(&tmpline->data[qdepth], current->data + i + 1, slen-qdepth);
2333 tmpline->data[slen] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002334
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002335 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002336
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002337 tmpline->prev = current;
2338 tmpline->next = current->next;
2339 if (current->next != NULL)
2340 current->next->prev = tmpline;
2341
2342 current->next = tmpline;
2343 current = tmpline;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002344 current_y++;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002345 } while ((strlenpt(current->data) > (fill))
Chris Allegrettacf1d8122002-03-21 19:53:36 +00002346 && !no_spaces(current->data + qdepth));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002347 }
Chris Allegretta9149e612000-11-27 00:23:41 +00002348 tmpbot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002349
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002350 if (current->next)
2351 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00002352 else
2353 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002354 current_x = 0;
2355 placewewant = 0;
2356
Adam Rogoyski09f97962000-06-20 02:50:33 +00002357 renumber(initial);
2358 totlines = filebot->lineno;
2359
2360 werase(edit);
2361
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002362 if ((current_y < 0) || (current_y >= editwinrows - 1)
2363 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00002364 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002365 center_cursor();
2366 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00002367 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002368 }
2369
Adam Rogoyski09f97962000-06-20 02:50:33 +00002370 edit_refresh();
Chris Allegretta9149e612000-11-27 00:23:41 +00002371 statusbar(_("Can now UnJustify!"));
Chris Allegretta07798352000-11-27 22:58:23 +00002372 /* Change the shortcut list to display the unjustify code */
2373 shortcut_init(1);
2374 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002375 reset_cursor();
2376
Chris Allegretta88520c92001-05-05 17:45:54 +00002377 /* Now get a keystroke and see if it's unjustify; if not, unget the keystroke
Chris Allegretta9149e612000-11-27 00:23:41 +00002378 and return */
Chris Allegretta5f071802001-05-06 02:34:31 +00002379
2380#ifndef DISABLE_MOUSE
2381#ifdef NCURSES_MOUSE_VERSION
2382
2383 /* If it was a mouse click, parse it with do_mouse and it might become
2384 the unjustify key. Else give it back to the input stream. */
2385 if ((kbinput = wgetch(edit)) == KEY_MOUSE)
2386 do_mouse();
2387 else
2388 ungetch(kbinput);
2389#endif
2390#endif
2391
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002392 if ((kbinput = wgetch(edit)) != NANO_UNJUSTIFY_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002393 ungetch(kbinput);
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002394 blank_statusbar_refresh();
2395 } else {
Chris Allegretta9149e612000-11-27 00:23:41 +00002396 /* Else restore the justify we just did (ungrateful user!) */
2397 if (tmptop->prev != NULL)
2398 tmptop->prev->next = tmpbot->next;
Chris Allegrettad022eac2000-11-27 02:50:49 +00002399 else
2400 fileage = current;
Chris Allegretta9149e612000-11-27 00:23:41 +00002401 tmpbot->next->prev = tmptop->prev;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002402 current = tmpbot->next;
Chris Allegretta9149e612000-11-27 00:23:41 +00002403 tmpbot->next = NULL;
2404 do_uncut_text();
Chris Allegrettad022eac2000-11-27 02:50:49 +00002405 if (tmptop->prev == NULL)
2406 edit_refresh();
2407
Chris Allegretta88520c92001-05-05 17:45:54 +00002408 /* Restore totsize from before justify */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002409 totsize = totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002410 free_filestruct(tmptop);
2411 blank_statusbar_refresh();
2412 }
Chris Allegretta4a9c8582000-11-27 22:59:40 +00002413 shortcut_init(0);
2414 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002415 free_filestruct(cutbuffer);
2416 cutbuffer = cutbak;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002417
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002418 return 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002419#endif
2420}
2421
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002422#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002423void help_init(void)
2424{
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002425 int i, sofar = 0, meta_shortcut = 0, helplen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002426 long allocsize = 1; /* How much space we're gonna need for the help text */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002427 char buf[BUFSIZ] = "", *ptr = NULL;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002428 toggle *t;
2429 shortcut *s;
Chris Allegrettab3655b42001-10-22 03:15:31 +00002430
Chris Allegretta7e65d2f2002-02-15 21:12:52 +00002431 helplen = length_of_list(currshortcut);
Chris Allegretta13fd44b2002-01-02 13:59:11 +00002432
Chris Allegrettab3655b42001-10-22 03:15:31 +00002433 /* First set up the initial help text for the current function */
2434 if (currshortcut == whereis_list || currshortcut == replace_list
2435 || currshortcut == replace_list_2)
2436 ptr = _("Search Command Help Text\n\n "
2437 "Enter the words or characters you would like to search "
2438 "for, then hit enter. If there is a match for the text you "
2439 "entered, the screen will be updated to the location of the "
Jordi Mallach773623c2001-10-28 21:00:49 +00002440 "nearest match for the search string.\n\n "
2441 "If using Pico Mode via the -p or --pico flags, using the "
2442 "Meta-P toggle or using a nanorc file, the previous search "
2443 "string will be shown in brackets after the Search: prompt. "
Jordi Mallachf4e57292001-12-26 00:16:40 +00002444 "Hitting enter without entering any text will perform the "
Jordi Mallach773623c2001-10-28 21:00:49 +00002445 "previous search. Otherwise, the previous string will be "
2446 "placed in front of the cursor, and can be edited or deleted "
2447 "before hitting enter.\n\n The following functions keys are "
2448 "available in Search mode:\n\n");
Chris Allegrettab3655b42001-10-22 03:15:31 +00002449 else if (currshortcut == goto_list)
2450 ptr = _("Goto Line Help Text\n\n "
2451 "Enter the line number that you wish to go to and hit "
Jordi Mallach773623c2001-10-28 21:00:49 +00002452 "Enter. If there are fewer lines of text than the "
Chris Allegrettab3655b42001-10-22 03:15:31 +00002453 "number you entered, you will be brought to the last line "
2454 "of the file.\n\n The following functions keys are "
2455 "available in Goto Line mode:\n\n");
2456 else if (currshortcut == insertfile_list)
2457 ptr = _("Insert File Help Text\n\n "
2458 "Type in the name of a file to be inserted into the current "
2459 "file buffer at the current cursor location.\n\n "
2460 "If you have compiled nano with multiple file buffer "
2461 "support, and enable multiple buffers with the -F "
Jordi Mallach773623c2001-10-28 21:00:49 +00002462 "or --multibuffer command line flags, the Meta-F toggle or "
2463 "using a nanorc file, inserting a file will cause it to be "
Chris Allegretta180a5692002-01-02 14:30:33 +00002464 "loaded into a separate buffer (use Meta-< and > to switch "
Chris Allegretta48b06702002-02-22 04:30:50 +00002465 "between file buffers).\n\n If you need another blank "
Chris Allegrettab479c892002-03-09 20:03:10 +00002466 "buffer, do not enter any filename, or type in a "
2467 "nonexistent filename at the prompt and press "
2468 "Enter.\n\n The following function keys are "
Chris Allegretta48b06702002-02-22 04:30:50 +00002469 "available in Insert File mode:\n\n");
Chris Allegrettab3655b42001-10-22 03:15:31 +00002470 else if (currshortcut == writefile_list)
2471 ptr = _("Write File Help Text\n\n "
2472 "Type the name that you wish to save the current file "
2473 "as and hit enter to save the file.\n\n "
2474 "If you are using the marker code with Ctrl-^ and have "
2475 "selected text, you will be prompted to save only the "
2476 "selected portion to a separate file. To reduce the "
2477 "chance of overwriting the current file with just a portion "
2478 "of it, the current filename is not the default in this "
2479 "mode.\n\n The following function keys are available in "
2480 "Write File mode:\n\n");
2481#ifndef DISABLE_BROWSER
2482 else if (currshortcut == browser_list)
2483 ptr = _("File Browser Help Text\n\n "
2484 "The file browser is used to visually browse the "
2485 "directory structure to select a file for reading "
2486 "or writing. You may use the arrow keys or Page Up/"
2487 "Down to browse through the files, and S or Enter to "
2488 "choose the selected file or enter the selected "
2489 "directory. To move up one level, select the directory "
2490 "called \"..\" at the top of the file list.\n\n The "
2491 "following functions keys are available in the file "
2492 "browser:\n\n");
2493 else if (currshortcut == gotodir_list)
2494 ptr = _("Browser Goto Directory Help Text\n\n "
2495 "Enter the name of the directory you would like to "
2496 "browse to.\n\n If tab completion has not been disabled, "
2497 "you can use the TAB key to (attempt to) automatically "
Chris Allegretta1f8394d2002-03-09 19:58:18 +00002498 "complete the directory name.\n\n The following function "
Chris Allegrettab3655b42001-10-22 03:15:31 +00002499 "keys are available in Browser GotoDir mode:\n\n");
2500#endif
2501 else if (currshortcut == spell_list)
2502 ptr = _("Spell Check Help Text\n\n "
2503 "The spell checker checks the spelling of all text "
2504 "in the current file. When an unknown word is "
2505 "encountered, it is highlighted and a replacement can "
2506 "be edited. It will then prompt to replace every "
2507 "instance of the given misspelled word in the "
2508 "current file.\n\n The following other functions are "
2509 "available in Spell Check mode:\n\n");
Chris Allegretta52c5a6e2002-03-21 05:07:28 +00002510#ifndef NANO_SMALL
2511 else if (currshortcut == extcmd_list)
2512 ptr = _("External Command Help Text\n\n "
2513 "This menu allows you to insert the output of a command "
2514 "run by the shell into the current buffer (or a new "
2515 "buffer in multibuffer mode).\n\n The following keys are "
2516 "available in this mode:\n\n");
2517#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00002518 else /* Default to the main help list */
2519 ptr = help_text_init;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002520
2521 /* Compute the space needed for the shortcut lists - we add 15 to
2522 have room for the shortcut abbrev and its possible alternate keys */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002523 s = currshortcut;
2524 for (i = 0; i <= helplen - 1; i++) {
2525 if (s->help != NULL)
2526 allocsize += strlen(s->help) + 15;
2527 s = s->next;
2528 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002529
Chris Allegrettab3655b42001-10-22 03:15:31 +00002530 /* If we're on the main list, we also allocate space for toggle help text. */
2531 if (currshortcut == main_list) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002532 for (t = toggles; t != NULL; t = t->next)
2533 if (t->desc != NULL)
2534 allocsize += strlen(t->desc) + 30;
Chris Allegrettab3655b42001-10-22 03:15:31 +00002535 }
2536
2537 allocsize += strlen(ptr);
2538
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002539 if (help_text != NULL)
2540 free(help_text);
2541
2542 /* Allocate space for the help text */
Chris Allegretta88b09152001-05-17 11:35:43 +00002543 help_text = charalloc(allocsize);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002544
2545 /* Now add the text we want */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002546 strcpy(help_text, ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002547
2548 /* Now add our shortcut info */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002549 s = currshortcut;
Chris Allegretta13fd44b2002-01-02 13:59:11 +00002550 for (i = 0; i <= helplen - 1; i++) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002551 if (s->val > 0 && s->val < 'a')
2552 sofar = snprintf(buf, BUFSIZ, "^%c ", s->val + 64);
2553 else {
2554 if (s->altval > 0) {
2555 sofar = 0;
2556 meta_shortcut = 1;
2557 }
2558 else
2559 sofar = snprintf(buf, BUFSIZ, " ");
2560 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002561
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002562 if (!meta_shortcut) {
2563 if (s->misc1 > KEY_F0 && s->misc1 <= KEY_F(64))
2564 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
2565 s->misc1 - KEY_F0);
2566 else
2567 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
2568 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002569
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002570 if (s->altval > 0 && s->altval < 91
2571 && (s->altval - 32) > 32)
2572 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2573 (meta_shortcut ? "M-%c " : "(M-%c) "),
2574 s->altval - 32);
Chris Allegretta5902f962002-03-07 12:40:39 +00002575 else if (s->altval >= 'a')
2576 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2577 (meta_shortcut ? "M-%c " : "(M-%c) "),
2578 s->altval - 32);
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002579 else if (s->altval > 0)
2580 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2581 (meta_shortcut ? "M-%c " : "(M-%c) "),
2582 s->altval);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002583 /* Hack */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002584 else if (s->val >= 'a')
2585 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2586 (meta_shortcut ? "(M-%c) " : "M-%c "),
2587 s->val - 32);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002588 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002589 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002590
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002591 if (meta_shortcut) {
2592 if (s->misc1 > KEY_F0 && s->misc1 <= KEY_F(64))
2593 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2594 "(F%d) ", s->misc1 - KEY_F0);
2595 else
2596 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2597 " ");
2598 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002599
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002600 if (s->help != NULL)
2601 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", s->help);
Chris Allegretta756f2202000-09-01 13:32:47 +00002602
2603 strcat(help_text, buf);
2604 strcat(help_text, "\n");
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002605
2606 s = s->next;
Chris Allegretta756f2202000-09-01 13:32:47 +00002607 }
2608
2609 /* And the toggles... */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002610 if (currshortcut == main_list)
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002611 for (t = toggles; t != NULL; t = t->next) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00002612 sofar = snprintf(buf, BUFSIZ,
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002613 "M-%c ", t->val - 32);
2614 if (t->desc != NULL) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00002615 snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002616 t->desc);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002617 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002618 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00002619 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002620 }
2621
2622}
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002623#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002624
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002625void do_toggle(toggle *which)
Chris Allegretta756f2202000-09-01 13:32:47 +00002626{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002627#ifdef NANO_SMALL
2628 nano_disabled_msg();
2629#else
Jordi Mallach2dc0f6b2000-09-07 10:48:00 +00002630 char *enabled = _("enabled");
2631 char *disabled = _("disabled");
Chris Allegrettaf0f63a82000-09-02 18:44:21 +00002632
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002633 switch (which->val) {
Chris Allegretta8d990b52001-09-22 22:14:25 +00002634 case TOGGLE_BACKWARDS_KEY:
2635 case TOGGLE_CASE_KEY:
2636 case TOGGLE_REGEXP_KEY:
2637 return;
2638 }
Chris Allegretta8d990b52001-09-22 22:14:25 +00002639
Chris Allegretta658399a2001-06-14 02:54:22 +00002640 /* Even easier! */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002641 TOGGLE(which->flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002642
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002643 switch (which->val) {
Chris Allegretta756f2202000-09-01 13:32:47 +00002644 case TOGGLE_PICOMODE_KEY:
Chris Allegretta07798352000-11-27 22:58:23 +00002645 shortcut_init(0);
Chris Allegrettac1049ac2001-08-17 00:03:46 +00002646 SET(CLEAR_BACKUPSTRING);
Chris Allegretta756f2202000-09-01 13:32:47 +00002647 display_main_list();
2648 break;
2649 case TOGGLE_SUSPEND_KEY:
2650 signal_init();
2651 break;
2652 case TOGGLE_MOUSE_KEY:
2653 mouse_init();
2654 break;
2655 case TOGGLE_NOHELP_KEY:
Chris Allegretta2a42af12000-09-12 23:02:49 +00002656 wclear(bottomwin);
2657 wrefresh(bottomwin);
2658 window_init();
Chris Allegrettaaffeda82000-12-18 04:03:48 +00002659 fix_editbot();
Chris Allegretta2a42af12000-09-12 23:02:49 +00002660 edit_refresh();
2661 display_main_list();
Chris Allegretta756f2202000-09-01 13:32:47 +00002662 break;
Chris Allegretta99e30e12001-09-23 02:45:27 +00002663 case TOGGLE_DOS_KEY:
2664 UNSET(MAC_FILE);
2665 break;
2666 case TOGGLE_MAC_KEY:
2667 UNSET(DOS_FILE);
2668 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002669 }
Chris Allegretta2a42af12000-09-12 23:02:49 +00002670
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002671 if (!ISSET(which->flag)) {
2672 if (which->val == TOGGLE_NOHELP_KEY ||
2673 which->val == TOGGLE_WRAP_KEY)
2674 statusbar("%s %s", which->desc, enabled);
Chris Allegretta819e3db2001-07-11 02:37:19 +00002675 else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002676 statusbar("%s %s", which->desc, disabled);
Chris Allegretta819e3db2001-07-11 02:37:19 +00002677 } else {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002678 if (which->val == TOGGLE_NOHELP_KEY ||
2679 which->val == TOGGLE_WRAP_KEY)
2680 statusbar("%s %s", which->desc, disabled);
Chris Allegretta819e3db2001-07-11 02:37:19 +00002681 else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002682 statusbar("%s %s", which->desc, enabled);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002683 }
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002684
Chris Allegretta756f2202000-09-01 13:32:47 +00002685#endif
2686}
2687
Chris Allegretta88520c92001-05-05 17:45:54 +00002688/* If the NumLock key has made the keypad go awry, print an error
2689 message; hopefully we can address it later. */
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002690void print_numlock_warning(void)
2691{
2692 static int didmsg = 0;
2693 if (!didmsg) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002694 statusbar(_
2695 ("NumLock glitch detected. Keypad will malfunction with NumLock off"));
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002696 didmsg = 1;
2697 }
2698}
2699
Chris Allegretta1748cd12001-01-13 17:22:54 +00002700/* This function returns the correct keystroke, given the A,B,C or D
2701 input key. This is a common sequence of many terms which send
2702 Esc-O-[A-D] or Esc-[-[A-D]. */
2703int ABCD(int input)
2704{
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002705 switch (input) {
2706 case 'A':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002707 case 'a':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002708 return (KEY_UP);
2709 case 'B':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002710 case 'b':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002711 return (KEY_DOWN);
2712 case 'C':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002713 case 'c':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002714 return (KEY_RIGHT);
2715 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002716 case 'd':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002717 return (KEY_LEFT);
2718 default:
2719 return 0;
Chris Allegretta1748cd12001-01-13 17:22:54 +00002720 }
2721}
2722
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002723int main(int argc, char *argv[])
2724{
2725 int optchr;
2726 int kbinput; /* Input from keyboard */
2727 long startline = 0; /* Line to try and start at */
Chris Allegretta08020882001-01-29 23:37:54 +00002728 int keyhandled; /* Have we handled the keystroke yet? */
Chris Allegretta9caa1932002-02-15 20:08:05 +00002729 int modify_control_seq;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002730 char *argv0;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002731 shortcut *s;
Chris Allegretta40ecbad2002-03-06 15:27:44 +00002732#ifndef NANO_SMALL
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002733 toggle *t;
Chris Allegretta40ecbad2002-03-06 15:27:44 +00002734#endif
Chris Allegretta0357c4d2001-09-19 02:59:25 +00002735
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002736#ifdef _POSIX_VDISABLE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002737 struct termios term;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002738#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002739
2740#ifdef HAVE_GETOPT_LONG
2741 int option_index = 0;
2742 struct option long_options[] = {
Chris Allegretta805c26d2000-09-06 13:39:17 +00002743#ifdef HAVE_REGEX_H
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002744 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00002745#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002746 {"version", 0, 0, 'V'},
2747 {"const", 0, 0, 'c'},
2748 {"suspend", 0, 0, 'z'},
2749 {"nowrap", 0, 0, 'w'},
2750 {"nohelp", 0, 0, 'x'},
2751 {"help", 0, 0, 'h'},
Chris Allegretta7492cec2000-12-18 04:55:21 +00002752 {"view", 0, 0, 'v'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002753#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002754 {"cut", 0, 0, 'k'},
Chris Allegretta7004c282001-09-22 00:42:10 +00002755 {"dos", 0, 0, 'D'},
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002756 {"mac", 0, 0, 'M'},
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002757 {"noconvert", 0, 0, 'N'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002758 {"autoindent", 0, 0, 'i'},
Chris Allegrettaff989832001-09-17 13:48:00 +00002759#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002760 {"tempfile", 0, 0, 't'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002761#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002762 {"speller", 1, 0, 's'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002763#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00002764
2765#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002766 {"fill", 1, 0, 'r'},
Chris Allegretta6fe61492001-05-21 12:56:25 +00002767#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002768 {"mouse", 0, 0, 'm'},
Chris Allegrettae1f14522001-09-19 03:19:43 +00002769#ifndef DISABLE_OPERATINGDIR
2770 {"operatingdir", 1, 0, 'o'},
2771#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002772 {"pico", 0, 0, 'p'},
2773 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00002774 {"tabsize", 1, 0, 'T'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002775
Chris Allegretta355fbe52001-07-14 19:32:47 +00002776#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002777 {"multibuffer", 0, 0, 'F'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002778#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002779#ifndef NANO_SMALL
2780 {"smooth", 0, 0, 'S'},
2781#endif
Chris Allegretta48bd3782002-01-03 21:26:34 +00002782 {"keypad", 0, 0, 'K'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002783 {0, 0, 0, 0}
2784 };
2785#endif
2786
2787 /* Flag inits... */
2788 SET(FOLLOW_SYMLINKS);
2789
2790#ifndef NANO_SMALL
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002791#ifdef ENABLE_NLS
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002792 setlocale(LC_ALL, "");
2793 bindtextdomain(PACKAGE, LOCALEDIR);
2794 textdomain(PACKAGE);
2795#endif
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002796#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002797
Chris Allegretta8d8e0122001-04-18 04:28:54 +00002798#ifdef ENABLE_NANORC
2799 do_rcfile();
2800#endif /* ENABLE_NANORC */
2801
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002802#ifdef HAVE_GETOPT_LONG
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002803 while ((optchr = getopt_long(argc, argv, "h?DFKMNQ:RST:Vabcefgijklmo:pr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002804 long_options, &option_index)) != EOF) {
2805#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002806 while ((optchr =
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002807 getopt(argc, argv, "h?DFKMNQ:RST:Vabcefgijklmo:pr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002808#endif
2809
2810 switch (optchr) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002811
Chris Allegretta7004c282001-09-22 00:42:10 +00002812#ifndef NANO_SMALL
2813 case 'D':
2814 SET(DOS_FILE);
2815 break;
2816#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +00002817#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002818 case 'F':
Chris Allegretta355fbe52001-07-14 19:32:47 +00002819 SET(MULTIBUFFER);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002820 break;
2821#endif
Chris Allegretta48bd3782002-01-03 21:26:34 +00002822 case 'K':
2823 SET(ALT_KEYPAD);
2824 break;
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002825#ifndef NANO_SMALL
2826 case 'M':
2827 SET(MAC_FILE);
2828 break;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002829 case 'N':
2830 SET(NO_CONVERT);
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002831 break;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002832#endif
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002833 case 'Q':
2834#ifndef DISABLE_JUSTIFY
2835 quotestr = optarg;
2836 break;
2837#else
2838 usage(); /* To stop bogus data for tab width */
2839 finish(1);
2840#endif
Chris Allegretta805c26d2000-09-06 13:39:17 +00002841#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +00002842 case 'R':
2843 SET(USE_REGEXP);
2844 break;
Chris Allegretta47805612000-07-07 02:35:34 +00002845#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002846#ifndef NANO_SMALL
2847 case 'S':
2848 SET(SMOOTHSCROLL);
2849 break;
2850#endif
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002851 case 'T':
2852 tabsize = atoi(optarg);
2853 if (tabsize <= 0) {
2854 usage(); /* To stop bogus data for tab width */
2855 finish(1);
2856 }
2857 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002858 case 'V':
2859 version();
2860 exit(0);
Chris Allegrettae1f14522001-09-19 03:19:43 +00002861 case 'a':
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002862 case 'b':
2863 case 'e':
2864 case 'f':
Rocco Corsi12f294c2001-04-14 06:50:24 +00002865 case 'g':
2866 case 'j':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002867 /* Pico compatibility flags */
2868 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002869 case 'c':
2870 SET(CONSTUPDATE);
2871 break;
2872 case 'h':
2873 case '?':
2874 usage();
2875 exit(0);
Chris Allegrettaff989832001-09-17 13:48:00 +00002876#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002877 case 'i':
2878 SET(AUTOINDENT);
2879 break;
Chris Allegretta627de192000-07-12 02:09:17 +00002880 case 'k':
2881 SET(CUT_TO_END);
2882 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002883#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002884 case 'l':
2885 UNSET(FOLLOW_SYMLINKS);
2886 break;
2887 case 'm':
2888 SET(USE_MOUSE);
2889 break;
Chris Allegrettae1f14522001-09-19 03:19:43 +00002890#ifndef DISABLE_OPERATINGDIR
2891 case 'o':
2892 operating_dir = charalloc(strlen(optarg) + 1);
2893 strcpy(operating_dir, optarg);
2894
2895 /* make sure we're inside the operating directory */
2896 if (check_operating_dir(".", 0)) {
2897 if (chdir(operating_dir) == -1) {
2898 free(operating_dir);
2899 operating_dir = NULL;
2900 }
2901 }
2902 break;
2903#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002904 case 'p':
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002905 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002906 break;
2907 case 'r':
Chris Allegretta6fe61492001-05-21 12:56:25 +00002908#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002909 fill = atoi(optarg);
Chris Allegretta6fe61492001-05-21 12:56:25 +00002910 if (fill < 0)
2911 wrap_at = fill;
2912 else if (fill == 0) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002913 usage(); /* To stop bogus data (like a string) */
2914 finish(1);
2915 }
2916 break;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002917#else
2918 usage();
2919 exit(0);
2920
2921#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002922#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002923 case 's':
Chris Allegretta88b09152001-05-17 11:35:43 +00002924 alt_speller = charalloc(strlen(optarg) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002925 strcpy(alt_speller, optarg);
2926 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002927#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002928 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00002929 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002930 break;
2931 case 'v':
2932 SET(VIEW_MODE);
2933 break;
2934 case 'w':
Chris Allegrettacef7fbb2001-04-02 05:36:08 +00002935#ifdef DISABLE_WRAPPING
2936 usage();
2937 exit(0);
2938#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002939 SET(NO_WRAP);
2940 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002941#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002942 case 'x':
2943 SET(NO_HELP);
2944 break;
2945 case 'z':
2946 SET(SUSPEND);
2947 break;
2948 default:
2949 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002950 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002951 }
2952
2953 }
2954
2955 argv0 = strrchr(argv[0], '/');
2956 if ((argv0 && strstr(argv0, "pico"))
2957 || (!argv0 && strstr(argv[0], "pico")))
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002958 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002959
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002960 /* See if there's a non-option in argv (first non-option is the
2961 filename, if +LINE is not given) */
2962 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002963 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002964 else {
2965 /* Look for the +line flag... */
2966 if (argv[optind][0] == '+') {
2967 startline = atoi(&argv[optind][1]);
2968 optind++;
2969 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002970 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002971 else
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002972 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002973
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002974 } else
2975 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002976 }
2977
2978
2979 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002980 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002981
Chris Allegretta9239d742000-09-06 15:19:18 +00002982#ifdef _POSIX_VDISABLE
Chris Allegretta8f6c0692000-07-19 01:16:18 +00002983 term = oldterm;
2984 term.c_cc[VINTR] = _POSIX_VDISABLE;
2985 term.c_cc[VQUIT] = _POSIX_VDISABLE;
2986 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002987 tcsetattr(0, TCSANOW, &term);
Chris Allegretta9239d742000-09-06 15:19:18 +00002988#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002989
2990 /* now ncurses init stuff... */
2991 initscr();
2992 savetty();
2993 nonl();
2994 cbreak();
2995 noecho();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002996
2997 /* Set up some global variables */
Chris Allegretta56214c62001-09-27 02:46:53 +00002998 global_init(0);
Chris Allegretta07798352000-11-27 22:58:23 +00002999 shortcut_init(0);
Rocco Corsiaf5c3022001-01-12 07:51:05 +00003000#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003001 init_help_msg();
3002 help_init();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00003003#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00003004 signal_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003005
3006#ifdef DEBUG
3007 fprintf(stderr, _("Main: set up windows\n"));
3008#endif
3009
Chris Allegretta2a42af12000-09-12 23:02:49 +00003010 window_init();
Chris Allegretta756f2202000-09-01 13:32:47 +00003011 mouse_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003012
Chris Allegretta48bd3782002-01-03 21:26:34 +00003013 if (!ISSET(ALT_KEYPAD)) {
3014 keypad(edit, TRUE);
3015 keypad(bottomwin, TRUE);
3016 }
3017
Chris Allegretta08893e02001-11-29 02:42:27 +00003018#ifdef ENABLE_COLOR
3019 do_colorinit();
3020
Chris Allegretta08893e02001-11-29 02:42:27 +00003021#endif /* ENABLE_COLOR */
3022
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003023#ifdef DEBUG
3024 fprintf(stderr, _("Main: bottom win\n"));
3025#endif
Chris Allegretta88520c92001-05-05 17:45:54 +00003026 /* Set up bottom of window */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003027 display_main_list();
3028
3029#ifdef DEBUG
3030 fprintf(stderr, _("Main: open file\n"));
3031#endif
3032
Chris Allegrettaf4b96012001-01-03 07:11:47 +00003033 titlebar(NULL);
Chris Allegretta31c76662000-11-21 06:20:20 +00003034
3035 /* Now we check to see if argv[optind] is non-null to determine if
3036 we're dealing with a new file or not, not argc == 1... */
3037 if (argv[optind] == NULL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003038 new_file();
3039 else
3040 open_file(filename, 0, 0);
3041
3042 if (startline > 0)
Chris Allegretta2d7893d2001-07-11 02:08:33 +00003043 do_gotoline(startline, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003044 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00003045 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003046
Chris Allegretta08020882001-01-29 23:37:54 +00003047 /* return here after a sigwinch */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003048 sigsetjmp(jmpbuf, 1);
Chris Allegretta08020882001-01-29 23:37:54 +00003049
3050 /* Fix clobber-age */
3051 kbinput = 0;
3052 keyhandled = 0;
3053 modify_control_seq = 0;
3054
Robert Siemborski6967eec2000-07-08 14:23:32 +00003055 edit_refresh();
3056 reset_cursor();
3057
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003058 while (1) {
Chris Allegretta9239d742000-09-06 15:19:18 +00003059
Chris Allegretta6fe61492001-05-21 12:56:25 +00003060#ifndef DISABLE_MOUSE
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003061 currshortcut = main_list;
Chris Allegretta6fe61492001-05-21 12:56:25 +00003062#endif
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003063
Chris Allegretta9239d742000-09-06 15:19:18 +00003064#ifndef _POSIX_VDISABLE
3065 /* We're going to have to do it the old way, i.e. on cygwin */
3066 raw();
3067#endif
3068
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003069 kbinput = wgetch(edit);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003070#ifdef DEBUG
3071 fprintf(stderr, "AHA! %c (%d)\n", kbinput, kbinput);
3072#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003073
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003074 if (kbinput == 27) { /* Grab Alt-key stuff first */
3075 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003076 /* Alt-O, suddenly very important ;) */
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003077 case 'O':
Chris Allegretta16e41682000-09-11 22:33:54 +00003078 kbinput = wgetch(edit);
Chris Allegretta316e4d92001-04-28 16:31:19 +00003079 if ((kbinput <= 'D' && kbinput >= 'A') ||
3080 (kbinput <= 'd' && kbinput >= 'a'))
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003081 kbinput = ABCD(kbinput);
Chris Allegretta201d9bf2001-01-14 03:17:53 +00003082 else if (kbinput <= 'z' && kbinput >= 'j')
3083 print_numlock_warning();
3084 else if (kbinput <= 'S' && kbinput >= 'P')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003085 kbinput = KEY_F(kbinput - 79);
Chris Allegretta16e41682000-09-11 22:33:54 +00003086#ifdef DEBUG
3087 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003088 fprintf(stderr, _("I got Alt-O-%c! (%d)\n"),
3089 kbinput, kbinput);
3090 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003091 }
3092#endif
3093 break;
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003094 case 27:
3095 /* If we get Alt-Alt, the next keystroke should be the same as a
3096 control sequence */
3097 modify_control_seq = 1;
3098 keyhandled = 1;
3099 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00003100#ifndef NANO_SMALL
Chris Allegretta76e291b2001-10-14 19:05:10 +00003101 case ' ':
3102 /* If control-space is next word, Alt-space should be previous word */
3103 do_prev_word();
3104 keyhandled = 1;
3105 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00003106#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003107 case '[':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003108 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003109 case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */
Chris Allegretta16e41682000-09-11 22:33:54 +00003110 kbinput = wgetch(edit);
3111 if (kbinput >= '1' && kbinput <= '5') {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003112 kbinput = KEY_F(kbinput - 48);
3113 wgetch(edit);
3114 } else if (kbinput >= '7' && kbinput <= '9') {
3115 kbinput = KEY_F(kbinput - 49);
3116 wgetch(edit);
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003117 } else if (kbinput == '~')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003118 kbinput = KEY_HOME;
Chris Allegretta16e41682000-09-11 22:33:54 +00003119
3120#ifdef DEBUG
3121 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003122 fprintf(stderr, _("I got Alt-[-1-%c! (%d)\n"),
3123 kbinput, kbinput);
3124 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003125 }
3126#endif
3127
3128 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003129 case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */
Chris Allegretta16e41682000-09-11 22:33:54 +00003130 kbinput = wgetch(edit);
Chris Allegretta16e41682000-09-11 22:33:54 +00003131 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003132 case '0':
3133 kbinput = KEY_F(9);
3134 wgetch(edit);
3135 break;
3136 case '1':
3137 kbinput = KEY_F(10);
3138 wgetch(edit);
3139 break;
3140 case '3':
3141 kbinput = KEY_F(11);
3142 wgetch(edit);
3143 break;
3144 case '4':
3145 kbinput = KEY_F(12);
3146 wgetch(edit);
3147 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003148 case '~':
3149 goto do_insertkey;
Chris Allegretta16e41682000-09-11 22:33:54 +00003150#ifdef DEBUG
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003151 default:
3152 fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"),
3153 kbinput, kbinput);
3154 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003155#endif
3156
3157 }
3158 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003159 case '3': /* Alt-[-3 = Delete? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003160 kbinput = NANO_DELETE_KEY;
3161 wgetch(edit);
3162 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003163 case '4': /* Alt-[-4 = End? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003164 kbinput = NANO_END_KEY;
3165 wgetch(edit);
3166 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003167 case '5': /* Alt-[-5 = Page Up */
Chris Allegretta16e41682000-09-11 22:33:54 +00003168 kbinput = KEY_PPAGE;
3169 wgetch(edit);
3170 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003171 case 'V': /* Alt-[-V = Page Up in Hurd Console */
Chris Allegretta7bf72742001-10-28 04:29:55 +00003172 case 'I': /* Alt-[-I = Page Up - FreeBSD Console */
3173 kbinput = KEY_PPAGE;
3174 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003175 case '6': /* Alt-[-6 = Page Down */
Chris Allegretta16e41682000-09-11 22:33:54 +00003176 kbinput = KEY_NPAGE;
3177 wgetch(edit);
3178 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003179 case 'U': /* Alt-[-U = Page Down in Hurd Console */
Chris Allegretta7bf72742001-10-28 04:29:55 +00003180 case 'G': /* Alt-[-G = Page Down - FreeBSD Console */
3181 kbinput = KEY_NPAGE;
3182 break;
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003183 case '7':
3184 kbinput = KEY_HOME;
3185 wgetch(edit);
3186 break;
3187 case '8':
3188 kbinput = KEY_END;
3189 wgetch(edit);
3190 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003191 case '9': /* Alt-[-9 = Delete in Hurd Console */
3192 kbinput = KEY_DC;
3193 break;
Chris Allegretta32da4562002-01-02 15:12:21 +00003194 case '@': /* Alt-[-@ = Insert in Hurd Console */
3195 case 'L': /* Alt-[-L = Insert - FreeBSD Console */
3196 goto do_insertkey;
3197 case '[': /* Alt-[-[-[A-E], F1-F5 in Linux console */
Chris Allegretta16e41682000-09-11 22:33:54 +00003198 kbinput = wgetch(edit);
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003199 if (kbinput >= 'A' && kbinput <= 'E')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003200 kbinput = KEY_F(kbinput - 64);
Chris Allegretta16e41682000-09-11 22:33:54 +00003201 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003202 case 'A':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003203 case 'B':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003204 case 'C':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003205 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00003206 case 'a':
3207 case 'b':
3208 case 'c':
3209 case 'd':
Chris Allegretta1748cd12001-01-13 17:22:54 +00003210 kbinput = ABCD(kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003211 break;
3212 case 'H':
3213 kbinput = KEY_HOME;
3214 break;
3215 case 'F':
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003216 case 'Y': /* End Key in Hurd Console */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003217 kbinput = KEY_END;
3218 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003219 default:
3220#ifdef DEBUG
3221 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
3222 kbinput, kbinput);
3223#endif
3224 break;
3225 }
3226 break;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003227
Chris Allegretta355fbe52001-07-14 19:32:47 +00003228#ifdef ENABLE_MULTIBUFFER
Chris Allegretta819e3db2001-07-11 02:37:19 +00003229 case NANO_OPENPREV_KEY:
Chris Allegretta180a5692002-01-02 14:30:33 +00003230 case NANO_OPENPREV_ALTKEY:
Chris Allegretta819e3db2001-07-11 02:37:19 +00003231 open_prevfile(0);
3232 keyhandled = 1;
3233 break;
3234 case NANO_OPENNEXT_KEY:
Chris Allegretta180a5692002-01-02 14:30:33 +00003235 case NANO_OPENNEXT_ALTKEY:
Chris Allegretta819e3db2001-07-11 02:37:19 +00003236 open_nextfile(0);
3237 keyhandled = 1;
3238 break;
Chris Allegretta9cf9e062001-07-11 12:06:13 +00003239#endif
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003240
3241#if !defined (NANO_SMALL) && defined (HAVE_REGEX_H)
3242 case NANO_BRACKET_KEY:
3243 do_find_bracket();
3244 keyhandled = 1;
3245 break;
3246#endif
3247
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003248 default:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003249 /* Check for the altkey defs.... */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003250 for (s = main_list; s != NULL; s = s->next)
3251 if (kbinput == s->altval ||
3252 kbinput == s->altval - 32) {
3253 kbinput = s->val;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003254 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003255 }
Chris Allegretta756f2202000-09-01 13:32:47 +00003256#ifndef NANO_SMALL
3257 /* And for toggle switches */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003258 for (t = toggles; t != NULL && !keyhandled; t = t->next)
3259 if (kbinput == t->val ||
3260 (t->val > 'a' &&
3261 kbinput == t->val - 32)) {
3262 do_toggle(t);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003263 keyhandled = 1;
3264 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00003265 }
3266#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003267#ifdef DEBUG
3268 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
3269 kbinput);
3270#endif
3271 break;
3272 }
3273 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003274 /* If the modify_control_seq is set, we received an Alt-Alt
3275 sequence before this, so we make this key a control sequence
3276 by subtracting 64 or 96, depending on its value. */
3277 if (!keyhandled && modify_control_seq) {
3278 if (kbinput >= 'A' && kbinput < 'a')
3279 kbinput -= 64;
3280 else if (kbinput >= 'a' && kbinput <= 'z')
3281 kbinput -= 96;
3282
3283 modify_control_seq = 0;
3284 }
3285
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003286 /* Look through the main shortcut list to see if we've hit a
3287 shortcut key */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003288
Chris Allegrettaf5de33a2002-02-27 04:14:16 +00003289#if !defined(DISABLE_BROWSER) || !defined(DISABLE_MOUSE) || !defined (DISABLE_HELP)
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003290 for (s = currshortcut; s != NULL && !keyhandled; s = s->next) {
Chris Allegrettaf5de33a2002-02-27 04:14:16 +00003291#else
3292 for (s = main_list; s != NULL && !keyhandled; s = s->next) {
3293#endif
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003294 if (kbinput == s->val ||
3295 (s->misc1 && kbinput == s->misc1) ||
3296 (s->misc2 && kbinput == s->misc2)) {
3297 if (ISSET(VIEW_MODE) && !s->viewok)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003298 print_view_warning();
3299 else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003300 s->func();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003301 keyhandled = 1;
3302 }
3303 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003304 /* If we're in raw mode or using Alt-Alt-x, we have to catch
3305 Control-S and Control-Q */
Chris Allegretta9239d742000-09-06 15:19:18 +00003306 if (kbinput == 17 || kbinput == 19)
3307 keyhandled = 1;
3308
Chris Allegretta9caa1932002-02-15 20:08:05 +00003309 /* Catch ^Z by hand when triggered also
3310 407 == ^Z in Linux console when keypad() is used? */
3311 if (kbinput == 26 || kbinput == 407) {
Chris Allegretta9239d742000-09-06 15:19:18 +00003312 if (ISSET(SUSPEND))
3313 do_suspend(0);
3314 keyhandled = 1;
3315 }
Chris Allegretta9239d742000-09-06 15:19:18 +00003316
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003317
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003318#ifndef USE_SLANG
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003319 /* Hack, make insert key do something useful, like insert file */
3320 if (kbinput == KEY_IC) {
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003321#else
3322 if (0) {
3323#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003324 do_insertkey:
3325
3326#ifdef ENABLE_MULTIBUFFER
Chris Allegretta32da4562002-01-02 15:12:21 +00003327 /* do_insertfile_void() contains the logic needed to
3328 handle view mode with the view mode/multibuffer
3329 exception, so use it here */
3330 do_insertfile_void();
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003331#else
Chris Allegretta32da4562002-01-02 15:12:21 +00003332 print_view_warning();
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003333#endif
3334
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003335 keyhandled = 1;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003336 }
3337
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003338 /* Last gasp, stuff that's not in the main lists */
3339 if (!keyhandled)
3340 switch (kbinput) {
Chris Allegretta84de5522001-04-12 14:51:48 +00003341#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003342#ifdef NCURSES_MOUSE_VERSION
3343 case KEY_MOUSE:
3344 do_mouse();
3345 break;
3346#endif
3347#endif
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003348
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003349 case 0: /* Erg */
Chris Allegretta48ebb812001-10-24 01:34:15 +00003350#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003351 do_next_word();
3352 break;
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003353#endif
Chris Allegrettaf4f7e042001-01-04 16:56:15 +00003354
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003355 case -1: /* Stuff that we don't want to do squat */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003356 case 410: /* Must ignore this, it gets sent when we resize */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003357 case 29: /* Ctrl-] */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003358#ifdef PDCURSES
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003359 case 541: /* ???? */
3360 case 542: /* Control and alt in Windows *shrug* */
Chris Allegretta72623582000-11-29 23:43:28 +00003361 case 543: /* Right ctrl key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003362 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +00003363 case 545: /* Right alt key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003364#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003365
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003366 break;
3367 default:
3368#ifdef DEBUG
3369 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
3370#endif
3371 /* We no longer stop unhandled sequences so that people with
3372 odd character sets can type... */
3373
3374 if (ISSET(VIEW_MODE)) {
3375 print_view_warning();
3376 break;
3377 }
3378 do_char(kbinput);
3379 }
Chris Allegretta7fdbd052001-10-02 00:55:38 +00003380 if (ISSET(DISABLE_CURPOS))
3381 UNSET(DISABLE_CURPOS);
3382 else if (ISSET(CONSTUPDATE))
Chris Allegretta2084acc2001-11-29 03:43:08 +00003383 do_cursorpos(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003384
3385 reset_cursor();
3386 wrefresh(edit);
3387 keyhandled = 0;
3388 }
3389
3390 getchar();
3391 finish(0);
3392
3393}