blob: e1925d53d8f7650dc16b65264b787c079f4e66a4 [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * nano.c *
4 * *
5 * Copyright (C) 1999 Chris Allegretta *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 1, or (at your option) *
9 * any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 * *
20 **************************************************************************/
21
Chris Allegretta6efda542001-04-28 18:03:52 +000022#include "config.h"
23
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000024#include <stdio.h>
25#include <stdlib.h>
26#include <stdarg.h>
27#include <signal.h>
Chris Allegretta08020882001-01-29 23:37:54 +000028#include <setjmp.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000029#include <unistd.h>
30#include <string.h>
31#include <fcntl.h>
32#include <sys/stat.h>
33#include <sys/ioctl.h>
34#include <sys/param.h>
Chris Allegretta27eb13f2000-11-05 16:52:21 +000035#include <sys/types.h>
36#include <sys/wait.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000037#include <errno.h>
38#include <ctype.h>
39#include <locale.h>
40#include <limits.h>
Adam Rogoyski77f36de2000-06-07 03:56:54 +000041#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000042
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000043#include "proto.h"
44#include "nano.h"
45
46#ifndef NANO_SMALL
47#include <libintl.h>
48#define _(string) gettext(string)
49#else
50#define _(string) (string)
51#endif
52
53#ifdef HAVE_TERMIOS_H
54#include <termios.h>
55#endif
56
57#ifdef HAVE_TERMIO_H
58#include <termio.h>
59#endif
60
61#ifdef HAVE_GETOPT_H
62#include <getopt.h>
63#endif
64
Chris Allegretta6fe61492001-05-21 12:56:25 +000065#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000066/* Former globals, now static */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000067int fill = 0; /* Fill - where to wrap lines, basically */
Chris Allegretta6fe61492001-05-21 12:56:25 +000068int wrap_at = 0; /* Right justified fill value, allows resize */
69#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +000070
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000071struct termios oldterm; /* The user's original term settings */
Chris Allegretta88520c92001-05-05 17:45:54 +000072static struct sigaction act; /* For all our fun signal handlers */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000073
Rocco Corsiaf5c3022001-01-12 07:51:05 +000074#ifndef DISABLE_HELP
Chris Allegretta6b58acd2001-04-12 03:01:53 +000075static char *help_text_init = ""; /* Initial message, not including shortcuts */
Chris Allegretta65121632000-12-18 07:05:27 +000076#endif
77
Chris Allegretta27eb13f2000-11-05 16:52:21 +000078char *last_search = NULL; /* Last string we searched for */
79char *last_replace = NULL; /* Last replacement string */
80int search_last_line; /* Is this the last search line? */
81
Chris Allegretta08020882001-01-29 23:37:54 +000082static sigjmp_buf jmpbuf; /* Used to return to mainloop after SIGWINCH */
83
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000084/* What we do when we're all set to exit */
85RETSIGTYPE finish(int sigage)
86{
Chris Allegrettac08f50d2001-01-06 18:12:43 +000087
88 keypad(edit, TRUE);
89 keypad(bottomwin, TRUE);
90
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000091 if (!ISSET(NO_HELP)) {
92 mvwaddstr(bottomwin, 1, 0, hblank);
93 mvwaddstr(bottomwin, 2, 0, hblank);
Chris Allegretta4da1fc62000-06-21 03:00:43 +000094 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000095 mvwaddstr(bottomwin, 0, 0, hblank);
Chris Allegretta6b58acd2001-04-12 03:01:53 +000096
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000097 wrefresh(bottomwin);
98 endwin();
99
100 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000101 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000102
103 exit(sigage);
104}
105
106/* Die (gracefully?) */
107void die(char *msg, ...)
108{
109 va_list ap;
110
111 va_start(ap, msg);
112 vfprintf(stderr, msg, ap);
113 va_end(ap);
114
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000115 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000116 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000117
118 clear();
119 refresh();
120 resetty();
121 endwin();
122
123 fprintf(stderr, msg);
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000124
125 /* save the currently loaded file (if modified, its open_files entry
126 isn't up to date) */
127 die_save_file(filename);
128
Chris Allegretta355fbe52001-07-14 19:32:47 +0000129#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000130 /* then save all of the other loaded files, if any */
131 if (open_files) {
132 filestruct *tmp;
133
134 tmp = open_files;
135
136 while (open_files->prev)
137 open_files = open_files->prev;
138
139 while (open_files->next) {
140
141 /* if we already saved the file above (i. e. if it was the
142 currently loaded file), don't save it again */
143 if (tmp != open_files) {
144 fileage = open_files->file;
145 die_save_file(open_files->data);
146 }
147
148 open_files = open_files->next;
149 }
150
151 }
152#endif
153
154 exit(1); /* We have a problem: exit w/ errorlevel(1) */
155}
156
157void die_save_file(char *die_filename)
158{
159 char *name;
160 int i;
161
162 /* if we can't save we have REAL bad problems,
163 * but we might as well TRY. */
164 if (die_filename[0] == '\0') {
165 name = "nano.save";
166 i = write_file(name, 1, 0, 0);
167 } else {
168
169 char *buf = charalloc(strlen(die_filename) + 6);
170 strcpy(buf, die_filename);
171 strcat(buf, ".save");
172 i = write_file(buf, 1, 0, 0);
173 name = buf;
174 }
175
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000176 if (i != -1)
177 fprintf(stderr, _("\nBuffer written to %s\n"), name);
178 else
Chris Allegretta9756d622000-12-03 03:06:45 +0000179 fprintf(stderr, _("\nNo %s written (file exists?)\n"), name);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000180}
181
Chris Allegrettae61e8302001-01-14 05:18:27 +0000182/* Die with an error message that the screen was too small if, well, the
183 screen is too small */
184void die_too_small(void)
185{
186 char *too_small_msg = _("Window size is too small for Nano...");
187
188 die(too_small_msg);
189
190}
191
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000192void print_view_warning(void)
193{
194 statusbar(_("Key illegal in VIEW mode"));
195}
196
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000197void clear_filename(void)
198{
199 if (filename != NULL)
200 free(filename);
Chris Allegretta88b09152001-05-17 11:35:43 +0000201 filename = charalloc(1);
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000202 filename[0] = 0;
203}
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +0000204
Chris 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 Allegrettaa2ea1932000-06-06 05:53:49 +0000238}
239
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000240#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000241void init_help_msg(void)
242{
243
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000244 help_text_init =
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000245 _(" nano help text\n\n "
246 "The nano editor is designed to emulate the functionality and "
247 "ease-of-use of the UW Pico text editor. There are four main "
248 "sections of the editor: The top line shows the program "
249 "version, the current filename being edited, and whether "
250 "or not the file has been modified. Next is the main editor "
251 "window showing the file being edited. The status line is "
252 "the third line from the bottom and shows important messages. "
253 "The bottom two lines show the most commonly used shortcuts "
254 "in the editor.\n\n "
255 "The notation for shortcuts is as follows: Control-key "
Chris Allegrettae49f1232000-09-02 07:20:39 +0000256 "sequences are notated with a caret (^) symbol and are entered "
Chris Allegrettad56bd792000-09-02 07:27:10 +0000257 "with the Control (Ctrl) key. Escape-key sequences are notated "
258 "with the Meta (M) symbol and can be entered using either the "
259 "Esc, Alt or Meta key depending on your keyboard setup. The "
260 "following keystrokes are available in the main editor window. "
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000261 "Optional keys are shown in parentheses:\n\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000262
263}
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 */
396void null_at(char *data, int index)
397{
398 data[index] = 0;
399 align(&data);
400}
401
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000402void usage(void)
403{
404#ifdef HAVE_GETOPT_LONG
405 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
406 printf(_("Option Long option Meaning\n"));
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000407
Chris Allegretta7004c282001-09-22 00:42:10 +0000408#ifndef NANO_SMALL
409 printf
410 (_
411 (" -D --dos Write file in DOS format\n"));
412#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000413#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000414 printf
415 (_
Chris Allegretta355fbe52001-07-14 19:32:47 +0000416 (" -F --multibuffer Enable multiple file buffers\n"));
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000417#endif
Chris Allegretta8fa1e282001-09-22 04:20:25 +0000418#ifndef NANO_SMALL
419 printf
420 (_
421 (" -M --mac Write file in Mac format\n"));
422#endif
Chris Allegretta805c26d2000-09-06 13:39:17 +0000423#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000424 printf(_
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000425 (" -R --regexp Use regular expressions for search\n"));
Chris Allegretta47805612000-07-07 02:35:34 +0000426#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +0000427#ifndef NANO_SMALL
428 printf(_
429 (" -S --smooth Smooth scrolling\n"));
430#endif
Chris Allegretta7004c282001-09-22 00:42:10 +0000431 printf(_
432 (" -T [num] --tabsize=[num] Set width of a tab to num\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000433 printf
434 (_
435 (" -V --version Print version information and exit\n"));
436 printf(_
437 (" -c --const Constantly show cursor position\n"));
438 printf(_
439 (" -h --help Show this message\n"));
Chris Allegrettaff989832001-09-17 13:48:00 +0000440#ifndef NANO_SMALL
Chris Allegrettad55655f2000-12-27 03:36:47 +0000441 printf(_
442 (" -i --autoindent Automatically indent new lines\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000443 printf(_
Chris Allegretta627de192000-07-12 02:09:17 +0000444 (" -k --cut Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000445#endif
Chris Allegretta627de192000-07-12 02:09:17 +0000446 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000447 (" -l --nofollow Don't follow symbolic links, overwrite\n"));
Chris Allegretta84de5522001-04-12 14:51:48 +0000448#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000449#ifdef NCURSES_MOUSE_VERSION
450 printf(_(" -m --mouse Enable mouse\n"));
451#endif
452#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000453#ifndef DISABLE_OPERATINGDIR
Chris Allegrettad55655f2000-12-27 03:36:47 +0000454 printf(_
Chris Allegretta56214c62001-09-27 02:46:53 +0000455 (" -o [dir] --operatingdir=[dir] Set operating directory\n"));
Chris Allegrettae1f14522001-09-19 03:19:43 +0000456#endif
457 printf(_
458 (" -p --pico Emulate Pico as closely as possible\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000459
460#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000461 printf
462 (_
463 (" -r [#cols] --fill=[#cols] Set fill cols to (wrap lines at) #cols\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000464#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000465#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000466 printf(_
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000467 (" -s [prog] --speller=[prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000468#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000469 printf(_
470 (" -t --tempfile Auto save on exit, don't prompt\n"));
471 printf(_
472 (" -v --view View (read only) mode\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000473#ifndef DISABLE_WRAPPING
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000474 printf(_
475 (" -w --nowrap Don't wrap long lines\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000476#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000477 printf(_
478 (" -x --nohelp Don't show help window\n"));
479 printf(_
480 (" -z --suspend Enable suspend\n"));
481 printf(_
482 (" +LINE Start at line number LINE\n"));
483#else
484 printf(_("Usage: nano [option] +LINE <file>\n\n"));
485 printf(_("Option Meaning\n"));
Chris Allegretta7004c282001-09-22 00:42:10 +0000486#ifndef NANO_SMALL
487 printf(_(" -D Write file in DOS format\n"));
488#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +0000489#ifdef ENABLE_MULTIBUFFER
490 printf(_(" -F Enable multiple file buffers\n"));
491#endif
Chris Allegretta8fa1e282001-09-22 04:20:25 +0000492#ifndef NANO_SMALL
493 printf(_(" -M Write file in Mac format\n"));
494#endif
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000495 printf(_(" -T [num] Set width of a tab to num\n"));
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000496 printf(_(" -R Use regular expressions for search\n"));
Chris Allegretta3e3ae942001-09-22 19:02:04 +0000497#ifndef NANO_SMALL
498 printf(_(" -S Smooth scrolling\n"));
499#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000500 printf(_(" -V Print version information and exit\n"));
501 printf(_(" -c Constantly show cursor position\n"));
502 printf(_(" -h Show this message\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000503#ifndef NANO_SMALL
Chris Allegrettaff989832001-09-17 13:48:00 +0000504 printf(_(" -i Automatically indent new lines\n"));
Chris Allegretta627de192000-07-12 02:09:17 +0000505 printf(_(" -k Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000506#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000507 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000508 (" -l Don't follow symbolic links, overwrite\n"));
Chris Allegretta84de5522001-04-12 14:51:48 +0000509#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000510#ifdef NCURSES_MOUSE_VERSION
511 printf(_(" -m Enable mouse\n"));
512#endif
513#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000514#ifndef DISABLE_OPERATINGDIR
515 printf(_(" -o [dir] Set operating directory\n"));
516#endif
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +0000517 printf(_(" -p Emulate Pico as closely as possible\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000518
519#ifndef DISABLE_WRAPJUSTIFY
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000520 printf(_
521 (" -r [#cols] Set fill cols to (wrap lines at) #cols\n"));
Chris Allegretta6fe61492001-05-21 12:56:25 +0000522#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000523#ifndef DISABLE_SPELLER
Chris Allegrettad55655f2000-12-27 03:36:47 +0000524 printf(_(" -s [prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000525#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000526 printf(_(" -t Auto save on exit, don't prompt\n"));
527 printf(_(" -v View (read only) mode\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000528#ifndef DISABLE_WRAPPING
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000529 printf(_(" -w Don't wrap long lines\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000530#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000531 printf(_(" -x Don't show help window\n"));
532 printf(_(" -z Enable suspend\n"));
533 printf(_(" +LINE Start at line number LINE\n"));
534#endif
535 exit(0);
536}
537
538void version(void)
539{
Chris Allegrettac46dd812001-02-14 14:28:27 +0000540 printf(_(" GNU nano version %s (compiled %s, %s)\n"),
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000541 VERSION, __TIME__, __DATE__);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000542 printf(_
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000543 (" Email: nano@nano-editor.org Web: http://www.nano-editor.org"));
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000544 printf(_("\n Compiled options:"));
Chris Allegrettaff269f82000-12-01 18:46:01 +0000545
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000546#ifdef NANO_EXTRA
547 printf(" --enable-extra");
Chris Allegretta355fbe52001-07-14 19:32:47 +0000548#else
549#ifdef ENABLE_MULTIBUFFER
550 printf(" --enable-multibuffer");
551#endif /* ENABLE_MULTIBUFFER */
552#endif /* NANO_EXTRA */
553
Chris Allegrettab881d3e2001-04-18 04:34:43 +0000554#ifdef ENABLE_NANORC
555 printf(" --enable-nanorc");
556#endif
Chris Allegretta8ce24132001-04-30 11:28:46 +0000557#ifdef ENABLE_COLOR
558 printf(" --enable-color");
559#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000560
561#ifdef NANO_SMALL
562 printf(" --enable-tiny");
563#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000564#ifdef DISABLE_BROWSER
Chris Allegretta6636dc32001-01-05 05:41:07 +0000565 printf(" --disable-browser");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000566#endif
567#ifdef DISABLE_TABCOMP
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000568 printf(" --disable-tabcomp");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000569#endif
570#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +0000571 printf(" --disable-justify");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000572#endif
573#ifdef DISABLE_SPELLER
Chris Allegretta7b36c522000-12-06 01:08:10 +0000574 printf(" --disable-speller");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000575#endif
576#ifdef DISABLE_HELP
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000577 printf(" --disable-help");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000578#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000579#ifdef DISABLE_MOUSE
580 printf(" --disable-mouse");
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000581#endif
Chris Allegrettae1f14522001-09-19 03:19:43 +0000582#ifdef DISABLE_OPERATINGDIR
583 printf(" --disable-operatingdir");
584#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000585#endif /* NANO_SMALL */
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000586
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000587#ifdef DISABLE_WRAPPING
588 printf(" --disable-wrapping");
589#endif
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000590#ifdef USE_SLANG
591 printf(" --with-slang");
592#endif
593 printf("\n");
594
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000595}
596
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000597/* Create a new node. This does NOT initialize the data members used
598 only by open_files. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000599filestruct *make_new_node(filestruct * prevnode)
600{
601 filestruct *newnode;
602
603 newnode = nmalloc(sizeof(filestruct));
604 newnode->data = NULL;
605
606 newnode->prev = prevnode;
607 newnode->next = NULL;
608
609 if (prevnode != NULL)
610 newnode->lineno = prevnode->lineno + 1;
611
612 return newnode;
613}
614
Chris Allegretta2d7893d2001-07-11 02:08:33 +0000615/* Splice a node into an existing filestruct. This does NOT set the data
616 members used only by open_files. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000617void splice_node(filestruct * begin, filestruct * newnode,
618 filestruct * end)
Chris Allegretta7975ed82000-07-28 00:58:35 +0000619{
Chris Allegrettae3167732001-03-18 16:59:34 +0000620 newnode->next = end;
621 newnode->prev = begin;
622 begin->next = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000623 if (end != NULL)
Chris Allegrettae3167732001-03-18 16:59:34 +0000624 end->prev = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000625}
626
Chris Allegrettae3167732001-03-18 16:59:34 +0000627int do_mark(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000628{
629#ifdef NANO_SMALL
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000630 nano_disabled_msg();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000631#else
632 if (!ISSET(MARK_ISSET)) {
633 statusbar(_("Mark Set"));
634 SET(MARK_ISSET);
635 mark_beginbuf = current;
636 mark_beginx = current_x;
637 } else {
638 statusbar(_("Mark UNset"));
639 UNSET(MARK_ISSET);
640 mark_beginbuf = NULL;
641 mark_beginx = 0;
642
643 edit_refresh();
644 }
645#endif
646 return 1;
647}
648
649int no_help(void)
650{
651 if ISSET
652 (NO_HELP)
653 return 2;
654 else
655 return 0;
656}
657
Chris Allegretta3bc8c722000-12-10 17:03:25 +0000658#if defined(DISABLE_JUSTIFY) || defined(DISABLE_SPELLER) || defined(DISABLE_HELP)
Chris Allegrettaff269f82000-12-01 18:46:01 +0000659void nano_disabled_msg(void)
660{
661 statusbar("Sorry, support for this function has been disabled");
662}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000663#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000664
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000665/* The user typed a printable character; add it to the edit buffer */
666void do_char(char ch)
667{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000668 /* magic-line: when a character is inserted on the current magic line,
669 * it means we need a new one! */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000670 if (filebot == current && current->data[0] == '\0') {
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000671 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000672 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000673 }
674
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000675 /* More dangerousness fun =) */
676 current->data = nrealloc(current->data, strlen(current->data) + 2);
677 memmove(&current->data[current_x + 1],
678 &current->data[current_x],
679 strlen(current->data) - current_x + 1);
680 current->data[current_x] = ch;
681 do_right();
682
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000683#ifndef DISABLE_WRAPPING
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000684 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000685 check_wrap(current, ch);
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000686#endif
687
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000688 set_modified();
689 check_statblank();
690 UNSET(KEEP_CUTBUFFER);
691 totsize++;
692
693}
694
695/* Someone hits return *gasp!* */
696int do_enter(filestruct * inptr)
697{
Chris Allegrettae3167732001-03-18 16:59:34 +0000698 filestruct *newnode;
Chris Allegretta68532c32001-09-17 13:49:33 +0000699 char *tmp;
700#ifndef NANO_SMALL
701 char *spc;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000702 int extra = 0;
Chris Allegretta68532c32001-09-17 13:49:33 +0000703#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000704
Chris Allegrettae3167732001-03-18 16:59:34 +0000705 newnode = make_new_node(inptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000706 tmp = &current->data[current_x];
707 current_x = 0;
708
Chris Allegrettaff989832001-09-17 13:48:00 +0000709#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000710 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
711 if (ISSET(AUTOINDENT)) {
712 spc = current->data;
713 if (spc) {
714 while ((*spc == ' ') || (*spc == '\t')) {
715 extra++;
716 spc++;
717 current_x++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +0000718 totsize++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000719 }
Chris Allegretta88b09152001-05-17 11:35:43 +0000720 newnode->data = charalloc(strlen(tmp) + extra + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000721 strncpy(newnode->data, current->data, extra);
722 strcpy(&newnode->data[extra], tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000723 }
Chris Allegrettaff989832001-09-17 13:48:00 +0000724 } else
725#endif
726 {
Chris Allegretta88b09152001-05-17 11:35:43 +0000727 newnode->data = charalloc(strlen(tmp) + 1);
Chris Allegrettae3167732001-03-18 16:59:34 +0000728 strcpy(newnode->data, tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000729 }
730 *tmp = 0;
731
Chris Allegrettada721be2000-07-31 01:26:42 +0000732 if (inptr->next == NULL) {
Chris Allegrettae3167732001-03-18 16:59:34 +0000733 filebot = newnode;
734 editbot = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000735 }
Chris Allegrettae3167732001-03-18 16:59:34 +0000736 splice_node(inptr, newnode, inptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000737
738 totsize++;
739 renumber(current);
Chris Allegrettae3167732001-03-18 16:59:34 +0000740 current = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000741 align(&current->data);
742
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000743 /* The logic here is as follows:
744 * -> If we are at the bottom of the buffer, we want to recenter
Chris Allegretta88520c92001-05-05 17:45:54 +0000745 * (read: rebuild) the screen and forcibly move the cursor.
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000746 * -> otherwise, we want simply to redraw the screen and update
747 * where we think the cursor is.
748 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000749 if (current_y == editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +0000750 edit_update(current, CENTER);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000751 reset_cursor();
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000752 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000753 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000754 edit_refresh();
755 update_cursor();
756 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000757
758 totlines++;
759 set_modified();
760
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000761 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000762 return 1;
763}
764
765int do_enter_void(void)
766{
767 return do_enter(current);
768}
769
770void do_next_word(void)
771{
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000772 filestruct *fileptr, *old;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000773 int i;
774
775 if (current == NULL)
776 return;
777
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000778 old = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000779 i = current_x;
780 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
781 if (fileptr == current) {
782 while (isalnum((int) fileptr->data[i])
783 && fileptr->data[i] != 0)
784 i++;
785
786 if (fileptr->data[i] == 0) {
787 i = 0;
788 continue;
789 }
790 }
791 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
792 i++;
793
794 if (fileptr->data[i] != 0)
795 break;
796
797 i = 0;
798 }
799 if (fileptr == NULL)
800 current = filebot;
801 else
802 current = fileptr;
803
804 current_x = i;
805 placewewant = xplustabs();
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000806
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000807 if (current->lineno >= editbot->lineno)
Chris Allegretta234a34d2000-07-29 04:33:38 +0000808 edit_update(current, CENTER);
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000809 else {
810 /* If we've jumped lines, refresh the old line. We can't just use
811 * current->prev here, because we may have skipped over some blank
812 * lines, in which case the previous line is the wrong one.
813 */
814 if (current != old)
815 update_line(old, 0);
816
817 update_line(current, current_x);
818 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000819
820}
821
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000822#ifndef DISABLE_WRAPPING
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000823void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000824{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000825 int i = 0; /* Index into ->data for line. */
826 int i_tabs = 0; /* Screen position of ->data[i]. */
827 int last_word_end = -1; /* Location of end of last word found. */
828 int current_word_start = -1; /* Location of start of current word. */
829 int current_word_start_t = -1; /* Location of start of current word screen position. */
830 int current_word_end = -1; /* Location of end of current word */
831 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000832 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000833
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000834 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000835 int right = 0;
836 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000837
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000838 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000839
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000840 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000841 if (!isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000842 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000843
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000844 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000845 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000846
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000847 while (!isspace((int) inptr->data[i])
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000848 && inptr->data[i]) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000849 i++;
850 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000851 if (inptr->data[i] < 32)
852 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000853 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000854
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000855 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000856 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000857 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000858 } else {
859 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000860 current_word_end_t = i_tabs - 1;
861 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000862 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000863
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000864 if (inptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000865 if (i_tabs % tabsize != 0);
866 i_tabs += tabsize - (i_tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000867 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000868
Adam Rogoyski09f97962000-06-20 02:50:33 +0000869 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000870 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000871 }
872
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000873 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000874 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000875 * a) one word takes up the whole line with no starting spaces.
876 * - do nothing and return.
877 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000878 * - word starts new line.
879 * - keep white space on original line up to the cursor.
880 * *) cursor is after word at wrap point
881 * - either it's all white space after word, and this routine isn't called.
882 * - or we are actually in case 2 (2 words).
883 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000884 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000885 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000886 * - white space at end of original line is cleared, unless
887 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000888 * b) cursor is at the word at the wrap point.
889 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000890 * - white space on original line is kept to where cursor was.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000891 * c) cursor is past the word at the wrap point.
892 * - word at wrap point starts a new line.
Chris Allegretta56214c62001-09-27 02:46:53 +0000893 * - white space at end of original line is cleared
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000894 */
895
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000896 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000897
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000898 /* Category 1a: one word taking up the whole line with no beginning spaces. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000899 if ((last_word_end == -1) && (!isspace((int) inptr->data[0]))) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000900 for (i = current_word_end; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000901 if (!isspace((int) inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000902 current_word_start = i;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000903 while (!isspace((int) inptr->data[i]) && (i < len)) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000904 i++;
905 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000906 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000907 current_word_end = i;
908 break;
909 }
910 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000911
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000912 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000913 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000914 return;
915 }
916 if (current_x >= last_word_end) {
917 right = (current_x - current_word_start) + 1;
918 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000919 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000920 }
921
Chris Allegretta88b09152001-05-17 11:35:43 +0000922 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000923 strcpy(temp->data, &inptr->data[current_word_start]);
924 inptr->data = nrealloc(inptr->data, last_word_end + 2);
925 inptr->data[last_word_end + 1] = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000926 } else
927 /* Category 1b: one word on the line and word not taking up whole line
928 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000929 if (last_word_end == -1) {
Chris Allegretta88b09152001-05-17 11:35:43 +0000930 temp->data = charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000931 strcpy(temp->data, &inptr->data[current_word_start]);
932
933 /* Inside word, remove it from original, and move cursor to right spot. */
934 if (current_x >= current_word_start) {
935 right = current_x - current_word_start;
Chris Allegretta56214c62001-09-27 02:46:53 +0000936
937 /* Decrease totsize by the number of spaces we removed, less
938 one for the new line we're replacing the spaces with. */
939 totsize -= (current_word_start - 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000940 current_x = 0;
Chris Allegrettaff989832001-09-17 13:48:00 +0000941#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +0000942 if (ISSET(AUTOINDENT)) {
943 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000944 while ((inptr->next->data[i] == ' '
945 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +0000946 i++;
947 right++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000948 }
Chris Allegretta94a78b82001-03-14 08:28:48 +0000949 }
Chris Allegrettaff989832001-09-17 13:48:00 +0000950#endif
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000951 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000952 }
953
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000954 null_at(inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000955
956 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
957 mark_beginbuf = temp;
958 mark_beginx = 0;
959 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000960 }
961
962 /* Category 2: two or more words on the line. */
963 else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000964 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000965 if (current_x < current_word_start) {
966 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +0000967 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000968 strcpy(temp->data, &inptr->data[current_word_start]);
969
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000970 if (!isspace((int) input_char)) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000971 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +0000972
973 /* Decrement totsize each time we remove a space. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000974 while (isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000975 i--;
Chris Allegretta56214c62001-09-27 02:46:53 +0000976 totsize--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000977 assert(i >= 0);
978 }
Chris Allegretta56214c62001-09-27 02:46:53 +0000979 /* And increment it to account for the blank line we're
980 replacing the spaces with. */
981 totsize++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000982 } else if (current_x <= last_word_end)
983 i = last_word_end - 1;
984 else
985 i = current_x;
986
987 inptr->data = nrealloc(inptr->data, i + 2);
988 inptr->data[i + 1] = 0;
989 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000990
991
992 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000993 else if ((current_x >= current_word_start)
994 && (current_x <= (current_word_end + 1))) {
995 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +0000996 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000997 strcpy(temp->data, &inptr->data[current_word_start]);
998
999 down = 1;
1000
1001 right = current_x - current_word_start;
Chris Allegrettaff989832001-09-17 13:48:00 +00001002#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001003 if (ISSET(AUTOINDENT)) {
1004 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001005 while ((inptr->next->data[i] == ' '
1006 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001007 i++;
1008 right++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001009 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001010 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001011#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001012 i = current_word_start - 1;
Chris Allegretta56214c62001-09-27 02:46:53 +00001013 current_x = current_word_start;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001014
Chris Allegretta56214c62001-09-27 02:46:53 +00001015 null_at(inptr->data, current_word_start);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001016
Chris Allegretta56214c62001-09-27 02:46:53 +00001017 /* Increment totsize to account for the new line that
1018 will be added below, so that it won't end up being
1019 short by one. */
1020 totsize++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001021 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001022
1023
1024 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001025 else {
1026 temp->data =
Chris Allegretta88b09152001-05-17 11:35:43 +00001027 charalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001028 strcpy(temp->data, &inptr->data[current_word_start]);
1029
1030 down = 1;
1031 right = current_x - current_word_start;
1032
1033 current_x = current_word_start;
1034 i = current_word_start - 1;
1035
Chris Allegretta56214c62001-09-27 02:46:53 +00001036 /* Decrement totsize each time we remove a space. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001037 while (isspace((int) inptr->data[i])) {
Adam Rogoyski3d449b42000-06-19 17:30:14 +00001038 i--;
Chris Allegretta56214c62001-09-27 02:46:53 +00001039 totsize--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001040 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001041 inptr->data = nrealloc(inptr->data, i + 2);
1042 inptr->data[i + 1] = 0;
1043 }
Chris Allegretta56214c62001-09-27 02:46:53 +00001044 /* And increment it to account for the blank line we're
1045 replacing the spaces with. */
1046 totsize++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001047 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001048 }
1049
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001050 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001051 if (ISSET(SAMELINEWRAP) && inptr->next) {
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001052 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001053
Chris Allegretta94a78b82001-03-14 08:28:48 +00001054 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001055 char *p =
Chris Allegretta88b09152001-05-17 11:35:43 +00001056 charalloc((strlen(temp->data) + strlen(inptr->next->data) + 2));
Chris Allegretta94a78b82001-03-14 08:28:48 +00001057
Chris Allegretta56214c62001-09-27 02:46:53 +00001058 /* We're adding to an existing line instead of creating a new
1059 one; decrement totlines here so that when it gets incremented
1060 below, it won't end up being high by one. */
1061 totlines--;
1062
Chris Allegrettaff989832001-09-17 13:48:00 +00001063#ifndef NANO_SMALL
Chris Allegretta94a78b82001-03-14 08:28:48 +00001064 if (ISSET(AUTOINDENT)) {
1065 int non = 0;
1066
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001067 /* Grab the beginning of the next line until it's not a
1068 space or tab, then null terminate it so we can strcat it
1069 to hell */
1070 while ((inptr->next->data[non] == ' '
Chris Allegretta355fbe52001-07-14 19:32:47 +00001071 || inptr->next->data[non] == '\t')) {
1072 p[non] = inptr->next->data[non];
1073 non++;
1074 }
Chris Allegretta94a78b82001-03-14 08:28:48 +00001075 p[non] = 0;
1076 strcat(p, temp->data);
1077 strcat(p, " ");
1078
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001079 /* Now tack on the rest of the next line after the spaces and
1080 tabs */
Chris Allegretta94a78b82001-03-14 08:28:48 +00001081 strcat(p, &inptr->next->data[non]);
Chris Allegrettaff989832001-09-17 13:48:00 +00001082 } else
1083#endif
1084 {
Chris Allegretta94a78b82001-03-14 08:28:48 +00001085 strcpy(p, temp->data);
1086 strcat(p, " ");
1087 strcat(p, inptr->next->data);
1088 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001089
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001090 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001091 inptr->next->data = p;
1092
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001093 free(temp->data);
1094 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001095
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +00001096 current_x = old_x;
1097 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001098 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001099 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001100 else {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001101
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001102 temp->prev = inptr;
1103 temp->next = inptr->next;
1104
1105 if (inptr->next)
1106 inptr->next->prev = temp;
1107 inptr->next = temp;
1108
1109 if (!temp->next)
1110 filebot = temp;
1111
1112 SET(SAMELINEWRAP);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001113
Chris Allegrettaff989832001-09-17 13:48:00 +00001114#ifndef NANO_SMALL
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001115 if (ISSET(AUTOINDENT)) {
1116 char *spc = inptr->data;
1117 char *t = NULL;
1118 int extra = 0;
1119 if (spc) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001120 while ((*spc == ' ') || (*spc == '\t')) {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001121 extra++;
1122 spc++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001123 totsize++;
1124 }
Chris Allegretta88b09152001-05-17 11:35:43 +00001125 t = charalloc(strlen(temp->data) + extra + 1);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +00001126 strncpy(t, inptr->data, extra);
1127 strcpy(t + extra, temp->data);
1128 free(temp->data);
1129 temp->data = t;
1130 }
1131 }
Chris Allegrettaff989832001-09-17 13:48:00 +00001132#endif
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001133 }
1134
1135
1136 totlines++;
Chris Allegretta88520c92001-05-05 17:45:54 +00001137 /* Everything about it makes me want this line here, but it causes
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001138 * totsize to be high by one for some reason. Sigh. (Rob) */
1139 /* totsize++; */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001140
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001141 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001142 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001143
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001144
1145 /* Move the cursor to the new line if appropriate. */
1146 if (down) {
1147 do_right();
1148 }
1149
1150 /* Move the cursor to the correct spot in the line if appropriate. */
1151 while (right--) {
1152 do_right();
1153 }
1154
Chris Allegretta234a34d2000-07-29 04:33:38 +00001155 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001156 reset_cursor();
1157 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001158}
1159
1160/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001161void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001162{
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001163 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001164#ifdef DEBUG
1165 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
1166 inptr->data);
1167#endif
1168
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001169 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001170 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001171 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001172 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001173
1174 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001175 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001176
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001177 while (isspace((int) inptr->data[i]) && inptr->data[i])
Adam Rogoyski09f97962000-06-20 02:50:33 +00001178 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001179
Adam Rogoyski09f97962000-06-20 02:50:33 +00001180 if (!inptr->data[i])
1181 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001182
Adam Rogoyski09f97962000-06-20 02:50:33 +00001183 /* String must be at least 1 character long. */
1184 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001185 if (isspace((int) inptr->data[i])) {
Adam Rogoyski09f97962000-06-20 02:50:33 +00001186 if (!char_found)
1187 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001188 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001189 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001190 } else
1191 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001192 }
Adam Rogoyski09f97962000-06-20 02:50:33 +00001193
1194 if (char_found == 2)
1195 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001196 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001197}
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001198#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001199
1200/* Stuff we do when we abort from programs and want to clean up the
Chris Allegretta88520c92001-05-05 17:45:54 +00001201 * screen. This doesn't do much right now.
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001202 */
1203void do_early_abort(void)
1204{
1205 blank_statusbar_refresh();
1206}
1207
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001208int do_backspace(void)
1209{
1210 filestruct *previous, *tmp;
1211
1212 if (current_x != 0) {
1213 /* Let's get dangerous */
1214 memmove(&current->data[current_x - 1], &current->data[current_x],
1215 strlen(current->data) - current_x + 1);
1216#ifdef DEBUG
1217 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
1218#endif
1219 align(&current->data);
1220 do_left();
1221 } else {
1222 if (current == fileage)
1223 return 0; /* Can't delete past top of file */
1224
1225 previous = current->prev;
1226 current_x = strlen(previous->data);
1227 previous->data = nrealloc(previous->data,
1228 strlen(previous->data) +
1229 strlen(current->data) + 1);
1230 strcat(previous->data, current->data);
1231
1232 tmp = current;
1233 unlink_node(current);
1234 delete_node(current);
1235 if (current == edittop) {
1236 if (previous->next)
1237 current = previous->next;
1238 else
1239 current = previous;
Chris Allegretta3e3ae942001-09-22 19:02:04 +00001240 page_up();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001241 } else {
1242 if (previous->next)
1243 current = previous->next;
1244 else
1245 current = previous;
1246 update_line(current, current_x);
1247 }
1248
1249 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001250 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001251 filebot = current;
1252 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001253
1254 /* Recreate the magic line if we're deleting it AND if the
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001255 line we're on now is NOT blank. if it is blank we
1256 can just use IT for the magic line. This is how Pico
1257 appears to do it, in any case */
Chris Allegretta28a0f892000-07-05 22:47:54 +00001258 if (strcmp(current->data, "")) {
1259 new_magicline();
1260 fix_editbot();
1261 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001262 }
1263
1264 current = previous;
1265 renumber(current);
1266 previous_line();
1267 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001268#ifdef DEBUG
1269 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
1270#endif
1271
1272 }
1273
1274 totsize--;
1275 set_modified();
1276 UNSET(KEEP_CUTBUFFER);
1277 edit_refresh();
1278 return 1;
1279}
1280
1281int do_delete(void)
1282{
1283 filestruct *foo;
1284
1285 if (current_x != strlen(current->data)) {
1286 /* Let's get dangerous */
1287 memmove(&current->data[current_x], &current->data[current_x + 1],
1288 strlen(current->data) - current_x);
1289
1290 align(&current->data);
1291
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001292 /* Now that we have a magic lnie again, we can check for both being
1293 on the line before filebot as well as at filebot */
Chris Allegretta4ed13152001-02-10 17:50:50 +00001294 } else if (current->next != NULL && current->next != filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001295 current->data = nrealloc(current->data,
1296 strlen(current->data) +
1297 strlen(current->next->data) + 1);
1298 strcat(current->data, current->next->data);
1299
1300 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001301 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001302 filebot = current;
1303 editbot = current;
1304 }
1305
1306 unlink_node(foo);
1307 delete_node(foo);
1308 update_line(current, current_x);
1309
Chris Allegretta4ed13152001-02-10 17:50:50 +00001310 /* Please see the comment in do_backspace if you don't understand
Chris Allegretta28a0f892000-07-05 22:47:54 +00001311 this test */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001312 if (current == filebot && strcmp(current->data, "")) {
Chris Allegretta28a0f892000-07-05 22:47:54 +00001313 new_magicline();
1314 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001315 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001316 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001317 renumber(current);
1318 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001319 } else
1320 return 0;
1321
1322 totsize--;
1323 set_modified();
1324 UNSET(KEEP_CUTBUFFER);
1325 edit_refresh();
1326 return 1;
1327}
1328
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001329void wrap_reset(void)
1330{
1331 UNSET(SAMELINEWRAP);
1332}
1333
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001334#ifndef DISABLE_SPELLER
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001335
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001336int do_int_spell_fix(char *word)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001337{
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001338 char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001339 filestruct *begin;
1340 int i = 0, j = 0, beginx, beginx_top;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001341
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001342 /* save where we are */
1343 begin = current;
1344 beginx = current_x + 1;
1345
1346 /* save the current search/replace strings */
1347 search_init_globals();
1348 save_search = mallocstrcpy(save_search, last_search);
1349 save_replace = mallocstrcpy(save_replace, last_replace);
1350
1351 /* set search/replace strings to mis-spelt word */
1352 prevanswer = mallocstrcpy(prevanswer, word);
1353 last_search = mallocstrcpy(last_search, word);
1354 last_replace = mallocstrcpy(last_replace, word);
1355
1356 /* start from the top of file */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001357 current = fileage;
1358 current_x = beginx_top = -1;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001359
1360 search_last_line = FALSE;
1361
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001362 edit_update(fileage, TOP);
1363
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001364 /* make sure word is still mis-spelt (i.e. when multi-errors) */
Chris Allegretta8d990b52001-09-22 22:14:25 +00001365 if (findnextstr(TRUE, FALSE, fileage, beginx_top, prevanswer) != NULL) {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001366 do_replace_highlight(TRUE, prevanswer);
1367
1368 /* allow replace word to be corrected */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001369 i = statusq(0, spell_list, SPELL_LIST_LEN, last_replace,
1370 _("Edit a replacement"));
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001371
1372 do_replace_highlight(FALSE, prevanswer);
1373
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001374 /* start from the start of this line again */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001375 current = fileage;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001376 current_x = beginx_top;
1377
1378 search_last_line = FALSE;
1379
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001380 j = i;
1381 do_replace_loop(prevanswer, fileage, &beginx_top, TRUE, &j);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001382 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001383
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001384 /* restore the search/replace strings */
1385 last_search = mallocstrcpy(last_search, save_search);
1386 last_replace = mallocstrcpy(last_replace, save_replace);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001387
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001388 /* restore where we were */
1389 current = begin;
1390 current_x = beginx - 1;
1391
1392 edit_update(current, CENTER);
1393
1394 if (i == -1)
1395 return FALSE;
1396
1397 return TRUE;
1398}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001399
1400/* Integrated spell checking using 'spell' program */
Chris Allegretta271e9722000-11-10 18:15:43 +00001401int do_int_speller(char *tempfile_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001402{
Chris Allegretta271e9722000-11-10 18:15:43 +00001403 char *read_buff, *read_buff_ptr, *read_buff_word;
1404 long pipe_buff_size;
1405 int in_fd[2], tempfile_fd;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001406 int spell_status;
1407 pid_t pid_spell;
1408 ssize_t bytesread;
1409
Chris Allegretta271e9722000-11-10 18:15:43 +00001410 /* Create a pipe to spell program */
1411
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001412 if (pipe(in_fd) == -1)
1413 return FALSE;
1414
Chris Allegretta271e9722000-11-10 18:15:43 +00001415 /* A new process to run spell in */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001416
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001417 if ((pid_spell = fork()) == 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001418
1419 /* Child continues, (i.e. future spell process) */
1420
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001421 close(in_fd[0]);
1422
Chris Allegretta271e9722000-11-10 18:15:43 +00001423 /* replace the standard in with the tempfile */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001424
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001425 if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001426
1427 close(in_fd[1]);
1428 exit(1);
1429 }
1430
1431 if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
1432
1433 close(tempfile_fd);
1434 close(in_fd[1]);
1435 exit(1);
1436 }
1437 close(tempfile_fd);
1438
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001439
Chris Allegretta271e9722000-11-10 18:15:43 +00001440 /* send spell's standard out to the pipe */
1441
1442 if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1443
1444 close(in_fd[1]);
1445 exit(1);
1446 }
1447 close(in_fd[1]);
1448
1449 /* Start spell program, we are using the PATH here!?!? */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001450 execlp("spell", "spell", NULL);
1451
Chris Allegretta271e9722000-11-10 18:15:43 +00001452 /* Should not be reached, if spell is found!!! */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001453
Chris Allegretta271e9722000-11-10 18:15:43 +00001454 exit(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001455 }
1456
1457 /* Parent continues here */
1458
Chris Allegretta271e9722000-11-10 18:15:43 +00001459 close(in_fd[1]);
1460
1461 /* Child process was not forked successfully */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001462
1463 if (pid_spell < 0) {
1464
Chris Allegretta271e9722000-11-10 18:15:43 +00001465 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001466 return FALSE;
1467 }
1468
Chris Allegretta271e9722000-11-10 18:15:43 +00001469 /* Get system pipe buffer size */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001470
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001471 if ((pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001472
Chris Allegretta271e9722000-11-10 18:15:43 +00001473 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001474 return FALSE;
Chris Allegretta271e9722000-11-10 18:15:43 +00001475 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001476
Chris Allegretta88b09152001-05-17 11:35:43 +00001477 read_buff = charalloc(pipe_buff_size + 1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001478
Chris Allegretta271e9722000-11-10 18:15:43 +00001479 /* Process the returned spelling errors */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001480
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001481 while ((bytesread = read(in_fd[0], read_buff, pipe_buff_size)) > 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001482
Chris Allegretta271e9722000-11-10 18:15:43 +00001483 read_buff[bytesread] = (char) NULL;
1484 read_buff_word = read_buff_ptr = read_buff;
1485
1486 while (*read_buff_ptr != (char) NULL) {
1487
1488 /* Windows version may need to process additional char '\r' */
1489
1490 /* Possible problem here if last word not followed by '\n' */
1491
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001492 if (*read_buff_ptr == '\n') {
Chris Allegretta271e9722000-11-10 18:15:43 +00001493 *read_buff_ptr = (char) NULL;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001494 if (!do_int_spell_fix(read_buff_word)) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001495
1496 close(in_fd[0]);
1497 free(read_buff);
1498 replace_abort();
1499
1500 return TRUE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001501 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001502 read_buff_word = read_buff_ptr;
1503 read_buff_word++;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001504 }
1505
1506 read_buff_ptr++;
1507 }
1508 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001509
1510 close(in_fd[0]);
1511 free(read_buff);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001512 replace_abort();
1513
Chris Allegretta271e9722000-11-10 18:15:43 +00001514 /* Process end of spell process */
1515
1516 wait(&spell_status);
1517 if (WIFEXITED(spell_status)) {
1518 if (WEXITSTATUS(spell_status) != 0)
1519 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001520 } else
Chris Allegretta271e9722000-11-10 18:15:43 +00001521 return FALSE;
1522
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001523 return TRUE;
1524}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001525
1526/* External spell checking */
Chris Allegretta271e9722000-11-10 18:15:43 +00001527int do_alt_speller(char *file_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001528{
Chris Allegretta1b3381b2001-09-28 21:59:01 +00001529 int alt_spell_status, x_cur = current_x, y_cur = current_y, pww_cur = placewewant;
Chris Allegretta271e9722000-11-10 18:15:43 +00001530 pid_t pid_spell;
Chris Allegretta169ee842001-01-26 01:57:32 +00001531 char *ptr;
Rocco Corsi4dfaf932001-04-20 01:59:55 +00001532 long lineno_cur = current->lineno;
Chris Allegretta169ee842001-01-26 01:57:32 +00001533 static int arglen = 3;
1534 static char **spellargs = (char **) NULL;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001535
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001536 endwin();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001537
Chris Allegrettae434b452001-01-27 19:25:00 +00001538 /* Set up an argument list to pass the execvp function */
1539 if (spellargs == NULL) {
1540 spellargs = nmalloc(arglen * sizeof(char *));
Chris Allegretta271e9722000-11-10 18:15:43 +00001541
Chris Allegrettae434b452001-01-27 19:25:00 +00001542 spellargs[0] = strtok(alt_speller, " ");
1543 while ((ptr = strtok(NULL, " ")) != NULL) {
1544 arglen++;
1545 spellargs = nrealloc(spellargs, arglen * sizeof(char *));
1546 spellargs[arglen - 3] = ptr;
Chris Allegretta169ee842001-01-26 01:57:32 +00001547 }
Chris Allegrettae434b452001-01-27 19:25:00 +00001548 spellargs[arglen - 1] = NULL;
1549 }
1550 spellargs[arglen - 2] = file_name;
1551
1552 /* Start a new process for the alternate speller */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001553 if ((pid_spell = fork()) == 0) {
Chris Allegretta169ee842001-01-26 01:57:32 +00001554
Chris Allegretta88520c92001-05-05 17:45:54 +00001555 /* Start alternate spell program; we are using the PATH here!?!? */
Chris Allegretta169ee842001-01-26 01:57:32 +00001556 execvp(spellargs[0], spellargs);
Chris Allegretta271e9722000-11-10 18:15:43 +00001557
1558 /* Should not be reached, if alternate speller is found!!! */
1559
1560 exit(1);
1561 }
1562
1563 /* Could not fork?? */
1564
1565 if (pid_spell < 0)
1566 return FALSE;
1567
1568 /* Wait for alternate speller to complete */
1569
1570 wait(&alt_spell_status);
1571 if (WIFEXITED(alt_spell_status)) {
1572 if (WEXITSTATUS(alt_spell_status) != 0)
1573 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001574 } else
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001575 return FALSE;
1576
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001577 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001578 free_filestruct(fileage);
Chris Allegretta56214c62001-09-27 02:46:53 +00001579 global_init(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001580 open_file(file_name, 0, 1);
Rocco Corsi4dfaf932001-04-20 01:59:55 +00001581
Chris Allegretta1b3381b2001-09-28 21:59:01 +00001582 /* go back to the old position, mark the file as modified, and make
1583 sure that the titlebar is refreshed */
1584 do_gotopos(lineno_cur, x_cur, y_cur, pww_cur);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001585 set_modified();
Chris Allegrettae1f14522001-09-19 03:19:43 +00001586 clearok(topwin, FALSE);
1587 titlebar(NULL);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001588
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001589 return TRUE;
1590}
1591#endif
1592
1593int do_spell(void)
1594{
1595
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001596#ifdef DISABLE_SPELLER
Chris Allegrettaff269f82000-12-01 18:46:01 +00001597 nano_disabled_msg();
1598 return (TRUE);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001599#else
Chris Allegretta271e9722000-11-10 18:15:43 +00001600 char *temp;
1601 int spell_res;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001602
Chris Allegretta271e9722000-11-10 18:15:43 +00001603 if ((temp = tempnam(0, "nano.")) == NULL) {
1604 statusbar(_("Could not create a temporary filename: %s"),
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001605 strerror(errno));
Chris Allegretta271e9722000-11-10 18:15:43 +00001606 return 0;
1607 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001608
Chris Allegrettaecc3d7f2001-06-05 23:24:55 +00001609 if (write_file(temp, 1, 0, 0) == -1) {
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001610 statusbar(_("Spell checking failed: unable to write temp file!"));
Chris Allegretta271e9722000-11-10 18:15:43 +00001611 return 0;
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001612 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001613
Chris Allegrettae1f14522001-09-19 03:19:43 +00001614#ifdef ENABLE_MULTIBUFFER
1615 /* update the current open_files entry before spell-checking, in case
1616 any problems occur; the case of there being no open_files entries
1617 is handled elsewhere (before we reach this point); no duplicate
1618 checking is needed here */
1619 add_open_file(1, 0);
1620#endif
1621
Chris Allegretta271e9722000-11-10 18:15:43 +00001622 if (alt_speller)
1623 spell_res = do_alt_speller(temp);
1624 else
1625 spell_res = do_int_speller(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001626
Chris Allegretta271e9722000-11-10 18:15:43 +00001627 remove(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001628
1629 if (spell_res)
1630 statusbar(_("Finished checking spelling"));
1631 else
1632 statusbar(_("Spell checking failed"));
1633
1634 return spell_res;
1635
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001636#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001637}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001638
1639int do_exit(void)
1640{
1641 int i;
1642
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001643 if (!ISSET(MODIFIED)) {
1644
Chris Allegretta355fbe52001-07-14 19:32:47 +00001645#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001646 if (!close_open_file()) {
1647 display_main_list();
1648 return 1;
1649 }
1650 else
1651#endif
1652
1653 finish(0);
1654 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001655
Chris Allegretta30885552000-07-14 01:20:12 +00001656 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001657 i = 1;
1658 } else {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001659 i = do_yesno(0, 0,
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001660 _
1661 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1662 }
1663
1664#ifdef DEBUG
1665 dump_buffer(fileage);
1666#endif
1667
1668 if (i == 1) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001669 if (do_writeout(filename, 1, 0) > 0) {
1670
Chris Allegretta355fbe52001-07-14 19:32:47 +00001671#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001672 if (!close_open_file()) {
1673 display_main_list();
1674 return 1;
1675 }
1676 else
1677#endif
1678
1679 finish(0);
1680 }
1681 } else if (i == 0) {
1682
Chris Allegretta355fbe52001-07-14 19:32:47 +00001683#ifdef ENABLE_MULTIBUFFER
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001684 if (!close_open_file()) {
1685 display_main_list();
1686 return 1;
1687 }
1688 else
1689#endif
1690
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001691 finish(0);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00001692 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001693 statusbar(_("Cancelled"));
1694
1695 display_main_list();
1696 return 1;
1697}
1698
Chris Allegretta84de5522001-04-12 14:51:48 +00001699#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001700#ifdef NCURSES_MOUSE_VERSION
1701void do_mouse(void)
1702{
1703 MEVENT mevent;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001704 int foo = 0, tab_found = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001705
1706 if (getmouse(&mevent) == ERR)
1707 return;
1708
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001709 /* If mouse not in edit or bottom window, return */
1710 if (wenclose(edit, mevent.y, mevent.x)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001711
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001712 /* Don't let people screw with the marker when they're in a
1713 subfunction */
1714 if (currshortcut != main_list)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001715 return;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001716
1717 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1718 mevent.y -= 2;
1719
1720 /* Selecting where the cursor is sets the mark.
1721 * Selecting beyond the line length with the cursor at the end of the
1722 * line sets the mark as well.
1723 */
1724 if ((mevent.y == current_y) &&
1725 ((mevent.x == current_x) || (current_x == strlen(current->data)
1726 && (mevent.x >
1727 strlen(current->data))))) {
1728 if (ISSET(VIEW_MODE)) {
1729 print_view_warning();
1730 return;
1731 }
1732 do_mark();
1733 } else if (mevent.y > current_y) {
1734 while (mevent.y > current_y) {
1735 if (current->next != NULL)
1736 current = current->next;
1737 else
1738 break;
1739 current_y++;
1740 }
1741 } else if (mevent.y < current_y) {
1742 while (mevent.y < current_y) {
1743 if (current->prev != NULL)
1744 current = current->prev;
1745 else
1746 break;
1747 current_y--;
1748 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001749 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001750 current_x = mevent.x;
1751 placewewant = current_x;
1752 while (foo < current_x) {
1753 if (current->data[foo] == NANO_CONTROL_I) {
1754 current_x -= tabsize - (foo % tabsize);
1755 tab_found = 1;
1756 } else if (current->data[foo] & 0x80);
1757 else if (current->data[foo] < 32)
1758 current_x--;
1759 foo++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001760 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001761 /* This is where tab_found comes in. I can't figure out why,
1762 * but without it any line with a tab will place the cursor
1763 * one character behind. Whatever, this fixes it. */
1764 if (tab_found == 1)
1765 current_x++;
1766
1767 if (current_x > strlen(current->data))
1768 current_x = strlen(current->data);
1769
1770 update_cursor();
1771 edit_refresh();
1772 } else if (wenclose(bottomwin, mevent.y, mevent.x) && !ISSET(NO_HELP)) {
Chris Allegrettaa951f212001-09-27 21:07:39 +00001773
1774 int k, val = 0;
1775
1776 if (currslen < 2)
1777 k = COLS / 6;
1778 else
1779 k = COLS / ((currslen + (currslen %2)) / 2);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001780
1781 /* Determine what shortcut list was clicked */
1782 mevent.y -= (editwinrows + 3);
1783
1784 if (mevent.y < 0) /* They clicked on the statusbar */
1785 return;
1786
1787 /* Don't select stuff beyond list length */
1788 if (mevent.x / k >= currslen)
1789 return;
1790
1791 val = currshortcut[(mevent.x / k) * 2 + mevent.y].val;
1792
1793 /* And ungetch that value */
1794 ungetch(val);
Chris Allegretta6414b402001-09-21 03:21:11 +00001795
1796 /* And if it's an alt-key sequence, we should probably send alt
1797 too ;-) */
1798 if (val >= 'a' && val <= 'z')
1799 ungetch(27);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001800 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001801}
1802#endif
1803#endif
1804
1805/* Handler for SIGHUP */
1806RETSIGTYPE handle_hup(int signal)
1807{
Chris Allegrettae7a58932000-12-02 02:36:22 +00001808 die(_("Received SIGHUP"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001809}
1810
Chris Allegretta18f8be02000-09-04 03:20:38 +00001811/* What do we do when we catch the suspend signal */
1812RETSIGTYPE do_suspend(int signal)
1813{
Chris Allegretta18f8be02000-09-04 03:20:38 +00001814 endwin();
Chris Allegretta521e00d2001-06-28 16:52:52 +00001815 printf("\n\n\n\n\nUse \"fg\" to return to nano\n");
1816 fflush(stdout);
1817
1818 /* We used to re-enable the default SIG_DFL and raise SIGTSTP, but
1819 then we could be (and were) interrupted in the middle of the call.
1820 So we do it the mutt way instead */
1821 kill(0, SIGSTOP);
Chris Allegretta18f8be02000-09-04 03:20:38 +00001822}
1823
1824/* Restore the suspend handler when we come back into the prog */
1825RETSIGTYPE do_cont(int signal)
1826{
1827
Chris Allegretta521e00d2001-06-28 16:52:52 +00001828 /* Now we just update the screen instead of having to reenable the
1829 SIGTSTP handler */
1830
Chris Allegretta521e00d2001-06-28 16:52:52 +00001831 doupdate();
Chris Allegretta18f8be02000-09-04 03:20:38 +00001832}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001833
1834void handle_sigwinch(int s)
1835{
1836#ifndef NANO_SMALL
1837 char *tty = NULL;
1838 int fd = 0;
1839 int result = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001840 struct winsize win;
1841
1842 tty = ttyname(0);
1843 if (!tty)
1844 return;
1845 fd = open(tty, O_RDWR);
1846 if (fd == -1)
1847 return;
1848 result = ioctl(fd, TIOCGWINSZ, &win);
1849 if (result == -1)
1850 return;
1851
1852
1853 COLS = win.ws_col;
1854 LINES = win.ws_row;
1855
Chris Allegrettae61e8302001-01-14 05:18:27 +00001856 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1857 die_too_small();
1858
Chris Allegretta6fe61492001-05-21 12:56:25 +00001859#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettae61e8302001-01-14 05:18:27 +00001860 if ((fill = COLS - CHARS_FROM_EOL) < MIN_FILL_LENGTH)
1861 die_too_small();
Chris Allegretta6fe61492001-05-21 12:56:25 +00001862#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001863
Chris Allegretta0a06e072001-01-23 02:35:04 +00001864 hblank = nrealloc(hblank, COLS + 1);
1865 memset(hblank, ' ', COLS);
1866 hblank[COLS] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001867
Chris Allegretta618f5d72001-02-16 04:48:30 +00001868#ifdef HAVE_RESIZETERM
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001869 resizeterm(LINES, COLS);
1870#ifdef HAVE_WRESIZE
1871 if (wresize(topwin, 2, COLS) == ERR)
1872 die(_("Cannot resize top win"));
1873 if (mvwin(topwin, 0, 0) == ERR)
1874 die(_("Cannot move top win"));
1875 if (wresize(edit, editwinrows, COLS) == ERR)
1876 die(_("Cannot resize edit win"));
1877 if (mvwin(edit, 2, 0) == ERR)
1878 die(_("Cannot move edit win"));
1879 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1880 die(_("Cannot resize bottom win"));
1881 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1882 die(_("Cannot move bottom win"));
1883#endif /* HAVE_WRESIZE */
Chris Allegretta618f5d72001-02-16 04:48:30 +00001884#endif /* HAVE_RESIZETERM */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001885
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001886 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001887
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001888 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001889 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001890 }
1891 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00001892
1893 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001894 refresh();
Chris Allegrettaf4b96012001-01-03 07:11:47 +00001895 titlebar(NULL);
Chris Allegretta97accc62000-06-19 05:45:52 +00001896 edit_refresh();
1897 display_main_list();
Chris Allegretta08020882001-01-29 23:37:54 +00001898 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001899 total_refresh();
Chris Allegretta08020882001-01-29 23:37:54 +00001900
Chris Allegretta4e90c402001-01-29 23:40:43 +00001901 /* Turn cursor back on for sure */
1902 curs_set(1);
1903
Chris Allegretta08020882001-01-29 23:37:54 +00001904 /* Jump back to mainloop */
1905 siglongjmp(jmpbuf, 1);
1906
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001907#endif
1908}
1909
Chris Allegretta756f2202000-09-01 13:32:47 +00001910void signal_init(void)
1911{
Chris Allegrettaac899e52001-06-30 04:09:09 +00001912#ifdef _POSIX_VDISABLE
1913 struct termios term;
1914#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00001915
Chris Allegretta88520c92001-05-05 17:45:54 +00001916 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
Chris Allegretta756f2202000-09-01 13:32:47 +00001917 memset(&act, 0, sizeof(struct sigaction));
1918 act.sa_handler = SIG_IGN;
1919 sigaction(SIGINT, &act, NULL);
Chris Allegretta756f2202000-09-01 13:32:47 +00001920
Chris Allegretta88520c92001-05-05 17:45:54 +00001921 /* Trap SIGHUP cuz we want to write the file out. */
Chris Allegretta756f2202000-09-01 13:32:47 +00001922 act.sa_handler = handle_hup;
1923 sigaction(SIGHUP, &act, NULL);
1924
1925 act.sa_handler = handle_sigwinch;
1926 sigaction(SIGWINCH, &act, NULL);
1927
Chris Allegretta521e00d2001-06-28 16:52:52 +00001928 if (!ISSET(SUSPEND)) {
Chris Allegrettaac899e52001-06-30 04:09:09 +00001929
1930/* Insane! */
1931#ifdef _POSIX_VDISABLE
1932 tcgetattr(0, &term);
1933 term.c_cc[VSUSP] = _POSIX_VDISABLE;
1934 tcsetattr(0, TCSANOW, &term);
1935#else
1936 act.sa_handler = SIG_IGN;
Chris Allegretta521e00d2001-06-28 16:52:52 +00001937 sigaction(SIGTSTP, &act, NULL);
Chris Allegrettaac899e52001-06-30 04:09:09 +00001938#endif
1939
Chris Allegretta521e00d2001-06-28 16:52:52 +00001940 } else {
1941 /* if we don't do this, it seems other stuff interrupts the
1942 suspend handler! Try using nano with mutt without this line */
1943 sigfillset(&act.sa_mask);
1944
1945 act.sa_handler = do_suspend;
1946 sigaction(SIGTSTP, &act, NULL);
1947
1948 act.sa_handler = do_cont;
1949 sigaction(SIGCONT, &act, NULL);
1950 }
1951
Chris Allegretta756f2202000-09-01 13:32:47 +00001952}
1953
Chris Allegretta2a42af12000-09-12 23:02:49 +00001954void window_init(void)
1955{
Chris Allegrettae61e8302001-01-14 05:18:27 +00001956 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1957 die_too_small();
Chris Allegretta92c9dd22000-09-13 14:03:27 +00001958
Chris Allegretta88520c92001-05-05 17:45:54 +00001959 /* Set up the main text window */
Chris Allegretta2a42af12000-09-12 23:02:49 +00001960 edit = newwin(editwinrows, COLS, 2, 0);
1961
1962 /* And the other windows */
1963 topwin = newwin(2, COLS, 0, 0);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001964 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00001965
Chris Allegretta155d6202001-01-08 01:50:37 +00001966#ifdef PDCURSES
1967 /* Oops, I guess we need this again.
1968 Moved here so the keypad still works after a Meta-X, for example */
1969 keypad(edit, TRUE);
1970 keypad(bottomwin, TRUE);
1971#endif
1972
Chris Allegretta2a42af12000-09-12 23:02:49 +00001973}
1974
Chris Allegretta756f2202000-09-01 13:32:47 +00001975void mouse_init(void)
1976{
Chris Allegretta84de5522001-04-12 14:51:48 +00001977#ifndef DISABLE_MOUSE
Chris Allegretta756f2202000-09-01 13:32:47 +00001978#ifdef NCURSES_MOUSE_VERSION
1979 if (ISSET(USE_MOUSE)) {
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001980 keypad_on(edit, 1);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001981 keypad_on(bottomwin, 1);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001982
Chris Allegretta756f2202000-09-01 13:32:47 +00001983 mousemask(BUTTON1_RELEASED, NULL);
1984 mouseinterval(50);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00001985
Chris Allegretta63c8ab92001-01-04 02:33:52 +00001986 } else
Chris Allegretta756f2202000-09-01 13:32:47 +00001987 mousemask(0, NULL);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00001988
Chris Allegretta756f2202000-09-01 13:32:47 +00001989#endif
1990#endif
1991
1992}
1993
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001994int do_tab(void)
1995{
1996 do_char('\t');
1997 return 1;
1998}
1999
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002000#ifndef DISABLE_JUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002001int empty_line(const char *data)
2002{
2003 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002004 if (!isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002005 return 0;
2006
2007 data++;
2008 }
2009
2010 return 1;
2011}
2012
2013int no_spaces(const char *data)
2014{
2015 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002016 if (isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002017 return 0;
2018
2019 data++;
2020 }
2021
2022 return 1;
2023}
2024
2025void justify_format(char *data)
2026{
2027 int i = 0;
2028 int len = strlen(data);
2029
2030 /* Skip first character regardless and leading whitespace. */
2031 for (i = 1; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002032 if (!isspace((int) data[i]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002033 break;
2034 }
2035
2036 i++; /* (i) is now at least 2. */
2037
2038 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
2039 for (; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002040 if (isspace((int) data[i]) && isspace((int) data[i - 1])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002041 && (data[i - 2] != '.')) {
2042 memmove(data + i, data + i + 1, len - i);
2043 len--;
2044 i--;
2045 }
2046 }
2047}
2048#endif
2049
2050int do_justify(void)
2051{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002052#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +00002053 nano_disabled_msg();
2054 return 1;
2055#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002056 int slen = 0; /* length of combined lines on one line. */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002057 int initial_y, kbinput = 0, totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002058 filestruct *initial = NULL, *tmpjust = NULL, *cutbak, *tmptop, *tmpbot;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002059
2060 if (empty_line(current->data)) {
2061 /* Justify starting at first non-empty line. */
2062 do {
2063 if (!current->next)
2064 return 1;
2065
2066 current = current->next;
2067 current_y++;
2068 }
2069 while (empty_line(current->data));
2070 } else {
2071 /* Search back for the beginning of the paragraph, where
2072 * Paragraph is 1) A line with leading whitespace
2073 * or 2) A line following an empty line.
2074 */
2075 while (current->prev != NULL) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002076 if (isspace((int) current->data[0]) || !current->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002077 break;
2078
2079 current = current->prev;
2080 current_y--;
2081 }
2082
2083 /* First line with leading whitespace may be empty. */
2084 if (empty_line(current->data)) {
2085 if (current->next) {
2086 current = current->next;
2087 current_y++;
2088 } else
2089 return 1;
2090 }
2091 }
2092 initial = current;
2093 initial_y = current_y;
2094
2095 set_modified();
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002096 cutbak = cutbuffer; /* Got to like cutbak ;) */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002097 totbak = totsize;
Chris Allegretta9149e612000-11-27 00:23:41 +00002098 cutbuffer = NULL;
2099
2100 tmptop = current;
2101 tmpjust = copy_node(current);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002102
2103 /* This is annoying because it mucks with totsize */
Chris Allegretta9149e612000-11-27 00:23:41 +00002104 add_to_cutbuffer(tmpjust);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002105
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002106 /* Put the whole paragraph into one big line. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002107 while (current->next && !isspace((int) current->next->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002108 && current->next->data[0]) {
2109 filestruct *tmpnode = current->next;
2110 int len = strlen(current->data);
2111 int len2 = strlen(current->next->data);
2112
Chris Allegretta9149e612000-11-27 00:23:41 +00002113 tmpjust = NULL;
Chris Allegretta9149e612000-11-27 00:23:41 +00002114 tmpjust = copy_node(current->next);
2115 add_to_cutbuffer(tmpjust);
2116
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002117 /* Wiping out a newline */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002118 totsize--;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002119
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002120 /* length of both strings plus space between strings and ending \0. */
2121 current->data = nrealloc(current->data, len + len2 + 2);
2122 current->data[len++] = ' ';
2123 current->data[len] = '\0';
2124
2125 strncat(current->data, current->next->data, len2);
2126
2127 unlink_node(tmpnode);
2128 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002129 }
2130
2131 justify_format(current->data);
2132
2133 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002134 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002135
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002136 if ((strlenpt(current->data) > (fill))
2137 && !no_spaces(current->data)) {
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002138 do {
2139 int i = 0;
2140 int len2 = 0;
2141 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002142
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002143 /* Start at fill , unless line isn't that long (but it
2144 * appears at least fill long with tabs.
2145 */
2146 if (slen > fill)
2147 i = fill;
2148 else
2149 i = slen;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002150
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002151 for (; i > 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00002152 if (isspace((int) current->data[i]) &&
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002153 ((strlenpt(current->data) - strlen(current->data + i))
2154 <= fill))
2155 break;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002156 }
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00002157
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002158 if (!i)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002159 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002160
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002161 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002162
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002163 len2 = strlen(current->data + i + 1);
Chris Allegretta88b09152001-05-17 11:35:43 +00002164 tmpline->data = charalloc(len2 + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002165
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002166 /* Skip the white space in current. */
2167 memcpy(tmpline->data, current->data + i + 1, len2);
2168 tmpline->data[len2] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002169
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002170 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002171
Robert Siemborskia417ddc2000-07-24 23:18:48 +00002172 tmpline->prev = current;
2173 tmpline->next = current->next;
2174 if (current->next != NULL)
2175 current->next->prev = tmpline;
2176
2177 current->next = tmpline;
2178 current = tmpline;
2179 slen -= i + 1;
2180 current_y++;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002181 } while ((strlenpt(current->data) > (fill))
2182 && !no_spaces(current->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002183 }
Chris Allegretta9149e612000-11-27 00:23:41 +00002184 tmpbot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002185
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002186 if (current->next)
2187 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00002188 else
2189 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002190 current_x = 0;
2191 placewewant = 0;
2192
Adam Rogoyski09f97962000-06-20 02:50:33 +00002193 renumber(initial);
2194 totlines = filebot->lineno;
2195
2196 werase(edit);
2197
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002198 if ((current_y < 0) || (current_y >= editwinrows - 1)
2199 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00002200 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002201 center_cursor();
2202 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00002203 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002204 }
2205
Adam Rogoyski09f97962000-06-20 02:50:33 +00002206 edit_refresh();
Chris Allegretta9149e612000-11-27 00:23:41 +00002207 statusbar(_("Can now UnJustify!"));
Chris Allegretta07798352000-11-27 22:58:23 +00002208 /* Change the shortcut list to display the unjustify code */
2209 shortcut_init(1);
2210 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002211 reset_cursor();
2212
Chris Allegretta88520c92001-05-05 17:45:54 +00002213 /* Now get a keystroke and see if it's unjustify; if not, unget the keystroke
Chris Allegretta9149e612000-11-27 00:23:41 +00002214 and return */
Chris Allegretta5f071802001-05-06 02:34:31 +00002215
2216#ifndef DISABLE_MOUSE
2217#ifdef NCURSES_MOUSE_VERSION
2218
2219 /* If it was a mouse click, parse it with do_mouse and it might become
2220 the unjustify key. Else give it back to the input stream. */
2221 if ((kbinput = wgetch(edit)) == KEY_MOUSE)
2222 do_mouse();
2223 else
2224 ungetch(kbinput);
2225#endif
2226#endif
2227
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002228 if ((kbinput = wgetch(edit)) != NANO_UNJUSTIFY_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002229 ungetch(kbinput);
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002230 blank_statusbar_refresh();
2231 } else {
Chris Allegretta9149e612000-11-27 00:23:41 +00002232 /* Else restore the justify we just did (ungrateful user!) */
2233 if (tmptop->prev != NULL)
2234 tmptop->prev->next = tmpbot->next;
Chris Allegrettad022eac2000-11-27 02:50:49 +00002235 else
2236 fileage = current;
Chris Allegretta9149e612000-11-27 00:23:41 +00002237 tmpbot->next->prev = tmptop->prev;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002238 current = tmpbot->next;
Chris Allegretta9149e612000-11-27 00:23:41 +00002239 tmpbot->next = NULL;
2240 do_uncut_text();
Chris Allegrettad022eac2000-11-27 02:50:49 +00002241 if (tmptop->prev == NULL)
2242 edit_refresh();
2243
Chris Allegretta88520c92001-05-05 17:45:54 +00002244 /* Restore totsize from before justify */
Chris Allegretta17dcb722001-01-20 21:40:07 +00002245 totsize = totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002246 free_filestruct(tmptop);
2247 blank_statusbar_refresh();
2248 }
Chris Allegretta4a9c8582000-11-27 22:59:40 +00002249 shortcut_init(0);
2250 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002251 free_filestruct(cutbuffer);
2252 cutbuffer = cutbak;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002253
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002254 return 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002255#endif
2256}
2257
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002258#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002259void help_init(void)
2260{
2261 int i, sofar = 0;
2262 long allocsize = 1; /* How much space we're gonna need for the help text */
Chris Allegretta220ba692000-12-18 03:40:00 +00002263 char buf[BUFSIZ] = "";
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002264
2265 /* Compute the space needed for the shortcut lists - we add 15 to
2266 have room for the shortcut abbrev and its possible alternate keys */
Chris Allegretta220ba692000-12-18 03:40:00 +00002267 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002268 if (main_list[i].help != NULL)
2269 allocsize += strlen(main_list[i].help) + 15;
2270
Chris Allegretta756f2202000-09-01 13:32:47 +00002271 /* And for the toggle list, we also allocate space for extra text. */
Chris Allegretta423cbfd2000-09-04 16:21:29 +00002272 for (i = 0; i <= TOGGLE_LEN - 1; i++)
Chris Allegretta756f2202000-09-01 13:32:47 +00002273 if (toggles[i].desc != NULL)
2274 allocsize += strlen(toggles[i].desc) + 30;
2275
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002276 allocsize += strlen(help_text_init);
2277
2278 if (help_text != NULL)
2279 free(help_text);
2280
2281 /* Allocate space for the help text */
Chris Allegretta88b09152001-05-17 11:35:43 +00002282 help_text = charalloc(allocsize);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002283
2284 /* Now add the text we want */
2285 strcpy(help_text, help_text_init);
2286
2287 /* Now add our shortcut info */
Chris Allegretta220ba692000-12-18 03:40:00 +00002288 for (i = 0; i <= MAIN_LIST_LEN - 1; i++) {
Chris Allegretta8d990b52001-09-22 22:14:25 +00002289 if (main_list[i].val)
2290 sofar = snprintf(buf, BUFSIZ, "^%c ", main_list[i].val + 64);
2291 else
2292 sofar = snprintf(buf, BUFSIZ, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002293
2294 if (main_list[i].misc1 > KEY_F0 && main_list[i].misc1 <= KEY_F(64))
Robert Siemborski6af14312000-07-01 21:34:26 +00002295 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002296 main_list[i].misc1 - KEY_F0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002297 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002298 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002299
Chris Allegretta8d990b52001-09-22 22:14:25 +00002300 if (main_list[i].altval > 0 && main_list[i].altval < 91)
Chris Allegrettae49f1232000-09-02 07:20:39 +00002301 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002302 main_list[i].altval - 32);
Chris Allegretta8d990b52001-09-22 22:14:25 +00002303 else if (main_list[i].altval > 0)
2304 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
2305 main_list[i].altval);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002306 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002307 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002308
Chris Allegretta756f2202000-09-01 13:32:47 +00002309
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002310 if (main_list[i].help != NULL)
Robert Siemborski976847c2000-07-06 03:43:05 +00002311 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", main_list[i].help);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002312
Chris Allegretta756f2202000-09-01 13:32:47 +00002313
2314 strcat(help_text, buf);
2315 strcat(help_text, "\n");
2316 }
2317
2318 /* And the toggles... */
Chris Allegretta423cbfd2000-09-04 16:21:29 +00002319 for (i = 0; i <= TOGGLE_LEN - 1; i++) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002320 if (toggles[i].override_ch != 0)
2321 sofar = snprintf(buf, BUFSIZ,
2322 "M-%c ", toggles[i].override_ch);
2323 else
2324 sofar = snprintf(buf, BUFSIZ,
2325 "M-%c ", toggles[i].val - 32);
Chris Allegretta756f2202000-09-01 13:32:47 +00002326
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002327 if (toggles[i].desc != NULL) {
2328 if (toggles[i].flag != 0)
2329 snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
2330 toggles[i].desc);
2331 else
Chris Allegrettaa212acf2001-07-13 02:00:49 +00002332 snprintf(&buf[sofar], BUFSIZ - sofar, "%s",
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002333 toggles[i].desc);
2334 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002335
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002336 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00002337 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002338 }
2339
2340}
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002341#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002342
Chris Allegretta756f2202000-09-01 13:32:47 +00002343void do_toggle(int which)
2344{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002345#ifdef NANO_SMALL
2346 nano_disabled_msg();
2347#else
Jordi Mallach2dc0f6b2000-09-07 10:48:00 +00002348 char *enabled = _("enabled");
2349 char *disabled = _("disabled");
Chris Allegrettaf0f63a82000-09-02 18:44:21 +00002350
Chris Allegretta8d990b52001-09-22 22:14:25 +00002351 switch (toggles[which].val) {
2352 case TOGGLE_BACKWARDS_KEY:
2353 case TOGGLE_CASE_KEY:
2354 case TOGGLE_REGEXP_KEY:
2355 return;
2356 }
Chris Allegretta8d990b52001-09-22 22:14:25 +00002357
Chris Allegretta658399a2001-06-14 02:54:22 +00002358 /* Even easier! */
2359 TOGGLE(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002360
Chris Allegretta756f2202000-09-01 13:32:47 +00002361 switch (toggles[which].val) {
2362 case TOGGLE_PICOMODE_KEY:
Chris Allegretta07798352000-11-27 22:58:23 +00002363 shortcut_init(0);
Chris Allegrettac1049ac2001-08-17 00:03:46 +00002364 SET(CLEAR_BACKUPSTRING);
Chris Allegretta756f2202000-09-01 13:32:47 +00002365 display_main_list();
2366 break;
2367 case TOGGLE_SUSPEND_KEY:
2368 signal_init();
2369 break;
2370 case TOGGLE_MOUSE_KEY:
2371 mouse_init();
2372 break;
2373 case TOGGLE_NOHELP_KEY:
Chris Allegretta2a42af12000-09-12 23:02:49 +00002374 wclear(bottomwin);
2375 wrefresh(bottomwin);
2376 window_init();
Chris Allegrettaaffeda82000-12-18 04:03:48 +00002377 fix_editbot();
Chris Allegretta2a42af12000-09-12 23:02:49 +00002378 edit_refresh();
2379 display_main_list();
Chris Allegretta756f2202000-09-01 13:32:47 +00002380 break;
Chris Allegretta99e30e12001-09-23 02:45:27 +00002381 case TOGGLE_DOS_KEY:
2382 UNSET(MAC_FILE);
2383 break;
2384 case TOGGLE_MAC_KEY:
2385 UNSET(DOS_FILE);
2386 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002387 }
Chris Allegretta2a42af12000-09-12 23:02:49 +00002388
Chris Allegretta819e3db2001-07-11 02:37:19 +00002389 if (!ISSET(toggles[which].flag)) {
2390 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
2391 toggles[which].val == TOGGLE_WRAP_KEY)
2392 statusbar("%s %s", toggles[which].desc, enabled);
2393 else
2394 statusbar("%s %s", toggles[which].desc, disabled);
2395 } else {
2396 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
2397 toggles[which].val == TOGGLE_WRAP_KEY)
2398 statusbar("%s %s", toggles[which].desc, disabled);
2399 else
2400 statusbar("%s %s", toggles[which].desc, enabled);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002401 }
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002402
Chris Allegretta756f2202000-09-01 13:32:47 +00002403#endif
2404}
2405
Chris Allegretta88520c92001-05-05 17:45:54 +00002406/* If the NumLock key has made the keypad go awry, print an error
2407 message; hopefully we can address it later. */
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002408void print_numlock_warning(void)
2409{
2410 static int didmsg = 0;
2411 if (!didmsg) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002412 statusbar(_
2413 ("NumLock glitch detected. Keypad will malfunction with NumLock off"));
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002414 didmsg = 1;
2415 }
2416}
2417
Chris Allegretta1748cd12001-01-13 17:22:54 +00002418/* This function returns the correct keystroke, given the A,B,C or D
2419 input key. This is a common sequence of many terms which send
2420 Esc-O-[A-D] or Esc-[-[A-D]. */
2421int ABCD(int input)
2422{
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002423 switch (input) {
2424 case 'A':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002425 case 'a':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002426 return (KEY_UP);
2427 case 'B':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002428 case 'b':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002429 return (KEY_DOWN);
2430 case 'C':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002431 case 'c':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002432 return (KEY_RIGHT);
2433 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002434 case 'd':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002435 return (KEY_LEFT);
2436 default:
2437 return 0;
Chris Allegretta1748cd12001-01-13 17:22:54 +00002438 }
2439}
2440
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002441int main(int argc, char *argv[])
2442{
2443 int optchr;
2444 int kbinput; /* Input from keyboard */
2445 long startline = 0; /* Line to try and start at */
Chris Allegretta08020882001-01-29 23:37:54 +00002446 int keyhandled; /* Have we handled the keystroke yet? */
2447 int i, modify_control_seq;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002448 char *argv0;
Chris Allegretta0357c4d2001-09-19 02:59:25 +00002449 filestruct *oldcurrent; /* Check to constantly update */
2450 int oldcurrent_x; /* Same */
2451
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002452#ifdef _POSIX_VDISABLE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002453 struct termios term;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002454#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002455
2456#ifdef HAVE_GETOPT_LONG
2457 int option_index = 0;
2458 struct option long_options[] = {
Chris Allegretta805c26d2000-09-06 13:39:17 +00002459#ifdef HAVE_REGEX_H
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002460 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00002461#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002462 {"version", 0, 0, 'V'},
2463 {"const", 0, 0, 'c'},
2464 {"suspend", 0, 0, 'z'},
2465 {"nowrap", 0, 0, 'w'},
2466 {"nohelp", 0, 0, 'x'},
2467 {"help", 0, 0, 'h'},
Chris Allegretta7492cec2000-12-18 04:55:21 +00002468 {"view", 0, 0, 'v'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002469#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002470 {"cut", 0, 0, 'k'},
Chris Allegretta7004c282001-09-22 00:42:10 +00002471 {"dos", 0, 0, 'D'},
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002472 {"mac", 0, 0, 'M'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002473 {"autoindent", 0, 0, 'i'},
Chris Allegrettaff989832001-09-17 13:48:00 +00002474#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002475 {"tempfile", 0, 0, 't'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002476#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002477 {"speller", 1, 0, 's'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002478#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00002479
2480#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002481 {"fill", 1, 0, 'r'},
Chris Allegretta6fe61492001-05-21 12:56:25 +00002482#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002483 {"mouse", 0, 0, 'm'},
Chris Allegrettae1f14522001-09-19 03:19:43 +00002484#ifndef DISABLE_OPERATINGDIR
2485 {"operatingdir", 1, 0, 'o'},
2486#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002487 {"pico", 0, 0, 'p'},
2488 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00002489 {"tabsize", 1, 0, 'T'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002490
Chris Allegretta355fbe52001-07-14 19:32:47 +00002491#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002492 {"multibuffer", 0, 0, 'F'},
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002493#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002494#ifndef NANO_SMALL
2495 {"smooth", 0, 0, 'S'},
2496#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002497 {0, 0, 0, 0}
2498 };
2499#endif
2500
2501 /* Flag inits... */
2502 SET(FOLLOW_SYMLINKS);
2503
2504#ifndef NANO_SMALL
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002505#ifdef ENABLE_NLS
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002506 setlocale(LC_ALL, "");
2507 bindtextdomain(PACKAGE, LOCALEDIR);
2508 textdomain(PACKAGE);
2509#endif
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002510#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002511
Chris Allegretta8d8e0122001-04-18 04:28:54 +00002512#ifdef ENABLE_NANORC
2513 do_rcfile();
2514#endif /* ENABLE_NANORC */
2515
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002516#ifdef HAVE_GETOPT_LONG
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002517 while ((optchr = getopt_long(argc, argv, "h?DFMRST:Vabcefgijklmo:pr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002518 long_options, &option_index)) != EOF) {
2519#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002520 while ((optchr =
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002521 getopt(argc, argv, "h?DFMRST:Vabcefgijklmo:pr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002522#endif
2523
2524 switch (optchr) {
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002525
Chris Allegretta7004c282001-09-22 00:42:10 +00002526#ifndef NANO_SMALL
2527 case 'D':
2528 SET(DOS_FILE);
2529 break;
2530#endif
Chris Allegretta355fbe52001-07-14 19:32:47 +00002531#ifdef ENABLE_MULTIBUFFER
Chris Allegretta307d4c82001-07-15 20:25:33 +00002532 case 'F':
Chris Allegretta355fbe52001-07-14 19:32:47 +00002533 SET(MULTIBUFFER);
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002534 break;
2535#endif
Chris Allegretta8fa1e282001-09-22 04:20:25 +00002536#ifndef NANO_SMALL
2537 case 'M':
2538 SET(MAC_FILE);
2539 break;
2540#endif
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002541 case 'T':
Chris Allegretta99bf73f2000-08-04 00:22:08 +00002542 tabsize = atoi(optarg);
2543 if (tabsize <= 0) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002544 usage(); /* To stop bogus data for tab width */
2545 finish(1);
2546 }
2547 break;
Chris Allegretta805c26d2000-09-06 13:39:17 +00002548#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +00002549 case 'R':
2550 SET(USE_REGEXP);
2551 break;
Chris Allegretta47805612000-07-07 02:35:34 +00002552#endif
Chris Allegretta3e3ae942001-09-22 19:02:04 +00002553#ifndef NANO_SMALL
2554 case 'S':
2555 SET(SMOOTHSCROLL);
2556 break;
2557#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002558 case 'V':
2559 version();
2560 exit(0);
Chris Allegrettae1f14522001-09-19 03:19:43 +00002561 case 'a':
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002562 case 'b':
2563 case 'e':
2564 case 'f':
Rocco Corsi12f294c2001-04-14 06:50:24 +00002565 case 'g':
2566 case 'j':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002567 /* Pico compatibility flags */
2568 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002569 case 'c':
2570 SET(CONSTUPDATE);
2571 break;
2572 case 'h':
2573 case '?':
2574 usage();
2575 exit(0);
Chris Allegrettaff989832001-09-17 13:48:00 +00002576#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002577 case 'i':
2578 SET(AUTOINDENT);
2579 break;
Chris Allegretta627de192000-07-12 02:09:17 +00002580 case 'k':
2581 SET(CUT_TO_END);
2582 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002583#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002584 case 'l':
2585 UNSET(FOLLOW_SYMLINKS);
2586 break;
2587 case 'm':
2588 SET(USE_MOUSE);
2589 break;
Chris Allegrettae1f14522001-09-19 03:19:43 +00002590#ifndef DISABLE_OPERATINGDIR
2591 case 'o':
2592 operating_dir = charalloc(strlen(optarg) + 1);
2593 strcpy(operating_dir, optarg);
2594
2595 /* make sure we're inside the operating directory */
2596 if (check_operating_dir(".", 0)) {
2597 if (chdir(operating_dir) == -1) {
2598 free(operating_dir);
2599 operating_dir = NULL;
2600 }
2601 }
2602 break;
2603#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002604 case 'p':
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002605 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002606 break;
2607 case 'r':
Chris Allegretta6fe61492001-05-21 12:56:25 +00002608#ifndef DISABLE_WRAPJUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002609 fill = atoi(optarg);
Chris Allegretta6fe61492001-05-21 12:56:25 +00002610 if (fill < 0)
2611 wrap_at = fill;
2612 else if (fill == 0) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002613 usage(); /* To stop bogus data (like a string) */
2614 finish(1);
2615 }
2616 break;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002617#else
2618 usage();
2619 exit(0);
2620
2621#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002622#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002623 case 's':
Chris Allegretta88b09152001-05-17 11:35:43 +00002624 alt_speller = charalloc(strlen(optarg) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002625 strcpy(alt_speller, optarg);
2626 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002627#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002628 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00002629 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002630 break;
2631 case 'v':
2632 SET(VIEW_MODE);
2633 break;
2634 case 'w':
Chris Allegrettacef7fbb2001-04-02 05:36:08 +00002635#ifdef DISABLE_WRAPPING
2636 usage();
2637 exit(0);
2638#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002639 SET(NO_WRAP);
2640 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002641#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002642 case 'x':
2643 SET(NO_HELP);
2644 break;
2645 case 'z':
2646 SET(SUSPEND);
2647 break;
2648 default:
2649 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002650 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002651 }
2652
2653 }
2654
2655 argv0 = strrchr(argv[0], '/');
2656 if ((argv0 && strstr(argv0, "pico"))
2657 || (!argv0 && strstr(argv[0], "pico")))
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002658 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002659
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002660 /* See if there's a non-option in argv (first non-option is the
2661 filename, if +LINE is not given) */
2662 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002663 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002664 else {
2665 /* Look for the +line flag... */
2666 if (argv[optind][0] == '+') {
2667 startline = atoi(&argv[optind][1]);
2668 optind++;
2669 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002670 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002671 else
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002672 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002673
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002674 } else
2675 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002676 }
2677
2678
2679 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002680 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002681
Chris Allegretta9239d742000-09-06 15:19:18 +00002682#ifdef _POSIX_VDISABLE
Chris Allegretta8f6c0692000-07-19 01:16:18 +00002683 term = oldterm;
2684 term.c_cc[VINTR] = _POSIX_VDISABLE;
2685 term.c_cc[VQUIT] = _POSIX_VDISABLE;
2686 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002687 tcsetattr(0, TCSANOW, &term);
Chris Allegretta9239d742000-09-06 15:19:18 +00002688#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002689
2690 /* now ncurses init stuff... */
2691 initscr();
2692 savetty();
2693 nonl();
2694 cbreak();
2695 noecho();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002696
2697 /* Set up some global variables */
Chris Allegretta56214c62001-09-27 02:46:53 +00002698 global_init(0);
Chris Allegretta07798352000-11-27 22:58:23 +00002699 shortcut_init(0);
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002700#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002701 init_help_msg();
2702 help_init();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002703#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002704 signal_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002705
2706#ifdef DEBUG
2707 fprintf(stderr, _("Main: set up windows\n"));
2708#endif
2709
Chris Allegretta8ce24132001-04-30 11:28:46 +00002710#ifdef ENABLE_COLOR
2711 do_colorinit();
2712#endif /* ENABLE_COLOR */
2713
Chris Allegretta2a42af12000-09-12 23:02:49 +00002714 window_init();
Chris Allegretta756f2202000-09-01 13:32:47 +00002715 mouse_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002716
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002717#ifdef DEBUG
2718 fprintf(stderr, _("Main: bottom win\n"));
2719#endif
Chris Allegretta88520c92001-05-05 17:45:54 +00002720 /* Set up bottom of window */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002721 display_main_list();
2722
2723#ifdef DEBUG
2724 fprintf(stderr, _("Main: open file\n"));
2725#endif
2726
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002727 titlebar(NULL);
Chris Allegretta31c76662000-11-21 06:20:20 +00002728
2729 /* Now we check to see if argv[optind] is non-null to determine if
2730 we're dealing with a new file or not, not argc == 1... */
2731 if (argv[optind] == NULL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002732 new_file();
2733 else
2734 open_file(filename, 0, 0);
2735
2736 if (startline > 0)
Chris Allegretta2d7893d2001-07-11 02:08:33 +00002737 do_gotoline(startline, 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002738 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00002739 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002740
Chris Allegretta08020882001-01-29 23:37:54 +00002741 /* return here after a sigwinch */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002742 sigsetjmp(jmpbuf, 1);
Chris Allegretta08020882001-01-29 23:37:54 +00002743
2744 /* Fix clobber-age */
2745 kbinput = 0;
2746 keyhandled = 0;
2747 modify_control_seq = 0;
2748
Robert Siemborski6967eec2000-07-08 14:23:32 +00002749 edit_refresh();
2750 reset_cursor();
2751
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002752 while (1) {
Chris Allegretta0357c4d2001-09-19 02:59:25 +00002753 oldcurrent = current;
2754 oldcurrent_x = current_x;
Chris Allegretta9239d742000-09-06 15:19:18 +00002755
Chris Allegretta6fe61492001-05-21 12:56:25 +00002756#ifndef DISABLE_MOUSE
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002757 currshortcut = main_list;
2758 currslen = MAIN_VISIBLE;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002759#endif
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002760
Chris Allegretta9239d742000-09-06 15:19:18 +00002761#ifndef _POSIX_VDISABLE
2762 /* We're going to have to do it the old way, i.e. on cygwin */
2763 raw();
2764#endif
2765
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002766 kbinput = wgetch(edit);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002767#ifdef DEBUG
2768 fprintf(stderr, "AHA! %c (%d)\n", kbinput, kbinput);
2769#endif
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002770
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002771 if (kbinput == 27) { /* Grab Alt-key stuff first */
2772 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002773 /* Alt-O, suddenly very important ;) */
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002774 case 'O':
Chris Allegretta16e41682000-09-11 22:33:54 +00002775 kbinput = wgetch(edit);
Chris Allegretta316e4d92001-04-28 16:31:19 +00002776 if ((kbinput <= 'D' && kbinput >= 'A') ||
2777 (kbinput <= 'd' && kbinput >= 'a'))
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002778 kbinput = ABCD(kbinput);
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002779 else if (kbinput <= 'z' && kbinput >= 'j')
2780 print_numlock_warning();
2781 else if (kbinput <= 'S' && kbinput >= 'P')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002782 kbinput = KEY_F(kbinput - 79);
Chris Allegretta16e41682000-09-11 22:33:54 +00002783#ifdef DEBUG
2784 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002785 fprintf(stderr, _("I got Alt-O-%c! (%d)\n"),
2786 kbinput, kbinput);
2787 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002788 }
2789#endif
2790 break;
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002791 case 27:
2792 /* If we get Alt-Alt, the next keystroke should be the same as a
2793 control sequence */
2794 modify_control_seq = 1;
2795 keyhandled = 1;
2796 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002797 case '[':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002798 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002799 case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */
Chris Allegretta16e41682000-09-11 22:33:54 +00002800 kbinput = wgetch(edit);
2801 if (kbinput >= '1' && kbinput <= '5') {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002802 kbinput = KEY_F(kbinput - 48);
2803 wgetch(edit);
2804 } else if (kbinput >= '7' && kbinput <= '9') {
2805 kbinput = KEY_F(kbinput - 49);
2806 wgetch(edit);
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002807 } else if (kbinput == '~')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002808 kbinput = KEY_HOME;
Chris Allegretta16e41682000-09-11 22:33:54 +00002809
2810#ifdef DEBUG
2811 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002812 fprintf(stderr, _("I got Alt-[-1-%c! (%d)\n"),
2813 kbinput, kbinput);
2814 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002815 }
2816#endif
2817
2818 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002819 case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */
Chris Allegretta16e41682000-09-11 22:33:54 +00002820 kbinput = wgetch(edit);
Chris Allegretta16e41682000-09-11 22:33:54 +00002821 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002822 case '0':
2823 kbinput = KEY_F(9);
2824 wgetch(edit);
2825 break;
2826 case '1':
2827 kbinput = KEY_F(10);
2828 wgetch(edit);
2829 break;
2830 case '3':
2831 kbinput = KEY_F(11);
2832 wgetch(edit);
2833 break;
2834 case '4':
2835 kbinput = KEY_F(12);
2836 wgetch(edit);
2837 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002838 case '~':
2839 goto do_insertkey;
Chris Allegretta16e41682000-09-11 22:33:54 +00002840#ifdef DEBUG
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002841 default:
2842 fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"),
2843 kbinput, kbinput);
2844 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002845#endif
2846
2847 }
2848 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002849 case '3': /* Alt-[-3 = Delete? */
Chris Allegretta16e41682000-09-11 22:33:54 +00002850 kbinput = NANO_DELETE_KEY;
2851 wgetch(edit);
2852 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002853 case '4': /* Alt-[-4 = End? */
Chris Allegretta16e41682000-09-11 22:33:54 +00002854 kbinput = NANO_END_KEY;
2855 wgetch(edit);
2856 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002857 case '5': /* Alt-[-5 = Page Up */
Chris Allegretta16e41682000-09-11 22:33:54 +00002858 kbinput = KEY_PPAGE;
2859 wgetch(edit);
2860 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002861 case '6': /* Alt-[-6 = Page Down */
Chris Allegretta16e41682000-09-11 22:33:54 +00002862 kbinput = KEY_NPAGE;
2863 wgetch(edit);
2864 break;
Chris Allegrettab26ecb52001-07-04 16:27:05 +00002865 case '7':
2866 kbinput = KEY_HOME;
2867 wgetch(edit);
2868 break;
2869 case '8':
2870 kbinput = KEY_END;
2871 wgetch(edit);
2872 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002873 case '[': /* Alt-[-[-[A-E], F1-F5 in linux console */
Chris Allegretta16e41682000-09-11 22:33:54 +00002874 kbinput = wgetch(edit);
Chris Allegrettab26ecb52001-07-04 16:27:05 +00002875 if (kbinput >= 'A' && kbinput <= 'E')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002876 kbinput = KEY_F(kbinput - 64);
Chris Allegretta16e41682000-09-11 22:33:54 +00002877 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002878 case 'A':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002879 case 'B':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002880 case 'C':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002881 case 'D':
Chris Allegretta316e4d92001-04-28 16:31:19 +00002882 case 'a':
2883 case 'b':
2884 case 'c':
2885 case 'd':
Chris Allegretta1748cd12001-01-13 17:22:54 +00002886 kbinput = ABCD(kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002887 break;
2888 case 'H':
2889 kbinput = KEY_HOME;
2890 break;
2891 case 'F':
2892 kbinput = KEY_END;
2893 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002894 default:
2895#ifdef DEBUG
2896 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
2897 kbinput, kbinput);
2898#endif
2899 break;
2900 }
2901 break;
Chris Allegretta355fbe52001-07-14 19:32:47 +00002902#ifdef ENABLE_MULTIBUFFER
Chris Allegretta819e3db2001-07-11 02:37:19 +00002903 case NANO_OPENPREV_KEY:
2904 open_prevfile(0);
2905 keyhandled = 1;
2906 break;
2907 case NANO_OPENNEXT_KEY:
2908 open_nextfile(0);
2909 keyhandled = 1;
2910 break;
Chris Allegretta9cf9e062001-07-11 12:06:13 +00002911#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002912 default:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002913 /* Check for the altkey defs.... */
2914 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
2915 if (kbinput == main_list[i].altval ||
2916 kbinput == main_list[i].altval - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002917 kbinput = main_list[i].val;
2918 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002919 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002920#ifndef NANO_SMALL
2921 /* And for toggle switches */
2922 for (i = 0; i <= TOGGLE_LEN - 1 && !keyhandled; i++)
2923 if (kbinput == toggles[i].val ||
2924 kbinput == toggles[i].val - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002925 do_toggle(i);
2926 keyhandled = 1;
2927 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002928 }
2929#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002930#ifdef DEBUG
2931 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
2932 kbinput);
2933#endif
2934 break;
2935 }
2936 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002937 /* If the modify_control_seq is set, we received an Alt-Alt
2938 sequence before this, so we make this key a control sequence
2939 by subtracting 64 or 96, depending on its value. */
2940 if (!keyhandled && modify_control_seq) {
2941 if (kbinput >= 'A' && kbinput < 'a')
2942 kbinput -= 64;
2943 else if (kbinput >= 'a' && kbinput <= 'z')
2944 kbinput -= 96;
2945
2946 modify_control_seq = 0;
2947 }
2948
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002949 /* Look through the main shortcut list to see if we've hit a
2950 shortcut key */
Chris Allegretta756f2202000-09-01 13:32:47 +00002951 for (i = 0; i < MAIN_LIST_LEN && !keyhandled; i++) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002952 if (kbinput == main_list[i].val ||
2953 (main_list[i].misc1 && kbinput == main_list[i].misc1) ||
2954 (main_list[i].misc2 && kbinput == main_list[i].misc2)) {
2955 if (ISSET(VIEW_MODE) && !main_list[i].viewok)
2956 print_view_warning();
2957 else
2958 main_list[i].func();
2959 keyhandled = 1;
2960 }
2961 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002962 /* If we're in raw mode or using Alt-Alt-x, we have to catch
2963 Control-S and Control-Q */
Chris Allegretta9239d742000-09-06 15:19:18 +00002964 if (kbinput == 17 || kbinput == 19)
2965 keyhandled = 1;
2966
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002967 /* Catch ^Z by hand when triggered also */
Chris Allegretta9239d742000-09-06 15:19:18 +00002968 if (kbinput == 26) {
2969 if (ISSET(SUSPEND))
2970 do_suspend(0);
2971 keyhandled = 1;
2972 }
Chris Allegretta9239d742000-09-06 15:19:18 +00002973
Chris Allegrettace78c1e2001-09-23 01:18:03 +00002974
2975 /* Hack, make insert key do something useful, like insert file */
2976 if (kbinput == KEY_IC) {
2977 do_insertkey:
2978
2979#ifdef ENABLE_MULTIBUFFER
2980 do_insertfile(ISSET(MULTIBUFFER));
2981#else
2982 do_insertfile(0);
2983#endif
2984
2985 keyhandled = 1;
2986 }
2987
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002988 /* Last gasp, stuff that's not in the main lists */
2989 if (!keyhandled)
2990 switch (kbinput) {
Chris Allegretta84de5522001-04-12 14:51:48 +00002991#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002992#ifdef NCURSES_MOUSE_VERSION
2993 case KEY_MOUSE:
2994 do_mouse();
2995 break;
2996#endif
2997#endif
2998 case 0: /* Erg */
2999 do_next_word();
3000 break;
Chris Allegrettaf4f7e042001-01-04 16:56:15 +00003001
Chris Allegrettace78c1e2001-09-23 01:18:03 +00003002 case -1: /* Stuff that we don't want to do squat */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003003 case 410: /* Must ignore this, it gets sent when we resize */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003004#ifdef PDCURSES
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003005 case 541: /* ???? */
3006 case 542: /* Control and alt in Windows *shrug* */
Chris Allegretta72623582000-11-29 23:43:28 +00003007 case 543: /* Right ctrl key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003008 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +00003009 case 545: /* Right alt key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00003010#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003011
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003012 break;
3013 default:
3014#ifdef DEBUG
3015 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
3016#endif
3017 /* We no longer stop unhandled sequences so that people with
3018 odd character sets can type... */
3019
3020 if (ISSET(VIEW_MODE)) {
3021 print_view_warning();
3022 break;
3023 }
3024 do_char(kbinput);
3025 }
Chris Allegretta7fdbd052001-10-02 00:55:38 +00003026 if (ISSET(DISABLE_CURPOS))
3027 UNSET(DISABLE_CURPOS);
3028 else if (ISSET(CONSTUPDATE))
Chris Allegretta0357c4d2001-09-19 02:59:25 +00003029 if (current != oldcurrent || current_x != oldcurrent_x)
Chris Allegretta756f2202000-09-01 13:32:47 +00003030 do_cursorpos();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003031
3032 reset_cursor();
3033 wrefresh(edit);
3034 keyhandled = 0;
3035 }
3036
3037 getchar();
3038 finish(0);
3039
3040}