blob: 379b82a4421aaf04aa70b0d5ac3fcb17ea5f6a90 [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 *
Chris Allegretta3a24f3f2001-10-24 11:33:54 +00008 * the Free Software Foundation; either version 2, or (at your option) *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00009 * any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 * *
20 **************************************************************************/
21
Chris Allegretta6efda542001-04-28 18:03:52 +000022#include "config.h"
23
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000024#include <stdio.h>
25#include <stdlib.h>
26#include <stdarg.h>
27#include <signal.h>
Chris Allegretta08020882001-01-29 23:37:54 +000028#include <setjmp.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000029#include <unistd.h>
30#include <string.h>
31#include <fcntl.h>
32#include <sys/stat.h>
33#include <sys/ioctl.h>
34#include <sys/param.h>
Chris Allegretta27eb13f2000-11-05 16:52:21 +000035#include <sys/types.h>
36#include <sys/wait.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000037#include <errno.h>
38#include <ctype.h>
39#include <locale.h>
40#include <limits.h>
Adam Rogoyski77f36de2000-06-07 03:56:54 +000041#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000042
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000043#include "proto.h"
44#include "nano.h"
45
46#ifndef NANO_SMALL
47#include <libintl.h>
48#define _(string) gettext(string)
49#else
50#define _(string) (string)
51#endif
52
53#ifdef HAVE_TERMIOS_H
54#include <termios.h>
55#endif
56
57#ifdef HAVE_TERMIO_H
58#include <termio.h>
59#endif
60
61#ifdef HAVE_GETOPT_H
62#include <getopt.h>
63#endif
64
Chris Allegretta6fe61492001-05-21 12:56:25 +000065#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000066/* Former globals, now static */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000067int fill = 0; /* Fill - where to wrap lines, basically */
Chris Allegretta6fe61492001-05-21 12:56:25 +000068int wrap_at = 0; /* Right justified fill value, allows resize */
69#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +000070
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000071struct termios oldterm; /* The user's original term settings */
Chris Allegretta88520c92001-05-05 17:45:54 +000072static struct sigaction act; /* For all our fun signal handlers */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000073
Rocco Corsiaf5c3022001-01-12 07:51:05 +000074#ifndef DISABLE_HELP
Chris Allegretta6b58acd2001-04-12 03:01:53 +000075static char *help_text_init = ""; /* Initial message, not including shortcuts */
Chris Allegretta65121632000-12-18 07:05:27 +000076#endif
77
Chris Allegretta27eb13f2000-11-05 16:52:21 +000078char *last_search = NULL; /* Last string we searched for */
79char *last_replace = NULL; /* Last replacement string */
80int search_last_line; /* Is this the last search line? */
81
Chris Allegretta08020882001-01-29 23:37:54 +000082static sigjmp_buf jmpbuf; /* Used to return to mainloop after SIGWINCH */
83
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000084/* What we do when we're all set to exit */
85RETSIGTYPE finish(int sigage)
86{
Chris Allegrettac08f50d2001-01-06 18:12:43 +000087
88 keypad(edit, TRUE);
89 keypad(bottomwin, TRUE);
90
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000091 if (!ISSET(NO_HELP)) {
92 mvwaddstr(bottomwin, 1, 0, hblank);
93 mvwaddstr(bottomwin, 2, 0, hblank);
Chris Allegretta4da1fc62000-06-21 03:00:43 +000094 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000095 mvwaddstr(bottomwin, 0, 0, hblank);
Chris Allegretta6b58acd2001-04-12 03:01:53 +000096
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000097 wrefresh(bottomwin);
98 endwin();
99
100 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000101 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000102
103 exit(sigage);
104}
105
106/* Die (gracefully?) */
107void die(char *msg, ...)
108{
109 va_list ap;
110
111 va_start(ap, msg);
112 vfprintf(stderr, msg, ap);
113 va_end(ap);
114
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000115 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000116 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000117
118 clear();
119 refresh();
120 resetty();
121 endwin();
122
123 fprintf(stderr, msg);
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000124
125 /* save the currently loaded file (if modified, its open_files entry
126 isn't up to date) */
127 die_save_file(filename);
128
Chris Allegretta355fbe52001-07-14 19:32:47 +0000129#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000130 /* then save all of the other loaded files, if any */
131 if (open_files) {
132 filestruct *tmp;
133
134 tmp = open_files;
135
136 while (open_files->prev)
137 open_files = open_files->prev;
138
139 while (open_files->next) {
140
141 /* if we already saved the file above (i. e. if it was the
142 currently loaded file), don't save it again */
143 if (tmp != open_files) {
144 fileage = open_files->file;
145 die_save_file(open_files->data);
146 }
147
148 open_files = open_files->next;
149 }
150
151 }
152#endif
153
154 exit(1); /* We have a problem: exit w/ errorlevel(1) */
155}
156
157void die_save_file(char *die_filename)
158{
159 char *name;
160 int i;
161
162 /* if we can't save we have REAL bad problems,
163 * but we might as well TRY. */
164 if (die_filename[0] == '\0') {
165 name = "nano.save";
166 i = write_file(name, 1, 0, 0);
167 } else {
168
169 char *buf = charalloc(strlen(die_filename) + 6);
170 strcpy(buf, die_filename);
171 strcat(buf, ".save");
172 i = write_file(buf, 1, 0, 0);
173 name = buf;
174 }
175
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000176 if (i != -1)
177 fprintf(stderr, _("\nBuffer written to %s\n"), name);
178 else
Chris Allegretta9756d622000-12-03 03:06:45 +0000179 fprintf(stderr, _("\nNo %s written (file exists?)\n"), name);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000180}
181
Chris Allegrettae61e8302001-01-14 05:18:27 +0000182/* Die with an error message that the screen was too small if, well, the
183 screen is too small */
184void die_too_small(void)
185{
186 char *too_small_msg = _("Window size is too small for Nano...");
187
188 die(too_small_msg);
189
190}
191
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000192void print_view_warning(void)
193{
194 statusbar(_("Key illegal in VIEW mode"));
195}
196
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000197void clear_filename(void)
198{
199 if (filename != NULL)
200 free(filename);
Chris Allegretta88b09152001-05-17 11:35:43 +0000201 filename = charalloc(1);
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000202 filename[0] = 0;
203}
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +0000204
Chris Allegretta56214c62001-09-27 02:46:53 +0000205/* Initialize global variables - no better way for now. If
206 save_cutbuffer is nonzero, don't set cutbuffer to NULL. */
207void global_init(int save_cutbuffer)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000208{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000209 current_x = 0;
210 current_y = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000211
212 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
213 die_too_small();
214
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000215 fileage = NULL;
Chris Allegretta56214c62001-09-27 02:46:53 +0000216 if (!save_cutbuffer)
217 cutbuffer = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000218 current = NULL;
219 edittop = NULL;
220 editbot = NULL;
221 totlines = 0;
Chris Allegretta56214c62001-09-27 02:46:53 +0000222 totsize = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000223 placewewant = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000224
Chris Allegretta6fe61492001-05-21 12:56:25 +0000225#ifndef DISABLE_WRAPJUSTIFY
226 if (wrap_at)
227 fill = COLS + wrap_at;
228 else if (!fill)
Chris Allegrettae61e8302001-01-14 05:18:27 +0000229 fill = COLS - CHARS_FROM_EOL;
230
231 if (fill < MIN_FILL_LENGTH)
232 die_too_small();
Chris Allegretta6fe61492001-05-21 12:56:25 +0000233#endif
Chris Allegrettae61e8302001-01-14 05:18:27 +0000234
Chris Allegretta88b09152001-05-17 11:35:43 +0000235 hblank = charalloc(COLS + 1);
Chris Allegretta0a06e072001-01-23 02:35:04 +0000236 memset(hblank, ' ', COLS);
237 hblank[COLS] = 0;
Chris Allegretta76e291b2001-10-14 19:05:10 +0000238
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000239}
240
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000241#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000242void init_help_msg(void)
243{
244
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000245 help_text_init =
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000246 _(" nano help text\n\n "
247 "The nano editor is designed to emulate the functionality and "
248 "ease-of-use of the UW Pico text editor. There are four main "
249 "sections of the editor: The top line shows the program "
250 "version, the current filename being edited, and whether "
251 "or not the file has been modified. Next is the main editor "
252 "window showing the file being edited. The status line is "
253 "the third line from the bottom and shows important messages. "
254 "The bottom two lines show the most commonly used shortcuts "
255 "in the editor.\n\n "
256 "The notation for shortcuts is as follows: Control-key "
Chris Allegrettae49f1232000-09-02 07:20:39 +0000257 "sequences are notated with a caret (^) symbol and are entered "
Chris Allegrettad56bd792000-09-02 07:27:10 +0000258 "with the Control (Ctrl) key. Escape-key sequences are notated "
259 "with the Meta (M) symbol and can be entered using either the "
260 "Esc, Alt or Meta key depending on your keyboard setup. The "
261 "following keystrokes are available in the main editor window. "
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000262 "Optional keys are shown in parentheses:\n\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000263}
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000264#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000265
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000266/* Make a copy of a node to a pointer (space will be malloc()ed). This
267 does NOT copy the data members used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000268filestruct *copy_node(filestruct * src)
269{
270 filestruct *dst;
271
272 dst = nmalloc(sizeof(filestruct));
Chris Allegretta88b09152001-05-17 11:35:43 +0000273 dst->data = charalloc(strlen(src->data) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000274
275 dst->next = src->next;
276 dst->prev = src->prev;
277
278 strcpy(dst->data, src->data);
279 dst->lineno = src->lineno;
280
281 return dst;
282}
283
284/* Unlink a node from the rest of the struct */
285void unlink_node(filestruct * fileptr)
286{
287 if (fileptr->prev != NULL)
288 fileptr->prev->next = fileptr->next;
289
290 if (fileptr->next != NULL)
291 fileptr->next->prev = fileptr->prev;
292}
293
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000294/* Delete a node from the struct. This does NOT delete the data members
295 used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000296void delete_node(filestruct * fileptr)
297{
Chris Allegretta17dcb722001-01-20 21:40:07 +0000298 if (fileptr == NULL)
299 return;
300
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000301 if (fileptr->data != NULL)
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000302 free(fileptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000303 free(fileptr);
304}
305
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000306/* Okay, now let's duplicate a whole struct! This does NOT duplicate the
307 data members used only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000308filestruct *copy_filestruct(filestruct * src)
309{
310 filestruct *dst, *tmp, *head, *prev;
311
312 head = copy_node(src);
313 dst = head; /* Else we barf on copying just one line */
314 head->prev = NULL;
315 tmp = src->next;
316 prev = head;
317
318 while (tmp != NULL) {
319 dst = copy_node(tmp);
320 dst->prev = prev;
321 prev->next = dst;
322
323 prev = dst;
324 tmp = tmp->next;
325 }
326
327 dst->next = NULL;
328 return head;
329}
330
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000331/* Frees a struct. This does NOT free the data members used only by
332 open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000333int free_filestruct(filestruct * src)
334{
335 filestruct *fileptr = src;
336
337 if (src == NULL)
338 return 0;
339
340 while (fileptr->next != NULL) {
341 fileptr = fileptr->next;
Chris Allegretta17dcb722001-01-20 21:40:07 +0000342 delete_node(fileptr->prev);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000343
344#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000345 fprintf(stderr, _("delete_node(): free'd a node, YAY!\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000346#endif
347 }
Chris Allegretta17dcb722001-01-20 21:40:07 +0000348 delete_node(fileptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000349#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000350 fprintf(stderr, _("delete_node(): free'd last node.\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000351#endif
352
353 return 1;
354}
355
356int renumber_all(void)
357{
358 filestruct *temp;
359 long i = 1;
360
361 for (temp = fileage; temp != NULL; temp = temp->next) {
362 temp->lineno = i++;
363 }
364
365 return 0;
366}
367
368int renumber(filestruct * fileptr)
369{
370 filestruct *temp;
371
372 if (fileptr == NULL || fileptr->prev == NULL || fileptr == fileage) {
373 renumber_all();
374 return 0;
375 }
376 for (temp = fileptr; temp != NULL; temp = temp->next) {
Chris Allegretta5146fec2000-12-10 05:44:02 +0000377 if (temp->prev != NULL)
378 temp->lineno = temp->prev->lineno + 1;
379 else
380 temp->lineno = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000381 }
382
383 return 0;
384}
385
386/* Fix the memory allocation for a string */
387void align(char **strp)
388{
389 /* There was a serious bug here: the new address was never
390 stored anywhere... */
391
392 *strp = nrealloc(*strp, strlen(*strp) + 1);
393}
394
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000395/* Null a string at a certain index and align it */
Chris Allegrettafa0c6962001-10-22 23:22:19 +0000396void null_at(char **data, int index)
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000397{
Chris Allegrettafa0c6962001-10-22 23:22:19 +0000398
399 /* Ahh! Damn dereferencing */
400 (*data)[index] = 0;
401 align(data);
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000402}
403
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000404void usage(void)
405{
406#ifdef HAVE_GETOPT_LONG
407 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
408 printf(_("Option Long option Meaning\n"));
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000409
Chris Allegretta7004c282001-09-22 00:42:10 +0000410#ifndef NANO_SMALL
411 printf
412 (_
413 (" -D --dos Write file in DOS format\n"));
414#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000415#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000416 printf
417 (_
Chris Allegretta355fbe52001-07-14 19:32:47 +0000418 (" -F --multibuffer Enable multiple file buffers\n"));
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000419#endif
Chris Allegretta8fa1e282001-09-22 04:20:25 +0000420#ifndef NANO_SMALL
421 printf
422 (_
423 (" -M --mac Write file in Mac format\n"));
424#endif
Chris Allegretta805c26d2000-09-06 13:39:17 +0000425#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000426 printf(_
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000427 (" -R --regexp Use regular expressions for search\n"));
Chris Allegretta47805612000-07-07 02:35:34 +0000428#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +0000429#ifndef NANO_SMALL
430 printf(_
431 (" -S --smooth Smooth scrolling\n"));
432#endif
Chris Allegretta7004c282001-09-22 00:42:10 +0000433 printf(_
434 (" -T [num] --tabsize=[num] Set width of a tab to num\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000435 printf
436 (_
437 (" -V --version Print version information and exit\n"));
438 printf(_
439 (" -c --const Constantly show cursor position\n"));
440 printf(_
441 (" -h --help Show this message\n"));
Chris Allegrettaff989832001-09-17 13:48:00 +0000442#ifndef NANO_SMALL
Chris Allegrettad55655f2000-12-27 03:36:47 +0000443 printf(_
444 (" -i --autoindent Automatically indent new lines\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000445 printf(_
Chris Allegretta627de192000-07-12 02:09:17 +0000446 (" -k --cut Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000447#endif
Chris Allegretta627de192000-07-12 02:09:17 +0000448 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000449 (" -l --nofollow Don't follow symbolic links, overwrite\n"));
Chris Allegretta84de5522001-04-12 14:51:48 +0000450#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000451#ifdef NCURSES_MOUSE_VERSION
452 printf(_(" -m --mouse Enable mouse\n"));
453#endif
454#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000455#ifndef DISABLE_OPERATINGDIR
Chris Allegrettad55655f2000-12-27 03:36:47 +0000456 printf(_
Chris Allegretta56214c62001-09-27 02:46:53 +0000457 (" -o [dir] --operatingdir=[dir] Set operating directory\n"));
Chris Allegrettae1f14522001-09-19 03:19:43 +0000458#endif
459 printf(_
460 (" -p --pico Emulate Pico as closely as possible\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000461
462#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000463 printf
464 (_
465 (" -r [#cols] --fill=[#cols] Set fill cols to (wrap lines at) #cols\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000466#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000467#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000468 printf(_
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000469 (" -s [prog] --speller=[prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000470#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000471 printf(_
472 (" -t --tempfile Auto save on exit, don't prompt\n"));
473 printf(_
474 (" -v --view View (read only) mode\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000475#ifndef DISABLE_WRAPPING
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000476 printf(_
477 (" -w --nowrap Don't wrap long lines\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000478#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000479 printf(_
480 (" -x --nohelp Don't show help window\n"));
481 printf(_
482 (" -z --suspend Enable suspend\n"));
483 printf(_
484 (" +LINE Start at line number LINE\n"));
485#else
486 printf(_("Usage: nano [option] +LINE <file>\n\n"));
487 printf(_("Option Meaning\n"));
Chris Allegretta7004c282001-09-22 00:42:10 +0000488#ifndef NANO_SMALL
489 printf(_(" -D Write file in DOS format\n"));
490#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000491#ifdef ENABLE_MULTIBUFFER
492 printf(_(" -F Enable multiple file buffers\n"));
493#endif
Chris Allegretta8fa1e282001-09-22 04:20:25 +0000494#ifndef NANO_SMALL
495 printf(_(" -M Write file in Mac format\n"));
496#endif
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000497 printf(_(" -T [num] Set width of a tab to num\n"));
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000498 printf(_(" -R Use regular expressions for search\n"));
Chris Allegretta3e3ae942001-09-22 19:02:04 +0000499#ifndef NANO_SMALL
500 printf(_(" -S Smooth scrolling\n"));
501#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000502 printf(_(" -V Print version information and exit\n"));
503 printf(_(" -c Constantly show cursor position\n"));
504 printf(_(" -h Show this message\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000505#ifndef NANO_SMALL
Chris Allegrettaff989832001-09-17 13:48:00 +0000506 printf(_(" -i Automatically indent new lines\n"));
Chris Allegretta627de192000-07-12 02:09:17 +0000507 printf(_(" -k Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000508#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000509 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000510 (" -l Don't follow symbolic links, overwrite\n"));
Chris Allegretta84de5522001-04-12 14:51:48 +0000511#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000512#ifdef NCURSES_MOUSE_VERSION
513 printf(_(" -m Enable mouse\n"));
514#endif
515#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000516#ifndef DISABLE_OPERATINGDIR
517 printf(_(" -o [dir] Set operating directory\n"));
518#endif
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +0000519 printf(_(" -p Emulate Pico as closely as possible\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000520
521#ifndef DISABLE_WRAPJUSTIFY
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000522 printf(_
523 (" -r [#cols] Set fill cols to (wrap lines at) #cols\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000524#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000525#ifndef DISABLE_SPELLER
Chris Allegrettad55655f2000-12-27 03:36:47 +0000526 printf(_(" -s [prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000527#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000528 printf(_(" -t Auto save on exit, don't prompt\n"));
529 printf(_(" -v View (read only) mode\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000530#ifndef DISABLE_WRAPPING
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000531 printf(_(" -w Don't wrap long lines\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000532#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000533 printf(_(" -x Don't show help window\n"));
534 printf(_(" -z Enable suspend\n"));
535 printf(_(" +LINE Start at line number LINE\n"));
536#endif
537 exit(0);
538}
539
540void version(void)
541{
Chris Allegrettac46dd812001-02-14 14:28:27 +0000542 printf(_(" GNU nano version %s (compiled %s, %s)\n"),
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000543 VERSION, __TIME__, __DATE__);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000544 printf(_
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000545 (" Email: nano@nano-editor.org Web: http://www.nano-editor.org"));
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000546 printf(_("\n Compiled options:"));
Chris Allegrettaff269f82000-12-01 18:46:01 +0000547
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000548#ifdef NANO_EXTRA
549 printf(" --enable-extra");
Chris Allegretta355fbe52001-07-14 19:32:47 +0000550#else
551#ifdef ENABLE_MULTIBUFFER
552 printf(" --enable-multibuffer");
553#endif /* ENABLE_MULTIBUFFER */
554#endif /* NANO_EXTRA */
555
Chris Allegrettab881d3e2001-04-18 04:34:43 +0000556#ifdef ENABLE_NANORC
557 printf(" --enable-nanorc");
558#endif
Chris Allegretta8ce24132001-04-30 11:28:46 +0000559#ifdef ENABLE_COLOR
560 printf(" --enable-color");
561#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000562
563#ifdef NANO_SMALL
564 printf(" --enable-tiny");
565#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000566#ifdef DISABLE_BROWSER
Chris Allegretta6636dc32001-01-05 05:41:07 +0000567 printf(" --disable-browser");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000568#endif
569#ifdef DISABLE_TABCOMP
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000570 printf(" --disable-tabcomp");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000571#endif
572#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +0000573 printf(" --disable-justify");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000574#endif
575#ifdef DISABLE_SPELLER
Chris Allegretta7b36c522000-12-06 01:08:10 +0000576 printf(" --disable-speller");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000577#endif
578#ifdef DISABLE_HELP
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000579 printf(" --disable-help");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000580#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000581#ifdef DISABLE_MOUSE
582 printf(" --disable-mouse");
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000583#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000584#ifdef DISABLE_OPERATINGDIR
585 printf(" --disable-operatingdir");
586#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000587#endif /* NANO_SMALL */
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000588
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000589#ifdef DISABLE_WRAPPING
590 printf(" --disable-wrapping");
591#endif
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000592#ifdef USE_SLANG
593 printf(" --with-slang");
594#endif
595 printf("\n");
596
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000597}
598
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000599/* Create a new node. This does NOT initialize the data members used
600 only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000601filestruct *make_new_node(filestruct * prevnode)
602{
603 filestruct *newnode;
604
605 newnode = nmalloc(sizeof(filestruct));
606 newnode->data = NULL;
607
608 newnode->prev = prevnode;
609 newnode->next = NULL;
610
611 if (prevnode != NULL)
612 newnode->lineno = prevnode->lineno + 1;
613
614 return newnode;
615}
616
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000617/* Splice a node into an existing filestruct. This does NOT set the data
618 members used only by open_files. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000619void splice_node(filestruct * begin, filestruct * newnode,
620 filestruct * end)
Chris Allegretta7975ed82000-07-28 00:58:35 +0000621{
Chris Allegrettae3167732001-03-18 16:59:34 +0000622 newnode->next = end;
623 newnode->prev = begin;
624 begin->next = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000625 if (end != NULL)
Chris Allegrettae3167732001-03-18 16:59:34 +0000626 end->prev = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000627}
628
Chris Allegrettae3167732001-03-18 16:59:34 +0000629int do_mark(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000630{
631#ifdef NANO_SMALL
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000632 nano_disabled_msg();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000633#else
634 if (!ISSET(MARK_ISSET)) {
635 statusbar(_("Mark Set"));
636 SET(MARK_ISSET);
637 mark_beginbuf = current;
638 mark_beginx = current_x;
639 } else {
640 statusbar(_("Mark UNset"));
641 UNSET(MARK_ISSET);
642 mark_beginbuf = NULL;
643 mark_beginx = 0;
644
645 edit_refresh();
646 }
647#endif
648 return 1;
649}
650
651int no_help(void)
652{
653 if ISSET
654 (NO_HELP)
655 return 2;
656 else
657 return 0;
658}
659
Chris Allegretta3bc8c722000-12-10 17:03:25 +0000660#if defined(DISABLE_JUSTIFY) || defined(DISABLE_SPELLER) || defined(DISABLE_HELP)
Chris Allegrettaff269f82000-12-01 18:46:01 +0000661void nano_disabled_msg(void)
662{
663 statusbar("Sorry, support for this function has been disabled");
664}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000665#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000666
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000667/* The user typed a printable character; add it to the edit buffer */
668void do_char(char ch)
669{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000670 /* magic-line: when a character is inserted on the current magic line,
671 * it means we need a new one! */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000672 if (filebot == current && current->data[0] == '\0') {
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000673 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000674 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000675 }
676
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000677 /* More dangerousness fun =) */
678 current->data = nrealloc(current->data, strlen(current->data) + 2);
679 memmove(&current->data[current_x + 1],
680 &current->data[current_x],
681 strlen(current->data) - current_x + 1);
682 current->data[current_x] = ch;
683 do_right();
684
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000685#ifndef DISABLE_WRAPPING
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000686 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000687 check_wrap(current, ch);
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000688#endif
689
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000690 set_modified();
691 check_statblank();
692 UNSET(KEEP_CUTBUFFER);
693 totsize++;
694
695}
696
697/* Someone hits return *gasp!* */
698int do_enter(filestruct * inptr)
699{
Chris Allegrettae3167732001-03-18 16:59:34 +0000700 filestruct *newnode;
Chris Allegretta68532c32001-09-17 13:49:33 +0000701 char *tmp;
702#ifndef NANO_SMALL
703 char *spc;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000704 int extra = 0;
Chris Allegretta68532c32001-09-17 13:49:33 +0000705#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000706
Chris Allegrettae3167732001-03-18 16:59:34 +0000707 newnode = make_new_node(inptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000708 tmp = &current->data[current_x];
709 current_x = 0;
710
Chris Allegrettaff989832001-09-17 13:48:00 +0000711#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000712 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
713 if (ISSET(AUTOINDENT)) {
714 spc = current->data;
715 if (spc) {
716 while ((*spc == ' ') || (*spc == '\t')) {
717 extra++;
718 spc++;
719 current_x++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +0000720 totsize++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000721 }
Chris Allegretta88b09152001-05-17 11:35:43 +0000722 newnode->data = charalloc(strlen(tmp) + extra + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000723 strncpy(newnode->data, current->data, extra);
724 strcpy(&newnode->data[extra], tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000725 }
Chris Allegrettaff989832001-09-17 13:48:00 +0000726 } else
727#endif
728 {
Chris Allegretta88b09152001-05-17 11:35:43 +0000729 newnode->data = charalloc(strlen(tmp) + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000730 strcpy(newnode->data, tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000731 }
732 *tmp = 0;
733
Chris Allegrettada721be2000-07-31 01:26:42 +0000734 if (inptr->next == NULL) {
Chris Allegrettae3167732001-03-18 16:59:34 +0000735 filebot = newnode;
736 editbot = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000737 }
Chris Allegrettae3167732001-03-18 16:59:34 +0000738 splice_node(inptr, newnode, inptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000739
740 totsize++;
741 renumber(current);
Chris Allegrettae3167732001-03-18 16:59:34 +0000742 current = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000743 align(&current->data);
744
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000745 /* The logic here is as follows:
746 * -> If we are at the bottom of the buffer, we want to recenter
Chris Allegretta88520c92001-05-05 17:45:54 +0000747 * (read: rebuild) the screen and forcibly move the cursor.
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000748 * -> otherwise, we want simply to redraw the screen and update
749 * where we think the cursor is.
750 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000751 if (current_y == editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +0000752 edit_update(current, CENTER);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000753 reset_cursor();
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000754 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000755 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000756 edit_refresh();
757 update_cursor();
758 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000759
760 totlines++;
761 set_modified();
762
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000763 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000764 return 1;
765}
766
767int do_enter_void(void)
768{
769 return do_enter(current);
770}
771
Chris Allegrettaad3f4782001-10-02 03:54:13 +0000772#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000773void do_next_word(void)
774{
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000775 filestruct *fileptr, *old;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000776 int i;
777
778 if (current == NULL)
779 return;
780
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000781 old = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000782 i = current_x;
783 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
784 if (fileptr == current) {
785 while (isalnum((int) fileptr->data[i])
786 && fileptr->data[i] != 0)
787 i++;
788
789 if (fileptr->data[i] == 0) {
790 i = 0;
791 continue;
792 }
793 }
794 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
795 i++;
796
797 if (fileptr->data[i] != 0)
798 break;
799
800 i = 0;
801 }
802 if (fileptr == NULL)
803 current = filebot;
804 else
805 current = fileptr;
806
807 current_x = i;
808 placewewant = xplustabs();
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000809
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000810 if (current->lineno >= editbot->lineno)
Chris Allegretta234a34d2000-07-29 04:33:38 +0000811 edit_update(current, CENTER);
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000812 else {
813 /* If we've jumped lines, refresh the old line. We can't just use
814 * current->prev here, because we may have skipped over some blank
815 * lines, in which case the previous line is the wrong one.
816 */
817 if (current != old)
818 update_line(old, 0);
819
820 update_line(current, current_x);
821 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000822}
823
824/* the same thing for backwards */
825void do_prev_word(void)
826{
827 filestruct *fileptr, *old;
828 int i;
829
830 if (current == NULL)
831 return;
832
833 old = current;
834 i = current_x;
835 for (fileptr = current; fileptr != NULL; fileptr = fileptr->prev) {
836 if (fileptr == current) {
837 while (isalnum((int) fileptr->data[i])
838 && i != 0)
839 i--;
840
841 if (i == 0) {
842 if (fileptr->prev != NULL)
Chris Allegrettae59fc822001-10-24 18:07:58 +0000843 i = strlen(fileptr->prev->data);
Chris Allegretta878ced32001-10-22 20:05:34 +0000844 else if (fileptr == fileage && filebot != NULL) {
845 current_x = 0;
846 return;
847 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000848 continue;
849 }
850 }
851
852 while (!isalnum((int) fileptr->data[i]) && i != 0)
853 i--;
854
855 if (i > 0) {
856 i--;
857
858 while (isalnum((int) fileptr->data[i]) && i != 0)
859 i--;
860
Chris Allegretta6d0aa9f2001-10-26 15:21:41 +0000861 if (!isalnum((int) fileptr->data[i]))
862 i++;
863
864 if (i != 0 || i != current_x)
Chris Allegretta76e291b2001-10-14 19:05:10 +0000865 break;
866
867 }
868 if (fileptr->prev != NULL)
Chris Allegrettae59fc822001-10-24 18:07:58 +0000869 i = strlen(fileptr->prev->data);
Chris Allegretta878ced32001-10-22 20:05:34 +0000870 else if (fileptr == fileage && filebot != NULL) {
871 current_x = 0;
872 return;
873 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000874 }
875 if (fileptr == NULL)
876 current = fileage;
877 else
878 current = fileptr;
879
880 current_x = i;
881 placewewant = xplustabs();
882
883 if (current->lineno <= edittop->lineno)
884 edit_update(current, CENTER);
885 else {
886 /* If we've jumped lines, refresh the old line. We can't just use
887 * current->prev here, because we may have skipped over some blank
888 * lines, in which case the previous line is the wrong one.
889 */
890 if (current != old)
891 update_line(old, 0);
892
893 update_line(current, current_x);
894 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000895
896}
Chris Allegrettaad3f4782001-10-02 03:54:13 +0000897#endif /* NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000898
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000899#ifndef DISABLE_WRAPPING
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000900void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000901{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000902 int i = 0; /* Index into ->data for line. */
903 int i_tabs = 0; /* Screen position of ->data[i]. */
904 int last_word_end = -1; /* Location of end of last word found. */
905 int current_word_start = -1; /* Location of start of current word. */
906 int current_word_start_t = -1; /* Location of start of current word screen position. */
907 int current_word_end = -1; /* Location of end of current word */
908 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000909 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000910
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000911 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000912 int right = 0;
913 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000914
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000915 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000916
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000917 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000918 if (!isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000919 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000920
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000921 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000922 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000923
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000924 while (!isspace((int) inptr->data[i])
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000925 && inptr->data[i]) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000926 i++;
927 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000928 if (inptr->data[i] < 32)
929 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000930 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000931
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000932 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000933 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000934 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000935 } else {
936 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000937 current_word_end_t = i_tabs - 1;
938 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000939 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000940
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000941 if (inptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000942 if (i_tabs % tabsize != 0);
943 i_tabs += tabsize - (i_tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000944 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000945
Adam Rogoyski09f97962000-06-20 02:50:33 +0000946 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000947 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000948 }
949
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000950 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000951 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000952 * a) one word takes up the whole line with no starting spaces.
953 * - do nothing and return.
954 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000955 * - word starts new line.
956 * - keep white space on original line up to the cursor.
957 * *) cursor is after word at wrap point
958 * - either it's all white space after word, and this routine isn't called.
959 * - or we are actually in case 2 (2 words).
960 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000961 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000962 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000963 * - white space at end of original line is cleared, unless
964 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000965 * b) cursor is at the word at the wrap point.
966 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000967 * - white space on original line is kept to where cursor was.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000968 * c) cursor is past the word at the wrap point.
969 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000970 * - white space at end of original line is cleared
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000971 */
972
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000973 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000974
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000975 /* Category 1a: one word taking up the whole line with no beginning spaces. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000976 if ((last_word_end == -1) && (!isspace((int) inptr->data[0]))) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000977 for (i = current_word_end; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000978 if (!isspace((int) inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000979 current_word_start = i;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000980 while (!isspace((int) inptr->data[i]) && (i < len)) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000981 i++;
982 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000983 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000984 current_word_end = i;
985 break;
986 }
987 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000988
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000989 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000990 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000991 return;
992 }
993 if (current_x >= last_word_end) {
994 right = (current_x - current_word_start) + 1;
995 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000996 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000997 }
998
Chris Allegretta88b09152001-05-17 11:35:43 +0000999 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001000 strcpy(temp->data, &inptr->data[current_word_start]);
1001 inptr->data = nrealloc(inptr->data, last_word_end + 2);
1002 inptr->data[last_word_end + 1] = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001003 } else
1004 /* Category 1b: one word on the line and word not taking up whole line
1005 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001006 if (last_word_end == -1) {
Chris Allegretta88b09152001-05-17 11:35:43 +00001007 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001008 strcpy(temp->data, &inptr->data[current_word_start]);
1009
1010 /* Inside word, remove it from original, and move cursor to right spot. */
1011 if (current_x >= current_word_start) {
1012 right = current_x - current_word_start;
Chris Allegretta56214c62001-09-27 02:46:53 +00001013
1014 /* Decrease totsize by the number of spaces we removed, less
1015 one for the new line we're replacing the spaces with. */
1016 totsize -= (current_word_start - 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001017 current_x = 0;
Chris Allegrettaff989832001-09-17 13:48:00 +00001018#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001019 if (ISSET(AUTOINDENT)) {
1020 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001021 while ((inptr->next->data[i] == ' '
1022 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001023 i++;
1024 right++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001025 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001026 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001027#endif
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001028 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001029 }
1030
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001031 null_at(&inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001032
1033 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
1034 mark_beginbuf = temp;
1035 mark_beginx = 0;
1036 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001037 }
1038
1039 /* Category 2: two or more words on the line. */
1040 else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001041 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001042 if (current_x < current_word_start) {
1043 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001044 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001045 strcpy(temp->data, &inptr->data[current_word_start]);
1046
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001047 if (!isspace((int) input_char)) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001048 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001049
1050 /* Decrement totsize each time we remove a space. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001051 while (isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001052 i--;
Chris Allegretta56214c62001-09-27 02:46:53 +00001053 totsize--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001054 assert(i >= 0);
1055 }
Chris Allegretta56214c62001-09-27 02:46:53 +00001056 /* And increment it to account for the blank line we're
1057 replacing the spaces with. */
1058 totsize++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001059 } else if (current_x <= last_word_end)
1060 i = last_word_end - 1;
1061 else
1062 i = current_x;
1063
1064 inptr->data = nrealloc(inptr->data, i + 2);
1065 inptr->data[i + 1] = 0;
1066 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001067
1068
1069 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001070 else if ((current_x >= current_word_start)
1071 && (current_x <= (current_word_end + 1))) {
1072 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001073 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001074 strcpy(temp->data, &inptr->data[current_word_start]);
1075
1076 down = 1;
1077
1078 right = current_x - current_word_start;
Chris Allegrettaff989832001-09-17 13:48:00 +00001079#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001080 if (ISSET(AUTOINDENT)) {
1081 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001082 while ((inptr->next->data[i] == ' '
1083 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001084 i++;
1085 right++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001086 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001087 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001088#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001089 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001090 current_x = current_word_start;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001091
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001092 null_at(&inptr->data, current_word_start);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001093
Chris Allegretta56214c62001-09-27 02:46:53 +00001094 /* Increment totsize to account for the new line that
1095 will be added below, so that it won't end up being
1096 short by one. */
1097 totsize++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001098 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001099
1100
1101 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001102 else {
1103 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001104 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001105 strcpy(temp->data, &inptr->data[current_word_start]);
1106
1107 down = 1;
1108 right = current_x - current_word_start;
1109
1110 current_x = current_word_start;
1111 i = current_word_start - 1;
1112
Chris Allegretta56214c62001-09-27 02:46:53 +00001113 /* Decrement totsize each time we remove a space. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001114 while (isspace((int) inptr->data[i])) {
Adam Rogoyski3d449b42000-06-19 17:30:14 +00001115 i--;
Chris Allegretta56214c62001-09-27 02:46:53 +00001116 totsize--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001117 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001118 inptr->data = nrealloc(inptr->data, i + 2);
1119 inptr->data[i + 1] = 0;
1120 }
Chris Allegretta56214c62001-09-27 02:46:53 +00001121 /* And increment it to account for the blank line we're
1122 replacing the spaces with. */
1123 totsize++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001124 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001125 }
1126
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001127 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001128 if (ISSET(SAMELINEWRAP) && inptr->next) {
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001129 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001130
Chris Allegretta94a78b82001-03-14 08:28:48 +00001131 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001132 char *p =
Chris Allegretta88b09152001-05-17 11:35:43 +00001133 charalloc((strlen(temp->data) + strlen(inptr->next->data) + 2));
Chris Allegretta94a78b82001-03-14 08:28:48 +00001134
Chris Allegretta56214c62001-09-27 02:46:53 +00001135 /* We're adding to an existing line instead of creating a new
1136 one; decrement totlines here so that when it gets incremented
1137 below, it won't end up being high by one. */
1138 totlines--;
1139
Chris Allegrettaff989832001-09-17 13:48:00 +00001140#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001141 if (ISSET(AUTOINDENT)) {
1142 int non = 0;
1143
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001144 /* Grab the beginning of the next line until it's not a
1145 space or tab, then null terminate it so we can strcat it
1146 to hell */
1147 while ((inptr->next->data[non] == ' '
Chris Allegretta355fbe52001-07-14 19:32:47 +00001148 || inptr->next->data[non] == '\t')) {
1149 p[non] = inptr->next->data[non];
1150 non++;
1151 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001152 p[non] = 0;
1153 strcat(p, temp->data);
1154 strcat(p, " ");
1155
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001156 /* Now tack on the rest of the next line after the spaces and
1157 tabs */
Chris Allegretta94a78b82001-03-14 08:28:48 +00001158 strcat(p, &inptr->next->data[non]);
Chris Allegrettaff989832001-09-17 13:48:00 +00001159 } else
1160#endif
1161 {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001162 strcpy(p, temp->data);
1163 strcat(p, " ");
1164 strcat(p, inptr->next->data);
1165 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001166
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001167 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001168 inptr->next->data = p;
1169
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001170 free(temp->data);
1171 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001172
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001173 current_x = old_x;
1174 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001175 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001176 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001177 else {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001178
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001179 temp->prev = inptr;
1180 temp->next = inptr->next;
1181
1182 if (inptr->next)
1183 inptr->next->prev = temp;
1184 inptr->next = temp;
1185
1186 if (!temp->next)
1187 filebot = temp;
1188
1189 SET(SAMELINEWRAP);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001190
Chris Allegrettaff989832001-09-17 13:48:00 +00001191#ifndef NANO_SMALL
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001192 if (ISSET(AUTOINDENT)) {
1193 char *spc = inptr->data;
1194 char *t = NULL;
1195 int extra = 0;
1196 if (spc) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001197 while ((*spc == ' ') || (*spc == '\t')) {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001198 extra++;
1199 spc++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001200 totsize++;
1201 }
Chris Allegretta88b09152001-05-17 11:35:43 +00001202 t = charalloc(strlen(temp->data) + extra + 1);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001203 strncpy(t, inptr->data, extra);
1204 strcpy(t + extra, temp->data);
1205 free(temp->data);
1206 temp->data = t;
1207 }
1208 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001209#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001210 }
1211
1212
1213 totlines++;
Chris Allegretta88520c92001-05-05 17:45:54 +00001214 /* Everything about it makes me want this line here, but it causes
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001215 * totsize to be high by one for some reason. Sigh. (Rob) */
1216 /* totsize++; */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001217
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001218 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001219 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001220
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001221
1222 /* Move the cursor to the new line if appropriate. */
1223 if (down) {
1224 do_right();
1225 }
1226
1227 /* Move the cursor to the correct spot in the line if appropriate. */
1228 while (right--) {
1229 do_right();
1230 }
1231
Chris Allegretta234a34d2000-07-29 04:33:38 +00001232 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001233 reset_cursor();
1234 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001235}
1236
1237/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001238void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001239{
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001240 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001241#ifdef DEBUG
1242 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
1243 inptr->data);
1244#endif
1245
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001246 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001247 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001248 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001249 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001250
1251 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001252 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001253
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001254 while (isspace((int) inptr->data[i]) && inptr->data[i])
Adam Rogoyski09f97962000-06-20 02:50:33 +00001255 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001256
Adam Rogoyski09f97962000-06-20 02:50:33 +00001257 if (!inptr->data[i])
1258 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001259
Adam Rogoyski09f97962000-06-20 02:50:33 +00001260 /* String must be at least 1 character long. */
1261 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001262 if (isspace((int) inptr->data[i])) {
Adam Rogoyski09f97962000-06-20 02:50:33 +00001263 if (!char_found)
1264 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001265 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001266 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001267 } else
1268 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001269 }
Adam Rogoyski09f97962000-06-20 02:50:33 +00001270
1271 if (char_found == 2)
1272 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001273 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001274}
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001275#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001276
1277/* Stuff we do when we abort from programs and want to clean up the
Chris Allegretta88520c92001-05-05 17:45:54 +00001278 * screen. This doesn't do much right now.
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001279 */
1280void do_early_abort(void)
1281{
1282 blank_statusbar_refresh();
1283}
1284
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001285int do_backspace(void)
1286{
1287 filestruct *previous, *tmp;
1288
1289 if (current_x != 0) {
1290 /* Let's get dangerous */
1291 memmove(&current->data[current_x - 1], &current->data[current_x],
1292 strlen(current->data) - current_x + 1);
1293#ifdef DEBUG
1294 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
1295#endif
1296 align(&current->data);
1297 do_left();
1298 } else {
1299 if (current == fileage)
1300 return 0; /* Can't delete past top of file */
1301
1302 previous = current->prev;
1303 current_x = strlen(previous->data);
1304 previous->data = nrealloc(previous->data,
1305 strlen(previous->data) +
1306 strlen(current->data) + 1);
1307 strcat(previous->data, current->data);
1308
1309 tmp = current;
1310 unlink_node(current);
1311 delete_node(current);
1312 if (current == edittop) {
1313 if (previous->next)
1314 current = previous->next;
1315 else
1316 current = previous;
Chris Allegretta3e3ae942001-09-22 19:02:04 +00001317 page_up();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001318 } else {
1319 if (previous->next)
1320 current = previous->next;
1321 else
1322 current = previous;
1323 update_line(current, current_x);
1324 }
1325
1326 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001327 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001328 filebot = current;
1329 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001330
1331 /* Recreate the magic line if we're deleting it AND if the
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001332 line we're on now is NOT blank. if it is blank we
1333 can just use IT for the magic line. This is how Pico
1334 appears to do it, in any case */
Chris Allegretta28a0f892000-07-05 22:47:54 +00001335 if (strcmp(current->data, "")) {
1336 new_magicline();
1337 fix_editbot();
1338 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001339 }
1340
1341 current = previous;
1342 renumber(current);
1343 previous_line();
1344 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001345#ifdef DEBUG
1346 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
1347#endif
1348
1349 }
1350
1351 totsize--;
1352 set_modified();
1353 UNSET(KEEP_CUTBUFFER);
1354 edit_refresh();
1355 return 1;
1356}
1357
1358int do_delete(void)
1359{
1360 filestruct *foo;
1361
1362 if (current_x != strlen(current->data)) {
1363 /* Let's get dangerous */
1364 memmove(&current->data[current_x], &current->data[current_x + 1],
1365 strlen(current->data) - current_x);
1366
1367 align(&current->data);
1368
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001369 /* Now that we have a magic lnie again, we can check for both being
1370 on the line before filebot as well as at filebot */
Chris Allegretta4ed13152001-02-10 17:50:50 +00001371 } else if (current->next != NULL && current->next != filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001372 current->data = nrealloc(current->data,
1373 strlen(current->data) +
1374 strlen(current->next->data) + 1);
1375 strcat(current->data, current->next->data);
1376
1377 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001378 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001379 filebot = current;
1380 editbot = current;
1381 }
1382
1383 unlink_node(foo);
1384 delete_node(foo);
1385 update_line(current, current_x);
1386
Chris Allegretta4ed13152001-02-10 17:50:50 +00001387 /* Please see the comment in do_backspace if you don't understand
Chris Allegretta28a0f892000-07-05 22:47:54 +00001388 this test */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001389 if (current == filebot && strcmp(current->data, "")) {
Chris Allegretta28a0f892000-07-05 22:47:54 +00001390 new_magicline();
1391 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001392 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001393 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001394 renumber(current);
1395 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001396 } else
1397 return 0;
1398
1399 totsize--;
1400 set_modified();
1401 UNSET(KEEP_CUTBUFFER);
1402 edit_refresh();
1403 return 1;
1404}
1405
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001406void wrap_reset(void)
1407{
1408 UNSET(SAMELINEWRAP);
1409}
1410
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001411#ifndef DISABLE_SPELLER
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001412
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001413int do_int_spell_fix(char *word)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001414{
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001415 char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001416 filestruct *begin;
1417 int i = 0, j = 0, beginx, beginx_top;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001418
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001419 /* save where we are */
1420 begin = current;
1421 beginx = current_x + 1;
1422
1423 /* save the current search/replace strings */
1424 search_init_globals();
1425 save_search = mallocstrcpy(save_search, last_search);
1426 save_replace = mallocstrcpy(save_replace, last_replace);
1427
1428 /* set search/replace strings to mis-spelt word */
1429 prevanswer = mallocstrcpy(prevanswer, word);
1430 last_search = mallocstrcpy(last_search, word);
1431 last_replace = mallocstrcpy(last_replace, word);
1432
1433 /* start from the top of file */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001434 current = fileage;
1435 current_x = beginx_top = -1;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001436
1437 search_last_line = FALSE;
1438
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001439 edit_update(fileage, TOP);
1440
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001441 /* make sure word is still mis-spelt (i.e. when multi-errors) */
Chris Allegretta8d990b52001-09-22 22:14:25 +00001442 if (findnextstr(TRUE, FALSE, fileage, beginx_top, prevanswer) != NULL) {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001443 do_replace_highlight(TRUE, prevanswer);
1444
1445 /* allow replace word to be corrected */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001446 i = statusq(0, spell_list, SPELL_LIST_LEN, last_replace,
1447 _("Edit a replacement"));
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001448
1449 do_replace_highlight(FALSE, prevanswer);
1450
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001451 /* start from the start of this line again */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001452 current = fileage;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001453 current_x = beginx_top;
1454
1455 search_last_line = FALSE;
1456
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001457 j = i;
1458 do_replace_loop(prevanswer, fileage, &beginx_top, TRUE, &j);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001459 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001460
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001461 /* restore the search/replace strings */
1462 last_search = mallocstrcpy(last_search, save_search);
1463 last_replace = mallocstrcpy(last_replace, save_replace);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001464
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001465 /* restore where we were */
1466 current = begin;
1467 current_x = beginx - 1;
1468
1469 edit_update(current, CENTER);
1470
1471 if (i == -1)
1472 return FALSE;
1473
1474 return TRUE;
1475}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001476
1477/* Integrated spell checking using 'spell' program */
Chris Allegretta271e9722000-11-10 18:15:43 +00001478int do_int_speller(char *tempfile_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001479{
Chris Allegretta271e9722000-11-10 18:15:43 +00001480 char *read_buff, *read_buff_ptr, *read_buff_word;
1481 long pipe_buff_size;
1482 int in_fd[2], tempfile_fd;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001483 int spell_status;
1484 pid_t pid_spell;
1485 ssize_t bytesread;
1486
Chris Allegretta271e9722000-11-10 18:15:43 +00001487 /* Create a pipe to spell program */
1488
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001489 if (pipe(in_fd) == -1)
1490 return FALSE;
1491
Chris Allegretta271e9722000-11-10 18:15:43 +00001492 /* A new process to run spell in */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001493
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001494 if ((pid_spell = fork()) == 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001495
1496 /* Child continues, (i.e. future spell process) */
1497
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001498 close(in_fd[0]);
1499
Chris Allegretta271e9722000-11-10 18:15:43 +00001500 /* replace the standard in with the tempfile */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001501
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001502 if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001503
1504 close(in_fd[1]);
1505 exit(1);
1506 }
1507
1508 if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
1509
1510 close(tempfile_fd);
1511 close(in_fd[1]);
1512 exit(1);
1513 }
1514 close(tempfile_fd);
1515
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001516
Chris Allegretta271e9722000-11-10 18:15:43 +00001517 /* send spell's standard out to the pipe */
1518
1519 if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1520
1521 close(in_fd[1]);
1522 exit(1);
1523 }
1524 close(in_fd[1]);
1525
1526 /* Start spell program, we are using the PATH here!?!? */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001527 execlp("spell", "spell", NULL);
1528
Chris Allegretta271e9722000-11-10 18:15:43 +00001529 /* Should not be reached, if spell is found!!! */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001530
Chris Allegretta271e9722000-11-10 18:15:43 +00001531 exit(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001532 }
1533
1534 /* Parent continues here */
1535
Chris Allegretta271e9722000-11-10 18:15:43 +00001536 close(in_fd[1]);
1537
1538 /* Child process was not forked successfully */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001539
1540 if (pid_spell < 0) {
1541
Chris Allegretta271e9722000-11-10 18:15:43 +00001542 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001543 return FALSE;
1544 }
1545
Chris Allegretta271e9722000-11-10 18:15:43 +00001546 /* Get system pipe buffer size */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001547
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001548 if ((pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001549
Chris Allegretta271e9722000-11-10 18:15:43 +00001550 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001551 return FALSE;
Chris Allegretta271e9722000-11-10 18:15:43 +00001552 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001553
Chris Allegretta88b09152001-05-17 11:35:43 +00001554 read_buff = charalloc(pipe_buff_size + 1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001555
Chris Allegretta271e9722000-11-10 18:15:43 +00001556 /* Process the returned spelling errors */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001557
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001558 while ((bytesread = read(in_fd[0], read_buff, pipe_buff_size)) > 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001559
Chris Allegretta271e9722000-11-10 18:15:43 +00001560 read_buff[bytesread] = (char) NULL;
1561 read_buff_word = read_buff_ptr = read_buff;
1562
1563 while (*read_buff_ptr != (char) NULL) {
1564
1565 /* Windows version may need to process additional char '\r' */
1566
1567 /* Possible problem here if last word not followed by '\n' */
1568
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001569 if (*read_buff_ptr == '\n') {
Chris Allegretta271e9722000-11-10 18:15:43 +00001570 *read_buff_ptr = (char) NULL;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001571 if (!do_int_spell_fix(read_buff_word)) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001572
1573 close(in_fd[0]);
1574 free(read_buff);
1575 replace_abort();
1576
1577 return TRUE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001578 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001579 read_buff_word = read_buff_ptr;
1580 read_buff_word++;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001581 }
1582
1583 read_buff_ptr++;
1584 }
1585 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001586
1587 close(in_fd[0]);
1588 free(read_buff);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001589 replace_abort();
1590
Chris Allegretta271e9722000-11-10 18:15:43 +00001591 /* Process end of spell process */
1592
1593 wait(&spell_status);
1594 if (WIFEXITED(spell_status)) {
1595 if (WEXITSTATUS(spell_status) != 0)
1596 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001597 } else
Chris Allegretta271e9722000-11-10 18:15:43 +00001598 return FALSE;
1599
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001600 return TRUE;
1601}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001602
1603/* External spell checking */
Chris Allegretta271e9722000-11-10 18:15:43 +00001604int do_alt_speller(char *file_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001605{
Chris Allegrettab3655b42001-10-22 03:15:31 +00001606 int alt_spell_status, lineno_cur = current->lineno;
1607 int x_cur = current_x, y_cur = current_y, pww_cur = placewewant;
1608
Chris Allegretta271e9722000-11-10 18:15:43 +00001609 pid_t pid_spell;
Chris Allegretta169ee842001-01-26 01:57:32 +00001610 char *ptr;
1611 static int arglen = 3;
1612 static char **spellargs = (char **) NULL;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001613
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001614 endwin();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001615
Chris Allegrettae434b452001-01-27 19:25:00 +00001616 /* Set up an argument list to pass the execvp function */
1617 if (spellargs == NULL) {
1618 spellargs = nmalloc(arglen * sizeof(char *));
Chris Allegretta271e9722000-11-10 18:15:43 +00001619
Chris Allegrettae434b452001-01-27 19:25:00 +00001620 spellargs[0] = strtok(alt_speller, " ");
1621 while ((ptr = strtok(NULL, " ")) != NULL) {
1622 arglen++;
1623 spellargs = nrealloc(spellargs, arglen * sizeof(char *));
1624 spellargs[arglen - 3] = ptr;
Chris Allegretta169ee842001-01-26 01:57:32 +00001625 }
Chris Allegrettae434b452001-01-27 19:25:00 +00001626 spellargs[arglen - 1] = NULL;
1627 }
1628 spellargs[arglen - 2] = file_name;
1629
1630 /* Start a new process for the alternate speller */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001631 if ((pid_spell = fork()) == 0) {
Chris Allegretta169ee842001-01-26 01:57:32 +00001632
Chris Allegretta88520c92001-05-05 17:45:54 +00001633 /* Start alternate spell program; we are using the PATH here!?!? */
Chris Allegretta169ee842001-01-26 01:57:32 +00001634 execvp(spellargs[0], spellargs);
Chris Allegretta271e9722000-11-10 18:15:43 +00001635
1636 /* Should not be reached, if alternate speller is found!!! */
1637
1638 exit(1);
1639 }
1640
1641 /* Could not fork?? */
1642
1643 if (pid_spell < 0)
1644 return FALSE;
1645
1646 /* Wait for alternate speller to complete */
1647
1648 wait(&alt_spell_status);
1649 if (WIFEXITED(alt_spell_status)) {
1650 if (WEXITSTATUS(alt_spell_status) != 0)
1651 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001652 } else
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001653 return FALSE;
1654
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001655 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001656 free_filestruct(fileage);
Chris Allegretta56214c62001-09-27 02:46:53 +00001657 global_init(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001658 open_file(file_name, 0, 1);
Rocco Corsi4dfaf932001-04-20 01:59:55 +00001659
Chris Allegretta1b3381b2001-09-28 21:59:01 +00001660 /* go back to the old position, mark the file as modified, and make
1661 sure that the titlebar is refreshed */
1662 do_gotopos(lineno_cur, x_cur, y_cur, pww_cur);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001663 set_modified();
Chris Allegrettae1f14522001-09-19 03:19:43 +00001664 clearok(topwin, FALSE);
1665 titlebar(NULL);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001666
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001667 return TRUE;
1668}
1669#endif
1670
1671int do_spell(void)
1672{
1673
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001674#ifdef DISABLE_SPELLER
Chris Allegrettaff269f82000-12-01 18:46:01 +00001675 nano_disabled_msg();
1676 return (TRUE);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001677#else
Chris Allegretta271e9722000-11-10 18:15:43 +00001678 char *temp;
1679 int spell_res;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001680
Chris Allegretta271e9722000-11-10 18:15:43 +00001681 if ((temp = tempnam(0, "nano.")) == NULL) {
1682 statusbar(_("Could not create a temporary filename: %s"),
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001683 strerror(errno));
Chris Allegretta271e9722000-11-10 18:15:43 +00001684 return 0;
1685 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001686
Chris Allegrettaecc3d7f2001-06-05 23:24:55 +00001687 if (write_file(temp, 1, 0, 0) == -1) {
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001688 statusbar(_("Spell checking failed: unable to write temp file!"));
Chris Allegretta271e9722000-11-10 18:15:43 +00001689 return 0;
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001690 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001691
Chris Allegrettae1f14522001-09-19 03:19:43 +00001692#ifdef ENABLE_MULTIBUFFER
1693 /* update the current open_files entry before spell-checking, in case
1694 any problems occur; the case of there being no open_files entries
1695 is handled elsewhere (before we reach this point); no duplicate
1696 checking is needed here */
1697 add_open_file(1, 0);
1698#endif
1699
Chris Allegretta271e9722000-11-10 18:15:43 +00001700 if (alt_speller)
1701 spell_res = do_alt_speller(temp);
1702 else
1703 spell_res = do_int_speller(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001704
Chris Allegretta271e9722000-11-10 18:15:43 +00001705 remove(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001706
1707 if (spell_res)
1708 statusbar(_("Finished checking spelling"));
1709 else
1710 statusbar(_("Spell checking failed"));
1711
1712 return spell_res;
1713
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001714#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001715}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001716
1717int do_exit(void)
1718{
1719 int i;
1720
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001721 if (!ISSET(MODIFIED)) {
1722
Chris Allegretta355fbe52001-07-14 19:32:47 +00001723#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001724 if (!close_open_file()) {
1725 display_main_list();
1726 return 1;
1727 }
1728 else
1729#endif
1730
1731 finish(0);
1732 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001733
Chris Allegretta30885552000-07-14 01:20:12 +00001734 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001735 i = 1;
1736 } else {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001737 i = do_yesno(0, 0,
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001738 _
1739 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1740 }
1741
1742#ifdef DEBUG
1743 dump_buffer(fileage);
1744#endif
1745
1746 if (i == 1) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001747 if (do_writeout(filename, 1, 0) > 0) {
1748
Chris Allegretta355fbe52001-07-14 19:32:47 +00001749#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001750 if (!close_open_file()) {
1751 display_main_list();
1752 return 1;
1753 }
1754 else
1755#endif
1756
1757 finish(0);
1758 }
1759 } else if (i == 0) {
1760
Chris Allegretta355fbe52001-07-14 19:32:47 +00001761#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001762 if (!close_open_file()) {
1763 display_main_list();
1764 return 1;
1765 }
1766 else
1767#endif
1768
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001769 finish(0);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001770 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001771 statusbar(_("Cancelled"));
1772
1773 display_main_list();
1774 return 1;
1775}
1776
Chris Allegretta84de5522001-04-12 14:51:48 +00001777#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001778#ifdef NCURSES_MOUSE_VERSION
1779void do_mouse(void)
1780{
1781 MEVENT mevent;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001782 int foo = 0, tab_found = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001783
1784 if (getmouse(&mevent) == ERR)
1785 return;
1786
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001787 /* If mouse not in edit or bottom window, return */
1788 if (wenclose(edit, mevent.y, mevent.x)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001789
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001790 /* Don't let people screw with the marker when they're in a
1791 subfunction */
1792 if (currshortcut != main_list)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001793 return;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001794
1795 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1796 mevent.y -= 2;
1797
1798 /* Selecting where the cursor is sets the mark.
1799 * Selecting beyond the line length with the cursor at the end of the
1800 * line sets the mark as well.
1801 */
1802 if ((mevent.y == current_y) &&
1803 ((mevent.x == current_x) || (current_x == strlen(current->data)
1804 && (mevent.x >
1805 strlen(current->data))))) {
1806 if (ISSET(VIEW_MODE)) {
1807 print_view_warning();
1808 return;
1809 }
1810 do_mark();
1811 } else if (mevent.y > current_y) {
1812 while (mevent.y > current_y) {
1813 if (current->next != NULL)
1814 current = current->next;
1815 else
1816 break;
1817 current_y++;
1818 }
1819 } else if (mevent.y < current_y) {
1820 while (mevent.y < current_y) {
1821 if (current->prev != NULL)
1822 current = current->prev;
1823 else
1824 break;
1825 current_y--;
1826 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001827 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001828 current_x = mevent.x;
1829 placewewant = current_x;
1830 while (foo < current_x) {
1831 if (current->data[foo] == NANO_CONTROL_I) {
1832 current_x -= tabsize - (foo % tabsize);
1833 tab_found = 1;
1834 } else if (current->data[foo] & 0x80);
1835 else if (current->data[foo] < 32)
1836 current_x--;
1837 foo++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001838 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001839 /* This is where tab_found comes in. I can't figure out why,
1840 * but without it any line with a tab will place the cursor
1841 * one character behind. Whatever, this fixes it. */
1842 if (tab_found == 1)
1843 current_x++;
1844
1845 if (current_x > strlen(current->data))
1846 current_x = strlen(current->data);
1847
1848 update_cursor();
1849 edit_refresh();
1850 } else if (wenclose(bottomwin, mevent.y, mevent.x) && !ISSET(NO_HELP)) {
Chris Allegrettaa951f212001-09-27 21:07:39 +00001851
1852 int k, val = 0;
1853
1854 if (currslen < 2)
1855 k = COLS / 6;
1856 else
1857 k = COLS / ((currslen + (currslen %2)) / 2);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001858
1859 /* Determine what shortcut list was clicked */
1860 mevent.y -= (editwinrows + 3);
1861
1862 if (mevent.y < 0) /* They clicked on the statusbar */
1863 return;
1864
1865 /* Don't select stuff beyond list length */
1866 if (mevent.x / k >= currslen)
1867 return;
1868
1869 val = currshortcut[(mevent.x / k) * 2 + mevent.y].val;
1870
1871 /* And ungetch that value */
1872 ungetch(val);
Chris Allegretta6414b402001-09-21 03:21:11 +00001873
1874 /* And if it's an alt-key sequence, we should probably send alt
1875 too ;-) */
1876 if (val >= 'a' && val <= 'z')
1877 ungetch(27);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001878 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001879}
1880#endif
1881#endif
1882
1883/* Handler for SIGHUP */
1884RETSIGTYPE handle_hup(int signal)
1885{
Chris Allegrettae7a58932000-12-02 02:36:22 +00001886 die(_("Received SIGHUP"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001887}
1888
Chris Allegretta18f8be02000-09-04 03:20:38 +00001889/* What do we do when we catch the suspend signal */
1890RETSIGTYPE do_suspend(int signal)
1891{
Chris Allegretta18f8be02000-09-04 03:20:38 +00001892 endwin();
Chris Allegretta521e00d2001-06-28 16:52:52 +00001893 printf("\n\n\n\n\nUse \"fg\" to return to nano\n");
1894 fflush(stdout);
1895
1896 /* We used to re-enable the default SIG_DFL and raise SIGTSTP, but
1897 then we could be (and were) interrupted in the middle of the call.
1898 So we do it the mutt way instead */
1899 kill(0, SIGSTOP);
Chris Allegretta18f8be02000-09-04 03:20:38 +00001900}
1901
1902/* Restore the suspend handler when we come back into the prog */
1903RETSIGTYPE do_cont(int signal)
1904{
1905
Chris Allegretta521e00d2001-06-28 16:52:52 +00001906 /* Now we just update the screen instead of having to reenable the
1907 SIGTSTP handler */
1908
Chris Allegretta521e00d2001-06-28 16:52:52 +00001909 doupdate();
Chris Allegretta18f8be02000-09-04 03:20:38 +00001910}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001911
1912void handle_sigwinch(int s)
1913{
1914#ifndef NANO_SMALL
1915 char *tty = NULL;
1916 int fd = 0;
1917 int result = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001918 struct winsize win;
1919
1920 tty = ttyname(0);
1921 if (!tty)
1922 return;
1923 fd = open(tty, O_RDWR);
1924 if (fd == -1)
1925 return;
1926 result = ioctl(fd, TIOCGWINSZ, &win);
1927 if (result == -1)
1928 return;
1929
1930
1931 COLS = win.ws_col;
1932 LINES = win.ws_row;
1933
Chris Allegrettae61e8302001-01-14 05:18:27 +00001934 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1935 die_too_small();
1936
Chris Allegretta6fe61492001-05-21 12:56:25 +00001937#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettae61e8302001-01-14 05:18:27 +00001938 if ((fill = COLS - CHARS_FROM_EOL) < MIN_FILL_LENGTH)
1939 die_too_small();
Chris Allegretta6fe61492001-05-21 12:56:25 +00001940#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001941
Chris Allegretta0a06e072001-01-23 02:35:04 +00001942 hblank = nrealloc(hblank, COLS + 1);
1943 memset(hblank, ' ', COLS);
1944 hblank[COLS] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001945
Chris Allegretta618f5d72001-02-16 04:48:30 +00001946#ifdef HAVE_RESIZETERM
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001947 resizeterm(LINES, COLS);
1948#ifdef HAVE_WRESIZE
1949 if (wresize(topwin, 2, COLS) == ERR)
1950 die(_("Cannot resize top win"));
1951 if (mvwin(topwin, 0, 0) == ERR)
1952 die(_("Cannot move top win"));
1953 if (wresize(edit, editwinrows, COLS) == ERR)
1954 die(_("Cannot resize edit win"));
1955 if (mvwin(edit, 2, 0) == ERR)
1956 die(_("Cannot move edit win"));
1957 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1958 die(_("Cannot resize bottom win"));
1959 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1960 die(_("Cannot move bottom win"));
1961#endif /* HAVE_WRESIZE */
Chris Allegretta618f5d72001-02-16 04:48:30 +00001962#endif /* HAVE_RESIZETERM */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001963
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001964 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001965
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001966 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001967 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001968 }
1969 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00001970
1971 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001972 refresh();
Chris Allegrettaf4b96012001-01-03 07:11:47 +00001973 titlebar(NULL);
Chris Allegretta97accc62000-06-19 05:45:52 +00001974 edit_refresh();
1975 display_main_list();
Chris Allegretta08020882001-01-29 23:37:54 +00001976 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001977 total_refresh();
Chris Allegretta08020882001-01-29 23:37:54 +00001978
Chris Allegretta4e90c402001-01-29 23:40:43 +00001979 /* Turn cursor back on for sure */
1980 curs_set(1);
1981
Chris Allegretta08020882001-01-29 23:37:54 +00001982 /* Jump back to mainloop */
1983 siglongjmp(jmpbuf, 1);
1984
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001985#endif
1986}
1987
Chris Allegretta756f2202000-09-01 13:32:47 +00001988void signal_init(void)
1989{
Chris Allegrettaac899e52001-06-30 04:09:09 +00001990#ifdef _POSIX_VDISABLE
1991 struct termios term;
1992#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00001993
Chris Allegretta88520c92001-05-05 17:45:54 +00001994 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
Chris Allegretta756f2202000-09-01 13:32:47 +00001995 memset(&act, 0, sizeof(struct sigaction));
1996 act.sa_handler = SIG_IGN;
1997 sigaction(SIGINT, &act, NULL);
Chris Allegretta756f2202000-09-01 13:32:47 +00001998
Chris Allegretta88520c92001-05-05 17:45:54 +00001999 /* Trap SIGHUP cuz we want to write the file out. */
Chris Allegretta756f2202000-09-01 13:32:47 +00002000 act.sa_handler = handle_hup;
2001 sigaction(SIGHUP, &act, NULL);
2002
2003 act.sa_handler = handle_sigwinch;
2004 sigaction(SIGWINCH, &act, NULL);
2005
Chris Allegretta521e00d2001-06-28 16:52:52 +00002006 if (!ISSET(SUSPEND)) {
Chris Allegrettaac899e52001-06-30 04:09:09 +00002007
2008/* Insane! */
2009#ifdef _POSIX_VDISABLE
2010 tcgetattr(0, &term);
2011 term.c_cc[VSUSP] = _POSIX_VDISABLE;
2012 tcsetattr(0, TCSANOW, &term);
2013#else
2014 act.sa_handler = SIG_IGN;
Chris Allegretta521e00d2001-06-28 16:52:52 +00002015 sigaction(SIGTSTP, &act, NULL);
Chris Allegrettaac899e52001-06-30 04:09:09 +00002016#endif
2017
Chris Allegretta521e00d2001-06-28 16:52:52 +00002018 } else {
2019 /* if we don't do this, it seems other stuff interrupts the
2020 suspend handler! Try using nano with mutt without this line */
2021 sigfillset(&act.sa_mask);
2022
2023 act.sa_handler = do_suspend;
2024 sigaction(SIGTSTP, &act, NULL);
2025
2026 act.sa_handler = do_cont;
2027 sigaction(SIGCONT, &act, NULL);
2028 }
2029
Chris Allegretta756f2202000-09-01 13:32:47 +00002030}
2031
Chris Allegretta2a42af12000-09-12 23:02:49 +00002032void window_init(void)
2033{
Chris Allegrettae61e8302001-01-14 05:18:27 +00002034 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
2035 die_too_small();
Chris Allegretta92c9dd22000-09-13 14:03:27 +00002036
Chris Allegretta88520c92001-05-05 17:45:54 +00002037 /* Set up the main text window */
Chris Allegretta2a42af12000-09-12 23:02:49 +00002038 edit = newwin(editwinrows, COLS, 2, 0);
2039
2040 /* And the other windows */
2041 topwin = newwin(2, COLS, 0, 0);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002042 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002043
Chris Allegretta155d6202001-01-08 01:50:37 +00002044#ifdef PDCURSES
2045 /* Oops, I guess we need this again.
2046 Moved here so the keypad still works after a Meta-X, for example */
2047 keypad(edit, TRUE);
2048 keypad(bottomwin, TRUE);
2049#endif
2050
Chris Allegretta2a42af12000-09-12 23:02:49 +00002051}
2052
Chris Allegretta756f2202000-09-01 13:32:47 +00002053void mouse_init(void)
2054{
Chris Allegretta84de5522001-04-12 14:51:48 +00002055#ifndef DISABLE_MOUSE
Chris Allegretta756f2202000-09-01 13:32:47 +00002056#ifdef NCURSES_MOUSE_VERSION
2057 if (ISSET(USE_MOUSE)) {
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002058 keypad_on(edit, 1);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002059 keypad_on(bottomwin, 1);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002060
Chris Allegretta756f2202000-09-01 13:32:47 +00002061 mousemask(BUTTON1_RELEASED, NULL);
2062 mouseinterval(50);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00002063
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002064 } else
Chris Allegretta756f2202000-09-01 13:32:47 +00002065 mousemask(0, NULL);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002066
Chris Allegretta756f2202000-09-01 13:32:47 +00002067#endif
2068#endif
2069
2070}
2071
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002072int do_tab(void)
2073{
2074 do_char('\t');
2075 return 1;
2076}
2077
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002078#ifndef DISABLE_JUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002079int empty_line(const char *data)
2080{
2081 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002082 if (!isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002083 return 0;
2084
2085 data++;
2086 }
2087
2088 return 1;
2089}
2090
2091int no_spaces(const char *data)
2092{
2093 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002094 if (isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002095 return 0;
2096
2097 data++;
2098 }
2099
2100 return 1;
2101}
2102
2103void justify_format(char *data)
2104{
2105 int i = 0;
2106 int len = strlen(data);
2107
2108 /* Skip first character regardless and leading whitespace. */
2109 for (i = 1; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002110 if (!isspace((int) data[i]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002111 break;
2112 }
2113
2114 i++; /* (i) is now at least 2. */
2115
2116 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
2117 for (; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002118 if (isspace((int) data[i]) && isspace((int) data[i - 1])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002119 && (data[i - 2] != '.')) {
2120 memmove(data + i, data + i + 1, len - i);
2121 len--;
2122 i--;
2123 }
2124 }
2125}
2126#endif
2127
2128int do_justify(void)
2129{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002130#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +00002131 nano_disabled_msg();
2132 return 1;
2133#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002134 int slen = 0; /* length of combined lines on one line. */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002135 int initial_y, kbinput = 0, totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002136 filestruct *initial = NULL, *tmpjust = NULL, *cutbak, *tmptop, *tmpbot;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002137
2138 if (empty_line(current->data)) {
2139 /* Justify starting at first non-empty line. */
2140 do {
2141 if (!current->next)
2142 return 1;
2143
2144 current = current->next;
2145 current_y++;
2146 }
2147 while (empty_line(current->data));
2148 } else {
2149 /* Search back for the beginning of the paragraph, where
2150 * Paragraph is 1) A line with leading whitespace
2151 * or 2) A line following an empty line.
2152 */
2153 while (current->prev != NULL) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002154 if (isspace((int) current->data[0]) || !current->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002155 break;
2156
2157 current = current->prev;
2158 current_y--;
2159 }
2160
2161 /* First line with leading whitespace may be empty. */
2162 if (empty_line(current->data)) {
2163 if (current->next) {
2164 current = current->next;
2165 current_y++;
2166 } else
2167 return 1;
2168 }
2169 }
2170 initial = current;
2171 initial_y = current_y;
2172
2173 set_modified();
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002174 cutbak = cutbuffer; /* Got to like cutbak ;) */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002175 totbak = totsize;
Chris Allegretta9149e612000-11-27 00:23:41 +00002176 cutbuffer = NULL;
2177
2178 tmptop = current;
2179 tmpjust = copy_node(current);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002180
2181 /* This is annoying because it mucks with totsize */
Chris Allegretta9149e612000-11-27 00:23:41 +00002182 add_to_cutbuffer(tmpjust);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002183
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002184 /* Put the whole paragraph into one big line. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002185 while (current->next && !isspace((int) current->next->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002186 && current->next->data[0]) {
2187 filestruct *tmpnode = current->next;
2188 int len = strlen(current->data);
2189 int len2 = strlen(current->next->data);
2190
Chris Allegretta9149e612000-11-27 00:23:41 +00002191 tmpjust = NULL;
Chris Allegretta9149e612000-11-27 00:23:41 +00002192 tmpjust = copy_node(current->next);
2193 add_to_cutbuffer(tmpjust);
2194
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002195 /* Wiping out a newline */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002196 totsize--;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002197
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002198 /* length of both strings plus space between strings and ending \0. */
2199 current->data = nrealloc(current->data, len + len2 + 2);
2200 current->data[len++] = ' ';
2201 current->data[len] = '\0';
2202
2203 strncat(current->data, current->next->data, len2);
2204
2205 unlink_node(tmpnode);
2206 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002207 }
2208
2209 justify_format(current->data);
2210
2211 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002212 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002213
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002214 if ((strlenpt(current->data) > (fill))
2215 && !no_spaces(current->data)) {
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002216 do {
2217 int i = 0;
2218 int len2 = 0;
2219 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002220
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002221 /* Start at fill , unless line isn't that long (but it
2222 * appears at least fill long with tabs.
2223 */
2224 if (slen > fill)
2225 i = fill;
2226 else
2227 i = slen;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002228
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002229 for (; i > 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002230 if (isspace((int) current->data[i]) &&
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002231 ((strlenpt(current->data) - strlen(current->data + i))
2232 <= fill))
2233 break;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002234 }
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002235
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002236 if (!i)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002237 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002238
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002239 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002240
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002241 len2 = strlen(current->data + i + 1);
Chris Allegretta88b09152001-05-17 11:35:43 +00002242 tmpline->data = charalloc(len2 + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002243
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002244 /* Skip the white space in current. */
2245 memcpy(tmpline->data, current->data + i + 1, len2);
2246 tmpline->data[len2] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002247
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002248 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002249
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002250 tmpline->prev = current;
2251 tmpline->next = current->next;
2252 if (current->next != NULL)
2253 current->next->prev = tmpline;
2254
2255 current->next = tmpline;
2256 current = tmpline;
2257 slen -= i + 1;
2258 current_y++;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002259 } while ((strlenpt(current->data) > (fill))
2260 && !no_spaces(current->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002261 }
Chris Allegretta9149e612000-11-27 00:23:41 +00002262 tmpbot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002263
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002264 if (current->next)
2265 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00002266 else
2267 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002268 current_x = 0;
2269 placewewant = 0;
2270
Adam Rogoyski09f97962000-06-20 02:50:33 +00002271 renumber(initial);
2272 totlines = filebot->lineno;
2273
2274 werase(edit);
2275
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002276 if ((current_y < 0) || (current_y >= editwinrows - 1)
2277 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00002278 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002279 center_cursor();
2280 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00002281 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002282 }
2283
Adam Rogoyski09f97962000-06-20 02:50:33 +00002284 edit_refresh();
Chris Allegretta9149e612000-11-27 00:23:41 +00002285 statusbar(_("Can now UnJustify!"));
Chris Allegretta07798352000-11-27 22:58:23 +00002286 /* Change the shortcut list to display the unjustify code */
2287 shortcut_init(1);
2288 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002289 reset_cursor();
2290
Chris Allegretta88520c92001-05-05 17:45:54 +00002291 /* Now get a keystroke and see if it's unjustify; if not, unget the keystroke
Chris Allegretta9149e612000-11-27 00:23:41 +00002292 and return */
Chris Allegretta5f071802001-05-06 02:34:31 +00002293
2294#ifndef DISABLE_MOUSE
2295#ifdef NCURSES_MOUSE_VERSION
2296
2297 /* If it was a mouse click, parse it with do_mouse and it might become
2298 the unjustify key. Else give it back to the input stream. */
2299 if ((kbinput = wgetch(edit)) == KEY_MOUSE)
2300 do_mouse();
2301 else
2302 ungetch(kbinput);
2303#endif
2304#endif
2305
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002306 if ((kbinput = wgetch(edit)) != NANO_UNJUSTIFY_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002307 ungetch(kbinput);
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002308 blank_statusbar_refresh();
2309 } else {
Chris Allegretta9149e612000-11-27 00:23:41 +00002310 /* Else restore the justify we just did (ungrateful user!) */
2311 if (tmptop->prev != NULL)
2312 tmptop->prev->next = tmpbot->next;
Chris Allegrettad022eac2000-11-27 02:50:49 +00002313 else
2314 fileage = current;
Chris Allegretta9149e612000-11-27 00:23:41 +00002315 tmpbot->next->prev = tmptop->prev;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002316 current = tmpbot->next;
Chris Allegretta9149e612000-11-27 00:23:41 +00002317 tmpbot->next = NULL;
2318 do_uncut_text();
Chris Allegrettad022eac2000-11-27 02:50:49 +00002319 if (tmptop->prev == NULL)
2320 edit_refresh();
2321
Chris Allegretta88520c92001-05-05 17:45:54 +00002322 /* Restore totsize from before justify */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002323 totsize = totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002324 free_filestruct(tmptop);
2325 blank_statusbar_refresh();
2326 }
Chris Allegretta4a9c8582000-11-27 22:59:40 +00002327 shortcut_init(0);
2328 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002329 free_filestruct(cutbuffer);
2330 cutbuffer = cutbak;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002331
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002332 return 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002333#endif
2334}
2335
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002336#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002337void help_init(void)
2338{
2339 int i, sofar = 0;
2340 long allocsize = 1; /* How much space we're gonna need for the help text */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002341 char buf[BUFSIZ] = "", *ptr = NULL;
2342
2343 /* First set up the initial help text for the current function */
2344 if (currshortcut == whereis_list || currshortcut == replace_list
2345 || currshortcut == replace_list_2)
2346 ptr = _("Search Command Help Text\n\n "
2347 "Enter the words or characters you would like to search "
2348 "for, then hit enter. If there is a match for the text you "
2349 "entered, the screen will be updated to the location of the "
2350 " nearest match for the search string.\n\n "
2351 "If using Pico Mode via the -p or --pico flags or using the "
2352 "Meta-P toggle, the previous search string will be shown in "
2353 "brackets after the Search: prompt. Hitting enter without "
2354 "entering any text will preform the previous search. "
2355 "Otherwise, the previous string will be placed in front of "
2356 "the cursor, and can be edited or deleted before hitting "
2357 "enter.\n\n The following functions keys are available in "
2358 "Search mode:\n\n");
2359 else if (currshortcut == goto_list)
2360 ptr = _("Goto Line Help Text\n\n "
2361 "Enter the line number that you wish to go to and hit "
2362 "Enter. If thre are fewer lines of text than the "
2363 "number you entered, you will be brought to the last line "
2364 "of the file.\n\n The following functions keys are "
2365 "available in Goto Line mode:\n\n");
2366 else if (currshortcut == insertfile_list)
2367 ptr = _("Insert File Help Text\n\n "
2368 "Type in the name of a file to be inserted into the current "
2369 "file buffer at the current cursor location.\n\n "
2370 "If you have compiled nano with multiple file buffer "
2371 "support, and enable multiple buffers with the -F "
2372 "or --multibuffer command line flags or the Meta-F "
2373 "toggle, inserting a file will cause it to be loaded into "
2374 "a separate buffer (use Ctrl-< and > to switch between "
2375 "file buffers).\n\n The following function keys are "
2376 "available in Insert File mode:\n\n");
2377 else if (currshortcut == writefile_list)
2378 ptr = _("Write File Help Text\n\n "
2379 "Type the name that you wish to save the current file "
2380 "as and hit enter to save the file.\n\n "
2381 "If you are using the marker code with Ctrl-^ and have "
2382 "selected text, you will be prompted to save only the "
2383 "selected portion to a separate file. To reduce the "
2384 "chance of overwriting the current file with just a portion "
2385 "of it, the current filename is not the default in this "
2386 "mode.\n\n The following function keys are available in "
2387 "Write File mode:\n\n");
2388#ifndef DISABLE_BROWSER
2389 else if (currshortcut == browser_list)
2390 ptr = _("File Browser Help Text\n\n "
2391 "The file browser is used to visually browse the "
2392 "directory structure to select a file for reading "
2393 "or writing. You may use the arrow keys or Page Up/"
2394 "Down to browse through the files, and S or Enter to "
2395 "choose the selected file or enter the selected "
2396 "directory. To move up one level, select the directory "
2397 "called \"..\" at the top of the file list.\n\n The "
2398 "following functions keys are available in the file "
2399 "browser:\n\n");
2400 else if (currshortcut == gotodir_list)
2401 ptr = _("Browser Goto Directory Help Text\n\n "
2402 "Enter the name of the directory you would like to "
2403 "browse to.\n\n If tab completion has not been disabled, "
2404 "you can use the TAB key to (attempt to) automatically "
2405 "complete the directory name. The following function "
2406 "keys are available in Browser GotoDir mode:\n\n");
2407#endif
2408 else if (currshortcut == spell_list)
2409 ptr = _("Spell Check Help Text\n\n "
2410 "The spell checker checks the spelling of all text "
2411 "in the current file. When an unknown word is "
2412 "encountered, it is highlighted and a replacement can "
2413 "be edited. It will then prompt to replace every "
2414 "instance of the given misspelled word in the "
2415 "current file.\n\n The following other functions are "
2416 "available in Spell Check mode:\n\n");
2417 else /* Default to the main help list */
2418 ptr = help_text_init;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002419
2420 /* Compute the space needed for the shortcut lists - we add 15 to
2421 have room for the shortcut abbrev and its possible alternate keys */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002422 for (i = 0; i <= currslen - 1; i++)
2423 if (currshortcut[i].help != NULL)
2424 allocsize += strlen(currshortcut[i].help) + 15;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002425
Chris Allegrettab3655b42001-10-22 03:15:31 +00002426 /* If we're on the main list, we also allocate space for toggle help text. */
2427 if (currshortcut == main_list) {
2428 for (i = 0; i <= TOGGLE_LEN - 1; i++)
2429 if (toggles[i].desc != NULL)
2430 allocsize += strlen(toggles[i].desc) + 30;
Chris Allegretta756f2202000-09-01 13:32:47 +00002431
Chris Allegrettab3655b42001-10-22 03:15:31 +00002432 }
2433
2434 allocsize += strlen(ptr);
2435
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002436
2437 if (help_text != NULL)
2438 free(help_text);
2439
2440 /* Allocate space for the help text */
Chris Allegretta88b09152001-05-17 11:35:43 +00002441 help_text = charalloc(allocsize);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002442
2443 /* Now add the text we want */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002444 strcpy(help_text, ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002445
2446 /* Now add our shortcut info */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002447 for (i = 0; i <= currslen - 1; i++) {
2448 if (currshortcut[i].val > 0 && currshortcut[i].val < 'a')
2449 sofar = snprintf(buf, BUFSIZ, "^%c ", currshortcut[i].val + 64);
Chris Allegretta8d990b52001-09-22 22:14:25 +00002450 else
2451 sofar = snprintf(buf, BUFSIZ, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002452
Chris Allegrettab3655b42001-10-22 03:15:31 +00002453 if (currshortcut[i].misc1 > KEY_F0 && currshortcut[i].misc1 <= KEY_F(64))
Robert Siemborski6af14312000-07-01 21:34:26 +00002454 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
Chris Allegrettab3655b42001-10-22 03:15:31 +00002455 currshortcut[i].misc1 - KEY_F0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002456 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002457 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002458
Chris Allegrettab3655b42001-10-22 03:15:31 +00002459 if (currshortcut[i].altval > 0 && currshortcut[i].altval < 91)
Chris Allegrettae49f1232000-09-02 07:20:39 +00002460 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
Chris Allegrettab3655b42001-10-22 03:15:31 +00002461 currshortcut[i].altval - 32);
2462 else if (currshortcut[i].altval > 0)
Chris Allegretta8d990b52001-09-22 22:14:25 +00002463 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
Chris Allegrettab3655b42001-10-22 03:15:31 +00002464 currshortcut[i].altval);
2465 /* Hack */
2466 else if (currshortcut[i].val >= 'a')
2467 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
2468 currshortcut[i].val - 32);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002469 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002470 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002471
Chris Allegretta756f2202000-09-01 13:32:47 +00002472
Chris Allegrettab3655b42001-10-22 03:15:31 +00002473 if (currshortcut[i].help != NULL)
2474 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", currshortcut[i].help);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002475
Chris Allegretta756f2202000-09-01 13:32:47 +00002476
2477 strcat(help_text, buf);
2478 strcat(help_text, "\n");
2479 }
2480
2481 /* And the toggles... */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002482 if (currshortcut == main_list)
2483 for (i = 0; i <= TOGGLE_LEN - 1; i++) {
2484 if (toggles[i].override_ch != 0)
2485 sofar = snprintf(buf, BUFSIZ,
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002486 "M-%c ", toggles[i].override_ch);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002487 else
2488 sofar = snprintf(buf, BUFSIZ,
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002489 "M-%c ", toggles[i].val - 32);
Chris Allegretta756f2202000-09-01 13:32:47 +00002490
Chris Allegrettab3655b42001-10-22 03:15:31 +00002491 if (toggles[i].desc != NULL) {
2492 if (toggles[i].flag != 0)
2493 snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002494 toggles[i].desc);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002495 else
2496 snprintf(&buf[sofar], BUFSIZ - sofar, "%s",
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002497 toggles[i].desc);
2498 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002499
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002500 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00002501 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002502 }
2503
2504}
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002505#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002506
Chris Allegretta756f2202000-09-01 13:32:47 +00002507void do_toggle(int which)
2508{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002509#ifdef NANO_SMALL
2510 nano_disabled_msg();
2511#else
Jordi Mallach2dc0f6b2000-09-07 10:48:00 +00002512 char *enabled = _("enabled");
2513 char *disabled = _("disabled");
Chris Allegrettaf0f63a82000-09-02 18:44:21 +00002514
Chris Allegretta8d990b52001-09-22 22:14:25 +00002515 switch (toggles[which].val) {
2516 case TOGGLE_BACKWARDS_KEY:
2517 case TOGGLE_CASE_KEY:
2518 case TOGGLE_REGEXP_KEY:
2519 return;
2520 }
Chris Allegretta8d990b52001-09-22 22:14:25 +00002521
Chris Allegretta658399a2001-06-14 02:54:22 +00002522 /* Even easier! */
2523 TOGGLE(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002524
Chris Allegretta756f2202000-09-01 13:32:47 +00002525 switch (toggles[which].val) {
2526 case TOGGLE_PICOMODE_KEY:
Chris Allegretta07798352000-11-27 22:58:23 +00002527 shortcut_init(0);
Chris Allegrettac1049ac2001-08-17 00:03:46 +00002528 SET(CLEAR_BACKUPSTRING);
Chris Allegretta756f2202000-09-01 13:32:47 +00002529 display_main_list();
2530 break;
2531 case TOGGLE_SUSPEND_KEY:
2532 signal_init();
2533 break;
2534 case TOGGLE_MOUSE_KEY:
2535 mouse_init();
2536 break;
2537 case TOGGLE_NOHELP_KEY:
Chris Allegretta2a42af12000-09-12 23:02:49 +00002538 wclear(bottomwin);
2539 wrefresh(bottomwin);
2540 window_init();
Chris Allegrettaaffeda82000-12-18 04:03:48 +00002541 fix_editbot();
Chris Allegretta2a42af12000-09-12 23:02:49 +00002542 edit_refresh();
2543 display_main_list();
Chris Allegretta756f2202000-09-01 13:32:47 +00002544 break;
Chris Allegretta99e30e12001-09-23 02:45:27 +00002545 case TOGGLE_DOS_KEY:
2546 UNSET(MAC_FILE);
2547 break;
2548 case TOGGLE_MAC_KEY:
2549 UNSET(DOS_FILE);
2550 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002551 }
Chris Allegretta2a42af12000-09-12 23:02:49 +00002552
Chris Allegretta819e3db2001-07-11 02:37:19 +00002553 if (!ISSET(toggles[which].flag)) {
2554 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
2555 toggles[which].val == TOGGLE_WRAP_KEY)
2556 statusbar("%s %s", toggles[which].desc, enabled);
2557 else
2558 statusbar("%s %s", toggles[which].desc, disabled);
2559 } else {
2560 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
2561 toggles[which].val == TOGGLE_WRAP_KEY)
2562 statusbar("%s %s", toggles[which].desc, disabled);
2563 else
2564 statusbar("%s %s", toggles[which].desc, enabled);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002565 }
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002566
Chris Allegretta756f2202000-09-01 13:32:47 +00002567#endif
2568}
2569
Chris Allegretta88520c92001-05-05 17:45:54 +00002570/* If the NumLock key has made the keypad go awry, print an error
2571 message; hopefully we can address it later. */
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002572void print_numlock_warning(void)
2573{
2574 static int didmsg = 0;
2575 if (!didmsg) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002576 statusbar(_
2577 ("NumLock glitch detected. Keypad will malfunction with NumLock off"));
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002578 didmsg = 1;
2579 }
2580}
2581
Chris Allegretta1748cd12001-01-13 17:22:54 +00002582/* This function returns the correct keystroke, given the A,B,C or D
2583 input key. This is a common sequence of many terms which send
2584 Esc-O-[A-D] or Esc-[-[A-D]. */
2585int ABCD(int input)
2586{
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002587 switch (input) {
2588 case 'A':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002589 case 'a':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002590 return (KEY_UP);
2591 case 'B':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002592 case 'b':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002593 return (KEY_DOWN);
2594 case 'C':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002595 case 'c':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002596 return (KEY_RIGHT);
2597 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002598 case 'd':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002599 return (KEY_LEFT);
2600 default:
2601 return 0;
Chris Allegretta1748cd12001-01-13 17:22:54 +00002602 }
2603}
2604
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002605int main(int argc, char *argv[])
2606{
2607 int optchr;
2608 int kbinput; /* Input from keyboard */
2609 long startline = 0; /* Line to try and start at */
Chris Allegretta08020882001-01-29 23:37:54 +00002610 int keyhandled; /* Have we handled the keystroke yet? */
2611 int i, modify_control_seq;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002612 char *argv0;
Chris Allegrettab516d8e2001-10-03 00:01:36 +00002613 long constcheck; /* Check to constantly update */
Chris Allegretta0357c4d2001-09-19 02:59:25 +00002614
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002615#ifdef _POSIX_VDISABLE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002616 struct termios term;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002617#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002618
2619#ifdef HAVE_GETOPT_LONG
2620 int option_index = 0;
2621 struct option long_options[] = {
Chris Allegretta805c26d2000-09-06 13:39:17 +00002622#ifdef HAVE_REGEX_H
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002623 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00002624#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002625 {"version", 0, 0, 'V'},
2626 {"const", 0, 0, 'c'},
2627 {"suspend", 0, 0, 'z'},
2628 {"nowrap", 0, 0, 'w'},
2629 {"nohelp", 0, 0, 'x'},
2630 {"help", 0, 0, 'h'},
Chris Allegretta7492cec2000-12-18 04:55:21 +00002631 {"view", 0, 0, 'v'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002632#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002633 {"cut", 0, 0, 'k'},
Chris Allegretta7004c282001-09-22 00:42:10 +00002634 {"dos", 0, 0, 'D'},
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002635 {"mac", 0, 0, 'M'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002636 {"autoindent", 0, 0, 'i'},
Chris Allegrettaff989832001-09-17 13:48:00 +00002637#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002638 {"tempfile", 0, 0, 't'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002639#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002640 {"speller", 1, 0, 's'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002641#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00002642
2643#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002644 {"fill", 1, 0, 'r'},
Chris Allegretta6fe61492001-05-21 12:56:25 +00002645#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002646 {"mouse", 0, 0, 'm'},
Chris Allegrettae1f14522001-09-19 03:19:43 +00002647#ifndef DISABLE_OPERATINGDIR
2648 {"operatingdir", 1, 0, 'o'},
2649#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002650 {"pico", 0, 0, 'p'},
2651 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00002652 {"tabsize", 1, 0, 'T'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002653
Chris Allegretta355fbe52001-07-14 19:32:47 +00002654#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002655 {"multibuffer", 0, 0, 'F'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002656#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002657#ifndef NANO_SMALL
2658 {"smooth", 0, 0, 'S'},
2659#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002660 {0, 0, 0, 0}
2661 };
2662#endif
2663
2664 /* Flag inits... */
2665 SET(FOLLOW_SYMLINKS);
2666
2667#ifndef NANO_SMALL
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002668#ifdef ENABLE_NLS
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002669 setlocale(LC_ALL, "");
2670 bindtextdomain(PACKAGE, LOCALEDIR);
2671 textdomain(PACKAGE);
2672#endif
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002673#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002674
Chris Allegretta8d8e0122001-04-18 04:28:54 +00002675#ifdef ENABLE_NANORC
2676 do_rcfile();
2677#endif /* ENABLE_NANORC */
2678
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002679#ifdef HAVE_GETOPT_LONG
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002680 while ((optchr = getopt_long(argc, argv, "h?DFMRST:Vabcefgijklmo:pr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002681 long_options, &option_index)) != EOF) {
2682#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002683 while ((optchr =
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002684 getopt(argc, argv, "h?DFMRST:Vabcefgijklmo:pr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002685#endif
2686
2687 switch (optchr) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002688
Chris Allegretta7004c282001-09-22 00:42:10 +00002689#ifndef NANO_SMALL
2690 case 'D':
2691 SET(DOS_FILE);
2692 break;
2693#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +00002694#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002695 case 'F':
Chris Allegretta355fbe52001-07-14 19:32:47 +00002696 SET(MULTIBUFFER);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002697 break;
2698#endif
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002699#ifndef NANO_SMALL
2700 case 'M':
2701 SET(MAC_FILE);
2702 break;
2703#endif
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002704 case 'T':
Chris Allegretta99bf73f2000-08-04 00:22:08 +00002705 tabsize = atoi(optarg);
2706 if (tabsize <= 0) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002707 usage(); /* To stop bogus data for tab width */
2708 finish(1);
2709 }
2710 break;
Chris Allegretta805c26d2000-09-06 13:39:17 +00002711#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +00002712 case 'R':
2713 SET(USE_REGEXP);
2714 break;
Chris Allegretta47805612000-07-07 02:35:34 +00002715#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002716#ifndef NANO_SMALL
2717 case 'S':
2718 SET(SMOOTHSCROLL);
2719 break;
2720#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002721 case 'V':
2722 version();
2723 exit(0);
Chris Allegrettae1f14522001-09-19 03:19:43 +00002724 case 'a':
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002725 case 'b':
2726 case 'e':
2727 case 'f':
Rocco Corsi12f294c2001-04-14 06:50:24 +00002728 case 'g':
2729 case 'j':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002730 /* Pico compatibility flags */
2731 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002732 case 'c':
2733 SET(CONSTUPDATE);
2734 break;
2735 case 'h':
2736 case '?':
2737 usage();
2738 exit(0);
Chris Allegrettaff989832001-09-17 13:48:00 +00002739#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002740 case 'i':
2741 SET(AUTOINDENT);
2742 break;
Chris Allegretta627de192000-07-12 02:09:17 +00002743 case 'k':
2744 SET(CUT_TO_END);
2745 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002746#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002747 case 'l':
2748 UNSET(FOLLOW_SYMLINKS);
2749 break;
2750 case 'm':
2751 SET(USE_MOUSE);
2752 break;
Chris Allegrettae1f14522001-09-19 03:19:43 +00002753#ifndef DISABLE_OPERATINGDIR
2754 case 'o':
2755 operating_dir = charalloc(strlen(optarg) + 1);
2756 strcpy(operating_dir, optarg);
2757
2758 /* make sure we're inside the operating directory */
2759 if (check_operating_dir(".", 0)) {
2760 if (chdir(operating_dir) == -1) {
2761 free(operating_dir);
2762 operating_dir = NULL;
2763 }
2764 }
2765 break;
2766#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002767 case 'p':
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002768 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002769 break;
2770 case 'r':
Chris Allegretta6fe61492001-05-21 12:56:25 +00002771#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002772 fill = atoi(optarg);
Chris Allegretta6fe61492001-05-21 12:56:25 +00002773 if (fill < 0)
2774 wrap_at = fill;
2775 else if (fill == 0) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002776 usage(); /* To stop bogus data (like a string) */
2777 finish(1);
2778 }
2779 break;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002780#else
2781 usage();
2782 exit(0);
2783
2784#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002785#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002786 case 's':
Chris Allegretta88b09152001-05-17 11:35:43 +00002787 alt_speller = charalloc(strlen(optarg) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002788 strcpy(alt_speller, optarg);
2789 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002790#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002791 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00002792 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002793 break;
2794 case 'v':
2795 SET(VIEW_MODE);
2796 break;
2797 case 'w':
Chris Allegrettacef7fbb2001-04-02 05:36:08 +00002798#ifdef DISABLE_WRAPPING
2799 usage();
2800 exit(0);
2801#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002802 SET(NO_WRAP);
2803 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002804#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002805 case 'x':
2806 SET(NO_HELP);
2807 break;
2808 case 'z':
2809 SET(SUSPEND);
2810 break;
2811 default:
2812 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002813 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002814 }
2815
2816 }
2817
2818 argv0 = strrchr(argv[0], '/');
2819 if ((argv0 && strstr(argv0, "pico"))
2820 || (!argv0 && strstr(argv[0], "pico")))
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002821 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002822
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002823 /* See if there's a non-option in argv (first non-option is the
2824 filename, if +LINE is not given) */
2825 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002826 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002827 else {
2828 /* Look for the +line flag... */
2829 if (argv[optind][0] == '+') {
2830 startline = atoi(&argv[optind][1]);
2831 optind++;
2832 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002833 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002834 else
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002835 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002836
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002837 } else
2838 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002839 }
2840
2841
2842 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002843 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002844
Chris Allegretta9239d742000-09-06 15:19:18 +00002845#ifdef _POSIX_VDISABLE
Chris Allegretta8f6c0692000-07-19 01:16:18 +00002846 term = oldterm;
2847 term.c_cc[VINTR] = _POSIX_VDISABLE;
2848 term.c_cc[VQUIT] = _POSIX_VDISABLE;
2849 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002850 tcsetattr(0, TCSANOW, &term);
Chris Allegretta9239d742000-09-06 15:19:18 +00002851#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002852
2853 /* now ncurses init stuff... */
2854 initscr();
2855 savetty();
2856 nonl();
2857 cbreak();
2858 noecho();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002859
2860 /* Set up some global variables */
Chris Allegretta56214c62001-09-27 02:46:53 +00002861 global_init(0);
Chris Allegretta07798352000-11-27 22:58:23 +00002862 shortcut_init(0);
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002863#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002864 init_help_msg();
2865 help_init();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002866#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002867 signal_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002868
2869#ifdef DEBUG
2870 fprintf(stderr, _("Main: set up windows\n"));
2871#endif
2872
Chris Allegretta8ce24132001-04-30 11:28:46 +00002873#ifdef ENABLE_COLOR
2874 do_colorinit();
2875#endif /* ENABLE_COLOR */
2876
Chris Allegretta2a42af12000-09-12 23:02:49 +00002877 window_init();
Chris Allegretta756f2202000-09-01 13:32:47 +00002878 mouse_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002879
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002880#ifdef DEBUG
2881 fprintf(stderr, _("Main: bottom win\n"));
2882#endif
Chris Allegretta88520c92001-05-05 17:45:54 +00002883 /* Set up bottom of window */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002884 display_main_list();
2885
2886#ifdef DEBUG
2887 fprintf(stderr, _("Main: open file\n"));
2888#endif
2889
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002890 titlebar(NULL);
Chris Allegretta31c76662000-11-21 06:20:20 +00002891
2892 /* Now we check to see if argv[optind] is non-null to determine if
2893 we're dealing with a new file or not, not argc == 1... */
2894 if (argv[optind] == NULL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002895 new_file();
2896 else
2897 open_file(filename, 0, 0);
2898
2899 if (startline > 0)
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002900 do_gotoline(startline, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002901 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00002902 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002903
Chris Allegretta08020882001-01-29 23:37:54 +00002904 /* return here after a sigwinch */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002905 sigsetjmp(jmpbuf, 1);
Chris Allegretta08020882001-01-29 23:37:54 +00002906
2907 /* Fix clobber-age */
2908 kbinput = 0;
2909 keyhandled = 0;
2910 modify_control_seq = 0;
2911
Robert Siemborski6967eec2000-07-08 14:23:32 +00002912 edit_refresh();
2913 reset_cursor();
2914
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002915 while (1) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00002916 constcheck = current->lineno + current_x + current_y + totsize;
Chris Allegretta9239d742000-09-06 15:19:18 +00002917
Chris Allegretta6fe61492001-05-21 12:56:25 +00002918#ifndef DISABLE_MOUSE
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002919 currshortcut = main_list;
2920 currslen = MAIN_VISIBLE;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002921#endif
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002922
Chris Allegretta9239d742000-09-06 15:19:18 +00002923#ifndef _POSIX_VDISABLE
2924 /* We're going to have to do it the old way, i.e. on cygwin */
2925 raw();
2926#endif
2927
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002928 kbinput = wgetch(edit);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002929#ifdef DEBUG
2930 fprintf(stderr, "AHA! %c (%d)\n", kbinput, kbinput);
2931#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002932
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002933 if (kbinput == 27) { /* Grab Alt-key stuff first */
2934 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002935 /* Alt-O, suddenly very important ;) */
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002936 case 'O':
Chris Allegretta16e41682000-09-11 22:33:54 +00002937 kbinput = wgetch(edit);
Chris Allegretta316e4d92001-04-28 16:31:19 +00002938 if ((kbinput <= 'D' && kbinput >= 'A') ||
2939 (kbinput <= 'd' && kbinput >= 'a'))
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002940 kbinput = ABCD(kbinput);
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002941 else if (kbinput <= 'z' && kbinput >= 'j')
2942 print_numlock_warning();
2943 else if (kbinput <= 'S' && kbinput >= 'P')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002944 kbinput = KEY_F(kbinput - 79);
Chris Allegretta16e41682000-09-11 22:33:54 +00002945#ifdef DEBUG
2946 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002947 fprintf(stderr, _("I got Alt-O-%c! (%d)\n"),
2948 kbinput, kbinput);
2949 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002950 }
2951#endif
2952 break;
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002953 case 27:
2954 /* If we get Alt-Alt, the next keystroke should be the same as a
2955 control sequence */
2956 modify_control_seq = 1;
2957 keyhandled = 1;
2958 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00002959#ifndef NANO_SMALL
Chris Allegretta76e291b2001-10-14 19:05:10 +00002960 case ' ':
2961 /* If control-space is next word, Alt-space should be previous word */
2962 do_prev_word();
2963 keyhandled = 1;
2964 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00002965#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002966 case '[':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002967 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002968 case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */
Chris Allegretta16e41682000-09-11 22:33:54 +00002969 kbinput = wgetch(edit);
2970 if (kbinput >= '1' && kbinput <= '5') {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002971 kbinput = KEY_F(kbinput - 48);
2972 wgetch(edit);
2973 } else if (kbinput >= '7' && kbinput <= '9') {
2974 kbinput = KEY_F(kbinput - 49);
2975 wgetch(edit);
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002976 } else if (kbinput == '~')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002977 kbinput = KEY_HOME;
Chris Allegretta16e41682000-09-11 22:33:54 +00002978
2979#ifdef DEBUG
2980 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002981 fprintf(stderr, _("I got Alt-[-1-%c! (%d)\n"),
2982 kbinput, kbinput);
2983 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002984 }
2985#endif
2986
2987 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002988 case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */
Chris Allegretta16e41682000-09-11 22:33:54 +00002989 kbinput = wgetch(edit);
Chris Allegretta16e41682000-09-11 22:33:54 +00002990 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002991 case '0':
2992 kbinput = KEY_F(9);
2993 wgetch(edit);
2994 break;
2995 case '1':
2996 kbinput = KEY_F(10);
2997 wgetch(edit);
2998 break;
2999 case '3':
3000 kbinput = KEY_F(11);
3001 wgetch(edit);
3002 break;
3003 case '4':
3004 kbinput = KEY_F(12);
3005 wgetch(edit);
3006 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003007 case '~':
3008 goto do_insertkey;
Chris Allegretta16e41682000-09-11 22:33:54 +00003009#ifdef DEBUG
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003010 default:
3011 fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"),
3012 kbinput, kbinput);
3013 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003014#endif
3015
3016 }
3017 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003018 case '3': /* Alt-[-3 = Delete? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003019 kbinput = NANO_DELETE_KEY;
3020 wgetch(edit);
3021 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003022 case '4': /* Alt-[-4 = End? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003023 kbinput = NANO_END_KEY;
3024 wgetch(edit);
3025 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003026 case '5': /* Alt-[-5 = Page Up */
Chris Allegretta16e41682000-09-11 22:33:54 +00003027 kbinput = KEY_PPAGE;
3028 wgetch(edit);
3029 break;
Chris Allegretta7bf72742001-10-28 04:29:55 +00003030 case 'I': /* Alt-[-I = Page Up - FreeBSD Console */
3031 kbinput = KEY_PPAGE;
3032 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003033 case '6': /* Alt-[-6 = Page Down */
Chris Allegretta16e41682000-09-11 22:33:54 +00003034 kbinput = KEY_NPAGE;
3035 wgetch(edit);
3036 break;
Chris Allegretta7bf72742001-10-28 04:29:55 +00003037 case 'G': /* Alt-[-G = Page Down - FreeBSD Console */
3038 kbinput = KEY_NPAGE;
3039 break;
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003040 case '7':
3041 kbinput = KEY_HOME;
3042 wgetch(edit);
3043 break;
3044 case '8':
3045 kbinput = KEY_END;
3046 wgetch(edit);
3047 break;
Chris Allegretta7bf72742001-10-28 04:29:55 +00003048 case 'L': /* Insert Key - FreeBSD Console */
3049#ifdef ENABLE_MULTIBUFFER
3050 do_insertfile(ISSET(MULTIBUFFER));
3051#else
3052 do_insertfile(0);
3053#endif
3054 keyhandled = 1;
3055 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003056 case '[': /* Alt-[-[-[A-E], F1-F5 in linux console */
Chris Allegretta16e41682000-09-11 22:33:54 +00003057 kbinput = wgetch(edit);
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003058 if (kbinput >= 'A' && kbinput <= 'E')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003059 kbinput = KEY_F(kbinput - 64);
Chris Allegretta16e41682000-09-11 22:33:54 +00003060 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003061 case 'A':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003062 case 'B':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003063 case 'C':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003064 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00003065 case 'a':
3066 case 'b':
3067 case 'c':
3068 case 'd':
Chris Allegretta1748cd12001-01-13 17:22:54 +00003069 kbinput = ABCD(kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003070 break;
3071 case 'H':
3072 kbinput = KEY_HOME;
3073 break;
3074 case 'F':
3075 kbinput = KEY_END;
3076 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003077 default:
3078#ifdef DEBUG
3079 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
3080 kbinput, kbinput);
3081#endif
3082 break;
3083 }
3084 break;
Chris Allegretta355fbe52001-07-14 19:32:47 +00003085#ifdef ENABLE_MULTIBUFFER
Chris Allegretta819e3db2001-07-11 02:37:19 +00003086 case NANO_OPENPREV_KEY:
3087 open_prevfile(0);
3088 keyhandled = 1;
3089 break;
3090 case NANO_OPENNEXT_KEY:
3091 open_nextfile(0);
3092 keyhandled = 1;
3093 break;
Chris Allegretta9cf9e062001-07-11 12:06:13 +00003094#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003095 default:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003096 /* Check for the altkey defs.... */
3097 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
3098 if (kbinput == main_list[i].altval ||
3099 kbinput == main_list[i].altval - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003100 kbinput = main_list[i].val;
3101 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003102 }
Chris Allegretta756f2202000-09-01 13:32:47 +00003103#ifndef NANO_SMALL
3104 /* And for toggle switches */
3105 for (i = 0; i <= TOGGLE_LEN - 1 && !keyhandled; i++)
3106 if (kbinput == toggles[i].val ||
3107 kbinput == toggles[i].val - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003108 do_toggle(i);
3109 keyhandled = 1;
3110 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00003111 }
3112#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003113#ifdef DEBUG
3114 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
3115 kbinput);
3116#endif
3117 break;
3118 }
3119 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003120 /* If the modify_control_seq is set, we received an Alt-Alt
3121 sequence before this, so we make this key a control sequence
3122 by subtracting 64 or 96, depending on its value. */
3123 if (!keyhandled && modify_control_seq) {
3124 if (kbinput >= 'A' && kbinput < 'a')
3125 kbinput -= 64;
3126 else if (kbinput >= 'a' && kbinput <= 'z')
3127 kbinput -= 96;
3128
3129 modify_control_seq = 0;
3130 }
3131
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003132 /* Look through the main shortcut list to see if we've hit a
3133 shortcut key */
Chris Allegretta2cd72b62001-10-24 17:25:36 +00003134 for (i = 0; i < MAIN_LIST_LEN && !keyhandled; i++) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003135 if (kbinput == main_list[i].val ||
3136 (main_list[i].misc1 && kbinput == main_list[i].misc1) ||
3137 (main_list[i].misc2 && kbinput == main_list[i].misc2)) {
3138 if (ISSET(VIEW_MODE) && !main_list[i].viewok)
3139 print_view_warning();
3140 else
3141 main_list[i].func();
3142 keyhandled = 1;
3143 }
3144 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003145 /* If we're in raw mode or using Alt-Alt-x, we have to catch
3146 Control-S and Control-Q */
Chris Allegretta9239d742000-09-06 15:19:18 +00003147 if (kbinput == 17 || kbinput == 19)
3148 keyhandled = 1;
3149
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003150 /* Catch ^Z by hand when triggered also */
Chris Allegretta9239d742000-09-06 15:19:18 +00003151 if (kbinput == 26) {
3152 if (ISSET(SUSPEND))
3153 do_suspend(0);
3154 keyhandled = 1;
3155 }
Chris Allegretta9239d742000-09-06 15:19:18 +00003156
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003157
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003158#ifndef USE_SLANG
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003159 /* Hack, make insert key do something useful, like insert file */
3160 if (kbinput == KEY_IC) {
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003161#else
3162 if (0) {
3163#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003164 do_insertkey:
3165
3166#ifdef ENABLE_MULTIBUFFER
3167 do_insertfile(ISSET(MULTIBUFFER));
3168#else
3169 do_insertfile(0);
3170#endif
3171
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003172 keyhandled = 1;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003173 }
3174
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003175 /* Last gasp, stuff that's not in the main lists */
3176 if (!keyhandled)
3177 switch (kbinput) {
Chris Allegretta84de5522001-04-12 14:51:48 +00003178#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003179#ifdef NCURSES_MOUSE_VERSION
3180 case KEY_MOUSE:
3181 do_mouse();
3182 break;
3183#endif
3184#endif
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003185
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003186 case 0: /* Erg */
Chris Allegretta48ebb812001-10-24 01:34:15 +00003187#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003188 do_next_word();
3189 break;
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003190#endif
Chris Allegrettaf4f7e042001-01-04 16:56:15 +00003191
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003192 case -1: /* Stuff that we don't want to do squat */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003193 case 410: /* Must ignore this, it gets sent when we resize */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003194 case 29: /* Ctrl-] */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003195#ifdef PDCURSES
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003196 case 541: /* ???? */
3197 case 542: /* Control and alt in Windows *shrug* */
Chris Allegretta72623582000-11-29 23:43:28 +00003198 case 543: /* Right ctrl key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003199 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +00003200 case 545: /* Right alt key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003201#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003202
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003203 break;
3204 default:
3205#ifdef DEBUG
3206 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
3207#endif
3208 /* We no longer stop unhandled sequences so that people with
3209 odd character sets can type... */
3210
3211 if (ISSET(VIEW_MODE)) {
3212 print_view_warning();
3213 break;
3214 }
3215 do_char(kbinput);
3216 }
Chris Allegretta7fdbd052001-10-02 00:55:38 +00003217 if (ISSET(DISABLE_CURPOS))
3218 UNSET(DISABLE_CURPOS);
3219 else if (ISSET(CONSTUPDATE))
Chris Allegrettab3655b42001-10-22 03:15:31 +00003220 if (constcheck != current->lineno + current_x + current_y + totsize)
Chris Allegretta756f2202000-09-01 13:32:47 +00003221 do_cursorpos();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003222
3223 reset_cursor();
3224 wrefresh(edit);
3225 keyhandled = 0;
3226 }
3227
3228 getchar();
3229 finish(0);
3230
3231}