blob: 1357b616c70736ed89fe830afc20327644e64a0a [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * nano.c *
4 * *
5 * Copyright (C) 1999 Chris Allegretta *
6 * 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 *
8 * the Free Software Foundation; either version 1, or (at your option) *
9 * 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 Allegrettaa2ea1932000-06-06 05:53:49 +000067int fill = 0; /* Fill - where to wrap lines, basically */
Chris Allegretta6fe61492001-05-21 12:56:25 +000068int wrap_at = 0; /* Right justified fill value, allows resize */
69#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
103 exit(sigage);
104}
105
106/* Die (gracefully?) */
107void die(char *msg, ...)
108{
109 va_list ap;
110
111 va_start(ap, msg);
112 vfprintf(stderr, msg, ap);
113 va_end(ap);
114
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000115 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000116 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000117
118 clear();
119 refresh();
120 resetty();
121 endwin();
122
123 fprintf(stderr, msg);
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000124
125 /* save the currently loaded file (if modified, its open_files entry
126 isn't up to date) */
127 die_save_file(filename);
128
Chris Allegretta355fbe52001-07-14 19:32:47 +0000129#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000130 /* then save all of the other loaded files, if any */
131 if (open_files) {
132 filestruct *tmp;
133
134 tmp = open_files;
135
136 while (open_files->prev)
137 open_files = open_files->prev;
138
139 while (open_files->next) {
140
141 /* if we already saved the file above (i. e. if it was the
142 currently loaded file), don't save it again */
143 if (tmp != open_files) {
144 fileage = open_files->file;
145 die_save_file(open_files->data);
146 }
147
148 open_files = open_files->next;
149 }
150
151 }
152#endif
153
154 exit(1); /* We have a problem: exit w/ errorlevel(1) */
155}
156
157void die_save_file(char *die_filename)
158{
159 char *name;
160 int i;
161
162 /* if we can't save we have REAL bad problems,
163 * but we might as well TRY. */
164 if (die_filename[0] == '\0') {
165 name = "nano.save";
166 i = write_file(name, 1, 0, 0);
167 } else {
168
169 char *buf = charalloc(strlen(die_filename) + 6);
170 strcpy(buf, die_filename);
171 strcat(buf, ".save");
172 i = write_file(buf, 1, 0, 0);
173 name = buf;
174 }
175
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000176 if (i != -1)
177 fprintf(stderr, _("\nBuffer written to %s\n"), name);
178 else
Chris Allegretta9756d622000-12-03 03:06:45 +0000179 fprintf(stderr, _("\nNo %s written (file exists?)\n"), name);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000180}
181
Chris Allegrettae61e8302001-01-14 05:18:27 +0000182/* Die with an error message that the screen was too small if, well, the
183 screen is too small */
184void die_too_small(void)
185{
186 char *too_small_msg = _("Window size is too small for Nano...");
187
188 die(too_small_msg);
189
190}
191
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000192void print_view_warning(void)
193{
194 statusbar(_("Key illegal in VIEW mode"));
195}
196
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000197void clear_filename(void)
198{
199 if (filename != NULL)
200 free(filename);
Chris Allegretta88b09152001-05-17 11:35:43 +0000201 filename = charalloc(1);
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000202 filename[0] = 0;
203}
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +0000204
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000205/* Initialize global variables - no better way for now */
206void global_init(void)
207{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000208 current_x = 0;
209 current_y = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000210
211 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
212 die_too_small();
213
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000214 fileage = NULL;
215 cutbuffer = NULL;
216 current = NULL;
217 edittop = NULL;
218 editbot = NULL;
219 totlines = 0;
220 placewewant = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000221
Chris Allegretta6fe61492001-05-21 12:56:25 +0000222#ifndef DISABLE_WRAPJUSTIFY
223 if (wrap_at)
224 fill = COLS + wrap_at;
225 else if (!fill)
Chris Allegrettae61e8302001-01-14 05:18:27 +0000226 fill = COLS - CHARS_FROM_EOL;
227
228 if (fill < MIN_FILL_LENGTH)
229 die_too_small();
Chris Allegretta6fe61492001-05-21 12:56:25 +0000230#endif
Chris Allegrettae61e8302001-01-14 05:18:27 +0000231
Chris Allegretta88b09152001-05-17 11:35:43 +0000232 hblank = charalloc(COLS + 1);
Chris Allegretta0a06e072001-01-23 02:35:04 +0000233 memset(hblank, ' ', COLS);
234 hblank[COLS] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000235}
236
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000237#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000238void init_help_msg(void)
239{
240
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000241 help_text_init =
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000242 _(" nano help text\n\n "
243 "The nano editor is designed to emulate the functionality and "
244 "ease-of-use of the UW Pico text editor. There are four main "
245 "sections of the editor: The top line shows the program "
246 "version, the current filename being edited, and whether "
247 "or not the file has been modified. Next is the main editor "
248 "window showing the file being edited. The status line is "
249 "the third line from the bottom and shows important messages. "
250 "The bottom two lines show the most commonly used shortcuts "
251 "in the editor.\n\n "
252 "The notation for shortcuts is as follows: Control-key "
Chris Allegrettae49f1232000-09-02 07:20:39 +0000253 "sequences are notated with a caret (^) symbol and are entered "
Chris Allegrettad56bd792000-09-02 07:27:10 +0000254 "with the Control (Ctrl) key. Escape-key sequences are notated "
255 "with the Meta (M) symbol and can be entered using either the "
256 "Esc, Alt or Meta key depending on your keyboard setup. The "
257 "following keystrokes are available in the main editor window. "
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000258 "Optional keys are shown in parentheses:\n\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000259
260}
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000261#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000262
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000263/* Make a copy of a node to a pointer (space will be malloc()ed). This
264 does NOT copy the data members used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000265filestruct *copy_node(filestruct * src)
266{
267 filestruct *dst;
268
269 dst = nmalloc(sizeof(filestruct));
Chris Allegretta88b09152001-05-17 11:35:43 +0000270 dst->data = charalloc(strlen(src->data) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000271
272 dst->next = src->next;
273 dst->prev = src->prev;
274
275 strcpy(dst->data, src->data);
276 dst->lineno = src->lineno;
277
278 return dst;
279}
280
281/* Unlink a node from the rest of the struct */
282void unlink_node(filestruct * fileptr)
283{
284 if (fileptr->prev != NULL)
285 fileptr->prev->next = fileptr->next;
286
287 if (fileptr->next != NULL)
288 fileptr->next->prev = fileptr->prev;
289}
290
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000291/* Delete a node from the struct. This does NOT delete the data members
292 used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000293void delete_node(filestruct * fileptr)
294{
Chris Allegretta17dcb722001-01-20 21:40:07 +0000295 if (fileptr == NULL)
296 return;
297
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000298 if (fileptr->data != NULL)
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000299 free(fileptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000300 free(fileptr);
301}
302
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000303/* Okay, now let's duplicate a whole struct! This does NOT duplicate the
304 data members used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000305filestruct *copy_filestruct(filestruct * src)
306{
307 filestruct *dst, *tmp, *head, *prev;
308
309 head = copy_node(src);
310 dst = head; /* Else we barf on copying just one line */
311 head->prev = NULL;
312 tmp = src->next;
313 prev = head;
314
315 while (tmp != NULL) {
316 dst = copy_node(tmp);
317 dst->prev = prev;
318 prev->next = dst;
319
320 prev = dst;
321 tmp = tmp->next;
322 }
323
324 dst->next = NULL;
325 return head;
326}
327
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000328/* Frees a struct. This does NOT free the data members used only by
329 open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000330int free_filestruct(filestruct * src)
331{
332 filestruct *fileptr = src;
333
334 if (src == NULL)
335 return 0;
336
337 while (fileptr->next != NULL) {
338 fileptr = fileptr->next;
Chris Allegretta17dcb722001-01-20 21:40:07 +0000339 delete_node(fileptr->prev);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000340
341#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000342 fprintf(stderr, _("delete_node(): free'd a node, YAY!\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000343#endif
344 }
Chris Allegretta17dcb722001-01-20 21:40:07 +0000345 delete_node(fileptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000346#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000347 fprintf(stderr, _("delete_node(): free'd last node.\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000348#endif
349
350 return 1;
351}
352
353int renumber_all(void)
354{
355 filestruct *temp;
356 long i = 1;
357
358 for (temp = fileage; temp != NULL; temp = temp->next) {
359 temp->lineno = i++;
360 }
361
362 return 0;
363}
364
365int renumber(filestruct * fileptr)
366{
367 filestruct *temp;
368
369 if (fileptr == NULL || fileptr->prev == NULL || fileptr == fileage) {
370 renumber_all();
371 return 0;
372 }
373 for (temp = fileptr; temp != NULL; temp = temp->next) {
Chris Allegretta5146fec2000-12-10 05:44:02 +0000374 if (temp->prev != NULL)
375 temp->lineno = temp->prev->lineno + 1;
376 else
377 temp->lineno = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000378 }
379
380 return 0;
381}
382
383/* Fix the memory allocation for a string */
384void align(char **strp)
385{
386 /* There was a serious bug here: the new address was never
387 stored anywhere... */
388
389 *strp = nrealloc(*strp, strlen(*strp) + 1);
390}
391
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000392/* Null a string at a certain index and align it */
393void null_at(char *data, int index)
394{
395 data[index] = 0;
396 align(&data);
397}
398
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000399void usage(void)
400{
401#ifdef HAVE_GETOPT_LONG
402 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
403 printf(_("Option Long option Meaning\n"));
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000404
Chris Allegretta355fbe52001-07-14 19:32:47 +0000405#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000406 printf
407 (_
Chris Allegretta355fbe52001-07-14 19:32:47 +0000408 (" -F --multibuffer Enable multiple file buffers\n"));
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000409#endif
410
Chris Allegretta6724a7e2000-06-19 23:19:07 +0000411 printf(_
Chris Allegrettae9a2d032001-01-21 16:08:21 +0000412 (" -T [num] --tabsize=[num] Set width of a tab to num\n"));
Chris Allegretta805c26d2000-09-06 13:39:17 +0000413#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000414 printf(_
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000415 (" -R --regexp Use regular expressions for search\n"));
Chris Allegretta47805612000-07-07 02:35:34 +0000416#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000417 printf
418 (_
419 (" -V --version Print version information and exit\n"));
420 printf(_
421 (" -c --const Constantly show cursor position\n"));
422 printf(_
423 (" -h --help Show this message\n"));
Chris Allegrettad55655f2000-12-27 03:36:47 +0000424 printf(_
425 (" -i --autoindent Automatically indent new lines\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000426#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000427 printf(_
Chris Allegretta627de192000-07-12 02:09:17 +0000428 (" -k --cut Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000429#endif
Chris Allegretta627de192000-07-12 02:09:17 +0000430 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000431 (" -l --nofollow Don't follow symbolic links, overwrite\n"));
Chris Allegretta84de5522001-04-12 14:51:48 +0000432#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000433#ifdef NCURSES_MOUSE_VERSION
434 printf(_(" -m --mouse Enable mouse\n"));
435#endif
436#endif
Chris Allegrettad55655f2000-12-27 03:36:47 +0000437 printf(_
438 (" -p --pico Emulate Pico as closely as possible\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000439
440#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000441 printf
442 (_
443 (" -r [#cols] --fill=[#cols] Set fill cols to (wrap lines at) #cols\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000444#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000445#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000446 printf(_
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000447 (" -s [prog] --speller=[prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000448#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000449 printf(_
450 (" -t --tempfile Auto save on exit, don't prompt\n"));
451 printf(_
452 (" -v --view View (read only) mode\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000453#ifndef DISABLE_WRAPPING
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000454 printf(_
455 (" -w --nowrap Don't wrap long lines\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000456#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000457 printf(_
458 (" -x --nohelp Don't show help window\n"));
459 printf(_
460 (" -z --suspend Enable suspend\n"));
461 printf(_
462 (" +LINE Start at line number LINE\n"));
463#else
464 printf(_("Usage: nano [option] +LINE <file>\n\n"));
465 printf(_("Option Meaning\n"));
Chris Allegretta355fbe52001-07-14 19:32:47 +0000466#ifdef ENABLE_MULTIBUFFER
467 printf(_(" -F Enable multiple file buffers\n"));
468#endif
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000469 printf(_(" -T [num] Set width of a tab to num\n"));
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000470 printf(_(" -R Use regular expressions for search\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000471 printf(_(" -V Print version information and exit\n"));
472 printf(_(" -c Constantly show cursor position\n"));
473 printf(_(" -h Show this message\n"));
Chris Allegrettad55655f2000-12-27 03:36:47 +0000474 printf(_(" -i Automatically indent new lines\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000475#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +0000476 printf(_(" -k Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000477#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000478 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000479 (" -l Don't follow symbolic links, overwrite\n"));
Chris Allegretta84de5522001-04-12 14:51:48 +0000480#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000481#ifdef NCURSES_MOUSE_VERSION
482 printf(_(" -m Enable mouse\n"));
483#endif
484#endif
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +0000485 printf(_(" -p Emulate Pico as closely as possible\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000486
487#ifndef DISABLE_WRAPJUSTIFY
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000488 printf(_
489 (" -r [#cols] Set fill cols to (wrap lines at) #cols\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000490#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000491#ifndef DISABLE_SPELLER
Chris Allegrettad55655f2000-12-27 03:36:47 +0000492 printf(_(" -s [prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000493#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000494 printf(_(" -t Auto save on exit, don't prompt\n"));
495 printf(_(" -v View (read only) mode\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000496#ifndef DISABLE_WRAPPING
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000497 printf(_(" -w Don't wrap long lines\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000498#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000499 printf(_(" -x Don't show help window\n"));
500 printf(_(" -z Enable suspend\n"));
501 printf(_(" +LINE Start at line number LINE\n"));
502#endif
503 exit(0);
504}
505
506void version(void)
507{
Chris Allegrettac46dd812001-02-14 14:28:27 +0000508 printf(_(" GNU nano version %s (compiled %s, %s)\n"),
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000509 VERSION, __TIME__, __DATE__);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000510 printf(_
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000511 (" Email: nano@nano-editor.org Web: http://www.nano-editor.org"));
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000512 printf(_("\n Compiled options:"));
Chris Allegrettaff269f82000-12-01 18:46:01 +0000513
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000514#ifdef NANO_EXTRA
515 printf(" --enable-extra");
Chris Allegretta355fbe52001-07-14 19:32:47 +0000516#else
517#ifdef ENABLE_MULTIBUFFER
518 printf(" --enable-multibuffer");
519#endif /* ENABLE_MULTIBUFFER */
520#endif /* NANO_EXTRA */
521
Chris Allegrettab881d3e2001-04-18 04:34:43 +0000522#ifdef ENABLE_NANORC
523 printf(" --enable-nanorc");
524#endif
Chris Allegretta8ce24132001-04-30 11:28:46 +0000525#ifdef ENABLE_COLOR
526 printf(" --enable-color");
527#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000528
529#ifdef NANO_SMALL
530 printf(" --enable-tiny");
531#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000532#ifdef DISABLE_BROWSER
Chris Allegretta6636dc32001-01-05 05:41:07 +0000533 printf(" --disable-browser");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000534#endif
535#ifdef DISABLE_TABCOMP
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000536 printf(" --disable-tabcomp");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000537#endif
538#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +0000539 printf(" --disable-justify");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000540#endif
541#ifdef DISABLE_SPELLER
Chris Allegretta7b36c522000-12-06 01:08:10 +0000542 printf(" --disable-speller");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000543#endif
544#ifdef DISABLE_HELP
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000545 printf(" --disable-help");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000546#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000547#ifdef DISABLE_MOUSE
548 printf(" --disable-mouse");
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000549#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000550#endif /* NANO_SMALL */
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000551
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000552#ifdef DISABLE_WRAPPING
553 printf(" --disable-wrapping");
554#endif
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000555#ifdef USE_SLANG
556 printf(" --with-slang");
557#endif
558 printf("\n");
559
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000560}
561
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000562/* Create a new node. This does NOT initialize the data members used
563 only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000564filestruct *make_new_node(filestruct * prevnode)
565{
566 filestruct *newnode;
567
568 newnode = nmalloc(sizeof(filestruct));
569 newnode->data = NULL;
570
571 newnode->prev = prevnode;
572 newnode->next = NULL;
573
574 if (prevnode != NULL)
575 newnode->lineno = prevnode->lineno + 1;
576
577 return newnode;
578}
579
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000580/* Splice a node into an existing filestruct. This does NOT set the data
581 members used only by open_files. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000582void splice_node(filestruct * begin, filestruct * newnode,
583 filestruct * end)
Chris Allegretta7975ed82000-07-28 00:58:35 +0000584{
Chris Allegrettae3167732001-03-18 16:59:34 +0000585 newnode->next = end;
586 newnode->prev = begin;
587 begin->next = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000588 if (end != NULL)
Chris Allegrettae3167732001-03-18 16:59:34 +0000589 end->prev = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000590}
591
Chris Allegrettae3167732001-03-18 16:59:34 +0000592int do_mark(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000593{
594#ifdef NANO_SMALL
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000595 nano_disabled_msg();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000596#else
597 if (!ISSET(MARK_ISSET)) {
598 statusbar(_("Mark Set"));
599 SET(MARK_ISSET);
600 mark_beginbuf = current;
601 mark_beginx = current_x;
602 } else {
603 statusbar(_("Mark UNset"));
604 UNSET(MARK_ISSET);
605 mark_beginbuf = NULL;
606 mark_beginx = 0;
607
608 edit_refresh();
609 }
610#endif
Chris Allegretta41ed0162001-07-24 00:21:03 +0000611 SET(DISABLE_CURPOS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000612 return 1;
613}
614
615int no_help(void)
616{
617 if ISSET
618 (NO_HELP)
619 return 2;
620 else
621 return 0;
622}
623
Chris Allegretta3bc8c722000-12-10 17:03:25 +0000624#if defined(DISABLE_JUSTIFY) || defined(DISABLE_SPELLER) || defined(DISABLE_HELP)
Chris Allegrettaff269f82000-12-01 18:46:01 +0000625void nano_disabled_msg(void)
626{
627 statusbar("Sorry, support for this function has been disabled");
628}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000629#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000630
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000631/* The user typed a printable character; add it to the edit buffer */
632void do_char(char ch)
633{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000634 /* magic-line: when a character is inserted on the current magic line,
635 * it means we need a new one! */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000636 if (filebot == current && current->data[0] == '\0') {
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000637 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000638 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000639 }
640
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000641 /* More dangerousness fun =) */
642 current->data = nrealloc(current->data, strlen(current->data) + 2);
643 memmove(&current->data[current_x + 1],
644 &current->data[current_x],
645 strlen(current->data) - current_x + 1);
646 current->data[current_x] = ch;
647 do_right();
648
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000649#ifndef DISABLE_WRAPPING
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000650 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000651 check_wrap(current, ch);
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000652#endif
653
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000654 set_modified();
655 check_statblank();
656 UNSET(KEEP_CUTBUFFER);
657 totsize++;
658
659}
660
661/* Someone hits return *gasp!* */
662int do_enter(filestruct * inptr)
663{
Chris Allegrettae3167732001-03-18 16:59:34 +0000664 filestruct *newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000665 char *tmp, *spc;
666 int extra = 0;
667
Chris Allegrettae3167732001-03-18 16:59:34 +0000668 newnode = make_new_node(inptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000669 tmp = &current->data[current_x];
670 current_x = 0;
671
672 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
673 if (ISSET(AUTOINDENT)) {
674 spc = current->data;
675 if (spc) {
676 while ((*spc == ' ') || (*spc == '\t')) {
677 extra++;
678 spc++;
679 current_x++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +0000680 totsize++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000681 }
Chris Allegretta88b09152001-05-17 11:35:43 +0000682 newnode->data = charalloc(strlen(tmp) + extra + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000683 strncpy(newnode->data, current->data, extra);
684 strcpy(&newnode->data[extra], tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000685 }
686 } else {
Chris Allegretta88b09152001-05-17 11:35:43 +0000687 newnode->data = charalloc(strlen(tmp) + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000688 strcpy(newnode->data, tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000689 }
690 *tmp = 0;
691
Chris Allegrettada721be2000-07-31 01:26:42 +0000692 if (inptr->next == NULL) {
Chris Allegrettae3167732001-03-18 16:59:34 +0000693 filebot = newnode;
694 editbot = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000695 }
Chris Allegrettae3167732001-03-18 16:59:34 +0000696 splice_node(inptr, newnode, inptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000697
698 totsize++;
699 renumber(current);
Chris Allegrettae3167732001-03-18 16:59:34 +0000700 current = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000701 align(&current->data);
702
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000703 /* The logic here is as follows:
704 * -> If we are at the bottom of the buffer, we want to recenter
Chris Allegretta88520c92001-05-05 17:45:54 +0000705 * (read: rebuild) the screen and forcibly move the cursor.
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000706 * -> otherwise, we want simply to redraw the screen and update
707 * where we think the cursor is.
708 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000709 if (current_y == editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +0000710 edit_update(current, CENTER);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000711 reset_cursor();
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000712 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000713 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000714 edit_refresh();
715 update_cursor();
716 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000717
718 totlines++;
719 set_modified();
720
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000721 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000722 return 1;
723}
724
725int do_enter_void(void)
726{
727 return do_enter(current);
728}
729
730void do_next_word(void)
731{
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000732 filestruct *fileptr, *old;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000733 int i;
734
735 if (current == NULL)
736 return;
737
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000738 old = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000739 i = current_x;
740 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
741 if (fileptr == current) {
742 while (isalnum((int) fileptr->data[i])
743 && fileptr->data[i] != 0)
744 i++;
745
746 if (fileptr->data[i] == 0) {
747 i = 0;
748 continue;
749 }
750 }
751 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
752 i++;
753
754 if (fileptr->data[i] != 0)
755 break;
756
757 i = 0;
758 }
759 if (fileptr == NULL)
760 current = filebot;
761 else
762 current = fileptr;
763
764 current_x = i;
765 placewewant = xplustabs();
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000766
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000767 if (current->lineno >= editbot->lineno)
Chris Allegretta234a34d2000-07-29 04:33:38 +0000768 edit_update(current, CENTER);
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000769 else {
770 /* If we've jumped lines, refresh the old line. We can't just use
771 * current->prev here, because we may have skipped over some blank
772 * lines, in which case the previous line is the wrong one.
773 */
774 if (current != old)
775 update_line(old, 0);
776
777 update_line(current, current_x);
778 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000779
780}
781
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000782#ifndef DISABLE_WRAPPING
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000783void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000784{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000785 int i = 0; /* Index into ->data for line. */
786 int i_tabs = 0; /* Screen position of ->data[i]. */
787 int last_word_end = -1; /* Location of end of last word found. */
788 int current_word_start = -1; /* Location of start of current word. */
789 int current_word_start_t = -1; /* Location of start of current word screen position. */
790 int current_word_end = -1; /* Location of end of current word */
791 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000792 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000793
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000794 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000795 int right = 0;
796 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000797
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000798 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000799
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000800 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000801 if (!isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000802 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000803
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000804 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000805 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000806
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000807 while (!isspace((int) inptr->data[i])
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000808 && inptr->data[i]) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000809 i++;
810 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000811 if (inptr->data[i] < 32)
812 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000813 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000814
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000815 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000816 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000817 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000818 } else {
819 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000820 current_word_end_t = i_tabs - 1;
821 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000822 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000823
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000824 if (inptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000825 if (i_tabs % tabsize != 0);
826 i_tabs += tabsize - (i_tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000827 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000828
Adam Rogoyski09f97962000-06-20 02:50:33 +0000829 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000830 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000831 }
832
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000833 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000834 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000835 * a) one word takes up the whole line with no starting spaces.
836 * - do nothing and return.
837 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000838 * - word starts new line.
839 * - keep white space on original line up to the cursor.
840 * *) cursor is after word at wrap point
841 * - either it's all white space after word, and this routine isn't called.
842 * - or we are actually in case 2 (2 words).
843 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000844 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000845 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000846 * - white space at end of original line is cleared, unless
847 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000848 * b) cursor is at the word at the wrap point.
849 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000850 * 1. pressed a space and at first character of wrap point word.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000851 * - white space on original line is kept to where cursor was.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000852 * 2. pressed non space (or space elsewhere).
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000853 * - white space at end of original line is cleared.
854 * c) cursor is past the word at the wrap point.
855 * - word at wrap point starts a new line.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000856 * - white space at end of original line is cleared
857 */
858
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000859 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000860
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000861 /* Category 1a: one word taking up the whole line with no beginning spaces. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000862 if ((last_word_end == -1) && (!isspace((int) inptr->data[0]))) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000863 for (i = current_word_end; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000864 if (!isspace((int) inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000865 current_word_start = i;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000866 while (!isspace((int) inptr->data[i]) && (i < len)) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000867 i++;
868 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000869 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000870 current_word_end = i;
871 break;
872 }
873 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000874
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000875 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000876 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000877 return;
878 }
879 if (current_x >= last_word_end) {
880 right = (current_x - current_word_start) + 1;
881 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000882 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000883 }
884
Chris Allegretta88b09152001-05-17 11:35:43 +0000885 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000886 strcpy(temp->data, &inptr->data[current_word_start]);
887 inptr->data = nrealloc(inptr->data, last_word_end + 2);
888 inptr->data[last_word_end + 1] = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000889 } else
890 /* Category 1b: one word on the line and word not taking up whole line
891 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000892 if (last_word_end == -1) {
Chris Allegretta88b09152001-05-17 11:35:43 +0000893 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000894 strcpy(temp->data, &inptr->data[current_word_start]);
895
896 /* Inside word, remove it from original, and move cursor to right spot. */
897 if (current_x >= current_word_start) {
898 right = current_x - current_word_start;
899 current_x = 0;
Chris Allegretta94a78b82001-03-14 08:28:48 +0000900 if (ISSET(AUTOINDENT)) {
901 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000902 while ((inptr->next->data[i] == ' '
903 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +0000904 i++;
905 right++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000906 }
Chris Allegretta94a78b82001-03-14 08:28:48 +0000907 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000908 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000909 }
910
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000911 null_at(inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000912
913 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
914 mark_beginbuf = temp;
915 mark_beginx = 0;
916 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000917 }
918
919 /* Category 2: two or more words on the line. */
920 else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000921 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000922 if (current_x < current_word_start) {
923 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +0000924 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000925 strcpy(temp->data, &inptr->data[current_word_start]);
926
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000927 if (!isspace((int) input_char)) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000928 i = current_word_start - 1;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000929 while (isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000930 i--;
931 assert(i >= 0);
932 }
933 } else if (current_x <= last_word_end)
934 i = last_word_end - 1;
935 else
936 i = current_x;
937
938 inptr->data = nrealloc(inptr->data, i + 2);
939 inptr->data[i + 1] = 0;
940 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000941
942
943 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000944 else if ((current_x >= current_word_start)
945 && (current_x <= (current_word_end + 1))) {
946 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +0000947 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000948 strcpy(temp->data, &inptr->data[current_word_start]);
949
950 down = 1;
951
952 right = current_x - current_word_start;
Chris Allegretta94a78b82001-03-14 08:28:48 +0000953 if (ISSET(AUTOINDENT)) {
954 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000955 while ((inptr->next->data[i] == ' '
956 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +0000957 i++;
958 right++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000959 }
Chris Allegretta94a78b82001-03-14 08:28:48 +0000960 }
961
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000962 i = current_word_start - 1;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000963 if (isspace((int) input_char)
964 && (current_x == current_word_start)) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000965 current_x = current_word_start;
966
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000967 null_at(inptr->data, current_word_start);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000968 } else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000969
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000970 while (isspace((int) inptr->data[i])) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000971 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000972 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000973 }
974 inptr->data = nrealloc(inptr->data, i + 2);
975 inptr->data[i + 1] = 0;
976 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000977 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000978
979
980 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000981 else {
982 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +0000983 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000984 strcpy(temp->data, &inptr->data[current_word_start]);
985
986 down = 1;
987 right = current_x - current_word_start;
988
989 current_x = current_word_start;
990 i = current_word_start - 1;
991
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000992 while (isspace((int) inptr->data[i])) {
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000993 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000994 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000995 inptr->data = nrealloc(inptr->data, i + 2);
996 inptr->data[i + 1] = 0;
997 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000998 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000999 }
1000
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001001 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001002 if (ISSET(SAMELINEWRAP) && inptr->next) {
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001003 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001004
Chris Allegretta94a78b82001-03-14 08:28:48 +00001005 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001006 char *p =
Chris Allegretta88b09152001-05-17 11:35:43 +00001007 charalloc((strlen(temp->data) + strlen(inptr->next->data) + 2));
Chris Allegretta94a78b82001-03-14 08:28:48 +00001008
1009 if (ISSET(AUTOINDENT)) {
1010 int non = 0;
1011
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001012 /* Grab the beginning of the next line until it's not a
1013 space or tab, then null terminate it so we can strcat it
1014 to hell */
1015 while ((inptr->next->data[non] == ' '
Chris Allegretta355fbe52001-07-14 19:32:47 +00001016 || inptr->next->data[non] == '\t')) {
1017 p[non] = inptr->next->data[non];
1018 non++;
1019 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001020 p[non] = 0;
1021 strcat(p, temp->data);
1022 strcat(p, " ");
1023
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001024 /* Now tack on the rest of the next line after the spaces and
1025 tabs */
Chris Allegretta94a78b82001-03-14 08:28:48 +00001026 strcat(p, &inptr->next->data[non]);
1027 } else {
1028 strcpy(p, temp->data);
1029 strcat(p, " ");
1030 strcat(p, inptr->next->data);
1031 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001032
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001033 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001034 inptr->next->data = p;
1035
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001036 free(temp->data);
1037 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001038
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001039 current_x = old_x;
1040 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001041 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001042 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001043 else {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001044
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001045 temp->prev = inptr;
1046 temp->next = inptr->next;
1047
1048 if (inptr->next)
1049 inptr->next->prev = temp;
1050 inptr->next = temp;
1051
1052 if (!temp->next)
1053 filebot = temp;
1054
1055 SET(SAMELINEWRAP);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001056
1057 if (ISSET(AUTOINDENT)) {
1058 char *spc = inptr->data;
1059 char *t = NULL;
1060 int extra = 0;
1061 if (spc) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001062 while ((*spc == ' ') || (*spc == '\t')) {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001063 extra++;
1064 spc++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001065 totsize++;
1066 }
Chris Allegretta88b09152001-05-17 11:35:43 +00001067 t = charalloc(strlen(temp->data) + extra + 1);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001068 strncpy(t, inptr->data, extra);
1069 strcpy(t + extra, temp->data);
1070 free(temp->data);
1071 temp->data = t;
1072 }
1073 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001074 }
1075
1076
1077 totlines++;
Chris Allegretta88520c92001-05-05 17:45:54 +00001078 /* Everything about it makes me want this line here, but it causes
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001079 * totsize to be high by one for some reason. Sigh. (Rob) */
1080 /* totsize++; */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001081
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001082 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001083 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001084
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001085
1086 /* Move the cursor to the new line if appropriate. */
1087 if (down) {
1088 do_right();
1089 }
1090
1091 /* Move the cursor to the correct spot in the line if appropriate. */
1092 while (right--) {
1093 do_right();
1094 }
1095
Chris Allegretta234a34d2000-07-29 04:33:38 +00001096 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001097 reset_cursor();
1098 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001099}
1100
1101/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001102void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001103{
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001104 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001105#ifdef DEBUG
1106 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
1107 inptr->data);
1108#endif
1109
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001110 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001111 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001112 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001113 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001114
1115 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001116 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001117
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001118 while (isspace((int) inptr->data[i]) && inptr->data[i])
Adam Rogoyski09f97962000-06-20 02:50:33 +00001119 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001120
Adam Rogoyski09f97962000-06-20 02:50:33 +00001121 if (!inptr->data[i])
1122 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001123
Adam Rogoyski09f97962000-06-20 02:50:33 +00001124 /* String must be at least 1 character long. */
1125 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001126 if (isspace((int) inptr->data[i])) {
Adam Rogoyski09f97962000-06-20 02:50:33 +00001127 if (!char_found)
1128 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001129 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001130 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001131 } else
1132 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001133 }
Adam Rogoyski09f97962000-06-20 02:50:33 +00001134
1135 if (char_found == 2)
1136 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001137 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001138}
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001139#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001140
1141/* Stuff we do when we abort from programs and want to clean up the
Chris Allegretta88520c92001-05-05 17:45:54 +00001142 * screen. This doesn't do much right now.
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001143 */
1144void do_early_abort(void)
1145{
1146 blank_statusbar_refresh();
1147}
1148
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001149int do_backspace(void)
1150{
1151 filestruct *previous, *tmp;
1152
1153 if (current_x != 0) {
1154 /* Let's get dangerous */
1155 memmove(&current->data[current_x - 1], &current->data[current_x],
1156 strlen(current->data) - current_x + 1);
1157#ifdef DEBUG
1158 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
1159#endif
1160 align(&current->data);
1161 do_left();
1162 } else {
1163 if (current == fileage)
1164 return 0; /* Can't delete past top of file */
1165
1166 previous = current->prev;
1167 current_x = strlen(previous->data);
1168 previous->data = nrealloc(previous->data,
1169 strlen(previous->data) +
1170 strlen(current->data) + 1);
1171 strcat(previous->data, current->data);
1172
1173 tmp = current;
1174 unlink_node(current);
1175 delete_node(current);
1176 if (current == edittop) {
1177 if (previous->next)
1178 current = previous->next;
1179 else
1180 current = previous;
Chris Allegrettada721be2000-07-31 01:26:42 +00001181 page_up_center();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001182 } else {
1183 if (previous->next)
1184 current = previous->next;
1185 else
1186 current = previous;
1187 update_line(current, current_x);
1188 }
1189
1190 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001191 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001192 filebot = current;
1193 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001194
1195 /* Recreate the magic line if we're deleting it AND if the
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001196 line we're on now is NOT blank. if it is blank we
1197 can just use IT for the magic line. This is how Pico
1198 appears to do it, in any case */
Chris Allegretta28a0f892000-07-05 22:47:54 +00001199 if (strcmp(current->data, "")) {
1200 new_magicline();
1201 fix_editbot();
1202 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001203 }
1204
1205 current = previous;
1206 renumber(current);
1207 previous_line();
1208 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001209#ifdef DEBUG
1210 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
1211#endif
1212
1213 }
1214
1215 totsize--;
1216 set_modified();
1217 UNSET(KEEP_CUTBUFFER);
1218 edit_refresh();
1219 return 1;
1220}
1221
1222int do_delete(void)
1223{
1224 filestruct *foo;
1225
1226 if (current_x != strlen(current->data)) {
1227 /* Let's get dangerous */
1228 memmove(&current->data[current_x], &current->data[current_x + 1],
1229 strlen(current->data) - current_x);
1230
1231 align(&current->data);
1232
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001233 /* Now that we have a magic lnie again, we can check for both being
1234 on the line before filebot as well as at filebot */
Chris Allegretta4ed13152001-02-10 17:50:50 +00001235 } else if (current->next != NULL && current->next != filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001236 current->data = nrealloc(current->data,
1237 strlen(current->data) +
1238 strlen(current->next->data) + 1);
1239 strcat(current->data, current->next->data);
1240
1241 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001242 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001243 filebot = current;
1244 editbot = current;
1245 }
1246
1247 unlink_node(foo);
1248 delete_node(foo);
1249 update_line(current, current_x);
1250
Chris Allegretta4ed13152001-02-10 17:50:50 +00001251 /* Please see the comment in do_backspace if you don't understand
Chris Allegretta28a0f892000-07-05 22:47:54 +00001252 this test */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001253 if (current == filebot && strcmp(current->data, "")) {
Chris Allegretta28a0f892000-07-05 22:47:54 +00001254 new_magicline();
1255 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001256 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001257 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001258 renumber(current);
1259 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001260 } else
1261 return 0;
1262
1263 totsize--;
1264 set_modified();
1265 UNSET(KEEP_CUTBUFFER);
1266 edit_refresh();
1267 return 1;
1268}
1269
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001270void wrap_reset(void)
1271{
1272 UNSET(SAMELINEWRAP);
1273}
1274
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001275#ifndef DISABLE_SPELLER
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001276
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001277int do_int_spell_fix(char *word)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001278{
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001279 char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001280 filestruct *begin;
1281 int i = 0, j = 0, beginx, beginx_top;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001282
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001283 /* save where we are */
1284 begin = current;
1285 beginx = current_x + 1;
1286
1287 /* save the current search/replace strings */
1288 search_init_globals();
1289 save_search = mallocstrcpy(save_search, last_search);
1290 save_replace = mallocstrcpy(save_replace, last_replace);
1291
1292 /* set search/replace strings to mis-spelt word */
1293 prevanswer = mallocstrcpy(prevanswer, word);
1294 last_search = mallocstrcpy(last_search, word);
1295 last_replace = mallocstrcpy(last_replace, word);
1296
1297 /* start from the top of file */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001298 current = fileage;
1299 current_x = beginx_top = -1;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001300
1301 search_last_line = FALSE;
1302
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001303 edit_update(fileage, TOP);
1304
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001305 /* make sure word is still mis-spelt (i.e. when multi-errors) */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001306 if (findnextstr(TRUE, fileage, beginx_top, prevanswer) != NULL) {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001307 do_replace_highlight(TRUE, prevanswer);
1308
1309 /* allow replace word to be corrected */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001310 i = statusq(0, spell_list, SPELL_LIST_LEN, last_replace,
1311 _("Edit a replacement"));
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001312
1313 do_replace_highlight(FALSE, prevanswer);
1314
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001315 /* start from the start of this line again */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001316 current = fileage;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001317 current_x = beginx_top;
1318
1319 search_last_line = FALSE;
1320
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001321 j = i;
1322 do_replace_loop(prevanswer, fileage, &beginx_top, TRUE, &j);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001323 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001324
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001325 /* restore the search/replace strings */
1326 last_search = mallocstrcpy(last_search, save_search);
1327 last_replace = mallocstrcpy(last_replace, save_replace);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001328
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001329 /* restore where we were */
1330 current = begin;
1331 current_x = beginx - 1;
1332
1333 edit_update(current, CENTER);
1334
1335 if (i == -1)
1336 return FALSE;
1337
1338 return TRUE;
1339}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001340
1341/* Integrated spell checking using 'spell' program */
Chris Allegretta271e9722000-11-10 18:15:43 +00001342int do_int_speller(char *tempfile_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001343{
Chris Allegretta271e9722000-11-10 18:15:43 +00001344 char *read_buff, *read_buff_ptr, *read_buff_word;
1345 long pipe_buff_size;
1346 int in_fd[2], tempfile_fd;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001347 int spell_status;
1348 pid_t pid_spell;
1349 ssize_t bytesread;
1350
Chris Allegretta271e9722000-11-10 18:15:43 +00001351 /* Create a pipe to spell program */
1352
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001353 if (pipe(in_fd) == -1)
1354 return FALSE;
1355
Chris Allegretta271e9722000-11-10 18:15:43 +00001356 /* A new process to run spell in */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001357
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001358 if ((pid_spell = fork()) == 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001359
1360 /* Child continues, (i.e. future spell process) */
1361
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001362 close(in_fd[0]);
1363
Chris Allegretta271e9722000-11-10 18:15:43 +00001364 /* replace the standard in with the tempfile */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001365
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001366 if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001367
1368 close(in_fd[1]);
1369 exit(1);
1370 }
1371
1372 if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
1373
1374 close(tempfile_fd);
1375 close(in_fd[1]);
1376 exit(1);
1377 }
1378 close(tempfile_fd);
1379
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001380
Chris Allegretta271e9722000-11-10 18:15:43 +00001381 /* send spell's standard out to the pipe */
1382
1383 if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1384
1385 close(in_fd[1]);
1386 exit(1);
1387 }
1388 close(in_fd[1]);
1389
1390 /* Start spell program, we are using the PATH here!?!? */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001391 execlp("spell", "spell", NULL);
1392
Chris Allegretta271e9722000-11-10 18:15:43 +00001393 /* Should not be reached, if spell is found!!! */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001394
Chris Allegretta271e9722000-11-10 18:15:43 +00001395 exit(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001396 }
1397
1398 /* Parent continues here */
1399
Chris Allegretta271e9722000-11-10 18:15:43 +00001400 close(in_fd[1]);
1401
1402 /* Child process was not forked successfully */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001403
1404 if (pid_spell < 0) {
1405
Chris Allegretta271e9722000-11-10 18:15:43 +00001406 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001407 return FALSE;
1408 }
1409
Chris Allegretta271e9722000-11-10 18:15:43 +00001410 /* Get system pipe buffer size */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001411
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001412 if ((pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001413
Chris Allegretta271e9722000-11-10 18:15:43 +00001414 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001415 return FALSE;
Chris Allegretta271e9722000-11-10 18:15:43 +00001416 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001417
Chris Allegretta88b09152001-05-17 11:35:43 +00001418 read_buff = charalloc(pipe_buff_size + 1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001419
Chris Allegretta271e9722000-11-10 18:15:43 +00001420 /* Process the returned spelling errors */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001421
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001422 while ((bytesread = read(in_fd[0], read_buff, pipe_buff_size)) > 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001423
Chris Allegretta271e9722000-11-10 18:15:43 +00001424 read_buff[bytesread] = (char) NULL;
1425 read_buff_word = read_buff_ptr = read_buff;
1426
1427 while (*read_buff_ptr != (char) NULL) {
1428
1429 /* Windows version may need to process additional char '\r' */
1430
1431 /* Possible problem here if last word not followed by '\n' */
1432
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001433 if (*read_buff_ptr == '\n') {
Chris Allegretta271e9722000-11-10 18:15:43 +00001434 *read_buff_ptr = (char) NULL;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001435 if (!do_int_spell_fix(read_buff_word)) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001436
1437 close(in_fd[0]);
1438 free(read_buff);
1439 replace_abort();
1440
1441 return TRUE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001442 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001443 read_buff_word = read_buff_ptr;
1444 read_buff_word++;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001445 }
1446
1447 read_buff_ptr++;
1448 }
1449 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001450
1451 close(in_fd[0]);
1452 free(read_buff);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001453 replace_abort();
1454
Chris Allegretta271e9722000-11-10 18:15:43 +00001455 /* Process end of spell process */
1456
1457 wait(&spell_status);
1458 if (WIFEXITED(spell_status)) {
1459 if (WEXITSTATUS(spell_status) != 0)
1460 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001461 } else
Chris Allegretta271e9722000-11-10 18:15:43 +00001462 return FALSE;
1463
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001464 return TRUE;
1465}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001466
1467/* External spell checking */
Chris Allegretta271e9722000-11-10 18:15:43 +00001468int do_alt_speller(char *file_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001469{
Chris Allegretta271e9722000-11-10 18:15:43 +00001470 int alt_spell_status;
1471 pid_t pid_spell;
Chris Allegretta169ee842001-01-26 01:57:32 +00001472 char *ptr;
Rocco Corsi4dfaf932001-04-20 01:59:55 +00001473 long lineno_cur = current->lineno;
Chris Allegretta169ee842001-01-26 01:57:32 +00001474 static int arglen = 3;
1475 static char **spellargs = (char **) NULL;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001476
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001477 endwin();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001478
Chris Allegrettae434b452001-01-27 19:25:00 +00001479 /* Set up an argument list to pass the execvp function */
1480 if (spellargs == NULL) {
1481 spellargs = nmalloc(arglen * sizeof(char *));
Chris Allegretta271e9722000-11-10 18:15:43 +00001482
Chris Allegrettae434b452001-01-27 19:25:00 +00001483 spellargs[0] = strtok(alt_speller, " ");
1484 while ((ptr = strtok(NULL, " ")) != NULL) {
1485 arglen++;
1486 spellargs = nrealloc(spellargs, arglen * sizeof(char *));
1487 spellargs[arglen - 3] = ptr;
Chris Allegretta169ee842001-01-26 01:57:32 +00001488 }
Chris Allegrettae434b452001-01-27 19:25:00 +00001489 spellargs[arglen - 1] = NULL;
1490 }
1491 spellargs[arglen - 2] = file_name;
1492
1493 /* Start a new process for the alternate speller */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001494 if ((pid_spell = fork()) == 0) {
Chris Allegretta169ee842001-01-26 01:57:32 +00001495
Chris Allegretta88520c92001-05-05 17:45:54 +00001496 /* Start alternate spell program; we are using the PATH here!?!? */
Chris Allegretta169ee842001-01-26 01:57:32 +00001497 execvp(spellargs[0], spellargs);
Chris Allegretta271e9722000-11-10 18:15:43 +00001498
1499 /* Should not be reached, if alternate speller is found!!! */
1500
1501 exit(1);
1502 }
1503
1504 /* Could not fork?? */
1505
1506 if (pid_spell < 0)
1507 return FALSE;
1508
1509 /* Wait for alternate speller to complete */
1510
1511 wait(&alt_spell_status);
1512 if (WIFEXITED(alt_spell_status)) {
1513 if (WEXITSTATUS(alt_spell_status) != 0)
1514 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001515 } else
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001516 return FALSE;
1517
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001518 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001519 free_filestruct(fileage);
1520 global_init();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001521 open_file(file_name, 0, 1);
Rocco Corsi4dfaf932001-04-20 01:59:55 +00001522
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001523 do_gotoline(lineno_cur, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001524 set_modified();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001525
Chris Allegretta355fbe52001-07-14 19:32:47 +00001526#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001527 /* if we have multiple files open, the spell-checked (current) file
1528 is now stored after the un-spell-checked file in the open_files
1529 structure, so go back to the un-spell-checked file and close it */
1530 open_prevfile(0);
1531 close_open_file();
1532#endif
1533
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001534 return TRUE;
1535}
1536#endif
1537
1538int do_spell(void)
1539{
1540
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001541#ifdef DISABLE_SPELLER
Chris Allegrettaff269f82000-12-01 18:46:01 +00001542 nano_disabled_msg();
1543 return (TRUE);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001544#else
Chris Allegretta271e9722000-11-10 18:15:43 +00001545 char *temp;
1546 int spell_res;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001547
Chris Allegretta271e9722000-11-10 18:15:43 +00001548 if ((temp = tempnam(0, "nano.")) == NULL) {
1549 statusbar(_("Could not create a temporary filename: %s"),
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001550 strerror(errno));
Chris Allegretta271e9722000-11-10 18:15:43 +00001551 return 0;
1552 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001553
Chris Allegrettaecc3d7f2001-06-05 23:24:55 +00001554 if (write_file(temp, 1, 0, 0) == -1) {
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001555 statusbar(_("Spell checking failed: unable to write temp file!"));
Chris Allegretta271e9722000-11-10 18:15:43 +00001556 return 0;
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001557 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001558
Chris Allegretta271e9722000-11-10 18:15:43 +00001559 if (alt_speller)
1560 spell_res = do_alt_speller(temp);
1561 else
1562 spell_res = do_int_speller(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001563
Chris Allegretta271e9722000-11-10 18:15:43 +00001564 remove(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001565
1566 if (spell_res)
1567 statusbar(_("Finished checking spelling"));
1568 else
1569 statusbar(_("Spell checking failed"));
1570
1571 return spell_res;
1572
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001573#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001574}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001575
1576int do_exit(void)
1577{
1578 int i;
1579
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001580 if (!ISSET(MODIFIED)) {
1581
Chris Allegretta355fbe52001-07-14 19:32:47 +00001582#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001583 if (!close_open_file()) {
1584 display_main_list();
1585 return 1;
1586 }
1587 else
1588#endif
1589
1590 finish(0);
1591 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001592
Chris Allegretta30885552000-07-14 01:20:12 +00001593 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001594 i = 1;
1595 } else {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001596 i = do_yesno(0, 0,
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001597 _
1598 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1599 }
1600
1601#ifdef DEBUG
1602 dump_buffer(fileage);
1603#endif
1604
1605 if (i == 1) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001606 if (do_writeout(filename, 1, 0) > 0) {
1607
Chris Allegretta355fbe52001-07-14 19:32:47 +00001608#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001609 if (!close_open_file()) {
1610 display_main_list();
1611 return 1;
1612 }
1613 else
1614#endif
1615
1616 finish(0);
1617 }
1618 } else if (i == 0) {
1619
Chris Allegretta355fbe52001-07-14 19:32:47 +00001620#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001621 if (!close_open_file()) {
1622 display_main_list();
1623 return 1;
1624 }
1625 else
1626#endif
1627
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001628 finish(0);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001629 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001630 statusbar(_("Cancelled"));
1631
1632 display_main_list();
1633 return 1;
1634}
1635
Chris Allegretta84de5522001-04-12 14:51:48 +00001636#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001637#ifdef NCURSES_MOUSE_VERSION
1638void do_mouse(void)
1639{
1640 MEVENT mevent;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001641 int foo = 0, tab_found = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001642
1643 if (getmouse(&mevent) == ERR)
1644 return;
1645
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001646 /* If mouse not in edit or bottom window, return */
1647 if (wenclose(edit, mevent.y, mevent.x)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001648
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001649 /* Don't let people screw with the marker when they're in a
1650 subfunction */
1651 if (currshortcut != main_list)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001652 return;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001653
1654 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1655 mevent.y -= 2;
1656
1657 /* Selecting where the cursor is sets the mark.
1658 * Selecting beyond the line length with the cursor at the end of the
1659 * line sets the mark as well.
1660 */
1661 if ((mevent.y == current_y) &&
1662 ((mevent.x == current_x) || (current_x == strlen(current->data)
1663 && (mevent.x >
1664 strlen(current->data))))) {
1665 if (ISSET(VIEW_MODE)) {
1666 print_view_warning();
1667 return;
1668 }
1669 do_mark();
1670 } else if (mevent.y > current_y) {
1671 while (mevent.y > current_y) {
1672 if (current->next != NULL)
1673 current = current->next;
1674 else
1675 break;
1676 current_y++;
1677 }
1678 } else if (mevent.y < current_y) {
1679 while (mevent.y < current_y) {
1680 if (current->prev != NULL)
1681 current = current->prev;
1682 else
1683 break;
1684 current_y--;
1685 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001686 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001687 current_x = mevent.x;
1688 placewewant = current_x;
1689 while (foo < current_x) {
1690 if (current->data[foo] == NANO_CONTROL_I) {
1691 current_x -= tabsize - (foo % tabsize);
1692 tab_found = 1;
1693 } else if (current->data[foo] & 0x80);
1694 else if (current->data[foo] < 32)
1695 current_x--;
1696 foo++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001697 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001698 /* This is where tab_found comes in. I can't figure out why,
1699 * but without it any line with a tab will place the cursor
1700 * one character behind. Whatever, this fixes it. */
1701 if (tab_found == 1)
1702 current_x++;
1703
1704 if (current_x > strlen(current->data))
1705 current_x = strlen(current->data);
1706
1707 update_cursor();
1708 edit_refresh();
1709 } else if (wenclose(bottomwin, mevent.y, mevent.x) && !ISSET(NO_HELP)) {
1710 int k = COLS / 6, val = 0;
1711
1712 /* Determine what shortcut list was clicked */
1713 mevent.y -= (editwinrows + 3);
1714
1715 if (mevent.y < 0) /* They clicked on the statusbar */
1716 return;
1717
1718 /* Don't select stuff beyond list length */
1719 if (mevent.x / k >= currslen)
1720 return;
1721
1722 val = currshortcut[(mevent.x / k) * 2 + mevent.y].val;
1723
1724 /* And ungetch that value */
1725 ungetch(val);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001726 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001727}
1728#endif
1729#endif
1730
1731/* Handler for SIGHUP */
1732RETSIGTYPE handle_hup(int signal)
1733{
Chris Allegrettae7a58932000-12-02 02:36:22 +00001734 die(_("Received SIGHUP"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001735}
1736
Chris Allegretta18f8be02000-09-04 03:20:38 +00001737/* What do we do when we catch the suspend signal */
1738RETSIGTYPE do_suspend(int signal)
1739{
Chris Allegretta18f8be02000-09-04 03:20:38 +00001740 endwin();
Chris Allegretta521e00d2001-06-28 16:52:52 +00001741 printf("\n\n\n\n\nUse \"fg\" to return to nano\n");
1742 fflush(stdout);
1743
1744 /* We used to re-enable the default SIG_DFL and raise SIGTSTP, but
1745 then we could be (and were) interrupted in the middle of the call.
1746 So we do it the mutt way instead */
1747 kill(0, SIGSTOP);
Chris Allegretta18f8be02000-09-04 03:20:38 +00001748}
1749
1750/* Restore the suspend handler when we come back into the prog */
1751RETSIGTYPE do_cont(int signal)
1752{
1753
Chris Allegretta521e00d2001-06-28 16:52:52 +00001754 /* Now we just update the screen instead of having to reenable the
1755 SIGTSTP handler */
1756
Chris Allegretta521e00d2001-06-28 16:52:52 +00001757 doupdate();
Chris Allegretta18f8be02000-09-04 03:20:38 +00001758}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001759
1760void handle_sigwinch(int s)
1761{
1762#ifndef NANO_SMALL
1763 char *tty = NULL;
1764 int fd = 0;
1765 int result = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001766 struct winsize win;
1767
1768 tty = ttyname(0);
1769 if (!tty)
1770 return;
1771 fd = open(tty, O_RDWR);
1772 if (fd == -1)
1773 return;
1774 result = ioctl(fd, TIOCGWINSZ, &win);
1775 if (result == -1)
1776 return;
1777
1778
1779 COLS = win.ws_col;
1780 LINES = win.ws_row;
1781
Chris Allegrettae61e8302001-01-14 05:18:27 +00001782 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1783 die_too_small();
1784
Chris Allegretta6fe61492001-05-21 12:56:25 +00001785#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettae61e8302001-01-14 05:18:27 +00001786 if ((fill = COLS - CHARS_FROM_EOL) < MIN_FILL_LENGTH)
1787 die_too_small();
Chris Allegretta6fe61492001-05-21 12:56:25 +00001788#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001789
Chris Allegretta0a06e072001-01-23 02:35:04 +00001790 hblank = nrealloc(hblank, COLS + 1);
1791 memset(hblank, ' ', COLS);
1792 hblank[COLS] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001793
Chris Allegretta618f5d72001-02-16 04:48:30 +00001794#ifdef HAVE_RESIZETERM
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001795 resizeterm(LINES, COLS);
1796#ifdef HAVE_WRESIZE
1797 if (wresize(topwin, 2, COLS) == ERR)
1798 die(_("Cannot resize top win"));
1799 if (mvwin(topwin, 0, 0) == ERR)
1800 die(_("Cannot move top win"));
1801 if (wresize(edit, editwinrows, COLS) == ERR)
1802 die(_("Cannot resize edit win"));
1803 if (mvwin(edit, 2, 0) == ERR)
1804 die(_("Cannot move edit win"));
1805 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1806 die(_("Cannot resize bottom win"));
1807 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1808 die(_("Cannot move bottom win"));
1809#endif /* HAVE_WRESIZE */
Chris Allegretta618f5d72001-02-16 04:48:30 +00001810#endif /* HAVE_RESIZETERM */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001811
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001812 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001813
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001814 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001815 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001816 }
1817 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00001818
1819 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001820 refresh();
Chris Allegrettaf4b96012001-01-03 07:11:47 +00001821 titlebar(NULL);
Chris Allegretta97accc62000-06-19 05:45:52 +00001822 edit_refresh();
1823 display_main_list();
Chris Allegretta08020882001-01-29 23:37:54 +00001824 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001825 total_refresh();
Chris Allegretta08020882001-01-29 23:37:54 +00001826
Chris Allegretta4e90c402001-01-29 23:40:43 +00001827 /* Turn cursor back on for sure */
1828 curs_set(1);
1829
Chris Allegretta08020882001-01-29 23:37:54 +00001830 /* Jump back to mainloop */
1831 siglongjmp(jmpbuf, 1);
1832
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001833#endif
1834}
1835
Chris Allegretta756f2202000-09-01 13:32:47 +00001836void signal_init(void)
1837{
Chris Allegrettaac899e52001-06-30 04:09:09 +00001838#ifdef _POSIX_VDISABLE
1839 struct termios term;
1840#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00001841
Chris Allegretta88520c92001-05-05 17:45:54 +00001842 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
Chris Allegretta756f2202000-09-01 13:32:47 +00001843 memset(&act, 0, sizeof(struct sigaction));
1844 act.sa_handler = SIG_IGN;
1845 sigaction(SIGINT, &act, NULL);
Chris Allegretta756f2202000-09-01 13:32:47 +00001846
Chris Allegretta88520c92001-05-05 17:45:54 +00001847 /* Trap SIGHUP cuz we want to write the file out. */
Chris Allegretta756f2202000-09-01 13:32:47 +00001848 act.sa_handler = handle_hup;
1849 sigaction(SIGHUP, &act, NULL);
1850
1851 act.sa_handler = handle_sigwinch;
1852 sigaction(SIGWINCH, &act, NULL);
1853
Chris Allegretta521e00d2001-06-28 16:52:52 +00001854 if (!ISSET(SUSPEND)) {
Chris Allegrettaac899e52001-06-30 04:09:09 +00001855
1856/* Insane! */
1857#ifdef _POSIX_VDISABLE
1858 tcgetattr(0, &term);
1859 term.c_cc[VSUSP] = _POSIX_VDISABLE;
1860 tcsetattr(0, TCSANOW, &term);
1861#else
1862 act.sa_handler = SIG_IGN;
Chris Allegretta521e00d2001-06-28 16:52:52 +00001863 sigaction(SIGTSTP, &act, NULL);
Chris Allegrettaac899e52001-06-30 04:09:09 +00001864#endif
1865
Chris Allegretta521e00d2001-06-28 16:52:52 +00001866 } else {
1867 /* if we don't do this, it seems other stuff interrupts the
1868 suspend handler! Try using nano with mutt without this line */
1869 sigfillset(&act.sa_mask);
1870
1871 act.sa_handler = do_suspend;
1872 sigaction(SIGTSTP, &act, NULL);
1873
1874 act.sa_handler = do_cont;
1875 sigaction(SIGCONT, &act, NULL);
1876 }
1877
Chris Allegretta756f2202000-09-01 13:32:47 +00001878}
1879
Chris Allegretta2a42af12000-09-12 23:02:49 +00001880void window_init(void)
1881{
Chris Allegrettae61e8302001-01-14 05:18:27 +00001882 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1883 die_too_small();
Chris Allegretta92c9dd22000-09-13 14:03:27 +00001884
Chris Allegretta88520c92001-05-05 17:45:54 +00001885 /* Set up the main text window */
Chris Allegretta2a42af12000-09-12 23:02:49 +00001886 edit = newwin(editwinrows, COLS, 2, 0);
1887
1888 /* And the other windows */
1889 topwin = newwin(2, COLS, 0, 0);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001890 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00001891
Chris Allegretta155d6202001-01-08 01:50:37 +00001892#ifdef PDCURSES
1893 /* Oops, I guess we need this again.
1894 Moved here so the keypad still works after a Meta-X, for example */
1895 keypad(edit, TRUE);
1896 keypad(bottomwin, TRUE);
1897#endif
1898
Chris Allegretta2a42af12000-09-12 23:02:49 +00001899}
1900
Chris Allegretta756f2202000-09-01 13:32:47 +00001901void mouse_init(void)
1902{
Chris Allegretta84de5522001-04-12 14:51:48 +00001903#ifndef DISABLE_MOUSE
Chris Allegretta756f2202000-09-01 13:32:47 +00001904#ifdef NCURSES_MOUSE_VERSION
1905 if (ISSET(USE_MOUSE)) {
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001906 keypad_on(edit, 1);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001907 keypad_on(bottomwin, 1);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001908
Chris Allegretta756f2202000-09-01 13:32:47 +00001909 mousemask(BUTTON1_RELEASED, NULL);
1910 mouseinterval(50);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00001911
Chris Allegretta63c8ab92001-01-04 02:33:52 +00001912 } else
Chris Allegretta756f2202000-09-01 13:32:47 +00001913 mousemask(0, NULL);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00001914
Chris Allegretta756f2202000-09-01 13:32:47 +00001915#endif
1916#endif
1917
1918}
1919
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001920int do_tab(void)
1921{
1922 do_char('\t');
1923 return 1;
1924}
1925
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001926#ifndef DISABLE_JUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001927int empty_line(const char *data)
1928{
1929 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001930 if (!isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001931 return 0;
1932
1933 data++;
1934 }
1935
1936 return 1;
1937}
1938
1939int no_spaces(const char *data)
1940{
1941 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001942 if (isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001943 return 0;
1944
1945 data++;
1946 }
1947
1948 return 1;
1949}
1950
1951void justify_format(char *data)
1952{
1953 int i = 0;
1954 int len = strlen(data);
1955
1956 /* Skip first character regardless and leading whitespace. */
1957 for (i = 1; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001958 if (!isspace((int) data[i]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001959 break;
1960 }
1961
1962 i++; /* (i) is now at least 2. */
1963
1964 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
1965 for (; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001966 if (isspace((int) data[i]) && isspace((int) data[i - 1])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001967 && (data[i - 2] != '.')) {
1968 memmove(data + i, data + i + 1, len - i);
1969 len--;
1970 i--;
1971 }
1972 }
1973}
1974#endif
1975
1976int do_justify(void)
1977{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001978#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +00001979 nano_disabled_msg();
1980 return 1;
1981#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001982 int slen = 0; /* length of combined lines on one line. */
Chris Allegretta17dcb722001-01-20 21:40:07 +00001983 int initial_y, kbinput = 0, totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00001984 filestruct *initial = NULL, *tmpjust = NULL, *cutbak, *tmptop, *tmpbot;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001985
1986 if (empty_line(current->data)) {
1987 /* Justify starting at first non-empty line. */
1988 do {
1989 if (!current->next)
1990 return 1;
1991
1992 current = current->next;
1993 current_y++;
1994 }
1995 while (empty_line(current->data));
1996 } else {
1997 /* Search back for the beginning of the paragraph, where
1998 * Paragraph is 1) A line with leading whitespace
1999 * or 2) A line following an empty line.
2000 */
2001 while (current->prev != NULL) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002002 if (isspace((int) current->data[0]) || !current->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002003 break;
2004
2005 current = current->prev;
2006 current_y--;
2007 }
2008
2009 /* First line with leading whitespace may be empty. */
2010 if (empty_line(current->data)) {
2011 if (current->next) {
2012 current = current->next;
2013 current_y++;
2014 } else
2015 return 1;
2016 }
2017 }
2018 initial = current;
2019 initial_y = current_y;
2020
2021 set_modified();
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002022 cutbak = cutbuffer; /* Got to like cutbak ;) */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002023 totbak = totsize;
Chris Allegretta9149e612000-11-27 00:23:41 +00002024 cutbuffer = NULL;
2025
2026 tmptop = current;
2027 tmpjust = copy_node(current);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002028
2029 /* This is annoying because it mucks with totsize */
Chris Allegretta9149e612000-11-27 00:23:41 +00002030 add_to_cutbuffer(tmpjust);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002031
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002032 /* Put the whole paragraph into one big line. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002033 while (current->next && !isspace((int) current->next->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002034 && current->next->data[0]) {
2035 filestruct *tmpnode = current->next;
2036 int len = strlen(current->data);
2037 int len2 = strlen(current->next->data);
2038
Chris Allegretta9149e612000-11-27 00:23:41 +00002039 tmpjust = NULL;
Chris Allegretta9149e612000-11-27 00:23:41 +00002040 tmpjust = copy_node(current->next);
2041 add_to_cutbuffer(tmpjust);
2042
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002043 /* Wiping out a newline */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002044 totsize--;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002045
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002046 /* length of both strings plus space between strings and ending \0. */
2047 current->data = nrealloc(current->data, len + len2 + 2);
2048 current->data[len++] = ' ';
2049 current->data[len] = '\0';
2050
2051 strncat(current->data, current->next->data, len2);
2052
2053 unlink_node(tmpnode);
2054 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002055 }
2056
2057 justify_format(current->data);
2058
2059 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002060 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002061
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002062 if ((strlenpt(current->data) > (fill))
2063 && !no_spaces(current->data)) {
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002064 do {
2065 int i = 0;
2066 int len2 = 0;
2067 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002068
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002069 /* Start at fill , unless line isn't that long (but it
2070 * appears at least fill long with tabs.
2071 */
2072 if (slen > fill)
2073 i = fill;
2074 else
2075 i = slen;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002076
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002077 for (; i > 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002078 if (isspace((int) current->data[i]) &&
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002079 ((strlenpt(current->data) - strlen(current->data + i))
2080 <= fill))
2081 break;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002082 }
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002083
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002084 if (!i)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002085 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002086
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002087 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002088
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002089 len2 = strlen(current->data + i + 1);
Chris Allegretta88b09152001-05-17 11:35:43 +00002090 tmpline->data = charalloc(len2 + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002091
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002092 /* Skip the white space in current. */
2093 memcpy(tmpline->data, current->data + i + 1, len2);
2094 tmpline->data[len2] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002095
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002096 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002097
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002098 tmpline->prev = current;
2099 tmpline->next = current->next;
2100 if (current->next != NULL)
2101 current->next->prev = tmpline;
2102
2103 current->next = tmpline;
2104 current = tmpline;
2105 slen -= i + 1;
2106 current_y++;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002107 } while ((strlenpt(current->data) > (fill))
2108 && !no_spaces(current->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002109 }
Chris Allegretta9149e612000-11-27 00:23:41 +00002110 tmpbot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002111
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002112 if (current->next)
2113 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00002114 else
2115 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002116 current_x = 0;
2117 placewewant = 0;
2118
Adam Rogoyski09f97962000-06-20 02:50:33 +00002119 renumber(initial);
2120 totlines = filebot->lineno;
2121
2122 werase(edit);
2123
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002124 if ((current_y < 0) || (current_y >= editwinrows - 1)
2125 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00002126 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002127 center_cursor();
2128 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00002129 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002130 }
2131
Adam Rogoyski09f97962000-06-20 02:50:33 +00002132 edit_refresh();
Chris Allegretta9149e612000-11-27 00:23:41 +00002133 statusbar(_("Can now UnJustify!"));
Chris Allegretta07798352000-11-27 22:58:23 +00002134 /* Change the shortcut list to display the unjustify code */
2135 shortcut_init(1);
2136 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002137 reset_cursor();
2138
Chris Allegretta88520c92001-05-05 17:45:54 +00002139 /* Now get a keystroke and see if it's unjustify; if not, unget the keystroke
Chris Allegretta9149e612000-11-27 00:23:41 +00002140 and return */
Chris Allegretta5f071802001-05-06 02:34:31 +00002141
2142#ifndef DISABLE_MOUSE
2143#ifdef NCURSES_MOUSE_VERSION
2144
2145 /* If it was a mouse click, parse it with do_mouse and it might become
2146 the unjustify key. Else give it back to the input stream. */
2147 if ((kbinput = wgetch(edit)) == KEY_MOUSE)
2148 do_mouse();
2149 else
2150 ungetch(kbinput);
2151#endif
2152#endif
2153
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002154 if ((kbinput = wgetch(edit)) != NANO_UNJUSTIFY_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002155 ungetch(kbinput);
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002156 blank_statusbar_refresh();
2157 } else {
Chris Allegretta9149e612000-11-27 00:23:41 +00002158 /* Else restore the justify we just did (ungrateful user!) */
2159 if (tmptop->prev != NULL)
2160 tmptop->prev->next = tmpbot->next;
Chris Allegrettad022eac2000-11-27 02:50:49 +00002161 else
2162 fileage = current;
Chris Allegretta9149e612000-11-27 00:23:41 +00002163 tmpbot->next->prev = tmptop->prev;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002164 current = tmpbot->next;
Chris Allegretta9149e612000-11-27 00:23:41 +00002165 tmpbot->next = NULL;
2166 do_uncut_text();
Chris Allegrettad022eac2000-11-27 02:50:49 +00002167 if (tmptop->prev == NULL)
2168 edit_refresh();
2169
Chris Allegretta88520c92001-05-05 17:45:54 +00002170 /* Restore totsize from before justify */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002171 totsize = totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002172 free_filestruct(tmptop);
2173 blank_statusbar_refresh();
2174 }
Chris Allegretta4a9c8582000-11-27 22:59:40 +00002175 shortcut_init(0);
2176 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002177 free_filestruct(cutbuffer);
2178 cutbuffer = cutbak;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002179
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002180 return 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002181#endif
2182}
2183
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002184#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002185void help_init(void)
2186{
2187 int i, sofar = 0;
2188 long allocsize = 1; /* How much space we're gonna need for the help text */
Chris Allegretta220ba692000-12-18 03:40:00 +00002189 char buf[BUFSIZ] = "";
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002190
2191 /* Compute the space needed for the shortcut lists - we add 15 to
2192 have room for the shortcut abbrev and its possible alternate keys */
Chris Allegretta220ba692000-12-18 03:40:00 +00002193 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002194 if (main_list[i].help != NULL)
2195 allocsize += strlen(main_list[i].help) + 15;
2196
Chris Allegretta756f2202000-09-01 13:32:47 +00002197 /* And for the toggle list, we also allocate space for extra text. */
Chris Allegretta423cbfd2000-09-04 16:21:29 +00002198 for (i = 0; i <= TOGGLE_LEN - 1; i++)
Chris Allegretta756f2202000-09-01 13:32:47 +00002199 if (toggles[i].desc != NULL)
2200 allocsize += strlen(toggles[i].desc) + 30;
2201
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002202 allocsize += strlen(help_text_init);
2203
2204 if (help_text != NULL)
2205 free(help_text);
2206
2207 /* Allocate space for the help text */
Chris Allegretta88b09152001-05-17 11:35:43 +00002208 help_text = charalloc(allocsize);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002209
2210 /* Now add the text we want */
2211 strcpy(help_text, help_text_init);
2212
2213 /* Now add our shortcut info */
Chris Allegretta220ba692000-12-18 03:40:00 +00002214 for (i = 0; i <= MAIN_LIST_LEN - 1; i++) {
Robert Siemborski6af14312000-07-01 21:34:26 +00002215 sofar = snprintf(buf, BUFSIZ, "^%c ", main_list[i].val + 64);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002216
2217 if (main_list[i].misc1 > KEY_F0 && main_list[i].misc1 <= KEY_F(64))
Robert Siemborski6af14312000-07-01 21:34:26 +00002218 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002219 main_list[i].misc1 - KEY_F0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002220 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002221 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002222
2223 if (main_list[i].altval > 0)
Chris Allegrettae49f1232000-09-02 07:20:39 +00002224 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002225 main_list[i].altval - 32);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002226 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002227 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002228
Chris Allegretta756f2202000-09-01 13:32:47 +00002229
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002230 if (main_list[i].help != NULL)
Robert Siemborski976847c2000-07-06 03:43:05 +00002231 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", main_list[i].help);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002232
Chris Allegretta756f2202000-09-01 13:32:47 +00002233
2234 strcat(help_text, buf);
2235 strcat(help_text, "\n");
2236 }
2237
2238 /* And the toggles... */
Chris Allegretta423cbfd2000-09-04 16:21:29 +00002239 for (i = 0; i <= TOGGLE_LEN - 1; i++) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002240 if (toggles[i].override_ch != 0)
2241 sofar = snprintf(buf, BUFSIZ,
2242 "M-%c ", toggles[i].override_ch);
2243 else
2244 sofar = snprintf(buf, BUFSIZ,
2245 "M-%c ", toggles[i].val - 32);
Chris Allegretta756f2202000-09-01 13:32:47 +00002246
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002247 if (toggles[i].desc != NULL) {
2248 if (toggles[i].flag != 0)
2249 snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
2250 toggles[i].desc);
2251 else
Chris Allegrettaa212acf2001-07-13 02:00:49 +00002252 snprintf(&buf[sofar], BUFSIZ - sofar, "%s",
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002253 toggles[i].desc);
2254 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002255
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002256 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00002257 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002258 }
2259
2260}
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002261#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002262
Chris Allegretta756f2202000-09-01 13:32:47 +00002263void do_toggle(int which)
2264{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002265#ifdef NANO_SMALL
2266 nano_disabled_msg();
2267#else
Jordi Mallach2dc0f6b2000-09-07 10:48:00 +00002268 char *enabled = _("enabled");
2269 char *disabled = _("disabled");
Chris Allegrettaf0f63a82000-09-02 18:44:21 +00002270
Chris Allegretta658399a2001-06-14 02:54:22 +00002271 /* Even easier! */
2272 TOGGLE(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002273
Chris Allegretta756f2202000-09-01 13:32:47 +00002274 switch (toggles[which].val) {
2275 case TOGGLE_PICOMODE_KEY:
Chris Allegretta07798352000-11-27 22:58:23 +00002276 shortcut_init(0);
Chris Allegrettac1049ac2001-08-17 00:03:46 +00002277 SET(CLEAR_BACKUPSTRING);
Chris Allegretta756f2202000-09-01 13:32:47 +00002278 display_main_list();
2279 break;
2280 case TOGGLE_SUSPEND_KEY:
2281 signal_init();
2282 break;
2283 case TOGGLE_MOUSE_KEY:
2284 mouse_init();
2285 break;
2286 case TOGGLE_NOHELP_KEY:
Chris Allegretta2a42af12000-09-12 23:02:49 +00002287 wclear(bottomwin);
2288 wrefresh(bottomwin);
2289 window_init();
Chris Allegrettaaffeda82000-12-18 04:03:48 +00002290 fix_editbot();
Chris Allegretta2a42af12000-09-12 23:02:49 +00002291 edit_refresh();
2292 display_main_list();
Chris Allegretta756f2202000-09-01 13:32:47 +00002293 break;
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002294
Chris Allegretta756f2202000-09-01 13:32:47 +00002295 }
Chris Allegretta2a42af12000-09-12 23:02:49 +00002296
Chris Allegretta819e3db2001-07-11 02:37:19 +00002297 if (!ISSET(toggles[which].flag)) {
2298 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
2299 toggles[which].val == TOGGLE_WRAP_KEY)
2300 statusbar("%s %s", toggles[which].desc, enabled);
2301 else
2302 statusbar("%s %s", toggles[which].desc, disabled);
2303 } else {
2304 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
2305 toggles[which].val == TOGGLE_WRAP_KEY)
2306 statusbar("%s %s", toggles[which].desc, disabled);
2307 else
2308 statusbar("%s %s", toggles[which].desc, enabled);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002309 }
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002310
Chris Allegretta756f2202000-09-01 13:32:47 +00002311 SET(DISABLE_CURPOS);
2312
2313#endif
2314}
2315
Chris Allegretta88520c92001-05-05 17:45:54 +00002316/* If the NumLock key has made the keypad go awry, print an error
2317 message; hopefully we can address it later. */
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002318void print_numlock_warning(void)
2319{
2320 static int didmsg = 0;
2321 if (!didmsg) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002322 statusbar(_
2323 ("NumLock glitch detected. Keypad will malfunction with NumLock off"));
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002324 didmsg = 1;
2325 }
2326}
2327
Chris Allegretta1748cd12001-01-13 17:22:54 +00002328/* This function returns the correct keystroke, given the A,B,C or D
2329 input key. This is a common sequence of many terms which send
2330 Esc-O-[A-D] or Esc-[-[A-D]. */
2331int ABCD(int input)
2332{
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002333 switch (input) {
2334 case 'A':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002335 case 'a':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002336 return (KEY_UP);
2337 case 'B':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002338 case 'b':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002339 return (KEY_DOWN);
2340 case 'C':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002341 case 'c':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002342 return (KEY_RIGHT);
2343 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002344 case 'd':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002345 return (KEY_LEFT);
2346 default:
2347 return 0;
Chris Allegretta1748cd12001-01-13 17:22:54 +00002348 }
2349}
2350
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002351int main(int argc, char *argv[])
2352{
2353 int optchr;
2354 int kbinput; /* Input from keyboard */
2355 long startline = 0; /* Line to try and start at */
Chris Allegretta08020882001-01-29 23:37:54 +00002356 int keyhandled; /* Have we handled the keystroke yet? */
2357 int i, modify_control_seq;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002358 char *argv0;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002359#ifdef _POSIX_VDISABLE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002360 struct termios term;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002361#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002362
2363#ifdef HAVE_GETOPT_LONG
2364 int option_index = 0;
2365 struct option long_options[] = {
Chris Allegretta805c26d2000-09-06 13:39:17 +00002366#ifdef HAVE_REGEX_H
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002367 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00002368#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002369 {"version", 0, 0, 'V'},
2370 {"const", 0, 0, 'c'},
2371 {"suspend", 0, 0, 'z'},
2372 {"nowrap", 0, 0, 'w'},
2373 {"nohelp", 0, 0, 'x'},
2374 {"help", 0, 0, 'h'},
Chris Allegretta7492cec2000-12-18 04:55:21 +00002375 {"view", 0, 0, 'v'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002376#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002377 {"cut", 0, 0, 'k'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002378#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002379 {"autoindent", 0, 0, 'i'},
2380 {"tempfile", 0, 0, 't'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002381#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002382 {"speller", 1, 0, 's'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002383#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00002384
2385#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002386 {"fill", 1, 0, 'r'},
Chris Allegretta6fe61492001-05-21 12:56:25 +00002387#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002388 {"mouse", 0, 0, 'm'},
2389 {"pico", 0, 0, 'p'},
2390 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00002391 {"tabsize", 1, 0, 'T'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002392
Chris Allegretta355fbe52001-07-14 19:32:47 +00002393#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002394 {"multibuffer", 0, 0, 'F'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002395#endif
2396
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002397 {0, 0, 0, 0}
2398 };
2399#endif
2400
2401 /* Flag inits... */
2402 SET(FOLLOW_SYMLINKS);
2403
2404#ifndef NANO_SMALL
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002405#ifdef ENABLE_NLS
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002406 setlocale(LC_ALL, "");
2407 bindtextdomain(PACKAGE, LOCALEDIR);
2408 textdomain(PACKAGE);
2409#endif
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002410#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002411
Chris Allegretta8d8e0122001-04-18 04:28:54 +00002412#ifdef ENABLE_NANORC
2413 do_rcfile();
2414#endif /* ENABLE_NANORC */
2415
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002416#ifdef HAVE_GETOPT_LONG
Chris Allegretta307d4c82001-07-15 20:25:33 +00002417 while ((optchr = getopt_long(argc, argv, "h?FT:RVbcefgijklmpr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002418 long_options, &option_index)) != EOF) {
2419#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002420 while ((optchr =
Chris Allegretta307d4c82001-07-15 20:25:33 +00002421 getopt(argc, argv, "h?FT:RVbcefgijklmpr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002422#endif
2423
2424 switch (optchr) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002425
Chris Allegretta355fbe52001-07-14 19:32:47 +00002426#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002427 case 'F':
Chris Allegretta355fbe52001-07-14 19:32:47 +00002428 SET(MULTIBUFFER);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002429 break;
2430#endif
2431
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002432 case 'T':
Chris Allegretta99bf73f2000-08-04 00:22:08 +00002433 tabsize = atoi(optarg);
2434 if (tabsize <= 0) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002435 usage(); /* To stop bogus data for tab width */
2436 finish(1);
2437 }
2438 break;
Chris Allegretta805c26d2000-09-06 13:39:17 +00002439#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +00002440 case 'R':
2441 SET(USE_REGEXP);
2442 break;
Chris Allegretta47805612000-07-07 02:35:34 +00002443#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002444 case 'V':
2445 version();
2446 exit(0);
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002447 case 'b':
2448 case 'e':
2449 case 'f':
Rocco Corsi12f294c2001-04-14 06:50:24 +00002450 case 'g':
2451 case 'j':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002452 /* Pico compatibility flags */
2453 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002454 case 'c':
2455 SET(CONSTUPDATE);
2456 break;
2457 case 'h':
2458 case '?':
2459 usage();
2460 exit(0);
2461 case 'i':
2462 SET(AUTOINDENT);
2463 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002464#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002465 case 'k':
2466 SET(CUT_TO_END);
2467 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002468#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002469 case 'l':
2470 UNSET(FOLLOW_SYMLINKS);
2471 break;
2472 case 'm':
2473 SET(USE_MOUSE);
2474 break;
2475 case 'p':
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002476 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002477 break;
2478 case 'r':
Chris Allegretta6fe61492001-05-21 12:56:25 +00002479#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002480 fill = atoi(optarg);
Chris Allegretta6fe61492001-05-21 12:56:25 +00002481 if (fill < 0)
2482 wrap_at = fill;
2483 else if (fill == 0) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002484 usage(); /* To stop bogus data (like a string) */
2485 finish(1);
2486 }
2487 break;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002488#else
2489 usage();
2490 exit(0);
2491
2492#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002493#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002494 case 's':
Chris Allegretta88b09152001-05-17 11:35:43 +00002495 alt_speller = charalloc(strlen(optarg) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002496 strcpy(alt_speller, optarg);
2497 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002498#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002499 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00002500 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002501 break;
2502 case 'v':
2503 SET(VIEW_MODE);
2504 break;
2505 case 'w':
Chris Allegrettacef7fbb2001-04-02 05:36:08 +00002506#ifdef DISABLE_WRAPPING
2507 usage();
2508 exit(0);
2509#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002510 SET(NO_WRAP);
2511 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002512#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002513 case 'x':
2514 SET(NO_HELP);
2515 break;
2516 case 'z':
2517 SET(SUSPEND);
2518 break;
2519 default:
2520 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002521 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002522 }
2523
2524 }
2525
2526 argv0 = strrchr(argv[0], '/');
2527 if ((argv0 && strstr(argv0, "pico"))
2528 || (!argv0 && strstr(argv[0], "pico")))
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002529 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002530
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002531 /* See if there's a non-option in argv (first non-option is the
2532 filename, if +LINE is not given) */
2533 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002534 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002535 else {
2536 /* Look for the +line flag... */
2537 if (argv[optind][0] == '+') {
2538 startline = atoi(&argv[optind][1]);
2539 optind++;
2540 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002541 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002542 else
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002543 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002544
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002545 } else
2546 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002547 }
2548
2549
2550 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002551 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002552
Chris Allegretta9239d742000-09-06 15:19:18 +00002553#ifdef _POSIX_VDISABLE
Chris Allegretta8f6c0692000-07-19 01:16:18 +00002554 term = oldterm;
2555 term.c_cc[VINTR] = _POSIX_VDISABLE;
2556 term.c_cc[VQUIT] = _POSIX_VDISABLE;
2557 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002558 tcsetattr(0, TCSANOW, &term);
Chris Allegretta9239d742000-09-06 15:19:18 +00002559#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002560
2561 /* now ncurses init stuff... */
2562 initscr();
2563 savetty();
2564 nonl();
2565 cbreak();
2566 noecho();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002567
2568 /* Set up some global variables */
2569 global_init();
Chris Allegretta07798352000-11-27 22:58:23 +00002570 shortcut_init(0);
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002571#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002572 init_help_msg();
2573 help_init();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002574#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002575 signal_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002576
2577#ifdef DEBUG
2578 fprintf(stderr, _("Main: set up windows\n"));
2579#endif
2580
Chris Allegretta8ce24132001-04-30 11:28:46 +00002581#ifdef ENABLE_COLOR
2582 do_colorinit();
2583#endif /* ENABLE_COLOR */
2584
Chris Allegretta2a42af12000-09-12 23:02:49 +00002585 window_init();
Chris Allegretta756f2202000-09-01 13:32:47 +00002586 mouse_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002587
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002588#ifdef DEBUG
2589 fprintf(stderr, _("Main: bottom win\n"));
2590#endif
Chris Allegretta88520c92001-05-05 17:45:54 +00002591 /* Set up bottom of window */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002592 display_main_list();
2593
2594#ifdef DEBUG
2595 fprintf(stderr, _("Main: open file\n"));
2596#endif
2597
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002598 titlebar(NULL);
Chris Allegretta31c76662000-11-21 06:20:20 +00002599
2600 /* Now we check to see if argv[optind] is non-null to determine if
2601 we're dealing with a new file or not, not argc == 1... */
2602 if (argv[optind] == NULL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002603 new_file();
2604 else
2605 open_file(filename, 0, 0);
2606
2607 if (startline > 0)
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002608 do_gotoline(startline, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002609 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00002610 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002611
Chris Allegretta08020882001-01-29 23:37:54 +00002612 /* return here after a sigwinch */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002613 sigsetjmp(jmpbuf, 1);
Chris Allegretta08020882001-01-29 23:37:54 +00002614
2615 /* Fix clobber-age */
2616 kbinput = 0;
2617 keyhandled = 0;
2618 modify_control_seq = 0;
2619
Robert Siemborski6967eec2000-07-08 14:23:32 +00002620 edit_refresh();
2621 reset_cursor();
2622
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002623 while (1) {
Chris Allegretta9239d742000-09-06 15:19:18 +00002624
Chris Allegretta6fe61492001-05-21 12:56:25 +00002625#ifndef DISABLE_MOUSE
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002626 currshortcut = main_list;
2627 currslen = MAIN_VISIBLE;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002628#endif
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002629
Chris Allegretta9239d742000-09-06 15:19:18 +00002630#ifndef _POSIX_VDISABLE
2631 /* We're going to have to do it the old way, i.e. on cygwin */
2632 raw();
2633#endif
2634
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002635 kbinput = wgetch(edit);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002636#ifdef DEBUG
2637 fprintf(stderr, "AHA! %c (%d)\n", kbinput, kbinput);
2638#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002639 if (kbinput == 27) { /* Grab Alt-key stuff first */
2640 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002641 /* Alt-O, suddenly very important ;) */
Chris Allegretta16e41682000-09-11 22:33:54 +00002642 case 79:
2643 kbinput = wgetch(edit);
Chris Allegretta316e4d92001-04-28 16:31:19 +00002644 if ((kbinput <= 'D' && kbinput >= 'A') ||
2645 (kbinput <= 'd' && kbinput >= 'a'))
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002646 kbinput = ABCD(kbinput);
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002647 else if (kbinput <= 'z' && kbinput >= 'j')
2648 print_numlock_warning();
2649 else if (kbinput <= 'S' && kbinput >= 'P')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002650 kbinput = KEY_F(kbinput - 79);
Chris Allegretta16e41682000-09-11 22:33:54 +00002651#ifdef DEBUG
2652 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002653 fprintf(stderr, _("I got Alt-O-%c! (%d)\n"),
2654 kbinput, kbinput);
2655 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002656 }
2657#endif
2658 break;
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002659 case 27:
2660 /* If we get Alt-Alt, the next keystroke should be the same as a
2661 control sequence */
2662 modify_control_seq = 1;
2663 keyhandled = 1;
2664 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002665 case 91:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002666 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002667 case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */
Chris Allegretta16e41682000-09-11 22:33:54 +00002668 kbinput = wgetch(edit);
2669 if (kbinput >= '1' && kbinput <= '5') {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002670 kbinput = KEY_F(kbinput - 48);
2671 wgetch(edit);
2672 } else if (kbinput >= '7' && kbinput <= '9') {
2673 kbinput = KEY_F(kbinput - 49);
2674 wgetch(edit);
2675 } else if (kbinput == 126)
2676 kbinput = KEY_HOME;
Chris Allegretta16e41682000-09-11 22:33:54 +00002677
2678#ifdef DEBUG
2679 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002680 fprintf(stderr, _("I got Alt-[-1-%c! (%d)\n"),
2681 kbinput, kbinput);
2682 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002683 }
2684#endif
2685
2686 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002687 case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */
Chris Allegretta16e41682000-09-11 22:33:54 +00002688 kbinput = wgetch(edit);
Chris Allegretta16e41682000-09-11 22:33:54 +00002689 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002690 case '0':
2691 kbinput = KEY_F(9);
2692 wgetch(edit);
2693 break;
2694 case '1':
2695 kbinput = KEY_F(10);
2696 wgetch(edit);
2697 break;
2698 case '3':
2699 kbinput = KEY_F(11);
2700 wgetch(edit);
2701 break;
2702 case '4':
2703 kbinput = KEY_F(12);
2704 wgetch(edit);
2705 break;
2706 case 126: /* Hack, make insert key do something
Chris Allegretta88520c92001-05-05 17:45:54 +00002707 useful, like insert file */
Chris Allegretta355fbe52001-07-14 19:32:47 +00002708#ifdef ENABLE_MULTIBUFFER
2709 do_insertfile(ISSET(MULTIBUFFER));
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002710#else
2711 do_insertfile(0);
2712#endif
2713
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002714 keyhandled = 1;
2715 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002716#ifdef DEBUG
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002717 default:
2718 fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"),
2719 kbinput, kbinput);
2720 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002721#endif
2722
2723 }
2724 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002725 case '3': /* Alt-[-3 = Delete? */
Chris Allegretta16e41682000-09-11 22:33:54 +00002726 kbinput = NANO_DELETE_KEY;
2727 wgetch(edit);
2728 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002729 case '4': /* Alt-[-4 = End? */
Chris Allegretta16e41682000-09-11 22:33:54 +00002730 kbinput = NANO_END_KEY;
2731 wgetch(edit);
2732 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002733 case '5': /* Alt-[-5 = Page Up */
Chris Allegretta16e41682000-09-11 22:33:54 +00002734 kbinput = KEY_PPAGE;
2735 wgetch(edit);
2736 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002737 case '6': /* Alt-[-6 = Page Down */
Chris Allegretta16e41682000-09-11 22:33:54 +00002738 kbinput = KEY_NPAGE;
2739 wgetch(edit);
2740 break;
Chris Allegrettab26ecb52001-07-04 16:27:05 +00002741 case '7':
2742 kbinput = KEY_HOME;
2743 wgetch(edit);
2744 break;
2745 case '8':
2746 kbinput = KEY_END;
2747 wgetch(edit);
2748 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002749 case '[': /* Alt-[-[-[A-E], F1-F5 in linux console */
Chris Allegretta16e41682000-09-11 22:33:54 +00002750 kbinput = wgetch(edit);
Chris Allegrettab26ecb52001-07-04 16:27:05 +00002751 if (kbinput >= 'A' && kbinput <= 'E')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002752 kbinput = KEY_F(kbinput - 64);
Chris Allegretta16e41682000-09-11 22:33:54 +00002753 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002754 case 'A':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002755 case 'B':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002756 case 'C':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002757 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002758 case 'a':
2759 case 'b':
2760 case 'c':
2761 case 'd':
Chris Allegretta1748cd12001-01-13 17:22:54 +00002762 kbinput = ABCD(kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002763 break;
2764 case 'H':
2765 kbinput = KEY_HOME;
2766 break;
2767 case 'F':
2768 kbinput = KEY_END;
2769 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002770 default:
2771#ifdef DEBUG
2772 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
2773 kbinput, kbinput);
2774#endif
2775 break;
2776 }
2777 break;
Chris Allegretta355fbe52001-07-14 19:32:47 +00002778#ifdef ENABLE_MULTIBUFFER
Chris Allegretta819e3db2001-07-11 02:37:19 +00002779 case NANO_OPENPREV_KEY:
2780 open_prevfile(0);
2781 keyhandled = 1;
2782 break;
2783 case NANO_OPENNEXT_KEY:
2784 open_nextfile(0);
2785 keyhandled = 1;
2786 break;
Chris Allegretta9cf9e062001-07-11 12:06:13 +00002787#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002788 default:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002789 /* Check for the altkey defs.... */
2790 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
2791 if (kbinput == main_list[i].altval ||
2792 kbinput == main_list[i].altval - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002793 kbinput = main_list[i].val;
2794 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002795 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002796#ifndef NANO_SMALL
2797 /* And for toggle switches */
2798 for (i = 0; i <= TOGGLE_LEN - 1 && !keyhandled; i++)
2799 if (kbinput == toggles[i].val ||
2800 kbinput == toggles[i].val - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002801 do_toggle(i);
2802 keyhandled = 1;
2803 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002804 }
2805#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002806#ifdef DEBUG
2807 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
2808 kbinput);
2809#endif
2810 break;
2811 }
2812 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002813 /* If the modify_control_seq is set, we received an Alt-Alt
2814 sequence before this, so we make this key a control sequence
2815 by subtracting 64 or 96, depending on its value. */
2816 if (!keyhandled && modify_control_seq) {
2817 if (kbinput >= 'A' && kbinput < 'a')
2818 kbinput -= 64;
2819 else if (kbinput >= 'a' && kbinput <= 'z')
2820 kbinput -= 96;
2821
2822 modify_control_seq = 0;
2823 }
2824
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002825 /* Look through the main shortcut list to see if we've hit a
2826 shortcut key */
Chris Allegretta756f2202000-09-01 13:32:47 +00002827 for (i = 0; i < MAIN_LIST_LEN && !keyhandled; i++) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002828 if (kbinput == main_list[i].val ||
2829 (main_list[i].misc1 && kbinput == main_list[i].misc1) ||
2830 (main_list[i].misc2 && kbinput == main_list[i].misc2)) {
2831 if (ISSET(VIEW_MODE) && !main_list[i].viewok)
2832 print_view_warning();
2833 else
2834 main_list[i].func();
2835 keyhandled = 1;
2836 }
2837 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002838 /* If we're in raw mode or using Alt-Alt-x, we have to catch
2839 Control-S and Control-Q */
Chris Allegretta9239d742000-09-06 15:19:18 +00002840 if (kbinput == 17 || kbinput == 19)
2841 keyhandled = 1;
2842
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002843 /* Catch ^Z by hand when triggered also */
Chris Allegretta9239d742000-09-06 15:19:18 +00002844 if (kbinput == 26) {
2845 if (ISSET(SUSPEND))
2846 do_suspend(0);
2847 keyhandled = 1;
2848 }
Chris Allegretta9239d742000-09-06 15:19:18 +00002849
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002850 /* Last gasp, stuff that's not in the main lists */
2851 if (!keyhandled)
2852 switch (kbinput) {
Chris Allegretta84de5522001-04-12 14:51:48 +00002853#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002854#ifdef NCURSES_MOUSE_VERSION
2855 case KEY_MOUSE:
2856 do_mouse();
2857 break;
2858#endif
2859#endif
2860 case 0: /* Erg */
2861 do_next_word();
2862 break;
Chris Allegrettaf4f7e042001-01-04 16:56:15 +00002863
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002864 case 331: /* Stuff that we don't want to do squat */
2865 case -1:
2866 case 410: /* Must ignore this, it gets sent when we resize */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002867#ifdef PDCURSES
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002868 case 541: /* ???? */
2869 case 542: /* Control and alt in Windows *shrug* */
Chris Allegretta72623582000-11-29 23:43:28 +00002870 case 543: /* Right ctrl key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002871 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +00002872 case 545: /* Right alt key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002873#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002874
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002875 break;
2876 default:
2877#ifdef DEBUG
2878 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
2879#endif
2880 /* We no longer stop unhandled sequences so that people with
2881 odd character sets can type... */
2882
2883 if (ISSET(VIEW_MODE)) {
2884 print_view_warning();
2885 break;
2886 }
2887 do_char(kbinput);
2888 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002889 if (ISSET(CONSTUPDATE)) {
2890 if (ISSET(DISABLE_CURPOS))
2891 UNSET(DISABLE_CURPOS);
2892 else
2893 do_cursorpos();
2894 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002895
2896 reset_cursor();
2897 wrefresh(edit);
2898 keyhandled = 0;
2899 }
2900
2901 getchar();
2902 finish(0);
2903
2904}