blob: dd3444312b37ed98ff8d1eda8e463b6e7bafc202 [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
22#include <stdio.h>
23#include <stdlib.h>
24#include <stdarg.h>
25#include <signal.h>
26#include <unistd.h>
27#include <string.h>
28#include <fcntl.h>
29#include <sys/stat.h>
30#include <sys/ioctl.h>
31#include <sys/param.h>
Chris Allegretta27eb13f2000-11-05 16:52:21 +000032#include <sys/types.h>
33#include <sys/wait.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000034#include <errno.h>
35#include <ctype.h>
36#include <locale.h>
37#include <limits.h>
Adam Rogoyski77f36de2000-06-07 03:56:54 +000038#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000039
40#include "config.h"
41#include "proto.h"
42#include "nano.h"
43
44#ifndef NANO_SMALL
45#include <libintl.h>
46#define _(string) gettext(string)
47#else
48#define _(string) (string)
49#endif
50
51#ifdef HAVE_TERMIOS_H
52#include <termios.h>
53#endif
54
55#ifdef HAVE_TERMIO_H
56#include <termio.h>
57#endif
58
59#ifdef HAVE_GETOPT_H
60#include <getopt.h>
61#endif
62
63/* Former globals, now static */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000064int fill = 0; /* Fill - where to wrap lines, basically */
Rocco Corsiaf5c3022001-01-12 07:51:05 +000065
66#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000067static char *alt_speller; /* Alternative spell command */
Rocco Corsiaf5c3022001-01-12 07:51:05 +000068#endif
69
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000070struct termios oldterm; /* The user's original term settings */
Chris Allegretta18f8be02000-09-04 03:20:38 +000071static struct sigaction act; /* For all out fun signal handlers */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000072
Rocco Corsiaf5c3022001-01-12 07:51:05 +000073#ifndef DISABLE_HELP
Chris Allegretta65121632000-12-18 07:05:27 +000074static char *help_text_init = ""; /* Initial message, not including shortcuts */
75#endif
76
Chris Allegretta27eb13f2000-11-05 16:52:21 +000077char *last_search = NULL; /* Last string we searched for */
78char *last_replace = NULL; /* Last replacement string */
79int search_last_line; /* Is this the last search line? */
80
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000081/* What we do when we're all set to exit */
82RETSIGTYPE finish(int sigage)
83{
Chris Allegrettac08f50d2001-01-06 18:12:43 +000084
85 keypad(edit, TRUE);
86 keypad(bottomwin, TRUE);
87
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000088 if (!ISSET(NO_HELP)) {
89 mvwaddstr(bottomwin, 1, 0, hblank);
90 mvwaddstr(bottomwin, 2, 0, hblank);
Chris Allegretta4da1fc62000-06-21 03:00:43 +000091 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000092 mvwaddstr(bottomwin, 0, 0, hblank);
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +000093
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000094 wrefresh(bottomwin);
95 endwin();
96
97 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +000098 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000099
100 exit(sigage);
101}
102
103/* Die (gracefully?) */
104void die(char *msg, ...)
105{
106 va_list ap;
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000107 char *name;
108 int i;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000109
110 va_start(ap, msg);
111 vfprintf(stderr, msg, ap);
112 va_end(ap);
113
114 /* if we can't save we have REAL bad problems,
Robert Siemborskifcf32bf2000-07-17 03:04:54 +0000115 * but we might as well TRY. */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000116 if (filename[0] == '\0') {
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000117 name = "nano.save";
118 i = write_file(name, 1);
Robert Siemborskifcf32bf2000-07-17 03:04:54 +0000119 } else {
Chris Allegrettae7a58932000-12-02 02:36:22 +0000120
121 char *buf = nmalloc(strlen(filename) + 6);
122 strcpy(buf, filename);
123 strcat(buf, ".save");
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000124 i = write_file(buf, 1);
125 name = buf;
Robert Siemborskifcf32bf2000-07-17 03:04:54 +0000126 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000127 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000128 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000129
130 clear();
131 refresh();
132 resetty();
133 endwin();
134
135 fprintf(stderr, msg);
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000136 if (i != -1)
137 fprintf(stderr, _("\nBuffer written to %s\n"), name);
138 else
Chris Allegretta9756d622000-12-03 03:06:45 +0000139 fprintf(stderr, _("\nNo %s written (file exists?)\n"), name);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000140
141 exit(1); /* We have a problem: exit w/ errorlevel(1) */
142}
143
Chris Allegrettae61e8302001-01-14 05:18:27 +0000144/* Die with an error message that the screen was too small if, well, the
145 screen is too small */
146void die_too_small(void)
147{
148 char *too_small_msg = _("Window size is too small for Nano...");
149
150 die(too_small_msg);
151
152}
153
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000154void print_view_warning(void)
155{
156 statusbar(_("Key illegal in VIEW mode"));
157}
158
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000159void clear_filename(void)
160{
161 if (filename != NULL)
162 free(filename);
163 filename = nmalloc(1);
164 filename[0] = 0;
165}
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +0000166
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000167/* Initialize global variables - no better way for now */
168void global_init(void)
169{
170 int i;
171
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000172 current_x = 0;
173 current_y = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000174
175 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
176 die_too_small();
177
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000178 fileage = NULL;
179 cutbuffer = NULL;
180 current = NULL;
181 edittop = NULL;
182 editbot = NULL;
183 totlines = 0;
184 placewewant = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000185
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000186 if (!fill)
Chris Allegrettae61e8302001-01-14 05:18:27 +0000187 fill = COLS - CHARS_FROM_EOL;
188
189 if (fill < MIN_FILL_LENGTH)
190 die_too_small();
191
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000192 hblank = nmalloc(COLS + 1);
193
194 /* Thanks BG for this bit... */
195 for (i = 0; i <= COLS - 1; i++)
196 hblank[i] = ' ';
197 hblank[i] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000198}
199
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000200#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000201void init_help_msg(void)
202{
203
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000204 help_text_init =
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000205 _(" nano help text\n\n "
206 "The nano editor is designed to emulate the functionality and "
207 "ease-of-use of the UW Pico text editor. There are four main "
208 "sections of the editor: The top line shows the program "
209 "version, the current filename being edited, and whether "
210 "or not the file has been modified. Next is the main editor "
211 "window showing the file being edited. The status line is "
212 "the third line from the bottom and shows important messages. "
213 "The bottom two lines show the most commonly used shortcuts "
214 "in the editor.\n\n "
215 "The notation for shortcuts is as follows: Control-key "
Chris Allegrettae49f1232000-09-02 07:20:39 +0000216 "sequences are notated with a caret (^) symbol and are entered "
Chris Allegrettad56bd792000-09-02 07:27:10 +0000217 "with the Control (Ctrl) key. Escape-key sequences are notated "
218 "with the Meta (M) symbol and can be entered using either the "
219 "Esc, Alt or Meta key depending on your keyboard setup. The "
220 "following keystrokes are available in the main editor window. "
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000221 "Optional keys are shown in parentheses:\n\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000222
223}
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000224#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000225
226/* Make a copy of a node to a pointer (space will be malloc()ed) */
227filestruct *copy_node(filestruct * src)
228{
229 filestruct *dst;
230
231 dst = nmalloc(sizeof(filestruct));
232 dst->data = nmalloc(strlen(src->data) + 1);
233
234 dst->next = src->next;
235 dst->prev = src->prev;
236
237 strcpy(dst->data, src->data);
238 dst->lineno = src->lineno;
239
240 return dst;
241}
242
243/* Unlink a node from the rest of the struct */
244void unlink_node(filestruct * fileptr)
245{
246 if (fileptr->prev != NULL)
247 fileptr->prev->next = fileptr->next;
248
249 if (fileptr->next != NULL)
250 fileptr->next->prev = fileptr->prev;
251}
252
253void delete_node(filestruct * fileptr)
254{
Chris Allegretta17dcb722001-01-20 21:40:07 +0000255 if (fileptr == NULL)
256 return;
257
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000258 if (fileptr->data != NULL)
Chris Allegretta17dcb722001-01-20 21:40:07 +0000259 free(fileptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000260 free(fileptr);
261}
262
263/* Okay, now let's duplicate a whole struct! */
264filestruct *copy_filestruct(filestruct * src)
265{
266 filestruct *dst, *tmp, *head, *prev;
267
268 head = copy_node(src);
269 dst = head; /* Else we barf on copying just one line */
270 head->prev = NULL;
271 tmp = src->next;
272 prev = head;
273
274 while (tmp != NULL) {
275 dst = copy_node(tmp);
276 dst->prev = prev;
277 prev->next = dst;
278
279 prev = dst;
280 tmp = tmp->next;
281 }
282
283 dst->next = NULL;
284 return head;
285}
286
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000287int free_filestruct(filestruct * src)
288{
289 filestruct *fileptr = src;
290
291 if (src == NULL)
292 return 0;
293
294 while (fileptr->next != NULL) {
295 fileptr = fileptr->next;
Chris Allegretta17dcb722001-01-20 21:40:07 +0000296 delete_node(fileptr->prev);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000297
298#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000299 fprintf(stderr, _("delete_node(): free'd a node, YAY!\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000300#endif
301 }
Chris Allegretta17dcb722001-01-20 21:40:07 +0000302 delete_node(fileptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000303#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000304 fprintf(stderr, _("delete_node(): free'd last node.\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000305#endif
306
307 return 1;
308}
309
310int renumber_all(void)
311{
312 filestruct *temp;
313 long i = 1;
314
315 for (temp = fileage; temp != NULL; temp = temp->next) {
316 temp->lineno = i++;
317 }
318
319 return 0;
320}
321
322int renumber(filestruct * fileptr)
323{
324 filestruct *temp;
325
326 if (fileptr == NULL || fileptr->prev == NULL || fileptr == fileage) {
327 renumber_all();
328 return 0;
329 }
330 for (temp = fileptr; temp != NULL; temp = temp->next) {
Chris Allegretta5146fec2000-12-10 05:44:02 +0000331 if (temp->prev != NULL)
332 temp->lineno = temp->prev->lineno + 1;
333 else
334 temp->lineno = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000335 }
336
337 return 0;
338}
339
340/* Fix the memory allocation for a string */
341void align(char **strp)
342{
343 /* There was a serious bug here: the new address was never
344 stored anywhere... */
345
346 *strp = nrealloc(*strp, strlen(*strp) + 1);
347}
348
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000349/* Null a string at a certain index and align it */
350void null_at(char *data, int index)
351{
352 data[index] = 0;
353 align(&data);
354}
355
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000356void usage(void)
357{
358#ifdef HAVE_GETOPT_LONG
359 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
360 printf(_("Option Long option Meaning\n"));
Chris Allegretta6724a7e2000-06-19 23:19:07 +0000361 printf(_
362 (" -T --tabsize=[num] Set width of a tab to num\n"));
Chris Allegretta805c26d2000-09-06 13:39:17 +0000363#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000364 printf(_
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000365 (" -R --regexp Use regular expressions for search\n"));
Chris Allegretta47805612000-07-07 02:35:34 +0000366#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000367 printf
368 (_
369 (" -V --version Print version information and exit\n"));
370 printf(_
371 (" -c --const Constantly show cursor position\n"));
372 printf(_
373 (" -h --help Show this message\n"));
Chris Allegrettad55655f2000-12-27 03:36:47 +0000374 printf(_
375 (" -i --autoindent Automatically indent new lines\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000376#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000377 printf(_
Chris Allegretta627de192000-07-12 02:09:17 +0000378 (" -k --cut Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000379#endif
Chris Allegretta627de192000-07-12 02:09:17 +0000380 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000381 (" -l --nofollow Don't follow symbolic links, overwrite\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000382#ifndef NANO_SMALL
383#ifdef NCURSES_MOUSE_VERSION
384 printf(_(" -m --mouse Enable mouse\n"));
385#endif
386#endif
Chris Allegrettad55655f2000-12-27 03:36:47 +0000387 printf(_
388 (" -p --pico Emulate Pico as closely as possible\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000389 printf
390 (_
391 (" -r [#cols] --fill=[#cols] Set fill cols to (wrap lines at) #cols\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000392#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000393 printf(_
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000394 (" -s [prog] --speller=[prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000395#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000396 printf(_
397 (" -t --tempfile Auto save on exit, don't prompt\n"));
398 printf(_
399 (" -v --view View (read only) mode\n"));
400 printf(_
401 (" -w --nowrap Don't wrap long lines\n"));
402 printf(_
403 (" -x --nohelp Don't show help window\n"));
404 printf(_
405 (" -z --suspend Enable suspend\n"));
406 printf(_
407 (" +LINE Start at line number LINE\n"));
408#else
409 printf(_("Usage: nano [option] +LINE <file>\n\n"));
410 printf(_("Option Meaning\n"));
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000411 printf(_(" -T [num] Set width of a tab to num\n"));
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000412 printf(_(" -R Use regular expressions for search\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000413 printf(_(" -V Print version information and exit\n"));
414 printf(_(" -c Constantly show cursor position\n"));
415 printf(_(" -h Show this message\n"));
Chris Allegrettad55655f2000-12-27 03:36:47 +0000416 printf(_(" -i Automatically indent new lines\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000417#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +0000418 printf(_(" -k Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000419#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000420 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000421 (" -l Don't follow symbolic links, overwrite\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000422#ifndef NANO_SMALL
423#ifdef NCURSES_MOUSE_VERSION
424 printf(_(" -m Enable mouse\n"));
425#endif
426#endif
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +0000427 printf(_(" -p Emulate Pico as closely as possible\n"));
Chris Allegrettad55655f2000-12-27 03:36:47 +0000428 printf(_(" -r [#cols] Set fill cols to (wrap lines at) #cols\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000429#ifndef DISABLE_SPELLER
Chris Allegrettad55655f2000-12-27 03:36:47 +0000430 printf(_(" -s [prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000431#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000432 printf(_(" -t Auto save on exit, don't prompt\n"));
433 printf(_(" -v View (read only) mode\n"));
434 printf(_(" -w Don't wrap long lines\n"));
435 printf(_(" -x Don't show help window\n"));
436 printf(_(" -z Enable suspend\n"));
437 printf(_(" +LINE Start at line number LINE\n"));
438#endif
439 exit(0);
440}
441
442void version(void)
443{
444 printf(_(" nano version %s by Chris Allegretta (compiled %s, %s)\n"),
445 VERSION, __TIME__, __DATE__);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000446 printf(_
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000447 (" Email: nano@nano-editor.org Web: http://www.nano-editor.org"));
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000448 printf(_("\n Compiled options:"));
Chris Allegrettaff269f82000-12-01 18:46:01 +0000449
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000450#ifdef NANO_EXTRA
451 printf(" --enable-extra");
452#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000453
454#ifdef NANO_SMALL
455 printf(" --enable-tiny");
456#else
457 #ifdef DISABLE_BROWSER
Chris Allegretta6636dc32001-01-05 05:41:07 +0000458 printf(" --disable-browser");
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000459 #endif
460 #ifdef DISABLE_TABCOMP
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000461 printf(" --disable-tabcomp");
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000462 #endif
463 #ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +0000464 printf(" --disable-justify");
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000465 #endif
466 #ifdef DISABLE_SPELLER
Chris Allegretta7b36c522000-12-06 01:08:10 +0000467 printf(" --disable-speller");
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000468 #endif
469 #ifdef DISABLE_HELP
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000470 printf(" --disable-help");
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000471 #endif
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000472#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000473
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000474#ifdef USE_SLANG
475 printf(" --with-slang");
476#endif
477 printf("\n");
478
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000479}
480
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000481filestruct *make_new_node(filestruct * prevnode)
482{
483 filestruct *newnode;
484
485 newnode = nmalloc(sizeof(filestruct));
486 newnode->data = NULL;
487
488 newnode->prev = prevnode;
489 newnode->next = NULL;
490
491 if (prevnode != NULL)
492 newnode->lineno = prevnode->lineno + 1;
493
494 return newnode;
495}
496
Chris Allegretta7975ed82000-07-28 00:58:35 +0000497/* Splice a node into an existing filestruct */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000498void splice_node(filestruct * begin, filestruct * new, filestruct * end)
Chris Allegretta7975ed82000-07-28 00:58:35 +0000499{
500 new->next = end;
501 new->prev = begin;
502 begin->next = new;
503 if (end != NULL)
504 end->prev = new;
505}
506
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000507int do_mark()
508{
509#ifdef NANO_SMALL
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000510 nano_disabled_msg();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000511#else
512 if (!ISSET(MARK_ISSET)) {
513 statusbar(_("Mark Set"));
514 SET(MARK_ISSET);
515 mark_beginbuf = current;
516 mark_beginx = current_x;
517 } else {
518 statusbar(_("Mark UNset"));
519 UNSET(MARK_ISSET);
520 mark_beginbuf = NULL;
521 mark_beginx = 0;
522
523 edit_refresh();
524 }
525#endif
526 return 1;
527}
528
529int no_help(void)
530{
531 if ISSET
532 (NO_HELP)
533 return 2;
534 else
535 return 0;
536}
537
Chris Allegretta3bc8c722000-12-10 17:03:25 +0000538#if defined(DISABLE_JUSTIFY) || defined(DISABLE_SPELLER) || defined(DISABLE_HELP)
Chris Allegrettaff269f82000-12-01 18:46:01 +0000539void nano_disabled_msg(void)
540{
541 statusbar("Sorry, support for this function has been disabled");
542}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000543#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000544
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000545/* The user typed a printable character; add it to the edit buffer */
546void do_char(char ch)
547{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000548 /* magic-line: when a character is inserted on the current magic line,
549 * it means we need a new one! */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000550 if (filebot == current && current->data[0] == '\0') {
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000551 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000552 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000553 }
554
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000555 /* More dangerousness fun =) */
556 current->data = nrealloc(current->data, strlen(current->data) + 2);
557 memmove(&current->data[current_x + 1],
558 &current->data[current_x],
559 strlen(current->data) - current_x + 1);
560 current->data[current_x] = ch;
561 do_right();
562
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000563 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000564 check_wrap(current, ch);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000565 set_modified();
566 check_statblank();
567 UNSET(KEEP_CUTBUFFER);
568 totsize++;
569
570}
571
572/* Someone hits return *gasp!* */
573int do_enter(filestruct * inptr)
574{
575 filestruct *new;
576 char *tmp, *spc;
577 int extra = 0;
578
579 new = make_new_node(inptr);
580 tmp = &current->data[current_x];
581 current_x = 0;
582
583 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
584 if (ISSET(AUTOINDENT)) {
585 spc = current->data;
586 if (spc) {
587 while ((*spc == ' ') || (*spc == '\t')) {
588 extra++;
589 spc++;
590 current_x++;
591 }
592 new->data = nmalloc(strlen(tmp) + extra + 1);
593 strncpy(new->data, current->data, extra);
594 strcpy(&new->data[extra], tmp);
595 }
596 } else {
597 new->data = nmalloc(strlen(tmp) + 1);
598 strcpy(new->data, tmp);
599 }
600 *tmp = 0;
601
Chris Allegrettada721be2000-07-31 01:26:42 +0000602 if (inptr->next == NULL) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000603 filebot = new;
604 editbot = new;
605 }
Chris Allegretta7975ed82000-07-28 00:58:35 +0000606 splice_node(inptr, new, inptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000607
608 totsize++;
609 renumber(current);
610 current = new;
611 align(&current->data);
612
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000613 /* The logic here is as follows:
614 * -> If we are at the bottom of the buffer, we want to recenter
615 * (read: rebuild) the screen and forcably move the cursor.
616 * -> otherwise, we want simply to redraw the screen and update
617 * where we think the cursor is.
618 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000619 if (current_y == editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +0000620 edit_update(current, CENTER);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000621 reset_cursor();
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000622 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000623 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000624 edit_refresh();
625 update_cursor();
626 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000627
628 totlines++;
629 set_modified();
630
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000631 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000632 return 1;
633}
634
635int do_enter_void(void)
636{
637 return do_enter(current);
638}
639
640void do_next_word(void)
641{
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000642 filestruct *fileptr, *old;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000643 int i;
644
645 if (current == NULL)
646 return;
647
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000648 old = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000649 i = current_x;
650 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
651 if (fileptr == current) {
652 while (isalnum((int) fileptr->data[i])
653 && fileptr->data[i] != 0)
654 i++;
655
656 if (fileptr->data[i] == 0) {
657 i = 0;
658 continue;
659 }
660 }
661 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
662 i++;
663
664 if (fileptr->data[i] != 0)
665 break;
666
667 i = 0;
668 }
669 if (fileptr == NULL)
670 current = filebot;
671 else
672 current = fileptr;
673
674 current_x = i;
675 placewewant = xplustabs();
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000676
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000677 if (current->lineno >= editbot->lineno)
Chris Allegretta234a34d2000-07-29 04:33:38 +0000678 edit_update(current, CENTER);
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000679 else {
680 /* If we've jumped lines, refresh the old line. We can't just use
681 * current->prev here, because we may have skipped over some blank
682 * lines, in which case the previous line is the wrong one.
683 */
684 if (current != old)
685 update_line(old, 0);
686
687 update_line(current, current_x);
688 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000689
690}
691
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000692void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000693{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000694 int i = 0; /* Index into ->data for line. */
695 int i_tabs = 0; /* Screen position of ->data[i]. */
696 int last_word_end = -1; /* Location of end of last word found. */
697 int current_word_start = -1; /* Location of start of current word. */
698 int current_word_start_t = -1; /* Location of start of current word screen position. */
699 int current_word_end = -1; /* Location of end of current word */
700 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000701 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000702
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000703 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000704 int right = 0;
705 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000706
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000707 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000708
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000709 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000710 if (!isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000711 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000712
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000713 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000714 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000715
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000716 while (!isspace((int) inptr->data[i])
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000717 && inptr->data[i]) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000718 i++;
719 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000720 if (inptr->data[i] < 32)
721 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000722 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000723
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000724 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000725 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000726 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000727 } else {
728 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000729 current_word_end_t = i_tabs - 1;
730 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000731 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000732
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000733 if (inptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000734 if (i_tabs % tabsize != 0);
735 i_tabs += tabsize - (i_tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000736 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000737
Adam Rogoyski09f97962000-06-20 02:50:33 +0000738 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000739 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000740 }
741
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000742 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000743 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000744 * a) one word takes up the whole line with no starting spaces.
745 * - do nothing and return.
746 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000747 * - word starts new line.
748 * - keep white space on original line up to the cursor.
749 * *) cursor is after word at wrap point
750 * - either it's all white space after word, and this routine isn't called.
751 * - or we are actually in case 2 (2 words).
752 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000753 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000754 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000755 * - white space at end of original line is cleared, unless
756 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000757 * b) cursor is at the word at the wrap point.
758 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000759 * 1. pressed a space and at first character of wrap point word.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000760 * - white space on original line is kept to where cursor was.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000761 * 2. pressed non space (or space elsewhere).
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000762 * - white space at end of original line is cleared.
763 * c) cursor is past the word at the wrap point.
764 * - word at wrap point starts a new line.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000765 * - white space at end of original line is cleared
766 */
767
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000768 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000769
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000770 /* Category 1a: one word taking up the whole line with no beginning spaces. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000771 if ((last_word_end == -1) && (!isspace((int) inptr->data[0]))) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000772 for (i = current_word_end; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000773 if (!isspace((int) inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000774 current_word_start = i;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000775 while (!isspace((int) inptr->data[i]) && (i < len)) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000776 i++;
777 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000778 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000779 current_word_end = i;
780 break;
781 }
782 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000783
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000784 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000785 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000786 return;
787 }
788 if (current_x >= last_word_end) {
789 right = (current_x - current_word_start) + 1;
790 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000791 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000792 }
793
794 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
795 strcpy(temp->data, &inptr->data[current_word_start]);
796 inptr->data = nrealloc(inptr->data, last_word_end + 2);
797 inptr->data[last_word_end + 1] = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000798 } else
799 /* Category 1b: one word on the line and word not taking up whole line
800 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000801 if (last_word_end == -1) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000802 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
803 strcpy(temp->data, &inptr->data[current_word_start]);
804
805 /* Inside word, remove it from original, and move cursor to right spot. */
806 if (current_x >= current_word_start) {
807 right = current_x - current_word_start;
808 current_x = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000809 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000810 }
811
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000812 null_at(inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000813
814 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
815 mark_beginbuf = temp;
816 mark_beginx = 0;
817 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000818 }
819
820 /* Category 2: two or more words on the line. */
821 else {
822
823 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000824 if (current_x < current_word_start) {
825 temp->data =
826 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
827 strcpy(temp->data, &inptr->data[current_word_start]);
828
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000829 if (!isspace((int) input_char)) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000830 i = current_word_start - 1;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000831 while (isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000832 i--;
833 assert(i >= 0);
834 }
835 } else if (current_x <= last_word_end)
836 i = last_word_end - 1;
837 else
838 i = current_x;
839
840 inptr->data = nrealloc(inptr->data, i + 2);
841 inptr->data[i + 1] = 0;
842 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000843
844
845 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000846 else if ((current_x >= current_word_start)
847 && (current_x <= (current_word_end + 1))) {
848 temp->data =
849 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000850 strcpy(temp->data, &inptr->data[current_word_start]);
851
852 down = 1;
853
854 right = current_x - current_word_start;
855 i = current_word_start - 1;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000856 if (isspace((int) input_char)
857 && (current_x == current_word_start)) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000858 current_x = current_word_start;
859
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000860 null_at(inptr->data, current_word_start);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000861 } else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000862
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000863 while (isspace((int) inptr->data[i])) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000864 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000865 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000866 }
867 inptr->data = nrealloc(inptr->data, i + 2);
868 inptr->data[i + 1] = 0;
869 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000870 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000871
872
873 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000874 else {
875 temp->data =
876 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000877 strcpy(temp->data, &inptr->data[current_word_start]);
878
879 down = 1;
880 right = current_x - current_word_start;
881
882 current_x = current_word_start;
883 i = current_word_start - 1;
884
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000885 while (isspace((int) inptr->data[i])) {
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000886 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000887 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000888 inptr->data = nrealloc(inptr->data, i + 2);
889 inptr->data[i + 1] = 0;
890 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000891 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000892 }
893
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000894 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000895 if (ISSET(SAMELINEWRAP) && inptr->next) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000896 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
897 char *p =
898 nmalloc(strlen(temp->data) + strlen(inptr->next->data) + 2);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000899 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000900
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000901 strcpy(p, temp->data);
902 strcat(p, " ");
903 strcat(p, inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000904
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000905 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000906 inptr->next->data = p;
907
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000908 free(temp->data);
909 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000910
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000911 current_x = old_x;
912 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000913 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000914 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000915 else {
916 temp->prev = inptr;
917 temp->next = inptr->next;
918
919 if (inptr->next)
920 inptr->next->prev = temp;
921 inptr->next = temp;
922
923 if (!temp->next)
924 filebot = temp;
925
926 SET(SAMELINEWRAP);
927 }
928
929
930 totlines++;
Robert Siemborskia417ddc2000-07-24 23:18:48 +0000931 /* Everything about it makes me want this line here but it causes
932 * totsize to be high by one for some reason. Sigh. (Rob) */
933 /* totsize++; */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000934
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000935 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +0000936 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000937
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000938
939 /* Move the cursor to the new line if appropriate. */
940 if (down) {
941 do_right();
942 }
943
944 /* Move the cursor to the correct spot in the line if appropriate. */
945 while (right--) {
946 do_right();
947 }
948
Chris Allegretta234a34d2000-07-29 04:33:38 +0000949 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000950 reset_cursor();
951 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000952}
953
954/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000955void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000956{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000957 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000958#ifdef DEBUG
959 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
960 inptr->data);
961#endif
962
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000963 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000964 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000965 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000966 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000967
968 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000969 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000970
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000971 while (isspace((int) inptr->data[i]) && inptr->data[i])
Adam Rogoyski09f97962000-06-20 02:50:33 +0000972 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000973
Adam Rogoyski09f97962000-06-20 02:50:33 +0000974 if (!inptr->data[i])
975 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000976
Adam Rogoyski09f97962000-06-20 02:50:33 +0000977 /* String must be at least 1 character long. */
978 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000979 if (isspace((int) inptr->data[i])) {
Adam Rogoyski09f97962000-06-20 02:50:33 +0000980 if (!char_found)
981 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000982 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000983 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000984 } else
985 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000986 }
Adam Rogoyski09f97962000-06-20 02:50:33 +0000987
988 if (char_found == 2)
989 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000990 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000991}
992
993/* Stuff we do when we abort from programs and want to clean up the
994 * screen. This doesnt do much right now.
995 */
996void do_early_abort(void)
997{
998 blank_statusbar_refresh();
999}
1000
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001001int do_backspace(void)
1002{
1003 filestruct *previous, *tmp;
1004
1005 if (current_x != 0) {
1006 /* Let's get dangerous */
1007 memmove(&current->data[current_x - 1], &current->data[current_x],
1008 strlen(current->data) - current_x + 1);
1009#ifdef DEBUG
1010 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
1011#endif
1012 align(&current->data);
1013 do_left();
1014 } else {
1015 if (current == fileage)
1016 return 0; /* Can't delete past top of file */
1017
1018 previous = current->prev;
1019 current_x = strlen(previous->data);
1020 previous->data = nrealloc(previous->data,
1021 strlen(previous->data) +
1022 strlen(current->data) + 1);
1023 strcat(previous->data, current->data);
1024
1025 tmp = current;
1026 unlink_node(current);
1027 delete_node(current);
1028 if (current == edittop) {
1029 if (previous->next)
1030 current = previous->next;
1031 else
1032 current = previous;
Chris Allegrettada721be2000-07-31 01:26:42 +00001033 page_up_center();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001034 } else {
1035 if (previous->next)
1036 current = previous->next;
1037 else
1038 current = previous;
1039 update_line(current, current_x);
1040 }
1041
1042 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001043 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001044 filebot = current;
1045 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001046
1047 /* Recreate the magic line if we're deleting it AND if the
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001048 line we're on now is NOT blank. if it is blank we
1049 can just use IT for the magic line. This is how Pico
1050 appears to do it, in any case */
Chris Allegretta28a0f892000-07-05 22:47:54 +00001051 if (strcmp(current->data, "")) {
1052 new_magicline();
1053 fix_editbot();
1054 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001055 }
1056
1057 current = previous;
1058 renumber(current);
1059 previous_line();
1060 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001061#ifdef DEBUG
1062 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
1063#endif
1064
1065 }
1066
1067 totsize--;
1068 set_modified();
1069 UNSET(KEEP_CUTBUFFER);
1070 edit_refresh();
1071 return 1;
1072}
1073
1074int do_delete(void)
1075{
1076 filestruct *foo;
1077
1078 if (current_x != strlen(current->data)) {
1079 /* Let's get dangerous */
1080 memmove(&current->data[current_x], &current->data[current_x + 1],
1081 strlen(current->data) - current_x);
1082
1083 align(&current->data);
1084
1085 } else if (current->next != NULL) {
1086 current->data = nrealloc(current->data,
1087 strlen(current->data) +
1088 strlen(current->next->data) + 1);
1089 strcat(current->data, current->next->data);
1090
1091 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001092 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001093 filebot = current;
1094 editbot = current;
1095 }
1096
1097 unlink_node(foo);
1098 delete_node(foo);
1099 update_line(current, current_x);
1100
Chris Allegretta28a0f892000-07-05 22:47:54 +00001101 /* Please see the comment in do_basckspace if you don't understand
1102 this test */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001103 if (current == filebot && strcmp(current->data, "")) {
Chris Allegretta28a0f892000-07-05 22:47:54 +00001104 new_magicline();
1105 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001106 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001107 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001108 renumber(current);
1109 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001110 } else
1111 return 0;
1112
1113 totsize--;
1114 set_modified();
1115 UNSET(KEEP_CUTBUFFER);
1116 edit_refresh();
1117 return 1;
1118}
1119
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001120void wrap_reset(void)
1121{
1122 UNSET(SAMELINEWRAP);
1123}
1124
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001125#ifndef DISABLE_SPELLER
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001126
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001127int do_int_spell_fix(char *word)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001128{
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001129 char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001130 filestruct *begin;
1131 int i = 0, j = 0, beginx, beginx_top;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001132
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001133 /* save where we are */
1134 begin = current;
1135 beginx = current_x + 1;
1136
1137 /* save the current search/replace strings */
1138 search_init_globals();
1139 save_search = mallocstrcpy(save_search, last_search);
1140 save_replace = mallocstrcpy(save_replace, last_replace);
1141
1142 /* set search/replace strings to mis-spelt word */
1143 prevanswer = mallocstrcpy(prevanswer, word);
1144 last_search = mallocstrcpy(last_search, word);
1145 last_replace = mallocstrcpy(last_replace, word);
1146
1147 /* start from the top of file */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001148 current = fileage;
1149 current_x = beginx_top = -1;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001150
1151 search_last_line = FALSE;
1152
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001153 edit_update(fileage, TOP);
1154
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001155 /* make sure word is still mis-spelt (i.e. when multi-errors) */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001156 if (findnextstr(TRUE, fileage, beginx_top, prevanswer) != NULL)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001157 {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001158 do_replace_highlight(TRUE, prevanswer);
1159
1160 /* allow replace word to be corrected */
1161 i = statusq(0, spell_list, SPELL_LIST_LEN, last_replace,
1162 _("Edit a replacement"));
1163
1164 do_replace_highlight(FALSE, prevanswer);
1165
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001166 /* start from the start of this line again */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001167 current = fileage;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001168 current_x = beginx_top;
1169
1170 search_last_line = FALSE;
1171
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001172 j = i;
1173 do_replace_loop(prevanswer, fileage, &beginx_top, TRUE, &j);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001174 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001175
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001176 /* restore the search/replace strings */
1177 last_search = mallocstrcpy(last_search, save_search);
1178 last_replace = mallocstrcpy(last_replace, save_replace);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001179
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001180 /* restore where we were */
1181 current = begin;
1182 current_x = beginx - 1;
1183
1184 edit_update(current, CENTER);
1185
1186 if (i == -1)
1187 return FALSE;
1188
1189 return TRUE;
1190}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001191
1192/* Integrated spell checking using 'spell' program */
Chris Allegretta271e9722000-11-10 18:15:43 +00001193int do_int_speller(char *tempfile_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001194{
Chris Allegretta271e9722000-11-10 18:15:43 +00001195 char *read_buff, *read_buff_ptr, *read_buff_word;
1196 long pipe_buff_size;
1197 int in_fd[2], tempfile_fd;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001198 int spell_status;
1199 pid_t pid_spell;
1200 ssize_t bytesread;
1201
Chris Allegretta271e9722000-11-10 18:15:43 +00001202 /* Create a pipe to spell program */
1203
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001204 if (pipe(in_fd) == -1)
1205 return FALSE;
1206
Chris Allegretta271e9722000-11-10 18:15:43 +00001207 /* A new process to run spell in */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001208
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001209 if ( (pid_spell = fork()) == 0) {
1210
1211 /* Child continues, (i.e. future spell process) */
1212
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001213 close(in_fd[0]);
1214
Chris Allegretta271e9722000-11-10 18:15:43 +00001215 /* replace the standard in with the tempfile */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001216
Chris Allegretta271e9722000-11-10 18:15:43 +00001217 if ( (tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
1218
1219 close(in_fd[1]);
1220 exit(1);
1221 }
1222
1223 if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
1224
1225 close(tempfile_fd);
1226 close(in_fd[1]);
1227 exit(1);
1228 }
1229 close(tempfile_fd);
1230
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001231
Chris Allegretta271e9722000-11-10 18:15:43 +00001232 /* send spell's standard out to the pipe */
1233
1234 if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1235
1236 close(in_fd[1]);
1237 exit(1);
1238 }
1239 close(in_fd[1]);
1240
1241 /* Start spell program, we are using the PATH here!?!? */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001242 execlp("spell", "spell", NULL);
1243
Chris Allegretta271e9722000-11-10 18:15:43 +00001244 /* Should not be reached, if spell is found!!! */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001245
Chris Allegretta271e9722000-11-10 18:15:43 +00001246 exit(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001247 }
1248
1249 /* Parent continues here */
1250
Chris Allegretta271e9722000-11-10 18:15:43 +00001251 close(in_fd[1]);
1252
1253 /* Child process was not forked successfully */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001254
1255 if (pid_spell < 0) {
1256
Chris Allegretta271e9722000-11-10 18:15:43 +00001257 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001258 return FALSE;
1259 }
1260
Chris Allegretta271e9722000-11-10 18:15:43 +00001261 /* Get system pipe buffer size */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001262
Chris Allegretta271e9722000-11-10 18:15:43 +00001263 if ( (pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001264
Chris Allegretta271e9722000-11-10 18:15:43 +00001265 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001266 return FALSE;
Chris Allegretta271e9722000-11-10 18:15:43 +00001267 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001268
Chris Allegretta271e9722000-11-10 18:15:43 +00001269 read_buff = nmalloc( pipe_buff_size + 1 );
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001270
Chris Allegretta271e9722000-11-10 18:15:43 +00001271 /* Process the returned spelling errors */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001272
Chris Allegretta271e9722000-11-10 18:15:43 +00001273 while ( (bytesread = read(in_fd[0], read_buff, pipe_buff_size)) > 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001274
Chris Allegretta271e9722000-11-10 18:15:43 +00001275 read_buff[bytesread] = (char) NULL;
1276 read_buff_word = read_buff_ptr = read_buff;
1277
1278 while (*read_buff_ptr != (char) NULL) {
1279
1280 /* Windows version may need to process additional char '\r' */
1281
1282 /* Possible problem here if last word not followed by '\n' */
1283
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001284 if (*read_buff_ptr == '\n') {
Chris Allegretta271e9722000-11-10 18:15:43 +00001285 *read_buff_ptr = (char) NULL;
1286 if (!do_int_spell_fix(read_buff_word)) {
1287
1288 close(in_fd[0]);
1289 free(read_buff);
1290 replace_abort();
1291
1292 return TRUE;
1293 }
1294 read_buff_word = read_buff_ptr;
1295 read_buff_word++;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001296 }
1297
1298 read_buff_ptr++;
1299 }
1300 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001301
1302 close(in_fd[0]);
1303 free(read_buff);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001304 replace_abort();
1305
Chris Allegretta271e9722000-11-10 18:15:43 +00001306 /* Process end of spell process */
1307
1308 wait(&spell_status);
1309 if (WIFEXITED(spell_status)) {
1310 if (WEXITSTATUS(spell_status) != 0)
1311 return FALSE;
1312 }
1313 else
1314 return FALSE;
1315
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001316 return TRUE;
1317}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001318
1319/* External spell checking */
Chris Allegretta271e9722000-11-10 18:15:43 +00001320int do_alt_speller(char *file_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001321{
Chris Allegretta271e9722000-11-10 18:15:43 +00001322 int alt_spell_status;
1323 pid_t pid_spell;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001324
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001325 endwin();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001326
Chris Allegretta271e9722000-11-10 18:15:43 +00001327 /* Start a new process for the alternate speller */
1328
1329 if ( (pid_spell = fork()) == 0) {
1330
1331 /* Start alternate spell program, we are using the PATH here!?!? */
1332 execlp(alt_speller, alt_speller, file_name, NULL);
1333
1334 /* Should not be reached, if alternate speller is found!!! */
1335
1336 exit(1);
1337 }
1338
1339 /* Could not fork?? */
1340
1341 if (pid_spell < 0)
1342 return FALSE;
1343
1344 /* Wait for alternate speller to complete */
1345
1346 wait(&alt_spell_status);
1347 if (WIFEXITED(alt_spell_status)) {
1348 if (WEXITSTATUS(alt_spell_status) != 0)
1349 return FALSE;
1350 }
1351 else
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001352 return FALSE;
1353
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001354 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001355 free_filestruct(fileage);
1356 global_init();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001357 open_file(file_name, 0, 1);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001358 edit_update(fileage, CENTER);
Chris Allegretta271e9722000-11-10 18:15:43 +00001359 display_main_list();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001360 set_modified();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001361
1362 return TRUE;
1363}
1364#endif
1365
1366int do_spell(void)
1367{
1368
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001369#ifdef DISABLE_SPELLER
Chris Allegrettaff269f82000-12-01 18:46:01 +00001370 nano_disabled_msg();
1371 return (TRUE);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001372#else
Chris Allegretta271e9722000-11-10 18:15:43 +00001373 char *temp;
1374 int spell_res;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001375
Chris Allegretta271e9722000-11-10 18:15:43 +00001376 if ((temp = tempnam(0, "nano.")) == NULL) {
1377 statusbar(_("Could not create a temporary filename: %s"),
1378 strerror(errno));
1379 return 0;
1380 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001381
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001382 if (write_file(temp, 1) == -1) {
1383 statusbar(_("Spell checking failed: unable to write temp file!"));
Chris Allegretta271e9722000-11-10 18:15:43 +00001384 return 0;
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001385 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001386
Chris Allegretta271e9722000-11-10 18:15:43 +00001387 if (alt_speller)
1388 spell_res = do_alt_speller(temp);
1389 else
1390 spell_res = do_int_speller(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001391
Chris Allegretta271e9722000-11-10 18:15:43 +00001392 remove(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001393
1394 if (spell_res)
1395 statusbar(_("Finished checking spelling"));
1396 else
1397 statusbar(_("Spell checking failed"));
1398
1399 return spell_res;
1400
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001401#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001402}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001403
1404int do_exit(void)
1405{
1406 int i;
1407
1408 if (!ISSET(MODIFIED))
1409 finish(0);
1410
Chris Allegretta30885552000-07-14 01:20:12 +00001411 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001412 i = 1;
1413 } else {
1414 i =
1415 do_yesno(0, 0,
1416 _
1417 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1418 }
1419
1420#ifdef DEBUG
1421 dump_buffer(fileage);
1422#endif
1423
1424 if (i == 1) {
Chris Allegrettae1ebaf32001-01-07 05:50:36 +00001425 if (do_writeout(filename, 1) > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001426 finish(0);
1427 } else if (i == 0)
1428 finish(0);
1429 else
1430 statusbar(_("Cancelled"));
1431
1432 display_main_list();
1433 return 1;
1434}
1435
1436#ifndef NANO_SMALL
1437#ifdef NCURSES_MOUSE_VERSION
1438void do_mouse(void)
1439{
1440 MEVENT mevent;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001441 int foo = 0, tab_found = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001442
1443 if (getmouse(&mevent) == ERR)
1444 return;
1445
1446 /* If mouse not in edit window, return (add help selection later). */
1447 if (!wenclose(edit, mevent.y, mevent.x))
1448 return;
1449
1450 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1451 mevent.y -= 2;
1452
1453 /* Selecting where the cursor is sets the mark.
1454 * Selecting beyond the line length with the cursor at the end of the
1455 * line sets the mark as well.
1456 */
1457 if ((mevent.y == current_y) &&
1458 ((mevent.x == current_x) || (current_x == strlen(current->data)
1459 && (mevent.x >
1460 strlen(current->data))))) {
1461 if (ISSET(VIEW_MODE)) {
1462 print_view_warning();
1463 return;
1464 }
1465 do_mark();
1466 } else if (mevent.y > current_y) {
1467 while (mevent.y > current_y) {
1468 if (current->next != NULL)
1469 current = current->next;
1470 else
1471 break;
1472 current_y++;
1473 }
1474 } else if (mevent.y < current_y) {
1475 while (mevent.y < current_y) {
1476 if (current->prev != NULL)
1477 current = current->prev;
1478 else
1479 break;
1480 current_y--;
1481 }
1482 }
1483 current_x = mevent.x;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001484 placewewant = current_x;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001485 while (foo < current_x) {
1486 if (current->data[foo] == NANO_CONTROL_I) {
Chris Allegrettae10debd2000-08-22 01:26:42 +00001487 current_x -= tabsize - (foo % tabsize);
1488 tab_found = 1;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001489 } else if (current->data[foo] & 0x80);
1490 else if (current->data[foo] < 32)
Chris Allegrettae10debd2000-08-22 01:26:42 +00001491 current_x--;
1492 foo++;
1493 }
1494 /* This is where tab_found comes in. I can't figure out why,
1495 * but without it any line with a tab will place the cursor
1496 * one character behind. Whatever, this fixes it. */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001497 if (tab_found == 1)
Chris Allegrettae10debd2000-08-22 01:26:42 +00001498 current_x++;
1499
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001500 if (current_x > strlen(current->data))
1501 current_x = strlen(current->data);
1502
1503 update_cursor();
1504 edit_refresh();
1505
1506}
1507#endif
1508#endif
1509
1510/* Handler for SIGHUP */
1511RETSIGTYPE handle_hup(int signal)
1512{
Chris Allegrettae7a58932000-12-02 02:36:22 +00001513 die(_("Received SIGHUP"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001514}
1515
Chris Allegretta18f8be02000-09-04 03:20:38 +00001516/* What do we do when we catch the suspend signal */
1517RETSIGTYPE do_suspend(int signal)
1518{
1519
1520 act.sa_handler = SIG_DFL;
1521 sigemptyset(&act.sa_mask);
1522 sigaction(SIGTSTP, &act, NULL);
1523
1524 endwin();
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001525 fprintf(stderr, "\n\n\n\n\nUse \"fg\" to return to nano\n");
Chris Allegretta18f8be02000-09-04 03:20:38 +00001526 raise(SIGTSTP);
1527}
1528
1529/* Restore the suspend handler when we come back into the prog */
1530RETSIGTYPE do_cont(int signal)
1531{
1532
1533 act.sa_handler = do_suspend;
1534 sigemptyset(&act.sa_mask);
1535 sigaction(SIGTSTP, &act, NULL);
1536 initscr();
1537 total_refresh();
1538}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001539
1540void handle_sigwinch(int s)
1541{
1542#ifndef NANO_SMALL
1543 char *tty = NULL;
1544 int fd = 0;
1545 int result = 0;
1546 int i = 0;
1547 struct winsize win;
1548
1549 tty = ttyname(0);
1550 if (!tty)
1551 return;
1552 fd = open(tty, O_RDWR);
1553 if (fd == -1)
1554 return;
1555 result = ioctl(fd, TIOCGWINSZ, &win);
1556 if (result == -1)
1557 return;
1558
1559
1560 COLS = win.ws_col;
1561 LINES = win.ws_row;
1562
Chris Allegrettae61e8302001-01-14 05:18:27 +00001563 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1564 die_too_small();
1565
1566 if ((fill = COLS - CHARS_FROM_EOL) < MIN_FILL_LENGTH)
1567 die_too_small();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001568
1569 free(hblank);
1570 hblank = nmalloc(COLS + 1);
1571
1572 for (i = 0; i <= COLS - 1; i++)
1573 hblank[i] = ' ';
1574 hblank[i] = 0;
1575
1576#ifdef HAVE_NCURSES_H
1577 resizeterm(LINES, COLS);
1578#ifdef HAVE_WRESIZE
1579 if (wresize(topwin, 2, COLS) == ERR)
1580 die(_("Cannot resize top win"));
1581 if (mvwin(topwin, 0, 0) == ERR)
1582 die(_("Cannot move top win"));
1583 if (wresize(edit, editwinrows, COLS) == ERR)
1584 die(_("Cannot resize edit win"));
1585 if (mvwin(edit, 2, 0) == ERR)
1586 die(_("Cannot move edit win"));
1587 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1588 die(_("Cannot resize bottom win"));
1589 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1590 die(_("Cannot move bottom win"));
1591#endif /* HAVE_WRESIZE */
1592#endif /* HAVE_NCURSES_H */
1593
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001594 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001595
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001596 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001597 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001598 }
1599 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00001600
1601 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001602 refresh();
Chris Allegrettaf4b96012001-01-03 07:11:47 +00001603 titlebar(NULL);
Chris Allegretta97accc62000-06-19 05:45:52 +00001604 edit_refresh();
1605 display_main_list();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001606 total_refresh();
1607#endif
1608}
1609
Chris Allegretta756f2202000-09-01 13:32:47 +00001610void signal_init(void)
1611{
Chris Allegretta756f2202000-09-01 13:32:47 +00001612
1613 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
1614 memset(&act, 0, sizeof(struct sigaction));
1615 act.sa_handler = SIG_IGN;
1616 sigaction(SIGINT, &act, NULL);
Chris Allegretta756f2202000-09-01 13:32:47 +00001617
Chris Allegretta18f8be02000-09-04 03:20:38 +00001618 if (!ISSET(SUSPEND)) {
Chris Allegretta756f2202000-09-01 13:32:47 +00001619 sigaction(SIGTSTP, &act, NULL);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001620 } else {
Chris Allegretta18f8be02000-09-04 03:20:38 +00001621 act.sa_handler = do_suspend;
1622 sigaction(SIGTSTP, &act, NULL);
1623
1624 act.sa_handler = do_cont;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001625 sigaction(SIGCONT, &act, NULL);
Chris Allegretta18f8be02000-09-04 03:20:38 +00001626 }
1627
Chris Allegretta756f2202000-09-01 13:32:47 +00001628
1629 /* Trap SIGHUP cuz we want to write the file out. */
1630 act.sa_handler = handle_hup;
1631 sigaction(SIGHUP, &act, NULL);
1632
1633 act.sa_handler = handle_sigwinch;
1634 sigaction(SIGWINCH, &act, NULL);
1635
1636}
1637
Chris Allegretta2a42af12000-09-12 23:02:49 +00001638void window_init(void)
1639{
Chris Allegrettae61e8302001-01-14 05:18:27 +00001640 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1641 die_too_small();
Chris Allegretta92c9dd22000-09-13 14:03:27 +00001642
Chris Allegretta2a42af12000-09-12 23:02:49 +00001643 /* Setup up the main text window */
1644 edit = newwin(editwinrows, COLS, 2, 0);
1645
1646 /* And the other windows */
1647 topwin = newwin(2, COLS, 0, 0);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001648 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00001649
Chris Allegretta155d6202001-01-08 01:50:37 +00001650#ifdef PDCURSES
1651 /* Oops, I guess we need this again.
1652 Moved here so the keypad still works after a Meta-X, for example */
1653 keypad(edit, TRUE);
1654 keypad(bottomwin, TRUE);
1655#endif
1656
Chris Allegretta2a42af12000-09-12 23:02:49 +00001657}
1658
Chris Allegretta756f2202000-09-01 13:32:47 +00001659void mouse_init(void)
1660{
1661#ifndef NANO_SMALL
1662#ifdef NCURSES_MOUSE_VERSION
1663 if (ISSET(USE_MOUSE)) {
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001664 keypad_on(edit, 1);
1665
Chris Allegretta756f2202000-09-01 13:32:47 +00001666 mousemask(BUTTON1_RELEASED, NULL);
1667 mouseinterval(50);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00001668
Chris Allegretta63c8ab92001-01-04 02:33:52 +00001669 } else
Chris Allegretta756f2202000-09-01 13:32:47 +00001670 mousemask(0, NULL);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00001671
Chris Allegretta756f2202000-09-01 13:32:47 +00001672#endif
1673#endif
1674
1675}
1676
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001677int do_tab(void)
1678{
1679 do_char('\t');
1680 return 1;
1681}
1682
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001683#ifndef DISABLE_JUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001684int empty_line(const char *data)
1685{
1686 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001687 if (!isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001688 return 0;
1689
1690 data++;
1691 }
1692
1693 return 1;
1694}
1695
1696int no_spaces(const char *data)
1697{
1698 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001699 if (isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001700 return 0;
1701
1702 data++;
1703 }
1704
1705 return 1;
1706}
1707
1708void justify_format(char *data)
1709{
1710 int i = 0;
1711 int len = strlen(data);
1712
1713 /* Skip first character regardless and leading whitespace. */
1714 for (i = 1; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001715 if (!isspace((int) data[i]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001716 break;
1717 }
1718
1719 i++; /* (i) is now at least 2. */
1720
1721 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
1722 for (; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001723 if (isspace((int) data[i]) && isspace((int) data[i - 1])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001724 && (data[i - 2] != '.')) {
1725 memmove(data + i, data + i + 1, len - i);
1726 len--;
1727 i--;
1728 }
1729 }
1730}
1731#endif
1732
1733int do_justify(void)
1734{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001735#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +00001736 nano_disabled_msg();
1737 return 1;
1738#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001739 int slen = 0; /* length of combined lines on one line. */
Chris Allegretta17dcb722001-01-20 21:40:07 +00001740 int initial_y, kbinput = 0, totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00001741 filestruct *initial = NULL, *tmpjust = NULL, *cutbak, *tmptop, *tmpbot;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001742
1743 if (empty_line(current->data)) {
1744 /* Justify starting at first non-empty line. */
1745 do {
1746 if (!current->next)
1747 return 1;
1748
1749 current = current->next;
1750 current_y++;
1751 }
1752 while (empty_line(current->data));
1753 } else {
1754 /* Search back for the beginning of the paragraph, where
1755 * Paragraph is 1) A line with leading whitespace
1756 * or 2) A line following an empty line.
1757 */
1758 while (current->prev != NULL) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001759 if (isspace((int) current->data[0]) || !current->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001760 break;
1761
1762 current = current->prev;
1763 current_y--;
1764 }
1765
1766 /* First line with leading whitespace may be empty. */
1767 if (empty_line(current->data)) {
1768 if (current->next) {
1769 current = current->next;
1770 current_y++;
1771 } else
1772 return 1;
1773 }
1774 }
1775 initial = current;
1776 initial_y = current_y;
1777
1778 set_modified();
Chris Allegretta9149e612000-11-27 00:23:41 +00001779 cutbak = cutbuffer; /* Got to like cutbak ;) */
Chris Allegretta17dcb722001-01-20 21:40:07 +00001780 totbak = totsize;
Chris Allegretta9149e612000-11-27 00:23:41 +00001781 cutbuffer = NULL;
1782
1783 tmptop = current;
1784 tmpjust = copy_node(current);
1785 add_to_cutbuffer(tmpjust);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001786 /* Put the whole paragraph into one big line. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001787 while (current->next && !isspace((int) current->next->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001788 && current->next->data[0]) {
1789 filestruct *tmpnode = current->next;
1790 int len = strlen(current->data);
1791 int len2 = strlen(current->next->data);
1792
Chris Allegretta9149e612000-11-27 00:23:41 +00001793 tmpjust = NULL;
Chris Allegretta9149e612000-11-27 00:23:41 +00001794 tmpjust = copy_node(current->next);
1795 add_to_cutbuffer(tmpjust);
1796
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001797 /* length of both strings plus space between strings and ending \0. */
1798 current->data = nrealloc(current->data, len + len2 + 2);
1799 current->data[len++] = ' ';
1800 current->data[len] = '\0';
1801
1802 strncat(current->data, current->next->data, len2);
1803
1804 unlink_node(tmpnode);
1805 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001806 }
1807
1808 justify_format(current->data);
1809
1810 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001811 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001812
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001813 if ((strlenpt(current->data) > (fill))
1814 && !no_spaces(current->data)) {
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001815 do {
1816 int i = 0;
1817 int len2 = 0;
1818 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001819
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001820 /* Start at fill , unless line isn't that long (but it
1821 * appears at least fill long with tabs.
1822 */
1823 if (slen > fill)
1824 i = fill;
1825 else
1826 i = slen;
1827 for (; i > 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001828 if (isspace((int) current->data[i]) &&
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001829 ((strlenpt(current->data) - strlen(current->data + i))
1830 <= fill))
1831 break;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001832 }
1833 if (!i)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001834 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001835
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001836 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001837
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001838 len2 = strlen(current->data + i + 1);
1839 tmpline->data = nmalloc(len2 + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001840
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001841 /* Skip the white space in current. */
1842 memcpy(tmpline->data, current->data + i + 1, len2);
1843 tmpline->data[len2] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001844
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001845 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001846
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001847 tmpline->prev = current;
1848 tmpline->next = current->next;
1849 if (current->next != NULL)
1850 current->next->prev = tmpline;
1851
1852 current->next = tmpline;
1853 current = tmpline;
1854 slen -= i + 1;
1855 current_y++;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001856 } while ((strlenpt(current->data) > (fill))
1857 && !no_spaces(current->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001858 }
Chris Allegretta9149e612000-11-27 00:23:41 +00001859 tmpbot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001860
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001861 if (current->next)
1862 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00001863 else
1864 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001865 current_x = 0;
1866 placewewant = 0;
1867
Adam Rogoyski09f97962000-06-20 02:50:33 +00001868 renumber(initial);
1869 totlines = filebot->lineno;
1870
1871 werase(edit);
1872
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001873 if ((current_y < 0) || (current_y >= editwinrows - 1)
1874 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001875 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001876 center_cursor();
1877 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001878 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001879 }
1880
Adam Rogoyski09f97962000-06-20 02:50:33 +00001881 edit_refresh();
Chris Allegretta9149e612000-11-27 00:23:41 +00001882 statusbar(_("Can now UnJustify!"));
Chris Allegretta07798352000-11-27 22:58:23 +00001883 /* Change the shortcut list to display the unjustify code */
1884 shortcut_init(1);
1885 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00001886 reset_cursor();
1887
Chris Allegretta07798352000-11-27 22:58:23 +00001888 /* Now get a keystroke and see if it's unjustify, if not unget the keytroke
Chris Allegretta9149e612000-11-27 00:23:41 +00001889 and return */
Chris Allegretta4a9c8582000-11-27 22:59:40 +00001890 if ((kbinput = wgetch(edit)) != NANO_UNJUSTIFY_KEY)
Chris Allegretta07798352000-11-27 22:58:23 +00001891 ungetch(kbinput);
Chris Allegretta9149e612000-11-27 00:23:41 +00001892 else {
1893 /* Else restore the justify we just did (ungrateful user!) */
1894 if (tmptop->prev != NULL)
1895 tmptop->prev->next = tmpbot->next;
Chris Allegrettad022eac2000-11-27 02:50:49 +00001896 else
1897 fileage = current;
Chris Allegretta9149e612000-11-27 00:23:41 +00001898 tmpbot->next->prev = tmptop->prev;
1899 current = tmpbot->next;
1900 tmpbot->next = NULL;
1901 do_uncut_text();
Chris Allegrettad022eac2000-11-27 02:50:49 +00001902 if (tmptop->prev == NULL)
1903 edit_refresh();
1904
Chris Allegretta17dcb722001-01-20 21:40:07 +00001905 /* Restore totsize from befure justify */
1906 totsize = totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00001907 free_filestruct(tmptop);
1908 blank_statusbar_refresh();
1909 }
Chris Allegretta4a9c8582000-11-27 22:59:40 +00001910 shortcut_init(0);
1911 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00001912 free_filestruct(cutbuffer);
1913 cutbuffer = cutbak;
1914
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001915 return 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001916#endif
1917}
1918
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001919#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001920void help_init(void)
1921{
1922 int i, sofar = 0;
1923 long allocsize = 1; /* How much space we're gonna need for the help text */
Chris Allegretta220ba692000-12-18 03:40:00 +00001924 char buf[BUFSIZ] = "";
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001925
1926 /* Compute the space needed for the shortcut lists - we add 15 to
1927 have room for the shortcut abbrev and its possible alternate keys */
Chris Allegretta220ba692000-12-18 03:40:00 +00001928 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001929 if (main_list[i].help != NULL)
1930 allocsize += strlen(main_list[i].help) + 15;
1931
Chris Allegretta756f2202000-09-01 13:32:47 +00001932 /* And for the toggle list, we also allocate space for extra text. */
Chris Allegretta423cbfd2000-09-04 16:21:29 +00001933 for (i = 0; i <= TOGGLE_LEN - 1; i++)
Chris Allegretta756f2202000-09-01 13:32:47 +00001934 if (toggles[i].desc != NULL)
1935 allocsize += strlen(toggles[i].desc) + 30;
1936
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001937 allocsize += strlen(help_text_init);
1938
1939 if (help_text != NULL)
1940 free(help_text);
1941
1942 /* Allocate space for the help text */
1943 help_text = nmalloc(allocsize);
1944
1945 /* Now add the text we want */
1946 strcpy(help_text, help_text_init);
1947
1948 /* Now add our shortcut info */
Chris Allegretta220ba692000-12-18 03:40:00 +00001949 for (i = 0; i <= MAIN_LIST_LEN - 1; i++) {
Robert Siemborski6af14312000-07-01 21:34:26 +00001950 sofar = snprintf(buf, BUFSIZ, "^%c ", main_list[i].val + 64);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001951
1952 if (main_list[i].misc1 > KEY_F0 && main_list[i].misc1 <= KEY_F(64))
Robert Siemborski6af14312000-07-01 21:34:26 +00001953 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001954 main_list[i].misc1 - KEY_F0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001955 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001956 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001957
1958 if (main_list[i].altval > 0)
Chris Allegrettae49f1232000-09-02 07:20:39 +00001959 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001960 main_list[i].altval - 32);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001961 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001962 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001963
Chris Allegretta756f2202000-09-01 13:32:47 +00001964
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001965 if (main_list[i].help != NULL)
Robert Siemborski976847c2000-07-06 03:43:05 +00001966 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", main_list[i].help);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001967
Chris Allegretta756f2202000-09-01 13:32:47 +00001968
1969 strcat(help_text, buf);
1970 strcat(help_text, "\n");
1971 }
1972
1973 /* And the toggles... */
Chris Allegretta423cbfd2000-09-04 16:21:29 +00001974 for (i = 0; i <= TOGGLE_LEN - 1; i++) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001975 sofar = snprintf(buf, BUFSIZ,
1976 "M-%c ", toggles[i].val - 32);
Chris Allegretta756f2202000-09-01 13:32:47 +00001977
1978 if (toggles[i].desc != NULL)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001979 snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
1980 toggles[i].desc);
Chris Allegretta756f2202000-09-01 13:32:47 +00001981
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001982 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00001983 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001984 }
1985
1986}
Chris Allegretta3bc8c722000-12-10 17:03:25 +00001987#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001988
Chris Allegretta756f2202000-09-01 13:32:47 +00001989void do_toggle(int which)
1990{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001991#ifdef NANO_SMALL
1992 nano_disabled_msg();
1993#else
Jordi Mallach2dc0f6b2000-09-07 10:48:00 +00001994 char *enabled = _("enabled");
1995 char *disabled = _("disabled");
Chris Allegrettaf0f63a82000-09-02 18:44:21 +00001996
Chris Allegretta2a42af12000-09-12 23:02:49 +00001997 if (ISSET(toggles[which].flag))
Chris Allegretta756f2202000-09-01 13:32:47 +00001998 UNSET(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00001999 else
Chris Allegretta756f2202000-09-01 13:32:47 +00002000 SET(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002001
Chris Allegretta756f2202000-09-01 13:32:47 +00002002 switch (toggles[which].val) {
2003 case TOGGLE_PICOMODE_KEY:
Chris Allegretta07798352000-11-27 22:58:23 +00002004 shortcut_init(0);
Chris Allegretta756f2202000-09-01 13:32:47 +00002005 display_main_list();
2006 break;
2007 case TOGGLE_SUSPEND_KEY:
2008 signal_init();
2009 break;
2010 case TOGGLE_MOUSE_KEY:
2011 mouse_init();
2012 break;
2013 case TOGGLE_NOHELP_KEY:
Chris Allegretta2a42af12000-09-12 23:02:49 +00002014 wclear(bottomwin);
2015 wrefresh(bottomwin);
2016 window_init();
Chris Allegrettaaffeda82000-12-18 04:03:48 +00002017 fix_editbot();
Chris Allegretta2a42af12000-09-12 23:02:49 +00002018 edit_refresh();
2019 display_main_list();
Chris Allegretta756f2202000-09-01 13:32:47 +00002020 break;
2021 }
Chris Allegretta2a42af12000-09-12 23:02:49 +00002022
2023 if (!ISSET(toggles[which].flag)) {
2024 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002025 toggles[which].val == TOGGLE_WRAP_KEY)
Chris Allegretta2a42af12000-09-12 23:02:49 +00002026 statusbar("%s %s", toggles[which].desc, enabled);
2027 else
2028 statusbar("%s %s", toggles[which].desc, disabled);
2029 } else {
2030 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002031 toggles[which].val == TOGGLE_WRAP_KEY)
Chris Allegretta2a42af12000-09-12 23:02:49 +00002032 statusbar("%s %s", toggles[which].desc, disabled);
2033 else
2034 statusbar("%s %s", toggles[which].desc, enabled);
2035 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002036 SET(DISABLE_CURPOS);
2037
2038#endif
2039}
2040
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002041/* If the NumLock key has made the keypad gone awry, print an error
2042 message, hopefully we can address it later. */
2043void print_numlock_warning(void)
2044{
2045 static int didmsg = 0;
2046 if (!didmsg) {
Chris Allegretta40973792001-01-15 20:25:24 +00002047 statusbar(_("NumLock glitch detected. Keypad will malfunction with NumLock off"));
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002048 didmsg = 1;
2049 }
2050}
2051
Chris Allegretta1748cd12001-01-13 17:22:54 +00002052/* This function returns the correct keystroke, given the A,B,C or D
2053 input key. This is a common sequence of many terms which send
2054 Esc-O-[A-D] or Esc-[-[A-D]. */
2055int ABCD(int input)
2056{
2057 switch(input)
2058 {
2059 case 'A':
2060 return(KEY_UP);
2061 case 'B':
2062 return(KEY_DOWN);
2063 case 'C':
2064 return(KEY_RIGHT);
2065 case 'D':
2066 return(KEY_LEFT);
2067 default:
2068 return 0;
2069 }
2070}
2071
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002072int main(int argc, char *argv[])
2073{
2074 int optchr;
2075 int kbinput; /* Input from keyboard */
2076 long startline = 0; /* Line to try and start at */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002077 int keyhandled = 0; /* Have we handled the keystroke yet? */
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002078 int i, modify_control_seq = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002079 char *argv0;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002080#ifdef _POSIX_VDISABLE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002081 struct termios term;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002082#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002083
2084#ifdef HAVE_GETOPT_LONG
2085 int option_index = 0;
2086 struct option long_options[] = {
Chris Allegretta805c26d2000-09-06 13:39:17 +00002087#ifdef HAVE_REGEX_H
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002088 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00002089#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002090 {"version", 0, 0, 'V'},
2091 {"const", 0, 0, 'c'},
2092 {"suspend", 0, 0, 'z'},
2093 {"nowrap", 0, 0, 'w'},
2094 {"nohelp", 0, 0, 'x'},
2095 {"help", 0, 0, 'h'},
Chris Allegretta7492cec2000-12-18 04:55:21 +00002096 {"view", 0, 0, 'v'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002097#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002098 {"cut", 0, 0, 'k'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002099#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002100 {"autoindent", 0, 0, 'i'},
2101 {"tempfile", 0, 0, 't'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002102#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002103 {"speller", 1, 0, 's'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002104#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002105 {"fill", 1, 0, 'r'},
2106 {"mouse", 0, 0, 'm'},
2107 {"pico", 0, 0, 'p'},
2108 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00002109 {"tabsize", 1, 0, 'T'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002110 {0, 0, 0, 0}
2111 };
2112#endif
2113
2114 /* Flag inits... */
2115 SET(FOLLOW_SYMLINKS);
2116
2117#ifndef NANO_SMALL
2118 setlocale(LC_ALL, "");
2119 bindtextdomain(PACKAGE, LOCALEDIR);
2120 textdomain(PACKAGE);
2121#endif
2122
2123#ifdef HAVE_GETOPT_LONG
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002124 while ((optchr = getopt_long(argc, argv, "?T:RVbcefhiklmpr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002125 long_options, &option_index)) != EOF) {
2126#else
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002127 while ((optchr = getopt(argc, argv, "h?T:RVbcefiklmpr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002128#endif
2129
2130 switch (optchr) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002131 case 'T':
Chris Allegretta99bf73f2000-08-04 00:22:08 +00002132 tabsize = atoi(optarg);
2133 if (tabsize <= 0) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002134 usage(); /* To stop bogus data for tab width */
2135 finish(1);
2136 }
2137 break;
Chris Allegretta805c26d2000-09-06 13:39:17 +00002138#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +00002139 case 'R':
2140 SET(USE_REGEXP);
2141 break;
Chris Allegretta47805612000-07-07 02:35:34 +00002142#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002143 case 'V':
2144 version();
2145 exit(0);
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002146 case 'b':
2147 case 'e':
2148 case 'f':
2149 /* Pico compatibility flags */
2150 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002151 case 'c':
2152 SET(CONSTUPDATE);
2153 break;
2154 case 'h':
2155 case '?':
2156 usage();
2157 exit(0);
2158 case 'i':
2159 SET(AUTOINDENT);
2160 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002161#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002162 case 'k':
2163 SET(CUT_TO_END);
2164 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002165#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002166 case 'l':
2167 UNSET(FOLLOW_SYMLINKS);
2168 break;
2169 case 'm':
2170 SET(USE_MOUSE);
2171 break;
2172 case 'p':
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002173 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002174 break;
2175 case 'r':
2176 fill = atoi(optarg);
2177 if (fill <= 0) {
2178 usage(); /* To stop bogus data (like a string) */
2179 finish(1);
2180 }
2181 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002182#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002183 case 's':
2184 alt_speller = nmalloc(strlen(optarg) + 1);
2185 strcpy(alt_speller, optarg);
2186 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002187#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002188 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00002189 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002190 break;
2191 case 'v':
2192 SET(VIEW_MODE);
2193 break;
2194 case 'w':
2195 SET(NO_WRAP);
2196 break;
2197 case 'x':
2198 SET(NO_HELP);
2199 break;
2200 case 'z':
2201 SET(SUSPEND);
2202 break;
2203 default:
2204 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002205 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002206 }
2207
2208 }
2209
2210 argv0 = strrchr(argv[0], '/');
2211 if ((argv0 && strstr(argv0, "pico"))
2212 || (!argv0 && strstr(argv[0], "pico")))
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002213 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002214
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002215 /* See if there's a non-option in argv (first non-option is the
2216 filename, if +LINE is not given) */
2217 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002218 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002219 else {
2220 /* Look for the +line flag... */
2221 if (argv[optind][0] == '+') {
2222 startline = atoi(&argv[optind][1]);
2223 optind++;
2224 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002225 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002226 else
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002227 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002228
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002229 } else
2230 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002231 }
2232
2233
2234 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002235 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002236
Chris Allegretta9239d742000-09-06 15:19:18 +00002237#ifdef _POSIX_VDISABLE
Chris Allegretta8f6c0692000-07-19 01:16:18 +00002238 term = oldterm;
2239 term.c_cc[VINTR] = _POSIX_VDISABLE;
2240 term.c_cc[VQUIT] = _POSIX_VDISABLE;
2241 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002242 tcsetattr(0, TCSANOW, &term);
Chris Allegretta9239d742000-09-06 15:19:18 +00002243#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002244
2245 /* now ncurses init stuff... */
2246 initscr();
2247 savetty();
2248 nonl();
2249 cbreak();
2250 noecho();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002251
2252 /* Set up some global variables */
2253 global_init();
Chris Allegretta07798352000-11-27 22:58:23 +00002254 shortcut_init(0);
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002255#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002256 init_help_msg();
2257 help_init();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002258#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002259 signal_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002260
2261#ifdef DEBUG
2262 fprintf(stderr, _("Main: set up windows\n"));
2263#endif
2264
Chris Allegretta2a42af12000-09-12 23:02:49 +00002265 window_init();
Chris Allegretta756f2202000-09-01 13:32:47 +00002266 mouse_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002267
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002268#ifdef DEBUG
2269 fprintf(stderr, _("Main: bottom win\n"));
2270#endif
2271 /* Set up up bottom of window */
2272 display_main_list();
2273
2274#ifdef DEBUG
2275 fprintf(stderr, _("Main: open file\n"));
2276#endif
2277
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002278 titlebar(NULL);
Chris Allegretta31c76662000-11-21 06:20:20 +00002279
2280 /* Now we check to see if argv[optind] is non-null to determine if
2281 we're dealing with a new file or not, not argc == 1... */
2282 if (argv[optind] == NULL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002283 new_file();
2284 else
2285 open_file(filename, 0, 0);
2286
2287 if (startline > 0)
2288 do_gotoline(startline);
2289 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00002290 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002291
Robert Siemborski6967eec2000-07-08 14:23:32 +00002292 edit_refresh();
2293 reset_cursor();
2294
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002295 while (1) {
Chris Allegretta9239d742000-09-06 15:19:18 +00002296
2297#ifndef _POSIX_VDISABLE
2298 /* We're going to have to do it the old way, i.e. on cygwin */
2299 raw();
2300#endif
2301
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002302 kbinput = wgetch(edit);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002303#ifdef DEBUG
2304 fprintf(stderr, "AHA! %c (%d)\n", kbinput, kbinput);
2305#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002306 if (kbinput == 27) { /* Grab Alt-key stuff first */
2307 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002308 /* Alt-O, suddenly very important ;) */
Chris Allegretta16e41682000-09-11 22:33:54 +00002309 case 79:
2310 kbinput = wgetch(edit);
Chris Allegretta1748cd12001-01-13 17:22:54 +00002311 if (kbinput <= 'D' && kbinput >= 'A')
2312 kbinput = ABCD(kbinput);
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002313 else if (kbinput <= 'z' && kbinput >= 'j')
2314 print_numlock_warning();
2315 else if (kbinput <= 'S' && kbinput >= 'P')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002316 kbinput = KEY_F(kbinput - 79);
Chris Allegretta16e41682000-09-11 22:33:54 +00002317#ifdef DEBUG
2318 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002319 fprintf(stderr, _("I got Alt-O-%c! (%d)\n"),
2320 kbinput, kbinput);
2321 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002322 }
2323#endif
2324 break;
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002325 case 27:
2326 /* If we get Alt-Alt, the next keystroke should be the same as a
2327 control sequence */
2328 modify_control_seq = 1;
2329 keyhandled = 1;
2330 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002331 case 91:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002332 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002333 case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */
Chris Allegretta16e41682000-09-11 22:33:54 +00002334 kbinput = wgetch(edit);
2335 if (kbinput >= '1' && kbinput <= '5') {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002336 kbinput = KEY_F(kbinput - 48);
2337 wgetch(edit);
2338 } else if (kbinput >= '7' && kbinput <= '9') {
2339 kbinput = KEY_F(kbinput - 49);
2340 wgetch(edit);
2341 } else if (kbinput == 126)
2342 kbinput = KEY_HOME;
Chris Allegretta16e41682000-09-11 22:33:54 +00002343
2344#ifdef DEBUG
2345 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002346 fprintf(stderr, _("I got Alt-[-1-%c! (%d)\n"),
2347 kbinput, kbinput);
2348 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002349 }
2350#endif
2351
2352 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002353 case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */
Chris Allegretta16e41682000-09-11 22:33:54 +00002354 kbinput = wgetch(edit);
Chris Allegretta16e41682000-09-11 22:33:54 +00002355 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002356 case '0':
2357 kbinput = KEY_F(9);
2358 wgetch(edit);
2359 break;
2360 case '1':
2361 kbinput = KEY_F(10);
2362 wgetch(edit);
2363 break;
2364 case '3':
2365 kbinput = KEY_F(11);
2366 wgetch(edit);
2367 break;
2368 case '4':
2369 kbinput = KEY_F(12);
2370 wgetch(edit);
2371 break;
2372 case 126: /* Hack, make insert key do something
2373 usefile, like insert file */
2374 do_insertfile();
2375 keyhandled = 1;
2376 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002377#ifdef DEBUG
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002378 default:
2379 fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"),
2380 kbinput, kbinput);
2381 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002382#endif
2383
2384 }
2385 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002386 case '3': /* Alt-[-3 = Delete? */
Chris Allegretta16e41682000-09-11 22:33:54 +00002387 kbinput = NANO_DELETE_KEY;
2388 wgetch(edit);
2389 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002390 case '4': /* Alt-[-4 = End? */
Chris Allegretta16e41682000-09-11 22:33:54 +00002391 kbinput = NANO_END_KEY;
2392 wgetch(edit);
2393 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002394 case '5': /* Alt-[-5 = Page Up */
Chris Allegretta16e41682000-09-11 22:33:54 +00002395 kbinput = KEY_PPAGE;
2396 wgetch(edit);
2397 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002398 case '6': /* Alt-[-6 = Page Down */
Chris Allegretta16e41682000-09-11 22:33:54 +00002399 kbinput = KEY_NPAGE;
2400 wgetch(edit);
2401 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002402 case '[': /* Alt-[-[-[A-E], F1-F5 in linux console */
Chris Allegretta16e41682000-09-11 22:33:54 +00002403 kbinput = wgetch(edit);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002404 if (kbinput >= 'A' && kbinput <= 'E')
2405 kbinput = KEY_F(kbinput - 64);
Chris Allegretta16e41682000-09-11 22:33:54 +00002406 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002407 case 'A':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002408 case 'B':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002409 case 'C':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002410 case 'D':
Chris Allegretta1748cd12001-01-13 17:22:54 +00002411 kbinput = ABCD(kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002412 break;
2413 case 'H':
2414 kbinput = KEY_HOME;
2415 break;
2416 case 'F':
2417 kbinput = KEY_END;
2418 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002419 default:
2420#ifdef DEBUG
2421 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
2422 kbinput, kbinput);
2423#endif
2424 break;
2425 }
2426 break;
2427 default:
2428
2429 /* Check for the altkey defs.... */
2430 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
2431 if (kbinput == main_list[i].altval ||
2432 kbinput == main_list[i].altval - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002433 kbinput = main_list[i].val;
2434 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002435 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002436#ifndef NANO_SMALL
2437 /* And for toggle switches */
2438 for (i = 0; i <= TOGGLE_LEN - 1 && !keyhandled; i++)
2439 if (kbinput == toggles[i].val ||
2440 kbinput == toggles[i].val - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002441 do_toggle(i);
2442 keyhandled = 1;
2443 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002444 }
2445#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002446#ifdef DEBUG
2447 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
2448 kbinput);
2449#endif
2450 break;
2451 }
2452 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002453 /* If the modify_control_seq is set, we received an Alt-Alt
2454 sequence before this, so we make this key a control sequence
2455 by subtracting 64 or 96, depending on its value. */
2456 if (!keyhandled && modify_control_seq) {
2457 if (kbinput >= 'A' && kbinput < 'a')
2458 kbinput -= 64;
2459 else if (kbinput >= 'a' && kbinput <= 'z')
2460 kbinput -= 96;
2461
2462 modify_control_seq = 0;
2463 }
2464
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002465 /* Look through the main shortcut list to see if we've hit a
2466 shortcut key */
Chris Allegretta756f2202000-09-01 13:32:47 +00002467 for (i = 0; i < MAIN_LIST_LEN && !keyhandled; i++) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002468 if (kbinput == main_list[i].val ||
2469 (main_list[i].misc1 && kbinput == main_list[i].misc1) ||
2470 (main_list[i].misc2 && kbinput == main_list[i].misc2)) {
2471 if (ISSET(VIEW_MODE) && !main_list[i].viewok)
2472 print_view_warning();
2473 else
2474 main_list[i].func();
2475 keyhandled = 1;
2476 }
2477 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002478 /* If we're in raw mode or using Alt-Alt-x, we have to catch
2479 Control-S and Control-Q */
Chris Allegretta9239d742000-09-06 15:19:18 +00002480 if (kbinput == 17 || kbinput == 19)
2481 keyhandled = 1;
2482
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002483 /* Catch ^Z by hand when triggered also */
Chris Allegretta9239d742000-09-06 15:19:18 +00002484 if (kbinput == 26) {
2485 if (ISSET(SUSPEND))
2486 do_suspend(0);
2487 keyhandled = 1;
2488 }
Chris Allegretta9239d742000-09-06 15:19:18 +00002489
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002490 /* Last gasp, stuff that's not in the main lists */
2491 if (!keyhandled)
2492 switch (kbinput) {
2493#ifndef NANO_SMALL
2494#ifdef NCURSES_MOUSE_VERSION
2495 case KEY_MOUSE:
2496 do_mouse();
2497 break;
2498#endif
2499#endif
2500 case 0: /* Erg */
2501 do_next_word();
2502 break;
Chris Allegrettaf4f7e042001-01-04 16:56:15 +00002503
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002504 case 331: /* Stuff that we don't want to do squat */
2505 case -1:
2506 case 410: /* Must ignore this, it gets sent when we resize */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002507#ifdef PDCURSES
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002508 case 541: /* ???? */
2509 case 542: /* Control and alt in Windows *shrug* */
Chris Allegretta72623582000-11-29 23:43:28 +00002510 case 543: /* Right ctrl key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002511 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +00002512 case 545: /* Right alt key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002513#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002514
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002515 break;
2516 default:
2517#ifdef DEBUG
2518 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
2519#endif
2520 /* We no longer stop unhandled sequences so that people with
2521 odd character sets can type... */
2522
2523 if (ISSET(VIEW_MODE)) {
2524 print_view_warning();
2525 break;
2526 }
2527 do_char(kbinput);
2528 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002529 if (ISSET(CONSTUPDATE)) {
2530 if (ISSET(DISABLE_CURPOS))
2531 UNSET(DISABLE_CURPOS);
2532 else
2533 do_cursorpos();
2534 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002535
2536 reset_cursor();
2537 wrefresh(edit);
2538 keyhandled = 0;
2539 }
2540
2541 getchar();
2542 finish(0);
2543
2544}