blob: 0f520c1dcf7d5b2f4049b24127e53b3d0a80e6f5 [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
861 i++;
862 if (i != 0)
863 break;
864
865 }
866 if (fileptr->prev != NULL)
Chris Allegrettae59fc822001-10-24 18:07:58 +0000867 i = strlen(fileptr->prev->data);
Chris Allegretta878ced32001-10-22 20:05:34 +0000868 else if (fileptr == fileage && filebot != NULL) {
869 current_x = 0;
870 return;
871 }
Chris Allegretta76e291b2001-10-14 19:05:10 +0000872 }
873 if (fileptr == NULL)
874 current = fileage;
875 else
876 current = fileptr;
877
878 current_x = i;
879 placewewant = xplustabs();
880
881 if (current->lineno <= edittop->lineno)
882 edit_update(current, CENTER);
883 else {
884 /* If we've jumped lines, refresh the old line. We can't just use
885 * current->prev here, because we may have skipped over some blank
886 * lines, in which case the previous line is the wrong one.
887 */
888 if (current != old)
889 update_line(old, 0);
890
891 update_line(current, current_x);
892 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000893
894}
Chris Allegrettaad3f4782001-10-02 03:54:13 +0000895#endif /* NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000896
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000897#ifndef DISABLE_WRAPPING
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000898void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000899{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000900 int i = 0; /* Index into ->data for line. */
901 int i_tabs = 0; /* Screen position of ->data[i]. */
902 int last_word_end = -1; /* Location of end of last word found. */
903 int current_word_start = -1; /* Location of start of current word. */
904 int current_word_start_t = -1; /* Location of start of current word screen position. */
905 int current_word_end = -1; /* Location of end of current word */
906 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000907 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000908
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000909 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000910 int right = 0;
911 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000912
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000913 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000914
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000915 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000916 if (!isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000917 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000918
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000919 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000920 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000921
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000922 while (!isspace((int) inptr->data[i])
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000923 && inptr->data[i]) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000924 i++;
925 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000926 if (inptr->data[i] < 32)
927 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000928 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000929
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000930 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000931 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000932 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000933 } else {
934 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000935 current_word_end_t = i_tabs - 1;
936 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000937 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000938
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000939 if (inptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000940 if (i_tabs % tabsize != 0);
941 i_tabs += tabsize - (i_tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000942 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000943
Adam Rogoyski09f97962000-06-20 02:50:33 +0000944 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000945 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000946 }
947
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000948 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000949 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000950 * a) one word takes up the whole line with no starting spaces.
951 * - do nothing and return.
952 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000953 * - word starts new line.
954 * - keep white space on original line up to the cursor.
955 * *) cursor is after word at wrap point
956 * - either it's all white space after word, and this routine isn't called.
957 * - or we are actually in case 2 (2 words).
958 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000959 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000960 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000961 * - white space at end of original line is cleared, unless
962 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000963 * b) cursor is at the word at the wrap point.
964 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000965 * - white space on original line is kept to where cursor was.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000966 * c) cursor is past the word at the wrap point.
967 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000968 * - white space at end of original line is cleared
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000969 */
970
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000971 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000972
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000973 /* Category 1a: one word taking up the whole line with no beginning spaces. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000974 if ((last_word_end == -1) && (!isspace((int) inptr->data[0]))) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000975 for (i = current_word_end; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000976 if (!isspace((int) inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000977 current_word_start = i;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000978 while (!isspace((int) inptr->data[i]) && (i < len)) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000979 i++;
980 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000981 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000982 current_word_end = i;
983 break;
984 }
985 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000986
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000987 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000988 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000989 return;
990 }
991 if (current_x >= last_word_end) {
992 right = (current_x - current_word_start) + 1;
993 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000994 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000995 }
996
Chris Allegretta88b09152001-05-17 11:35:43 +0000997 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000998 strcpy(temp->data, &inptr->data[current_word_start]);
999 inptr->data = nrealloc(inptr->data, last_word_end + 2);
1000 inptr->data[last_word_end + 1] = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001001 } else
1002 /* Category 1b: one word on the line and word not taking up whole line
1003 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001004 if (last_word_end == -1) {
Chris Allegretta88b09152001-05-17 11:35:43 +00001005 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001006 strcpy(temp->data, &inptr->data[current_word_start]);
1007
1008 /* Inside word, remove it from original, and move cursor to right spot. */
1009 if (current_x >= current_word_start) {
1010 right = current_x - current_word_start;
Chris Allegretta56214c62001-09-27 02:46:53 +00001011
1012 /* Decrease totsize by the number of spaces we removed, less
1013 one for the new line we're replacing the spaces with. */
1014 totsize -= (current_word_start - 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001015 current_x = 0;
Chris Allegrettaff989832001-09-17 13:48:00 +00001016#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001017 if (ISSET(AUTOINDENT)) {
1018 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001019 while ((inptr->next->data[i] == ' '
1020 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001021 i++;
1022 right++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001023 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001024 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001025#endif
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001026 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001027 }
1028
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001029 null_at(&inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001030
1031 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
1032 mark_beginbuf = temp;
1033 mark_beginx = 0;
1034 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001035 }
1036
1037 /* Category 2: two or more words on the line. */
1038 else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001039 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001040 if (current_x < current_word_start) {
1041 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001042 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001043 strcpy(temp->data, &inptr->data[current_word_start]);
1044
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001045 if (!isspace((int) input_char)) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001046 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001047
1048 /* Decrement totsize each time we remove a space. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001049 while (isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001050 i--;
Chris Allegretta56214c62001-09-27 02:46:53 +00001051 totsize--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001052 assert(i >= 0);
1053 }
Chris Allegretta56214c62001-09-27 02:46:53 +00001054 /* And increment it to account for the blank line we're
1055 replacing the spaces with. */
1056 totsize++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001057 } else if (current_x <= last_word_end)
1058 i = last_word_end - 1;
1059 else
1060 i = current_x;
1061
1062 inptr->data = nrealloc(inptr->data, i + 2);
1063 inptr->data[i + 1] = 0;
1064 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001065
1066
1067 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001068 else if ((current_x >= current_word_start)
1069 && (current_x <= (current_word_end + 1))) {
1070 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001071 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001072 strcpy(temp->data, &inptr->data[current_word_start]);
1073
1074 down = 1;
1075
1076 right = current_x - current_word_start;
Chris Allegrettaff989832001-09-17 13:48:00 +00001077#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001078 if (ISSET(AUTOINDENT)) {
1079 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001080 while ((inptr->next->data[i] == ' '
1081 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001082 i++;
1083 right++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001084 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001085 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001086#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001087 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001088 current_x = current_word_start;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001089
Chris Allegrettafa0c6962001-10-22 23:22:19 +00001090 null_at(&inptr->data, current_word_start);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001091
Chris Allegretta56214c62001-09-27 02:46:53 +00001092 /* Increment totsize to account for the new line that
1093 will be added below, so that it won't end up being
1094 short by one. */
1095 totsize++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001096 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001097
1098
1099 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001100 else {
1101 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001102 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001103 strcpy(temp->data, &inptr->data[current_word_start]);
1104
1105 down = 1;
1106 right = current_x - current_word_start;
1107
1108 current_x = current_word_start;
1109 i = current_word_start - 1;
1110
Chris Allegretta56214c62001-09-27 02:46:53 +00001111 /* Decrement totsize each time we remove a space. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001112 while (isspace((int) inptr->data[i])) {
Adam Rogoyski3d449b42000-06-19 17:30:14 +00001113 i--;
Chris Allegretta56214c62001-09-27 02:46:53 +00001114 totsize--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001115 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001116 inptr->data = nrealloc(inptr->data, i + 2);
1117 inptr->data[i + 1] = 0;
1118 }
Chris Allegretta56214c62001-09-27 02:46:53 +00001119 /* And increment it to account for the blank line we're
1120 replacing the spaces with. */
1121 totsize++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001122 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001123 }
1124
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001125 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001126 if (ISSET(SAMELINEWRAP) && inptr->next) {
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001127 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001128
Chris Allegretta94a78b82001-03-14 08:28:48 +00001129 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001130 char *p =
Chris Allegretta88b09152001-05-17 11:35:43 +00001131 charalloc((strlen(temp->data) + strlen(inptr->next->data) + 2));
Chris Allegretta94a78b82001-03-14 08:28:48 +00001132
Chris Allegretta56214c62001-09-27 02:46:53 +00001133 /* We're adding to an existing line instead of creating a new
1134 one; decrement totlines here so that when it gets incremented
1135 below, it won't end up being high by one. */
1136 totlines--;
1137
Chris Allegrettaff989832001-09-17 13:48:00 +00001138#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001139 if (ISSET(AUTOINDENT)) {
1140 int non = 0;
1141
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001142 /* Grab the beginning of the next line until it's not a
1143 space or tab, then null terminate it so we can strcat it
1144 to hell */
1145 while ((inptr->next->data[non] == ' '
Chris Allegretta355fbe52001-07-14 19:32:47 +00001146 || inptr->next->data[non] == '\t')) {
1147 p[non] = inptr->next->data[non];
1148 non++;
1149 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001150 p[non] = 0;
1151 strcat(p, temp->data);
1152 strcat(p, " ");
1153
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001154 /* Now tack on the rest of the next line after the spaces and
1155 tabs */
Chris Allegretta94a78b82001-03-14 08:28:48 +00001156 strcat(p, &inptr->next->data[non]);
Chris Allegrettaff989832001-09-17 13:48:00 +00001157 } else
1158#endif
1159 {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001160 strcpy(p, temp->data);
1161 strcat(p, " ");
1162 strcat(p, inptr->next->data);
1163 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001164
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001165 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001166 inptr->next->data = p;
1167
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001168 free(temp->data);
1169 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001170
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001171 current_x = old_x;
1172 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001173 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001174 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001175 else {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001176
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001177 temp->prev = inptr;
1178 temp->next = inptr->next;
1179
1180 if (inptr->next)
1181 inptr->next->prev = temp;
1182 inptr->next = temp;
1183
1184 if (!temp->next)
1185 filebot = temp;
1186
1187 SET(SAMELINEWRAP);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001188
Chris Allegrettaff989832001-09-17 13:48:00 +00001189#ifndef NANO_SMALL
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001190 if (ISSET(AUTOINDENT)) {
1191 char *spc = inptr->data;
1192 char *t = NULL;
1193 int extra = 0;
1194 if (spc) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001195 while ((*spc == ' ') || (*spc == '\t')) {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001196 extra++;
1197 spc++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001198 totsize++;
1199 }
Chris Allegretta88b09152001-05-17 11:35:43 +00001200 t = charalloc(strlen(temp->data) + extra + 1);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001201 strncpy(t, inptr->data, extra);
1202 strcpy(t + extra, temp->data);
1203 free(temp->data);
1204 temp->data = t;
1205 }
1206 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001207#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001208 }
1209
1210
1211 totlines++;
Chris Allegretta88520c92001-05-05 17:45:54 +00001212 /* Everything about it makes me want this line here, but it causes
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001213 * totsize to be high by one for some reason. Sigh. (Rob) */
1214 /* totsize++; */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001215
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001216 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001217 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001218
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001219
1220 /* Move the cursor to the new line if appropriate. */
1221 if (down) {
1222 do_right();
1223 }
1224
1225 /* Move the cursor to the correct spot in the line if appropriate. */
1226 while (right--) {
1227 do_right();
1228 }
1229
Chris Allegretta234a34d2000-07-29 04:33:38 +00001230 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001231 reset_cursor();
1232 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001233}
1234
1235/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001236void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001237{
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001238 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001239#ifdef DEBUG
1240 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
1241 inptr->data);
1242#endif
1243
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001244 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001245 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001246 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001247 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001248
1249 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001250 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001251
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001252 while (isspace((int) inptr->data[i]) && inptr->data[i])
Adam Rogoyski09f97962000-06-20 02:50:33 +00001253 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001254
Adam Rogoyski09f97962000-06-20 02:50:33 +00001255 if (!inptr->data[i])
1256 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001257
Adam Rogoyski09f97962000-06-20 02:50:33 +00001258 /* String must be at least 1 character long. */
1259 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001260 if (isspace((int) inptr->data[i])) {
Adam Rogoyski09f97962000-06-20 02:50:33 +00001261 if (!char_found)
1262 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001263 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001264 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001265 } else
1266 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001267 }
Adam Rogoyski09f97962000-06-20 02:50:33 +00001268
1269 if (char_found == 2)
1270 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001271 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001272}
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001273#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001274
1275/* Stuff we do when we abort from programs and want to clean up the
Chris Allegretta88520c92001-05-05 17:45:54 +00001276 * screen. This doesn't do much right now.
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001277 */
1278void do_early_abort(void)
1279{
1280 blank_statusbar_refresh();
1281}
1282
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001283int do_backspace(void)
1284{
1285 filestruct *previous, *tmp;
1286
1287 if (current_x != 0) {
1288 /* Let's get dangerous */
1289 memmove(&current->data[current_x - 1], &current->data[current_x],
1290 strlen(current->data) - current_x + 1);
1291#ifdef DEBUG
1292 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
1293#endif
1294 align(&current->data);
1295 do_left();
1296 } else {
1297 if (current == fileage)
1298 return 0; /* Can't delete past top of file */
1299
1300 previous = current->prev;
1301 current_x = strlen(previous->data);
1302 previous->data = nrealloc(previous->data,
1303 strlen(previous->data) +
1304 strlen(current->data) + 1);
1305 strcat(previous->data, current->data);
1306
1307 tmp = current;
1308 unlink_node(current);
1309 delete_node(current);
1310 if (current == edittop) {
1311 if (previous->next)
1312 current = previous->next;
1313 else
1314 current = previous;
Chris Allegretta3e3ae942001-09-22 19:02:04 +00001315 page_up();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001316 } else {
1317 if (previous->next)
1318 current = previous->next;
1319 else
1320 current = previous;
1321 update_line(current, current_x);
1322 }
1323
1324 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001325 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001326 filebot = current;
1327 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001328
1329 /* Recreate the magic line if we're deleting it AND if the
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001330 line we're on now is NOT blank. if it is blank we
1331 can just use IT for the magic line. This is how Pico
1332 appears to do it, in any case */
Chris Allegretta28a0f892000-07-05 22:47:54 +00001333 if (strcmp(current->data, "")) {
1334 new_magicline();
1335 fix_editbot();
1336 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001337 }
1338
1339 current = previous;
1340 renumber(current);
1341 previous_line();
1342 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001343#ifdef DEBUG
1344 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
1345#endif
1346
1347 }
1348
1349 totsize--;
1350 set_modified();
1351 UNSET(KEEP_CUTBUFFER);
1352 edit_refresh();
1353 return 1;
1354}
1355
1356int do_delete(void)
1357{
1358 filestruct *foo;
1359
1360 if (current_x != strlen(current->data)) {
1361 /* Let's get dangerous */
1362 memmove(&current->data[current_x], &current->data[current_x + 1],
1363 strlen(current->data) - current_x);
1364
1365 align(&current->data);
1366
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001367 /* Now that we have a magic lnie again, we can check for both being
1368 on the line before filebot as well as at filebot */
Chris Allegretta4ed13152001-02-10 17:50:50 +00001369 } else if (current->next != NULL && current->next != filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001370 current->data = nrealloc(current->data,
1371 strlen(current->data) +
1372 strlen(current->next->data) + 1);
1373 strcat(current->data, current->next->data);
1374
1375 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001376 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001377 filebot = current;
1378 editbot = current;
1379 }
1380
1381 unlink_node(foo);
1382 delete_node(foo);
1383 update_line(current, current_x);
1384
Chris Allegretta4ed13152001-02-10 17:50:50 +00001385 /* Please see the comment in do_backspace if you don't understand
Chris Allegretta28a0f892000-07-05 22:47:54 +00001386 this test */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001387 if (current == filebot && strcmp(current->data, "")) {
Chris Allegretta28a0f892000-07-05 22:47:54 +00001388 new_magicline();
1389 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001390 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001391 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001392 renumber(current);
1393 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001394 } else
1395 return 0;
1396
1397 totsize--;
1398 set_modified();
1399 UNSET(KEEP_CUTBUFFER);
1400 edit_refresh();
1401 return 1;
1402}
1403
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001404void wrap_reset(void)
1405{
1406 UNSET(SAMELINEWRAP);
1407}
1408
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001409#ifndef DISABLE_SPELLER
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001410
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001411int do_int_spell_fix(char *word)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001412{
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001413 char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001414 filestruct *begin;
1415 int i = 0, j = 0, beginx, beginx_top;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001416
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001417 /* save where we are */
1418 begin = current;
1419 beginx = current_x + 1;
1420
1421 /* save the current search/replace strings */
1422 search_init_globals();
1423 save_search = mallocstrcpy(save_search, last_search);
1424 save_replace = mallocstrcpy(save_replace, last_replace);
1425
1426 /* set search/replace strings to mis-spelt word */
1427 prevanswer = mallocstrcpy(prevanswer, word);
1428 last_search = mallocstrcpy(last_search, word);
1429 last_replace = mallocstrcpy(last_replace, word);
1430
1431 /* start from the top of file */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001432 current = fileage;
1433 current_x = beginx_top = -1;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001434
1435 search_last_line = FALSE;
1436
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001437 edit_update(fileage, TOP);
1438
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001439 /* make sure word is still mis-spelt (i.e. when multi-errors) */
Chris Allegretta8d990b52001-09-22 22:14:25 +00001440 if (findnextstr(TRUE, FALSE, fileage, beginx_top, prevanswer) != NULL) {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001441 do_replace_highlight(TRUE, prevanswer);
1442
1443 /* allow replace word to be corrected */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001444 i = statusq(0, spell_list, SPELL_LIST_LEN, last_replace,
1445 _("Edit a replacement"));
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001446
1447 do_replace_highlight(FALSE, prevanswer);
1448
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001449 /* start from the start of this line again */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001450 current = fileage;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001451 current_x = beginx_top;
1452
1453 search_last_line = FALSE;
1454
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001455 j = i;
1456 do_replace_loop(prevanswer, fileage, &beginx_top, TRUE, &j);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001457 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001458
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001459 /* restore the search/replace strings */
1460 last_search = mallocstrcpy(last_search, save_search);
1461 last_replace = mallocstrcpy(last_replace, save_replace);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001462
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001463 /* restore where we were */
1464 current = begin;
1465 current_x = beginx - 1;
1466
1467 edit_update(current, CENTER);
1468
1469 if (i == -1)
1470 return FALSE;
1471
1472 return TRUE;
1473}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001474
1475/* Integrated spell checking using 'spell' program */
Chris Allegretta271e9722000-11-10 18:15:43 +00001476int do_int_speller(char *tempfile_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001477{
Chris Allegretta271e9722000-11-10 18:15:43 +00001478 char *read_buff, *read_buff_ptr, *read_buff_word;
1479 long pipe_buff_size;
1480 int in_fd[2], tempfile_fd;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001481 int spell_status;
1482 pid_t pid_spell;
1483 ssize_t bytesread;
1484
Chris Allegretta271e9722000-11-10 18:15:43 +00001485 /* Create a pipe to spell program */
1486
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001487 if (pipe(in_fd) == -1)
1488 return FALSE;
1489
Chris Allegretta271e9722000-11-10 18:15:43 +00001490 /* A new process to run spell in */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001491
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001492 if ((pid_spell = fork()) == 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001493
1494 /* Child continues, (i.e. future spell process) */
1495
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001496 close(in_fd[0]);
1497
Chris Allegretta271e9722000-11-10 18:15:43 +00001498 /* replace the standard in with the tempfile */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001499
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001500 if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001501
1502 close(in_fd[1]);
1503 exit(1);
1504 }
1505
1506 if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
1507
1508 close(tempfile_fd);
1509 close(in_fd[1]);
1510 exit(1);
1511 }
1512 close(tempfile_fd);
1513
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001514
Chris Allegretta271e9722000-11-10 18:15:43 +00001515 /* send spell's standard out to the pipe */
1516
1517 if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1518
1519 close(in_fd[1]);
1520 exit(1);
1521 }
1522 close(in_fd[1]);
1523
1524 /* Start spell program, we are using the PATH here!?!? */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001525 execlp("spell", "spell", NULL);
1526
Chris Allegretta271e9722000-11-10 18:15:43 +00001527 /* Should not be reached, if spell is found!!! */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001528
Chris Allegretta271e9722000-11-10 18:15:43 +00001529 exit(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001530 }
1531
1532 /* Parent continues here */
1533
Chris Allegretta271e9722000-11-10 18:15:43 +00001534 close(in_fd[1]);
1535
1536 /* Child process was not forked successfully */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001537
1538 if (pid_spell < 0) {
1539
Chris Allegretta271e9722000-11-10 18:15:43 +00001540 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001541 return FALSE;
1542 }
1543
Chris Allegretta271e9722000-11-10 18:15:43 +00001544 /* Get system pipe buffer size */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001545
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001546 if ((pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001547
Chris Allegretta271e9722000-11-10 18:15:43 +00001548 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001549 return FALSE;
Chris Allegretta271e9722000-11-10 18:15:43 +00001550 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001551
Chris Allegretta88b09152001-05-17 11:35:43 +00001552 read_buff = charalloc(pipe_buff_size + 1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001553
Chris Allegretta271e9722000-11-10 18:15:43 +00001554 /* Process the returned spelling errors */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001555
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001556 while ((bytesread = read(in_fd[0], read_buff, pipe_buff_size)) > 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001557
Chris Allegretta271e9722000-11-10 18:15:43 +00001558 read_buff[bytesread] = (char) NULL;
1559 read_buff_word = read_buff_ptr = read_buff;
1560
1561 while (*read_buff_ptr != (char) NULL) {
1562
1563 /* Windows version may need to process additional char '\r' */
1564
1565 /* Possible problem here if last word not followed by '\n' */
1566
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001567 if (*read_buff_ptr == '\n') {
Chris Allegretta271e9722000-11-10 18:15:43 +00001568 *read_buff_ptr = (char) NULL;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001569 if (!do_int_spell_fix(read_buff_word)) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001570
1571 close(in_fd[0]);
1572 free(read_buff);
1573 replace_abort();
1574
1575 return TRUE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001576 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001577 read_buff_word = read_buff_ptr;
1578 read_buff_word++;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001579 }
1580
1581 read_buff_ptr++;
1582 }
1583 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001584
1585 close(in_fd[0]);
1586 free(read_buff);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001587 replace_abort();
1588
Chris Allegretta271e9722000-11-10 18:15:43 +00001589 /* Process end of spell process */
1590
1591 wait(&spell_status);
1592 if (WIFEXITED(spell_status)) {
1593 if (WEXITSTATUS(spell_status) != 0)
1594 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001595 } else
Chris Allegretta271e9722000-11-10 18:15:43 +00001596 return FALSE;
1597
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001598 return TRUE;
1599}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001600
1601/* External spell checking */
Chris Allegretta271e9722000-11-10 18:15:43 +00001602int do_alt_speller(char *file_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001603{
Chris Allegrettab3655b42001-10-22 03:15:31 +00001604 int alt_spell_status, lineno_cur = current->lineno;
1605 int x_cur = current_x, y_cur = current_y, pww_cur = placewewant;
1606
Chris Allegretta271e9722000-11-10 18:15:43 +00001607 pid_t pid_spell;
Chris Allegretta169ee842001-01-26 01:57:32 +00001608 char *ptr;
1609 static int arglen = 3;
1610 static char **spellargs = (char **) NULL;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001611
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001612 endwin();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001613
Chris Allegrettae434b452001-01-27 19:25:00 +00001614 /* Set up an argument list to pass the execvp function */
1615 if (spellargs == NULL) {
1616 spellargs = nmalloc(arglen * sizeof(char *));
Chris Allegretta271e9722000-11-10 18:15:43 +00001617
Chris Allegrettae434b452001-01-27 19:25:00 +00001618 spellargs[0] = strtok(alt_speller, " ");
1619 while ((ptr = strtok(NULL, " ")) != NULL) {
1620 arglen++;
1621 spellargs = nrealloc(spellargs, arglen * sizeof(char *));
1622 spellargs[arglen - 3] = ptr;
Chris Allegretta169ee842001-01-26 01:57:32 +00001623 }
Chris Allegrettae434b452001-01-27 19:25:00 +00001624 spellargs[arglen - 1] = NULL;
1625 }
1626 spellargs[arglen - 2] = file_name;
1627
1628 /* Start a new process for the alternate speller */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001629 if ((pid_spell = fork()) == 0) {
Chris Allegretta169ee842001-01-26 01:57:32 +00001630
Chris Allegretta88520c92001-05-05 17:45:54 +00001631 /* Start alternate spell program; we are using the PATH here!?!? */
Chris Allegretta169ee842001-01-26 01:57:32 +00001632 execvp(spellargs[0], spellargs);
Chris Allegretta271e9722000-11-10 18:15:43 +00001633
1634 /* Should not be reached, if alternate speller is found!!! */
1635
1636 exit(1);
1637 }
1638
1639 /* Could not fork?? */
1640
1641 if (pid_spell < 0)
1642 return FALSE;
1643
1644 /* Wait for alternate speller to complete */
1645
1646 wait(&alt_spell_status);
1647 if (WIFEXITED(alt_spell_status)) {
1648 if (WEXITSTATUS(alt_spell_status) != 0)
1649 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001650 } else
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001651 return FALSE;
1652
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001653 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001654 free_filestruct(fileage);
Chris Allegretta56214c62001-09-27 02:46:53 +00001655 global_init(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001656 open_file(file_name, 0, 1);
Rocco Corsi4dfaf932001-04-20 01:59:55 +00001657
Chris Allegretta1b3381b2001-09-28 21:59:01 +00001658 /* go back to the old position, mark the file as modified, and make
1659 sure that the titlebar is refreshed */
1660 do_gotopos(lineno_cur, x_cur, y_cur, pww_cur);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001661 set_modified();
Chris Allegrettae1f14522001-09-19 03:19:43 +00001662 clearok(topwin, FALSE);
1663 titlebar(NULL);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001664
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001665 return TRUE;
1666}
1667#endif
1668
1669int do_spell(void)
1670{
1671
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001672#ifdef DISABLE_SPELLER
Chris Allegrettaff269f82000-12-01 18:46:01 +00001673 nano_disabled_msg();
1674 return (TRUE);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001675#else
Chris Allegretta271e9722000-11-10 18:15:43 +00001676 char *temp;
1677 int spell_res;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001678
Chris Allegretta271e9722000-11-10 18:15:43 +00001679 if ((temp = tempnam(0, "nano.")) == NULL) {
1680 statusbar(_("Could not create a temporary filename: %s"),
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001681 strerror(errno));
Chris Allegretta271e9722000-11-10 18:15:43 +00001682 return 0;
1683 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001684
Chris Allegrettaecc3d7f2001-06-05 23:24:55 +00001685 if (write_file(temp, 1, 0, 0) == -1) {
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001686 statusbar(_("Spell checking failed: unable to write temp file!"));
Chris Allegretta271e9722000-11-10 18:15:43 +00001687 return 0;
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001688 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001689
Chris Allegrettae1f14522001-09-19 03:19:43 +00001690#ifdef ENABLE_MULTIBUFFER
1691 /* update the current open_files entry before spell-checking, in case
1692 any problems occur; the case of there being no open_files entries
1693 is handled elsewhere (before we reach this point); no duplicate
1694 checking is needed here */
1695 add_open_file(1, 0);
1696#endif
1697
Chris Allegretta271e9722000-11-10 18:15:43 +00001698 if (alt_speller)
1699 spell_res = do_alt_speller(temp);
1700 else
1701 spell_res = do_int_speller(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001702
Chris Allegretta271e9722000-11-10 18:15:43 +00001703 remove(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001704
1705 if (spell_res)
1706 statusbar(_("Finished checking spelling"));
1707 else
1708 statusbar(_("Spell checking failed"));
1709
1710 return spell_res;
1711
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001712#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001713}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001714
1715int do_exit(void)
1716{
1717 int i;
1718
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001719 if (!ISSET(MODIFIED)) {
1720
Chris Allegretta355fbe52001-07-14 19:32:47 +00001721#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001722 if (!close_open_file()) {
1723 display_main_list();
1724 return 1;
1725 }
1726 else
1727#endif
1728
1729 finish(0);
1730 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001731
Chris Allegretta30885552000-07-14 01:20:12 +00001732 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001733 i = 1;
1734 } else {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001735 i = do_yesno(0, 0,
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001736 _
1737 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1738 }
1739
1740#ifdef DEBUG
1741 dump_buffer(fileage);
1742#endif
1743
1744 if (i == 1) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001745 if (do_writeout(filename, 1, 0) > 0) {
1746
Chris Allegretta355fbe52001-07-14 19:32:47 +00001747#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001748 if (!close_open_file()) {
1749 display_main_list();
1750 return 1;
1751 }
1752 else
1753#endif
1754
1755 finish(0);
1756 }
1757 } else if (i == 0) {
1758
Chris Allegretta355fbe52001-07-14 19:32:47 +00001759#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001760 if (!close_open_file()) {
1761 display_main_list();
1762 return 1;
1763 }
1764 else
1765#endif
1766
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001767 finish(0);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001768 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001769 statusbar(_("Cancelled"));
1770
1771 display_main_list();
1772 return 1;
1773}
1774
Chris Allegretta84de5522001-04-12 14:51:48 +00001775#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001776#ifdef NCURSES_MOUSE_VERSION
1777void do_mouse(void)
1778{
1779 MEVENT mevent;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001780 int foo = 0, tab_found = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001781
1782 if (getmouse(&mevent) == ERR)
1783 return;
1784
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001785 /* If mouse not in edit or bottom window, return */
1786 if (wenclose(edit, mevent.y, mevent.x)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001787
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001788 /* Don't let people screw with the marker when they're in a
1789 subfunction */
1790 if (currshortcut != main_list)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001791 return;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001792
1793 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1794 mevent.y -= 2;
1795
1796 /* Selecting where the cursor is sets the mark.
1797 * Selecting beyond the line length with the cursor at the end of the
1798 * line sets the mark as well.
1799 */
1800 if ((mevent.y == current_y) &&
1801 ((mevent.x == current_x) || (current_x == strlen(current->data)
1802 && (mevent.x >
1803 strlen(current->data))))) {
1804 if (ISSET(VIEW_MODE)) {
1805 print_view_warning();
1806 return;
1807 }
1808 do_mark();
1809 } else if (mevent.y > current_y) {
1810 while (mevent.y > current_y) {
1811 if (current->next != NULL)
1812 current = current->next;
1813 else
1814 break;
1815 current_y++;
1816 }
1817 } else if (mevent.y < current_y) {
1818 while (mevent.y < current_y) {
1819 if (current->prev != NULL)
1820 current = current->prev;
1821 else
1822 break;
1823 current_y--;
1824 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001825 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001826 current_x = mevent.x;
1827 placewewant = current_x;
1828 while (foo < current_x) {
1829 if (current->data[foo] == NANO_CONTROL_I) {
1830 current_x -= tabsize - (foo % tabsize);
1831 tab_found = 1;
1832 } else if (current->data[foo] & 0x80);
1833 else if (current->data[foo] < 32)
1834 current_x--;
1835 foo++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001836 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001837 /* This is where tab_found comes in. I can't figure out why,
1838 * but without it any line with a tab will place the cursor
1839 * one character behind. Whatever, this fixes it. */
1840 if (tab_found == 1)
1841 current_x++;
1842
1843 if (current_x > strlen(current->data))
1844 current_x = strlen(current->data);
1845
1846 update_cursor();
1847 edit_refresh();
1848 } else if (wenclose(bottomwin, mevent.y, mevent.x) && !ISSET(NO_HELP)) {
Chris Allegrettaa951f212001-09-27 21:07:39 +00001849
1850 int k, val = 0;
1851
1852 if (currslen < 2)
1853 k = COLS / 6;
1854 else
1855 k = COLS / ((currslen + (currslen %2)) / 2);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001856
1857 /* Determine what shortcut list was clicked */
1858 mevent.y -= (editwinrows + 3);
1859
1860 if (mevent.y < 0) /* They clicked on the statusbar */
1861 return;
1862
1863 /* Don't select stuff beyond list length */
1864 if (mevent.x / k >= currslen)
1865 return;
1866
1867 val = currshortcut[(mevent.x / k) * 2 + mevent.y].val;
1868
1869 /* And ungetch that value */
1870 ungetch(val);
Chris Allegretta6414b402001-09-21 03:21:11 +00001871
1872 /* And if it's an alt-key sequence, we should probably send alt
1873 too ;-) */
1874 if (val >= 'a' && val <= 'z')
1875 ungetch(27);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001876 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001877}
1878#endif
1879#endif
1880
1881/* Handler for SIGHUP */
1882RETSIGTYPE handle_hup(int signal)
1883{
Chris Allegrettae7a58932000-12-02 02:36:22 +00001884 die(_("Received SIGHUP"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001885}
1886
Chris Allegretta18f8be02000-09-04 03:20:38 +00001887/* What do we do when we catch the suspend signal */
1888RETSIGTYPE do_suspend(int signal)
1889{
Chris Allegretta18f8be02000-09-04 03:20:38 +00001890 endwin();
Chris Allegretta521e00d2001-06-28 16:52:52 +00001891 printf("\n\n\n\n\nUse \"fg\" to return to nano\n");
1892 fflush(stdout);
1893
1894 /* We used to re-enable the default SIG_DFL and raise SIGTSTP, but
1895 then we could be (and were) interrupted in the middle of the call.
1896 So we do it the mutt way instead */
1897 kill(0, SIGSTOP);
Chris Allegretta18f8be02000-09-04 03:20:38 +00001898}
1899
1900/* Restore the suspend handler when we come back into the prog */
1901RETSIGTYPE do_cont(int signal)
1902{
1903
Chris Allegretta521e00d2001-06-28 16:52:52 +00001904 /* Now we just update the screen instead of having to reenable the
1905 SIGTSTP handler */
1906
Chris Allegretta521e00d2001-06-28 16:52:52 +00001907 doupdate();
Chris Allegretta18f8be02000-09-04 03:20:38 +00001908}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001909
1910void handle_sigwinch(int s)
1911{
1912#ifndef NANO_SMALL
1913 char *tty = NULL;
1914 int fd = 0;
1915 int result = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001916 struct winsize win;
1917
1918 tty = ttyname(0);
1919 if (!tty)
1920 return;
1921 fd = open(tty, O_RDWR);
1922 if (fd == -1)
1923 return;
1924 result = ioctl(fd, TIOCGWINSZ, &win);
1925 if (result == -1)
1926 return;
1927
1928
1929 COLS = win.ws_col;
1930 LINES = win.ws_row;
1931
Chris Allegrettae61e8302001-01-14 05:18:27 +00001932 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1933 die_too_small();
1934
Chris Allegretta6fe61492001-05-21 12:56:25 +00001935#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettae61e8302001-01-14 05:18:27 +00001936 if ((fill = COLS - CHARS_FROM_EOL) < MIN_FILL_LENGTH)
1937 die_too_small();
Chris Allegretta6fe61492001-05-21 12:56:25 +00001938#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001939
Chris Allegretta0a06e072001-01-23 02:35:04 +00001940 hblank = nrealloc(hblank, COLS + 1);
1941 memset(hblank, ' ', COLS);
1942 hblank[COLS] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001943
Chris Allegretta618f5d72001-02-16 04:48:30 +00001944#ifdef HAVE_RESIZETERM
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001945 resizeterm(LINES, COLS);
1946#ifdef HAVE_WRESIZE
1947 if (wresize(topwin, 2, COLS) == ERR)
1948 die(_("Cannot resize top win"));
1949 if (mvwin(topwin, 0, 0) == ERR)
1950 die(_("Cannot move top win"));
1951 if (wresize(edit, editwinrows, COLS) == ERR)
1952 die(_("Cannot resize edit win"));
1953 if (mvwin(edit, 2, 0) == ERR)
1954 die(_("Cannot move edit win"));
1955 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1956 die(_("Cannot resize bottom win"));
1957 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1958 die(_("Cannot move bottom win"));
1959#endif /* HAVE_WRESIZE */
Chris Allegretta618f5d72001-02-16 04:48:30 +00001960#endif /* HAVE_RESIZETERM */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001961
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001962 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001963
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001964 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001965 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001966 }
1967 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00001968
1969 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001970 refresh();
Chris Allegrettaf4b96012001-01-03 07:11:47 +00001971 titlebar(NULL);
Chris Allegretta97accc62000-06-19 05:45:52 +00001972 edit_refresh();
1973 display_main_list();
Chris Allegretta08020882001-01-29 23:37:54 +00001974 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001975 total_refresh();
Chris Allegretta08020882001-01-29 23:37:54 +00001976
Chris Allegretta4e90c402001-01-29 23:40:43 +00001977 /* Turn cursor back on for sure */
1978 curs_set(1);
1979
Chris Allegretta08020882001-01-29 23:37:54 +00001980 /* Jump back to mainloop */
1981 siglongjmp(jmpbuf, 1);
1982
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001983#endif
1984}
1985
Chris Allegretta756f2202000-09-01 13:32:47 +00001986void signal_init(void)
1987{
Chris Allegrettaac899e52001-06-30 04:09:09 +00001988#ifdef _POSIX_VDISABLE
1989 struct termios term;
1990#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00001991
Chris Allegretta88520c92001-05-05 17:45:54 +00001992 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
Chris Allegretta756f2202000-09-01 13:32:47 +00001993 memset(&act, 0, sizeof(struct sigaction));
1994 act.sa_handler = SIG_IGN;
1995 sigaction(SIGINT, &act, NULL);
Chris Allegretta756f2202000-09-01 13:32:47 +00001996
Chris Allegretta88520c92001-05-05 17:45:54 +00001997 /* Trap SIGHUP cuz we want to write the file out. */
Chris Allegretta756f2202000-09-01 13:32:47 +00001998 act.sa_handler = handle_hup;
1999 sigaction(SIGHUP, &act, NULL);
2000
2001 act.sa_handler = handle_sigwinch;
2002 sigaction(SIGWINCH, &act, NULL);
2003
Chris Allegretta521e00d2001-06-28 16:52:52 +00002004 if (!ISSET(SUSPEND)) {
Chris Allegrettaac899e52001-06-30 04:09:09 +00002005
2006/* Insane! */
2007#ifdef _POSIX_VDISABLE
2008 tcgetattr(0, &term);
2009 term.c_cc[VSUSP] = _POSIX_VDISABLE;
2010 tcsetattr(0, TCSANOW, &term);
2011#else
2012 act.sa_handler = SIG_IGN;
Chris Allegretta521e00d2001-06-28 16:52:52 +00002013 sigaction(SIGTSTP, &act, NULL);
Chris Allegrettaac899e52001-06-30 04:09:09 +00002014#endif
2015
Chris Allegretta521e00d2001-06-28 16:52:52 +00002016 } else {
2017 /* if we don't do this, it seems other stuff interrupts the
2018 suspend handler! Try using nano with mutt without this line */
2019 sigfillset(&act.sa_mask);
2020
2021 act.sa_handler = do_suspend;
2022 sigaction(SIGTSTP, &act, NULL);
2023
2024 act.sa_handler = do_cont;
2025 sigaction(SIGCONT, &act, NULL);
2026 }
2027
Chris Allegretta756f2202000-09-01 13:32:47 +00002028}
2029
Chris Allegretta2a42af12000-09-12 23:02:49 +00002030void window_init(void)
2031{
Chris Allegrettae61e8302001-01-14 05:18:27 +00002032 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
2033 die_too_small();
Chris Allegretta92c9dd22000-09-13 14:03:27 +00002034
Chris Allegretta88520c92001-05-05 17:45:54 +00002035 /* Set up the main text window */
Chris Allegretta2a42af12000-09-12 23:02:49 +00002036 edit = newwin(editwinrows, COLS, 2, 0);
2037
2038 /* And the other windows */
2039 topwin = newwin(2, COLS, 0, 0);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002040 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002041
Chris Allegretta155d6202001-01-08 01:50:37 +00002042#ifdef PDCURSES
2043 /* Oops, I guess we need this again.
2044 Moved here so the keypad still works after a Meta-X, for example */
2045 keypad(edit, TRUE);
2046 keypad(bottomwin, TRUE);
2047#endif
2048
Chris Allegretta2a42af12000-09-12 23:02:49 +00002049}
2050
Chris Allegretta756f2202000-09-01 13:32:47 +00002051void mouse_init(void)
2052{
Chris Allegretta84de5522001-04-12 14:51:48 +00002053#ifndef DISABLE_MOUSE
Chris Allegretta756f2202000-09-01 13:32:47 +00002054#ifdef NCURSES_MOUSE_VERSION
2055 if (ISSET(USE_MOUSE)) {
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002056 keypad_on(edit, 1);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002057 keypad_on(bottomwin, 1);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002058
Chris Allegretta756f2202000-09-01 13:32:47 +00002059 mousemask(BUTTON1_RELEASED, NULL);
2060 mouseinterval(50);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00002061
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002062 } else
Chris Allegretta756f2202000-09-01 13:32:47 +00002063 mousemask(0, NULL);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00002064
Chris Allegretta756f2202000-09-01 13:32:47 +00002065#endif
2066#endif
2067
2068}
2069
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002070int do_tab(void)
2071{
2072 do_char('\t');
2073 return 1;
2074}
2075
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002076#ifndef DISABLE_JUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002077int empty_line(const char *data)
2078{
2079 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002080 if (!isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002081 return 0;
2082
2083 data++;
2084 }
2085
2086 return 1;
2087}
2088
2089int no_spaces(const char *data)
2090{
2091 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002092 if (isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002093 return 0;
2094
2095 data++;
2096 }
2097
2098 return 1;
2099}
2100
2101void justify_format(char *data)
2102{
2103 int i = 0;
2104 int len = strlen(data);
2105
2106 /* Skip first character regardless and leading whitespace. */
2107 for (i = 1; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002108 if (!isspace((int) data[i]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002109 break;
2110 }
2111
2112 i++; /* (i) is now at least 2. */
2113
2114 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
2115 for (; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002116 if (isspace((int) data[i]) && isspace((int) data[i - 1])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002117 && (data[i - 2] != '.')) {
2118 memmove(data + i, data + i + 1, len - i);
2119 len--;
2120 i--;
2121 }
2122 }
2123}
2124#endif
2125
2126int do_justify(void)
2127{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002128#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +00002129 nano_disabled_msg();
2130 return 1;
2131#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002132 int slen = 0; /* length of combined lines on one line. */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002133 int initial_y, kbinput = 0, totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002134 filestruct *initial = NULL, *tmpjust = NULL, *cutbak, *tmptop, *tmpbot;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002135
2136 if (empty_line(current->data)) {
2137 /* Justify starting at first non-empty line. */
2138 do {
2139 if (!current->next)
2140 return 1;
2141
2142 current = current->next;
2143 current_y++;
2144 }
2145 while (empty_line(current->data));
2146 } else {
2147 /* Search back for the beginning of the paragraph, where
2148 * Paragraph is 1) A line with leading whitespace
2149 * or 2) A line following an empty line.
2150 */
2151 while (current->prev != NULL) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002152 if (isspace((int) current->data[0]) || !current->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002153 break;
2154
2155 current = current->prev;
2156 current_y--;
2157 }
2158
2159 /* First line with leading whitespace may be empty. */
2160 if (empty_line(current->data)) {
2161 if (current->next) {
2162 current = current->next;
2163 current_y++;
2164 } else
2165 return 1;
2166 }
2167 }
2168 initial = current;
2169 initial_y = current_y;
2170
2171 set_modified();
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002172 cutbak = cutbuffer; /* Got to like cutbak ;) */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002173 totbak = totsize;
Chris Allegretta9149e612000-11-27 00:23:41 +00002174 cutbuffer = NULL;
2175
2176 tmptop = current;
2177 tmpjust = copy_node(current);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002178
2179 /* This is annoying because it mucks with totsize */
Chris Allegretta9149e612000-11-27 00:23:41 +00002180 add_to_cutbuffer(tmpjust);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002181
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002182 /* Put the whole paragraph into one big line. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002183 while (current->next && !isspace((int) current->next->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002184 && current->next->data[0]) {
2185 filestruct *tmpnode = current->next;
2186 int len = strlen(current->data);
2187 int len2 = strlen(current->next->data);
2188
Chris Allegretta9149e612000-11-27 00:23:41 +00002189 tmpjust = NULL;
Chris Allegretta9149e612000-11-27 00:23:41 +00002190 tmpjust = copy_node(current->next);
2191 add_to_cutbuffer(tmpjust);
2192
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002193 /* Wiping out a newline */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002194 totsize--;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002195
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002196 /* length of both strings plus space between strings and ending \0. */
2197 current->data = nrealloc(current->data, len + len2 + 2);
2198 current->data[len++] = ' ';
2199 current->data[len] = '\0';
2200
2201 strncat(current->data, current->next->data, len2);
2202
2203 unlink_node(tmpnode);
2204 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002205 }
2206
2207 justify_format(current->data);
2208
2209 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002210 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002211
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002212 if ((strlenpt(current->data) > (fill))
2213 && !no_spaces(current->data)) {
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002214 do {
2215 int i = 0;
2216 int len2 = 0;
2217 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002218
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002219 /* Start at fill , unless line isn't that long (but it
2220 * appears at least fill long with tabs.
2221 */
2222 if (slen > fill)
2223 i = fill;
2224 else
2225 i = slen;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002226
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002227 for (; i > 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002228 if (isspace((int) current->data[i]) &&
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002229 ((strlenpt(current->data) - strlen(current->data + i))
2230 <= fill))
2231 break;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002232 }
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002233
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002234 if (!i)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002235 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002236
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002237 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002238
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002239 len2 = strlen(current->data + i + 1);
Chris Allegretta88b09152001-05-17 11:35:43 +00002240 tmpline->data = charalloc(len2 + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002241
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002242 /* Skip the white space in current. */
2243 memcpy(tmpline->data, current->data + i + 1, len2);
2244 tmpline->data[len2] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002245
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002246 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002247
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002248 tmpline->prev = current;
2249 tmpline->next = current->next;
2250 if (current->next != NULL)
2251 current->next->prev = tmpline;
2252
2253 current->next = tmpline;
2254 current = tmpline;
2255 slen -= i + 1;
2256 current_y++;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002257 } while ((strlenpt(current->data) > (fill))
2258 && !no_spaces(current->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002259 }
Chris Allegretta9149e612000-11-27 00:23:41 +00002260 tmpbot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002261
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002262 if (current->next)
2263 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00002264 else
2265 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002266 current_x = 0;
2267 placewewant = 0;
2268
Adam Rogoyski09f97962000-06-20 02:50:33 +00002269 renumber(initial);
2270 totlines = filebot->lineno;
2271
2272 werase(edit);
2273
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002274 if ((current_y < 0) || (current_y >= editwinrows - 1)
2275 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00002276 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002277 center_cursor();
2278 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00002279 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002280 }
2281
Adam Rogoyski09f97962000-06-20 02:50:33 +00002282 edit_refresh();
Chris Allegretta9149e612000-11-27 00:23:41 +00002283 statusbar(_("Can now UnJustify!"));
Chris Allegretta07798352000-11-27 22:58:23 +00002284 /* Change the shortcut list to display the unjustify code */
2285 shortcut_init(1);
2286 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002287 reset_cursor();
2288
Chris Allegretta88520c92001-05-05 17:45:54 +00002289 /* Now get a keystroke and see if it's unjustify; if not, unget the keystroke
Chris Allegretta9149e612000-11-27 00:23:41 +00002290 and return */
Chris Allegretta5f071802001-05-06 02:34:31 +00002291
2292#ifndef DISABLE_MOUSE
2293#ifdef NCURSES_MOUSE_VERSION
2294
2295 /* If it was a mouse click, parse it with do_mouse and it might become
2296 the unjustify key. Else give it back to the input stream. */
2297 if ((kbinput = wgetch(edit)) == KEY_MOUSE)
2298 do_mouse();
2299 else
2300 ungetch(kbinput);
2301#endif
2302#endif
2303
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002304 if ((kbinput = wgetch(edit)) != NANO_UNJUSTIFY_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002305 ungetch(kbinput);
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002306 blank_statusbar_refresh();
2307 } else {
Chris Allegretta9149e612000-11-27 00:23:41 +00002308 /* Else restore the justify we just did (ungrateful user!) */
2309 if (tmptop->prev != NULL)
2310 tmptop->prev->next = tmpbot->next;
Chris Allegrettad022eac2000-11-27 02:50:49 +00002311 else
2312 fileage = current;
Chris Allegretta9149e612000-11-27 00:23:41 +00002313 tmpbot->next->prev = tmptop->prev;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002314 current = tmpbot->next;
Chris Allegretta9149e612000-11-27 00:23:41 +00002315 tmpbot->next = NULL;
2316 do_uncut_text();
Chris Allegrettad022eac2000-11-27 02:50:49 +00002317 if (tmptop->prev == NULL)
2318 edit_refresh();
2319
Chris Allegretta88520c92001-05-05 17:45:54 +00002320 /* Restore totsize from before justify */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002321 totsize = totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002322 free_filestruct(tmptop);
2323 blank_statusbar_refresh();
2324 }
Chris Allegretta4a9c8582000-11-27 22:59:40 +00002325 shortcut_init(0);
2326 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002327 free_filestruct(cutbuffer);
2328 cutbuffer = cutbak;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002329
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002330 return 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002331#endif
2332}
2333
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002334#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002335void help_init(void)
2336{
2337 int i, sofar = 0;
2338 long allocsize = 1; /* How much space we're gonna need for the help text */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002339 char buf[BUFSIZ] = "", *ptr = NULL;
2340
2341 /* First set up the initial help text for the current function */
2342 if (currshortcut == whereis_list || currshortcut == replace_list
2343 || currshortcut == replace_list_2)
2344 ptr = _("Search Command Help Text\n\n "
2345 "Enter the words or characters you would like to search "
2346 "for, then hit enter. If there is a match for the text you "
2347 "entered, the screen will be updated to the location of the "
2348 " nearest match for the search string.\n\n "
2349 "If using Pico Mode via the -p or --pico flags or using the "
2350 "Meta-P toggle, the previous search string will be shown in "
2351 "brackets after the Search: prompt. Hitting enter without "
2352 "entering any text will preform the previous search. "
2353 "Otherwise, the previous string will be placed in front of "
2354 "the cursor, and can be edited or deleted before hitting "
2355 "enter.\n\n The following functions keys are available in "
2356 "Search mode:\n\n");
2357 else if (currshortcut == goto_list)
2358 ptr = _("Goto Line Help Text\n\n "
2359 "Enter the line number that you wish to go to and hit "
2360 "Enter. If thre are fewer lines of text than the "
2361 "number you entered, you will be brought to the last line "
2362 "of the file.\n\n The following functions keys are "
2363 "available in Goto Line mode:\n\n");
2364 else if (currshortcut == insertfile_list)
2365 ptr = _("Insert File Help Text\n\n "
2366 "Type in the name of a file to be inserted into the current "
2367 "file buffer at the current cursor location.\n\n "
2368 "If you have compiled nano with multiple file buffer "
2369 "support, and enable multiple buffers with the -F "
2370 "or --multibuffer command line flags or the Meta-F "
2371 "toggle, inserting a file will cause it to be loaded into "
2372 "a separate buffer (use Ctrl-< and > to switch between "
2373 "file buffers).\n\n The following function keys are "
2374 "available in Insert File mode:\n\n");
2375 else if (currshortcut == writefile_list)
2376 ptr = _("Write File Help Text\n\n "
2377 "Type the name that you wish to save the current file "
2378 "as and hit enter to save the file.\n\n "
2379 "If you are using the marker code with Ctrl-^ and have "
2380 "selected text, you will be prompted to save only the "
2381 "selected portion to a separate file. To reduce the "
2382 "chance of overwriting the current file with just a portion "
2383 "of it, the current filename is not the default in this "
2384 "mode.\n\n The following function keys are available in "
2385 "Write File mode:\n\n");
2386#ifndef DISABLE_BROWSER
2387 else if (currshortcut == browser_list)
2388 ptr = _("File Browser Help Text\n\n "
2389 "The file browser is used to visually browse the "
2390 "directory structure to select a file for reading "
2391 "or writing. You may use the arrow keys or Page Up/"
2392 "Down to browse through the files, and S or Enter to "
2393 "choose the selected file or enter the selected "
2394 "directory. To move up one level, select the directory "
2395 "called \"..\" at the top of the file list.\n\n The "
2396 "following functions keys are available in the file "
2397 "browser:\n\n");
2398 else if (currshortcut == gotodir_list)
2399 ptr = _("Browser Goto Directory Help Text\n\n "
2400 "Enter the name of the directory you would like to "
2401 "browse to.\n\n If tab completion has not been disabled, "
2402 "you can use the TAB key to (attempt to) automatically "
2403 "complete the directory name. The following function "
2404 "keys are available in Browser GotoDir mode:\n\n");
2405#endif
2406 else if (currshortcut == spell_list)
2407 ptr = _("Spell Check Help Text\n\n "
2408 "The spell checker checks the spelling of all text "
2409 "in the current file. When an unknown word is "
2410 "encountered, it is highlighted and a replacement can "
2411 "be edited. It will then prompt to replace every "
2412 "instance of the given misspelled word in the "
2413 "current file.\n\n The following other functions are "
2414 "available in Spell Check mode:\n\n");
2415 else /* Default to the main help list */
2416 ptr = help_text_init;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002417
2418 /* Compute the space needed for the shortcut lists - we add 15 to
2419 have room for the shortcut abbrev and its possible alternate keys */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002420 for (i = 0; i <= currslen - 1; i++)
2421 if (currshortcut[i].help != NULL)
2422 allocsize += strlen(currshortcut[i].help) + 15;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002423
Chris Allegrettab3655b42001-10-22 03:15:31 +00002424 /* If we're on the main list, we also allocate space for toggle help text. */
2425 if (currshortcut == main_list) {
2426 for (i = 0; i <= TOGGLE_LEN - 1; i++)
2427 if (toggles[i].desc != NULL)
2428 allocsize += strlen(toggles[i].desc) + 30;
Chris Allegretta756f2202000-09-01 13:32:47 +00002429
Chris Allegrettab3655b42001-10-22 03:15:31 +00002430 }
2431
2432 allocsize += strlen(ptr);
2433
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002434
2435 if (help_text != NULL)
2436 free(help_text);
2437
2438 /* Allocate space for the help text */
Chris Allegretta88b09152001-05-17 11:35:43 +00002439 help_text = charalloc(allocsize);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002440
2441 /* Now add the text we want */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002442 strcpy(help_text, ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002443
2444 /* Now add our shortcut info */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002445 for (i = 0; i <= currslen - 1; i++) {
2446 if (currshortcut[i].val > 0 && currshortcut[i].val < 'a')
2447 sofar = snprintf(buf, BUFSIZ, "^%c ", currshortcut[i].val + 64);
Chris Allegretta8d990b52001-09-22 22:14:25 +00002448 else
2449 sofar = snprintf(buf, BUFSIZ, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002450
Chris Allegrettab3655b42001-10-22 03:15:31 +00002451 if (currshortcut[i].misc1 > KEY_F0 && currshortcut[i].misc1 <= KEY_F(64))
Robert Siemborski6af14312000-07-01 21:34:26 +00002452 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
Chris Allegrettab3655b42001-10-22 03:15:31 +00002453 currshortcut[i].misc1 - KEY_F0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002454 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002455 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002456
Chris Allegrettab3655b42001-10-22 03:15:31 +00002457 if (currshortcut[i].altval > 0 && currshortcut[i].altval < 91)
Chris Allegrettae49f1232000-09-02 07:20:39 +00002458 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
Chris Allegrettab3655b42001-10-22 03:15:31 +00002459 currshortcut[i].altval - 32);
2460 else if (currshortcut[i].altval > 0)
Chris Allegretta8d990b52001-09-22 22:14:25 +00002461 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
Chris Allegrettab3655b42001-10-22 03:15:31 +00002462 currshortcut[i].altval);
2463 /* Hack */
2464 else if (currshortcut[i].val >= 'a')
2465 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
2466 currshortcut[i].val - 32);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002467 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002468 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002469
Chris Allegretta756f2202000-09-01 13:32:47 +00002470
Chris Allegrettab3655b42001-10-22 03:15:31 +00002471 if (currshortcut[i].help != NULL)
2472 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", currshortcut[i].help);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002473
Chris Allegretta756f2202000-09-01 13:32:47 +00002474
2475 strcat(help_text, buf);
2476 strcat(help_text, "\n");
2477 }
2478
2479 /* And the toggles... */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002480 if (currshortcut == main_list)
2481 for (i = 0; i <= TOGGLE_LEN - 1; i++) {
2482 if (toggles[i].override_ch != 0)
2483 sofar = snprintf(buf, BUFSIZ,
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002484 "M-%c ", toggles[i].override_ch);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002485 else
2486 sofar = snprintf(buf, BUFSIZ,
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002487 "M-%c ", toggles[i].val - 32);
Chris Allegretta756f2202000-09-01 13:32:47 +00002488
Chris Allegrettab3655b42001-10-22 03:15:31 +00002489 if (toggles[i].desc != NULL) {
2490 if (toggles[i].flag != 0)
2491 snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002492 toggles[i].desc);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002493 else
2494 snprintf(&buf[sofar], BUFSIZ - sofar, "%s",
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002495 toggles[i].desc);
2496 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002497
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002498 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00002499 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002500 }
2501
2502}
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002503#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002504
Chris Allegretta756f2202000-09-01 13:32:47 +00002505void do_toggle(int which)
2506{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002507#ifdef NANO_SMALL
2508 nano_disabled_msg();
2509#else
Jordi Mallach2dc0f6b2000-09-07 10:48:00 +00002510 char *enabled = _("enabled");
2511 char *disabled = _("disabled");
Chris Allegrettaf0f63a82000-09-02 18:44:21 +00002512
Chris Allegretta8d990b52001-09-22 22:14:25 +00002513 switch (toggles[which].val) {
2514 case TOGGLE_BACKWARDS_KEY:
2515 case TOGGLE_CASE_KEY:
2516 case TOGGLE_REGEXP_KEY:
2517 return;
2518 }
Chris Allegretta8d990b52001-09-22 22:14:25 +00002519
Chris Allegretta658399a2001-06-14 02:54:22 +00002520 /* Even easier! */
2521 TOGGLE(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002522
Chris Allegretta756f2202000-09-01 13:32:47 +00002523 switch (toggles[which].val) {
2524 case TOGGLE_PICOMODE_KEY:
Chris Allegretta07798352000-11-27 22:58:23 +00002525 shortcut_init(0);
Chris Allegrettac1049ac2001-08-17 00:03:46 +00002526 SET(CLEAR_BACKUPSTRING);
Chris Allegretta756f2202000-09-01 13:32:47 +00002527 display_main_list();
2528 break;
2529 case TOGGLE_SUSPEND_KEY:
2530 signal_init();
2531 break;
2532 case TOGGLE_MOUSE_KEY:
2533 mouse_init();
2534 break;
2535 case TOGGLE_NOHELP_KEY:
Chris Allegretta2a42af12000-09-12 23:02:49 +00002536 wclear(bottomwin);
2537 wrefresh(bottomwin);
2538 window_init();
Chris Allegrettaaffeda82000-12-18 04:03:48 +00002539 fix_editbot();
Chris Allegretta2a42af12000-09-12 23:02:49 +00002540 edit_refresh();
2541 display_main_list();
Chris Allegretta756f2202000-09-01 13:32:47 +00002542 break;
Chris Allegretta99e30e12001-09-23 02:45:27 +00002543 case TOGGLE_DOS_KEY:
2544 UNSET(MAC_FILE);
2545 break;
2546 case TOGGLE_MAC_KEY:
2547 UNSET(DOS_FILE);
2548 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002549 }
Chris Allegretta2a42af12000-09-12 23:02:49 +00002550
Chris Allegretta819e3db2001-07-11 02:37:19 +00002551 if (!ISSET(toggles[which].flag)) {
2552 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
2553 toggles[which].val == TOGGLE_WRAP_KEY)
2554 statusbar("%s %s", toggles[which].desc, enabled);
2555 else
2556 statusbar("%s %s", toggles[which].desc, disabled);
2557 } else {
2558 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
2559 toggles[which].val == TOGGLE_WRAP_KEY)
2560 statusbar("%s %s", toggles[which].desc, disabled);
2561 else
2562 statusbar("%s %s", toggles[which].desc, enabled);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002563 }
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002564
Chris Allegretta756f2202000-09-01 13:32:47 +00002565#endif
2566}
2567
Chris Allegretta88520c92001-05-05 17:45:54 +00002568/* If the NumLock key has made the keypad go awry, print an error
2569 message; hopefully we can address it later. */
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002570void print_numlock_warning(void)
2571{
2572 static int didmsg = 0;
2573 if (!didmsg) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002574 statusbar(_
2575 ("NumLock glitch detected. Keypad will malfunction with NumLock off"));
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002576 didmsg = 1;
2577 }
2578}
2579
Chris Allegretta1748cd12001-01-13 17:22:54 +00002580/* This function returns the correct keystroke, given the A,B,C or D
2581 input key. This is a common sequence of many terms which send
2582 Esc-O-[A-D] or Esc-[-[A-D]. */
2583int ABCD(int input)
2584{
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002585 switch (input) {
2586 case 'A':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002587 case 'a':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002588 return (KEY_UP);
2589 case 'B':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002590 case 'b':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002591 return (KEY_DOWN);
2592 case 'C':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002593 case 'c':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002594 return (KEY_RIGHT);
2595 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002596 case 'd':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002597 return (KEY_LEFT);
2598 default:
2599 return 0;
Chris Allegretta1748cd12001-01-13 17:22:54 +00002600 }
2601}
2602
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002603int main(int argc, char *argv[])
2604{
2605 int optchr;
2606 int kbinput; /* Input from keyboard */
2607 long startline = 0; /* Line to try and start at */
Chris Allegretta08020882001-01-29 23:37:54 +00002608 int keyhandled; /* Have we handled the keystroke yet? */
2609 int i, modify_control_seq;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002610 char *argv0;
Chris Allegrettab516d8e2001-10-03 00:01:36 +00002611 long constcheck; /* Check to constantly update */
Chris Allegretta0357c4d2001-09-19 02:59:25 +00002612
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002613#ifdef _POSIX_VDISABLE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002614 struct termios term;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002615#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002616
2617#ifdef HAVE_GETOPT_LONG
2618 int option_index = 0;
2619 struct option long_options[] = {
Chris Allegretta805c26d2000-09-06 13:39:17 +00002620#ifdef HAVE_REGEX_H
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002621 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00002622#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002623 {"version", 0, 0, 'V'},
2624 {"const", 0, 0, 'c'},
2625 {"suspend", 0, 0, 'z'},
2626 {"nowrap", 0, 0, 'w'},
2627 {"nohelp", 0, 0, 'x'},
2628 {"help", 0, 0, 'h'},
Chris Allegretta7492cec2000-12-18 04:55:21 +00002629 {"view", 0, 0, 'v'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002630#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002631 {"cut", 0, 0, 'k'},
Chris Allegretta7004c282001-09-22 00:42:10 +00002632 {"dos", 0, 0, 'D'},
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002633 {"mac", 0, 0, 'M'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002634 {"autoindent", 0, 0, 'i'},
Chris Allegrettaff989832001-09-17 13:48:00 +00002635#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002636 {"tempfile", 0, 0, 't'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002637#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002638 {"speller", 1, 0, 's'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002639#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00002640
2641#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002642 {"fill", 1, 0, 'r'},
Chris Allegretta6fe61492001-05-21 12:56:25 +00002643#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002644 {"mouse", 0, 0, 'm'},
Chris Allegrettae1f14522001-09-19 03:19:43 +00002645#ifndef DISABLE_OPERATINGDIR
2646 {"operatingdir", 1, 0, 'o'},
2647#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002648 {"pico", 0, 0, 'p'},
2649 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00002650 {"tabsize", 1, 0, 'T'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002651
Chris Allegretta355fbe52001-07-14 19:32:47 +00002652#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002653 {"multibuffer", 0, 0, 'F'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002654#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002655#ifndef NANO_SMALL
2656 {"smooth", 0, 0, 'S'},
2657#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002658 {0, 0, 0, 0}
2659 };
2660#endif
2661
2662 /* Flag inits... */
2663 SET(FOLLOW_SYMLINKS);
2664
2665#ifndef NANO_SMALL
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002666#ifdef ENABLE_NLS
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002667 setlocale(LC_ALL, "");
2668 bindtextdomain(PACKAGE, LOCALEDIR);
2669 textdomain(PACKAGE);
2670#endif
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002671#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002672
Chris Allegretta8d8e0122001-04-18 04:28:54 +00002673#ifdef ENABLE_NANORC
2674 do_rcfile();
2675#endif /* ENABLE_NANORC */
2676
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002677#ifdef HAVE_GETOPT_LONG
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002678 while ((optchr = getopt_long(argc, argv, "h?DFMRST:Vabcefgijklmo:pr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002679 long_options, &option_index)) != EOF) {
2680#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002681 while ((optchr =
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002682 getopt(argc, argv, "h?DFMRST:Vabcefgijklmo:pr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002683#endif
2684
2685 switch (optchr) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002686
Chris Allegretta7004c282001-09-22 00:42:10 +00002687#ifndef NANO_SMALL
2688 case 'D':
2689 SET(DOS_FILE);
2690 break;
2691#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +00002692#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002693 case 'F':
Chris Allegretta355fbe52001-07-14 19:32:47 +00002694 SET(MULTIBUFFER);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002695 break;
2696#endif
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002697#ifndef NANO_SMALL
2698 case 'M':
2699 SET(MAC_FILE);
2700 break;
2701#endif
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002702 case 'T':
Chris Allegretta99bf73f2000-08-04 00:22:08 +00002703 tabsize = atoi(optarg);
2704 if (tabsize <= 0) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002705 usage(); /* To stop bogus data for tab width */
2706 finish(1);
2707 }
2708 break;
Chris Allegretta805c26d2000-09-06 13:39:17 +00002709#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +00002710 case 'R':
2711 SET(USE_REGEXP);
2712 break;
Chris Allegretta47805612000-07-07 02:35:34 +00002713#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002714#ifndef NANO_SMALL
2715 case 'S':
2716 SET(SMOOTHSCROLL);
2717 break;
2718#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002719 case 'V':
2720 version();
2721 exit(0);
Chris Allegrettae1f14522001-09-19 03:19:43 +00002722 case 'a':
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002723 case 'b':
2724 case 'e':
2725 case 'f':
Rocco Corsi12f294c2001-04-14 06:50:24 +00002726 case 'g':
2727 case 'j':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002728 /* Pico compatibility flags */
2729 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002730 case 'c':
2731 SET(CONSTUPDATE);
2732 break;
2733 case 'h':
2734 case '?':
2735 usage();
2736 exit(0);
Chris Allegrettaff989832001-09-17 13:48:00 +00002737#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002738 case 'i':
2739 SET(AUTOINDENT);
2740 break;
Chris Allegretta627de192000-07-12 02:09:17 +00002741 case 'k':
2742 SET(CUT_TO_END);
2743 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002744#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002745 case 'l':
2746 UNSET(FOLLOW_SYMLINKS);
2747 break;
2748 case 'm':
2749 SET(USE_MOUSE);
2750 break;
Chris Allegrettae1f14522001-09-19 03:19:43 +00002751#ifndef DISABLE_OPERATINGDIR
2752 case 'o':
2753 operating_dir = charalloc(strlen(optarg) + 1);
2754 strcpy(operating_dir, optarg);
2755
2756 /* make sure we're inside the operating directory */
2757 if (check_operating_dir(".", 0)) {
2758 if (chdir(operating_dir) == -1) {
2759 free(operating_dir);
2760 operating_dir = NULL;
2761 }
2762 }
2763 break;
2764#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002765 case 'p':
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002766 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002767 break;
2768 case 'r':
Chris Allegretta6fe61492001-05-21 12:56:25 +00002769#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002770 fill = atoi(optarg);
Chris Allegretta6fe61492001-05-21 12:56:25 +00002771 if (fill < 0)
2772 wrap_at = fill;
2773 else if (fill == 0) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002774 usage(); /* To stop bogus data (like a string) */
2775 finish(1);
2776 }
2777 break;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002778#else
2779 usage();
2780 exit(0);
2781
2782#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002783#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002784 case 's':
Chris Allegretta88b09152001-05-17 11:35:43 +00002785 alt_speller = charalloc(strlen(optarg) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002786 strcpy(alt_speller, optarg);
2787 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002788#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002789 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00002790 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002791 break;
2792 case 'v':
2793 SET(VIEW_MODE);
2794 break;
2795 case 'w':
Chris Allegrettacef7fbb2001-04-02 05:36:08 +00002796#ifdef DISABLE_WRAPPING
2797 usage();
2798 exit(0);
2799#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002800 SET(NO_WRAP);
2801 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002802#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002803 case 'x':
2804 SET(NO_HELP);
2805 break;
2806 case 'z':
2807 SET(SUSPEND);
2808 break;
2809 default:
2810 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002811 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002812 }
2813
2814 }
2815
2816 argv0 = strrchr(argv[0], '/');
2817 if ((argv0 && strstr(argv0, "pico"))
2818 || (!argv0 && strstr(argv[0], "pico")))
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002819 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002820
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002821 /* See if there's a non-option in argv (first non-option is the
2822 filename, if +LINE is not given) */
2823 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002824 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002825 else {
2826 /* Look for the +line flag... */
2827 if (argv[optind][0] == '+') {
2828 startline = atoi(&argv[optind][1]);
2829 optind++;
2830 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002831 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002832 else
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002833 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002834
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002835 } else
2836 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002837 }
2838
2839
2840 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002841 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002842
Chris Allegretta9239d742000-09-06 15:19:18 +00002843#ifdef _POSIX_VDISABLE
Chris Allegretta8f6c0692000-07-19 01:16:18 +00002844 term = oldterm;
2845 term.c_cc[VINTR] = _POSIX_VDISABLE;
2846 term.c_cc[VQUIT] = _POSIX_VDISABLE;
2847 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002848 tcsetattr(0, TCSANOW, &term);
Chris Allegretta9239d742000-09-06 15:19:18 +00002849#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002850
2851 /* now ncurses init stuff... */
2852 initscr();
2853 savetty();
2854 nonl();
2855 cbreak();
2856 noecho();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002857
2858 /* Set up some global variables */
Chris Allegretta56214c62001-09-27 02:46:53 +00002859 global_init(0);
Chris Allegretta07798352000-11-27 22:58:23 +00002860 shortcut_init(0);
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002861#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002862 init_help_msg();
2863 help_init();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002864#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002865 signal_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002866
2867#ifdef DEBUG
2868 fprintf(stderr, _("Main: set up windows\n"));
2869#endif
2870
Chris Allegretta8ce24132001-04-30 11:28:46 +00002871#ifdef ENABLE_COLOR
2872 do_colorinit();
2873#endif /* ENABLE_COLOR */
2874
Chris Allegretta2a42af12000-09-12 23:02:49 +00002875 window_init();
Chris Allegretta756f2202000-09-01 13:32:47 +00002876 mouse_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002877
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002878#ifdef DEBUG
2879 fprintf(stderr, _("Main: bottom win\n"));
2880#endif
Chris Allegretta88520c92001-05-05 17:45:54 +00002881 /* Set up bottom of window */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002882 display_main_list();
2883
2884#ifdef DEBUG
2885 fprintf(stderr, _("Main: open file\n"));
2886#endif
2887
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002888 titlebar(NULL);
Chris Allegretta31c76662000-11-21 06:20:20 +00002889
2890 /* Now we check to see if argv[optind] is non-null to determine if
2891 we're dealing with a new file or not, not argc == 1... */
2892 if (argv[optind] == NULL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002893 new_file();
2894 else
2895 open_file(filename, 0, 0);
2896
2897 if (startline > 0)
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002898 do_gotoline(startline, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002899 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00002900 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002901
Chris Allegretta08020882001-01-29 23:37:54 +00002902 /* return here after a sigwinch */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002903 sigsetjmp(jmpbuf, 1);
Chris Allegretta08020882001-01-29 23:37:54 +00002904
2905 /* Fix clobber-age */
2906 kbinput = 0;
2907 keyhandled = 0;
2908 modify_control_seq = 0;
2909
Robert Siemborski6967eec2000-07-08 14:23:32 +00002910 edit_refresh();
2911 reset_cursor();
2912
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002913 while (1) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00002914 constcheck = current->lineno + current_x + current_y + totsize;
Chris Allegretta9239d742000-09-06 15:19:18 +00002915
Chris Allegretta6fe61492001-05-21 12:56:25 +00002916#ifndef DISABLE_MOUSE
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002917 currshortcut = main_list;
2918 currslen = MAIN_VISIBLE;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002919#endif
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002920
Chris Allegretta9239d742000-09-06 15:19:18 +00002921#ifndef _POSIX_VDISABLE
2922 /* We're going to have to do it the old way, i.e. on cygwin */
2923 raw();
2924#endif
2925
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002926 kbinput = wgetch(edit);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002927#ifdef DEBUG
2928 fprintf(stderr, "AHA! %c (%d)\n", kbinput, kbinput);
2929#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002930
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002931 if (kbinput == 27) { /* Grab Alt-key stuff first */
2932 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002933 /* Alt-O, suddenly very important ;) */
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002934 case 'O':
Chris Allegretta16e41682000-09-11 22:33:54 +00002935 kbinput = wgetch(edit);
Chris Allegretta316e4d92001-04-28 16:31:19 +00002936 if ((kbinput <= 'D' && kbinput >= 'A') ||
2937 (kbinput <= 'd' && kbinput >= 'a'))
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002938 kbinput = ABCD(kbinput);
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002939 else if (kbinput <= 'z' && kbinput >= 'j')
2940 print_numlock_warning();
2941 else if (kbinput <= 'S' && kbinput >= 'P')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002942 kbinput = KEY_F(kbinput - 79);
Chris Allegretta16e41682000-09-11 22:33:54 +00002943#ifdef DEBUG
2944 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002945 fprintf(stderr, _("I got Alt-O-%c! (%d)\n"),
2946 kbinput, kbinput);
2947 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002948 }
2949#endif
2950 break;
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002951 case 27:
2952 /* If we get Alt-Alt, the next keystroke should be the same as a
2953 control sequence */
2954 modify_control_seq = 1;
2955 keyhandled = 1;
2956 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00002957#ifndef NANO_SMALL
Chris Allegretta76e291b2001-10-14 19:05:10 +00002958 case ' ':
2959 /* If control-space is next word, Alt-space should be previous word */
2960 do_prev_word();
2961 keyhandled = 1;
2962 break;
Chris Allegrettaabf22a82001-10-24 00:58:19 +00002963#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002964 case '[':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002965 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002966 case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */
Chris Allegretta16e41682000-09-11 22:33:54 +00002967 kbinput = wgetch(edit);
2968 if (kbinput >= '1' && kbinput <= '5') {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002969 kbinput = KEY_F(kbinput - 48);
2970 wgetch(edit);
2971 } else if (kbinput >= '7' && kbinput <= '9') {
2972 kbinput = KEY_F(kbinput - 49);
2973 wgetch(edit);
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002974 } else if (kbinput == '~')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002975 kbinput = KEY_HOME;
Chris Allegretta16e41682000-09-11 22:33:54 +00002976
2977#ifdef DEBUG
2978 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002979 fprintf(stderr, _("I got Alt-[-1-%c! (%d)\n"),
2980 kbinput, kbinput);
2981 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002982 }
2983#endif
2984
2985 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002986 case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */
Chris Allegretta16e41682000-09-11 22:33:54 +00002987 kbinput = wgetch(edit);
Chris Allegretta16e41682000-09-11 22:33:54 +00002988 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002989 case '0':
2990 kbinput = KEY_F(9);
2991 wgetch(edit);
2992 break;
2993 case '1':
2994 kbinput = KEY_F(10);
2995 wgetch(edit);
2996 break;
2997 case '3':
2998 kbinput = KEY_F(11);
2999 wgetch(edit);
3000 break;
3001 case '4':
3002 kbinput = KEY_F(12);
3003 wgetch(edit);
3004 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003005 case '~':
3006 goto do_insertkey;
Chris Allegretta16e41682000-09-11 22:33:54 +00003007#ifdef DEBUG
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003008 default:
3009 fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"),
3010 kbinput, kbinput);
3011 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00003012#endif
3013
3014 }
3015 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003016 case '3': /* Alt-[-3 = Delete? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003017 kbinput = NANO_DELETE_KEY;
3018 wgetch(edit);
3019 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003020 case '4': /* Alt-[-4 = End? */
Chris Allegretta16e41682000-09-11 22:33:54 +00003021 kbinput = NANO_END_KEY;
3022 wgetch(edit);
3023 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003024 case '5': /* Alt-[-5 = Page Up */
Chris Allegretta16e41682000-09-11 22:33:54 +00003025 kbinput = KEY_PPAGE;
3026 wgetch(edit);
3027 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003028 case '6': /* Alt-[-6 = Page Down */
Chris Allegretta16e41682000-09-11 22:33:54 +00003029 kbinput = KEY_NPAGE;
3030 wgetch(edit);
3031 break;
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003032 case '7':
3033 kbinput = KEY_HOME;
3034 wgetch(edit);
3035 break;
3036 case '8':
3037 kbinput = KEY_END;
3038 wgetch(edit);
3039 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003040 case '[': /* Alt-[-[-[A-E], F1-F5 in linux console */
Chris Allegretta16e41682000-09-11 22:33:54 +00003041 kbinput = wgetch(edit);
Chris Allegrettab26ecb52001-07-04 16:27:05 +00003042 if (kbinput >= 'A' && kbinput <= 'E')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003043 kbinput = KEY_F(kbinput - 64);
Chris Allegretta16e41682000-09-11 22:33:54 +00003044 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003045 case 'A':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003046 case 'B':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003047 case 'C':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003048 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00003049 case 'a':
3050 case 'b':
3051 case 'c':
3052 case 'd':
Chris Allegretta1748cd12001-01-13 17:22:54 +00003053 kbinput = ABCD(kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003054 break;
3055 case 'H':
3056 kbinput = KEY_HOME;
3057 break;
3058 case 'F':
3059 kbinput = KEY_END;
3060 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003061 default:
3062#ifdef DEBUG
3063 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
3064 kbinput, kbinput);
3065#endif
3066 break;
3067 }
3068 break;
Chris Allegretta355fbe52001-07-14 19:32:47 +00003069#ifdef ENABLE_MULTIBUFFER
Chris Allegretta819e3db2001-07-11 02:37:19 +00003070 case NANO_OPENPREV_KEY:
3071 open_prevfile(0);
3072 keyhandled = 1;
3073 break;
3074 case NANO_OPENNEXT_KEY:
3075 open_nextfile(0);
3076 keyhandled = 1;
3077 break;
Chris Allegretta9cf9e062001-07-11 12:06:13 +00003078#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003079 default:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003080 /* Check for the altkey defs.... */
3081 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
3082 if (kbinput == main_list[i].altval ||
3083 kbinput == main_list[i].altval - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003084 kbinput = main_list[i].val;
3085 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003086 }
Chris Allegretta756f2202000-09-01 13:32:47 +00003087#ifndef NANO_SMALL
3088 /* And for toggle switches */
3089 for (i = 0; i <= TOGGLE_LEN - 1 && !keyhandled; i++)
3090 if (kbinput == toggles[i].val ||
3091 kbinput == toggles[i].val - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003092 do_toggle(i);
3093 keyhandled = 1;
3094 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00003095 }
3096#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003097#ifdef DEBUG
3098 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
3099 kbinput);
3100#endif
3101 break;
3102 }
3103 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003104 /* If the modify_control_seq is set, we received an Alt-Alt
3105 sequence before this, so we make this key a control sequence
3106 by subtracting 64 or 96, depending on its value. */
3107 if (!keyhandled && modify_control_seq) {
3108 if (kbinput >= 'A' && kbinput < 'a')
3109 kbinput -= 64;
3110 else if (kbinput >= 'a' && kbinput <= 'z')
3111 kbinput -= 96;
3112
3113 modify_control_seq = 0;
3114 }
3115
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003116 /* Look through the main shortcut list to see if we've hit a
3117 shortcut key */
Chris Allegretta2cd72b62001-10-24 17:25:36 +00003118 for (i = 0; i < MAIN_LIST_LEN && !keyhandled; i++) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003119 if (kbinput == main_list[i].val ||
3120 (main_list[i].misc1 && kbinput == main_list[i].misc1) ||
3121 (main_list[i].misc2 && kbinput == main_list[i].misc2)) {
3122 if (ISSET(VIEW_MODE) && !main_list[i].viewok)
3123 print_view_warning();
3124 else
3125 main_list[i].func();
3126 keyhandled = 1;
3127 }
3128 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003129 /* If we're in raw mode or using Alt-Alt-x, we have to catch
3130 Control-S and Control-Q */
Chris Allegretta9239d742000-09-06 15:19:18 +00003131 if (kbinput == 17 || kbinput == 19)
3132 keyhandled = 1;
3133
Chris Allegretta51b3eec2000-12-18 02:23:50 +00003134 /* Catch ^Z by hand when triggered also */
Chris Allegretta9239d742000-09-06 15:19:18 +00003135 if (kbinput == 26) {
3136 if (ISSET(SUSPEND))
3137 do_suspend(0);
3138 keyhandled = 1;
3139 }
Chris Allegretta9239d742000-09-06 15:19:18 +00003140
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003141
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003142#ifndef USE_SLANG
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003143 /* Hack, make insert key do something useful, like insert file */
3144 if (kbinput == KEY_IC) {
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003145#else
3146 if (0) {
3147#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003148 do_insertkey:
3149
3150#ifdef ENABLE_MULTIBUFFER
3151 do_insertfile(ISSET(MULTIBUFFER));
3152#else
3153 do_insertfile(0);
3154#endif
3155
Chris Allegretta1c27d3e2001-10-02 02:56:45 +00003156 keyhandled = 1;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003157 }
3158
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003159 /* Last gasp, stuff that's not in the main lists */
3160 if (!keyhandled)
3161 switch (kbinput) {
Chris Allegretta84de5522001-04-12 14:51:48 +00003162#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003163#ifdef NCURSES_MOUSE_VERSION
3164 case KEY_MOUSE:
3165 do_mouse();
3166 break;
3167#endif
3168#endif
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003169
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003170 case 0: /* Erg */
Chris Allegretta48ebb812001-10-24 01:34:15 +00003171#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003172 do_next_word();
3173 break;
Chris Allegrettaad3f4782001-10-02 03:54:13 +00003174#endif
Chris Allegrettaf4f7e042001-01-04 16:56:15 +00003175
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003176 case -1: /* Stuff that we don't want to do squat */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003177 case 410: /* Must ignore this, it gets sent when we resize */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003178 case 29: /* Ctrl-] */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003179#ifdef PDCURSES
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003180 case 541: /* ???? */
3181 case 542: /* Control and alt in Windows *shrug* */
Chris Allegretta72623582000-11-29 23:43:28 +00003182 case 543: /* Right ctrl key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003183 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +00003184 case 545: /* Right alt key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003185#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003186
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003187 break;
3188 default:
3189#ifdef DEBUG
3190 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
3191#endif
3192 /* We no longer stop unhandled sequences so that people with
3193 odd character sets can type... */
3194
3195 if (ISSET(VIEW_MODE)) {
3196 print_view_warning();
3197 break;
3198 }
3199 do_char(kbinput);
3200 }
Chris Allegretta7fdbd052001-10-02 00:55:38 +00003201 if (ISSET(DISABLE_CURPOS))
3202 UNSET(DISABLE_CURPOS);
3203 else if (ISSET(CONSTUPDATE))
Chris Allegrettab3655b42001-10-22 03:15:31 +00003204 if (constcheck != current->lineno + current_x + current_y + totsize)
Chris Allegretta756f2202000-09-01 13:32:47 +00003205 do_cursorpos();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003206
3207 reset_cursor();
3208 wrefresh(edit);
3209 keyhandled = 0;
3210 }
3211
3212 getchar();
3213 finish(0);
3214
3215}