blob: 5e50e4c72a1d18e5098b2dcb60aa464885ce274e [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * nano.c *
4 * *
Jordi Mallach8ae57892002-01-04 17:57:40 +00005 * Copyright (C) 1999-2002 Chris Allegretta *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00006 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
Chris Allegretta3a24f3f2001-10-24 11:33:54 +00008 * the Free Software Foundation; either version 2, or (at your option) *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00009 * any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 * *
20 **************************************************************************/
21
Chris Allegretta6efda542001-04-28 18:03:52 +000022#include "config.h"
23
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000024#include <stdio.h>
25#include <stdlib.h>
26#include <stdarg.h>
27#include <signal.h>
Chris Allegretta08020882001-01-29 23:37:54 +000028#include <setjmp.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000029#include <unistd.h>
30#include <string.h>
31#include <fcntl.h>
32#include <sys/stat.h>
33#include <sys/ioctl.h>
34#include <sys/param.h>
Chris Allegretta27eb13f2000-11-05 16:52:21 +000035#include <sys/types.h>
36#include <sys/wait.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000037#include <errno.h>
38#include <ctype.h>
39#include <locale.h>
40#include <limits.h>
Adam Rogoyski77f36de2000-06-07 03:56:54 +000041#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000042
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000043#include "proto.h"
44#include "nano.h"
45
46#ifndef NANO_SMALL
47#include <libintl.h>
48#define _(string) gettext(string)
49#else
50#define _(string) (string)
51#endif
52
53#ifdef HAVE_TERMIOS_H
54#include <termios.h>
55#endif
56
57#ifdef HAVE_TERMIO_H
58#include <termio.h>
59#endif
60
61#ifdef HAVE_GETOPT_H
62#include <getopt.h>
63#endif
64
Chris Allegretta6fe61492001-05-21 12:56:25 +000065#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000066/* Former globals, now static */
Chris Allegrettaa8c22572002-02-15 19:17:02 +000067int fill = 0;/* Fill - where to wrap lines, basically */
Chris Allegretta7e65d2f2002-02-15 21:12:52 +000068int wrap_at = 0;/* Right justified fill value, allows resize */
Chris Allegretta6fe61492001-05-21 12:56:25 +000069#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +000070
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000071struct termios oldterm; /* The user's original term settings */
Chris Allegretta88520c92001-05-05 17:45:54 +000072static struct sigaction act; /* For all our fun signal handlers */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000073
Rocco Corsiaf5c3022001-01-12 07:51:05 +000074#ifndef DISABLE_HELP
Chris Allegretta6b58acd2001-04-12 03:01:53 +000075static char *help_text_init = ""; /* Initial message, not including shortcuts */
Chris Allegretta65121632000-12-18 07:05:27 +000076#endif
77
Chris Allegretta27eb13f2000-11-05 16:52:21 +000078char *last_search = NULL; /* Last string we searched for */
79char *last_replace = NULL; /* Last replacement string */
80int search_last_line; /* Is this the last search line? */
81
Chris Allegretta08020882001-01-29 23:37:54 +000082static sigjmp_buf jmpbuf; /* Used to return to mainloop after SIGWINCH */
83
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000084/* What we do when we're all set to exit */
85RETSIGTYPE finish(int sigage)
86{
Chris Allegrettac08f50d2001-01-06 18:12:43 +000087
88 keypad(edit, TRUE);
89 keypad(bottomwin, TRUE);
90
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000091 if (!ISSET(NO_HELP)) {
92 mvwaddstr(bottomwin, 1, 0, hblank);
93 mvwaddstr(bottomwin, 2, 0, hblank);
Chris Allegretta4da1fc62000-06-21 03:00:43 +000094 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000095 mvwaddstr(bottomwin, 0, 0, hblank);
Chris Allegretta6b58acd2001-04-12 03:01:53 +000096
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000097 wrefresh(bottomwin);
98 endwin();
99
100 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000101 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000102
Chris Allegrettaf5de33a2002-02-27 04:14:16 +0000103 thanks_for_all_the_fish();
104
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000105 exit(sigage);
106}
107
108/* Die (gracefully?) */
109void die(char *msg, ...)
110{
111 va_list ap;
112
113 va_start(ap, msg);
114 vfprintf(stderr, msg, ap);
115 va_end(ap);
116
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000117 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000118 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000119
120 clear();
121 refresh();
122 resetty();
123 endwin();
124
125 fprintf(stderr, msg);
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000126
Chris Allegretta32da4562002-01-02 15:12:21 +0000127 /* save the currently loaded file if it's been modified */
128 if (ISSET(MODIFIED))
129 die_save_file(filename);
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000130
Chris Allegretta355fbe52001-07-14 19:32:47 +0000131#ifdef ENABLE_MULTIBUFFER
Chris Allegretta32da4562002-01-02 15:12:21 +0000132 /* then save all of the other modified loaded files, if any */
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000133 if (open_files) {
134 filestruct *tmp;
135
136 tmp = open_files;
137
138 while (open_files->prev)
139 open_files = open_files->prev;
140
141 while (open_files->next) {
142
143 /* if we already saved the file above (i. e. if it was the
144 currently loaded file), don't save it again */
145 if (tmp != open_files) {
146 fileage = open_files->file;
Chris Allegretta32da4562002-01-02 15:12:21 +0000147 /* save the file if it's been modified */
148 if (open_files->file_modified)
149 die_save_file(open_files->data);
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000150 }
151
152 open_files = open_files->next;
153 }
154
155 }
156#endif
157
158 exit(1); /* We have a problem: exit w/ errorlevel(1) */
159}
160
161void die_save_file(char *die_filename)
162{
Chris Allegretta48b06702002-02-22 04:30:50 +0000163 char *name, *ret;
164 int i = -1;
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000165
166 /* if we can't save we have REAL bad problems,
167 * but we might as well TRY. */
168 if (die_filename[0] == '\0') {
169 name = "nano.save";
Chris Allegretta48b06702002-02-22 04:30:50 +0000170 ret = get_next_filename(name);
171 if (strcmp(ret, ""))
172 i = write_file(ret, 1, 0, 0);
173 name = ret;
174 }
175 else {
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000176 char *buf = charalloc(strlen(die_filename) + 6);
177 strcpy(buf, die_filename);
178 strcat(buf, ".save");
Chris Allegretta48b06702002-02-22 04:30:50 +0000179 ret = get_next_filename(buf);
180 if (strcmp(ret, ""))
181 i = write_file(ret, 1, 0, 0);
182 name = ret;
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000183 }
184
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000185 if (i != -1)
186 fprintf(stderr, _("\nBuffer written to %s\n"), name);
187 else
Chris Allegretta48b06702002-02-22 04:30:50 +0000188 fprintf(stderr, _("\nNo %s written (too many backup files?)\n"), name);
189
190 free(ret);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000191}
192
Chris Allegrettae61e8302001-01-14 05:18:27 +0000193/* Die with an error message that the screen was too small if, well, the
194 screen is too small */
195void die_too_small(void)
196{
197 char *too_small_msg = _("Window size is too small for Nano...");
198
199 die(too_small_msg);
200
201}
202
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000203void print_view_warning(void)
204{
205 statusbar(_("Key illegal in VIEW mode"));
206}
207
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000208void clear_filename(void)
209{
210 if (filename != NULL)
211 free(filename);
Chris Allegretta88b09152001-05-17 11:35:43 +0000212 filename = charalloc(1);
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000213 filename[0] = 0;
214}
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +0000215
Chris Allegretta56214c62001-09-27 02:46:53 +0000216/* Initialize global variables - no better way for now. If
217 save_cutbuffer is nonzero, don't set cutbuffer to NULL. */
218void global_init(int save_cutbuffer)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000219{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000220 current_x = 0;
221 current_y = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000222
223 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
224 die_too_small();
225
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000226 fileage = NULL;
Chris Allegretta56214c62001-09-27 02:46:53 +0000227 if (!save_cutbuffer)
228 cutbuffer = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000229 current = NULL;
230 edittop = NULL;
231 editbot = NULL;
232 totlines = 0;
Chris Allegretta56214c62001-09-27 02:46:53 +0000233 totsize = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000234 placewewant = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000235
Chris Allegretta6fe61492001-05-21 12:56:25 +0000236#ifndef DISABLE_WRAPJUSTIFY
237 if (wrap_at)
238 fill = COLS + wrap_at;
239 else if (!fill)
Chris Allegrettae61e8302001-01-14 05:18:27 +0000240 fill = COLS - CHARS_FROM_EOL;
241
242 if (fill < MIN_FILL_LENGTH)
243 die_too_small();
Chris Allegretta6fe61492001-05-21 12:56:25 +0000244#endif
Chris Allegrettae61e8302001-01-14 05:18:27 +0000245
Chris Allegretta88b09152001-05-17 11:35:43 +0000246 hblank = charalloc(COLS + 1);
Chris Allegretta0a06e072001-01-23 02:35:04 +0000247 memset(hblank, ' ', COLS);
248 hblank[COLS] = 0;
Chris Allegretta76e291b2001-10-14 19:05:10 +0000249
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000250}
251
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000252#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000253void init_help_msg(void)
254{
255
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000256 help_text_init =
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000257 _(" nano help text\n\n "
258 "The nano editor is designed to emulate the functionality and "
259 "ease-of-use of the UW Pico text editor. There are four main "
260 "sections of the editor: The top line shows the program "
261 "version, the current filename being edited, and whether "
262 "or not the file has been modified. Next is the main editor "
263 "window showing the file being edited. The status line is "
264 "the third line from the bottom and shows important messages. "
265 "The bottom two lines show the most commonly used shortcuts "
266 "in the editor.\n\n "
267 "The notation for shortcuts is as follows: Control-key "
Chris Allegrettae49f1232000-09-02 07:20:39 +0000268 "sequences are notated with a caret (^) symbol and are entered "
Chris Allegrettad56bd792000-09-02 07:27:10 +0000269 "with the Control (Ctrl) key. Escape-key sequences are notated "
270 "with the Meta (M) symbol and can be entered using either the "
271 "Esc, Alt or Meta key depending on your keyboard setup. The "
272 "following keystrokes are available in the main editor window. "
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000273 "Optional keys are shown in parentheses:\n\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000274}
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000275#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000276
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000277/* Make a copy of a node to a pointer (space will be malloc()ed). This
278 does NOT copy the data members used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000279filestruct *copy_node(filestruct * src)
280{
281 filestruct *dst;
282
283 dst = nmalloc(sizeof(filestruct));
Chris Allegretta88b09152001-05-17 11:35:43 +0000284 dst->data = charalloc(strlen(src->data) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000285
286 dst->next = src->next;
287 dst->prev = src->prev;
288
289 strcpy(dst->data, src->data);
290 dst->lineno = src->lineno;
291
292 return dst;
293}
294
295/* Unlink a node from the rest of the struct */
296void unlink_node(filestruct * fileptr)
297{
298 if (fileptr->prev != NULL)
299 fileptr->prev->next = fileptr->next;
300
301 if (fileptr->next != NULL)
302 fileptr->next->prev = fileptr->prev;
303}
304
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000305/* Delete a node from the struct. This does NOT delete the data members
306 used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000307void delete_node(filestruct * fileptr)
308{
Chris Allegretta17dcb722001-01-20 21:40:07 +0000309 if (fileptr == NULL)
310 return;
311
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000312 if (fileptr->data != NULL)
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000313 free(fileptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000314 free(fileptr);
315}
316
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000317/* Okay, now let's duplicate a whole struct! This does NOT duplicate the
318 data members used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000319filestruct *copy_filestruct(filestruct * src)
320{
321 filestruct *dst, *tmp, *head, *prev;
322
323 head = copy_node(src);
324 dst = head; /* Else we barf on copying just one line */
325 head->prev = NULL;
326 tmp = src->next;
327 prev = head;
328
329 while (tmp != NULL) {
330 dst = copy_node(tmp);
331 dst->prev = prev;
332 prev->next = dst;
333
334 prev = dst;
335 tmp = tmp->next;
336 }
337
338 dst->next = NULL;
339 return head;
340}
341
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000342/* Frees a struct. This does NOT free the data members used only by
343 open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000344int free_filestruct(filestruct * src)
345{
346 filestruct *fileptr = src;
347
348 if (src == NULL)
349 return 0;
350
351 while (fileptr->next != NULL) {
352 fileptr = fileptr->next;
Chris Allegretta17dcb722001-01-20 21:40:07 +0000353 delete_node(fileptr->prev);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000354
355#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000356 fprintf(stderr, _("delete_node(): free'd a node, YAY!\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000357#endif
358 }
Chris Allegretta17dcb722001-01-20 21:40:07 +0000359 delete_node(fileptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000360#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000361 fprintf(stderr, _("delete_node(): free'd last node.\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000362#endif
363
364 return 1;
365}
366
367int renumber_all(void)
368{
369 filestruct *temp;
370 long i = 1;
371
372 for (temp = fileage; temp != NULL; temp = temp->next) {
373 temp->lineno = i++;
374 }
375
376 return 0;
377}
378
379int renumber(filestruct * fileptr)
380{
381 filestruct *temp;
382
383 if (fileptr == NULL || fileptr->prev == NULL || fileptr == fileage) {
384 renumber_all();
385 return 0;
386 }
387 for (temp = fileptr; temp != NULL; temp = temp->next) {
Chris Allegretta5146fec2000-12-10 05:44:02 +0000388 if (temp->prev != NULL)
389 temp->lineno = temp->prev->lineno + 1;
390 else
391 temp->lineno = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000392 }
393
394 return 0;
395}
396
397/* Fix the memory allocation for a string */
398void align(char **strp)
399{
400 /* There was a serious bug here: the new address was never
401 stored anywhere... */
402
403 *strp = nrealloc(*strp, strlen(*strp) + 1);
404}
405
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000406/* Null a string at a certain index and align it */
Chris Allegrettafa0c6962001-10-22 23:22:19 +0000407void null_at(char **data, int index)
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000408{
Chris Allegrettafa0c6962001-10-22 23:22:19 +0000409
410 /* Ahh! Damn dereferencing */
411 (*data)[index] = 0;
412 align(data);
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000413}
414
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000415void usage(void)
416{
417#ifdef HAVE_GETOPT_LONG
418 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
419 printf(_("Option Long option Meaning\n"));
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000420
Chris Allegretta7004c282001-09-22 00:42:10 +0000421#ifndef NANO_SMALL
422 printf
423 (_
424 (" -D --dos Write file in DOS format\n"));
425#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000426#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000427 printf
428 (_
Chris Allegretta355fbe52001-07-14 19:32:47 +0000429 (" -F --multibuffer Enable multiple file buffers\n"));
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000430#endif
Chris Allegretta48bd3782002-01-03 21:26:34 +0000431 printf(_
432 (" -K --keypad Use alternate keypad routines\n"));
Chris Allegretta8fa1e282001-09-22 04:20:25 +0000433#ifndef NANO_SMALL
434 printf
435 (_
436 (" -M --mac Write file in Mac format\n"));
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000437 printf
438 (_
439 (" -N --noconvert Don't convert files from DOS/Mac format\n"));
Chris Allegretta47805612000-07-07 02:35:34 +0000440#endif
Chris Allegrettae4f940d2002-03-03 22:36:36 +0000441#ifndef DISABLE_JUSTIFY
442 printf
443 (_
Chris Allegretta309aa502002-03-04 12:15:44 +0000444 (" -Q [str] --quotestr [str] Quoting string, default \"> \"\n"));
Chris Allegrettae4f940d2002-03-03 22:36:36 +0000445#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +0000446#ifndef NANO_SMALL
447 printf(_
448 (" -S --smooth Smooth scrolling\n"));
449#endif
Chris Allegretta7004c282001-09-22 00:42:10 +0000450 printf(_
451 (" -T [num] --tabsize=[num] Set width of a tab to num\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000452 printf
453 (_
454 (" -V --version Print version information and exit\n"));
455 printf(_
456 (" -c --const Constantly show cursor position\n"));
457 printf(_
458 (" -h --help Show this message\n"));
Chris Allegrettaff989832001-09-17 13:48:00 +0000459#ifndef NANO_SMALL
Chris Allegrettad55655f2000-12-27 03:36:47 +0000460 printf(_
461 (" -i --autoindent Automatically indent new lines\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000462 printf(_
Chris Allegretta627de192000-07-12 02:09:17 +0000463 (" -k --cut Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000464#endif
Chris Allegretta627de192000-07-12 02:09:17 +0000465 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000466 (" -l --nofollow Don't follow symbolic links, overwrite\n"));
Chris Allegretta84de5522001-04-12 14:51:48 +0000467#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000468#ifdef NCURSES_MOUSE_VERSION
469 printf(_(" -m --mouse Enable mouse\n"));
470#endif
471#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000472#ifndef DISABLE_OPERATINGDIR
Chris Allegrettad55655f2000-12-27 03:36:47 +0000473 printf(_
Chris Allegretta56214c62001-09-27 02:46:53 +0000474 (" -o [dir] --operatingdir=[dir] Set operating directory\n"));
Chris Allegrettae1f14522001-09-19 03:19:43 +0000475#endif
476 printf(_
477 (" -p --pico Emulate Pico as closely as possible\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000478
479#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000480 printf
481 (_
482 (" -r [#cols] --fill=[#cols] Set fill cols to (wrap lines at) #cols\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000483#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000484#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000485 printf(_
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000486 (" -s [prog] --speller=[prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000487#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000488 printf(_
489 (" -t --tempfile Auto save on exit, don't prompt\n"));
490 printf(_
491 (" -v --view View (read only) mode\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000492#ifndef DISABLE_WRAPPING
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000493 printf(_
494 (" -w --nowrap Don't wrap long lines\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000495#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000496 printf(_
497 (" -x --nohelp Don't show help window\n"));
498 printf(_
499 (" -z --suspend Enable suspend\n"));
500 printf(_
501 (" +LINE Start at line number LINE\n"));
502#else
503 printf(_("Usage: nano [option] +LINE <file>\n\n"));
504 printf(_("Option Meaning\n"));
Chris Allegretta7004c282001-09-22 00:42:10 +0000505#ifndef NANO_SMALL
506 printf(_(" -D Write file in DOS format\n"));
507#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000508#ifdef ENABLE_MULTIBUFFER
509 printf(_(" -F Enable multiple file buffers\n"));
510#endif
Jordi Mallach345a8462002-01-07 11:35:16 +0000511 printf(_(" -K Use alternate keypad routines\n"));
Chris Allegretta8fa1e282001-09-22 04:20:25 +0000512#ifndef NANO_SMALL
513 printf(_(" -M Write file in Mac format\n"));
514#endif
Chris Allegrettae4f940d2002-03-03 22:36:36 +0000515#ifndef DISABLE_JUSTIFY
516 printf(_(" -Q [str] Quoting string, default \"> \"\n"));
517#endif
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000518 printf(_(" -R Use regular expressions for search\n"));
Chris Allegretta3e3ae942001-09-22 19:02:04 +0000519#ifndef NANO_SMALL
520 printf(_(" -S Smooth scrolling\n"));
521#endif
Chris Allegretta48bd3782002-01-03 21:26:34 +0000522 printf(_(" -T [num] Set width of a tab to num\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000523 printf(_(" -V Print version information and exit\n"));
524 printf(_(" -c Constantly show cursor position\n"));
525 printf(_(" -h Show this message\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000526#ifndef NANO_SMALL
Chris Allegrettaff989832001-09-17 13:48:00 +0000527 printf(_(" -i Automatically indent new lines\n"));
Chris Allegretta627de192000-07-12 02:09:17 +0000528 printf(_(" -k Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000529#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000530 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000531 (" -l Don't follow symbolic links, overwrite\n"));
Chris Allegretta84de5522001-04-12 14:51:48 +0000532#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000533#ifdef NCURSES_MOUSE_VERSION
534 printf(_(" -m Enable mouse\n"));
535#endif
536#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000537#ifndef DISABLE_OPERATINGDIR
538 printf(_(" -o [dir] Set operating directory\n"));
539#endif
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +0000540 printf(_(" -p Emulate Pico as closely as possible\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000541
542#ifndef DISABLE_WRAPJUSTIFY
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000543 printf(_
544 (" -r [#cols] Set fill cols to (wrap lines at) #cols\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000545#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000546#ifndef DISABLE_SPELLER
Chris Allegrettad55655f2000-12-27 03:36:47 +0000547 printf(_(" -s [prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000548#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000549 printf(_(" -t Auto save on exit, don't prompt\n"));
550 printf(_(" -v View (read only) mode\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000551#ifndef DISABLE_WRAPPING
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000552 printf(_(" -w Don't wrap long lines\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000553#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000554 printf(_(" -x Don't show help window\n"));
555 printf(_(" -z Enable suspend\n"));
556 printf(_(" +LINE Start at line number LINE\n"));
557#endif
558 exit(0);
559}
560
561void version(void)
562{
Chris Allegrettac46dd812001-02-14 14:28:27 +0000563 printf(_(" GNU nano version %s (compiled %s, %s)\n"),
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000564 VERSION, __TIME__, __DATE__);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000565 printf(_
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000566 (" Email: nano@nano-editor.org Web: http://www.nano-editor.org"));
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000567 printf(_("\n Compiled options:"));
Chris Allegrettaff269f82000-12-01 18:46:01 +0000568
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000569#ifdef NANO_EXTRA
570 printf(" --enable-extra");
Jordi Mallach5285ca92002-01-17 12:40:33 +0000571#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000572#ifdef ENABLE_MULTIBUFFER
573 printf(" --enable-multibuffer");
Jordi Mallach5285ca92002-01-17 12:40:33 +0000574#endif
Chris Allegrettab881d3e2001-04-18 04:34:43 +0000575#ifdef ENABLE_NANORC
576 printf(" --enable-nanorc");
577#endif
Chris Allegretta8ce24132001-04-30 11:28:46 +0000578#ifdef ENABLE_COLOR
579 printf(" --enable-color");
580#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000581
582#ifdef NANO_SMALL
583 printf(" --enable-tiny");
584#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000585#ifdef DISABLE_BROWSER
Chris Allegretta6636dc32001-01-05 05:41:07 +0000586 printf(" --disable-browser");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000587#endif
588#ifdef DISABLE_TABCOMP
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000589 printf(" --disable-tabcomp");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000590#endif
591#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +0000592 printf(" --disable-justify");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000593#endif
594#ifdef DISABLE_SPELLER
Chris Allegretta7b36c522000-12-06 01:08:10 +0000595 printf(" --disable-speller");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000596#endif
597#ifdef DISABLE_HELP
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000598 printf(" --disable-help");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000599#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000600#ifdef DISABLE_MOUSE
601 printf(" --disable-mouse");
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000602#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000603#ifdef DISABLE_OPERATINGDIR
604 printf(" --disable-operatingdir");
605#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000606#endif /* NANO_SMALL */
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000607
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000608#ifdef DISABLE_WRAPPING
609 printf(" --disable-wrapping");
610#endif
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000611#ifdef USE_SLANG
612 printf(" --with-slang");
613#endif
614 printf("\n");
615
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000616}
617
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000618/* Create a new node. This does NOT initialize the data members used
619 only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000620filestruct *make_new_node(filestruct * prevnode)
621{
622 filestruct *newnode;
623
624 newnode = nmalloc(sizeof(filestruct));
625 newnode->data = NULL;
626
627 newnode->prev = prevnode;
628 newnode->next = NULL;
629
630 if (prevnode != NULL)
631 newnode->lineno = prevnode->lineno + 1;
632
633 return newnode;
634}
635
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000636/* Splice a node into an existing filestruct. This does NOT set the data
637 members used only by open_files. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000638void splice_node(filestruct * begin, filestruct * newnode,
639 filestruct * end)
Chris Allegretta7975ed82000-07-28 00:58:35 +0000640{
Chris Allegrettae3167732001-03-18 16:59:34 +0000641 newnode->next = end;
642 newnode->prev = begin;
643 begin->next = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000644 if (end != NULL)
Chris Allegrettae3167732001-03-18 16:59:34 +0000645 end->prev = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000646}
647
Chris Allegrettae3167732001-03-18 16:59:34 +0000648int do_mark(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000649{
650#ifdef NANO_SMALL
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000651 nano_disabled_msg();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000652#else
653 if (!ISSET(MARK_ISSET)) {
654 statusbar(_("Mark Set"));
655 SET(MARK_ISSET);
656 mark_beginbuf = current;
657 mark_beginx = current_x;
658 } else {
659 statusbar(_("Mark UNset"));
660 UNSET(MARK_ISSET);
661 mark_beginbuf = NULL;
662 mark_beginx = 0;
663
664 edit_refresh();
665 }
666#endif
667 return 1;
668}
669
670int no_help(void)
671{
672 if ISSET
673 (NO_HELP)
674 return 2;
675 else
676 return 0;
677}
678
Chris Allegretta3bc8c722000-12-10 17:03:25 +0000679#if defined(DISABLE_JUSTIFY) || defined(DISABLE_SPELLER) || defined(DISABLE_HELP)
Chris Allegrettaff269f82000-12-01 18:46:01 +0000680void nano_disabled_msg(void)
681{
682 statusbar("Sorry, support for this function has been disabled");
683}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000684#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000685
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000686/* The user typed a printable character; add it to the edit buffer */
687void do_char(char ch)
688{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000689 /* magic-line: when a character is inserted on the current magic line,
690 * it means we need a new one! */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000691 if (filebot == current && current->data[0] == '\0') {
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000692 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000693 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000694 }
695
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000696 /* More dangerousness fun =) */
697 current->data = nrealloc(current->data, strlen(current->data) + 2);
698 memmove(&current->data[current_x + 1],
699 &current->data[current_x],
700 strlen(current->data) - current_x + 1);
701 current->data[current_x] = ch;
702 do_right();
703
Chris Allegrettab2cd10d2002-01-20 00:54:42 +0000704#ifdef ENABLE_COLOR
705 edit_refresh();
706#endif
707
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000708#ifndef DISABLE_WRAPPING
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000709 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000710 check_wrap(current, ch);
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000711#endif
712
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000713 set_modified();
714 check_statblank();
715 UNSET(KEEP_CUTBUFFER);
716 totsize++;
717
718}
719
720/* Someone hits return *gasp!* */
721int do_enter(filestruct * inptr)
722{
Chris Allegrettae3167732001-03-18 16:59:34 +0000723 filestruct *newnode;
Chris Allegretta68532c32001-09-17 13:49:33 +0000724 char *tmp;
725#ifndef NANO_SMALL
726 char *spc;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000727 int extra = 0;
Chris Allegretta68532c32001-09-17 13:49:33 +0000728#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000729
Chris Allegrettae3167732001-03-18 16:59:34 +0000730 newnode = make_new_node(inptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000731 tmp = &current->data[current_x];
732 current_x = 0;
733
Chris Allegrettaff989832001-09-17 13:48:00 +0000734#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000735 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
736 if (ISSET(AUTOINDENT)) {
737 spc = current->data;
738 if (spc) {
739 while ((*spc == ' ') || (*spc == '\t')) {
740 extra++;
741 spc++;
742 current_x++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +0000743 totsize++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000744 }
Chris Allegretta88b09152001-05-17 11:35:43 +0000745 newnode->data = charalloc(strlen(tmp) + extra + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000746 strncpy(newnode->data, current->data, extra);
747 strcpy(&newnode->data[extra], tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000748 }
Chris Allegrettaff989832001-09-17 13:48:00 +0000749 } else
750#endif
751 {
Chris Allegretta88b09152001-05-17 11:35:43 +0000752 newnode->data = charalloc(strlen(tmp) + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000753 strcpy(newnode->data, tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000754 }
755 *tmp = 0;
756
Chris Allegrettada721be2000-07-31 01:26:42 +0000757 if (inptr->next == NULL) {
Chris Allegrettae3167732001-03-18 16:59:34 +0000758 filebot = newnode;
759 editbot = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000760 }
Chris Allegrettae3167732001-03-18 16:59:34 +0000761 splice_node(inptr, newnode, inptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000762
763 totsize++;
764 renumber(current);
Chris Allegrettae3167732001-03-18 16:59:34 +0000765 current = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000766 align(&current->data);
767
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000768 /* The logic here is as follows:
769 * -> If we are at the bottom of the buffer, we want to recenter
Chris Allegretta88520c92001-05-05 17:45:54 +0000770 * (read: rebuild) the screen and forcibly move the cursor.
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000771 * -> otherwise, we want simply to redraw the screen and update
772 * where we think the cursor is.
773 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000774 if (current_y == editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +0000775 edit_update(current, CENTER);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000776 reset_cursor();
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000777 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000778 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000779 edit_refresh();
780 update_cursor();
781 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000782
783 totlines++;
784 set_modified();
785
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000786 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000787 return 1;
788}
789
790int do_enter_void(void)
791{
792 return do_enter(current);
793}
794
Chris Allegrettaad3f4782001-10-02 03:54:13 +0000795#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000796void do_next_word(void)
797{
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000798 filestruct *fileptr, *old;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000799 int i;
800
801 if (current == NULL)
802 return;
803
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000804 old = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000805 i = current_x;
806 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
807 if (fileptr == current) {
808 while (isalnum((int) fileptr->data[i])
809 && fileptr->data[i] != 0)
810 i++;
811
812 if (fileptr->data[i] == 0) {
813 i = 0;
814 continue;
815 }
816 }
817 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
818 i++;
819
820 if (fileptr->data[i] != 0)
821 break;
822
823 i = 0;
824 }
825 if (fileptr == NULL)
826 current = filebot;
827 else
828 current = fileptr;
829
830 current_x = i;
831 placewewant = xplustabs();
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000832
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000833 if (current->lineno >= editbot->lineno)
Chris Allegretta234a34d2000-07-29 04:33:38 +0000834 edit_update(current, CENTER);
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000835 else {
836 /* If we've jumped lines, refresh the old line. We can't just use
837 * current->prev here, because we may have skipped over some blank
838 * lines, in which case the previous line is the wrong one.
839 */
840 if (current != old)
841 update_line(old, 0);
842
843 update_line(current, current_x);
844 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000845}
846
847/* the same thing for backwards */
848void do_prev_word(void)
849{
850 filestruct *fileptr, *old;
851 int i;
852
853 if (current == NULL)
854 return;
855
856 old = current;
857 i = current_x;
858 for (fileptr = current; fileptr != NULL; fileptr = fileptr->prev) {
859 if (fileptr == current) {
860 while (isalnum((int) fileptr->data[i])
861 && i != 0)
862 i--;
863
864 if (i == 0) {
865 if (fileptr->prev != NULL)
Chris Allegrettae59fc822001-10-24 18:07:58 +0000866 i = strlen(fileptr->prev->data);
Chris Allegretta878ced32001-10-22 20:05:34 +0000867 else if (fileptr == fileage && filebot != NULL) {
868 current_x = 0;
869 return;
870 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000871 continue;
872 }
873 }
874
875 while (!isalnum((int) fileptr->data[i]) && i != 0)
876 i--;
877
878 if (i > 0) {
879 i--;
880
881 while (isalnum((int) fileptr->data[i]) && i != 0)
882 i--;
883
Chris Allegretta6d0aa9f2001-10-26 15:21:41 +0000884 if (!isalnum((int) fileptr->data[i]))
885 i++;
886
887 if (i != 0 || i != current_x)
Chris Allegretta76e291b2001-10-14 19:05:10 +0000888 break;
889
890 }
891 if (fileptr->prev != NULL)
Chris Allegrettae59fc822001-10-24 18:07:58 +0000892 i = strlen(fileptr->prev->data);
Chris Allegretta878ced32001-10-22 20:05:34 +0000893 else if (fileptr == fileage && filebot != NULL) {
894 current_x = 0;
895 return;
896 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000897 }
898 if (fileptr == NULL)
899 current = fileage;
900 else
901 current = fileptr;
902
903 current_x = i;
904 placewewant = xplustabs();
905
906 if (current->lineno <= edittop->lineno)
907 edit_update(current, CENTER);
908 else {
909 /* If we've jumped lines, refresh the old line. We can't just use
910 * current->prev here, because we may have skipped over some blank
911 * lines, in which case the previous line is the wrong one.
912 */
913 if (current != old)
914 update_line(old, 0);
915
916 update_line(current, current_x);
917 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000918
919}
Chris Allegrettaad3f4782001-10-02 03:54:13 +0000920#endif /* NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000921
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000922#ifndef DISABLE_WRAPPING
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000923void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000924{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000925 int i = 0; /* Index into ->data for line. */
926 int i_tabs = 0; /* Screen position of ->data[i]. */
927 int last_word_end = -1; /* Location of end of last word found. */
928 int current_word_start = -1; /* Location of start of current word. */
929 int current_word_start_t = -1; /* Location of start of current word screen position. */
930 int current_word_end = -1; /* Location of end of current word */
931 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000932 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000933
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000934 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000935 int right = 0;
936 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000937
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000938 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000939
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000940 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000941 if (!isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000942 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000943
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000944 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000945 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000946
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000947 while (!isspace((int) inptr->data[i])
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000948 && inptr->data[i]) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000949 i++;
950 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000951 if (inptr->data[i] < 32)
952 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000953 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000954
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000955 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000956 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000957 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000958 } else {
959 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000960 current_word_end_t = i_tabs - 1;
961 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000962 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000963
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000964 if (inptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000965 if (i_tabs % tabsize != 0);
966 i_tabs += tabsize - (i_tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000967 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000968
Adam Rogoyski09f97962000-06-20 02:50:33 +0000969 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000970 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000971 }
972
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000973 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000974 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000975 * a) one word takes up the whole line with no starting spaces.
976 * - do nothing and return.
977 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000978 * - word starts new line.
979 * - keep white space on original line up to the cursor.
980 * *) cursor is after word at wrap point
981 * - either it's all white space after word, and this routine isn't called.
982 * - or we are actually in case 2 (2 words).
983 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000984 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000985 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000986 * - white space at end of original line is cleared, unless
987 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000988 * b) cursor is at the word at the wrap point.
989 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000990 * - white space on original line is kept to where cursor was.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000991 * c) cursor is past the word at the wrap point.
992 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000993 * - white space at end of original line is cleared
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000994 */
995
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000996 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000997
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000998 /* Category 1a: one word taking up the whole line with no beginning spaces. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000999 if ((last_word_end == -1) && (!isspace((int) inptr->data[0]))) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001000 for (i = current_word_end; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001001 if (!isspace((int) inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001002 current_word_start = i;
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001003 while (!isspace((int) inptr->data[i]) && (i < len)) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001004 i++;
1005 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001006 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001007 current_word_end = i;
1008 break;
1009 }
1010 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001011
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001012 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001013 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001014 return;
1015 }
1016 if (current_x >= last_word_end) {
1017 right = (current_x - current_word_start) + 1;
1018 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001019 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001020 }
1021
Chris Allegretta2084acc2001-11-29 03:43:08 +00001022 /* Subtract length of original line, plus one for the newline, from
1023 totsize. */
1024 totsize -= (strlen(inptr->data) + 1);
1025
Chris Allegretta88b09152001-05-17 11:35:43 +00001026 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001027 strcpy(temp->data, &inptr->data[current_word_start]);
1028 inptr->data = nrealloc(inptr->data, last_word_end + 2);
1029 inptr->data[last_word_end + 1] = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001030
1031 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1032 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
1033
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001034 } else
1035 /* Category 1b: one word on the line and word not taking up whole line
1036 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001037 if (last_word_end == -1) {
Chris Allegretta88b09152001-05-17 11:35:43 +00001038 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001039 strcpy(temp->data, &inptr->data[current_word_start]);
1040
1041 /* Inside word, remove it from original, and move cursor to right spot. */
1042 if (current_x >= current_word_start) {
1043 right = current_x - current_word_start;
Chris Allegretta56214c62001-09-27 02:46:53 +00001044
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001045 current_x = 0;
Chris Allegrettaff989832001-09-17 13:48:00 +00001046#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001047 if (ISSET(AUTOINDENT)) {
1048 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001049 while ((inptr->next->data[i] == ' '
1050 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001051 i++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001052 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001053 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001054#endif
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001055 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001056 }
1057
Chris Allegretta2084acc2001-11-29 03:43:08 +00001058 /* Subtract length of original line, plus one for the newline, from
1059 totsize. */
1060 totsize -= (strlen(inptr->data) + 1);
1061
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001062 null_at(&inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001063
Chris Allegretta2084acc2001-11-29 03:43:08 +00001064 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1065 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
1066
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001067 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
1068 mark_beginbuf = temp;
1069 mark_beginx = 0;
1070 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001071 }
1072
1073 /* Category 2: two or more words on the line. */
1074 else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001075 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001076 if (current_x < current_word_start) {
1077 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001078 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001079 strcpy(temp->data, &inptr->data[current_word_start]);
1080
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001081 if (!isspace((int) input_char)) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001082 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001083
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001084 while (isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001085 i--;
1086 assert(i >= 0);
1087 }
1088 } else if (current_x <= last_word_end)
1089 i = last_word_end - 1;
1090 else
1091 i = current_x;
1092
Chris Allegretta2084acc2001-11-29 03:43:08 +00001093 /* Subtract length of original line, plus one for the newline, from
1094 totsize. */
1095 totsize -= (strlen(inptr->data) + 1);
1096
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001097 inptr->data = nrealloc(inptr->data, i + 2);
1098 inptr->data[i + 1] = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001099
1100 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1101 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
1102
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001103 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001104
1105
1106 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001107 else if ((current_x >= current_word_start)
1108 && (current_x <= (current_word_end + 1))) {
1109 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001110 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001111 strcpy(temp->data, &inptr->data[current_word_start]);
1112
1113 down = 1;
1114
1115 right = current_x - current_word_start;
Chris Allegrettaff989832001-09-17 13:48:00 +00001116#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001117 if (ISSET(AUTOINDENT)) {
1118 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001119 while ((inptr->next->data[i] == ' '
1120 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001121 i++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001122 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001123 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001124#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001125 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001126 current_x = current_word_start;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001127
Chris Allegretta2084acc2001-11-29 03:43:08 +00001128 /* Subtract length of original line, plus one for the newline, from
1129 totsize. */
1130 totsize -= (strlen(inptr->data) + 1);
1131
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001132 null_at(&inptr->data, current_word_start);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001133
Chris Allegretta2084acc2001-11-29 03:43:08 +00001134 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1135 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001136 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001137
1138
1139 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001140 else {
1141 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001142 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001143 strcpy(temp->data, &inptr->data[current_word_start]);
1144
1145 down = 1;
1146 right = current_x - current_word_start;
1147
1148 current_x = current_word_start;
1149 i = current_word_start - 1;
1150
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001151 while (isspace((int) inptr->data[i])) {
Adam Rogoyski3d449b42000-06-19 17:30:14 +00001152 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001153 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001154 }
Chris Allegretta2084acc2001-11-29 03:43:08 +00001155
1156 /* Subtract length of original line, plus one for the newline, from
1157 totsize. */
1158 totsize -= (strlen(inptr->data) + 1);
1159
1160 inptr->data = nrealloc(inptr->data, i + 2);
1161 inptr->data[i + 1] = 0;
1162
1163 /* Now add lengths of new lines, plus two for the newlines, to totsize. */
1164 totsize += (strlen(inptr->data) + strlen(temp->data) + 2);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001165 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001166 }
1167
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001168 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001169 if (ISSET(SAMELINEWRAP) && inptr->next) {
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001170 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001171
Chris Allegretta94a78b82001-03-14 08:28:48 +00001172 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001173 char *p =
Chris Allegretta88b09152001-05-17 11:35:43 +00001174 charalloc((strlen(temp->data) + strlen(inptr->next->data) + 2));
Chris Allegretta94a78b82001-03-14 08:28:48 +00001175
Chris Allegretta56214c62001-09-27 02:46:53 +00001176 /* We're adding to an existing line instead of creating a new
1177 one; decrement totlines here so that when it gets incremented
1178 below, it won't end up being high by one. */
1179 totlines--;
1180
Chris Allegrettaff989832001-09-17 13:48:00 +00001181#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001182 if (ISSET(AUTOINDENT)) {
1183 int non = 0;
1184
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001185 /* Grab the beginning of the next line until it's not a
1186 space or tab, then null terminate it so we can strcat it
1187 to hell */
1188 while ((inptr->next->data[non] == ' '
Chris Allegretta355fbe52001-07-14 19:32:47 +00001189 || inptr->next->data[non] == '\t')) {
1190 p[non] = inptr->next->data[non];
1191 non++;
1192 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001193 p[non] = 0;
1194 strcat(p, temp->data);
1195 strcat(p, " ");
1196
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001197 /* Now tack on the rest of the next line after the spaces and
1198 tabs */
Chris Allegretta94a78b82001-03-14 08:28:48 +00001199 strcat(p, &inptr->next->data[non]);
Chris Allegrettaff989832001-09-17 13:48:00 +00001200 } else
1201#endif
1202 {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001203 strcpy(p, temp->data);
1204 strcat(p, " ");
1205 strcat(p, inptr->next->data);
1206 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001207
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001208 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001209 inptr->next->data = p;
1210
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001211 free(temp->data);
1212 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001213
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001214 current_x = old_x;
1215 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001216 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001217 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001218 else {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001219
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001220 temp->prev = inptr;
1221 temp->next = inptr->next;
1222
1223 if (inptr->next)
1224 inptr->next->prev = temp;
1225 inptr->next = temp;
1226
1227 if (!temp->next)
1228 filebot = temp;
1229
1230 SET(SAMELINEWRAP);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001231
Chris Allegrettaff989832001-09-17 13:48:00 +00001232#ifndef NANO_SMALL
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001233 if (ISSET(AUTOINDENT)) {
1234 char *spc = inptr->data;
1235 char *t = NULL;
1236 int extra = 0;
1237 if (spc) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001238 while ((*spc == ' ') || (*spc == '\t')) {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001239 extra++;
1240 spc++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001241 totsize++;
Chris Allegretta438f7132002-01-16 00:54:47 +00001242 right++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001243 }
Chris Allegretta88b09152001-05-17 11:35:43 +00001244 t = charalloc(strlen(temp->data) + extra + 1);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001245 strncpy(t, inptr->data, extra);
1246 strcpy(t + extra, temp->data);
1247 free(temp->data);
1248 temp->data = t;
1249 }
1250 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001251#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001252 }
1253
1254
1255 totlines++;
Chris Allegretta88520c92001-05-05 17:45:54 +00001256 /* Everything about it makes me want this line here, but it causes
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001257 * totsize to be high by one for some reason. Sigh. (Rob) */
1258 /* totsize++; */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001259
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001260 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001261 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001262
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001263
1264 /* Move the cursor to the new line if appropriate. */
1265 if (down) {
1266 do_right();
1267 }
1268
1269 /* Move the cursor to the correct spot in the line if appropriate. */
1270 while (right--) {
1271 do_right();
1272 }
1273
Chris Allegretta234a34d2000-07-29 04:33:38 +00001274 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001275 reset_cursor();
1276 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001277}
1278
1279/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001280void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001281{
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001282 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001283#ifdef DEBUG
1284 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
1285 inptr->data);
1286#endif
1287
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001288 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001289 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001290 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001291 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001292
1293 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001294 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001295
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001296 while (isspace((int) inptr->data[i]) && inptr->data[i])
Adam Rogoyski09f97962000-06-20 02:50:33 +00001297 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001298
Adam Rogoyski09f97962000-06-20 02:50:33 +00001299 if (!inptr->data[i])
1300 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001301
Adam Rogoyski09f97962000-06-20 02:50:33 +00001302 /* String must be at least 1 character long. */
1303 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001304 if (isspace((int) inptr->data[i])) {
Adam Rogoyski09f97962000-06-20 02:50:33 +00001305 if (!char_found)
1306 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001307 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001308 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001309 } else
1310 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001311 }
Adam Rogoyski09f97962000-06-20 02:50:33 +00001312
1313 if (char_found == 2)
1314 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001315 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001316}
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001317#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001318
1319/* Stuff we do when we abort from programs and want to clean up the
Chris Allegretta88520c92001-05-05 17:45:54 +00001320 * screen. This doesn't do much right now.
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001321 */
1322void do_early_abort(void)
1323{
1324 blank_statusbar_refresh();
1325}
1326
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001327int do_backspace(void)
1328{
1329 filestruct *previous, *tmp;
1330
1331 if (current_x != 0) {
1332 /* Let's get dangerous */
1333 memmove(&current->data[current_x - 1], &current->data[current_x],
1334 strlen(current->data) - current_x + 1);
1335#ifdef DEBUG
1336 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
1337#endif
1338 align(&current->data);
1339 do_left();
1340 } else {
1341 if (current == fileage)
1342 return 0; /* Can't delete past top of file */
1343
1344 previous = current->prev;
1345 current_x = strlen(previous->data);
1346 previous->data = nrealloc(previous->data,
1347 strlen(previous->data) +
1348 strlen(current->data) + 1);
1349 strcat(previous->data, current->data);
1350
1351 tmp = current;
1352 unlink_node(current);
1353 delete_node(current);
1354 if (current == edittop) {
1355 if (previous->next)
1356 current = previous->next;
1357 else
1358 current = previous;
Chris Allegretta3e3ae942001-09-22 19:02:04 +00001359 page_up();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001360 } else {
1361 if (previous->next)
1362 current = previous->next;
1363 else
1364 current = previous;
1365 update_line(current, current_x);
1366 }
1367
1368 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001369 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001370 filebot = current;
1371 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001372
1373 /* Recreate the magic line if we're deleting it AND if the
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001374 line we're on now is NOT blank. if it is blank we
1375 can just use IT for the magic line. This is how Pico
1376 appears to do it, in any case */
Chris Allegretta28a0f892000-07-05 22:47:54 +00001377 if (strcmp(current->data, "")) {
1378 new_magicline();
1379 fix_editbot();
1380 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001381 }
1382
1383 current = previous;
1384 renumber(current);
1385 previous_line();
1386 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001387#ifdef DEBUG
1388 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
1389#endif
1390
1391 }
1392
1393 totsize--;
1394 set_modified();
1395 UNSET(KEEP_CUTBUFFER);
1396 edit_refresh();
1397 return 1;
1398}
1399
1400int do_delete(void)
1401{
1402 filestruct *foo;
1403
Chris Allegretta2084acc2001-11-29 03:43:08 +00001404 /* blbf -> blank line before filebot (see below) */
1405 int blbf = 0;
1406
1407 if (current->next == filebot && !strcmp(current->data, ""))
1408 blbf = 1;
1409
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001410 if (current_x != strlen(current->data)) {
1411 /* Let's get dangerous */
1412 memmove(&current->data[current_x], &current->data[current_x + 1],
1413 strlen(current->data) - current_x);
1414
1415 align(&current->data);
1416
Chris Allegretta2084acc2001-11-29 03:43:08 +00001417 /* Now that we have a magic line again, we can check for both being
1418 on the line before filebot as well as at filebot; it's a special
1419 case if we're on the line before filebot and it's blank, since we
1420 should be able to delete it */
1421 } else if (current->next != NULL && (current->next != filebot || blbf)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001422 current->data = nrealloc(current->data,
1423 strlen(current->data) +
1424 strlen(current->next->data) + 1);
1425 strcat(current->data, current->next->data);
1426
1427 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001428 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001429 filebot = current;
1430 editbot = current;
1431 }
1432
1433 unlink_node(foo);
1434 delete_node(foo);
1435 update_line(current, current_x);
1436
Chris Allegretta4ed13152001-02-10 17:50:50 +00001437 /* Please see the comment in do_backspace if you don't understand
Chris Allegretta28a0f892000-07-05 22:47:54 +00001438 this test */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001439 if (current == filebot && strcmp(current->data, "")) {
Chris Allegretta28a0f892000-07-05 22:47:54 +00001440 new_magicline();
1441 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001442 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001443 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001444 renumber(current);
1445 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001446 } else
1447 return 0;
1448
1449 totsize--;
1450 set_modified();
1451 UNSET(KEEP_CUTBUFFER);
1452 edit_refresh();
1453 return 1;
1454}
1455
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001456void wrap_reset(void)
1457{
1458 UNSET(SAMELINEWRAP);
1459}
1460
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001461#ifndef DISABLE_SPELLER
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001462
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001463int do_int_spell_fix(char *word)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001464{
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001465 char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001466 filestruct *begin;
Chris Allegretta23b74b22002-01-21 20:32:22 +00001467 int i = 0, j = 0, beginx, beginx_top, reverse_search_set;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001468
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001469 /* save where we are */
1470 begin = current;
1471 beginx = current_x + 1;
1472
Chris Allegretta23b74b22002-01-21 20:32:22 +00001473 /* Make sure Spell Check goes forward only */
1474 reverse_search_set = ISSET(REVERSE_SEARCH);
1475 UNSET(REVERSE_SEARCH);
1476
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001477 /* save the current search/replace strings */
1478 search_init_globals();
1479 save_search = mallocstrcpy(save_search, last_search);
1480 save_replace = mallocstrcpy(save_replace, last_replace);
1481
1482 /* set search/replace strings to mis-spelt word */
1483 prevanswer = mallocstrcpy(prevanswer, word);
1484 last_search = mallocstrcpy(last_search, word);
1485 last_replace = mallocstrcpy(last_replace, word);
1486
1487 /* start from the top of file */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001488 current = fileage;
1489 current_x = beginx_top = -1;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001490
1491 search_last_line = FALSE;
1492
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001493 edit_update(fileage, TOP);
1494
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001495 while (1) {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001496
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001497 /* make sure word is still mis-spelt (i.e. when multi-errors) */
1498 if (findnextstr(TRUE, FALSE, fileage, beginx_top, prevanswer) != NULL) {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001499
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001500 /* find wholewords only */
1501 if (!is_whole_word(current_x, current, prevanswer))
1502 continue;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001503
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001504 do_replace_highlight(TRUE, prevanswer);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001505
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001506 /* allow replace word to be corrected */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001507 i = statusq(0, spell_list, last_replace, _("Edit a replacement"));
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001508
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001509 do_replace_highlight(FALSE, prevanswer);
1510
1511 /* start from the start of this line again */
1512 current = fileage;
1513 current_x = beginx_top;
1514
1515 search_last_line = FALSE;
1516
1517 if (strcmp(prevanswer,answer) != 0) {
1518 j = i;
1519 do_replace_loop(prevanswer, fileage, &beginx_top, TRUE, &j);
1520 }
Chris Allegretta80838272001-12-02 06:03:22 +00001521 }
Chris Allegretta1bc0c7e2002-01-08 15:00:24 +00001522
1523 break;
Rocco Corsi562964d2002-01-13 03:18:03 +00001524 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001525
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001526 /* restore the search/replace strings */
1527 last_search = mallocstrcpy(last_search, save_search);
1528 last_replace = mallocstrcpy(last_replace, save_replace);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001529
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001530 /* restore where we were */
1531 current = begin;
1532 current_x = beginx - 1;
1533
Chris Allegretta23b74b22002-01-21 20:32:22 +00001534 /* restore Search/Replace direction */
1535 if (reverse_search_set)
1536 SET(REVERSE_SEARCH);
1537
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001538 edit_update(current, CENTER);
1539
1540 if (i == -1)
1541 return FALSE;
1542
1543 return TRUE;
1544}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001545
1546/* Integrated spell checking using 'spell' program */
Chris Allegretta271e9722000-11-10 18:15:43 +00001547int do_int_speller(char *tempfile_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001548{
Chris Allegretta271e9722000-11-10 18:15:43 +00001549 char *read_buff, *read_buff_ptr, *read_buff_word;
1550 long pipe_buff_size;
1551 int in_fd[2], tempfile_fd;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001552 int spell_status;
1553 pid_t pid_spell;
1554 ssize_t bytesread;
1555
Chris Allegretta271e9722000-11-10 18:15:43 +00001556 /* Create a pipe to spell program */
1557
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001558 if (pipe(in_fd) == -1)
1559 return FALSE;
1560
Chris Allegretta271e9722000-11-10 18:15:43 +00001561 /* A new process to run spell in */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001562
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001563 if ((pid_spell = fork()) == 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001564
1565 /* Child continues, (i.e. future spell process) */
1566
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001567 close(in_fd[0]);
1568
Chris Allegretta271e9722000-11-10 18:15:43 +00001569 /* replace the standard in with the tempfile */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001570
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001571 if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001572
1573 close(in_fd[1]);
1574 exit(1);
1575 }
1576
1577 if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
1578
1579 close(tempfile_fd);
1580 close(in_fd[1]);
1581 exit(1);
1582 }
1583 close(tempfile_fd);
1584
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001585
Chris Allegretta271e9722000-11-10 18:15:43 +00001586 /* send spell's standard out to the pipe */
1587
1588 if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1589
1590 close(in_fd[1]);
1591 exit(1);
1592 }
1593 close(in_fd[1]);
1594
1595 /* Start spell program, we are using the PATH here!?!? */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001596 execlp("spell", "spell", NULL);
1597
Chris Allegretta271e9722000-11-10 18:15:43 +00001598 /* Should not be reached, if spell is found!!! */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001599
Chris Allegretta271e9722000-11-10 18:15:43 +00001600 exit(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001601 }
1602
1603 /* Parent continues here */
1604
Chris Allegretta271e9722000-11-10 18:15:43 +00001605 close(in_fd[1]);
1606
1607 /* Child process was not forked successfully */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001608
1609 if (pid_spell < 0) {
1610
Chris Allegretta271e9722000-11-10 18:15:43 +00001611 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001612 return FALSE;
1613 }
1614
Chris Allegretta271e9722000-11-10 18:15:43 +00001615 /* Get system pipe buffer size */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001616
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001617 if ((pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001618
Chris Allegretta271e9722000-11-10 18:15:43 +00001619 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001620 return FALSE;
Chris Allegretta271e9722000-11-10 18:15:43 +00001621 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001622
Chris Allegretta88b09152001-05-17 11:35:43 +00001623 read_buff = charalloc(pipe_buff_size + 1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001624
Chris Allegretta271e9722000-11-10 18:15:43 +00001625 /* Process the returned spelling errors */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001626
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001627 while ((bytesread = read(in_fd[0], read_buff, pipe_buff_size)) > 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001628
Chris Allegretta271e9722000-11-10 18:15:43 +00001629 read_buff[bytesread] = (char) NULL;
1630 read_buff_word = read_buff_ptr = read_buff;
1631
1632 while (*read_buff_ptr != (char) NULL) {
1633
1634 /* Windows version may need to process additional char '\r' */
1635
1636 /* Possible problem here if last word not followed by '\n' */
1637
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001638 if (*read_buff_ptr == '\n') {
Chris Allegretta271e9722000-11-10 18:15:43 +00001639 *read_buff_ptr = (char) NULL;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001640 if (!do_int_spell_fix(read_buff_word)) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001641
1642 close(in_fd[0]);
1643 free(read_buff);
1644 replace_abort();
1645
1646 return TRUE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001647 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001648 read_buff_word = read_buff_ptr;
1649 read_buff_word++;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001650 }
1651
1652 read_buff_ptr++;
1653 }
1654 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001655
1656 close(in_fd[0]);
1657 free(read_buff);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001658 replace_abort();
1659
Chris Allegretta271e9722000-11-10 18:15:43 +00001660 /* Process end of spell process */
1661
1662 wait(&spell_status);
1663 if (WIFEXITED(spell_status)) {
1664 if (WEXITSTATUS(spell_status) != 0)
1665 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001666 } else
Chris Allegretta271e9722000-11-10 18:15:43 +00001667 return FALSE;
1668
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001669 return TRUE;
1670}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001671
1672/* External spell checking */
Chris Allegretta271e9722000-11-10 18:15:43 +00001673int do_alt_speller(char *file_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001674{
Chris Allegrettab3655b42001-10-22 03:15:31 +00001675 int alt_spell_status, lineno_cur = current->lineno;
1676 int x_cur = current_x, y_cur = current_y, pww_cur = placewewant;
1677
Chris Allegretta271e9722000-11-10 18:15:43 +00001678 pid_t pid_spell;
Chris Allegretta169ee842001-01-26 01:57:32 +00001679 char *ptr;
1680 static int arglen = 3;
1681 static char **spellargs = (char **) NULL;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001682
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001683 endwin();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001684
Chris Allegrettae434b452001-01-27 19:25:00 +00001685 /* Set up an argument list to pass the execvp function */
1686 if (spellargs == NULL) {
1687 spellargs = nmalloc(arglen * sizeof(char *));
Chris Allegretta271e9722000-11-10 18:15:43 +00001688
Chris Allegrettae434b452001-01-27 19:25:00 +00001689 spellargs[0] = strtok(alt_speller, " ");
1690 while ((ptr = strtok(NULL, " ")) != NULL) {
1691 arglen++;
1692 spellargs = nrealloc(spellargs, arglen * sizeof(char *));
1693 spellargs[arglen - 3] = ptr;
Chris Allegretta169ee842001-01-26 01:57:32 +00001694 }
Chris Allegrettae434b452001-01-27 19:25:00 +00001695 spellargs[arglen - 1] = NULL;
1696 }
1697 spellargs[arglen - 2] = file_name;
1698
1699 /* Start a new process for the alternate speller */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001700 if ((pid_spell = fork()) == 0) {
Chris Allegretta169ee842001-01-26 01:57:32 +00001701
Chris Allegretta88520c92001-05-05 17:45:54 +00001702 /* Start alternate spell program; we are using the PATH here!?!? */
Chris Allegretta169ee842001-01-26 01:57:32 +00001703 execvp(spellargs[0], spellargs);
Chris Allegretta271e9722000-11-10 18:15:43 +00001704
1705 /* Should not be reached, if alternate speller is found!!! */
1706
1707 exit(1);
1708 }
1709
1710 /* Could not fork?? */
1711
1712 if (pid_spell < 0)
1713 return FALSE;
1714
1715 /* Wait for alternate speller to complete */
1716
1717 wait(&alt_spell_status);
1718 if (WIFEXITED(alt_spell_status)) {
1719 if (WEXITSTATUS(alt_spell_status) != 0)
1720 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001721 } else
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001722 return FALSE;
1723
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001724 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001725 free_filestruct(fileage);
Chris Allegretta56214c62001-09-27 02:46:53 +00001726 global_init(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001727 open_file(file_name, 0, 1);
Rocco Corsi4dfaf932001-04-20 01:59:55 +00001728
Chris Allegretta1b3381b2001-09-28 21:59:01 +00001729 /* go back to the old position, mark the file as modified, and make
1730 sure that the titlebar is refreshed */
1731 do_gotopos(lineno_cur, x_cur, y_cur, pww_cur);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001732 set_modified();
Chris Allegrettae1f14522001-09-19 03:19:43 +00001733 clearok(topwin, FALSE);
1734 titlebar(NULL);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001735
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001736 return TRUE;
1737}
1738#endif
1739
1740int do_spell(void)
1741{
1742
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001743#ifdef DISABLE_SPELLER
Chris Allegrettaff269f82000-12-01 18:46:01 +00001744 nano_disabled_msg();
1745 return (TRUE);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001746#else
Chris Allegretta271e9722000-11-10 18:15:43 +00001747 char *temp;
1748 int spell_res;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001749
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001750 if ((temp = safe_tempnam(0, "nano.")) == NULL) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001751 statusbar(_("Could not create a temporary filename: %s"),
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001752 strerror(errno));
Chris Allegretta271e9722000-11-10 18:15:43 +00001753 return 0;
1754 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001755
Chris Allegrettaecc3d7f2001-06-05 23:24:55 +00001756 if (write_file(temp, 1, 0, 0) == -1) {
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001757 statusbar(_("Spell checking failed: unable to write temp file!"));
Chris Allegretta271e9722000-11-10 18:15:43 +00001758 return 0;
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001759 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001760
Chris Allegrettae1f14522001-09-19 03:19:43 +00001761#ifdef ENABLE_MULTIBUFFER
1762 /* update the current open_files entry before spell-checking, in case
1763 any problems occur; the case of there being no open_files entries
Chris Allegretta48b06702002-02-22 04:30:50 +00001764 is handled elsewhere (before we reach this point) */
1765 add_open_file(1);
Chris Allegrettae1f14522001-09-19 03:19:43 +00001766#endif
1767
Chris Allegretta271e9722000-11-10 18:15:43 +00001768 if (alt_speller)
1769 spell_res = do_alt_speller(temp);
1770 else
1771 spell_res = do_int_speller(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001772
Chris Allegretta271e9722000-11-10 18:15:43 +00001773 remove(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001774
1775 if (spell_res)
1776 statusbar(_("Finished checking spelling"));
1777 else
1778 statusbar(_("Spell checking failed"));
1779
1780 return spell_res;
1781
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001782#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001783}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001784
1785int do_exit(void)
1786{
1787 int i;
1788
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001789 if (!ISSET(MODIFIED)) {
1790
Chris Allegretta355fbe52001-07-14 19:32:47 +00001791#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001792 if (!close_open_file()) {
1793 display_main_list();
1794 return 1;
1795 }
1796 else
1797#endif
1798
1799 finish(0);
1800 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001801
Chris Allegretta30885552000-07-14 01:20:12 +00001802 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001803 i = 1;
1804 } else {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001805 i = do_yesno(0, 0,
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001806 _
1807 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1808 }
1809
1810#ifdef DEBUG
1811 dump_buffer(fileage);
1812#endif
1813
1814 if (i == 1) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001815 if (do_writeout(filename, 1, 0) > 0) {
1816
Chris Allegretta355fbe52001-07-14 19:32:47 +00001817#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001818 if (!close_open_file()) {
1819 display_main_list();
1820 return 1;
1821 }
1822 else
1823#endif
1824
1825 finish(0);
1826 }
1827 } else if (i == 0) {
1828
Chris Allegretta355fbe52001-07-14 19:32:47 +00001829#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001830 if (!close_open_file()) {
1831 display_main_list();
1832 return 1;
1833 }
1834 else
1835#endif
1836
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001837 finish(0);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001838 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001839 statusbar(_("Cancelled"));
1840
1841 display_main_list();
1842 return 1;
1843}
1844
Chris Allegretta84de5522001-04-12 14:51:48 +00001845#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001846#ifdef NCURSES_MOUSE_VERSION
1847void do_mouse(void)
1848{
1849 MEVENT mevent;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001850 int foo = 0, tab_found = 0;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001851 int currslen;
Chris Allegretta40639dd2002-03-04 12:25:34 +00001852 shortcut *s = currshortcut;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001853
1854 if (getmouse(&mevent) == ERR)
1855 return;
1856
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001857 /* If mouse not in edit or bottom window, return */
1858 if (wenclose(edit, mevent.y, mevent.x)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001859
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001860 /* Don't let people screw with the marker when they're in a
1861 subfunction */
1862 if (currshortcut != main_list)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001863 return;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001864
1865 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1866 mevent.y -= 2;
1867
1868 /* Selecting where the cursor is sets the mark.
1869 * Selecting beyond the line length with the cursor at the end of the
1870 * line sets the mark as well.
1871 */
1872 if ((mevent.y == current_y) &&
1873 ((mevent.x == current_x) || (current_x == strlen(current->data)
1874 && (mevent.x >
1875 strlen(current->data))))) {
1876 if (ISSET(VIEW_MODE)) {
1877 print_view_warning();
1878 return;
1879 }
1880 do_mark();
1881 } else if (mevent.y > current_y) {
1882 while (mevent.y > current_y) {
1883 if (current->next != NULL)
1884 current = current->next;
1885 else
1886 break;
1887 current_y++;
1888 }
1889 } else if (mevent.y < current_y) {
1890 while (mevent.y < current_y) {
1891 if (current->prev != NULL)
1892 current = current->prev;
1893 else
1894 break;
1895 current_y--;
1896 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001897 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001898 current_x = mevent.x;
1899 placewewant = current_x;
1900 while (foo < current_x) {
1901 if (current->data[foo] == NANO_CONTROL_I) {
1902 current_x -= tabsize - (foo % tabsize);
1903 tab_found = 1;
1904 } else if (current->data[foo] & 0x80);
1905 else if (current->data[foo] < 32)
1906 current_x--;
1907 foo++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001908 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001909 /* This is where tab_found comes in. I can't figure out why,
1910 * but without it any line with a tab will place the cursor
1911 * one character behind. Whatever, this fixes it. */
1912 if (tab_found == 1)
1913 current_x++;
1914
1915 if (current_x > strlen(current->data))
1916 current_x = strlen(current->data);
1917
1918 update_cursor();
1919 edit_refresh();
1920 } else if (wenclose(bottomwin, mevent.y, mevent.x) && !ISSET(NO_HELP)) {
Chris Allegrettaa951f212001-09-27 21:07:39 +00001921
Chris Allegretta40639dd2002-03-04 12:25:34 +00001922 int i, k;
Chris Allegrettaa951f212001-09-27 21:07:39 +00001923
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001924 if (currshortcut == main_list)
1925 currslen = MAIN_VISIBLE;
1926 else
1927 currslen = length_of_list(currshortcut);
1928
Chris Allegrettaa951f212001-09-27 21:07:39 +00001929 if (currslen < 2)
1930 k = COLS / 6;
1931 else
1932 k = COLS / ((currslen + (currslen %2)) / 2);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001933
1934 /* Determine what shortcut list was clicked */
1935 mevent.y -= (editwinrows + 3);
1936
1937 if (mevent.y < 0) /* They clicked on the statusbar */
1938 return;
1939
1940 /* Don't select stuff beyond list length */
1941 if (mevent.x / k >= currslen)
1942 return;
1943
Chris Allegretta40639dd2002-03-04 12:25:34 +00001944 for (i = 0; i < (mevent.x / k) * 2 + mevent.y; i++)
1945 s = s->next;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001946
1947 /* And ungetch that value */
Chris Allegretta40639dd2002-03-04 12:25:34 +00001948 ungetch(s->val);
Chris Allegretta6414b402001-09-21 03:21:11 +00001949
1950 /* And if it's an alt-key sequence, we should probably send alt
1951 too ;-) */
Chris Allegretta40639dd2002-03-04 12:25:34 +00001952 if (s->val >= 'a' && s->val <= 'z')
Chris Allegretta6414b402001-09-21 03:21:11 +00001953 ungetch(27);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001954 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001955}
1956#endif
1957#endif
1958
1959/* Handler for SIGHUP */
1960RETSIGTYPE handle_hup(int signal)
1961{
Chris Allegrettae7a58932000-12-02 02:36:22 +00001962 die(_("Received SIGHUP"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001963}
1964
Chris Allegretta18f8be02000-09-04 03:20:38 +00001965/* What do we do when we catch the suspend signal */
1966RETSIGTYPE do_suspend(int signal)
1967{
Chris Allegretta18f8be02000-09-04 03:20:38 +00001968 endwin();
Chris Allegretta521e00d2001-06-28 16:52:52 +00001969 printf("\n\n\n\n\nUse \"fg\" to return to nano\n");
1970 fflush(stdout);
1971
Chris Allegretta7b0667f2002-01-10 12:44:21 +00001972 /* Restore the terminal settings for the disabled keys */
1973 tcsetattr(0, TCSANOW, &oldterm);
1974
Chris Allegretta521e00d2001-06-28 16:52:52 +00001975 /* We used to re-enable the default SIG_DFL and raise SIGTSTP, but
1976 then we could be (and were) interrupted in the middle of the call.
1977 So we do it the mutt way instead */
1978 kill(0, SIGSTOP);
Chris Allegretta18f8be02000-09-04 03:20:38 +00001979}
1980
1981/* Restore the suspend handler when we come back into the prog */
1982RETSIGTYPE do_cont(int signal)
1983{
1984
Chris Allegretta521e00d2001-06-28 16:52:52 +00001985 /* Now we just update the screen instead of having to reenable the
1986 SIGTSTP handler */
1987
Chris Allegretta521e00d2001-06-28 16:52:52 +00001988 doupdate();
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00001989 /* The Hurd seems to need this, otherwise a ^Y after a ^Z will
1990 start suspending again */
1991 signal_init();
Chris Allegretta18f8be02000-09-04 03:20:38 +00001992}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001993
1994void handle_sigwinch(int s)
1995{
1996#ifndef NANO_SMALL
1997 char *tty = NULL;
1998 int fd = 0;
1999 int result = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002000 struct winsize win;
2001
2002 tty = ttyname(0);
2003 if (!tty)
2004 return;
2005 fd = open(tty, O_RDWR);
2006 if (fd == -1)
2007 return;
2008 result = ioctl(fd, TIOCGWINSZ, &win);
2009 if (result == -1)
2010 return;
2011
2012
2013 COLS = win.ws_col;
2014 LINES = win.ws_row;
2015
Chris Allegrettae61e8302001-01-14 05:18:27 +00002016 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
2017 die_too_small();
2018
Chris Allegretta6fe61492001-05-21 12:56:25 +00002019#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettae61e8302001-01-14 05:18:27 +00002020 if ((fill = COLS - CHARS_FROM_EOL) < MIN_FILL_LENGTH)
2021 die_too_small();
Chris Allegretta6fe61492001-05-21 12:56:25 +00002022#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002023
Chris Allegretta0a06e072001-01-23 02:35:04 +00002024 hblank = nrealloc(hblank, COLS + 1);
2025 memset(hblank, ' ', COLS);
2026 hblank[COLS] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002027
Chris Allegretta618f5d72001-02-16 04:48:30 +00002028#ifdef HAVE_RESIZETERM
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002029 resizeterm(LINES, COLS);
2030#ifdef HAVE_WRESIZE
2031 if (wresize(topwin, 2, COLS) == ERR)
2032 die(_("Cannot resize top win"));
2033 if (mvwin(topwin, 0, 0) == ERR)
2034 die(_("Cannot move top win"));
2035 if (wresize(edit, editwinrows, COLS) == ERR)
2036 die(_("Cannot resize edit win"));
2037 if (mvwin(edit, 2, 0) == ERR)
2038 die(_("Cannot move edit win"));
2039 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
2040 die(_("Cannot resize bottom win"));
2041 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
2042 die(_("Cannot move bottom win"));
2043#endif /* HAVE_WRESIZE */
Chris Allegretta618f5d72001-02-16 04:48:30 +00002044#endif /* HAVE_RESIZETERM */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002045
Robert Siemborskidd53ec22000-07-04 02:35:19 +00002046 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002047
Chris Allegrettabceb1b22000-06-19 04:22:15 +00002048 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00002049 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002050 }
2051 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00002052
2053 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002054 refresh();
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002055 titlebar(NULL);
Chris Allegretta97accc62000-06-19 05:45:52 +00002056 edit_refresh();
2057 display_main_list();
Chris Allegretta08020882001-01-29 23:37:54 +00002058 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002059 total_refresh();
Chris Allegretta08020882001-01-29 23:37:54 +00002060
Chris Allegretta4e90c402001-01-29 23:40:43 +00002061 /* Turn cursor back on for sure */
2062 curs_set(1);
2063
Chris Allegretta08020882001-01-29 23:37:54 +00002064 /* Jump back to mainloop */
2065 siglongjmp(jmpbuf, 1);
2066
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002067#endif
2068}
2069
Chris Allegretta756f2202000-09-01 13:32:47 +00002070void signal_init(void)
2071{
Chris Allegrettaac899e52001-06-30 04:09:09 +00002072#ifdef _POSIX_VDISABLE
2073 struct termios term;
2074#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002075
Chris Allegretta88520c92001-05-05 17:45:54 +00002076 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
Chris Allegretta756f2202000-09-01 13:32:47 +00002077 memset(&act, 0, sizeof(struct sigaction));
2078 act.sa_handler = SIG_IGN;
2079 sigaction(SIGINT, &act, NULL);
Chris Allegretta756f2202000-09-01 13:32:47 +00002080
Chris Allegretta88520c92001-05-05 17:45:54 +00002081 /* Trap SIGHUP cuz we want to write the file out. */
Chris Allegretta756f2202000-09-01 13:32:47 +00002082 act.sa_handler = handle_hup;
2083 sigaction(SIGHUP, &act, NULL);
2084
2085 act.sa_handler = handle_sigwinch;
2086 sigaction(SIGWINCH, &act, NULL);
2087
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002088
2089#ifdef _POSIX_VDISABLE
2090 tcgetattr(0, &term);
2091
2092#ifdef VDSUSP
2093 term.c_cc[VDSUSP] = _POSIX_VDISABLE;
2094#endif /* VDSUSP */
2095
2096#endif /* _POSIX_VDISABLE */
2097
Chris Allegretta521e00d2001-06-28 16:52:52 +00002098 if (!ISSET(SUSPEND)) {
Chris Allegrettaac899e52001-06-30 04:09:09 +00002099
2100/* Insane! */
2101#ifdef _POSIX_VDISABLE
Chris Allegrettaac899e52001-06-30 04:09:09 +00002102 term.c_cc[VSUSP] = _POSIX_VDISABLE;
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002103#else
Chris Allegrettaac899e52001-06-30 04:09:09 +00002104 act.sa_handler = SIG_IGN;
Chris Allegretta521e00d2001-06-28 16:52:52 +00002105 sigaction(SIGTSTP, &act, NULL);
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002106#endif
Chris Allegrettaac899e52001-06-30 04:09:09 +00002107
Chris Allegretta521e00d2001-06-28 16:52:52 +00002108 } else {
2109 /* if we don't do this, it seems other stuff interrupts the
2110 suspend handler! Try using nano with mutt without this line */
2111 sigfillset(&act.sa_mask);
2112
2113 act.sa_handler = do_suspend;
2114 sigaction(SIGTSTP, &act, NULL);
2115
2116 act.sa_handler = do_cont;
2117 sigaction(SIGCONT, &act, NULL);
2118 }
2119
Chris Allegretta0bb70dc2001-12-17 04:34:23 +00002120
2121#ifdef _POSIX_VDISABLE
2122 tcsetattr(0, TCSANOW, &term);
2123#endif
2124
2125
Chris Allegretta756f2202000-09-01 13:32:47 +00002126}
2127
Chris Allegretta2a42af12000-09-12 23:02:49 +00002128void window_init(void)
2129{
Chris Allegrettae61e8302001-01-14 05:18:27 +00002130 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
2131 die_too_small();
Chris Allegretta92c9dd22000-09-13 14:03:27 +00002132
Chris Allegretta88520c92001-05-05 17:45:54 +00002133 /* Set up the main text window */
Chris Allegretta2a42af12000-09-12 23:02:49 +00002134 edit = newwin(editwinrows, COLS, 2, 0);
2135
2136 /* And the other windows */
2137 topwin = newwin(2, COLS, 0, 0);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002138 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002139
Chris Allegretta155d6202001-01-08 01:50:37 +00002140#ifdef PDCURSES
2141 /* Oops, I guess we need this again.
2142 Moved here so the keypad still works after a Meta-X, for example */
2143 keypad(edit, TRUE);
2144 keypad(bottomwin, TRUE);
2145#endif
2146
Chris Allegretta2a42af12000-09-12 23:02:49 +00002147}
2148
Chris Allegretta756f2202000-09-01 13:32:47 +00002149void mouse_init(void)
2150{
Chris Allegretta84de5522001-04-12 14:51:48 +00002151#ifndef DISABLE_MOUSE
Chris Allegretta756f2202000-09-01 13:32:47 +00002152#ifdef NCURSES_MOUSE_VERSION
2153 if (ISSET(USE_MOUSE)) {
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002154 keypad_on(edit, 1);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002155 keypad_on(bottomwin, 1);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002156
Chris Allegretta756f2202000-09-01 13:32:47 +00002157 mousemask(BUTTON1_RELEASED, NULL);
2158 mouseinterval(50);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00002159
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002160 } else
Chris Allegretta756f2202000-09-01 13:32:47 +00002161 mousemask(0, NULL);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002162
Chris Allegretta756f2202000-09-01 13:32:47 +00002163#endif
2164#endif
2165
2166}
2167
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002168int do_tab(void)
2169{
2170 do_char('\t');
2171 return 1;
2172}
2173
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002174#ifndef DISABLE_JUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002175int empty_line(const char *data)
2176{
2177 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002178 if (!isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002179 return 0;
2180
2181 data++;
2182 }
2183
2184 return 1;
2185}
2186
2187int no_spaces(const char *data)
2188{
2189 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002190 if (isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002191 return 0;
2192
2193 data++;
2194 }
2195
2196 return 1;
2197}
2198
2199void justify_format(char *data)
2200{
2201 int i = 0;
2202 int len = strlen(data);
2203
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002204 /* Skip leading whitespace. */
2205 for (i = 0; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002206 if (!isspace((int) data[i]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002207 break;
2208 }
2209
2210 i++; /* (i) is now at least 2. */
2211
2212 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
2213 for (; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002214 if (isspace((int) data[i]) && isspace((int) data[i - 1])
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002215 && (data[i - 2] != '.')
2216 && (data[i-2]!='!') && (data[i-2]!='?')) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002217 memmove(data + i, data + i + 1, len - i);
2218 len--;
2219 i--;
2220 }
2221 }
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002222 /* Skip trailing whitespace.
2223 * i<=len iff there was a non-space in the line. In that case, we
2224 * strip spaces from the end of the line. Note that "line" means the
2225 * whole paragraph. */
2226 if (i<=len) {
2227 for(i=len-1; i>0 && isspace((int) data[i]); i--);
2228 data[i+1] = '\0';
2229 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002230}
2231#endif
2232
2233int do_justify(void)
2234{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002235#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +00002236 nano_disabled_msg();
2237 return 1;
2238#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002239 int slen = 0; /* length of combined lines on one line. */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002240 int initial_y, kbinput = 0, totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002241 filestruct *initial = NULL, *tmpjust = NULL, *cutbak, *tmptop, *tmpbot;
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002242 filestruct *samecheck = current;
2243 int qdepth = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002244
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002245 /* Compute quote depth level */
2246 while (!strncmp(&current->data[qdepth], quotestr, strlen(quotestr)))
2247 qdepth += strlen(quotestr);
2248
2249 if (empty_line(&current->data[qdepth])) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002250 /* Justify starting at first non-empty line. */
2251 do {
2252 if (!current->next)
2253 return 1;
2254
2255 current = current->next;
2256 current_y++;
2257 }
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002258 while (strlen(current->data) >= qdepth
2259 && !strncmp(current->data, samecheck->data, qdepth)
2260 && empty_line(&current->data[qdepth]));
2261
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002262 } else {
2263 /* Search back for the beginning of the paragraph, where
2264 * Paragraph is 1) A line with leading whitespace
2265 * or 2) A line following an empty line.
2266 */
2267 while (current->prev != NULL) {
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002268 if (strncmp(current->data, samecheck->data, qdepth)
2269
2270 /* Don't keep going back if the previous line is more
2271 intented quotestr-wise than samecheck */
2272 || !strncmp(&current->data[qdepth], quotestr, strlen(quotestr))
2273 || isspace((int) current->data[qdepth])
2274 || empty_line(&current->data[qdepth]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002275 break;
2276
2277 current = current->prev;
2278 current_y--;
2279 }
2280
2281 /* First line with leading whitespace may be empty. */
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002282 if (strncmp(current->data, samecheck->data, qdepth)
2283 || !strncmp(&current->data[qdepth], quotestr, strlen(quotestr))
2284 || empty_line(&current->data[qdepth])) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002285 if (current->next) {
2286 current = current->next;
2287 current_y++;
2288 } else
2289 return 1;
2290 }
2291 }
2292 initial = current;
2293 initial_y = current_y;
2294
2295 set_modified();
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002296 cutbak = cutbuffer; /* Got to like cutbak ;) */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002297 totbak = totsize;
Chris Allegretta9149e612000-11-27 00:23:41 +00002298 cutbuffer = NULL;
2299
2300 tmptop = current;
2301 tmpjust = copy_node(current);
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002302 samecheck = tmpjust;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002303
2304 /* This is annoying because it mucks with totsize */
Chris Allegretta9149e612000-11-27 00:23:41 +00002305 add_to_cutbuffer(tmpjust);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002306
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002307 /* Put the whole paragraph into one big line. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002308 while (current->next && !isspace((int) current->next->data[0])
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002309 && !strncmp(current->next->data, samecheck->data, qdepth)
2310 && !empty_line(&current->next->data[qdepth])) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002311 filestruct *tmpnode = current->next;
2312 int len = strlen(current->data);
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002313 int len2 = strlen(current->next->data) - qdepth;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002314
Chris Allegretta9149e612000-11-27 00:23:41 +00002315 tmpjust = NULL;
Chris Allegretta9149e612000-11-27 00:23:41 +00002316 tmpjust = copy_node(current->next);
2317 add_to_cutbuffer(tmpjust);
2318
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002319 /* Wiping out a newline */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002320 totsize--;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002321
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002322 /* length of both strings plus space between strings and ending \0. */
2323 current->data = nrealloc(current->data, len + len2 + 2);
2324 current->data[len++] = ' ';
2325 current->data[len] = '\0';
2326
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002327 strncat(current->data, &current->next->data[qdepth], len2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002328
2329 unlink_node(tmpnode);
2330 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002331 }
2332
2333 justify_format(current->data);
2334
2335 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002336 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002337
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002338 if ((strlenpt(current->data) > (fill))
2339 && !no_spaces(current->data)) {
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002340 do {
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002341 int i = 0, j = 0;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002342 int len2 = 0;
2343 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002344
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002345
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002346/* The following code maybe could be better. In particular, can we
2347 * merely increment instead of calling strnlenpt for each new character?
2348 * In fact, can we assume the only tabs are at the beginning of the line?
2349 */
2350/* Note that we CAN break before the first word, since that is how
2351 * pico does it. */
2352 int last_space = -1; /* index of the last breakpoint */
2353 int allowed_width;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002354
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002355 i = qdepth * strlen(quotestr); /* the line starts with
2356 indentation, so we must skip it! */
2357 allowed_width = fill - i; /* how wide can our lines be? */
2358
2359 for(; i<slen; i++) {
2360 if (isspace((int) current->data[i])) last_space = i;
2361 if (last_space!=-1 &&
2362 strnlenpt(current->data,i) >= allowed_width) {
2363 i = last_space;
2364 break;
2365 }
2366 }
2367/* Now data[i] is a space. We want to break at the LAST space in this
2368 * group. Probably, the only possibility is two in a row, but let's be
2369 * generic. Note that we actually replace this final space with \0. Is
2370 * this okay? It seems to work fine. */
2371 for(; i<slen-1 && isspace((int) current->data[i+1]); i++) ;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002372
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002373 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002374
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002375 len2 = strlen(current->data + i + 1);
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002376 tmpline->data = charalloc(len2 + 1 + qdepth);
2377
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002378 for (j = 0; j < qdepth; j += strlen(quotestr))
2379 strcpy(&tmpline->data[j], quotestr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002380
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002381 /* Skip the white space in current. */
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002382 memcpy(&tmpline->data[j], current->data + i + 1, len2);
Chris Allegretta63245302002-03-04 18:12:28 +00002383 tmpline->data[len2 + qdepth] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002384
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002385 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002386
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002387 tmpline->prev = current;
2388 tmpline->next = current->next;
2389 if (current->next != NULL)
2390 current->next->prev = tmpline;
2391
2392 current->next = tmpline;
2393 current = tmpline;
2394 slen -= i + 1;
2395 current_y++;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002396 } while ((strlenpt(current->data) > (fill))
2397 && !no_spaces(current->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002398 }
Chris Allegretta9149e612000-11-27 00:23:41 +00002399 tmpbot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002400
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002401 if (current->next)
2402 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00002403 else
2404 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002405 current_x = 0;
2406 placewewant = 0;
2407
Adam Rogoyski09f97962000-06-20 02:50:33 +00002408 renumber(initial);
2409 totlines = filebot->lineno;
2410
2411 werase(edit);
2412
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002413 if ((current_y < 0) || (current_y >= editwinrows - 1)
2414 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00002415 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002416 center_cursor();
2417 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00002418 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002419 }
2420
Adam Rogoyski09f97962000-06-20 02:50:33 +00002421 edit_refresh();
Chris Allegretta9149e612000-11-27 00:23:41 +00002422 statusbar(_("Can now UnJustify!"));
Chris Allegretta07798352000-11-27 22:58:23 +00002423 /* Change the shortcut list to display the unjustify code */
2424 shortcut_init(1);
2425 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002426 reset_cursor();
2427
Chris Allegretta88520c92001-05-05 17:45:54 +00002428 /* Now get a keystroke and see if it's unjustify; if not, unget the keystroke
Chris Allegretta9149e612000-11-27 00:23:41 +00002429 and return */
Chris Allegretta5f071802001-05-06 02:34:31 +00002430
2431#ifndef DISABLE_MOUSE
2432#ifdef NCURSES_MOUSE_VERSION
2433
2434 /* If it was a mouse click, parse it with do_mouse and it might become
2435 the unjustify key. Else give it back to the input stream. */
2436 if ((kbinput = wgetch(edit)) == KEY_MOUSE)
2437 do_mouse();
2438 else
2439 ungetch(kbinput);
2440#endif
2441#endif
2442
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002443 if ((kbinput = wgetch(edit)) != NANO_UNJUSTIFY_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002444 ungetch(kbinput);
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002445 blank_statusbar_refresh();
2446 } else {
Chris Allegretta9149e612000-11-27 00:23:41 +00002447 /* Else restore the justify we just did (ungrateful user!) */
2448 if (tmptop->prev != NULL)
2449 tmptop->prev->next = tmpbot->next;
Chris Allegrettad022eac2000-11-27 02:50:49 +00002450 else
2451 fileage = current;
Chris Allegretta9149e612000-11-27 00:23:41 +00002452 tmpbot->next->prev = tmptop->prev;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002453 current = tmpbot->next;
Chris Allegretta9149e612000-11-27 00:23:41 +00002454 tmpbot->next = NULL;
2455 do_uncut_text();
Chris Allegrettad022eac2000-11-27 02:50:49 +00002456 if (tmptop->prev == NULL)
2457 edit_refresh();
2458
Chris Allegretta88520c92001-05-05 17:45:54 +00002459 /* Restore totsize from before justify */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002460 totsize = totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002461 free_filestruct(tmptop);
2462 blank_statusbar_refresh();
2463 }
Chris Allegretta4a9c8582000-11-27 22:59:40 +00002464 shortcut_init(0);
2465 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002466 free_filestruct(cutbuffer);
2467 cutbuffer = cutbak;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002468
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002469 return 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002470#endif
2471}
2472
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002473#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002474void help_init(void)
2475{
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002476 int i, sofar = 0, meta_shortcut = 0, helplen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002477 long allocsize = 1; /* How much space we're gonna need for the help text */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002478 char buf[BUFSIZ] = "", *ptr = NULL;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002479 toggle *t;
2480 shortcut *s;
Chris Allegrettab3655b42001-10-22 03:15:31 +00002481
Chris Allegretta7e65d2f2002-02-15 21:12:52 +00002482 helplen = length_of_list(currshortcut);
Chris Allegretta13fd44b2002-01-02 13:59:11 +00002483
Chris Allegrettab3655b42001-10-22 03:15:31 +00002484 /* First set up the initial help text for the current function */
2485 if (currshortcut == whereis_list || currshortcut == replace_list
2486 || currshortcut == replace_list_2)
2487 ptr = _("Search Command Help Text\n\n "
2488 "Enter the words or characters you would like to search "
2489 "for, then hit enter. If there is a match for the text you "
2490 "entered, the screen will be updated to the location of the "
Jordi Mallach773623c2001-10-28 21:00:49 +00002491 "nearest match for the search string.\n\n "
2492 "If using Pico Mode via the -p or --pico flags, using the "
2493 "Meta-P toggle or using a nanorc file, the previous search "
2494 "string will be shown in brackets after the Search: prompt. "
Jordi Mallachf4e57292001-12-26 00:16:40 +00002495 "Hitting enter without entering any text will perform the "
Jordi Mallach773623c2001-10-28 21:00:49 +00002496 "previous search. Otherwise, the previous string will be "
2497 "placed in front of the cursor, and can be edited or deleted "
2498 "before hitting enter.\n\n The following functions keys are "
2499 "available in Search mode:\n\n");
Chris Allegrettab3655b42001-10-22 03:15:31 +00002500 else if (currshortcut == goto_list)
2501 ptr = _("Goto Line Help Text\n\n "
2502 "Enter the line number that you wish to go to and hit "
Jordi Mallach773623c2001-10-28 21:00:49 +00002503 "Enter. If there are fewer lines of text than the "
Chris Allegrettab3655b42001-10-22 03:15:31 +00002504 "number you entered, you will be brought to the last line "
2505 "of the file.\n\n The following functions keys are "
2506 "available in Goto Line mode:\n\n");
2507 else if (currshortcut == insertfile_list)
2508 ptr = _("Insert File Help Text\n\n "
2509 "Type in the name of a file to be inserted into the current "
2510 "file buffer at the current cursor location.\n\n "
2511 "If you have compiled nano with multiple file buffer "
2512 "support, and enable multiple buffers with the -F "
Jordi Mallach773623c2001-10-28 21:00:49 +00002513 "or --multibuffer command line flags, the Meta-F toggle or "
2514 "using a nanorc file, inserting a file will cause it to be "
Chris Allegretta180a5692002-01-02 14:30:33 +00002515 "loaded into a separate buffer (use Meta-< and > to switch "
Chris Allegretta48b06702002-02-22 04:30:50 +00002516 "between file buffers).\n\n If you need another blank "
2517 "buffer, just press Enter at the prompt without typing in a "
2518 "filename, or type in a nonexistent filename at the prompt "
2519 "and press Enter.\n\n The following function keys are "
2520 "available in Insert File mode:\n\n");
Chris Allegrettab3655b42001-10-22 03:15:31 +00002521 else if (currshortcut == writefile_list)
2522 ptr = _("Write File Help Text\n\n "
2523 "Type the name that you wish to save the current file "
2524 "as and hit enter to save the file.\n\n "
2525 "If you are using the marker code with Ctrl-^ and have "
2526 "selected text, you will be prompted to save only the "
2527 "selected portion to a separate file. To reduce the "
2528 "chance of overwriting the current file with just a portion "
2529 "of it, the current filename is not the default in this "
2530 "mode.\n\n The following function keys are available in "
2531 "Write File mode:\n\n");
2532#ifndef DISABLE_BROWSER
2533 else if (currshortcut == browser_list)
2534 ptr = _("File Browser Help Text\n\n "
2535 "The file browser is used to visually browse the "
2536 "directory structure to select a file for reading "
2537 "or writing. You may use the arrow keys or Page Up/"
2538 "Down to browse through the files, and S or Enter to "
2539 "choose the selected file or enter the selected "
2540 "directory. To move up one level, select the directory "
2541 "called \"..\" at the top of the file list.\n\n The "
2542 "following functions keys are available in the file "
2543 "browser:\n\n");
2544 else if (currshortcut == gotodir_list)
2545 ptr = _("Browser Goto Directory Help Text\n\n "
2546 "Enter the name of the directory you would like to "
2547 "browse to.\n\n If tab completion has not been disabled, "
2548 "you can use the TAB key to (attempt to) automatically "
2549 "complete the directory name. The following function "
2550 "keys are available in Browser GotoDir mode:\n\n");
2551#endif
2552 else if (currshortcut == spell_list)
2553 ptr = _("Spell Check Help Text\n\n "
2554 "The spell checker checks the spelling of all text "
2555 "in the current file. When an unknown word is "
2556 "encountered, it is highlighted and a replacement can "
2557 "be edited. It will then prompt to replace every "
2558 "instance of the given misspelled word in the "
2559 "current file.\n\n The following other functions are "
2560 "available in Spell Check mode:\n\n");
2561 else /* Default to the main help list */
2562 ptr = help_text_init;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002563
2564 /* Compute the space needed for the shortcut lists - we add 15 to
2565 have room for the shortcut abbrev and its possible alternate keys */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002566 s = currshortcut;
2567 for (i = 0; i <= helplen - 1; i++) {
2568 if (s->help != NULL)
2569 allocsize += strlen(s->help) + 15;
2570 s = s->next;
2571 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002572
Chris Allegrettab3655b42001-10-22 03:15:31 +00002573 /* If we're on the main list, we also allocate space for toggle help text. */
2574 if (currshortcut == main_list) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002575 for (t = toggles; t != NULL; t = t->next)
2576 if (t->desc != NULL)
2577 allocsize += strlen(t->desc) + 30;
Chris Allegrettab3655b42001-10-22 03:15:31 +00002578 }
2579
2580 allocsize += strlen(ptr);
2581
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002582 if (help_text != NULL)
2583 free(help_text);
2584
2585 /* Allocate space for the help text */
Chris Allegretta88b09152001-05-17 11:35:43 +00002586 help_text = charalloc(allocsize);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002587
2588 /* Now add the text we want */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002589 strcpy(help_text, ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002590
2591 /* Now add our shortcut info */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002592 s = currshortcut;
Chris Allegretta13fd44b2002-01-02 13:59:11 +00002593 for (i = 0; i <= helplen - 1; i++) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002594 if (s->val > 0 && s->val < 'a')
2595 sofar = snprintf(buf, BUFSIZ, "^%c ", s->val + 64);
2596 else {
2597 if (s->altval > 0) {
2598 sofar = 0;
2599 meta_shortcut = 1;
2600 }
2601 else
2602 sofar = snprintf(buf, BUFSIZ, " ");
2603 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002604
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002605 if (!meta_shortcut) {
2606 if (s->misc1 > KEY_F0 && s->misc1 <= KEY_F(64))
2607 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
2608 s->misc1 - KEY_F0);
2609 else
2610 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
2611 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002612
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002613 if (s->altval > 0 && s->altval < 91
2614 && (s->altval - 32) > 32)
2615 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2616 (meta_shortcut ? "M-%c " : "(M-%c) "),
2617 s->altval - 32);
2618 else if (s->altval > 0)
2619 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2620 (meta_shortcut ? "M-%c " : "(M-%c) "),
2621 s->altval);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002622 /* Hack */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002623 else if (s->val >= 'a')
2624 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2625 (meta_shortcut ? "(M-%c) " : "M-%c "),
2626 s->val - 32);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002627 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002628 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002629
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002630 if (meta_shortcut) {
2631 if (s->misc1 > KEY_F0 && s->misc1 <= KEY_F(64))
2632 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2633 "(F%d) ", s->misc1 - KEY_F0);
2634 else
2635 sofar += snprintf(&buf[sofar], BUFSIZ - sofar,
2636 " ");
2637 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002638
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002639 if (s->help != NULL)
2640 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", s->help);
Chris Allegretta756f2202000-09-01 13:32:47 +00002641
2642 strcat(help_text, buf);
2643 strcat(help_text, "\n");
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002644
2645 s = s->next;
Chris Allegretta756f2202000-09-01 13:32:47 +00002646 }
2647
2648 /* And the toggles... */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002649 if (currshortcut == main_list)
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002650 for (t = toggles; t != NULL; t = t->next) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00002651 sofar = snprintf(buf, BUFSIZ,
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002652 "M-%c ", t->val - 32);
2653 if (t->desc != NULL) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00002654 snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002655 t->desc);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002656 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002657 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00002658 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002659 }
2660
2661}
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002662#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002663
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002664void do_toggle(toggle *which)
Chris Allegretta756f2202000-09-01 13:32:47 +00002665{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002666#ifdef NANO_SMALL
2667 nano_disabled_msg();
2668#else
Jordi Mallach2dc0f6b2000-09-07 10:48:00 +00002669 char *enabled = _("enabled");
2670 char *disabled = _("disabled");
Chris Allegrettaf0f63a82000-09-02 18:44:21 +00002671
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002672 switch (which->val) {
Chris Allegretta8d990b52001-09-22 22:14:25 +00002673 case TOGGLE_BACKWARDS_KEY:
2674 case TOGGLE_CASE_KEY:
2675 case TOGGLE_REGEXP_KEY:
2676 return;
2677 }
Chris Allegretta8d990b52001-09-22 22:14:25 +00002678
Chris Allegretta658399a2001-06-14 02:54:22 +00002679 /* Even easier! */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002680 TOGGLE(which->flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002681
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002682 switch (which->val) {
Chris Allegretta756f2202000-09-01 13:32:47 +00002683 case TOGGLE_PICOMODE_KEY:
Chris Allegretta07798352000-11-27 22:58:23 +00002684 shortcut_init(0);
Chris Allegrettac1049ac2001-08-17 00:03:46 +00002685 SET(CLEAR_BACKUPSTRING);
Chris Allegretta756f2202000-09-01 13:32:47 +00002686 display_main_list();
2687 break;
2688 case TOGGLE_SUSPEND_KEY:
2689 signal_init();
2690 break;
2691 case TOGGLE_MOUSE_KEY:
2692 mouse_init();
2693 break;
2694 case TOGGLE_NOHELP_KEY:
Chris Allegretta2a42af12000-09-12 23:02:49 +00002695 wclear(bottomwin);
2696 wrefresh(bottomwin);
2697 window_init();
Chris Allegrettaaffeda82000-12-18 04:03:48 +00002698 fix_editbot();
Chris Allegretta2a42af12000-09-12 23:02:49 +00002699 edit_refresh();
2700 display_main_list();
Chris Allegretta756f2202000-09-01 13:32:47 +00002701 break;
Chris Allegretta99e30e12001-09-23 02:45:27 +00002702 case TOGGLE_DOS_KEY:
2703 UNSET(MAC_FILE);
2704 break;
2705 case TOGGLE_MAC_KEY:
2706 UNSET(DOS_FILE);
2707 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002708 }
Chris Allegretta2a42af12000-09-12 23:02:49 +00002709
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002710 if (!ISSET(which->flag)) {
2711 if (which->val == TOGGLE_NOHELP_KEY ||
2712 which->val == TOGGLE_WRAP_KEY)
2713 statusbar("%s %s", which->desc, enabled);
Chris Allegretta819e3db2001-07-11 02:37:19 +00002714 else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002715 statusbar("%s %s", which->desc, disabled);
Chris Allegretta819e3db2001-07-11 02:37:19 +00002716 } else {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002717 if (which->val == TOGGLE_NOHELP_KEY ||
2718 which->val == TOGGLE_WRAP_KEY)
2719 statusbar("%s %s", which->desc, disabled);
Chris Allegretta819e3db2001-07-11 02:37:19 +00002720 else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002721 statusbar("%s %s", which->desc, enabled);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002722 }
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002723
Chris Allegretta756f2202000-09-01 13:32:47 +00002724#endif
2725}
2726
Chris Allegretta88520c92001-05-05 17:45:54 +00002727/* If the NumLock key has made the keypad go awry, print an error
2728 message; hopefully we can address it later. */
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002729void print_numlock_warning(void)
2730{
2731 static int didmsg = 0;
2732 if (!didmsg) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002733 statusbar(_
2734 ("NumLock glitch detected. Keypad will malfunction with NumLock off"));
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002735 didmsg = 1;
2736 }
2737}
2738
Chris Allegretta1748cd12001-01-13 17:22:54 +00002739/* This function returns the correct keystroke, given the A,B,C or D
2740 input key. This is a common sequence of many terms which send
2741 Esc-O-[A-D] or Esc-[-[A-D]. */
2742int ABCD(int input)
2743{
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002744 switch (input) {
2745 case 'A':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002746 case 'a':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002747 return (KEY_UP);
2748 case 'B':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002749 case 'b':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002750 return (KEY_DOWN);
2751 case 'C':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002752 case 'c':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002753 return (KEY_RIGHT);
2754 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002755 case 'd':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002756 return (KEY_LEFT);
2757 default:
2758 return 0;
Chris Allegretta1748cd12001-01-13 17:22:54 +00002759 }
2760}
2761
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002762int main(int argc, char *argv[])
2763{
2764 int optchr;
2765 int kbinput; /* Input from keyboard */
2766 long startline = 0; /* Line to try and start at */
Chris Allegretta08020882001-01-29 23:37:54 +00002767 int keyhandled; /* Have we handled the keystroke yet? */
Chris Allegretta9caa1932002-02-15 20:08:05 +00002768 int modify_control_seq;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002769 char *argv0;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002770 shortcut *s;
2771 toggle *t;
Chris Allegretta0357c4d2001-09-19 02:59:25 +00002772
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002773#ifdef _POSIX_VDISABLE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002774 struct termios term;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002775#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002776
2777#ifdef HAVE_GETOPT_LONG
2778 int option_index = 0;
2779 struct option long_options[] = {
Chris Allegretta805c26d2000-09-06 13:39:17 +00002780#ifdef HAVE_REGEX_H
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002781 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00002782#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002783 {"version", 0, 0, 'V'},
2784 {"const", 0, 0, 'c'},
2785 {"suspend", 0, 0, 'z'},
2786 {"nowrap", 0, 0, 'w'},
2787 {"nohelp", 0, 0, 'x'},
2788 {"help", 0, 0, 'h'},
Chris Allegretta7492cec2000-12-18 04:55:21 +00002789 {"view", 0, 0, 'v'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002790#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002791 {"cut", 0, 0, 'k'},
Chris Allegretta7004c282001-09-22 00:42:10 +00002792 {"dos", 0, 0, 'D'},
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002793 {"mac", 0, 0, 'M'},
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002794 {"noconvert", 0, 0, 'N'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002795 {"autoindent", 0, 0, 'i'},
Chris Allegrettaff989832001-09-17 13:48:00 +00002796#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002797 {"tempfile", 0, 0, 't'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002798#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002799 {"speller", 1, 0, 's'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002800#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00002801
2802#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002803 {"fill", 1, 0, 'r'},
Chris Allegretta6fe61492001-05-21 12:56:25 +00002804#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002805 {"mouse", 0, 0, 'm'},
Chris Allegrettae1f14522001-09-19 03:19:43 +00002806#ifndef DISABLE_OPERATINGDIR
2807 {"operatingdir", 1, 0, 'o'},
2808#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002809 {"pico", 0, 0, 'p'},
2810 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00002811 {"tabsize", 1, 0, 'T'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002812
Chris Allegretta355fbe52001-07-14 19:32:47 +00002813#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002814 {"multibuffer", 0, 0, 'F'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002815#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002816#ifndef NANO_SMALL
2817 {"smooth", 0, 0, 'S'},
2818#endif
Chris Allegretta48bd3782002-01-03 21:26:34 +00002819 {"keypad", 0, 0, 'K'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002820 {0, 0, 0, 0}
2821 };
2822#endif
2823
2824 /* Flag inits... */
2825 SET(FOLLOW_SYMLINKS);
2826
2827#ifndef NANO_SMALL
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002828#ifdef ENABLE_NLS
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002829 setlocale(LC_ALL, "");
2830 bindtextdomain(PACKAGE, LOCALEDIR);
2831 textdomain(PACKAGE);
2832#endif
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002833#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002834
Chris Allegretta8d8e0122001-04-18 04:28:54 +00002835#ifdef ENABLE_NANORC
2836 do_rcfile();
2837#endif /* ENABLE_NANORC */
2838
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002839#ifdef HAVE_GETOPT_LONG
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002840 while ((optchr = getopt_long(argc, argv, "h?DFKMNQ:RST:Vabcefgijklmo:pr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002841 long_options, &option_index)) != EOF) {
2842#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002843 while ((optchr =
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002844 getopt(argc, argv, "h?DFKMNQ:RST:Vabcefgijklmo:pr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002845#endif
2846
2847 switch (optchr) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002848
Chris Allegretta7004c282001-09-22 00:42:10 +00002849#ifndef NANO_SMALL
2850 case 'D':
2851 SET(DOS_FILE);
2852 break;
2853#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +00002854#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002855 case 'F':
Chris Allegretta355fbe52001-07-14 19:32:47 +00002856 SET(MULTIBUFFER);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002857 break;
2858#endif
Chris Allegretta48bd3782002-01-03 21:26:34 +00002859 case 'K':
2860 SET(ALT_KEYPAD);
2861 break;
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002862#ifndef NANO_SMALL
2863 case 'M':
2864 SET(MAC_FILE);
2865 break;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002866 case 'N':
2867 SET(NO_CONVERT);
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002868 break;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002869#endif
Chris Allegrettae4f940d2002-03-03 22:36:36 +00002870 case 'Q':
2871#ifndef DISABLE_JUSTIFY
2872 quotestr = optarg;
2873 break;
2874#else
2875 usage(); /* To stop bogus data for tab width */
2876 finish(1);
2877#endif
Chris Allegretta805c26d2000-09-06 13:39:17 +00002878#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +00002879 case 'R':
2880 SET(USE_REGEXP);
2881 break;
Chris Allegretta47805612000-07-07 02:35:34 +00002882#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002883#ifndef NANO_SMALL
2884 case 'S':
2885 SET(SMOOTHSCROLL);
2886 break;
2887#endif
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002888 case 'T':
2889 tabsize = atoi(optarg);
2890 if (tabsize <= 0) {
2891 usage(); /* To stop bogus data for tab width */
2892 finish(1);
2893 }
2894 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002895 case 'V':
2896 version();
2897 exit(0);
Chris Allegrettae1f14522001-09-19 03:19:43 +00002898 case 'a':
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002899 case 'b':
2900 case 'e':
2901 case 'f':
Rocco Corsi12f294c2001-04-14 06:50:24 +00002902 case 'g':
2903 case 'j':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002904 /* Pico compatibility flags */
2905 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002906 case 'c':
2907 SET(CONSTUPDATE);
2908 break;
2909 case 'h':
2910 case '?':
2911 usage();
2912 exit(0);
Chris Allegrettaff989832001-09-17 13:48:00 +00002913#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002914 case 'i':
2915 SET(AUTOINDENT);
2916 break;
Chris Allegretta627de192000-07-12 02:09:17 +00002917 case 'k':
2918 SET(CUT_TO_END);
2919 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002920#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002921 case 'l':
2922 UNSET(FOLLOW_SYMLINKS);
2923 break;
2924 case 'm':
2925 SET(USE_MOUSE);
2926 break;
Chris Allegrettae1f14522001-09-19 03:19:43 +00002927#ifndef DISABLE_OPERATINGDIR
2928 case 'o':
2929 operating_dir = charalloc(strlen(optarg) + 1);
2930 strcpy(operating_dir, optarg);
2931
2932 /* make sure we're inside the operating directory */
2933 if (check_operating_dir(".", 0)) {
2934 if (chdir(operating_dir) == -1) {
2935 free(operating_dir);
2936 operating_dir = NULL;
2937 }
2938 }
2939 break;
2940#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002941 case 'p':
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002942 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002943 break;
2944 case 'r':
Chris Allegretta6fe61492001-05-21 12:56:25 +00002945#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002946 fill = atoi(optarg);
Chris Allegretta6fe61492001-05-21 12:56:25 +00002947 if (fill < 0)
2948 wrap_at = fill;
2949 else if (fill == 0) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002950 usage(); /* To stop bogus data (like a string) */
2951 finish(1);
2952 }
2953 break;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002954#else
2955 usage();
2956 exit(0);
2957
2958#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002959#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002960 case 's':
Chris Allegretta88b09152001-05-17 11:35:43 +00002961 alt_speller = charalloc(strlen(optarg) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002962 strcpy(alt_speller, optarg);
2963 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002964#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002965 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00002966 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002967 break;
2968 case 'v':
2969 SET(VIEW_MODE);
2970 break;
2971 case 'w':
Chris Allegrettacef7fbb2001-04-02 05:36:08 +00002972#ifdef DISABLE_WRAPPING
2973 usage();
2974 exit(0);
2975#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002976 SET(NO_WRAP);
2977 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002978#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002979 case 'x':
2980 SET(NO_HELP);
2981 break;
2982 case 'z':
2983 SET(SUSPEND);
2984 break;
2985 default:
2986 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002987 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002988 }
2989
2990 }
2991
2992 argv0 = strrchr(argv[0], '/');
2993 if ((argv0 && strstr(argv0, "pico"))
2994 || (!argv0 && strstr(argv[0], "pico")))
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002995 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002996
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002997 /* See if there's a non-option in argv (first non-option is the
2998 filename, if +LINE is not given) */
2999 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00003000 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003001 else {
3002 /* Look for the +line flag... */
3003 if (argv[optind][0] == '+') {
3004 startline = atoi(&argv[optind][1]);
3005 optind++;
3006 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00003007 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003008 else
Chris Allegretta1a6e9042000-12-14 13:56:28 +00003009 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003010
Chris Allegretta1a6e9042000-12-14 13:56:28 +00003011 } else
3012 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003013 }
3014
3015
3016 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003017 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003018
Chris Allegretta9239d742000-09-06 15:19:18 +00003019#ifdef _POSIX_VDISABLE
Chris Allegretta8f6c0692000-07-19 01:16:18 +00003020 term = oldterm;
3021 term.c_cc[VINTR] = _POSIX_VDISABLE;
3022 term.c_cc[VQUIT] = _POSIX_VDISABLE;
3023 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003024 tcsetattr(0, TCSANOW, &term);
Chris Allegretta9239d742000-09-06 15:19:18 +00003025#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003026
3027 /* now ncurses init stuff... */
3028 initscr();
3029 savetty();
3030 nonl();
3031 cbreak();
3032 noecho();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003033
3034 /* Set up some global variables */
Chris Allegretta56214c62001-09-27 02:46:53 +00003035 global_init(0);
Chris Allegretta07798352000-11-27 22:58:23 +00003036 shortcut_init(0);
Rocco Corsiaf5c3022001-01-12 07:51:05 +00003037#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003038 init_help_msg();
3039 help_init();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00003040#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00003041 signal_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003042
3043#ifdef DEBUG
3044 fprintf(stderr, _("Main: set up windows\n"));
3045#endif
3046
Chris Allegretta2a42af12000-09-12 23:02:49 +00003047 window_init();
Chris Allegretta756f2202000-09-01 13:32:47 +00003048 mouse_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003049
Chris Allegretta48bd3782002-01-03 21:26:34 +00003050 if (!ISSET(ALT_KEYPAD)) {
3051 keypad(edit, TRUE);
3052 keypad(bottomwin, TRUE);
3053 }
3054
Chris Allegretta08893e02001-11-29 02:42:27 +00003055#ifdef ENABLE_COLOR
3056 do_colorinit();
3057
Chris Allegretta08893e02001-11-29 02:42:27 +00003058#endif /* ENABLE_COLOR */
3059
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003060#ifdef DEBUG
3061 fprintf(stderr, _("Main: bottom win\n"));
3062#endif
Chris Allegretta88520c92001-05-05 17:45:54 +00003063 /* Set up bottom of window */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003064 display_main_list();
3065
3066#ifdef DEBUG
3067 fprintf(stderr, _("Main: open file\n"));
3068#endif
3069
Chris Allegrettaf4b96012001-01-03 07:11:47 +00003070 titlebar(NULL);
Chris Allegretta31c76662000-11-21 06:20:20 +00003071
3072 /* Now we check to see if argv[optind] is non-null to determine if
3073 we're dealing with a new file or not, not argc == 1... */
3074 if (argv[optind] == NULL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003075 new_file();
3076 else
3077 open_file(filename, 0, 0);
3078
3079 if (startline > 0)
Chris Allegretta2d7893d2001-07-11 02:08:33 +00003080 do_gotoline(startline, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003081 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00003082 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003083
Chris Allegretta08020882001-01-29 23:37:54 +00003084 /* return here after a sigwinch */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003085 sigsetjmp(jmpbuf, 1);
Chris Allegretta08020882001-01-29 23:37:54 +00003086
3087 /* Fix clobber-age */
3088 kbinput = 0;
3089 keyhandled = 0;
3090 modify_control_seq = 0;
3091
Robert Siemborski6967eec2000-07-08 14:23:32 +00003092 edit_refresh();
3093 reset_cursor();
3094
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003095 while (1) {
Chris Allegretta9239d742000-09-06 15:19:18 +00003096
Chris Allegretta6fe61492001-05-21 12:56:25 +00003097#ifndef DISABLE_MOUSE
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003098 currshortcut = main_list;
Chris Allegretta6fe61492001-05-21 12:56:25 +00003099#endif
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003100
Chris Allegretta9239d742000-09-06 15:19:18 +00003101#ifndef _POSIX_VDISABLE
3102 /* We're going to have to do it the old way, i.e. on cygwin */
3103 raw();
3104#endif
3105
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003106 kbinput = wgetch(edit);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003107#ifdef DEBUG
3108 fprintf(stderr, "AHA! %c (%d)\n", kbinput, kbinput);
3109#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003110
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003111 if (kbinput == 27) { /* Grab Alt-key stuff first */
3112 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003113 /* Alt-O, suddenly very important ;) */
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003114 case 'O':
Chris Allegretta16e41682000-09-11 22:33:54 +00003115 kbinput = wgetch(edit);
Chris Allegretta316e4d92001-04-28 16:31:19 +00003116 if ((kbinput <= 'D' && kbinput >= 'A') ||
3117 (kbinput <= 'd' && kbinput >= 'a'))
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003118 kbinput = ABCD(kbinput);
Chris Allegretta201d9bf2001-01-14 03:17:53 +00003119 else if (kbinput <= 'z' && kbinput >= 'j')
3120 print_numlock_warning();
3121 else if (kbinput <= 'S' && kbinput >= 'P')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003122 kbinput = KEY_F(kbinput - 79);
Chris Allegretta16e41682000-09-11 22:33:54 +00003123#ifdef DEBUG
3124 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003125 fprintf(stderr, _("I got Alt-O-%c! (%d)\n"),
3126 kbinput, kbinput);
3127 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003128 }
3129#endif
3130 break;
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003131 case 27:
3132 /* If we get Alt-Alt, the next keystroke should be the same as a
3133 control sequence */
3134 modify_control_seq = 1;
3135 keyhandled = 1;
3136 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00003137#ifndef NANO_SMALL
Chris Allegretta76e291b2001-10-14 19:05:10 +00003138 case ' ':
3139 /* If control-space is next word, Alt-space should be previous word */
3140 do_prev_word();
3141 keyhandled = 1;
3142 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00003143#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003144 case '[':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003145 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003146 case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */
Chris Allegretta16e41682000-09-11 22:33:54 +00003147 kbinput = wgetch(edit);
3148 if (kbinput >= '1' && kbinput <= '5') {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003149 kbinput = KEY_F(kbinput - 48);
3150 wgetch(edit);
3151 } else if (kbinput >= '7' && kbinput <= '9') {
3152 kbinput = KEY_F(kbinput - 49);
3153 wgetch(edit);
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003154 } else if (kbinput == '~')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003155 kbinput = KEY_HOME;
Chris Allegretta16e41682000-09-11 22:33:54 +00003156
3157#ifdef DEBUG
3158 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003159 fprintf(stderr, _("I got Alt-[-1-%c! (%d)\n"),
3160 kbinput, kbinput);
3161 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003162 }
3163#endif
3164
3165 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003166 case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */
Chris Allegretta16e41682000-09-11 22:33:54 +00003167 kbinput = wgetch(edit);
Chris Allegretta16e41682000-09-11 22:33:54 +00003168 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003169 case '0':
3170 kbinput = KEY_F(9);
3171 wgetch(edit);
3172 break;
3173 case '1':
3174 kbinput = KEY_F(10);
3175 wgetch(edit);
3176 break;
3177 case '3':
3178 kbinput = KEY_F(11);
3179 wgetch(edit);
3180 break;
3181 case '4':
3182 kbinput = KEY_F(12);
3183 wgetch(edit);
3184 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003185 case '~':
3186 goto do_insertkey;
Chris Allegretta16e41682000-09-11 22:33:54 +00003187#ifdef DEBUG
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003188 default:
3189 fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"),
3190 kbinput, kbinput);
3191 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003192#endif
3193
3194 }
3195 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003196 case '3': /* Alt-[-3 = Delete? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003197 kbinput = NANO_DELETE_KEY;
3198 wgetch(edit);
3199 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003200 case '4': /* Alt-[-4 = End? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003201 kbinput = NANO_END_KEY;
3202 wgetch(edit);
3203 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003204 case '5': /* Alt-[-5 = Page Up */
Chris Allegretta16e41682000-09-11 22:33:54 +00003205 kbinput = KEY_PPAGE;
3206 wgetch(edit);
3207 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003208 case 'V': /* Alt-[-V = Page Up in Hurd Console */
Chris Allegretta7bf72742001-10-28 04:29:55 +00003209 case 'I': /* Alt-[-I = Page Up - FreeBSD Console */
3210 kbinput = KEY_PPAGE;
3211 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003212 case '6': /* Alt-[-6 = Page Down */
Chris Allegretta16e41682000-09-11 22:33:54 +00003213 kbinput = KEY_NPAGE;
3214 wgetch(edit);
3215 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003216 case 'U': /* Alt-[-U = Page Down in Hurd Console */
Chris Allegretta7bf72742001-10-28 04:29:55 +00003217 case 'G': /* Alt-[-G = Page Down - FreeBSD Console */
3218 kbinput = KEY_NPAGE;
3219 break;
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003220 case '7':
3221 kbinput = KEY_HOME;
3222 wgetch(edit);
3223 break;
3224 case '8':
3225 kbinput = KEY_END;
3226 wgetch(edit);
3227 break;
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003228 case '9': /* Alt-[-9 = Delete in Hurd Console */
3229 kbinput = KEY_DC;
3230 break;
Chris Allegretta32da4562002-01-02 15:12:21 +00003231 case '@': /* Alt-[-@ = Insert in Hurd Console */
3232 case 'L': /* Alt-[-L = Insert - FreeBSD Console */
3233 goto do_insertkey;
3234 case '[': /* Alt-[-[-[A-E], F1-F5 in Linux console */
Chris Allegretta16e41682000-09-11 22:33:54 +00003235 kbinput = wgetch(edit);
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003236 if (kbinput >= 'A' && kbinput <= 'E')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003237 kbinput = KEY_F(kbinput - 64);
Chris Allegretta16e41682000-09-11 22:33:54 +00003238 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003239 case 'A':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003240 case 'B':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003241 case 'C':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003242 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00003243 case 'a':
3244 case 'b':
3245 case 'c':
3246 case 'd':
Chris Allegretta1748cd12001-01-13 17:22:54 +00003247 kbinput = ABCD(kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003248 break;
3249 case 'H':
3250 kbinput = KEY_HOME;
3251 break;
3252 case 'F':
Chris Allegretta9b8b3702001-11-19 05:09:15 +00003253 case 'Y': /* End Key in Hurd Console */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003254 kbinput = KEY_END;
3255 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003256 default:
3257#ifdef DEBUG
3258 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
3259 kbinput, kbinput);
3260#endif
3261 break;
3262 }
3263 break;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003264
Chris Allegretta355fbe52001-07-14 19:32:47 +00003265#ifdef ENABLE_MULTIBUFFER
Chris Allegretta819e3db2001-07-11 02:37:19 +00003266 case NANO_OPENPREV_KEY:
Chris Allegretta180a5692002-01-02 14:30:33 +00003267 case NANO_OPENPREV_ALTKEY:
Chris Allegretta819e3db2001-07-11 02:37:19 +00003268 open_prevfile(0);
3269 keyhandled = 1;
3270 break;
3271 case NANO_OPENNEXT_KEY:
Chris Allegretta180a5692002-01-02 14:30:33 +00003272 case NANO_OPENNEXT_ALTKEY:
Chris Allegretta819e3db2001-07-11 02:37:19 +00003273 open_nextfile(0);
3274 keyhandled = 1;
3275 break;
Chris Allegretta9cf9e062001-07-11 12:06:13 +00003276#endif
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003277
3278#if !defined (NANO_SMALL) && defined (HAVE_REGEX_H)
3279 case NANO_BRACKET_KEY:
3280 do_find_bracket();
3281 keyhandled = 1;
3282 break;
3283#endif
3284
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003285 default:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003286 /* Check for the altkey defs.... */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003287 for (s = main_list; s != NULL; s = s->next)
3288 if (kbinput == s->altval ||
3289 kbinput == s->altval - 32) {
3290 kbinput = s->val;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003291 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003292 }
Chris Allegretta756f2202000-09-01 13:32:47 +00003293#ifndef NANO_SMALL
3294 /* And for toggle switches */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003295 for (t = toggles; t != NULL && !keyhandled; t = t->next)
3296 if (kbinput == t->val ||
3297 (t->val > 'a' &&
3298 kbinput == t->val - 32)) {
3299 do_toggle(t);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003300 keyhandled = 1;
3301 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00003302 }
3303#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003304#ifdef DEBUG
3305 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
3306 kbinput);
3307#endif
3308 break;
3309 }
3310 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003311 /* If the modify_control_seq is set, we received an Alt-Alt
3312 sequence before this, so we make this key a control sequence
3313 by subtracting 64 or 96, depending on its value. */
3314 if (!keyhandled && modify_control_seq) {
3315 if (kbinput >= 'A' && kbinput < 'a')
3316 kbinput -= 64;
3317 else if (kbinput >= 'a' && kbinput <= 'z')
3318 kbinput -= 96;
3319
3320 modify_control_seq = 0;
3321 }
3322
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003323 /* Look through the main shortcut list to see if we've hit a
3324 shortcut key */
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003325
Chris Allegrettaf5de33a2002-02-27 04:14:16 +00003326#if !defined(DISABLE_BROWSER) || !defined(DISABLE_MOUSE) || !defined (DISABLE_HELP)
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003327 for (s = currshortcut; s != NULL && !keyhandled; s = s->next) {
Chris Allegrettaf5de33a2002-02-27 04:14:16 +00003328#else
3329 for (s = main_list; s != NULL && !keyhandled; s = s->next) {
3330#endif
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003331 if (kbinput == s->val ||
3332 (s->misc1 && kbinput == s->misc1) ||
3333 (s->misc2 && kbinput == s->misc2)) {
3334 if (ISSET(VIEW_MODE) && !s->viewok)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003335 print_view_warning();
3336 else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003337 s->func();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003338 keyhandled = 1;
3339 }
3340 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003341 /* If we're in raw mode or using Alt-Alt-x, we have to catch
3342 Control-S and Control-Q */
Chris Allegretta9239d742000-09-06 15:19:18 +00003343 if (kbinput == 17 || kbinput == 19)
3344 keyhandled = 1;
3345
Chris Allegretta9caa1932002-02-15 20:08:05 +00003346 /* Catch ^Z by hand when triggered also
3347 407 == ^Z in Linux console when keypad() is used? */
3348 if (kbinput == 26 || kbinput == 407) {
Chris Allegretta9239d742000-09-06 15:19:18 +00003349 if (ISSET(SUSPEND))
3350 do_suspend(0);
3351 keyhandled = 1;
3352 }
Chris Allegretta9239d742000-09-06 15:19:18 +00003353
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003354
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003355#ifndef USE_SLANG
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003356 /* Hack, make insert key do something useful, like insert file */
3357 if (kbinput == KEY_IC) {
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003358#else
3359 if (0) {
3360#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003361 do_insertkey:
3362
3363#ifdef ENABLE_MULTIBUFFER
Chris Allegretta32da4562002-01-02 15:12:21 +00003364 /* do_insertfile_void() contains the logic needed to
3365 handle view mode with the view mode/multibuffer
3366 exception, so use it here */
3367 do_insertfile_void();
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003368#else
Chris Allegretta32da4562002-01-02 15:12:21 +00003369 print_view_warning();
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003370#endif
3371
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003372 keyhandled = 1;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003373 }
3374
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003375 /* Last gasp, stuff that's not in the main lists */
3376 if (!keyhandled)
3377 switch (kbinput) {
Chris Allegretta84de5522001-04-12 14:51:48 +00003378#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003379#ifdef NCURSES_MOUSE_VERSION
3380 case KEY_MOUSE:
3381 do_mouse();
3382 break;
3383#endif
3384#endif
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003385
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003386 case 0: /* Erg */
Chris Allegretta48ebb812001-10-24 01:34:15 +00003387#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003388 do_next_word();
3389 break;
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003390#endif
Chris Allegrettaf4f7e042001-01-04 16:56:15 +00003391
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003392 case -1: /* Stuff that we don't want to do squat */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003393 case 410: /* Must ignore this, it gets sent when we resize */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003394 case 29: /* Ctrl-] */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003395#ifdef PDCURSES
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003396 case 541: /* ???? */
3397 case 542: /* Control and alt in Windows *shrug* */
Chris Allegretta72623582000-11-29 23:43:28 +00003398 case 543: /* Right ctrl key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003399 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +00003400 case 545: /* Right alt key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003401#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003402
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003403 break;
3404 default:
3405#ifdef DEBUG
3406 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
3407#endif
3408 /* We no longer stop unhandled sequences so that people with
3409 odd character sets can type... */
3410
3411 if (ISSET(VIEW_MODE)) {
3412 print_view_warning();
3413 break;
3414 }
3415 do_char(kbinput);
3416 }
Chris Allegretta7fdbd052001-10-02 00:55:38 +00003417 if (ISSET(DISABLE_CURPOS))
3418 UNSET(DISABLE_CURPOS);
3419 else if (ISSET(CONSTUPDATE))
Chris Allegretta2084acc2001-11-29 03:43:08 +00003420 do_cursorpos(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003421
3422 reset_cursor();
3423 wrefresh(edit);
3424 keyhandled = 0;
3425 }
3426
3427 getchar();
3428 finish(0);
3429
3430}