2000-08-07 01:13:45 +04:00
|
|
|
|
/* $Id$ */
|
2000-06-06 09:53:49 +04:00
|
|
|
|
/**************************************************************************
|
|
|
|
|
* nano.c *
|
|
|
|
|
* *
|
2005-01-01 10:28:15 +03:00
|
|
|
|
* Copyright (C) 1999-2005 Chris Allegretta *
|
2000-06-06 09:53:49 +04:00
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
2001-10-24 15:33:54 +04:00
|
|
|
|
* the Free Software Foundation; either version 2, or (at your option) *
|
2000-06-06 09:53:49 +04:00
|
|
|
|
* any later version. *
|
|
|
|
|
* *
|
2005-05-15 23:57:17 +04:00
|
|
|
|
* This program is distributed in the hope that it will be useful, but *
|
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
|
|
|
|
* General Public License for more details. *
|
2000-06-06 09:53:49 +04:00
|
|
|
|
* *
|
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
|
|
|
|
* along with this program; if not, write to the Free Software *
|
2005-05-15 23:57:17 +04:00
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
|
|
|
|
* 02110-1301, USA. *
|
2000-06-06 09:53:49 +04:00
|
|
|
|
* *
|
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
2004-11-18 02:17:05 +03:00
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
#include <config.h>
|
|
|
|
|
#endif
|
2001-04-28 22:03:52 +04:00
|
|
|
|
|
2000-06-06 09:53:49 +04:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
|
#include <sys/param.h>
|
2000-11-05 19:52:21 +03:00
|
|
|
|
#include <sys/wait.h>
|
2000-06-06 09:53:49 +04:00
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <locale.h>
|
2000-06-07 07:56:54 +04:00
|
|
|
|
#include <assert.h>
|
2000-06-06 09:53:49 +04:00
|
|
|
|
#include "proto.h"
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_TERMIOS_H
|
|
|
|
|
#include <termios.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_GETOPT_H
|
|
|
|
|
#include <getopt.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-05-18 05:20:36 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
#include <setjmp.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-05-21 16:56:25 +04:00
|
|
|
|
#ifndef DISABLE_WRAPJUSTIFY
|
2005-06-15 03:38:41 +04:00
|
|
|
|
static ssize_t fill = 0; /* Fill - where to wrap lines */
|
2001-05-21 16:56:25 +04:00
|
|
|
|
#endif
|
2003-09-11 00:08:00 +04:00
|
|
|
|
#ifndef DISABLE_WRAPPING
|
2004-08-06 02:10:22 +04:00
|
|
|
|
static bool same_line_wrap = FALSE; /* Whether wrapped text should
|
2004-06-22 19:38:47 +04:00
|
|
|
|
be prepended to the next
|
|
|
|
|
line */
|
2003-09-11 00:08:00 +04:00
|
|
|
|
#endif
|
2001-01-12 10:51:05 +03:00
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
static struct termios oldterm; /* The user's original term settings */
|
2001-05-05 21:45:54 +04:00
|
|
|
|
static struct sigaction act; /* For all our fun signal handlers */
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2004-05-18 05:20:36 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2005-06-16 03:35:53 +04:00
|
|
|
|
static sigjmp_buf jmpbuf; /* Used to return to main() after a
|
|
|
|
|
SIGWINCH. */
|
2004-08-05 19:16:19 +04:00
|
|
|
|
static int pid; /* The PID of the newly forked process
|
|
|
|
|
* in open_pipe(). It must be global
|
|
|
|
|
* because the signal handler needs
|
|
|
|
|
* it. */
|
2004-05-18 05:20:36 +04:00
|
|
|
|
#endif
|
2001-01-30 02:37:54 +03:00
|
|
|
|
|
2004-11-23 07:08:28 +03:00
|
|
|
|
#ifndef DISABLE_JUSTIFY
|
|
|
|
|
static filestruct *jusbottom = NULL;
|
|
|
|
|
/* Pointer to end of justify buffer. */
|
|
|
|
|
#endif
|
|
|
|
|
|
2005-01-19 22:52:42 +03:00
|
|
|
|
void print_view_warning(void)
|
|
|
|
|
{
|
|
|
|
|
statusbar(_("Key illegal in VIEW mode"));
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-25 23:41:11 +04:00
|
|
|
|
/* What we do when we're all set to exit. */
|
|
|
|
|
void finish(void)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
2004-05-18 05:20:36 +04:00
|
|
|
|
if (!ISSET(NO_HELP))
|
|
|
|
|
blank_bottombars();
|
|
|
|
|
else
|
|
|
|
|
blank_statusbar();
|
2001-04-12 07:01:53 +04:00
|
|
|
|
|
2000-06-06 09:53:49 +04:00
|
|
|
|
wrefresh(bottomwin);
|
|
|
|
|
endwin();
|
|
|
|
|
|
2004-05-18 05:20:36 +04:00
|
|
|
|
/* Restore the old terminal settings. */
|
2000-06-21 07:00:43 +04:00
|
|
|
|
tcsetattr(0, TCSANOW, &oldterm);
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2003-03-11 06:50:40 +03:00
|
|
|
|
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
|
|
|
|
|
if (!ISSET(NO_RCFILE) && ISSET(HISTORYLOG))
|
|
|
|
|
save_history();
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-05-12 23:52:15 +04:00
|
|
|
|
#ifdef DEBUG
|
2002-02-27 07:14:16 +03:00
|
|
|
|
thanks_for_all_the_fish();
|
2002-05-12 23:52:15 +04:00
|
|
|
|
#endif
|
2002-02-27 07:14:16 +03:00
|
|
|
|
|
2004-05-25 23:41:11 +04:00
|
|
|
|
exit(0);
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-08-11 03:05:59 +04:00
|
|
|
|
/* Die (gracefully?). */
|
2002-07-19 05:08:59 +04:00
|
|
|
|
void die(const char *msg, ...)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
|
|
|
|
va_list ap;
|
|
|
|
|
|
2003-02-03 06:32:08 +03:00
|
|
|
|
endwin();
|
|
|
|
|
curses_ended = TRUE;
|
|
|
|
|
|
2004-05-18 05:20:36 +04:00
|
|
|
|
/* Restore the old terminal settings. */
|
2001-07-11 06:08:33 +04:00
|
|
|
|
tcsetattr(0, TCSANOW, &oldterm);
|
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
va_start(ap, msg);
|
|
|
|
|
vfprintf(stderr, msg, ap);
|
|
|
|
|
va_end(ap);
|
2001-07-11 06:08:33 +04:00
|
|
|
|
|
2004-12-01 18:11:27 +03:00
|
|
|
|
/* Save the current file buffer if it's been modified. */
|
2005-06-06 20:27:18 +04:00
|
|
|
|
if (ISSET(MODIFIED)) {
|
|
|
|
|
/* If we've partitioned the filestruct, unpartition it now. */
|
|
|
|
|
if (filepart != NULL)
|
|
|
|
|
unpartition_filestruct(&filepart);
|
|
|
|
|
|
2002-01-02 18:12:21 +03:00
|
|
|
|
die_save_file(filename);
|
2005-06-06 20:27:18 +04:00
|
|
|
|
}
|
2001-07-11 06:08:33 +04:00
|
|
|
|
|
2001-07-14 23:32:47 +04:00
|
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
2004-12-01 18:11:27 +03:00
|
|
|
|
/* Save all of the other modified file buffers, if any. */
|
2002-12-22 19:30:00 +03:00
|
|
|
|
if (open_files != NULL) {
|
2004-12-01 18:11:27 +03:00
|
|
|
|
openfilestruct *tmp = open_files;
|
2001-07-11 06:08:33 +04:00
|
|
|
|
|
2004-12-01 18:11:27 +03:00
|
|
|
|
while (tmp != open_files->next) {
|
|
|
|
|
open_files = open_files->next;
|
2001-07-11 06:08:33 +04:00
|
|
|
|
|
2004-12-01 18:11:27 +03:00
|
|
|
|
/* Save the current file buffer if it's been modified. */
|
|
|
|
|
if (open_files->flags & MODIFIED) {
|
|
|
|
|
/* Set fileage and filebot to match the current file
|
|
|
|
|
* buffer, and then write it to disk. */
|
2002-04-10 06:31:20 +04:00
|
|
|
|
fileage = open_files->fileage;
|
2002-05-11 07:04:44 +04:00
|
|
|
|
filebot = open_files->filebot;
|
2004-12-01 18:11:27 +03:00
|
|
|
|
die_save_file(open_files->filename);
|
2001-07-11 06:08:33 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-12-01 18:11:27 +03:00
|
|
|
|
/* Get out. */
|
|
|
|
|
exit(1);
|
2001-07-11 06:08:33 +04:00
|
|
|
|
}
|
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
void die_save_file(const char *die_filename)
|
2001-07-11 06:08:33 +04:00
|
|
|
|
{
|
2005-05-29 03:21:30 +04:00
|
|
|
|
char *retval;
|
2004-08-06 02:10:22 +04:00
|
|
|
|
bool failed = TRUE;
|
2001-07-11 06:08:33 +04:00
|
|
|
|
|
2004-05-29 05:20:17 +04:00
|
|
|
|
/* If we're using restricted mode, don't write any emergency backup
|
|
|
|
|
* files, since that would allow reading from or writing to files
|
|
|
|
|
* not specified on the command line. */
|
2004-04-30 08:49:02 +04:00
|
|
|
|
if (ISSET(RESTRICTED))
|
|
|
|
|
return;
|
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
/* If we can't save, we have REAL bad problems, but we might as well
|
2005-04-14 07:52:28 +04:00
|
|
|
|
* TRY. */
|
2002-07-19 05:08:59 +04:00
|
|
|
|
if (die_filename[0] == '\0')
|
2004-08-11 03:05:59 +04:00
|
|
|
|
die_filename = "nano";
|
|
|
|
|
|
2005-05-29 06:22:55 +04:00
|
|
|
|
retval = get_next_filename(die_filename, ".save");
|
2005-05-29 03:21:30 +04:00
|
|
|
|
if (retval[0] != '\0')
|
2005-05-31 08:28:15 +04:00
|
|
|
|
failed = (write_file(retval, NULL, TRUE, FALSE, TRUE) == -1);
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2004-08-06 02:10:22 +04:00
|
|
|
|
if (!failed)
|
2005-05-29 03:21:30 +04:00
|
|
|
|
fprintf(stderr, _("\nBuffer written to %s\n"), retval);
|
2005-06-01 08:23:52 +04:00
|
|
|
|
else if (retval[0] != '\0')
|
2005-05-30 03:03:28 +04:00
|
|
|
|
fprintf(stderr, _("\nBuffer not written to %s: %s\n"), retval,
|
2005-06-01 08:23:52 +04:00
|
|
|
|
strerror(errno));
|
|
|
|
|
else
|
|
|
|
|
fprintf(stderr, _("\nBuffer not written: %s\n"),
|
2005-05-30 03:03:28 +04:00
|
|
|
|
_("Too many backup files?"));
|
2002-02-22 07:30:50 +03:00
|
|
|
|
|
2005-05-29 03:21:30 +04:00
|
|
|
|
free(retval);
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
|
|
|
|
|
2001-01-14 08:18:27 +03:00
|
|
|
|
/* Die with an error message that the screen was too small if, well, the
|
2002-07-19 05:08:59 +04:00
|
|
|
|
* screen is too small. */
|
2005-01-19 22:52:42 +03:00
|
|
|
|
void check_die_too_small(void)
|
2001-01-14 08:18:27 +03:00
|
|
|
|
{
|
2005-01-19 22:52:42 +03:00
|
|
|
|
editwinrows = LINES - 5 + no_more_space() + no_help();
|
|
|
|
|
if (editwinrows < MIN_EDITOR_ROWS)
|
|
|
|
|
die(_("Window size is too small for nano...\n"));
|
2001-01-14 08:18:27 +03:00
|
|
|
|
}
|
|
|
|
|
|
2005-06-16 05:37:13 +04:00
|
|
|
|
/* Reinitialize the variables that depend on the window size. That is,
|
|
|
|
|
* fill and hblank. */
|
2005-01-19 22:52:42 +03:00
|
|
|
|
void resize_variables(void)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
2005-01-19 22:52:42 +03:00
|
|
|
|
#ifndef DISABLE_WRAPJUSTIFY
|
|
|
|
|
fill = wrap_at;
|
|
|
|
|
if (fill <= 0)
|
|
|
|
|
fill += COLS;
|
|
|
|
|
if (fill < 0)
|
|
|
|
|
fill = 0;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
hblank = charealloc(hblank, COLS + 1);
|
2005-06-12 19:24:36 +04:00
|
|
|
|
charset(hblank, ' ', COLS);
|
2005-01-19 22:52:42 +03:00
|
|
|
|
hblank[COLS] = '\0';
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-01-10 02:04:55 +03:00
|
|
|
|
/* Initialize global variables -- no better way for now. If
|
2004-08-06 02:10:22 +04:00
|
|
|
|
* save_cutbuffer is TRUE, don't set cutbuffer to NULL. */
|
|
|
|
|
void global_init(bool save_cutbuffer)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
2005-01-19 22:52:42 +03:00
|
|
|
|
check_die_too_small();
|
|
|
|
|
resize_variables();
|
2001-01-14 08:18:27 +03:00
|
|
|
|
|
2000-06-06 09:53:49 +04:00
|
|
|
|
fileage = NULL;
|
2005-01-19 22:52:42 +03:00
|
|
|
|
edittop = NULL;
|
|
|
|
|
current = NULL;
|
2001-09-27 06:46:53 +04:00
|
|
|
|
if (!save_cutbuffer)
|
|
|
|
|
cutbuffer = NULL;
|
2005-01-19 22:52:42 +03:00
|
|
|
|
current_x = 0;
|
|
|
|
|
placewewant = 0;
|
|
|
|
|
current_y = 0;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
totlines = 0;
|
2001-09-27 06:46:53 +04:00
|
|
|
|
totsize = 0;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
void window_init(void)
|
|
|
|
|
{
|
2005-01-19 22:52:42 +03:00
|
|
|
|
check_die_too_small();
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
2003-01-26 07:15:56 +03:00
|
|
|
|
if (topwin != NULL)
|
|
|
|
|
delwin(topwin);
|
2004-03-29 22:36:39 +04:00
|
|
|
|
if (edit != NULL)
|
|
|
|
|
delwin(edit);
|
2003-01-26 07:15:56 +03:00
|
|
|
|
if (bottomwin != NULL)
|
|
|
|
|
delwin(bottomwin);
|
|
|
|
|
|
2004-03-29 22:36:39 +04:00
|
|
|
|
/* Set up the windows. */
|
2005-01-17 08:06:55 +03:00
|
|
|
|
topwin = newwin(2 - no_more_space(), COLS, 0, 0);
|
|
|
|
|
edit = newwin(editwinrows, COLS, 2 - no_more_space(), 0);
|
2005-01-19 23:55:42 +03:00
|
|
|
|
bottomwin = newwin(3 - no_help(), COLS, editwinrows +
|
|
|
|
|
(2 - no_more_space()), 0);
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
2004-05-18 05:20:36 +04:00
|
|
|
|
/* Turn the keypad back on. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
keypad(edit, TRUE);
|
|
|
|
|
keypad(bottomwin, TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
2003-10-04 00:26:25 +04:00
|
|
|
|
#ifndef DISABLE_MOUSE
|
2002-09-07 00:35:28 +04:00
|
|
|
|
void mouse_init(void)
|
|
|
|
|
{
|
|
|
|
|
if (ISSET(USE_MOUSE)) {
|
|
|
|
|
mousemask(BUTTON1_RELEASED, NULL);
|
|
|
|
|
mouseinterval(50);
|
|
|
|
|
} else
|
|
|
|
|
mousemask(0, NULL);
|
|
|
|
|
}
|
2002-12-22 19:30:00 +03:00
|
|
|
|
#endif
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
|
|
|
|
#ifndef DISABLE_HELP
|
|
|
|
|
/* This function allocates help_text, and stores the help string in it.
|
|
|
|
|
* help_text should be NULL initially. */
|
|
|
|
|
void help_init(void)
|
|
|
|
|
{
|
2005-03-22 05:51:01 +03:00
|
|
|
|
size_t allocsize = 0; /* Space needed for help_text. */
|
2005-03-30 22:11:59 +04:00
|
|
|
|
const char *htx[3]; /* Untranslated help message. We break
|
|
|
|
|
* it up into three chunks in case the
|
|
|
|
|
* full string is too long for the
|
|
|
|
|
* compiler to handle. */
|
2004-08-05 19:45:09 +04:00
|
|
|
|
char *ptr;
|
2004-03-20 00:46:34 +03:00
|
|
|
|
const shortcut *s;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
const toggle *t;
|
2005-02-25 22:17:57 +03:00
|
|
|
|
#ifdef ENABLE_NANORC
|
|
|
|
|
bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
|
|
|
|
|
|
|
|
|
|
UNSET(WHITESPACE_DISPLAY);
|
|
|
|
|
#endif
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#endif
|
|
|
|
|
|
2004-08-05 19:45:09 +04:00
|
|
|
|
/* First, set up the initial help text for the current function. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
if (currshortcut == whereis_list || currshortcut == replace_list
|
2005-03-30 22:11:59 +04:00
|
|
|
|
|| currshortcut == replace_list_2) {
|
|
|
|
|
htx[0] = N_("Search Command Help Text\n\n "
|
|
|
|
|
"Enter the words or characters you would like to "
|
|
|
|
|
"search for, and then press Enter. If there is a "
|
|
|
|
|
"match for the text you entered, the screen will be "
|
|
|
|
|
"updated to the location of the nearest match for the "
|
|
|
|
|
"search string.\n\n The previous search string will be "
|
|
|
|
|
"shown in brackets after the search prompt. Hitting "
|
|
|
|
|
"Enter without entering any text will perform the "
|
|
|
|
|
"previous search. ");
|
|
|
|
|
htx[1] = N_("If you have selected text with the mark and then "
|
|
|
|
|
"search to replace, only matches in the selected text "
|
|
|
|
|
"will be replaced.\n\n The following function keys are "
|
|
|
|
|
"available in Search mode:\n\n");
|
|
|
|
|
htx[2] = NULL;
|
|
|
|
|
} else if (currshortcut == gotoline_list) {
|
|
|
|
|
htx[0] = N_("Go To Line Help Text\n\n "
|
2002-09-07 00:35:28 +04:00
|
|
|
|
"Enter the line number that you wish to go to and hit "
|
|
|
|
|
"Enter. If there are fewer lines of text than the "
|
2005-03-30 22:11:59 +04:00
|
|
|
|
"number you entered, you will be brought to the last "
|
|
|
|
|
"line of the file.\n\n The following function keys are "
|
2002-09-07 00:35:28 +04:00
|
|
|
|
"available in Go To Line mode:\n\n");
|
2005-03-30 22:11:59 +04:00
|
|
|
|
htx[1] = NULL;
|
|
|
|
|
htx[2] = NULL;
|
|
|
|
|
} else if (currshortcut == insertfile_list) {
|
|
|
|
|
htx[0] = N_("Insert File Help Text\n\n "
|
|
|
|
|
"Type in the name of a file to be inserted into the "
|
|
|
|
|
"current file buffer at the current cursor "
|
|
|
|
|
"location.\n\n If you have compiled nano with multiple "
|
|
|
|
|
"file buffer support, and enable multiple file buffers "
|
|
|
|
|
"with the -F or --multibuffer command line flags, the "
|
|
|
|
|
"Meta-F toggle, or a nanorc file, inserting a file "
|
|
|
|
|
"will cause it to be loaded into a separate buffer "
|
|
|
|
|
"(use Meta-< and > to switch between file buffers). ");
|
|
|
|
|
htx[1] = N_("If you need another blank buffer, do not enter "
|
|
|
|
|
"any filename, or type in a nonexistent filename at "
|
|
|
|
|
"the prompt and press Enter.\n\n The following "
|
2004-11-08 00:30:55 +03:00
|
|
|
|
"function keys are available in Insert File mode:\n\n");
|
2005-03-30 22:11:59 +04:00
|
|
|
|
htx[2] = NULL;
|
|
|
|
|
} else if (currshortcut == writefile_list) {
|
|
|
|
|
htx[0] = N_("Write File Help Text\n\n "
|
2002-09-07 00:35:28 +04:00
|
|
|
|
"Type the name that you wish to save the current file "
|
2005-03-30 22:11:59 +04:00
|
|
|
|
"as and press Enter to save the file.\n\n If you have "
|
2004-10-18 05:51:43 +04:00
|
|
|
|
"selected text with the mark, you will be prompted to "
|
2002-09-07 00:35:28 +04:00
|
|
|
|
"save only the selected portion to a separate file. To "
|
|
|
|
|
"reduce the chance of overwriting the current file with "
|
|
|
|
|
"just a portion of it, the current filename is not the "
|
|
|
|
|
"default in this mode.\n\n The following function keys "
|
|
|
|
|
"are available in Write File mode:\n\n");
|
2005-03-30 22:11:59 +04:00
|
|
|
|
htx[1] = NULL;
|
|
|
|
|
htx[2] = NULL;
|
|
|
|
|
}
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#ifndef DISABLE_BROWSER
|
2005-03-30 22:11:59 +04:00
|
|
|
|
else if (currshortcut == browser_list) {
|
|
|
|
|
htx[0] = N_("File Browser Help Text\n\n "
|
2002-09-07 00:35:28 +04:00
|
|
|
|
"The file browser is used to visually browse the "
|
|
|
|
|
"directory structure to select a file for reading "
|
|
|
|
|
"or writing. You may use the arrow keys or Page Up/"
|
|
|
|
|
"Down to browse through the files, and S or Enter to "
|
|
|
|
|
"choose the selected file or enter the selected "
|
2005-03-30 22:11:59 +04:00
|
|
|
|
"directory. To move up one level, select the "
|
|
|
|
|
"directory called \"..\" at the top of the file "
|
|
|
|
|
"list.\n\n The following function keys are available "
|
|
|
|
|
"in the file browser:\n\n");
|
|
|
|
|
htx[1] = NULL;
|
|
|
|
|
htx[2] = NULL;
|
|
|
|
|
} else if (currshortcut == gotodir_list) {
|
|
|
|
|
htx[0] = N_("Browser Go To Directory Help Text\n\n "
|
2002-09-07 00:35:28 +04:00
|
|
|
|
"Enter the name of the directory you would like to "
|
2005-03-30 22:11:59 +04:00
|
|
|
|
"browse to.\n\n If tab completion has not been "
|
|
|
|
|
"disabled, you can use the Tab key to (attempt to) "
|
|
|
|
|
"automatically complete the directory name.\n\n The "
|
|
|
|
|
"following function keys are available in Browser Go "
|
|
|
|
|
"To Directory mode:\n\n");
|
|
|
|
|
htx[1] = NULL;
|
|
|
|
|
htx[2] = NULL;
|
|
|
|
|
}
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#endif
|
2003-02-05 05:51:19 +03:00
|
|
|
|
#ifndef DISABLE_SPELLER
|
2005-03-30 22:11:59 +04:00
|
|
|
|
else if (currshortcut == spell_list) {
|
|
|
|
|
htx[0] = N_("Spell Check Help Text\n\n "
|
|
|
|
|
"The spell checker checks the spelling of all text in "
|
|
|
|
|
"the current file. When an unknown word is "
|
2002-09-07 00:35:28 +04:00
|
|
|
|
"encountered, it is highlighted and a replacement can "
|
|
|
|
|
"be edited. It will then prompt to replace every "
|
2005-03-30 22:11:59 +04:00
|
|
|
|
"instance of the given misspelled word in the current "
|
|
|
|
|
"file, or, if you have selected text with the mark, in "
|
|
|
|
|
"the selected text.\n\n The following other functions "
|
|
|
|
|
"are available in Spell Check mode:\n\n");
|
|
|
|
|
htx[1] = NULL;
|
|
|
|
|
htx[2] = NULL;
|
|
|
|
|
}
|
2003-02-05 05:51:19 +03:00
|
|
|
|
#endif
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2005-03-30 22:11:59 +04:00
|
|
|
|
else if (currshortcut == extcmd_list) {
|
|
|
|
|
htx[0] = N_("Execute Command Help Text\n\n "
|
|
|
|
|
"This menu allows you to insert the output of a "
|
|
|
|
|
"command run by the shell into the current buffer (or "
|
|
|
|
|
"a new buffer in multiple file buffer mode). If you "
|
|
|
|
|
"need another blank buffer, do not enter any "
|
|
|
|
|
"command.\n\n The following keys are available in "
|
|
|
|
|
"Execute Command mode:\n\n");
|
|
|
|
|
htx[1] = NULL;
|
|
|
|
|
htx[2] = NULL;
|
|
|
|
|
}
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#endif
|
2005-03-30 22:11:59 +04:00
|
|
|
|
else {
|
2004-08-05 19:45:09 +04:00
|
|
|
|
/* Default to the main help list. */
|
2005-03-30 22:11:59 +04:00
|
|
|
|
htx[0] = N_(" nano help text\n\n "
|
|
|
|
|
"The nano editor is designed to emulate the "
|
|
|
|
|
"functionality and ease-of-use of the UW Pico text "
|
|
|
|
|
"editor. There are four main sections of the editor. "
|
|
|
|
|
"The top line shows the program version, the current "
|
|
|
|
|
"filename being edited, and whether or not the file "
|
|
|
|
|
"has been modified. Next is the main editor window "
|
|
|
|
|
"showing the file being edited. The status line is "
|
|
|
|
|
"the third line from the bottom and shows important "
|
|
|
|
|
"messages. The bottom two lines show the most "
|
2005-04-26 00:08:29 +04:00
|
|
|
|
"commonly used shortcuts in the editor.\n\n ");
|
2005-03-30 22:11:59 +04:00
|
|
|
|
htx[1] = N_("The notation for shortcuts is as follows: "
|
|
|
|
|
"Control-key sequences are notated with a caret (^) "
|
|
|
|
|
"symbol and can be entered either by using the Control "
|
|
|
|
|
"(Ctrl) key or pressing the Escape (Esc) key twice. "
|
|
|
|
|
"Escape-key sequences are notated with the Meta (M) "
|
|
|
|
|
"symbol and can be entered using either the Esc, Alt, "
|
|
|
|
|
"or Meta key depending on your keyboard setup. ");
|
|
|
|
|
htx[2] = N_("Also, pressing Esc twice and then typing a "
|
|
|
|
|
"three-digit decimal number from 000 to 255 will enter "
|
2005-06-15 03:38:08 +04:00
|
|
|
|
"the character with the corresponding value. The "
|
|
|
|
|
"following keystrokes are available in the main editor "
|
|
|
|
|
"window. Alternative keys are shown in "
|
|
|
|
|
"parentheses:\n\n");
|
2005-03-30 22:11:59 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
htx[0] = _(htx[0]);
|
|
|
|
|
if (htx[1] != NULL)
|
|
|
|
|
htx[1] = _(htx[1]);
|
|
|
|
|
if (htx[2] != NULL)
|
|
|
|
|
htx[2] = _(htx[2]);
|
|
|
|
|
|
|
|
|
|
allocsize += strlen(htx[0]);
|
|
|
|
|
if (htx[1] != NULL)
|
|
|
|
|
allocsize += strlen(htx[1]);
|
|
|
|
|
if (htx[2] != NULL)
|
|
|
|
|
allocsize += strlen(htx[2]);
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
|
|
|
|
/* The space needed for the shortcut lists, at most COLS characters,
|
|
|
|
|
* plus '\n'. */
|
2005-03-22 05:51:01 +03:00
|
|
|
|
allocsize += (COLS < 24 ? (24 * mb_cur_max()) :
|
|
|
|
|
((COLS + 1) * mb_cur_max())) * length_of_list(currshortcut);
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
|
|
|
|
#ifndef NANO_SMALL
|
2004-08-05 19:45:09 +04:00
|
|
|
|
/* If we're on the main list, we also count the toggle help text.
|
2004-08-06 02:10:22 +04:00
|
|
|
|
* Each line has "M-%c\t\t\t", which fills 24 columns, plus a space,
|
|
|
|
|
* plus translated text, plus '\n'. */
|
2003-02-10 05:32:58 +03:00
|
|
|
|
if (currshortcut == main_list) {
|
2005-02-25 22:17:57 +03:00
|
|
|
|
size_t endis_len = strlen(_("enable/disable"));
|
2003-02-10 05:32:58 +03:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
for (t = toggles; t != NULL; t = t->next)
|
2005-02-25 22:17:57 +03:00
|
|
|
|
allocsize += 8 + strlen(t->desc) + endis_len;
|
2003-02-10 05:32:58 +03:00
|
|
|
|
}
|
2004-11-12 00:50:01 +03:00
|
|
|
|
#endif
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
|
|
|
|
/* help_text has been freed and set to NULL unless the user resized
|
|
|
|
|
* while in the help screen. */
|
|
|
|
|
free(help_text);
|
|
|
|
|
|
2004-08-05 19:45:09 +04:00
|
|
|
|
/* Allocate space for the help text. */
|
2005-03-22 05:51:01 +03:00
|
|
|
|
help_text = charalloc(allocsize + 1);
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
2004-08-05 19:45:09 +04:00
|
|
|
|
/* Now add the text we want. */
|
2005-03-30 22:11:59 +04:00
|
|
|
|
strcpy(help_text, htx[0]);
|
|
|
|
|
if (htx[1] != NULL)
|
|
|
|
|
strcat(help_text, htx[1]);
|
|
|
|
|
if (htx[2] != NULL)
|
|
|
|
|
strcat(help_text, htx[2]);
|
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
ptr = help_text + strlen(help_text);
|
|
|
|
|
|
2004-09-12 01:41:13 +04:00
|
|
|
|
/* Now add our shortcut info. Assume that each shortcut has, at the
|
|
|
|
|
* very least, an equivalent control key, an equivalent primary meta
|
|
|
|
|
* key sequence, or both. Also assume that the meta key values are
|
|
|
|
|
* not control characters. We can display a maximum of 3 shortcut
|
|
|
|
|
* entries. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
for (s = currshortcut; s != NULL; s = s->next) {
|
2004-09-12 01:41:13 +04:00
|
|
|
|
int entries = 0;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
2004-09-12 01:41:13 +04:00
|
|
|
|
/* Control key. */
|
2004-03-20 00:46:34 +03:00
|
|
|
|
if (s->ctrlval != NANO_NO_KEY) {
|
2004-09-12 01:41:13 +04:00
|
|
|
|
entries++;
|
2005-05-03 01:48:34 +04:00
|
|
|
|
/* Yucky sentinel values that we can't handle a better
|
|
|
|
|
* way. */
|
2005-02-25 22:17:57 +03:00
|
|
|
|
if (s->ctrlval == NANO_CONTROL_SPACE) {
|
|
|
|
|
char *space_ptr = display_string(_("Space"), 0, 6,
|
|
|
|
|
FALSE);
|
|
|
|
|
|
|
|
|
|
ptr += sprintf(ptr, "^%s", space_ptr);
|
|
|
|
|
|
|
|
|
|
free(space_ptr);
|
|
|
|
|
} else if (s->ctrlval == NANO_CONTROL_8)
|
2003-11-28 22:47:42 +03:00
|
|
|
|
ptr += sprintf(ptr, "^?");
|
2005-05-03 01:48:34 +04:00
|
|
|
|
/* Normal values. */
|
2003-11-28 22:47:42 +03:00
|
|
|
|
else
|
2004-03-20 00:46:34 +03:00
|
|
|
|
ptr += sprintf(ptr, "^%c", s->ctrlval + 64);
|
2004-09-12 01:41:13 +04:00
|
|
|
|
*(ptr++) = '\t';
|
2003-11-28 22:47:42 +03:00
|
|
|
|
}
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
2004-09-12 01:41:13 +04:00
|
|
|
|
/* Function key. */
|
|
|
|
|
if (s->funcval != NANO_NO_KEY) {
|
|
|
|
|
entries++;
|
2004-11-02 01:35:26 +03:00
|
|
|
|
/* If this is the first entry, put it in the middle. */
|
|
|
|
|
if (entries == 1) {
|
|
|
|
|
entries++;
|
|
|
|
|
*(ptr++) = '\t';
|
|
|
|
|
}
|
2004-03-20 00:46:34 +03:00
|
|
|
|
ptr += sprintf(ptr, "(F%d)", s->funcval - KEY_F0);
|
2004-09-12 01:41:13 +04:00
|
|
|
|
*(ptr++) = '\t';
|
|
|
|
|
}
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
2005-06-16 03:33:54 +04:00
|
|
|
|
/* Primary meta key sequence. If it's the first entry, don't
|
|
|
|
|
* put parentheses around it. */
|
2004-09-12 01:41:13 +04:00
|
|
|
|
if (s->metaval != NANO_NO_KEY) {
|
|
|
|
|
entries++;
|
|
|
|
|
/* If this is the last entry, put it at the end. */
|
|
|
|
|
if (entries == 2 && s->miscval == NANO_NO_KEY) {
|
|
|
|
|
entries++;
|
|
|
|
|
*(ptr++) = '\t';
|
|
|
|
|
}
|
2005-06-16 03:33:54 +04:00
|
|
|
|
/* Yucky sentinel values that we can't handle a better
|
|
|
|
|
* way. */
|
|
|
|
|
if (s->metaval == NANO_ALT_SPACE && entries == 1) {
|
|
|
|
|
char *space_ptr = display_string(_("Space"), 0, 5,
|
2005-02-25 22:17:57 +03:00
|
|
|
|
FALSE);
|
|
|
|
|
|
2005-06-16 03:33:54 +04:00
|
|
|
|
ptr += sprintf(ptr, "M-%s", space_ptr);
|
2005-02-25 22:17:57 +03:00
|
|
|
|
|
2005-06-16 03:33:54 +04:00
|
|
|
|
free(space_ptr);
|
2005-02-25 22:17:57 +03:00
|
|
|
|
} else
|
2005-06-16 03:20:56 +04:00
|
|
|
|
/* Normal values. */
|
|
|
|
|
ptr += sprintf(ptr, (entries == 1) ? "M-%c" : "(M-%c)",
|
2004-09-12 01:41:13 +04:00
|
|
|
|
toupper(s->metaval));
|
|
|
|
|
*(ptr++) = '\t';
|
|
|
|
|
}
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
2004-09-12 01:41:13 +04:00
|
|
|
|
/* Miscellaneous meta key sequence. */
|
|
|
|
|
if (entries < 3 && s->miscval != NANO_NO_KEY) {
|
|
|
|
|
entries++;
|
|
|
|
|
/* If this is the last entry, put it at the end. */
|
|
|
|
|
if (entries == 2) {
|
|
|
|
|
entries++;
|
|
|
|
|
*(ptr++) = '\t';
|
|
|
|
|
}
|
2004-03-20 00:46:34 +03:00
|
|
|
|
ptr += sprintf(ptr, "(M-%c)", toupper(s->miscval));
|
2004-09-12 01:41:13 +04:00
|
|
|
|
*(ptr++) = '\t';
|
|
|
|
|
}
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
2004-09-12 01:41:13 +04:00
|
|
|
|
/* Make sure all the help text starts at the same place. */
|
|
|
|
|
while (entries < 3) {
|
|
|
|
|
entries++;
|
|
|
|
|
*(ptr++) = '\t';
|
|
|
|
|
}
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
|
|
|
|
assert(s->help != NULL);
|
2005-02-25 22:17:57 +03:00
|
|
|
|
|
|
|
|
|
if (COLS > 24) {
|
|
|
|
|
char *help_ptr = display_string(s->help, 0, COLS - 24,
|
|
|
|
|
FALSE);
|
|
|
|
|
|
|
|
|
|
ptr += sprintf(ptr, help_ptr);
|
|
|
|
|
|
|
|
|
|
free(help_ptr);
|
|
|
|
|
}
|
2005-06-13 18:00:22 +04:00
|
|
|
|
|
2005-02-25 22:17:57 +03:00
|
|
|
|
ptr += sprintf(ptr, "\n");
|
2002-09-07 00:35:28 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
/* And the toggles... */
|
2004-03-20 00:46:34 +03:00
|
|
|
|
if (currshortcut == main_list) {
|
2002-09-07 00:35:28 +04:00
|
|
|
|
for (t = toggles; t != NULL; t = t->next) {
|
2005-03-04 20:09:41 +03:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
assert(t->desc != NULL);
|
2005-03-04 20:09:41 +03:00
|
|
|
|
|
2004-10-22 02:49:51 +04:00
|
|
|
|
ptr += sprintf(ptr, "M-%c\t\t\t%s %s\n", toupper(t->val),
|
|
|
|
|
t->desc, _("enable/disable"));
|
2002-09-07 00:35:28 +04:00
|
|
|
|
}
|
2004-03-20 00:46:34 +03:00
|
|
|
|
}
|
2005-02-25 22:17:57 +03:00
|
|
|
|
|
|
|
|
|
#ifdef ENABLE_NANORC
|
|
|
|
|
if (old_whitespace)
|
|
|
|
|
SET(WHITESPACE_DISPLAY);
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
|
|
|
|
/* If all went well, we didn't overwrite the allocated space for
|
2004-08-05 19:45:09 +04:00
|
|
|
|
* help_text. */
|
2005-03-22 06:58:51 +03:00
|
|
|
|
assert(strlen(help_text) <= allocsize + 1);
|
2002-09-07 00:35:28 +04:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Create a new filestruct node. Note that we specifically do not set
|
|
|
|
|
* prevnode->next equal to the new line. */
|
|
|
|
|
filestruct *make_new_node(filestruct *prevnode)
|
|
|
|
|
{
|
|
|
|
|
filestruct *newnode = (filestruct *)nmalloc(sizeof(filestruct));
|
2005-05-15 00:52:20 +04:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
newnode->data = NULL;
|
|
|
|
|
newnode->prev = prevnode;
|
|
|
|
|
newnode->next = NULL;
|
2004-11-25 07:39:07 +03:00
|
|
|
|
newnode->lineno = (prevnode != NULL) ? prevnode->lineno + 1 : 1;
|
2005-05-15 00:52:20 +04:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
return newnode;
|
|
|
|
|
}
|
|
|
|
|
|
2004-11-25 07:39:07 +03:00
|
|
|
|
/* Make a copy of a filestruct node. */
|
2002-07-19 05:08:59 +04:00
|
|
|
|
filestruct *copy_node(const filestruct *src)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
2005-03-04 20:09:41 +03:00
|
|
|
|
filestruct *dst;
|
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
assert(src != NULL);
|
2005-03-04 20:09:41 +03:00
|
|
|
|
|
|
|
|
|
dst = (filestruct *)nmalloc(sizeof(filestruct));
|
|
|
|
|
|
2004-11-25 07:39:07 +03:00
|
|
|
|
dst->data = mallocstrcpy(NULL, src->data);
|
2000-06-06 09:53:49 +04:00
|
|
|
|
dst->next = src->next;
|
|
|
|
|
dst->prev = src->prev;
|
|
|
|
|
dst->lineno = src->lineno;
|
2005-03-04 20:09:41 +03:00
|
|
|
|
|
2000-06-06 09:53:49 +04:00
|
|
|
|
return dst;
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
/* Splice a node into an existing filestruct. */
|
2004-07-08 21:15:10 +04:00
|
|
|
|
void splice_node(filestruct *begin, filestruct *newnode, filestruct
|
|
|
|
|
*end)
|
2002-09-07 00:35:28 +04:00
|
|
|
|
{
|
2004-11-25 07:39:07 +03:00
|
|
|
|
assert(newnode != NULL && begin != NULL);
|
2005-03-04 20:09:41 +03:00
|
|
|
|
|
2004-11-25 07:39:07 +03:00
|
|
|
|
newnode->next = end;
|
|
|
|
|
newnode->prev = begin;
|
|
|
|
|
begin->next = newnode;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
if (end != NULL)
|
|
|
|
|
end->prev = newnode;
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-10 06:31:20 +04:00
|
|
|
|
/* Unlink a node from the rest of the filestruct. */
|
2002-07-19 05:08:59 +04:00
|
|
|
|
void unlink_node(const filestruct *fileptr)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
2002-07-19 05:08:59 +04:00
|
|
|
|
assert(fileptr != NULL);
|
2005-03-04 20:09:41 +03:00
|
|
|
|
|
2002-04-10 06:31:20 +04:00
|
|
|
|
if (fileptr->prev != NULL)
|
|
|
|
|
fileptr->prev->next = fileptr->next;
|
|
|
|
|
if (fileptr->next != NULL)
|
|
|
|
|
fileptr->next->prev = fileptr->prev;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Delete a node from the filestruct. */
|
2002-07-19 05:08:59 +04:00
|
|
|
|
void delete_node(filestruct *fileptr)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
2004-11-25 07:39:07 +03:00
|
|
|
|
assert(fileptr != NULL && fileptr->data != NULL);
|
2005-03-04 20:09:41 +03:00
|
|
|
|
|
2004-11-25 07:39:07 +03:00
|
|
|
|
if (fileptr->data != NULL)
|
|
|
|
|
free(fileptr->data);
|
|
|
|
|
free(fileptr);
|
2002-04-10 06:31:20 +04:00
|
|
|
|
}
|
|
|
|
|
|
2005-05-15 00:52:20 +04:00
|
|
|
|
/* Duplicate a whole filestruct. */
|
2002-07-19 05:08:59 +04:00
|
|
|
|
filestruct *copy_filestruct(const filestruct *src)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
2005-05-15 00:52:20 +04:00
|
|
|
|
filestruct *head, *copy;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
assert(src != NULL);
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2005-05-15 00:52:20 +04:00
|
|
|
|
copy = copy_node(src);
|
|
|
|
|
copy->prev = NULL;
|
|
|
|
|
head = copy;
|
2002-07-19 05:08:59 +04:00
|
|
|
|
src = src->next;
|
2005-05-15 00:52:20 +04:00
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
while (src != NULL) {
|
2005-05-15 00:52:20 +04:00
|
|
|
|
copy->next = copy_node(src);
|
|
|
|
|
copy->next->prev = copy;
|
|
|
|
|
copy = copy->next;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
src = src->next;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
2005-05-15 00:52:20 +04:00
|
|
|
|
copy->next = NULL;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
|
|
|
|
return head;
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-10 06:31:20 +04:00
|
|
|
|
/* Frees a filestruct. */
|
2002-07-19 05:08:59 +04:00
|
|
|
|
void free_filestruct(filestruct *src)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
2004-11-25 07:39:07 +03:00
|
|
|
|
assert(src != NULL);
|
|
|
|
|
|
|
|
|
|
while (src->next != NULL) {
|
|
|
|
|
src = src->next;
|
|
|
|
|
delete_node(src->prev);
|
2002-04-10 06:31:20 +04:00
|
|
|
|
}
|
2004-11-25 07:39:07 +03:00
|
|
|
|
delete_node(src);
|
2002-04-10 06:31:20 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-11-04 01:03:41 +03:00
|
|
|
|
/* Partition a filestruct so it begins at (top, top_x) and ends at (bot,
|
|
|
|
|
* bot_x). */
|
|
|
|
|
partition *partition_filestruct(filestruct *top, size_t top_x,
|
|
|
|
|
filestruct *bot, size_t bot_x)
|
|
|
|
|
{
|
|
|
|
|
partition *p;
|
2005-03-04 20:09:41 +03:00
|
|
|
|
|
2004-11-08 06:22:23 +03:00
|
|
|
|
assert(top != NULL && bot != NULL && fileage != NULL && filebot != NULL);
|
2004-11-04 01:03:41 +03:00
|
|
|
|
|
|
|
|
|
/* Initialize the partition. */
|
|
|
|
|
p = (partition *)nmalloc(sizeof(partition));
|
|
|
|
|
|
2004-11-04 19:45:48 +03:00
|
|
|
|
/* If the top and bottom of the partition are different from the top
|
|
|
|
|
* and bottom of the filestruct, save the latter and then set them
|
|
|
|
|
* to top and bot. */
|
|
|
|
|
if (top != fileage) {
|
|
|
|
|
p->fileage = fileage;
|
|
|
|
|
fileage = top;
|
|
|
|
|
} else
|
|
|
|
|
p->fileage = NULL;
|
|
|
|
|
if (bot != filebot) {
|
|
|
|
|
p->filebot = filebot;
|
|
|
|
|
filebot = bot;
|
|
|
|
|
} else
|
|
|
|
|
p->filebot = NULL;
|
2004-11-04 01:03:41 +03:00
|
|
|
|
|
|
|
|
|
/* Save the line above the top of the partition, detach the top of
|
|
|
|
|
* the partition from it, and save the text before top_x in
|
|
|
|
|
* top_data. */
|
|
|
|
|
p->top_prev = top->prev;
|
|
|
|
|
top->prev = NULL;
|
|
|
|
|
p->top_data = mallocstrncpy(NULL, top->data, top_x + 1);
|
|
|
|
|
p->top_data[top_x] = '\0';
|
|
|
|
|
|
|
|
|
|
/* Save the line below the bottom of the partition, detach the
|
|
|
|
|
* bottom of the partition from it, and save the text after bot_x in
|
|
|
|
|
* bot_data. */
|
|
|
|
|
p->bot_next = bot->next;
|
|
|
|
|
bot->next = NULL;
|
|
|
|
|
p->bot_data = mallocstrcpy(NULL, bot->data + bot_x);
|
|
|
|
|
|
|
|
|
|
/* Remove all text after bot_x at the bottom of the partition. */
|
|
|
|
|
null_at(&bot->data, bot_x);
|
|
|
|
|
|
|
|
|
|
/* Remove all text before top_x at the top of the partition. */
|
|
|
|
|
charmove(top->data, top->data + top_x, strlen(top->data) -
|
|
|
|
|
top_x + 1);
|
|
|
|
|
align(&top->data);
|
|
|
|
|
|
|
|
|
|
/* Return the partition. */
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Unpartition a filestruct so it begins at (fileage, 0) and ends at
|
|
|
|
|
* (filebot, strlen(filebot)) again. */
|
2004-11-22 03:16:23 +03:00
|
|
|
|
void unpartition_filestruct(partition **p)
|
2004-11-04 01:03:41 +03:00
|
|
|
|
{
|
|
|
|
|
char *tmp;
|
2005-03-04 20:09:41 +03:00
|
|
|
|
|
2004-11-08 06:19:10 +03:00
|
|
|
|
assert(p != NULL && fileage != NULL && filebot != NULL);
|
2004-11-04 01:03:41 +03:00
|
|
|
|
|
|
|
|
|
/* Reattach the line above the top of the partition, and restore the
|
|
|
|
|
* text before top_x from top_data. Free top_data when we're done
|
|
|
|
|
* with it. */
|
|
|
|
|
tmp = mallocstrcpy(NULL, fileage->data);
|
2004-11-22 03:16:23 +03:00
|
|
|
|
fileage->prev = (*p)->top_prev;
|
2004-11-04 18:31:43 +03:00
|
|
|
|
if (fileage->prev != NULL)
|
|
|
|
|
fileage->prev->next = fileage;
|
2004-11-22 03:16:23 +03:00
|
|
|
|
fileage->data = charealloc(fileage->data, strlen((*p)->top_data) +
|
2004-11-04 01:03:41 +03:00
|
|
|
|
strlen(fileage->data) + 1);
|
2004-11-22 03:16:23 +03:00
|
|
|
|
strcpy(fileage->data, (*p)->top_data);
|
|
|
|
|
free((*p)->top_data);
|
2004-11-04 01:03:41 +03:00
|
|
|
|
strcat(fileage->data, tmp);
|
|
|
|
|
free(tmp);
|
|
|
|
|
|
|
|
|
|
/* Reattach the line below the bottom of the partition, and restore
|
|
|
|
|
* the text after bot_x from bot_data. Free bot_data when we're
|
|
|
|
|
* done with it. */
|
2004-11-22 03:16:23 +03:00
|
|
|
|
filebot->next = (*p)->bot_next;
|
2004-11-04 18:31:43 +03:00
|
|
|
|
if (filebot->next != NULL)
|
|
|
|
|
filebot->next->prev = filebot;
|
2004-11-04 01:03:41 +03:00
|
|
|
|
filebot->data = charealloc(filebot->data, strlen(filebot->data) +
|
2004-11-22 03:16:23 +03:00
|
|
|
|
strlen((*p)->bot_data) + 1);
|
|
|
|
|
strcat(filebot->data, (*p)->bot_data);
|
|
|
|
|
free((*p)->bot_data);
|
2004-11-04 01:03:41 +03:00
|
|
|
|
|
2004-11-04 19:45:48 +03:00
|
|
|
|
/* Restore the top and bottom of the filestruct, if they were
|
|
|
|
|
* different from the top and bottom of the partition. */
|
2004-11-22 03:16:23 +03:00
|
|
|
|
if ((*p)->fileage != NULL)
|
|
|
|
|
fileage = (*p)->fileage;
|
|
|
|
|
if ((*p)->filebot != NULL)
|
|
|
|
|
filebot = (*p)->filebot;
|
2004-11-04 01:03:41 +03:00
|
|
|
|
|
|
|
|
|
/* Uninitialize the partition. */
|
2004-11-22 03:16:23 +03:00
|
|
|
|
free(*p);
|
|
|
|
|
*p = NULL;
|
2004-11-04 01:03:41 +03:00
|
|
|
|
}
|
|
|
|
|
|
2004-11-23 07:08:28 +03:00
|
|
|
|
/* Move all the text between (top, top_x) and (bot, bot_x) in the
|
|
|
|
|
* current filestruct to a filestruct beginning with file_top and ending
|
|
|
|
|
* with file_bot. If no text is between (top, top_x) and (bot, bot_x),
|
|
|
|
|
* don't do anything. */
|
|
|
|
|
void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
|
|
|
|
|
filestruct *top, size_t top_x, filestruct *bot, size_t bot_x)
|
|
|
|
|
{
|
|
|
|
|
filestruct *top_save;
|
2005-01-27 23:49:07 +03:00
|
|
|
|
size_t part_totsize;
|
2004-11-23 07:08:28 +03:00
|
|
|
|
bool at_edittop;
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
bool mark_inside = FALSE;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
assert(file_top != NULL && file_bot != NULL && top != NULL && bot != NULL);
|
|
|
|
|
|
|
|
|
|
/* If (top, top_x)-(bot, bot_x) doesn't cover any text, get out. */
|
|
|
|
|
if (top == bot && top_x == bot_x)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Partition the filestruct so that it contains only the text from
|
|
|
|
|
* (top, top_x) to (bot, bot_x), keep track of whether the top of
|
|
|
|
|
* the partition is the top of the edit window, and keep track of
|
|
|
|
|
* whether the mark begins inside the partition. */
|
|
|
|
|
filepart = partition_filestruct(top, top_x, bot, bot_x);
|
|
|
|
|
at_edittop = (fileage == edittop);
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
if (ISSET(MARK_ISSET))
|
|
|
|
|
mark_inside = (mark_beginbuf->lineno >= fileage->lineno &&
|
|
|
|
|
mark_beginbuf->lineno <= filebot->lineno &&
|
|
|
|
|
(mark_beginbuf != fileage || mark_beginx >= top_x) &&
|
|
|
|
|
(mark_beginbuf != filebot || mark_beginx <= bot_x));
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Get the number of characters in the text, and subtract it from
|
|
|
|
|
* totsize. */
|
|
|
|
|
get_totals(top, bot, NULL, &part_totsize);
|
|
|
|
|
totsize -= part_totsize;
|
|
|
|
|
|
|
|
|
|
if (*file_top == NULL) {
|
|
|
|
|
/* If file_top is empty, just move all the text directly into
|
|
|
|
|
* it. This is equivalent to tacking the text in top onto the
|
|
|
|
|
* (lack of) text at the end of file_top. */
|
|
|
|
|
*file_top = fileage;
|
|
|
|
|
*file_bot = filebot;
|
|
|
|
|
} else {
|
|
|
|
|
/* Otherwise, tack the text in top onto the text at the end of
|
|
|
|
|
* file_bot. */
|
|
|
|
|
(*file_bot)->data = charealloc((*file_bot)->data,
|
|
|
|
|
strlen((*file_bot)->data) + strlen(fileage->data) + 1);
|
|
|
|
|
strcat((*file_bot)->data, fileage->data);
|
|
|
|
|
|
|
|
|
|
/* Attach the line after top to the line after file_bot. Then,
|
|
|
|
|
* if there's more than one line after top, move file_bot down
|
|
|
|
|
* to bot. */
|
|
|
|
|
(*file_bot)->next = fileage->next;
|
|
|
|
|
if ((*file_bot)->next != NULL) {
|
|
|
|
|
(*file_bot)->next->prev = *file_bot;
|
|
|
|
|
*file_bot = filebot;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Since the text has now been saved, remove it from the filestruct.
|
|
|
|
|
* If the top of the partition was the top of the edit window, set
|
|
|
|
|
* edittop to where the text used to start. If the mark began
|
|
|
|
|
* inside the partition, set the beginning of the mark to where the
|
|
|
|
|
* text used to start. */
|
|
|
|
|
fileage = (filestruct *)nmalloc(sizeof(filestruct));
|
|
|
|
|
fileage->data = mallocstrcpy(NULL, "");
|
|
|
|
|
filebot = fileage;
|
|
|
|
|
if (at_edittop)
|
|
|
|
|
edittop = fileage;
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
if (mark_inside) {
|
|
|
|
|
mark_beginbuf = fileage;
|
|
|
|
|
mark_beginx = top_x;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Restore the current line and cursor position. */
|
|
|
|
|
current = fileage;
|
|
|
|
|
current_x = top_x;
|
|
|
|
|
|
|
|
|
|
top_save = fileage;
|
|
|
|
|
|
|
|
|
|
/* Unpartition the filestruct so that it contains all the text
|
|
|
|
|
* again, minus the saved text. */
|
|
|
|
|
unpartition_filestruct(&filepart);
|
|
|
|
|
|
|
|
|
|
/* Renumber starting with the beginning line of the old
|
|
|
|
|
* partition. */
|
|
|
|
|
renumber(top_save);
|
|
|
|
|
|
|
|
|
|
if (filebot->data[0] != '\0')
|
|
|
|
|
new_magicline();
|
|
|
|
|
|
|
|
|
|
/* Set totlines to the new number of lines in the file. */
|
|
|
|
|
totlines = filebot->lineno;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Copy all the text from the filestruct beginning with file_top and
|
|
|
|
|
* ending with file_bot to the current filestruct at the current cursor
|
|
|
|
|
* position. */
|
|
|
|
|
void copy_from_filestruct(filestruct *file_top, filestruct *file_bot)
|
|
|
|
|
{
|
|
|
|
|
filestruct *top_save;
|
|
|
|
|
int part_totlines;
|
2005-01-27 23:49:07 +03:00
|
|
|
|
size_t part_totsize;
|
2004-11-23 07:08:28 +03:00
|
|
|
|
bool at_edittop;
|
|
|
|
|
|
|
|
|
|
assert(file_top != NULL && file_bot != NULL);
|
|
|
|
|
|
|
|
|
|
/* Partition the filestruct so that it contains no text, and keep
|
|
|
|
|
* track of whether the top of the partition is the top of the edit
|
|
|
|
|
* window. */
|
|
|
|
|
filepart = partition_filestruct(current, current_x, current,
|
|
|
|
|
current_x);
|
|
|
|
|
at_edittop = (fileage == edittop);
|
|
|
|
|
|
|
|
|
|
/* Put the top and bottom of the filestruct at copies of file_top
|
|
|
|
|
* and file_bot. */
|
|
|
|
|
fileage = copy_filestruct(file_top);
|
|
|
|
|
filebot = fileage;
|
|
|
|
|
while (filebot->next != NULL)
|
|
|
|
|
filebot = filebot->next;
|
|
|
|
|
|
|
|
|
|
/* Restore the current line and cursor position. */
|
|
|
|
|
current = filebot;
|
|
|
|
|
current_x = strlen(filebot->data);
|
|
|
|
|
if (fileage == filebot)
|
|
|
|
|
current_x += strlen(filepart->top_data);
|
|
|
|
|
|
|
|
|
|
/* Get the number of lines and the number of characters in the saved
|
|
|
|
|
* text, and add the latter to totsize. */
|
|
|
|
|
get_totals(fileage, filebot, &part_totlines, &part_totsize);
|
|
|
|
|
totsize += part_totsize;
|
|
|
|
|
|
|
|
|
|
/* If the top of the partition was the top of the edit window, set
|
|
|
|
|
* edittop to where the saved text now starts, and update the
|
|
|
|
|
* current y-coordinate to account for the number of lines it
|
|
|
|
|
* has, less one since the first line will be tacked onto the
|
|
|
|
|
* current line. */
|
|
|
|
|
if (at_edittop)
|
|
|
|
|
edittop = fileage;
|
|
|
|
|
current_y += part_totlines - 1;
|
|
|
|
|
|
|
|
|
|
top_save = fileage;
|
|
|
|
|
|
|
|
|
|
/* Unpartition the filestruct so that it contains all the text
|
|
|
|
|
* again, minus the saved text. */
|
|
|
|
|
unpartition_filestruct(&filepart);
|
|
|
|
|
|
|
|
|
|
/* Renumber starting with the beginning line of the old
|
|
|
|
|
* partition. */
|
|
|
|
|
renumber(top_save);
|
|
|
|
|
|
|
|
|
|
if (filebot->data[0] != '\0')
|
|
|
|
|
new_magicline();
|
|
|
|
|
|
|
|
|
|
/* Set totlines to the new number of lines in the file. */
|
|
|
|
|
totlines = filebot->lineno;
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
void renumber_all(void)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
|
|
|
|
filestruct *temp;
|
2002-03-06 06:30:40 +03:00
|
|
|
|
int i = 1;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
assert(fileage == NULL || fileage != fileage->next);
|
2005-03-04 20:09:41 +03:00
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
for (temp = fileage; temp != NULL; temp = temp->next)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
temp->lineno = i++;
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
void renumber(filestruct *fileptr)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
2002-07-19 05:08:59 +04:00
|
|
|
|
if (fileptr == NULL || fileptr->prev == NULL || fileptr == fileage)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
renumber_all();
|
2002-07-19 05:08:59 +04:00
|
|
|
|
else {
|
|
|
|
|
int lineno = fileptr->prev->lineno;
|
2001-10-23 03:22:19 +04:00
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
assert(fileptr != fileptr->next);
|
2005-03-04 20:09:41 +03:00
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
for (; fileptr != NULL; fileptr = fileptr->next)
|
|
|
|
|
fileptr->lineno = ++lineno;
|
|
|
|
|
}
|
2000-07-28 05:41:29 +04:00
|
|
|
|
}
|
|
|
|
|
|
2005-03-22 23:17:38 +03:00
|
|
|
|
#ifdef HAVE_GETOPT_LONG
|
|
|
|
|
#define print1opt(shortflag, longflag, desc) print1opt_full(shortflag, longflag, desc)
|
|
|
|
|
#else
|
|
|
|
|
#define print1opt(shortflag, longflag, desc) print1opt_full(shortflag, desc)
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-08-05 19:16:19 +04:00
|
|
|
|
/* Print one usage string to the screen. This cuts down on duplicate
|
2005-03-21 10:24:47 +03:00
|
|
|
|
* strings to translate, and leaves out the parts that shouldn't be
|
2002-07-19 05:08:59 +04:00
|
|
|
|
* translatable (the flag names). */
|
2005-03-21 10:24:47 +03:00
|
|
|
|
void print1opt_full(const char *shortflag
|
|
|
|
|
#ifdef HAVE_GETOPT_LONG
|
|
|
|
|
, const char *longflag
|
|
|
|
|
#endif
|
|
|
|
|
, const char *desc)
|
2002-03-09 21:51:58 +03:00
|
|
|
|
{
|
|
|
|
|
printf(" %s\t", shortflag);
|
|
|
|
|
if (strlen(shortflag) < 8)
|
|
|
|
|
printf("\t");
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_GETOPT_LONG
|
|
|
|
|
printf("%s\t", longflag);
|
|
|
|
|
if (strlen(longflag) < 8)
|
|
|
|
|
printf("\t\t");
|
|
|
|
|
else if (strlen(longflag) < 16)
|
|
|
|
|
printf("\t");
|
|
|
|
|
#endif
|
|
|
|
|
|
2005-04-14 07:13:49 +04:00
|
|
|
|
if (desc != NULL)
|
|
|
|
|
printf("%s", _(desc));
|
|
|
|
|
printf("\n");
|
2002-03-09 21:51:58 +03:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-21 20:10:37 +04:00
|
|
|
|
void usage(void)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
|
|
|
|
#ifdef HAVE_GETOPT_LONG
|
2005-05-21 21:15:46 +04:00
|
|
|
|
printf(
|
|
|
|
|
_("Usage: nano [+LINE,COLUMN] [GNU long option] [option] [file]\n\n"));
|
2002-07-19 05:08:59 +04:00
|
|
|
|
printf(_("Option\t\tLong option\t\tMeaning\n"));
|
2000-06-06 09:53:49 +04:00
|
|
|
|
#else
|
2002-07-19 05:08:59 +04:00
|
|
|
|
printf(_("Usage: nano [+LINE] [option] [file]\n\n"));
|
|
|
|
|
printf(_("Option\t\tMeaning\n"));
|
2004-08-08 02:00:02 +04:00
|
|
|
|
#endif
|
2002-03-09 21:51:58 +03:00
|
|
|
|
|
2004-08-05 19:45:09 +04:00
|
|
|
|
print1opt("-h, -?", "--help", N_("Show this message"));
|
2005-05-21 21:15:46 +04:00
|
|
|
|
print1opt(_("+LINE,COLUMN"), "",
|
|
|
|
|
N_("Start at line LINE, column COLUMN"));
|
2001-09-22 04:42:10 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-08-05 19:45:09 +04:00
|
|
|
|
print1opt("-A", "--smarthome", N_("Enable smart home key"));
|
2005-05-30 06:09:21 +04:00
|
|
|
|
print1opt("-B", "--backup", N_("Save backups of existing files"));
|
2005-06-16 03:20:56 +04:00
|
|
|
|
print1opt(_("-C [dir]"), _("--backupdir=[dir]"),
|
2005-05-30 06:09:21 +04:00
|
|
|
|
N_("Directory for saving unique backup files"));
|
2005-06-16 03:20:56 +04:00
|
|
|
|
print1opt("-E", "--tabstospaces",
|
|
|
|
|
N_("Convert typed tabs to spaces"));
|
2001-09-22 04:42:10 +04:00
|
|
|
|
#endif
|
2001-07-14 23:32:47 +04:00
|
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
2004-08-05 19:45:09 +04:00
|
|
|
|
print1opt("-F", "--multibuffer", N_("Enable multiple file buffers"));
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#endif
|
|
|
|
|
#ifdef ENABLE_NANORC
|
2003-09-07 01:44:37 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2005-05-21 21:15:46 +04:00
|
|
|
|
print1opt("-H", "--historylog",
|
|
|
|
|
N_("Log & read search/replace string history"));
|
2003-09-07 01:44:37 +04:00
|
|
|
|
#endif
|
2005-05-21 21:15:46 +04:00
|
|
|
|
print1opt("-I", "--ignorercfiles",
|
|
|
|
|
N_("Don't look at nanorc files"));
|
2001-09-22 08:20:25 +04:00
|
|
|
|
#endif
|
|
|
|
|
#ifndef NANO_SMALL
|
2005-05-21 21:15:46 +04:00
|
|
|
|
print1opt("-N", "--noconvert",
|
|
|
|
|
N_("Don't convert files from DOS/Mac format"));
|
2002-03-04 01:36:36 +03:00
|
|
|
|
#endif
|
2005-01-17 08:06:55 +03:00
|
|
|
|
print1opt("-O", "--morespace", N_("Use more space for editing"));
|
2002-03-04 01:36:36 +03:00
|
|
|
|
#ifndef DISABLE_JUSTIFY
|
2005-05-21 21:15:46 +04:00
|
|
|
|
print1opt(_("-Q [str]"), _("--quotestr=[str]"),
|
2005-06-16 21:26:01 +04:00
|
|
|
|
N_("Quoting string"));
|
2001-07-14 23:32:47 +04:00
|
|
|
|
#endif
|
2005-06-18 02:53:41 +04:00
|
|
|
|
print1opt("-R", "--restricted", N_("Restricted mode"));
|
2001-09-22 23:02:04 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-08-05 19:45:09 +04:00
|
|
|
|
print1opt("-S", "--smooth", N_("Smooth scrolling"));
|
2001-09-22 23:02:04 +04:00
|
|
|
|
#endif
|
2005-05-21 21:15:46 +04:00
|
|
|
|
print1opt(_("-T [#cols]"), _("--tabsize=[#cols]"),
|
|
|
|
|
N_("Set width of a tab in cols to #cols"));
|
2005-06-17 23:09:18 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2005-06-17 23:06:25 +04:00
|
|
|
|
print1opt("-U", _("--quickblank"),
|
|
|
|
|
N_("Do quick statusbar blanking"));
|
2005-06-17 23:09:18 +04:00
|
|
|
|
#endif
|
2005-05-21 21:15:46 +04:00
|
|
|
|
print1opt("-V", "--version",
|
|
|
|
|
N_("Print version information and exit"));
|
2002-05-04 08:23:30 +04:00
|
|
|
|
#ifdef ENABLE_COLOR
|
2005-05-21 21:15:46 +04:00
|
|
|
|
print1opt(_("-Y [str]"), _("--syntax=[str]"),
|
|
|
|
|
N_("Syntax definition to use"));
|
2002-05-04 08:23:30 +04:00
|
|
|
|
#endif
|
2004-08-05 19:45:09 +04:00
|
|
|
|
print1opt("-c", "--const", N_("Constantly show cursor position"));
|
2005-05-21 21:15:46 +04:00
|
|
|
|
print1opt("-d", "--rebinddelete",
|
|
|
|
|
N_("Fix Backspace/Delete confusion problem"));
|
2005-03-21 10:24:47 +03:00
|
|
|
|
#ifndef NANO_SMALL
|
2005-05-21 21:15:46 +04:00
|
|
|
|
print1opt("-i", "--autoindent",
|
|
|
|
|
N_("Automatically indent new lines"));
|
2005-03-21 10:24:47 +03:00
|
|
|
|
print1opt("-k", "--cut", N_("Cut from cursor to end of line"));
|
2005-03-27 01:49:46 +03:00
|
|
|
|
#endif
|
2005-05-21 21:15:46 +04:00
|
|
|
|
print1opt("-l", "--nofollow",
|
|
|
|
|
N_("Don't follow symbolic links, overwrite"));
|
2003-10-04 00:26:25 +04:00
|
|
|
|
#ifndef DISABLE_MOUSE
|
2004-08-05 19:45:09 +04:00
|
|
|
|
print1opt("-m", "--mouse", N_("Enable mouse"));
|
2000-06-06 09:53:49 +04:00
|
|
|
|
#endif
|
2001-09-19 07:19:43 +04:00
|
|
|
|
#ifndef DISABLE_OPERATINGDIR
|
2005-05-21 21:15:46 +04:00
|
|
|
|
print1opt(_("-o [dir]"), _("--operatingdir=[dir]"),
|
|
|
|
|
N_("Set operating directory"));
|
2000-06-06 09:53:49 +04:00
|
|
|
|
#endif
|
2005-05-21 21:15:46 +04:00
|
|
|
|
print1opt("-p", "--preserve",
|
|
|
|
|
N_("Preserve XON (^Q) and XOFF (^S) keys"));
|
2001-05-21 16:56:25 +04:00
|
|
|
|
#ifndef DISABLE_WRAPJUSTIFY
|
2005-05-21 21:15:46 +04:00
|
|
|
|
print1opt(_("-r [#cols]"), _("--fill=[#cols]"),
|
|
|
|
|
N_("Set fill cols to (wrap lines at) #cols"));
|
2001-05-21 16:56:25 +04:00
|
|
|
|
#endif
|
2001-01-12 10:51:05 +03:00
|
|
|
|
#ifndef DISABLE_SPELLER
|
2005-05-21 21:15:46 +04:00
|
|
|
|
print1opt(_("-s [prog]"), _("--speller=[prog]"),
|
|
|
|
|
N_("Enable alternate speller"));
|
2001-01-12 10:51:05 +03:00
|
|
|
|
#endif
|
2005-05-21 21:15:46 +04:00
|
|
|
|
print1opt("-t", "--tempfile",
|
|
|
|
|
N_("Auto save on exit, don't prompt"));
|
2004-08-05 19:45:09 +04:00
|
|
|
|
print1opt("-v", "--view", N_("View (read only) mode"));
|
2001-04-02 09:36:08 +04:00
|
|
|
|
#ifndef DISABLE_WRAPPING
|
2004-08-05 19:45:09 +04:00
|
|
|
|
print1opt("-w", "--nowrap", N_("Don't wrap long lines"));
|
2000-06-06 09:53:49 +04:00
|
|
|
|
#endif
|
2004-08-05 19:45:09 +04:00
|
|
|
|
print1opt("-x", "--nohelp", N_("Don't show help window"));
|
|
|
|
|
print1opt("-z", "--suspend", N_("Enable suspend"));
|
2002-07-19 05:08:59 +04:00
|
|
|
|
|
2004-08-05 19:16:19 +04:00
|
|
|
|
/* This is a special case. */
|
2005-04-14 07:13:49 +04:00
|
|
|
|
print1opt("-a, -b, -e,", "", NULL);
|
2005-05-21 21:15:46 +04:00
|
|
|
|
print1opt("-f, -g, -j", "", N_("(ignored, for Pico compatibility)"));
|
2002-03-09 21:51:58 +03:00
|
|
|
|
|
2000-06-06 09:53:49 +04:00
|
|
|
|
exit(0);
|
|
|
|
|
}
|
|
|
|
|
|
2002-08-21 20:10:37 +04:00
|
|
|
|
void version(void)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
2005-03-11 07:22:34 +03:00
|
|
|
|
printf(_(" GNU nano version %s (compiled %s, %s)\n"), VERSION,
|
|
|
|
|
__TIME__, __DATE__);
|
|
|
|
|
printf(
|
|
|
|
|
_(" Email: nano@nano-editor.org Web: http://www.nano-editor.org/"));
|
2000-11-24 23:45:14 +03:00
|
|
|
|
printf(_("\n Compiled options:"));
|
2000-12-01 21:46:01 +03:00
|
|
|
|
|
2003-01-17 06:39:41 +03:00
|
|
|
|
#ifndef ENABLE_NLS
|
|
|
|
|
printf(" --disable-nls");
|
|
|
|
|
#endif
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf(" --enable-debug");
|
|
|
|
|
#endif
|
2000-11-24 23:45:14 +03:00
|
|
|
|
#ifdef NANO_EXTRA
|
|
|
|
|
printf(" --enable-extra");
|
2002-01-17 15:40:33 +03:00
|
|
|
|
#endif
|
2001-01-12 10:51:05 +03:00
|
|
|
|
#ifdef NANO_SMALL
|
|
|
|
|
printf(" --enable-tiny");
|
|
|
|
|
#else
|
2001-04-12 07:01:53 +04:00
|
|
|
|
#ifdef DISABLE_BROWSER
|
2001-01-05 08:41:07 +03:00
|
|
|
|
printf(" --disable-browser");
|
2001-04-12 07:01:53 +04:00
|
|
|
|
#endif
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#ifdef DISABLE_HELP
|
|
|
|
|
printf(" --disable-help");
|
2001-04-12 07:01:53 +04:00
|
|
|
|
#endif
|
|
|
|
|
#ifdef DISABLE_JUSTIFY
|
2000-12-01 21:46:01 +03:00
|
|
|
|
printf(" --disable-justify");
|
2001-04-12 07:01:53 +04:00
|
|
|
|
#endif
|
2003-10-04 00:26:25 +04:00
|
|
|
|
#ifdef DISABLE_MOUSE
|
2001-04-12 18:51:48 +04:00
|
|
|
|
printf(" --disable-mouse");
|
2000-12-18 08:36:51 +03:00
|
|
|
|
#endif
|
2001-09-19 07:19:43 +04:00
|
|
|
|
#ifdef DISABLE_OPERATINGDIR
|
|
|
|
|
printf(" --disable-operatingdir");
|
|
|
|
|
#endif
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#ifdef DISABLE_SPELLER
|
|
|
|
|
printf(" --disable-speller");
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef DISABLE_TABCOMP
|
|
|
|
|
printf(" --disable-tabcomp");
|
|
|
|
|
#endif
|
|
|
|
|
#endif /* NANO_SMALL */
|
|
|
|
|
#ifdef DISABLE_WRAPPING
|
|
|
|
|
printf(" --disable-wrapping");
|
|
|
|
|
#endif
|
2002-10-25 20:08:53 +04:00
|
|
|
|
#ifdef DISABLE_ROOTWRAP
|
|
|
|
|
printf(" --disable-wrapping-as-root");
|
|
|
|
|
#endif
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#ifdef ENABLE_COLOR
|
|
|
|
|
printf(" --enable-color");
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
|
|
|
|
printf(" --enable-multibuffer");
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef ENABLE_NANORC
|
|
|
|
|
printf(" --enable-nanorc");
|
|
|
|
|
#endif
|
2000-11-24 23:45:14 +03:00
|
|
|
|
#ifdef USE_SLANG
|
|
|
|
|
printf(" --with-slang");
|
|
|
|
|
#endif
|
|
|
|
|
printf("\n");
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
|
|
|
|
|
2005-01-17 08:06:55 +03:00
|
|
|
|
int no_more_space(void)
|
|
|
|
|
{
|
|
|
|
|
return ISSET(MORE_SPACE) ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
2000-06-06 09:53:49 +04:00
|
|
|
|
int no_help(void)
|
|
|
|
|
{
|
2002-07-19 05:08:59 +04:00
|
|
|
|
return ISSET(NO_HELP) ? 2 : 0;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-07-02 18:31:03 +04:00
|
|
|
|
void nano_disabled_msg(void)
|
2000-12-01 21:46:01 +03:00
|
|
|
|
{
|
2002-07-19 05:08:59 +04:00
|
|
|
|
statusbar(_("Sorry, support for this function has been disabled"));
|
2000-12-01 21:46:01 +03:00
|
|
|
|
}
|
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2005-01-19 22:52:42 +03:00
|
|
|
|
void cancel_fork(int signal)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
2002-12-22 19:30:00 +03:00
|
|
|
|
if (kill(pid, SIGKILL) == -1)
|
|
|
|
|
nperror("kill");
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-08-06 02:10:22 +04:00
|
|
|
|
/* Return TRUE on success. */
|
|
|
|
|
bool open_pipe(const char *command)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
2002-09-07 00:35:28 +04:00
|
|
|
|
int fd[2];
|
|
|
|
|
FILE *f;
|
|
|
|
|
struct sigaction oldaction, newaction;
|
2005-06-14 06:24:25 +04:00
|
|
|
|
/* Original and temporary handlers for SIGINT. */
|
2004-08-06 02:10:22 +04:00
|
|
|
|
bool sig_failed = FALSE;
|
2005-06-14 06:24:25 +04:00
|
|
|
|
/* Did sigaction() fail without changing the signal handlers? */
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
/* Make our pipes. */
|
|
|
|
|
if (pipe(fd) == -1) {
|
|
|
|
|
statusbar(_("Could not pipe"));
|
2004-08-06 02:10:22 +04:00
|
|
|
|
return FALSE;
|
2000-12-02 02:49:48 +03:00
|
|
|
|
}
|
2001-10-14 23:05:10 +04:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
/* Fork a child. */
|
|
|
|
|
if ((pid = fork()) == 0) {
|
|
|
|
|
close(fd[0]);
|
|
|
|
|
dup2(fd[1], fileno(stdout));
|
|
|
|
|
dup2(fd[1], fileno(stderr));
|
2004-08-06 02:10:22 +04:00
|
|
|
|
|
2005-06-14 06:24:25 +04:00
|
|
|
|
/* If execl() returns at all, there was an error. */
|
2005-02-10 05:26:08 +03:00
|
|
|
|
execl("/bin/sh", "sh", "-c", command, NULL);
|
2002-09-07 00:35:28 +04:00
|
|
|
|
exit(0);
|
|
|
|
|
}
|
2001-10-14 23:05:10 +04:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
/* Else continue as parent. */
|
|
|
|
|
close(fd[1]);
|
|
|
|
|
|
|
|
|
|
if (pid == -1) {
|
|
|
|
|
close(fd[0]);
|
|
|
|
|
statusbar(_("Could not fork"));
|
2004-08-06 02:10:22 +04:00
|
|
|
|
return FALSE;
|
2001-10-14 23:05:10 +04:00
|
|
|
|
}
|
2002-07-19 05:08:59 +04:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
/* Before we start reading the forked command's output, we set
|
2005-06-14 06:24:25 +04:00
|
|
|
|
* things up so that Ctrl-C will cancel the new process. */
|
2004-05-18 05:20:36 +04:00
|
|
|
|
|
2004-05-19 20:04:27 +04:00
|
|
|
|
/* Enable interpretation of the special control keys so that we get
|
|
|
|
|
* SIGINT when Ctrl-C is pressed. */
|
2004-05-18 05:20:36 +04:00
|
|
|
|
enable_signals();
|
|
|
|
|
|
2002-11-04 19:05:42 +03:00
|
|
|
|
if (sigaction(SIGINT, NULL, &newaction) == -1) {
|
2004-08-06 02:10:22 +04:00
|
|
|
|
sig_failed = TRUE;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
nperror("sigaction");
|
2002-07-19 05:08:59 +04:00
|
|
|
|
} else {
|
2002-09-07 00:35:28 +04:00
|
|
|
|
newaction.sa_handler = cancel_fork;
|
2002-11-04 19:05:42 +03:00
|
|
|
|
if (sigaction(SIGINT, &newaction, &oldaction) == -1) {
|
2004-08-06 02:10:22 +04:00
|
|
|
|
sig_failed = TRUE;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
nperror("sigaction");
|
|
|
|
|
}
|
2002-07-19 05:08:59 +04:00
|
|
|
|
}
|
2002-09-07 00:35:28 +04:00
|
|
|
|
/* Note that now oldaction is the previous SIGINT signal handler,
|
|
|
|
|
* to be restored later. */
|
2001-10-14 23:05:10 +04:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
f = fdopen(fd[0], "rb");
|
2002-12-22 19:30:00 +03:00
|
|
|
|
if (f == NULL)
|
2004-08-06 02:10:22 +04:00
|
|
|
|
nperror("fdopen");
|
2004-08-08 01:27:37 +04:00
|
|
|
|
|
2004-09-06 01:40:31 +04:00
|
|
|
|
read_file(f, "stdin");
|
2005-03-22 05:50:24 +03:00
|
|
|
|
|
2004-08-05 19:16:19 +04:00
|
|
|
|
/* If multibuffer mode is on, we could be here in view mode. If so,
|
|
|
|
|
* don't set the modification flag. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
if (!ISSET(VIEW_MODE))
|
|
|
|
|
set_modified();
|
|
|
|
|
|
|
|
|
|
if (wait(NULL) == -1)
|
|
|
|
|
nperror("wait");
|
|
|
|
|
|
2004-08-06 02:10:22 +04:00
|
|
|
|
if (!sig_failed && sigaction(SIGINT, &oldaction, NULL) == -1)
|
2002-09-07 00:35:28 +04:00
|
|
|
|
nperror("sigaction");
|
|
|
|
|
|
2004-05-19 20:04:27 +04:00
|
|
|
|
/* Disable interpretation of the special control keys so that we can
|
|
|
|
|
* use Ctrl-C for other things. */
|
2004-05-18 05:20:36 +04:00
|
|
|
|
disable_signals();
|
|
|
|
|
|
2004-08-06 02:10:22 +04:00
|
|
|
|
return TRUE;
|
2002-05-12 23:52:15 +04:00
|
|
|
|
}
|
2004-03-05 22:54:58 +03:00
|
|
|
|
#endif /* !NANO_SMALL */
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2004-07-02 18:31:03 +04:00
|
|
|
|
void do_verbatim_input(void)
|
2003-11-28 22:47:42 +03:00
|
|
|
|
{
|
2005-01-12 06:25:57 +03:00
|
|
|
|
int *kbinput;
|
|
|
|
|
size_t kbinput_len, i;
|
|
|
|
|
char *output;
|
2003-11-28 22:47:42 +03:00
|
|
|
|
|
2005-06-14 06:24:25 +04:00
|
|
|
|
statusbar(_("Verbatim Input"));
|
2004-05-28 21:23:33 +04:00
|
|
|
|
|
2004-12-04 20:41:52 +03:00
|
|
|
|
/* Read in all the verbatim characters. */
|
|
|
|
|
kbinput = get_verbatim_kbinput(edit, &kbinput_len);
|
2003-11-28 22:47:42 +03:00
|
|
|
|
|
2005-03-17 06:52:08 +03:00
|
|
|
|
/* Display all the verbatim characters at once, not filtering out
|
|
|
|
|
* control characters. */
|
2005-01-12 06:25:57 +03:00
|
|
|
|
output = charalloc(kbinput_len + 1);
|
2003-11-28 22:47:42 +03:00
|
|
|
|
|
2005-01-12 06:25:57 +03:00
|
|
|
|
for (i = 0; i < kbinput_len; i++)
|
|
|
|
|
output[i] = (char)kbinput[i];
|
|
|
|
|
output[i] = '\0';
|
|
|
|
|
|
2005-03-17 06:52:08 +03:00
|
|
|
|
do_output(output, kbinput_len, TRUE);
|
2005-01-12 06:25:57 +03:00
|
|
|
|
|
|
|
|
|
free(output);
|
2003-11-28 22:47:42 +03:00
|
|
|
|
}
|
|
|
|
|
|
2004-07-02 18:31:03 +04:00
|
|
|
|
void do_backspace(void)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
2003-09-08 03:57:24 +04:00
|
|
|
|
if (current != fileage || current_x > 0) {
|
2004-05-29 00:44:09 +04:00
|
|
|
|
do_left(FALSE);
|
2003-09-08 03:57:24 +04:00
|
|
|
|
do_delete();
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-07-02 18:31:03 +04:00
|
|
|
|
void do_delete(void)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
2004-08-06 02:10:22 +04:00
|
|
|
|
bool do_refresh = FALSE;
|
2004-05-29 00:44:09 +04:00
|
|
|
|
/* Do we have to call edit_refresh(), or can we get away with
|
|
|
|
|
* update_line()? */
|
|
|
|
|
|
2005-03-04 20:09:41 +03:00
|
|
|
|
assert(current != NULL && current->data != NULL && current_x <= strlen(current->data));
|
2002-07-30 03:46:38 +04:00
|
|
|
|
|
2004-04-19 06:44:13 +04:00
|
|
|
|
placewewant = xplustabs();
|
2001-11-29 06:43:08 +03:00
|
|
|
|
|
2004-04-19 06:44:13 +04:00
|
|
|
|
if (current->data[current_x] != '\0') {
|
2005-02-11 23:09:11 +03:00
|
|
|
|
int char_buf_len = parse_mbchar(current->data + current_x, NULL,
|
|
|
|
|
NULL, NULL);
|
2004-12-23 20:43:27 +03:00
|
|
|
|
size_t line_len = strlen(current->data + current_x);
|
2001-11-29 06:43:08 +03:00
|
|
|
|
|
2004-04-19 06:44:13 +04:00
|
|
|
|
assert(current_x < strlen(current->data));
|
2002-07-20 17:57:41 +04:00
|
|
|
|
|
2004-04-19 06:44:13 +04:00
|
|
|
|
/* Let's get dangerous. */
|
2004-12-23 20:43:27 +03:00
|
|
|
|
charmove(¤t->data[current_x],
|
2005-01-12 06:25:57 +03:00
|
|
|
|
¤t->data[current_x + char_buf_len],
|
|
|
|
|
line_len - char_buf_len + 1);
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2005-01-12 06:25:57 +03:00
|
|
|
|
null_at(¤t->data, current_x + line_len - char_buf_len);
|
2004-04-19 06:44:13 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
if (current_x < mark_beginx && mark_beginbuf == current)
|
2005-01-12 06:25:57 +03:00
|
|
|
|
mark_beginx -= char_buf_len;
|
2002-07-30 03:46:38 +04:00
|
|
|
|
#endif
|
2005-01-27 23:49:07 +03:00
|
|
|
|
totsize--;
|
2004-04-19 06:44:13 +04:00
|
|
|
|
} else if (current != filebot && (current->next != filebot ||
|
|
|
|
|
current->data[0] == '\0')) {
|
2002-05-12 23:52:15 +04:00
|
|
|
|
/* We can delete the line before filebot only if it is blank: it
|
2004-05-24 09:05:07 +04:00
|
|
|
|
* becomes the new magicline then. */
|
2004-04-19 06:44:13 +04:00
|
|
|
|
filestruct *foo = current->next;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2004-04-19 06:44:13 +04:00
|
|
|
|
assert(current_x == strlen(current->data));
|
2004-05-29 00:44:09 +04:00
|
|
|
|
|
|
|
|
|
/* If we're deleting at the end of a line, we need to call
|
|
|
|
|
* edit_refresh(). */
|
|
|
|
|
if (current->data[current_x] == '\0')
|
|
|
|
|
do_refresh = TRUE;
|
|
|
|
|
|
2004-12-23 20:43:27 +03:00
|
|
|
|
current->data = charealloc(current->data,
|
|
|
|
|
current_x + strlen(foo->data) + 1);
|
2004-04-19 06:44:13 +04:00
|
|
|
|
strcpy(current->data + current_x, foo->data);
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
if (mark_beginbuf == current->next) {
|
|
|
|
|
mark_beginx += current_x;
|
|
|
|
|
mark_beginbuf = current;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2004-03-19 05:15:42 +03:00
|
|
|
|
if (filebot == foo)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
filebot = current;
|
|
|
|
|
|
|
|
|
|
unlink_node(foo);
|
|
|
|
|
delete_node(foo);
|
|
|
|
|
renumber(current);
|
|
|
|
|
totlines--;
|
2004-12-23 20:43:27 +03:00
|
|
|
|
totsize--;
|
2004-08-08 01:27:37 +04:00
|
|
|
|
#ifndef DISABLE_WRAPPING
|
2004-04-19 06:44:13 +04:00
|
|
|
|
wrap_reset();
|
2004-08-08 01:27:37 +04:00
|
|
|
|
#endif
|
2000-06-06 09:53:49 +04:00
|
|
|
|
} else
|
2004-07-02 18:31:03 +04:00
|
|
|
|
return;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
|
|
|
|
set_modified();
|
2004-05-29 00:44:09 +04:00
|
|
|
|
|
|
|
|
|
#ifdef ENABLE_COLOR
|
|
|
|
|
/* If color syntaxes are turned on, we need to call
|
|
|
|
|
* edit_refresh(). */
|
2005-03-10 23:55:11 +03:00
|
|
|
|
if (!ISSET(NO_COLOR_SYNTAX))
|
2004-05-29 00:44:09 +04:00
|
|
|
|
do_refresh = TRUE;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (do_refresh)
|
|
|
|
|
edit_refresh();
|
|
|
|
|
else
|
|
|
|
|
update_line(current, current_x);
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-07-02 18:31:03 +04:00
|
|
|
|
void do_tab(void)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
2005-06-16 03:20:56 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
if (ISSET(TABS_TO_SPACES)) {
|
|
|
|
|
char *output;
|
|
|
|
|
size_t output_len = 0, new_pww = placewewant;
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
new_pww++;
|
|
|
|
|
output_len++;
|
|
|
|
|
} while (new_pww % tabsize != 0);
|
|
|
|
|
|
|
|
|
|
output = charalloc(output_len + 1);
|
|
|
|
|
|
|
|
|
|
charset(output, ' ', output_len);
|
|
|
|
|
output[output_len] = '\0';
|
|
|
|
|
|
|
|
|
|
do_output(output, output_len, TRUE);
|
2005-06-16 05:36:10 +04:00
|
|
|
|
|
|
|
|
|
free(output);
|
2005-06-16 03:20:56 +04:00
|
|
|
|
} else {
|
|
|
|
|
#endif
|
|
|
|
|
do_output("\t", 1, TRUE);
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
|
|
|
|
|
2005-06-12 20:00:09 +04:00
|
|
|
|
/* Someone hits Return *gasp!* */
|
2004-07-02 18:31:03 +04:00
|
|
|
|
void do_enter(void)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
2004-05-28 00:09:52 +04:00
|
|
|
|
filestruct *newnode = make_new_node(current);
|
|
|
|
|
size_t extra = 0;
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
assert(current != NULL && current->data != NULL);
|
2002-01-21 23:32:22 +03:00
|
|
|
|
|
2002-06-13 04:40:19 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2002-09-07 00:35:28 +04:00
|
|
|
|
/* Do auto-indenting, like the neolithic Turbo Pascal editor. */
|
|
|
|
|
if (ISSET(AUTOINDENT)) {
|
2004-05-28 00:09:52 +04:00
|
|
|
|
/* If we are breaking the line in the indentation, the new
|
|
|
|
|
* indentation should have only current_x characters, and
|
|
|
|
|
* current_x should not change. */
|
|
|
|
|
extra = indent_length(current->data);
|
|
|
|
|
if (extra > current_x)
|
2002-09-07 00:35:28 +04:00
|
|
|
|
extra = current_x;
|
2004-05-28 00:09:52 +04:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
newnode->data = charalloc(strlen(current->data + current_x) +
|
|
|
|
|
extra + 1);
|
|
|
|
|
strcpy(&newnode->data[extra], current->data + current_x);
|
|
|
|
|
#ifndef NANO_SMALL
|
2005-03-04 20:09:41 +03:00
|
|
|
|
if (ISSET(AUTOINDENT)) {
|
2005-06-22 04:24:11 +04:00
|
|
|
|
strncpy(newnode->data, current->data, extra);
|
2005-03-04 20:09:41 +03:00
|
|
|
|
totsize += mbstrlen(newnode->data);
|
|
|
|
|
}
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#endif
|
2004-05-28 00:09:52 +04:00
|
|
|
|
null_at(¤t->data, current_x);
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
if (current == mark_beginbuf && current_x < mark_beginx) {
|
|
|
|
|
mark_beginbuf = newnode;
|
|
|
|
|
mark_beginx += extra - current_x;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
}
|
2004-05-28 00:09:52 +04:00
|
|
|
|
#endif
|
|
|
|
|
current_x = extra;
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2004-05-28 00:09:52 +04:00
|
|
|
|
if (current == filebot)
|
2002-09-07 00:35:28 +04:00
|
|
|
|
filebot = newnode;
|
|
|
|
|
splice_node(current, newnode, current->next);
|
2002-01-21 23:32:22 +03:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
renumber(current);
|
|
|
|
|
current = newnode;
|
2004-05-28 00:09:52 +04:00
|
|
|
|
|
|
|
|
|
edit_refresh();
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
totlines++;
|
2004-12-29 19:42:48 +03:00
|
|
|
|
totsize++;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
set_modified();
|
|
|
|
|
placewewant = xplustabs();
|
2000-11-05 19:52:21 +03:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2005-06-26 23:03:48 +04:00
|
|
|
|
/* Move to the next word in the current filestruct. If allow_punct is
|
|
|
|
|
* TRUE, treat punctuation as part of a word. If allow_update is TRUE,
|
|
|
|
|
* update the screen afterward. Return TRUE if we started on a word,
|
|
|
|
|
* and FALSE otherwise. */
|
|
|
|
|
bool do_next_word(bool allow_punct, bool allow_update)
|
2000-11-05 19:52:21 +03:00
|
|
|
|
{
|
2005-01-15 00:33:47 +03:00
|
|
|
|
size_t pww_save = placewewant;
|
|
|
|
|
const filestruct *current_save = current;
|
2005-01-31 21:59:30 +03:00
|
|
|
|
char *char_mb;
|
2005-01-15 00:59:01 +03:00
|
|
|
|
int char_mb_len;
|
2005-06-13 02:31:03 +04:00
|
|
|
|
bool started_on_word = FALSE;
|
2005-01-15 00:33:47 +03:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
assert(current != NULL && current->data != NULL);
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2005-01-31 21:59:30 +03:00
|
|
|
|
char_mb = charalloc(mb_cur_max());
|
|
|
|
|
|
2005-01-15 03:34:57 +03:00
|
|
|
|
/* Move forward until we find the character after the last letter of
|
|
|
|
|
* the current word. */
|
2005-01-15 00:33:47 +03:00
|
|
|
|
while (current->data[current_x] != '\0') {
|
2005-02-11 23:09:11 +03:00
|
|
|
|
char_mb_len = parse_mbchar(current->data + current_x, char_mb,
|
|
|
|
|
NULL, NULL);
|
2005-01-15 00:33:47 +03:00
|
|
|
|
|
2005-01-15 03:34:57 +03:00
|
|
|
|
/* If we've found it, stop moving forward through the current
|
|
|
|
|
* line. */
|
2005-06-26 23:03:48 +04:00
|
|
|
|
if (!is_word_mbchar(char_mb, allow_punct))
|
2005-01-15 00:33:47 +03:00
|
|
|
|
break;
|
2005-06-13 18:00:22 +04:00
|
|
|
|
|
2005-06-13 02:31:03 +04:00
|
|
|
|
/* If we haven't found it, then we've started on a word, so set
|
|
|
|
|
* started_on_word to TRUE. */
|
2005-06-13 18:00:22 +04:00
|
|
|
|
started_on_word = TRUE;
|
2005-01-15 00:33:47 +03:00
|
|
|
|
|
2005-01-15 00:59:01 +03:00
|
|
|
|
current_x += char_mb_len;
|
2005-01-15 00:33:47 +03:00
|
|
|
|
}
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2005-01-15 03:34:57 +03:00
|
|
|
|
/* Move forward until we find the first letter of the next word. */
|
2005-01-15 18:05:20 +03:00
|
|
|
|
if (current->data[current_x] != '\0')
|
|
|
|
|
current_x += char_mb_len;
|
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
for (; current != NULL; current = current->next) {
|
2005-01-15 00:33:47 +03:00
|
|
|
|
while (current->data[current_x] != '\0') {
|
2005-01-15 00:59:01 +03:00
|
|
|
|
char_mb_len = parse_mbchar(current->data + current_x,
|
2005-02-11 23:09:11 +03:00
|
|
|
|
char_mb, NULL, NULL);
|
2005-01-15 00:33:47 +03:00
|
|
|
|
|
2005-01-15 03:34:57 +03:00
|
|
|
|
/* If we've found it, stop moving forward through the
|
|
|
|
|
* current line. */
|
2005-06-26 23:03:48 +04:00
|
|
|
|
if (is_word_mbchar(char_mb, allow_punct))
|
2005-01-15 00:33:47 +03:00
|
|
|
|
break;
|
|
|
|
|
|
2005-01-15 00:59:01 +03:00
|
|
|
|
current_x += char_mb_len;
|
2005-01-15 00:33:47 +03:00
|
|
|
|
}
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2005-01-15 03:34:57 +03:00
|
|
|
|
/* If we've found it, stop moving forward to the beginnings of
|
|
|
|
|
* subsequent lines. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
if (current->data[current_x] != '\0')
|
|
|
|
|
break;
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
current_x = 0;
|
|
|
|
|
}
|
2005-01-15 00:33:47 +03:00
|
|
|
|
|
2005-01-15 01:08:18 +03:00
|
|
|
|
free(char_mb);
|
|
|
|
|
|
2005-01-15 03:34:57 +03:00
|
|
|
|
/* If we haven't found it, leave the cursor at the end of the
|
|
|
|
|
* file. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
if (current == NULL)
|
|
|
|
|
current = filebot;
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
placewewant = xplustabs();
|
2000-11-10 21:15:43 +03:00
|
|
|
|
|
2005-06-13 02:31:03 +04:00
|
|
|
|
/* If allow_update is TRUE, update the screen. */
|
|
|
|
|
if (allow_update)
|
|
|
|
|
edit_redraw(current_save, pww_save);
|
|
|
|
|
|
|
|
|
|
/* Return whether we started on a word. */
|
|
|
|
|
return started_on_word;
|
|
|
|
|
}
|
|
|
|
|
|
2005-06-26 23:03:48 +04:00
|
|
|
|
/* Move to the next word in the current filestruct, not counting
|
|
|
|
|
* punctuation as part of a word, and updating the screen afterward. */
|
2005-06-13 02:31:03 +04:00
|
|
|
|
void do_next_word_void(void)
|
|
|
|
|
{
|
2005-06-26 23:03:48 +04:00
|
|
|
|
do_next_word(FALSE, TRUE);
|
2002-09-07 00:35:28 +04:00
|
|
|
|
}
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2005-06-26 23:03:48 +04:00
|
|
|
|
/* Move to the previous word in the current filestruct. If allow_punct
|
|
|
|
|
* is TRUE, treat punctuation as part of a word. If allow_update is
|
|
|
|
|
* TRUE, update the screen afterward. Return TRUE if we started on a
|
|
|
|
|
* word, and FALSE otherwise. */
|
|
|
|
|
bool do_prev_word(bool allow_punct, bool allow_update)
|
2002-09-07 00:35:28 +04:00
|
|
|
|
{
|
2005-01-15 00:33:47 +03:00
|
|
|
|
size_t pww_save = placewewant;
|
|
|
|
|
const filestruct *current_save = current;
|
2005-01-31 21:59:30 +03:00
|
|
|
|
char *char_mb;
|
2005-01-15 03:34:57 +03:00
|
|
|
|
int char_mb_len;
|
2005-06-26 23:03:48 +04:00
|
|
|
|
bool begin_line = FALSE, started_on_word = FALSE;
|
2005-01-15 00:33:47 +03:00
|
|
|
|
|
2002-12-22 19:30:00 +03:00
|
|
|
|
assert(current != NULL && current->data != NULL);
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2005-01-31 21:59:30 +03:00
|
|
|
|
char_mb = charalloc(mb_cur_max());
|
|
|
|
|
|
2005-01-15 03:34:57 +03:00
|
|
|
|
/* Move backward until we find the character before the first letter
|
|
|
|
|
* of the current word. */
|
|
|
|
|
while (!begin_line) {
|
2005-02-11 23:09:11 +03:00
|
|
|
|
char_mb_len = parse_mbchar(current->data + current_x, char_mb,
|
|
|
|
|
NULL, NULL);
|
2004-10-30 05:03:15 +04:00
|
|
|
|
|
2005-01-15 03:34:57 +03:00
|
|
|
|
/* If we've found it, stop moving backward through the current
|
|
|
|
|
* line. */
|
2005-06-26 23:03:48 +04:00
|
|
|
|
if (!is_word_mbchar(char_mb, allow_punct))
|
2005-01-15 03:34:57 +03:00
|
|
|
|
break;
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2005-06-26 23:03:48 +04:00
|
|
|
|
/* If we haven't found it, then we've started on a word, so set
|
|
|
|
|
* started_on_word to TRUE. */
|
|
|
|
|
started_on_word = TRUE;
|
|
|
|
|
|
2005-01-15 03:34:57 +03:00
|
|
|
|
if (current_x == 0)
|
|
|
|
|
begin_line = TRUE;
|
|
|
|
|
else
|
|
|
|
|
current_x = move_mbleft(current->data, current_x);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Move backward until we find the last letter of the previous
|
|
|
|
|
* word. */
|
2005-01-15 18:05:20 +03:00
|
|
|
|
if (current_x == 0)
|
|
|
|
|
begin_line = TRUE;
|
|
|
|
|
else
|
|
|
|
|
current_x = move_mbleft(current->data, current_x);
|
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
for (; current != NULL; current = current->prev) {
|
2005-01-15 03:34:57 +03:00
|
|
|
|
while (!begin_line) {
|
|
|
|
|
char_mb_len = parse_mbchar(current->data + current_x,
|
2005-02-11 23:09:11 +03:00
|
|
|
|
char_mb, NULL, NULL);
|
2005-01-15 03:34:57 +03:00
|
|
|
|
|
|
|
|
|
/* If we've found it, stop moving backward through the
|
|
|
|
|
* current line. */
|
2005-06-26 23:03:48 +04:00
|
|
|
|
if (is_word_mbchar(char_mb, allow_punct))
|
2005-01-15 03:34:57 +03:00
|
|
|
|
break;
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2005-01-15 03:34:57 +03:00
|
|
|
|
if (current_x == 0)
|
|
|
|
|
begin_line = TRUE;
|
|
|
|
|
else
|
|
|
|
|
current_x = move_mbleft(current->data, current_x);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If we've found it, stop moving backward to the ends of
|
|
|
|
|
* previous lines. */
|
|
|
|
|
if (!begin_line)
|
2002-09-07 00:35:28 +04:00
|
|
|
|
break;
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2005-01-15 03:34:57 +03:00
|
|
|
|
if (current->prev != NULL) {
|
|
|
|
|
begin_line = FALSE;
|
|
|
|
|
current_x = strlen(current->prev->data);
|
|
|
|
|
}
|
2000-11-05 19:52:21 +03:00
|
|
|
|
}
|
|
|
|
|
|
2005-01-15 03:34:57 +03:00
|
|
|
|
/* If we haven't found it, leave the cursor at the beginning of the
|
|
|
|
|
* file. */
|
2004-05-24 06:35:02 +04:00
|
|
|
|
if (current == NULL) {
|
2002-09-07 00:35:28 +04:00
|
|
|
|
current = fileage;
|
|
|
|
|
current_x = 0;
|
2005-01-15 03:34:57 +03:00
|
|
|
|
/* If we've found it, move backward until we find the character
|
|
|
|
|
* before the first letter of the previous word. */
|
|
|
|
|
} else if (!begin_line) {
|
|
|
|
|
if (current_x == 0)
|
|
|
|
|
begin_line = TRUE;
|
|
|
|
|
else
|
|
|
|
|
current_x = move_mbleft(current->data, current_x);
|
|
|
|
|
|
|
|
|
|
while (!begin_line) {
|
|
|
|
|
char_mb_len = parse_mbchar(current->data + current_x,
|
2005-02-11 23:09:11 +03:00
|
|
|
|
char_mb, NULL, NULL);
|
2005-01-15 03:34:57 +03:00
|
|
|
|
|
|
|
|
|
/* If we've found it, stop moving backward through the
|
|
|
|
|
* current line. */
|
2005-06-26 23:03:48 +04:00
|
|
|
|
if (!is_word_mbchar(char_mb, allow_punct))
|
2005-01-15 03:34:57 +03:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (current_x == 0)
|
|
|
|
|
begin_line = TRUE;
|
|
|
|
|
else
|
|
|
|
|
current_x = move_mbleft(current->data, current_x);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If we've found it, move forward to the first letter of the
|
|
|
|
|
* previous word. */
|
|
|
|
|
if (!begin_line)
|
|
|
|
|
current_x += char_mb_len;
|
2002-03-25 06:26:27 +03:00
|
|
|
|
}
|
2000-11-10 21:15:43 +03:00
|
|
|
|
|
2005-01-15 03:34:57 +03:00
|
|
|
|
free(char_mb);
|
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
placewewant = xplustabs();
|
2000-11-10 21:15:43 +03:00
|
|
|
|
|
2005-06-26 23:03:48 +04:00
|
|
|
|
/* If allow_update is TRUE, update the screen. */
|
|
|
|
|
if (allow_update)
|
|
|
|
|
edit_redraw(current_save, pww_save);
|
|
|
|
|
|
|
|
|
|
/* Return whether we started on a word. */
|
|
|
|
|
return started_on_word;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Move to the previous word in the current filestruct, not counting
|
|
|
|
|
* punctuation as part of a word, and updating the screen afterward. */
|
|
|
|
|
void do_prev_word_void(void)
|
|
|
|
|
{
|
|
|
|
|
do_prev_word(FALSE, TRUE);
|
2002-09-07 00:35:28 +04:00
|
|
|
|
}
|
2000-11-10 21:15:43 +03:00
|
|
|
|
|
2005-06-13 02:31:03 +04:00
|
|
|
|
void do_word_count(void)
|
|
|
|
|
{
|
|
|
|
|
size_t words = 0;
|
|
|
|
|
size_t current_x_save = current_x, pww_save = placewewant;
|
|
|
|
|
filestruct *current_save = current;
|
2005-06-13 03:20:20 +04:00
|
|
|
|
bool old_mark_set = ISSET(MARK_ISSET);
|
|
|
|
|
bool added_magicline = FALSE;
|
|
|
|
|
/* Whether we added a magicline after filebot. */
|
|
|
|
|
filestruct *top, *bot;
|
|
|
|
|
size_t top_x, bot_x;
|
|
|
|
|
|
|
|
|
|
if (old_mark_set) {
|
|
|
|
|
/* If the mark is on, partition the filestruct so that it
|
|
|
|
|
* contains only the marked text, keep track of whether the text
|
|
|
|
|
* will need a magicline added while we're counting words, add
|
|
|
|
|
* the magicline if necessary, and turn the mark off. */
|
|
|
|
|
mark_order((const filestruct **)&top, &top_x,
|
|
|
|
|
(const filestruct **)&bot, &bot_x, NULL);
|
|
|
|
|
filepart = partition_filestruct(top, top_x, bot, bot_x);
|
|
|
|
|
if ((added_magicline = (filebot->data[0] != '\0')))
|
|
|
|
|
new_magicline();
|
|
|
|
|
UNSET(MARK_ISSET);
|
|
|
|
|
}
|
2005-06-13 02:31:03 +04:00
|
|
|
|
|
2005-06-13 03:20:20 +04:00
|
|
|
|
/* Start at the top of the file. */
|
2005-06-13 02:31:03 +04:00
|
|
|
|
current = fileage;
|
|
|
|
|
current_x = 0;
|
|
|
|
|
placewewant = 0;
|
|
|
|
|
|
2005-06-26 23:03:48 +04:00
|
|
|
|
/* Keep moving to the next word (counting punctuation characters as
|
|
|
|
|
* part of a word so that we match the output of "wc -w"), without
|
|
|
|
|
* updating the screen, until we reach the end of the file,
|
|
|
|
|
* incrementing the total word count whenever we're on a word just
|
|
|
|
|
* before moving. */
|
2005-06-13 02:31:03 +04:00
|
|
|
|
while (current != filebot || current_x != 0) {
|
2005-06-26 23:03:48 +04:00
|
|
|
|
if (do_next_word(TRUE, FALSE))
|
2005-06-13 02:31:03 +04:00
|
|
|
|
words++;
|
|
|
|
|
}
|
|
|
|
|
|
2005-06-13 03:20:20 +04:00
|
|
|
|
if (old_mark_set) {
|
|
|
|
|
/* If the mark was on and we added a magicline, remove it
|
|
|
|
|
* now. */
|
|
|
|
|
if (added_magicline)
|
|
|
|
|
remove_magicline();
|
|
|
|
|
|
|
|
|
|
/* Unpartition the filestruct so that it contains all the text
|
|
|
|
|
* again, and turn the mark back on. */
|
|
|
|
|
unpartition_filestruct(&filepart);
|
|
|
|
|
SET(MARK_ISSET);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Restore where we were. */
|
2005-06-13 02:31:03 +04:00
|
|
|
|
current = current_save;
|
|
|
|
|
current_x = current_x_save;
|
|
|
|
|
placewewant = pww_save;
|
|
|
|
|
|
|
|
|
|
/* Display the total word count on the statusbar. */
|
2005-06-13 03:20:20 +04:00
|
|
|
|
statusbar("%s: %lu", old_mark_set ? _("Word Count in Selection") :
|
|
|
|
|
_("Word Count"), (unsigned long)words);
|
2005-06-13 02:31:03 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-07-02 18:31:03 +04:00
|
|
|
|
void do_mark(void)
|
2002-09-07 00:35:28 +04:00
|
|
|
|
{
|
2003-09-29 01:26:49 +04:00
|
|
|
|
TOGGLE(MARK_ISSET);
|
|
|
|
|
if (ISSET(MARK_ISSET)) {
|
2002-09-07 00:35:28 +04:00
|
|
|
|
statusbar(_("Mark Set"));
|
|
|
|
|
mark_beginbuf = current;
|
|
|
|
|
mark_beginx = current_x;
|
|
|
|
|
} else {
|
|
|
|
|
statusbar(_("Mark UNset"));
|
|
|
|
|
edit_refresh();
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-04-30 08:49:02 +04:00
|
|
|
|
#endif /* !NANO_SMALL */
|
2000-11-10 21:15:43 +03:00
|
|
|
|
|
2003-09-11 00:08:00 +04:00
|
|
|
|
#ifndef DISABLE_WRAPPING
|
2002-09-07 00:35:28 +04:00
|
|
|
|
void wrap_reset(void)
|
|
|
|
|
{
|
2004-06-22 19:38:47 +04:00
|
|
|
|
same_line_wrap = FALSE;
|
2000-11-05 19:52:21 +03:00
|
|
|
|
}
|
2003-09-11 00:08:00 +04:00
|
|
|
|
#endif
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#ifndef DISABLE_WRAPPING
|
2004-05-31 18:58:59 +04:00
|
|
|
|
/* We wrap the given line. Precondition: we assume the cursor has been
|
|
|
|
|
* moved forward since the last typed character. Return value: whether
|
|
|
|
|
* we wrapped. */
|
2005-03-20 00:15:30 +03:00
|
|
|
|
bool do_wrap(filestruct *line)
|
2000-11-05 19:52:21 +03:00
|
|
|
|
{
|
2005-03-20 06:10:31 +03:00
|
|
|
|
size_t line_len;
|
2004-05-31 18:58:59 +04:00
|
|
|
|
/* Length of the line we wrap. */
|
2005-03-20 06:10:31 +03:00
|
|
|
|
ssize_t wrap_loc;
|
2005-03-20 00:15:30 +03:00
|
|
|
|
/* Index of line->data where we wrap. */
|
2002-06-13 04:40:19 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2005-03-20 00:15:30 +03:00
|
|
|
|
const char *indent_string = NULL;
|
2004-05-31 18:58:59 +04:00
|
|
|
|
/* Indentation to prepend to the new line. */
|
2005-03-20 00:15:30 +03:00
|
|
|
|
size_t indent_len = 0; /* The length of indent_string. */
|
2002-06-13 04:40:19 +04:00
|
|
|
|
#endif
|
2005-03-20 00:15:30 +03:00
|
|
|
|
const char *after_break; /* The text after the wrap point. */
|
|
|
|
|
size_t after_break_len; /* The length of after_break. */
|
2004-08-06 02:10:22 +04:00
|
|
|
|
bool wrapping = FALSE; /* Do we prepend to the next line? */
|
2005-03-20 00:15:30 +03:00
|
|
|
|
const char *next_line = NULL;
|
2004-07-17 23:49:12 +04:00
|
|
|
|
/* The next line, minus indentation. */
|
2005-03-20 00:15:30 +03:00
|
|
|
|
size_t next_line_len = 0; /* The length of next_line. */
|
|
|
|
|
char *new_line = NULL; /* The line we create. */
|
|
|
|
|
size_t new_line_len = 0; /* The eventual length of new_line. */
|
|
|
|
|
|
|
|
|
|
/* There are three steps. First, we decide where to wrap. Then, we
|
|
|
|
|
* create the new wrap line. Finally, we clean up. */
|
|
|
|
|
|
|
|
|
|
/* Step 1, finding where to wrap. We are going to add a new line
|
|
|
|
|
* after a blank character. In this step, we call break_line() to
|
|
|
|
|
* get the location of the last blank we can break the line at, and
|
|
|
|
|
* and set wrap_loc to the location of the character after it, so
|
|
|
|
|
* that the blank is preserved at the end of the line.
|
|
|
|
|
*
|
|
|
|
|
* If there is no legal wrap point, or we reach the last character
|
|
|
|
|
* of the line while trying to find one, we should return without
|
|
|
|
|
* wrapping. Note that if autoindent is turned on, we don't break
|
|
|
|
|
* at the end of it! */
|
2002-06-13 04:40:19 +04:00
|
|
|
|
|
2005-03-20 06:10:31 +03:00
|
|
|
|
assert(line != NULL && line->data != NULL);
|
|
|
|
|
|
|
|
|
|
/* Save the length of the line. */
|
|
|
|
|
line_len = strlen(line->data);
|
|
|
|
|
|
2005-03-20 00:15:30 +03:00
|
|
|
|
/* Find the last blank where we can break the line. */
|
|
|
|
|
wrap_loc = break_line(line->data, fill, FALSE);
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2005-03-20 00:15:30 +03:00
|
|
|
|
/* If we couldn't break the line, or we've reached the end of it, we
|
|
|
|
|
* don't wrap. */
|
|
|
|
|
if (wrap_loc == -1 || line->data[wrap_loc] == '\0')
|
2004-05-31 18:58:59 +04:00
|
|
|
|
return FALSE;
|
2000-11-10 21:15:43 +03:00
|
|
|
|
|
2005-03-20 00:15:30 +03:00
|
|
|
|
/* Otherwise, move forward to the character just after the blank. */
|
|
|
|
|
wrap_loc += move_mbright(line->data + wrap_loc, 0);
|
|
|
|
|
|
|
|
|
|
/* If we've reached the end of the line, we don't wrap. */
|
|
|
|
|
if (line->data[wrap_loc] == '\0')
|
|
|
|
|
return FALSE;
|
2000-11-10 21:15:43 +03:00
|
|
|
|
|
2005-03-20 00:15:30 +03:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
/* If autoindent is turned on, and we're on the character just after
|
|
|
|
|
* the indentation, we don't wrap. */
|
|
|
|
|
if (ISSET(AUTOINDENT)) {
|
|
|
|
|
/* Get the indentation of this line. */
|
|
|
|
|
indent_string = line->data;
|
|
|
|
|
indent_len = indent_length(indent_string);
|
2004-12-20 04:13:55 +03:00
|
|
|
|
|
2005-03-20 00:15:30 +03:00
|
|
|
|
if (wrap_loc == indent_len)
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2005-03-20 00:15:30 +03:00
|
|
|
|
/* Step 2, making the new wrap line. It will consist of indentation
|
|
|
|
|
* followed by the text after the wrap point, optionally followed by
|
|
|
|
|
* a space (if the text after the wrap point doesn't end in a blank)
|
|
|
|
|
* and the text of the next line, if they can fit without
|
|
|
|
|
* wrapping, the next line exists, and the same_line_wrap flag is
|
|
|
|
|
* set. */
|
|
|
|
|
|
|
|
|
|
/* after_break is the text that will be wrapped to the next line. */
|
|
|
|
|
after_break = line->data + wrap_loc;
|
|
|
|
|
after_break_len = line_len - wrap_loc;
|
|
|
|
|
|
|
|
|
|
assert(strlen(after_break) == after_break_len);
|
|
|
|
|
|
|
|
|
|
/* We prepend the wrapped text to the next line, if the
|
|
|
|
|
* same_line_wrap flag is set, there is a next line, and prepending
|
|
|
|
|
* would not make the line too long. */
|
|
|
|
|
if (same_line_wrap && line->next != NULL) {
|
|
|
|
|
const char *end = after_break + move_mbleft(after_break,
|
|
|
|
|
after_break_len);
|
|
|
|
|
|
|
|
|
|
/* If after_break doesn't end in a blank, make sure it ends in a
|
|
|
|
|
* space. */
|
|
|
|
|
if (!is_blank_mbchar(end)) {
|
|
|
|
|
line_len++;
|
|
|
|
|
line->data = charealloc(line->data, line_len + 1);
|
|
|
|
|
line->data[line_len - 1] = ' ';
|
|
|
|
|
line->data[line_len] = '\0';
|
|
|
|
|
after_break = line->data + wrap_loc;
|
|
|
|
|
after_break_len++;
|
|
|
|
|
totsize++;
|
|
|
|
|
}
|
2000-11-10 21:15:43 +03:00
|
|
|
|
|
2005-03-20 00:15:30 +03:00
|
|
|
|
next_line = line->next->data;
|
|
|
|
|
next_line_len = strlen(next_line);
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2005-06-15 11:18:30 +04:00
|
|
|
|
if (after_break_len + next_line_len <= fill) {
|
2004-05-31 18:58:59 +04:00
|
|
|
|
wrapping = TRUE;
|
2005-03-20 00:15:30 +03:00
|
|
|
|
new_line_len += next_line_len;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
2001-04-20 05:59:55 +04:00
|
|
|
|
|
2005-03-20 00:15:30 +03:00
|
|
|
|
/* new_line_len is now the length of the text that will be wrapped
|
|
|
|
|
* to the next line, plus (if we're prepending to it) the length of
|
|
|
|
|
* the text of the next line. */
|
|
|
|
|
new_line_len += after_break_len;
|
|
|
|
|
|
2002-06-13 04:40:19 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2002-09-07 00:35:28 +04:00
|
|
|
|
if (ISSET(AUTOINDENT)) {
|
2005-03-20 00:15:30 +03:00
|
|
|
|
if (wrapping) {
|
|
|
|
|
/* If we're wrapping, the indentation will come from the
|
|
|
|
|
* next line. */
|
|
|
|
|
indent_string = next_line;
|
|
|
|
|
indent_len = indent_length(indent_string);
|
|
|
|
|
next_line += indent_len;
|
|
|
|
|
} else {
|
|
|
|
|
/* Otherwise, it will come from this line, in which case
|
|
|
|
|
* we should increase new_line_len to make room for it. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
new_line_len += indent_len;
|
2005-03-20 00:15:30 +03:00
|
|
|
|
totsize += mbstrnlen(indent_string, indent_len);
|
|
|
|
|
}
|
2002-08-21 20:10:37 +04:00
|
|
|
|
}
|
2002-06-13 04:40:19 +04:00
|
|
|
|
#endif
|
|
|
|
|
|
2005-03-20 00:15:30 +03:00
|
|
|
|
/* Now we allocate the new line and copy the text into it. */
|
|
|
|
|
new_line = charalloc(new_line_len + 1);
|
|
|
|
|
new_line[0] = '\0';
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
if (ISSET(AUTOINDENT)) {
|
2005-03-20 00:15:30 +03:00
|
|
|
|
/* Copy the indentation. */
|
2005-06-22 04:24:11 +04:00
|
|
|
|
strncpy(new_line, indent_string, indent_len);
|
2005-03-20 00:15:30 +03:00
|
|
|
|
new_line[indent_len] = '\0';
|
|
|
|
|
new_line_len += indent_len;
|
2000-12-02 07:36:50 +03:00
|
|
|
|
}
|
2001-09-19 07:19:43 +04:00
|
|
|
|
#endif
|
2004-12-20 04:13:55 +03:00
|
|
|
|
|
2005-03-20 00:15:30 +03:00
|
|
|
|
/* Copy all the text after the wrap point of the current line. */
|
|
|
|
|
strcat(new_line, after_break);
|
|
|
|
|
|
|
|
|
|
/* Break the current line at the wrap point. */
|
|
|
|
|
null_at(&line->data, wrap_loc);
|
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
if (wrapping) {
|
2005-03-20 00:15:30 +03:00
|
|
|
|
/* If we're wrapping, copy the text from the next line, minus
|
|
|
|
|
* the indentation that we already copied above. */
|
|
|
|
|
strcat(new_line, next_line);
|
|
|
|
|
|
|
|
|
|
free(line->next->data);
|
|
|
|
|
line->next->data = new_line;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
} else {
|
2005-03-20 00:15:30 +03:00
|
|
|
|
/* Otherwise, make a new line and copy the text after where we
|
|
|
|
|
* broke this line to the beginning of the new line. */
|
|
|
|
|
splice_node(current, make_new_node(current), current->next);
|
|
|
|
|
|
|
|
|
|
current->next->data = new_line;
|
2001-09-19 07:19:43 +04:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
totlines++;
|
2005-03-20 00:15:30 +03:00
|
|
|
|
totsize++;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
}
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2005-03-20 00:15:30 +03:00
|
|
|
|
/* Step 3, clean up. Reposition the cursor and mark, and do some
|
|
|
|
|
* other sundry things. */
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2005-03-20 00:15:30 +03:00
|
|
|
|
/* Set the same_line_wrap flag, so that later wraps of this line
|
|
|
|
|
* will be prepended to the next line. */
|
2004-06-22 19:38:47 +04:00
|
|
|
|
same_line_wrap = TRUE;
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
/* Each line knows its line number. We recalculate these if we
|
|
|
|
|
* inserted a new line. */
|
|
|
|
|
if (!wrapping)
|
2005-03-20 00:15:30 +03:00
|
|
|
|
renumber(line);
|
2000-11-05 19:52:21 +03:00
|
|
|
|
|
2005-03-20 00:15:30 +03:00
|
|
|
|
/* If the cursor was after the break point, we must move it. We
|
|
|
|
|
* also clear the same_line_wrap flag in this case. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
if (current_x > wrap_loc) {
|
2005-03-20 00:15:30 +03:00
|
|
|
|
same_line_wrap = FALSE;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
current = current->next;
|
2005-06-15 23:26:48 +04:00
|
|
|
|
current_x -= wrap_loc
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2005-06-15 23:26:48 +04:00
|
|
|
|
- indent_len
|
2000-07-03 07:10:14 +04:00
|
|
|
|
#endif
|
2005-06-15 23:26:48 +04:00
|
|
|
|
;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
placewewant = xplustabs();
|
|
|
|
|
}
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2002-03-29 19:31:29 +03:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-07-17 23:49:12 +04:00
|
|
|
|
/* If the mark was on this line after the wrap point, we move it
|
2005-03-20 00:15:30 +03:00
|
|
|
|
* down. If it was on the next line and we wrapped onto that line,
|
|
|
|
|
* we move it right. */
|
|
|
|
|
if (mark_beginbuf == line && mark_beginx > wrap_loc) {
|
|
|
|
|
mark_beginbuf = line->next;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
mark_beginx -= wrap_loc - indent_len + 1;
|
2005-03-20 00:15:30 +03:00
|
|
|
|
} else if (wrapping && mark_beginbuf == line->next)
|
2002-09-07 00:35:28 +04:00
|
|
|
|
mark_beginx += after_break_len;
|
2005-03-20 00:15:30 +03:00
|
|
|
|
#endif
|
2002-03-29 19:31:29 +03:00
|
|
|
|
|
2004-05-31 18:58:59 +04:00
|
|
|
|
return TRUE;
|
2002-03-29 19:31:29 +03:00
|
|
|
|
}
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#endif /* !DISABLE_WRAPPING */
|
2002-03-29 19:31:29 +03:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#ifndef DISABLE_SPELLER
|
2003-08-31 20:44:10 +04:00
|
|
|
|
/* A word is misspelled in the file. Let the user replace it. We
|
2004-08-06 02:10:22 +04:00
|
|
|
|
* return FALSE if the user cancels. */
|
|
|
|
|
bool do_int_spell_fix(const char *word)
|
2002-03-29 19:31:29 +03:00
|
|
|
|
{
|
2004-10-27 01:14:56 +04:00
|
|
|
|
char *save_search, *save_replace;
|
2005-06-15 23:21:04 +04:00
|
|
|
|
size_t match_len;
|
2004-10-21 20:25:44 +04:00
|
|
|
|
size_t current_x_save = current_x, pww_save = placewewant;
|
2004-10-27 01:14:56 +04:00
|
|
|
|
filestruct *edittop_save = edittop, *current_save = current;
|
2003-01-26 22:57:44 +03:00
|
|
|
|
/* Save where we are. */
|
2004-10-27 00:58:30 +04:00
|
|
|
|
bool canceled = FALSE;
|
2003-01-26 22:57:44 +03:00
|
|
|
|
/* The return value. */
|
2004-08-06 02:10:22 +04:00
|
|
|
|
bool case_sens_set = ISSET(CASE_SENSITIVE);
|
2004-10-11 17:55:33 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2005-06-16 22:48:30 +04:00
|
|
|
|
bool backwards_search_set = ISSET(BACKWARDS_SEARCH);
|
2004-10-09 20:59:43 +04:00
|
|
|
|
#endif
|
2004-10-09 21:15:46 +04:00
|
|
|
|
#ifdef HAVE_REGEX_H
|
2004-10-09 20:59:43 +04:00
|
|
|
|
bool regexp_set = ISSET(USE_REGEXP);
|
|
|
|
|
#endif
|
2004-10-15 20:35:34 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
bool old_mark_set = ISSET(MARK_ISSET);
|
2004-11-06 03:18:27 +03:00
|
|
|
|
bool added_magicline = FALSE;
|
|
|
|
|
/* Whether we added a magicline after filebot. */
|
2004-11-06 02:03:03 +03:00
|
|
|
|
bool right_side_up = FALSE;
|
|
|
|
|
/* TRUE if (mark_beginbuf, mark_beginx) is the top of the mark,
|
|
|
|
|
* FALSE if (current, current_x) is. */
|
2004-11-04 01:03:41 +03:00
|
|
|
|
filestruct *top, *bot;
|
2004-11-06 02:55:58 +03:00
|
|
|
|
size_t top_x, bot_x;
|
2004-10-15 20:35:34 +04:00
|
|
|
|
#endif
|
2002-03-29 19:31:29 +03:00
|
|
|
|
|
2004-10-09 20:59:43 +04:00
|
|
|
|
/* Make sure spell-check is case sensitive. */
|
2002-12-10 03:53:21 +03:00
|
|
|
|
SET(CASE_SENSITIVE);
|
2004-10-09 20:59:43 +04:00
|
|
|
|
|
2004-10-11 17:55:33 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-10-09 20:59:43 +04:00
|
|
|
|
/* Make sure spell-check goes forward only. */
|
2005-06-16 22:48:30 +04:00
|
|
|
|
UNSET(BACKWARDS_SEARCH);
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#endif
|
2004-10-09 21:15:46 +04:00
|
|
|
|
#ifdef HAVE_REGEX_H
|
2004-10-09 20:59:43 +04:00
|
|
|
|
/* Make sure spell-check doesn't use regular expressions. */
|
|
|
|
|
UNSET(USE_REGEXP);
|
|
|
|
|
#endif
|
2002-03-29 19:31:29 +03:00
|
|
|
|
|
2004-02-24 23:41:39 +03:00
|
|
|
|
/* Save the current search/replace strings. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
search_init_globals();
|
|
|
|
|
save_search = last_search;
|
|
|
|
|
save_replace = last_replace;
|
2002-03-29 19:31:29 +03:00
|
|
|
|
|
2004-11-17 23:47:14 +03:00
|
|
|
|
/* Set the search/replace strings to the misspelled word. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
last_search = mallocstrcpy(NULL, word);
|
|
|
|
|
last_replace = mallocstrcpy(NULL, word);
|
2002-03-29 19:31:29 +03:00
|
|
|
|
|
2004-11-04 01:03:41 +03:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
if (old_mark_set) {
|
2004-11-04 19:45:48 +03:00
|
|
|
|
/* If the mark is on, partition the filestruct so that it
|
2004-11-06 03:18:27 +03:00
|
|
|
|
* contains only the marked text, keep track of whether the text
|
|
|
|
|
* will have a magicline added when we're done correcting
|
|
|
|
|
* misspelled words, and turn the mark off. */
|
2004-11-04 01:03:41 +03:00
|
|
|
|
mark_order((const filestruct **)&top, &top_x,
|
2004-11-06 02:03:03 +03:00
|
|
|
|
(const filestruct **)&bot, &bot_x, &right_side_up);
|
2004-11-04 01:03:41 +03:00
|
|
|
|
filepart = partition_filestruct(top, top_x, bot, bot_x);
|
2004-11-06 03:18:27 +03:00
|
|
|
|
added_magicline = (filebot->data[0] != '\0');
|
2004-11-04 01:03:41 +03:00
|
|
|
|
UNSET(MARK_ISSET);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-02-24 23:41:39 +03:00
|
|
|
|
/* Start from the top of the file. */
|
2004-10-18 06:06:53 +04:00
|
|
|
|
edittop = fileage;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
current = fileage;
|
2004-10-30 05:03:15 +04:00
|
|
|
|
current_x = (size_t)-1;
|
2004-10-21 20:25:44 +04:00
|
|
|
|
placewewant = 0;
|
2002-03-29 19:31:29 +03:00
|
|
|
|
|
2004-02-24 23:41:39 +03:00
|
|
|
|
/* Find the first whole-word occurrence of word. */
|
2004-10-31 16:20:30 +03:00
|
|
|
|
findnextstr_wrap_reset();
|
2005-06-15 23:21:04 +04:00
|
|
|
|
while (findnextstr(TRUE, TRUE, FALSE, fileage, 0, word,
|
|
|
|
|
&match_len)) {
|
2003-01-26 22:57:44 +03:00
|
|
|
|
if (is_whole_word(current_x, current->data, word)) {
|
2005-06-15 23:21:04 +04:00
|
|
|
|
size_t xpt = xplustabs();
|
|
|
|
|
char *exp_word = display_string(current->data, xpt,
|
|
|
|
|
strnlenpt(current->data, current_x + match_len) - xpt,
|
|
|
|
|
FALSE);
|
|
|
|
|
|
2003-01-26 22:57:44 +03:00
|
|
|
|
edit_refresh();
|
2002-03-29 19:31:29 +03:00
|
|
|
|
|
2005-06-15 23:21:04 +04:00
|
|
|
|
do_replace_highlight(TRUE, exp_word);
|
2002-03-29 19:31:29 +03:00
|
|
|
|
|
2004-10-15 20:25:56 +04:00
|
|
|
|
/* Allow all instances of the word to be corrected. */
|
2004-10-27 00:58:30 +04:00
|
|
|
|
canceled = (statusq(FALSE, spell_list, word,
|
2003-01-13 04:35:15 +03:00
|
|
|
|
#ifndef NANO_SMALL
|
2003-01-26 22:57:44 +03:00
|
|
|
|
NULL,
|
2003-01-13 04:35:15 +03:00
|
|
|
|
#endif
|
2004-10-27 00:58:30 +04:00
|
|
|
|
_("Edit a replacement")) == -1);
|
2002-03-29 19:31:29 +03:00
|
|
|
|
|
2005-06-15 23:21:04 +04:00
|
|
|
|
do_replace_highlight(FALSE, exp_word);
|
|
|
|
|
|
|
|
|
|
free(exp_word);
|
2002-03-29 19:31:29 +03:00
|
|
|
|
|
2004-10-27 00:58:30 +04:00
|
|
|
|
if (!canceled && strcmp(word, answer) != 0) {
|
2003-01-26 22:57:44 +03:00
|
|
|
|
current_x--;
|
2004-10-27 00:58:30 +04:00
|
|
|
|
do_replace_loop(word, current, ¤t_x, TRUE,
|
|
|
|
|
&canceled);
|
2002-09-07 00:35:28 +04:00
|
|
|
|
}
|
2003-01-26 22:57:44 +03:00
|
|
|
|
|
|
|
|
|
break;
|
2001-07-11 06:08:33 +04:00
|
|
|
|
}
|
2004-10-19 02:19:22 +04:00
|
|
|
|
}
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2004-11-06 02:55:58 +03:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
if (old_mark_set) {
|
2004-11-15 21:44:30 +03:00
|
|
|
|
/* If the mark was on and we added a magicline, remove it
|
|
|
|
|
* now. */
|
2004-11-06 03:18:27 +03:00
|
|
|
|
if (added_magicline)
|
|
|
|
|
remove_magicline();
|
2004-11-06 02:55:58 +03:00
|
|
|
|
|
2004-11-06 05:37:25 +03:00
|
|
|
|
/* Put the beginning and the end of the mark at the beginning
|
|
|
|
|
* and the end of the spell-checked text. */
|
|
|
|
|
if (fileage == filebot)
|
2004-11-17 23:47:14 +03:00
|
|
|
|
bot_x += top_x;
|
2004-11-06 05:37:25 +03:00
|
|
|
|
if (right_side_up) {
|
2004-11-17 23:47:14 +03:00
|
|
|
|
mark_beginx = top_x;
|
|
|
|
|
current_x_save = bot_x;
|
2004-11-06 05:37:25 +03:00
|
|
|
|
} else {
|
2004-11-17 23:47:14 +03:00
|
|
|
|
current_x_save = top_x;
|
|
|
|
|
mark_beginx = bot_x;
|
2004-11-06 05:37:25 +03:00
|
|
|
|
}
|
2004-11-06 03:18:27 +03:00
|
|
|
|
|
2004-11-15 21:44:30 +03:00
|
|
|
|
/* Unpartition the filestruct so that it contains all the text
|
|
|
|
|
* again, and turn the mark back on. */
|
2004-11-22 03:16:23 +03:00
|
|
|
|
unpartition_filestruct(&filepart);
|
2004-11-06 03:18:27 +03:00
|
|
|
|
SET(MARK_ISSET);
|
2004-11-06 02:55:58 +03:00
|
|
|
|
}
|
|
|
|
|
#endif
|
2004-11-06 02:03:03 +03:00
|
|
|
|
|
2004-02-24 23:41:39 +03:00
|
|
|
|
/* Restore the search/replace strings. */
|
|
|
|
|
free(last_search);
|
|
|
|
|
last_search = save_search;
|
|
|
|
|
free(last_replace);
|
|
|
|
|
last_replace = save_replace;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2004-02-24 23:41:39 +03:00
|
|
|
|
/* Restore where we were. */
|
2004-10-18 06:06:53 +04:00
|
|
|
|
edittop = edittop_save;
|
2003-01-26 22:57:44 +03:00
|
|
|
|
current = current_save;
|
|
|
|
|
current_x = current_x_save;
|
2004-10-21 20:25:44 +04:00
|
|
|
|
placewewant = pww_save;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2004-10-09 20:59:43 +04:00
|
|
|
|
/* Restore case sensitivity setting. */
|
2002-12-10 03:53:21 +03:00
|
|
|
|
if (!case_sens_set)
|
|
|
|
|
UNSET(CASE_SENSITIVE);
|
|
|
|
|
|
2004-10-11 17:55:33 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-10-09 20:59:43 +04:00
|
|
|
|
/* Restore search/replace direction. */
|
2005-06-16 22:48:30 +04:00
|
|
|
|
if (backwards_search_set)
|
|
|
|
|
SET(BACKWARDS_SEARCH);
|
2001-07-11 06:08:33 +04:00
|
|
|
|
#endif
|
2004-10-09 21:15:46 +04:00
|
|
|
|
#ifdef HAVE_REGEX_H
|
2004-10-09 20:59:43 +04:00
|
|
|
|
/* Restore regular expression usage setting. */
|
|
|
|
|
if (regexp_set)
|
|
|
|
|
SET(USE_REGEXP);
|
|
|
|
|
#endif
|
2001-07-11 06:08:33 +04:00
|
|
|
|
|
2004-10-27 00:58:30 +04:00
|
|
|
|
return !canceled;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
|
|
|
|
|
2005-06-15 07:56:36 +04:00
|
|
|
|
/* Integrated spell checking using the spell program, filtered through
|
|
|
|
|
* the sort and uniq programs. Return NULL for normal termination,
|
|
|
|
|
* and the error string otherwise. */
|
2004-08-06 02:10:22 +04:00
|
|
|
|
const char *do_int_speller(const char *tempfile_name)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
2002-09-07 00:35:28 +04:00
|
|
|
|
char *read_buff, *read_buff_ptr, *read_buff_word;
|
|
|
|
|
size_t pipe_buff_size, read_buff_size, read_buff_read, bytesread;
|
2003-01-13 02:54:05 +03:00
|
|
|
|
int spell_fd[2], sort_fd[2], uniq_fd[2], tempfile_fd = -1;
|
2002-12-09 03:58:51 +03:00
|
|
|
|
pid_t pid_spell, pid_sort, pid_uniq;
|
|
|
|
|
int spell_status, sort_status, uniq_status;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2004-01-23 22:34:03 +03:00
|
|
|
|
/* Create all three pipes up front. */
|
2005-04-15 21:48:20 +04:00
|
|
|
|
if (pipe(spell_fd) == -1 || pipe(sort_fd) == -1 ||
|
|
|
|
|
pipe(uniq_fd) == -1)
|
2003-01-13 02:54:05 +03:00
|
|
|
|
return _("Could not create pipe");
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2002-12-10 03:16:27 +03:00
|
|
|
|
statusbar(_("Creating misspelled word list, please wait..."));
|
2001-04-12 07:01:53 +04:00
|
|
|
|
|
2004-01-23 22:34:03 +03:00
|
|
|
|
/* A new process to run spell in. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
if ((pid_spell = fork()) == 0) {
|
2004-01-23 22:34:03 +03:00
|
|
|
|
/* Child continues (i.e, future spell process). */
|
2002-12-09 03:58:51 +03:00
|
|
|
|
close(spell_fd[0]);
|
2002-02-15 22:17:02 +03:00
|
|
|
|
|
2004-01-23 22:34:03 +03:00
|
|
|
|
/* Replace the standard input with the temp file. */
|
2003-01-13 02:54:05 +03:00
|
|
|
|
if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1)
|
|
|
|
|
goto close_pipes_and_exit;
|
|
|
|
|
|
|
|
|
|
if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO)
|
|
|
|
|
goto close_pipes_and_exit;
|
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
close(tempfile_fd);
|
2001-04-12 07:01:53 +04:00
|
|
|
|
|
2004-01-23 22:34:03 +03:00
|
|
|
|
/* Send spell's standard output to the pipe. */
|
2003-01-13 02:54:05 +03:00
|
|
|
|
if (dup2(spell_fd[1], STDOUT_FILENO) != STDOUT_FILENO)
|
|
|
|
|
goto close_pipes_and_exit;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2002-12-09 03:58:51 +03:00
|
|
|
|
close(spell_fd[1]);
|
2001-04-12 07:01:53 +04:00
|
|
|
|
|
2005-06-15 07:56:36 +04:00
|
|
|
|
/* Start the spell program; we are using PATH. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
execlp("spell", "spell", NULL);
|
2001-04-12 07:01:53 +04:00
|
|
|
|
|
2005-06-15 07:56:36 +04:00
|
|
|
|
/* This should not be reached if spell is found. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
exit(1);
|
2001-04-12 07:01:53 +04:00
|
|
|
|
}
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2004-01-23 22:34:03 +03:00
|
|
|
|
/* Parent continues here. */
|
2002-12-09 03:58:51 +03:00
|
|
|
|
close(spell_fd[1]);
|
|
|
|
|
|
2004-01-23 22:34:03 +03:00
|
|
|
|
/* A new process to run sort in. */
|
2002-12-09 03:58:51 +03:00
|
|
|
|
if ((pid_sort = fork()) == 0) {
|
2004-01-23 22:34:03 +03:00
|
|
|
|
/* Child continues (i.e, future spell process). Replace the
|
|
|
|
|
* standard input with the standard output of the old pipe. */
|
2003-01-13 02:54:05 +03:00
|
|
|
|
if (dup2(spell_fd[0], STDIN_FILENO) != STDIN_FILENO)
|
|
|
|
|
goto close_pipes_and_exit;
|
|
|
|
|
|
2002-12-09 03:58:51 +03:00
|
|
|
|
close(spell_fd[0]);
|
|
|
|
|
|
2004-01-23 22:34:03 +03:00
|
|
|
|
/* Send sort's standard output to the new pipe. */
|
2003-01-13 02:54:05 +03:00
|
|
|
|
if (dup2(sort_fd[1], STDOUT_FILENO) != STDOUT_FILENO)
|
|
|
|
|
goto close_pipes_and_exit;
|
2002-12-09 03:58:51 +03:00
|
|
|
|
|
|
|
|
|
close(sort_fd[1]);
|
|
|
|
|
|
2005-06-15 07:56:36 +04:00
|
|
|
|
/* Start the sort program. Use -f to remove mixed case. If
|
|
|
|
|
* this isn't portable, let me know. */
|
2002-12-09 03:58:51 +03:00
|
|
|
|
execlp("sort", "sort", "-f", NULL);
|
|
|
|
|
|
2005-06-15 07:56:36 +04:00
|
|
|
|
/* This should not be reached if sort is found. */
|
2002-12-09 03:58:51 +03:00
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-16 06:11:23 +03:00
|
|
|
|
close(spell_fd[0]);
|
2002-12-09 03:58:51 +03:00
|
|
|
|
close(sort_fd[1]);
|
|
|
|
|
|
2004-01-23 22:34:03 +03:00
|
|
|
|
/* A new process to run uniq in. */
|
2002-12-09 03:58:51 +03:00
|
|
|
|
if ((pid_uniq = fork()) == 0) {
|
2004-01-23 22:34:03 +03:00
|
|
|
|
/* Child continues (i.e, future uniq process). Replace the
|
|
|
|
|
* standard input with the standard output of the old pipe. */
|
2003-01-13 02:54:05 +03:00
|
|
|
|
if (dup2(sort_fd[0], STDIN_FILENO) != STDIN_FILENO)
|
|
|
|
|
goto close_pipes_and_exit;
|
|
|
|
|
|
2002-12-09 03:58:51 +03:00
|
|
|
|
close(sort_fd[0]);
|
|
|
|
|
|
2004-01-23 22:34:03 +03:00
|
|
|
|
/* Send uniq's standard output to the new pipe. */
|
2003-01-13 02:54:05 +03:00
|
|
|
|
if (dup2(uniq_fd[1], STDOUT_FILENO) != STDOUT_FILENO)
|
|
|
|
|
goto close_pipes_and_exit;
|
2002-12-09 03:58:51 +03:00
|
|
|
|
|
|
|
|
|
close(uniq_fd[1]);
|
|
|
|
|
|
2005-06-15 07:56:36 +04:00
|
|
|
|
/* Start the uniq program; we are using PATH. */
|
2002-12-09 03:58:51 +03:00
|
|
|
|
execlp("uniq", "uniq", NULL);
|
|
|
|
|
|
2005-06-15 07:56:36 +04:00
|
|
|
|
/* This should not be reached if uniq is found. */
|
2002-12-09 03:58:51 +03:00
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-16 06:11:23 +03:00
|
|
|
|
close(sort_fd[0]);
|
2002-12-09 03:58:51 +03:00
|
|
|
|
close(uniq_fd[1]);
|
2001-06-28 20:52:52 +04:00
|
|
|
|
|
2005-06-15 07:56:36 +04:00
|
|
|
|
/* The child process was not forked successfully. */
|
2002-12-09 03:58:51 +03:00
|
|
|
|
if (pid_spell < 0 || pid_sort < 0 || pid_uniq < 0) {
|
|
|
|
|
close(uniq_fd[0]);
|
2002-12-16 07:25:53 +03:00
|
|
|
|
return _("Could not fork");
|
2002-09-07 00:35:28 +04:00
|
|
|
|
}
|
2000-09-04 07:20:38 +04:00
|
|
|
|
|
2005-06-15 07:56:36 +04:00
|
|
|
|
/* Get the system pipe buffer size. */
|
2002-12-09 03:58:51 +03:00
|
|
|
|
if ((pipe_buff_size = fpathconf(uniq_fd[0], _PC_PIPE_BUF)) < 1) {
|
|
|
|
|
close(uniq_fd[0]);
|
2002-12-16 07:25:53 +03:00
|
|
|
|
return _("Could not get size of pipe buffer");
|
2002-09-07 00:35:28 +04:00
|
|
|
|
}
|
2002-07-19 05:08:59 +04:00
|
|
|
|
|
2004-01-23 22:34:03 +03:00
|
|
|
|
/* Read in the returned spelling errors. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
read_buff_read = 0;
|
|
|
|
|
read_buff_size = pipe_buff_size + 1;
|
|
|
|
|
read_buff = read_buff_ptr = charalloc(read_buff_size);
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2005-06-15 07:15:45 +04:00
|
|
|
|
while ((bytesread = read(uniq_fd[0], read_buff_ptr,
|
|
|
|
|
pipe_buff_size)) > 0) {
|
2002-09-07 00:35:28 +04:00
|
|
|
|
read_buff_read += bytesread;
|
|
|
|
|
read_buff_size += pipe_buff_size;
|
2005-06-15 07:15:45 +04:00
|
|
|
|
read_buff = read_buff_ptr = charealloc(read_buff,
|
|
|
|
|
read_buff_size);
|
2002-09-07 00:35:28 +04:00
|
|
|
|
read_buff_ptr += read_buff_read;
|
|
|
|
|
}
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2005-05-31 07:33:30 +04:00
|
|
|
|
*read_buff_ptr = '\0';
|
2002-12-09 03:58:51 +03:00
|
|
|
|
close(uniq_fd[0]);
|
2001-01-14 08:18:27 +03:00
|
|
|
|
|
2004-01-23 22:34:03 +03:00
|
|
|
|
/* Process the spelling errors. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
read_buff_word = read_buff_ptr = read_buff;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2002-12-22 19:30:00 +03:00
|
|
|
|
while (*read_buff_ptr != '\0') {
|
2005-06-15 07:56:36 +04:00
|
|
|
|
if ((*read_buff_ptr == '\r') || (*read_buff_ptr == '\n')) {
|
2005-05-31 07:33:30 +04:00
|
|
|
|
*read_buff_ptr = '\0';
|
2002-09-07 00:35:28 +04:00
|
|
|
|
if (read_buff_word != read_buff_ptr) {
|
|
|
|
|
if (!do_int_spell_fix(read_buff_word)) {
|
|
|
|
|
read_buff_word = read_buff_ptr;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
read_buff_word = read_buff_ptr + 1;
|
|
|
|
|
}
|
|
|
|
|
read_buff_ptr++;
|
|
|
|
|
}
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2005-06-15 07:56:36 +04:00
|
|
|
|
/* Special case: the last word doesn't end with '\r' or '\n'. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
if (read_buff_word != read_buff_ptr)
|
|
|
|
|
do_int_spell_fix(read_buff_word);
|
2000-06-19 09:45:52 +04:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
free(read_buff);
|
|
|
|
|
replace_abort();
|
2003-01-26 22:57:44 +03:00
|
|
|
|
edit_refresh();
|
2001-01-30 02:37:54 +03:00
|
|
|
|
|
2005-06-15 07:56:36 +04:00
|
|
|
|
/* Process the end of the spell process. */
|
2002-12-16 07:25:53 +03:00
|
|
|
|
waitpid(pid_spell, &spell_status, 0);
|
|
|
|
|
waitpid(pid_sort, &sort_status, 0);
|
|
|
|
|
waitpid(pid_uniq, &uniq_status, 0);
|
2002-12-09 03:58:51 +03:00
|
|
|
|
|
2002-12-16 07:25:53 +03:00
|
|
|
|
if (WIFEXITED(spell_status) == 0 || WEXITSTATUS(spell_status))
|
|
|
|
|
return _("Error invoking \"spell\"");
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
2002-12-16 07:25:53 +03:00
|
|
|
|
if (WIFEXITED(sort_status) == 0 || WEXITSTATUS(sort_status))
|
|
|
|
|
return _("Error invoking \"sort -f\"");
|
|
|
|
|
|
|
|
|
|
if (WIFEXITED(uniq_status) == 0 || WEXITSTATUS(uniq_status))
|
|
|
|
|
return _("Error invoking \"uniq\"");
|
|
|
|
|
|
|
|
|
|
/* Otherwise... */
|
|
|
|
|
return NULL;
|
2003-01-13 02:54:05 +03:00
|
|
|
|
|
2004-01-23 22:34:03 +03:00
|
|
|
|
close_pipes_and_exit:
|
|
|
|
|
/* Don't leak any handles. */
|
2003-01-13 02:54:05 +03:00
|
|
|
|
close(tempfile_fd);
|
|
|
|
|
close(spell_fd[0]);
|
|
|
|
|
close(spell_fd[1]);
|
|
|
|
|
close(sort_fd[0]);
|
|
|
|
|
close(sort_fd[1]);
|
|
|
|
|
close(uniq_fd[0]);
|
|
|
|
|
close(uniq_fd[1]);
|
|
|
|
|
exit(1);
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
|
|
|
|
|
2002-12-22 19:30:00 +03:00
|
|
|
|
/* External spell checking. Return value: NULL for normal termination,
|
|
|
|
|
* otherwise the error string. */
|
2004-05-24 01:11:14 +04:00
|
|
|
|
const char *do_alt_speller(char *tempfile_name)
|
2000-09-01 17:32:47 +04:00
|
|
|
|
{
|
2004-11-06 02:03:03 +03:00
|
|
|
|
int alt_spell_status, lineno_save = current->lineno;
|
|
|
|
|
size_t current_x_save = current_x, pww_save = placewewant;
|
|
|
|
|
int current_y_save = current_y;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
pid_t pid_spell;
|
|
|
|
|
char *ptr;
|
|
|
|
|
static int arglen = 3;
|
2004-09-06 01:40:31 +04:00
|
|
|
|
static char **spellargs = NULL;
|
|
|
|
|
FILE *f;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-09-06 01:40:31 +04:00
|
|
|
|
bool old_mark_set = ISSET(MARK_ISSET);
|
2004-11-04 01:03:41 +03:00
|
|
|
|
bool added_magicline = FALSE;
|
|
|
|
|
/* Whether we added a magicline after filebot. */
|
2004-11-06 02:03:03 +03:00
|
|
|
|
bool right_side_up = FALSE;
|
|
|
|
|
/* TRUE if (mark_beginbuf, mark_beginx) is the top of the mark,
|
|
|
|
|
* FALSE if (current, current_x) is. */
|
2004-11-17 23:47:14 +03:00
|
|
|
|
filestruct *top, *bot;
|
|
|
|
|
size_t top_x, bot_x;
|
2004-11-06 02:03:03 +03:00
|
|
|
|
int mbb_lineno_save = 0;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
/* We're going to close the current file, and open the output of
|
2004-01-23 22:34:03 +03:00
|
|
|
|
* the alternate spell command. The line that mark_beginbuf
|
|
|
|
|
* points to will be freed, so we save the line number and
|
|
|
|
|
* restore afterwards. */
|
2005-01-27 23:49:07 +03:00
|
|
|
|
size_t totsize_save = totsize;
|
2004-11-04 01:03:41 +03:00
|
|
|
|
/* Our saved value of totsize, used when we spell-check a marked
|
|
|
|
|
* selection. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
2004-09-06 01:40:31 +04:00
|
|
|
|
if (old_mark_set) {
|
2004-11-04 01:03:41 +03:00
|
|
|
|
/* If the mark is on, save the number of the line it starts on,
|
|
|
|
|
* and then turn the mark off. */
|
2004-11-06 02:03:03 +03:00
|
|
|
|
mbb_lineno_save = mark_beginbuf->lineno;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
UNSET(MARK_ISSET);
|
|
|
|
|
}
|
2001-06-30 08:09:09 +04:00
|
|
|
|
#endif
|
2000-09-01 17:32:47 +04:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
endwin();
|
2000-09-01 17:32:47 +04:00
|
|
|
|
|
2004-01-23 22:34:03 +03:00
|
|
|
|
/* Set up an argument list to pass execvp(). */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
if (spellargs == NULL) {
|
2003-06-15 00:41:34 +04:00
|
|
|
|
spellargs = (char **)nmalloc(arglen * sizeof(char *));
|
2001-06-28 20:52:52 +04:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
spellargs[0] = strtok(alt_speller, " ");
|
|
|
|
|
while ((ptr = strtok(NULL, " ")) != NULL) {
|
|
|
|
|
arglen++;
|
2003-06-15 00:41:34 +04:00
|
|
|
|
spellargs = (char **)nrealloc(spellargs, arglen * sizeof(char *));
|
2002-09-07 00:35:28 +04:00
|
|
|
|
spellargs[arglen - 3] = ptr;
|
|
|
|
|
}
|
|
|
|
|
spellargs[arglen - 1] = NULL;
|
|
|
|
|
}
|
|
|
|
|
spellargs[arglen - 2] = tempfile_name;
|
2001-12-17 07:34:23 +03:00
|
|
|
|
|
2004-01-23 22:34:03 +03:00
|
|
|
|
/* Start a new process for the alternate speller. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
if ((pid_spell = fork()) == 0) {
|
2004-01-23 22:34:03 +03:00
|
|
|
|
/* Start alternate spell program; we are using PATH. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
execvp(spellargs[0], spellargs);
|
2001-12-17 07:34:23 +03:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
/* Should not be reached, if alternate speller is found!!! */
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
2001-12-17 07:34:23 +03:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
/* Could not fork?? */
|
|
|
|
|
if (pid_spell < 0)
|
2002-12-16 07:25:53 +03:00
|
|
|
|
return _("Could not fork");
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
2004-01-23 22:34:03 +03:00
|
|
|
|
/* Wait for alternate speller to complete. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
wait(&alt_spell_status);
|
2004-01-23 22:34:03 +03:00
|
|
|
|
|
2005-06-21 05:33:31 +04:00
|
|
|
|
refresh();
|
|
|
|
|
|
|
|
|
|
/* Restore the terminal to its previous state. */
|
|
|
|
|
terminal_init();
|
|
|
|
|
|
|
|
|
|
/* Turn the cursor back on for sure. */
|
|
|
|
|
curs_set(1);
|
|
|
|
|
|
2004-12-20 04:13:55 +03:00
|
|
|
|
if (!WIFEXITED(alt_spell_status) ||
|
|
|
|
|
WEXITSTATUS(alt_spell_status) != 0) {
|
2002-12-16 07:25:53 +03:00
|
|
|
|
char *altspell_error = NULL;
|
|
|
|
|
char *invoke_error = _("Could not invoke \"%s\"");
|
2004-12-20 04:18:49 +03:00
|
|
|
|
int msglen = strlen(invoke_error) + strlen(alt_speller) + 2;
|
2002-12-16 07:25:53 +03:00
|
|
|
|
|
2005-06-21 05:33:31 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
/* Turn the mark back on if it was on before. */
|
|
|
|
|
if (old_mark_set)
|
|
|
|
|
SET(MARK_ISSET);
|
|
|
|
|
#endif
|
2004-10-16 08:56:34 +04:00
|
|
|
|
|
2005-06-21 05:41:46 +04:00
|
|
|
|
altspell_error = charalloc(msglen);
|
|
|
|
|
snprintf(altspell_error, msglen, invoke_error, alt_speller);
|
2005-06-21 05:33:31 +04:00
|
|
|
|
return altspell_error;
|
|
|
|
|
}
|
2005-03-21 00:20:47 +03:00
|
|
|
|
|
2004-08-06 02:10:22 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-09-06 01:40:31 +04:00
|
|
|
|
if (old_mark_set) {
|
2005-01-27 23:49:07 +03:00
|
|
|
|
size_t part_totsize;
|
2004-11-04 01:03:41 +03:00
|
|
|
|
|
|
|
|
|
/* If the mark was on, partition the filestruct so that it
|
|
|
|
|
* contains only the marked text, and keep track of whether the
|
|
|
|
|
* temp file (which should contain the spell-checked marked
|
|
|
|
|
* text) will have a magicline added when it's reloaded. */
|
|
|
|
|
mark_order((const filestruct **)&top, &top_x,
|
2004-11-06 02:03:03 +03:00
|
|
|
|
(const filestruct **)&bot, &bot_x, &right_side_up);
|
2004-11-04 01:03:41 +03:00
|
|
|
|
filepart = partition_filestruct(top, top_x, bot, bot_x);
|
|
|
|
|
added_magicline = (filebot->data[0] != '\0');
|
|
|
|
|
|
2004-11-22 19:04:18 +03:00
|
|
|
|
/* Get the number of characters in the marked text, and subtract
|
|
|
|
|
* it from the saved value of totsize. Note that we don't need
|
|
|
|
|
* to save totlines. */
|
|
|
|
|
get_totals(top, bot, NULL, &part_totsize);
|
2005-01-27 23:49:07 +03:00
|
|
|
|
totsize_save -= part_totsize;
|
2004-11-04 01:03:41 +03:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Reinitialize the filestruct. */
|
|
|
|
|
free_filestruct(fileage);
|
|
|
|
|
global_init(TRUE);
|
|
|
|
|
|
|
|
|
|
/* Reload the temp file. Do what load_buffer() would do, except for
|
|
|
|
|
* making a new buffer for the temp file if multibuffer support is
|
|
|
|
|
* available. */
|
|
|
|
|
open_file(tempfile_name, FALSE, &f);
|
|
|
|
|
read_file(f, tempfile_name);
|
|
|
|
|
current = fileage;
|
|
|
|
|
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
if (old_mark_set) {
|
2004-11-05 18:03:12 +03:00
|
|
|
|
filestruct *top_save = fileage;
|
2004-11-04 01:03:41 +03:00
|
|
|
|
|
2004-11-15 21:44:30 +03:00
|
|
|
|
/* If the mark was on and we added a magicline, remove it
|
|
|
|
|
* now. */
|
2004-11-04 01:03:41 +03:00
|
|
|
|
if (added_magicline)
|
|
|
|
|
remove_magicline();
|
|
|
|
|
|
2004-11-06 05:37:25 +03:00
|
|
|
|
/* Put the beginning and the end of the mark at the beginning
|
|
|
|
|
* and the end of the spell-checked text. */
|
|
|
|
|
if (fileage == filebot)
|
2004-11-17 23:47:14 +03:00
|
|
|
|
bot_x += top_x;
|
2004-11-06 05:37:25 +03:00
|
|
|
|
if (right_side_up) {
|
2004-11-17 23:47:14 +03:00
|
|
|
|
mark_beginx = top_x;
|
|
|
|
|
current_x_save = bot_x;
|
2004-11-06 05:37:25 +03:00
|
|
|
|
} else {
|
2004-11-17 23:47:14 +03:00
|
|
|
|
current_x_save = top_x;
|
|
|
|
|
mark_beginx = bot_x;
|
2004-11-06 05:37:25 +03:00
|
|
|
|
}
|
2004-11-06 02:03:03 +03:00
|
|
|
|
|
2004-11-15 21:44:30 +03:00
|
|
|
|
/* Unpartition the filestruct so that it contains all the text
|
|
|
|
|
* again. Note that we've replaced the marked text originally
|
|
|
|
|
* in the partition with the spell-checked marked text in the
|
|
|
|
|
* temp file. */
|
2004-11-22 03:16:23 +03:00
|
|
|
|
unpartition_filestruct(&filepart);
|
2004-11-04 01:03:41 +03:00
|
|
|
|
|
|
|
|
|
/* Renumber starting with the beginning line of the old
|
2004-11-22 19:04:18 +03:00
|
|
|
|
* partition. Also set totlines to the new number of lines in
|
|
|
|
|
* the file, add the number of characters in the spell-checked
|
|
|
|
|
* marked text to the saved value of totsize, and then make that
|
|
|
|
|
* saved value the actual value. */
|
2004-11-05 18:03:12 +03:00
|
|
|
|
renumber(top_save);
|
2004-11-22 19:04:18 +03:00
|
|
|
|
totlines = filebot->lineno;
|
2005-01-27 23:49:07 +03:00
|
|
|
|
totsize_save += totsize;
|
|
|
|
|
totsize = totsize_save;
|
2004-11-04 01:03:41 +03:00
|
|
|
|
|
|
|
|
|
/* Assign mark_beginbuf to the line where the mark began
|
|
|
|
|
* before. */
|
2004-11-06 02:03:03 +03:00
|
|
|
|
do_gotopos(mbb_lineno_save, mark_beginx, current_y_save, 0);
|
2002-09-07 00:35:28 +04:00
|
|
|
|
mark_beginbuf = current;
|
2004-11-04 01:03:41 +03:00
|
|
|
|
|
|
|
|
|
/* Assign mark_beginx to the location in mark_beginbuf where the
|
|
|
|
|
* mark began before, adjusted for any shortening of the
|
|
|
|
|
* line. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
mark_beginx = current_x;
|
2004-09-06 01:40:31 +04:00
|
|
|
|
|
2004-11-04 01:03:41 +03:00
|
|
|
|
/* Turn the mark back on. */
|
|
|
|
|
SET(MARK_ISSET);
|
2002-09-07 00:35:28 +04:00
|
|
|
|
}
|
|
|
|
|
#endif
|
2001-12-17 07:34:23 +03:00
|
|
|
|
|
2005-04-16 22:27:57 +04:00
|
|
|
|
/* Go back to the old position, mark the file as modified, and
|
|
|
|
|
* update the titlebar. */
|
2004-11-06 02:03:03 +03:00
|
|
|
|
do_gotopos(lineno_save, current_x_save, current_y_save, pww_save);
|
2005-04-16 22:27:57 +04:00
|
|
|
|
SET(MODIFIED);
|
2002-09-07 00:35:28 +04:00
|
|
|
|
titlebar(NULL);
|
2001-06-30 08:09:09 +04:00
|
|
|
|
|
2002-12-16 07:25:53 +03:00
|
|
|
|
return NULL;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
}
|
2001-06-30 08:09:09 +04:00
|
|
|
|
|
2004-07-02 18:31:03 +04:00
|
|
|
|
void do_spell(void)
|
2002-09-07 00:35:28 +04:00
|
|
|
|
{
|
2004-01-23 22:34:03 +03:00
|
|
|
|
int i;
|
2005-05-31 08:28:15 +04:00
|
|
|
|
FILE *temp_file;
|
|
|
|
|
char *temp = safe_tempfile(&temp_file);
|
2004-05-24 01:11:14 +04:00
|
|
|
|
const char *spell_msg;
|
2001-06-28 20:52:52 +04:00
|
|
|
|
|
2004-05-24 01:11:14 +04:00
|
|
|
|
if (temp == NULL) {
|
|
|
|
|
statusbar(_("Could not create temp file: %s"), strerror(errno));
|
2004-07-02 18:31:03 +04:00
|
|
|
|
return;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
}
|
2000-09-01 17:32:47 +04:00
|
|
|
|
|
2004-01-23 22:34:03 +03:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
if (ISSET(MARK_ISSET))
|
2005-05-31 08:28:15 +04:00
|
|
|
|
i = write_marked(temp, temp_file, TRUE, FALSE);
|
2004-01-23 22:34:03 +03:00
|
|
|
|
else
|
|
|
|
|
#endif
|
2005-05-31 08:28:15 +04:00
|
|
|
|
i = write_file(temp, temp_file, TRUE, FALSE, FALSE);
|
2004-01-23 22:34:03 +03:00
|
|
|
|
|
|
|
|
|
if (i == -1) {
|
2004-08-12 06:52:14 +04:00
|
|
|
|
statusbar(_("Error writing temp file: %s"), strerror(errno));
|
2002-09-07 00:35:28 +04:00
|
|
|
|
free(temp);
|
2004-07-02 18:31:03 +04:00
|
|
|
|
return;
|
2000-09-04 07:20:38 +04:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
2004-01-23 22:34:03 +03:00
|
|
|
|
/* Update the current open_files entry before spell-checking, in
|
|
|
|
|
* case any problems occur. */
|
2004-07-02 18:31:03 +04:00
|
|
|
|
add_open_file(TRUE);
|
2001-12-17 07:34:23 +03:00
|
|
|
|
#endif
|
2000-09-13 18:03:27 +04:00
|
|
|
|
|
2005-04-14 21:08:35 +04:00
|
|
|
|
spell_msg = (alt_speller != NULL) ? do_alt_speller(temp) :
|
2004-05-24 01:11:14 +04:00
|
|
|
|
do_int_speller(temp);
|
2004-01-23 22:34:03 +03:00
|
|
|
|
unlink(temp);
|
2003-02-12 05:52:04 +03:00
|
|
|
|
free(temp);
|
2001-01-04 05:33:52 +03:00
|
|
|
|
|
2005-06-16 00:21:02 +04:00
|
|
|
|
/* If the spell-checker printed any error messages onscreen, make
|
2005-06-19 02:33:55 +04:00
|
|
|
|
* sure that they're cleared off. */
|
2005-06-21 05:33:31 +04:00
|
|
|
|
total_refresh();
|
2005-06-16 00:21:02 +04:00
|
|
|
|
|
2004-08-06 02:10:22 +04:00
|
|
|
|
if (spell_msg != NULL)
|
2004-05-24 01:11:14 +04:00
|
|
|
|
statusbar(_("Spell checking failed: %s: %s"), spell_msg,
|
|
|
|
|
strerror(errno));
|
2004-08-06 02:10:22 +04:00
|
|
|
|
else
|
2004-05-24 01:11:14 +04:00
|
|
|
|
statusbar(_("Finished checking spelling"));
|
2000-09-01 17:32:47 +04:00
|
|
|
|
}
|
2004-04-30 08:49:02 +04:00
|
|
|
|
#endif /* !DISABLE_SPELLER */
|
2000-09-01 17:32:47 +04:00
|
|
|
|
|
2005-03-20 00:15:30 +03:00
|
|
|
|
#if !defined(DISABLE_HELP) || !defined(DISABLE_JUSTIFY) || !defined(DISABLE_WRAPPING)
|
2005-03-19 00:29:33 +03:00
|
|
|
|
/* We are trying to break a chunk off line. We find the last blank such
|
|
|
|
|
* that the display length to there is at most goal + 1. If there is no
|
2005-03-20 00:15:30 +03:00
|
|
|
|
* such blank, then we find the first blank. We then take the last
|
|
|
|
|
* blank in that group of blanks. The terminating '\0' counts as a
|
|
|
|
|
* blank, as does a '\n' if newline is TRUE. */
|
|
|
|
|
ssize_t break_line(const char *line, ssize_t goal, bool newline)
|
2005-03-19 00:29:33 +03:00
|
|
|
|
{
|
|
|
|
|
ssize_t blank_loc = -1;
|
|
|
|
|
/* Current tentative return value. Index of the last blank we
|
|
|
|
|
* found with short enough display width. */
|
|
|
|
|
ssize_t cur_loc = 0;
|
|
|
|
|
/* Current index in line. */
|
|
|
|
|
int line_len;
|
|
|
|
|
|
|
|
|
|
assert(line != NULL);
|
|
|
|
|
|
|
|
|
|
while (*line != '\0' && goal >= 0) {
|
|
|
|
|
size_t pos = 0;
|
|
|
|
|
|
|
|
|
|
line_len = parse_mbchar(line, NULL, NULL, &pos);
|
|
|
|
|
|
|
|
|
|
if (is_blank_mbchar(line) || (newline && *line == '\n')) {
|
|
|
|
|
blank_loc = cur_loc;
|
|
|
|
|
|
|
|
|
|
if (newline && *line == '\n')
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
goal -= pos;
|
|
|
|
|
line += line_len;
|
|
|
|
|
cur_loc += line_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (goal >= 0)
|
|
|
|
|
/* In fact, the whole line displays shorter than goal. */
|
|
|
|
|
return cur_loc;
|
|
|
|
|
|
|
|
|
|
if (blank_loc == -1) {
|
|
|
|
|
/* No blank was found that was short enough. */
|
2005-03-20 00:15:30 +03:00
|
|
|
|
bool found_blank = FALSE;
|
2005-03-19 00:29:33 +03:00
|
|
|
|
|
2005-03-20 00:15:30 +03:00
|
|
|
|
while (*line != '\0') {
|
|
|
|
|
line_len = parse_mbchar(line, NULL, NULL, NULL);
|
2005-03-19 00:29:33 +03:00
|
|
|
|
|
2005-03-20 00:15:30 +03:00
|
|
|
|
if (is_blank_mbchar(line) || (newline && *line == '\n')) {
|
|
|
|
|
if (!found_blank)
|
|
|
|
|
found_blank = TRUE;
|
|
|
|
|
} else if (found_blank)
|
|
|
|
|
return cur_loc - line_len;
|
2005-03-19 00:29:33 +03:00
|
|
|
|
|
2005-03-20 00:15:30 +03:00
|
|
|
|
line += line_len;
|
|
|
|
|
cur_loc += line_len;
|
2005-03-19 00:29:33 +03:00
|
|
|
|
}
|
2005-03-20 00:15:30 +03:00
|
|
|
|
|
|
|
|
|
return -1;
|
2005-03-19 00:29:33 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Move to the last blank after blank_loc, if there is one. */
|
|
|
|
|
line -= cur_loc;
|
|
|
|
|
line += blank_loc;
|
|
|
|
|
line_len = parse_mbchar(line, NULL, NULL, NULL);
|
|
|
|
|
line += line_len;
|
|
|
|
|
|
|
|
|
|
while (*line != '\0' && (is_blank_mbchar(line) ||
|
|
|
|
|
(newline && *line == '\n'))) {
|
|
|
|
|
line_len = parse_mbchar(line, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
|
|
line += line_len;
|
|
|
|
|
blank_loc += line_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return blank_loc;
|
|
|
|
|
}
|
2005-03-20 00:15:30 +03:00
|
|
|
|
#endif /* !DISABLE_HELP || !DISABLE_JUSTIFY || !DISABLE_WRAPPING */
|
2005-03-19 00:29:33 +03:00
|
|
|
|
|
2005-03-18 08:20:54 +03:00
|
|
|
|
#if !defined(NANO_SMALL) || !defined(DISABLE_JUSTIFY)
|
2004-05-29 21:05:52 +04:00
|
|
|
|
/* The "indentation" of a line is the whitespace between the quote part
|
|
|
|
|
* and the non-whitespace of the line. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
size_t indent_length(const char *line)
|
|
|
|
|
{
|
2002-07-19 05:08:59 +04:00
|
|
|
|
size_t len = 0;
|
2005-01-31 21:59:30 +03:00
|
|
|
|
char *blank_mb;
|
|
|
|
|
int blank_mb_len;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
assert(line != NULL);
|
2005-01-31 21:59:30 +03:00
|
|
|
|
|
|
|
|
|
blank_mb = charalloc(mb_cur_max());
|
|
|
|
|
|
|
|
|
|
while (*line != '\0') {
|
2005-02-11 23:09:11 +03:00
|
|
|
|
blank_mb_len = parse_mbchar(line, blank_mb, NULL, NULL);
|
2005-01-31 21:59:30 +03:00
|
|
|
|
|
|
|
|
|
if (!is_blank_mbchar(blank_mb))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
line += blank_mb_len;
|
|
|
|
|
len += blank_mb_len;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
2005-01-31 21:59:30 +03:00
|
|
|
|
|
|
|
|
|
free(blank_mb);
|
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
return len;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
2005-03-18 08:20:54 +03:00
|
|
|
|
#endif /* !NANO_SMALL || !DISABLE_JUSTIFY */
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#ifndef DISABLE_JUSTIFY
|
2005-03-14 07:31:44 +03:00
|
|
|
|
/* justify_format() replaces blanks with spaces and multiple spaces by 1
|
2005-03-14 23:06:23 +03:00
|
|
|
|
* (except it maintains up to 2 after a character in punct optionally
|
|
|
|
|
* followed by a character in brackets, and removes all from the end).
|
2002-07-19 05:08:59 +04:00
|
|
|
|
*
|
2005-03-14 23:32:00 +03:00
|
|
|
|
* justify_format() might make paragraph->data shorter, and change the
|
|
|
|
|
* actual pointer with null_at().
|
2002-07-19 05:08:59 +04:00
|
|
|
|
*
|
2005-03-14 23:32:00 +03:00
|
|
|
|
* justify_format() will not look at the first skip characters of
|
|
|
|
|
* paragraph. skip should be at most strlen(paragraph->data). The
|
|
|
|
|
* character at paragraph[skip + 1] must not be blank. */
|
2005-03-13 06:28:37 +03:00
|
|
|
|
void justify_format(filestruct *paragraph, size_t skip)
|
2002-08-21 20:10:37 +04:00
|
|
|
|
{
|
2005-03-13 06:28:37 +03:00
|
|
|
|
char *end, *new_end, *new_paragraph_data;
|
|
|
|
|
size_t shift = 0;
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
size_t mark_shift = 0;
|
|
|
|
|
#endif
|
2002-07-19 05:08:59 +04:00
|
|
|
|
|
|
|
|
|
/* These four asserts are assumptions about the input data. */
|
2005-03-13 06:28:37 +03:00
|
|
|
|
assert(paragraph != NULL);
|
|
|
|
|
assert(paragraph->data != NULL);
|
|
|
|
|
assert(skip < strlen(paragraph->data));
|
2005-06-16 16:43:08 +04:00
|
|
|
|
assert(!is_blank_mbchar(paragraph->data + skip));
|
2005-03-13 06:28:37 +03:00
|
|
|
|
|
|
|
|
|
end = paragraph->data + skip;
|
|
|
|
|
new_paragraph_data = charalloc(strlen(paragraph->data) + 1);
|
2005-06-22 04:24:11 +04:00
|
|
|
|
strncpy(new_paragraph_data, paragraph->data, skip);
|
2005-03-13 06:28:37 +03:00
|
|
|
|
new_end = new_paragraph_data + skip;
|
|
|
|
|
|
|
|
|
|
while (*end != '\0') {
|
2005-03-15 08:44:03 +03:00
|
|
|
|
int end_len;
|
|
|
|
|
|
2005-03-13 06:28:37 +03:00
|
|
|
|
/* If this character is blank, make sure that it's a space with
|
|
|
|
|
* no blanks after it. */
|
2005-03-15 08:44:03 +03:00
|
|
|
|
if (is_blank_mbchar(end)) {
|
|
|
|
|
end_len = parse_mbchar(end, NULL, NULL, NULL);
|
|
|
|
|
|
2005-03-13 06:28:37 +03:00
|
|
|
|
*new_end = ' ';
|
|
|
|
|
new_end++;
|
2005-03-15 08:44:03 +03:00
|
|
|
|
end += end_len;
|
2005-03-13 06:28:37 +03:00
|
|
|
|
|
2005-03-15 08:44:03 +03:00
|
|
|
|
while (*end != '\0' && is_blank_mbchar(end)) {
|
|
|
|
|
end_len = parse_mbchar(end, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
|
|
end += end_len;
|
|
|
|
|
shift += end_len;
|
2005-03-14 23:06:23 +03:00
|
|
|
|
|
2005-03-13 06:28:37 +03:00
|
|
|
|
#ifndef NANO_SMALL
|
2005-03-14 23:06:23 +03:00
|
|
|
|
/* Keep track of the change in the current line. */
|
2005-03-13 06:28:37 +03:00
|
|
|
|
if (mark_beginbuf == paragraph &&
|
|
|
|
|
mark_beginx >= end - paragraph->data)
|
2005-03-15 08:44:03 +03:00
|
|
|
|
mark_shift += end_len;
|
2005-03-13 06:28:37 +03:00
|
|
|
|
#endif
|
2002-10-17 06:19:31 +04:00
|
|
|
|
}
|
2005-03-14 23:06:23 +03:00
|
|
|
|
/* If this character is punctuation optionally followed by a
|
|
|
|
|
* bracket and then followed by blanks, make sure there are no
|
|
|
|
|
* more than two blanks after it, and make sure that the blanks
|
|
|
|
|
* are spaces. */
|
2005-03-15 08:44:03 +03:00
|
|
|
|
} else if (mbstrchr(punct, end) != NULL) {
|
|
|
|
|
end_len = parse_mbchar(end, NULL, NULL, NULL);
|
2005-03-13 06:28:37 +03:00
|
|
|
|
|
2005-03-15 08:44:03 +03:00
|
|
|
|
while (end_len > 0) {
|
2005-03-13 06:28:37 +03:00
|
|
|
|
*new_end = *end;
|
|
|
|
|
new_end++;
|
|
|
|
|
end++;
|
2005-03-15 08:44:03 +03:00
|
|
|
|
end_len--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*end != '\0' && mbstrchr(brackets, end) != NULL) {
|
|
|
|
|
end_len = parse_mbchar(end, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
|
|
while (end_len > 0) {
|
|
|
|
|
*new_end = *end;
|
|
|
|
|
new_end++;
|
|
|
|
|
end++;
|
|
|
|
|
end_len--;
|
|
|
|
|
}
|
2005-03-14 23:06:23 +03:00
|
|
|
|
}
|
2005-03-13 06:28:37 +03:00
|
|
|
|
|
2005-03-15 08:44:03 +03:00
|
|
|
|
if (*end != '\0' && is_blank_mbchar(end)) {
|
|
|
|
|
end_len = parse_mbchar(end, NULL, NULL, NULL);
|
|
|
|
|
|
2005-03-14 23:06:23 +03:00
|
|
|
|
*new_end = ' ';
|
|
|
|
|
new_end++;
|
2005-03-15 08:44:03 +03:00
|
|
|
|
end += end_len;
|
2005-03-14 23:06:23 +03:00
|
|
|
|
}
|
2005-03-13 06:28:37 +03:00
|
|
|
|
|
2005-03-15 08:44:03 +03:00
|
|
|
|
if (*end != '\0' && is_blank_mbchar(end)) {
|
|
|
|
|
end_len = parse_mbchar(end, NULL, NULL, NULL);
|
|
|
|
|
|
2005-03-14 23:06:23 +03:00
|
|
|
|
*new_end = ' ';
|
|
|
|
|
new_end++;
|
2005-03-15 08:44:03 +03:00
|
|
|
|
end += end_len;
|
2005-03-14 23:06:23 +03:00
|
|
|
|
}
|
2005-03-13 06:28:37 +03:00
|
|
|
|
|
2005-03-15 08:44:03 +03:00
|
|
|
|
while (*end != '\0' && is_blank_mbchar(end)) {
|
|
|
|
|
end_len = parse_mbchar(end, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
|
|
end += end_len;
|
|
|
|
|
shift += end_len;
|
2002-10-17 06:19:31 +04:00
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2005-03-15 08:44:03 +03:00
|
|
|
|
/* Keep track of the change in the current line. */
|
|
|
|
|
if (mark_beginbuf == paragraph &&
|
|
|
|
|
mark_beginx >= end - paragraph->data)
|
|
|
|
|
mark_shift += end_len;
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#endif
|
2005-03-13 06:28:37 +03:00
|
|
|
|
}
|
2005-03-14 23:06:23 +03:00
|
|
|
|
/* If this character is neither blank nor punctuation, leave it
|
|
|
|
|
* alone. */
|
2002-07-19 05:08:59 +04:00
|
|
|
|
} else {
|
2005-03-15 08:44:03 +03:00
|
|
|
|
end_len = parse_mbchar(end, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
|
|
while (end_len > 0) {
|
|
|
|
|
*new_end = *end;
|
|
|
|
|
new_end++;
|
|
|
|
|
end++;
|
|
|
|
|
end_len--;
|
|
|
|
|
}
|
2002-07-19 05:08:59 +04:00
|
|
|
|
}
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
|
|
|
|
|
2005-03-13 06:28:37 +03:00
|
|
|
|
assert(*end == '\0');
|
|
|
|
|
|
|
|
|
|
*new_end = *end;
|
|
|
|
|
|
2005-03-14 23:06:23 +03:00
|
|
|
|
/* Make sure that there are no spaces at the end of the line. */
|
2005-03-13 06:28:37 +03:00
|
|
|
|
while (new_end > new_paragraph_data + skip &&
|
|
|
|
|
*(new_end - 1) == ' ') {
|
|
|
|
|
new_end--;
|
|
|
|
|
shift++;
|
|
|
|
|
}
|
2005-03-02 02:21:21 +03:00
|
|
|
|
|
2005-03-13 06:28:37 +03:00
|
|
|
|
if (shift > 0) {
|
|
|
|
|
totsize -= shift;
|
|
|
|
|
null_at(&new_paragraph_data, new_end - new_paragraph_data);
|
|
|
|
|
free(paragraph->data);
|
|
|
|
|
paragraph->data = new_paragraph_data;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2005-03-13 06:28:37 +03:00
|
|
|
|
/* Adjust the mark coordinates to compensate for the change in
|
|
|
|
|
* the current line. */
|
|
|
|
|
if (mark_beginbuf == paragraph) {
|
|
|
|
|
mark_beginx -= mark_shift;
|
|
|
|
|
if (mark_beginx > new_end - new_paragraph_data)
|
|
|
|
|
mark_beginx = new_end - new_paragraph_data;
|
|
|
|
|
}
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#endif
|
2005-03-13 06:28:37 +03:00
|
|
|
|
} else
|
|
|
|
|
free(new_paragraph_data);
|
2002-07-19 05:08:59 +04:00
|
|
|
|
}
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
/* The "quote part" of a line is the largest initial substring matching
|
|
|
|
|
* the quote string. This function returns the length of the quote part
|
|
|
|
|
* of the given line.
|
|
|
|
|
*
|
|
|
|
|
* Note that if !HAVE_REGEX_H then we match concatenated copies of
|
|
|
|
|
* quotestr. */
|
2004-07-30 07:54:34 +04:00
|
|
|
|
size_t quote_length(const char *line)
|
2002-08-21 20:10:37 +04:00
|
|
|
|
{
|
2004-07-30 07:54:34 +04:00
|
|
|
|
#ifdef HAVE_REGEX_H
|
2002-07-19 05:08:59 +04:00
|
|
|
|
regmatch_t matches;
|
2004-07-30 07:54:34 +04:00
|
|
|
|
int rc = regexec("ereg, line, 1, &matches, 0);
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2004-07-30 07:54:34 +04:00
|
|
|
|
if (rc == REG_NOMATCH || matches.rm_so == (regoff_t)-1)
|
2002-07-19 05:08:59 +04:00
|
|
|
|
return 0;
|
2004-07-30 07:54:34 +04:00
|
|
|
|
/* matches.rm_so should be 0, since the quote string should start
|
|
|
|
|
* with the caret ^. */
|
2002-07-19 05:08:59 +04:00
|
|
|
|
return matches.rm_eo;
|
|
|
|
|
#else /* !HAVE_REGEX_H */
|
|
|
|
|
size_t qdepth = 0;
|
2002-03-04 01:36:36 +03:00
|
|
|
|
|
2004-07-17 23:49:12 +04:00
|
|
|
|
/* Compute quote depth level. */
|
2004-07-31 18:10:23 +04:00
|
|
|
|
while (strncmp(line + qdepth, quotestr, quotelen) == 0)
|
2004-07-30 07:54:34 +04:00
|
|
|
|
qdepth += quotelen;
|
2002-07-19 05:08:59 +04:00
|
|
|
|
return qdepth;
|
|
|
|
|
#endif /* !HAVE_REGEX_H */
|
2004-07-30 07:54:34 +04:00
|
|
|
|
}
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
/* a_line and b_line are lines of text. The quotation part of a_line is
|
|
|
|
|
* the first a_quote characters. Check that the quotation part of
|
|
|
|
|
* b_line is the same. */
|
2004-08-06 02:10:22 +04:00
|
|
|
|
bool quotes_match(const char *a_line, size_t a_quote, const char
|
|
|
|
|
*b_line)
|
2002-08-21 20:10:37 +04:00
|
|
|
|
{
|
2004-12-20 04:13:55 +03:00
|
|
|
|
/* Here is the assumption about a_quote. */
|
2004-07-30 07:54:34 +04:00
|
|
|
|
assert(a_quote == quote_length(a_line));
|
2004-12-20 04:13:55 +03:00
|
|
|
|
|
2005-03-12 23:29:22 +03:00
|
|
|
|
return (a_quote == quote_length(b_line) &&
|
|
|
|
|
strncmp(a_line, b_line, a_quote) == 0);
|
2002-07-19 05:08:59 +04:00
|
|
|
|
}
|
2002-03-04 01:36:36 +03:00
|
|
|
|
|
2004-07-30 07:54:34 +04:00
|
|
|
|
/* We assume a_line and b_line have no quote part. Then, we return
|
|
|
|
|
* whether b_line could follow a_line in a paragraph. */
|
2004-08-06 02:10:22 +04:00
|
|
|
|
bool indents_match(const char *a_line, size_t a_indent, const char
|
2004-05-14 05:17:25 +04:00
|
|
|
|
*b_line, size_t b_indent)
|
2002-08-21 20:10:37 +04:00
|
|
|
|
{
|
2002-07-19 05:08:59 +04:00
|
|
|
|
assert(a_indent == indent_length(a_line));
|
|
|
|
|
assert(b_indent == indent_length(b_line));
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2005-03-12 23:29:22 +03:00
|
|
|
|
return (b_indent <= a_indent &&
|
|
|
|
|
strncmp(a_line, b_line, b_indent) == 0);
|
2002-07-19 05:08:59 +04:00
|
|
|
|
}
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2004-07-30 07:54:34 +04:00
|
|
|
|
/* Is foo the beginning of a paragraph?
|
|
|
|
|
*
|
|
|
|
|
* A line of text consists of a "quote part", followed by an
|
|
|
|
|
* "indentation part", followed by text. The functions quote_length()
|
|
|
|
|
* and indent_length() calculate these parts.
|
|
|
|
|
*
|
|
|
|
|
* A line is "part of a paragraph" if it has a part not in the quote
|
|
|
|
|
* part or the indentation.
|
|
|
|
|
*
|
|
|
|
|
* A line is "the beginning of a paragraph" if it is part of a
|
|
|
|
|
* paragraph and
|
|
|
|
|
* 1) it is the top line of the file, or
|
|
|
|
|
* 2) the line above it is not part of a paragraph, or
|
|
|
|
|
* 3) the line above it does not have precisely the same quote
|
|
|
|
|
* part, or
|
|
|
|
|
* 4) the indentation of this line is not an initial substring of
|
|
|
|
|
* the indentation of the previous line, or
|
|
|
|
|
* 5) this line has no quote part and some indentation, and
|
2005-03-13 19:42:36 +03:00
|
|
|
|
* autoindent isn't turned on.
|
|
|
|
|
* The reason for number 5) is that if autoindent isn't turned on,
|
|
|
|
|
* then an indented line is expected to start a paragraph, as in
|
|
|
|
|
* books. Thus, nano can justify an indented paragraph only if
|
|
|
|
|
* autoindent is turned on. */
|
2004-07-30 07:54:34 +04:00
|
|
|
|
bool begpar(const filestruct *const foo)
|
|
|
|
|
{
|
|
|
|
|
size_t quote_len;
|
|
|
|
|
size_t indent_len;
|
|
|
|
|
size_t temp_id_len;
|
|
|
|
|
|
|
|
|
|
/* Case 1). */
|
|
|
|
|
if (foo->prev == NULL)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
quote_len = quote_length(foo->data);
|
|
|
|
|
indent_len = indent_length(foo->data + quote_len);
|
|
|
|
|
|
|
|
|
|
/* Not part of a paragraph. */
|
|
|
|
|
if (foo->data[quote_len + indent_len] == '\0')
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
/* Case 3). */
|
|
|
|
|
if (!quotes_match(foo->data, quote_len, foo->prev->data))
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
temp_id_len = indent_length(foo->prev->data + quote_len);
|
|
|
|
|
|
|
|
|
|
/* Case 2) or 5) or 4). */
|
|
|
|
|
if (foo->prev->data[quote_len + temp_id_len] == '\0' ||
|
|
|
|
|
(quote_len == 0 && indent_len > 0
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
&& !ISSET(AUTOINDENT)
|
|
|
|
|
#endif
|
|
|
|
|
) || !indents_match(foo->prev->data + quote_len, temp_id_len,
|
|
|
|
|
foo->data + quote_len, indent_len))
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* We find the last beginning-of-paragraph line before the current
|
|
|
|
|
* line. */
|
2005-03-14 00:12:25 +03:00
|
|
|
|
void do_para_begin(bool allow_update)
|
2004-07-30 07:54:34 +04:00
|
|
|
|
{
|
2005-01-15 00:26:38 +03:00
|
|
|
|
const filestruct *current_save = current;
|
|
|
|
|
const size_t pww_save = placewewant;
|
2004-07-30 07:54:34 +04:00
|
|
|
|
|
|
|
|
|
current_x = 0;
|
|
|
|
|
placewewant = 0;
|
|
|
|
|
|
|
|
|
|
if (current->prev != NULL) {
|
|
|
|
|
do {
|
|
|
|
|
current = current->prev;
|
2004-08-27 21:02:05 +04:00
|
|
|
|
current_y--;
|
2004-07-30 07:54:34 +04:00
|
|
|
|
} while (!begpar(current));
|
|
|
|
|
}
|
|
|
|
|
|
2005-03-14 00:12:25 +03:00
|
|
|
|
if (allow_update)
|
|
|
|
|
edit_redraw(current_save, pww_save);
|
2004-07-30 07:54:34 +04:00
|
|
|
|
}
|
|
|
|
|
|
2005-03-14 00:12:25 +03:00
|
|
|
|
void do_para_begin_void(void)
|
2004-07-30 07:54:34 +04:00
|
|
|
|
{
|
2005-03-14 00:12:25 +03:00
|
|
|
|
do_para_begin(TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Is foo inside a paragraph? */
|
|
|
|
|
bool inpar(const filestruct *const foo)
|
|
|
|
|
{
|
|
|
|
|
size_t quote_len;
|
2004-07-30 07:54:34 +04:00
|
|
|
|
|
2005-03-14 00:12:25 +03:00
|
|
|
|
if (foo == NULL)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
quote_len = quote_length(foo->data);
|
|
|
|
|
|
|
|
|
|
return foo->data[quote_len + indent_length(foo->data +
|
|
|
|
|
quote_len)] != '\0';
|
2004-07-30 07:54:34 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* A line is the last line of a paragraph if it is in a paragraph, and
|
|
|
|
|
* the next line isn't, or is the beginning of a paragraph. We move
|
|
|
|
|
* down to the end of a paragraph, then one line farther. */
|
2005-03-14 00:12:25 +03:00
|
|
|
|
void do_para_end(bool allow_update)
|
2004-07-30 07:54:34 +04:00
|
|
|
|
{
|
2005-01-15 00:26:38 +03:00
|
|
|
|
const filestruct *const current_save = current;
|
|
|
|
|
const size_t pww_save = placewewant;
|
2004-07-30 07:54:34 +04:00
|
|
|
|
|
|
|
|
|
current_x = 0;
|
|
|
|
|
placewewant = 0;
|
|
|
|
|
|
2005-03-14 00:12:25 +03:00
|
|
|
|
while (current->next != NULL && !inpar(current))
|
2004-07-30 07:54:34 +04:00
|
|
|
|
current = current->next;
|
|
|
|
|
|
2005-03-14 00:12:25 +03:00
|
|
|
|
while (current->next != NULL && inpar(current->next) &&
|
2004-08-27 21:02:05 +04:00
|
|
|
|
!begpar(current->next)) {
|
2004-07-30 07:54:34 +04:00
|
|
|
|
current = current->next;
|
2004-08-27 21:02:05 +04:00
|
|
|
|
current_y++;
|
|
|
|
|
}
|
2004-07-30 07:54:34 +04:00
|
|
|
|
|
|
|
|
|
if (current->next != NULL)
|
|
|
|
|
current = current->next;
|
|
|
|
|
|
2005-03-14 00:12:25 +03:00
|
|
|
|
if (allow_update)
|
|
|
|
|
edit_redraw(current_save, pww_save);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void do_para_end_void(void)
|
|
|
|
|
{
|
|
|
|
|
do_para_end(TRUE);
|
2004-07-30 07:54:34 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-11-23 07:08:28 +03:00
|
|
|
|
/* Put the next par_len lines, starting with first_line, into the
|
|
|
|
|
* justify buffer, leaving copies of those lines in place. Assume there
|
|
|
|
|
* are enough lines after first_line. Return the new copy of
|
|
|
|
|
* first_line. */
|
2004-05-14 05:17:25 +04:00
|
|
|
|
filestruct *backup_lines(filestruct *first_line, size_t par_len, size_t
|
|
|
|
|
quote_len)
|
2002-08-21 20:10:37 +04:00
|
|
|
|
{
|
2004-11-23 07:08:28 +03:00
|
|
|
|
filestruct *top = first_line;
|
|
|
|
|
/* The top of the paragraph we're backing up. */
|
|
|
|
|
filestruct *bot = first_line;
|
|
|
|
|
/* The bottom of the paragraph we're backing up. */
|
|
|
|
|
size_t i;
|
|
|
|
|
/* Generic loop variable. */
|
|
|
|
|
size_t current_x_save = current_x;
|
|
|
|
|
int fl_lineno_save = first_line->lineno;
|
|
|
|
|
int edittop_lineno_save = edittop->lineno;
|
|
|
|
|
int current_lineno_save = current->lineno;
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
bool old_mark_set = ISSET(MARK_ISSET);
|
|
|
|
|
int mbb_lineno_save = 0;
|
2005-03-12 23:29:22 +03:00
|
|
|
|
size_t mark_beginx_save = 0;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2005-03-12 23:29:22 +03:00
|
|
|
|
if (old_mark_set) {
|
2004-11-23 07:08:28 +03:00
|
|
|
|
mbb_lineno_save = mark_beginbuf->lineno;
|
2005-03-12 23:29:22 +03:00
|
|
|
|
mark_beginx_save = mark_beginx;
|
|
|
|
|
}
|
2004-11-23 07:08:28 +03:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Move bot down par_len lines to the newline after the last line of
|
|
|
|
|
* the paragraph. */
|
|
|
|
|
for (i = par_len; i > 0; i--)
|
|
|
|
|
bot = bot->next;
|
|
|
|
|
|
|
|
|
|
/* Move the paragraph from the main filestruct to the justify
|
|
|
|
|
* buffer. */
|
|
|
|
|
move_to_filestruct(&jusbuffer, &jusbottom, top, 0, bot, 0);
|
|
|
|
|
|
|
|
|
|
/* Copy the paragraph from the justify buffer to the main
|
|
|
|
|
* filestruct. */
|
|
|
|
|
copy_from_filestruct(jusbuffer, jusbottom);
|
2002-07-19 05:08:59 +04:00
|
|
|
|
|
2004-11-23 07:08:28 +03:00
|
|
|
|
/* Move upward from the last line of the paragraph to the first
|
|
|
|
|
* line, putting first_line, edittop, current, and mark_beginbuf at
|
|
|
|
|
* the same lines in the copied paragraph that they had in the
|
|
|
|
|
* original paragraph. */
|
|
|
|
|
top = current->prev;
|
|
|
|
|
for (i = par_len; i > 0; i--) {
|
|
|
|
|
if (top->lineno == fl_lineno_save)
|
|
|
|
|
first_line = top;
|
|
|
|
|
if (top->lineno == edittop_lineno_save)
|
|
|
|
|
edittop = top;
|
|
|
|
|
if (top->lineno == current_lineno_save)
|
|
|
|
|
current = top;
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2005-03-12 23:29:22 +03:00
|
|
|
|
if (old_mark_set && top->lineno == mbb_lineno_save) {
|
2004-11-23 07:08:28 +03:00
|
|
|
|
mark_beginbuf = top;
|
2005-03-12 23:29:22 +03:00
|
|
|
|
mark_beginx = mark_beginx_save;
|
|
|
|
|
}
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#endif
|
2004-11-23 07:08:28 +03:00
|
|
|
|
top = top->prev;
|
2002-07-19 05:08:59 +04:00
|
|
|
|
}
|
2004-11-23 07:08:28 +03:00
|
|
|
|
|
|
|
|
|
/* Put current_x at the same place in the copied paragraph that it
|
|
|
|
|
* had in the original paragraph. */
|
|
|
|
|
current_x = current_x_save;
|
|
|
|
|
|
|
|
|
|
set_modified();
|
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
return first_line;
|
|
|
|
|
}
|
|
|
|
|
|
2004-07-30 07:54:34 +04:00
|
|
|
|
/* Find the beginning of the current paragraph if we're in one, or the
|
|
|
|
|
* beginning of the next paragraph if we're not. Afterwards, save the
|
2005-03-14 00:12:25 +03:00
|
|
|
|
* quote length and paragraph length in *quote and *par. Return TRUE if
|
|
|
|
|
* we found a paragraph, or FALSE if there was an error or we didn't
|
2004-07-30 07:54:34 +04:00
|
|
|
|
* find a paragraph.
|
2002-07-19 05:08:59 +04:00
|
|
|
|
*
|
2004-07-30 07:54:34 +04:00
|
|
|
|
* See the comment at begpar() for more about when a line is the
|
|
|
|
|
* beginning of a paragraph. */
|
2005-03-14 00:12:25 +03:00
|
|
|
|
bool find_paragraph(size_t *const quote, size_t *const par)
|
2004-02-27 21:54:04 +03:00
|
|
|
|
{
|
2002-07-19 05:08:59 +04:00
|
|
|
|
size_t quote_len;
|
2005-03-14 00:12:25 +03:00
|
|
|
|
/* Length of the initial quotation of the paragraph we search
|
|
|
|
|
* for. */
|
2002-07-19 05:08:59 +04:00
|
|
|
|
size_t par_len;
|
2005-03-14 00:12:25 +03:00
|
|
|
|
/* Number of lines in the paragraph we search for. */
|
|
|
|
|
filestruct *current_save;
|
|
|
|
|
/* The line at the beginning of the paragraph we search for. */
|
|
|
|
|
size_t current_y_save;
|
|
|
|
|
/* The y-coordinate at the beginning of the paragraph we search
|
|
|
|
|
* for. */
|
2003-09-05 00:25:29 +04:00
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#ifdef HAVE_REGEX_H
|
2004-07-30 07:54:34 +04:00
|
|
|
|
if (quoterc != 0) {
|
|
|
|
|
statusbar(_("Bad quote string %s: %s"), quotestr, quoteerr);
|
2005-03-14 00:12:25 +03:00
|
|
|
|
return FALSE;
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#endif
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
assert(current != NULL);
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2005-03-14 00:12:25 +03:00
|
|
|
|
/* Move back to the beginning of the current line. */
|
2003-09-05 00:25:29 +04:00
|
|
|
|
current_x = 0;
|
|
|
|
|
|
2005-03-14 00:12:25 +03:00
|
|
|
|
/* Find the first line of the current or next paragraph. First, if
|
|
|
|
|
* the current line isn't in a paragraph, move forward to the line
|
2005-03-22 04:53:57 +03:00
|
|
|
|
* after the last line of the next paragraph. If we end up on the
|
|
|
|
|
* same line, or the line before that isn't in a paragraph, it means
|
|
|
|
|
* that there aren't any paragraphs left, so get out. Otherwise,
|
|
|
|
|
* move back to the last line of the paragraph. If the current line
|
|
|
|
|
* is in a paragraph and it isn't the first line of that paragraph,
|
|
|
|
|
* move back to the first line. */
|
2005-03-14 00:12:25 +03:00
|
|
|
|
if (!inpar(current)) {
|
2005-03-17 07:24:12 +03:00
|
|
|
|
filestruct *current_save = current;
|
|
|
|
|
|
2005-03-14 00:12:25 +03:00
|
|
|
|
do_para_end(FALSE);
|
2005-03-17 07:24:12 +03:00
|
|
|
|
if (current == current_save || !inpar(current->prev))
|
2005-03-14 00:12:25 +03:00
|
|
|
|
return FALSE;
|
2005-03-22 04:53:57 +03:00
|
|
|
|
if (current->prev != NULL)
|
|
|
|
|
current = current->prev;
|
2004-02-27 21:54:04 +03:00
|
|
|
|
}
|
2005-03-14 00:12:25 +03:00
|
|
|
|
if (!begpar(current))
|
|
|
|
|
do_para_begin(FALSE);
|
2004-02-27 21:54:04 +03:00
|
|
|
|
|
2005-03-14 00:12:25 +03:00
|
|
|
|
/* Now current is the first line of the paragraph. Set quote_len to
|
|
|
|
|
* the quotation length of that line, and set par_len to the number
|
|
|
|
|
* of lines in this paragraph. */
|
|
|
|
|
quote_len = quote_length(current->data);
|
|
|
|
|
current_save = current;
|
|
|
|
|
current_y_save = current_y;
|
|
|
|
|
do_para_end(FALSE);
|
|
|
|
|
par_len = current->lineno - current_save->lineno;
|
|
|
|
|
current = current_save;
|
|
|
|
|
current_y = current_y_save;
|
2004-02-27 21:54:04 +03:00
|
|
|
|
|
2004-07-30 07:54:34 +04:00
|
|
|
|
/* Save the values of quote_len and par_len. */
|
|
|
|
|
assert(quote != NULL && par != NULL);
|
2005-03-04 20:09:41 +03:00
|
|
|
|
|
2004-07-30 07:54:34 +04:00
|
|
|
|
*quote = quote_len;
|
|
|
|
|
*par = par_len;
|
2004-02-27 21:54:04 +03:00
|
|
|
|
|
2005-03-14 00:12:25 +03:00
|
|
|
|
return TRUE;
|
2004-02-27 21:54:04 +03:00
|
|
|
|
}
|
|
|
|
|
|
2004-05-13 21:28:03 +04:00
|
|
|
|
/* If full_justify is TRUE, justify the entire file. Otherwise, justify
|
|
|
|
|
* the current paragraph. */
|
2004-08-06 02:10:22 +04:00
|
|
|
|
void do_justify(bool full_justify)
|
2004-02-27 21:54:04 +03:00
|
|
|
|
{
|
2004-05-18 00:32:51 +04:00
|
|
|
|
filestruct *first_par_line = NULL;
|
|
|
|
|
/* Will be the first line of the resulting justified paragraph.
|
2004-11-23 07:08:28 +03:00
|
|
|
|
* For restoring after unjustify. */
|
2004-05-18 00:38:00 +04:00
|
|
|
|
filestruct *last_par_line;
|
2004-11-23 07:08:28 +03:00
|
|
|
|
/* Will be the line containing the newline after the last line
|
|
|
|
|
* of the result. Also for restoring after unjustify. */
|
2004-02-27 21:54:04 +03:00
|
|
|
|
|
|
|
|
|
/* We save these global variables to be restored if the user
|
2004-10-29 19:48:40 +04:00
|
|
|
|
* unjustifies. Note that we don't need to save totlines. */
|
2004-10-30 05:03:15 +04:00
|
|
|
|
size_t current_x_save = current_x;
|
|
|
|
|
int current_y_save = current_y;
|
2005-01-27 23:49:07 +03:00
|
|
|
|
unsigned long flags_save = flags;
|
|
|
|
|
size_t totsize_save = totsize;
|
2004-10-29 19:48:40 +04:00
|
|
|
|
filestruct *edittop_save = edittop, *current_save = current;
|
2004-02-27 21:54:04 +03:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
filestruct *mark_beginbuf_save = mark_beginbuf;
|
2004-10-30 05:16:08 +04:00
|
|
|
|
size_t mark_beginx_save = mark_beginx;
|
2004-02-27 21:54:04 +03:00
|
|
|
|
#endif
|
2004-07-01 22:59:52 +04:00
|
|
|
|
int kbinput;
|
2005-01-12 02:05:05 +03:00
|
|
|
|
bool meta_key, func_key, s_or_t, ran_func, finished;
|
2004-02-27 21:54:04 +03:00
|
|
|
|
|
2004-05-18 00:32:51 +04:00
|
|
|
|
/* If we're justifying the entire file, start at the beginning. */
|
|
|
|
|
if (full_justify)
|
2004-05-13 21:28:03 +04:00
|
|
|
|
current = fileage;
|
2004-05-18 00:32:51 +04:00
|
|
|
|
|
|
|
|
|
last_par_line = current;
|
2004-05-13 21:28:03 +04:00
|
|
|
|
|
|
|
|
|
while (TRUE) {
|
2005-03-13 06:28:37 +03:00
|
|
|
|
size_t i;
|
|
|
|
|
/* Generic loop variable. */
|
2004-07-30 07:54:34 +04:00
|
|
|
|
size_t quote_len;
|
|
|
|
|
/* Length of the initial quotation of the paragraph we
|
|
|
|
|
* justify. */
|
2005-03-13 06:28:37 +03:00
|
|
|
|
size_t indent_len;
|
|
|
|
|
/* Length of the initial indentation of the paragraph we
|
|
|
|
|
* justify. */
|
2004-07-30 07:54:34 +04:00
|
|
|
|
size_t par_len;
|
2005-03-13 06:28:37 +03:00
|
|
|
|
/* Number of lines in the paragraph we justify. */
|
|
|
|
|
ssize_t break_pos;
|
|
|
|
|
/* Where we will break lines. */
|
2005-03-17 08:08:15 +03:00
|
|
|
|
char *indent_string;
|
2005-03-13 18:48:36 +03:00
|
|
|
|
/* The first indentation that doesn't match the initial
|
|
|
|
|
* indentation of the paragraph we justify. This is put at
|
|
|
|
|
* the beginning of every line broken off the first
|
2005-03-13 23:39:33 +03:00
|
|
|
|
* justified line of the paragraph. (Note that this works
|
|
|
|
|
* because a paragraph can only contain two indentations at
|
|
|
|
|
* most: the initial one, and a different one starting on a
|
|
|
|
|
* line after the first. See the comment at begpar() for
|
|
|
|
|
* more about when a line is part of a paragraph.) */
|
2004-07-30 07:54:34 +04:00
|
|
|
|
|
|
|
|
|
/* Find the first line of the paragraph to be justified. That
|
|
|
|
|
* is the start of this paragraph if we're in one, or the start
|
|
|
|
|
* of the next otherwise. Save the quote length and paragraph
|
2004-12-04 20:36:14 +03:00
|
|
|
|
* length (number of lines). Don't refresh the screen yet,
|
2005-03-17 07:48:14 +03:00
|
|
|
|
* since we'll do that after we justify.
|
|
|
|
|
*
|
|
|
|
|
* If the search failed, we do one of two things. If we're
|
|
|
|
|
* justifying the whole file, we've found at least one
|
|
|
|
|
* paragraph, and the search didn't leave us on the last line of
|
|
|
|
|
* the file, it means that we should justify all the way to the
|
|
|
|
|
* last line of the file, so set the last line of the text to be
|
|
|
|
|
* justified to the last line of the file and break out of the
|
|
|
|
|
* loop. Otherwise, it means that there are no paragraph(s) to
|
|
|
|
|
* justify, so refresh the screen and get out. */
|
2005-03-14 00:12:25 +03:00
|
|
|
|
if (!find_paragraph("e_len, &par_len)) {
|
2005-03-17 07:48:14 +03:00
|
|
|
|
if (full_justify && first_par_line != NULL &&
|
|
|
|
|
first_par_line != filebot) {
|
2004-11-23 07:08:28 +03:00
|
|
|
|
last_par_line = filebot;
|
2004-05-13 21:28:03 +04:00
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
edit_refresh();
|
2004-07-02 18:31:03 +04:00
|
|
|
|
return;
|
2004-05-13 21:28:03 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
2003-09-05 00:25:29 +04:00
|
|
|
|
|
2005-03-13 06:28:37 +03:00
|
|
|
|
/* If we haven't already done it, copy the original paragraph(s)
|
|
|
|
|
* to the justify buffer. */
|
|
|
|
|
if (first_par_line == NULL)
|
|
|
|
|
first_par_line = backup_lines(current, full_justify ?
|
|
|
|
|
filebot->lineno - current->lineno : par_len, quote_len);
|
|
|
|
|
|
2005-03-17 08:08:15 +03:00
|
|
|
|
/* Initialize indent_string to a blank string. */
|
|
|
|
|
indent_string = mallocstrcpy(NULL, "");
|
|
|
|
|
|
2005-03-13 18:48:36 +03:00
|
|
|
|
/* Find the first indentation in the paragraph that doesn't
|
|
|
|
|
* match the indentation of the first line, and save it<EFBFBD>in
|
|
|
|
|
* indent_string. If all the indentations are the same, save
|
|
|
|
|
* the indentation of the first line in indent_string. */
|
|
|
|
|
{
|
|
|
|
|
const filestruct *indent_line = current;
|
|
|
|
|
bool past_first_line = FALSE;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < par_len; i++) {
|
2005-03-13 19:05:47 +03:00
|
|
|
|
indent_len = quote_len +
|
2005-03-13 18:48:36 +03:00
|
|
|
|
indent_length(indent_line->data + quote_len);
|
|
|
|
|
|
|
|
|
|
if (indent_len != strlen(indent_string)) {
|
|
|
|
|
indent_string = mallocstrncpy(indent_string,
|
|
|
|
|
indent_line->data, indent_len + 1);
|
|
|
|
|
indent_string[indent_len] = '\0';
|
|
|
|
|
|
|
|
|
|
if (past_first_line)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (indent_line == current)
|
|
|
|
|
past_first_line = TRUE;
|
|
|
|
|
|
|
|
|
|
indent_line = indent_line->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now tack all the lines of the paragraph together, skipping
|
|
|
|
|
* the quoting and indentation on all lines after the first. */
|
2005-03-13 06:28:37 +03:00
|
|
|
|
for (i = 0; i < par_len - 1; i++) {
|
|
|
|
|
filestruct *next_line = current->next;
|
|
|
|
|
size_t line_len = strlen(current->data);
|
|
|
|
|
size_t next_line_len = strlen(current->next->data);
|
|
|
|
|
|
|
|
|
|
indent_len = quote_len + indent_length(current->next->data +
|
2004-05-24 01:11:14 +04:00
|
|
|
|
quote_len);
|
2005-03-13 18:48:36 +03:00
|
|
|
|
|
2005-03-13 06:28:37 +03:00
|
|
|
|
next_line_len -= indent_len;
|
|
|
|
|
totsize -= indent_len;
|
|
|
|
|
|
2005-03-13 18:48:36 +03:00
|
|
|
|
/* We're just about to tack the next line onto this one. If
|
2005-03-18 08:20:54 +03:00
|
|
|
|
* this line isn't empty, make sure it ends in a space. */
|
2005-03-13 06:28:37 +03:00
|
|
|
|
if (line_len > 0 && current->data[line_len - 1] != ' ') {
|
|
|
|
|
line_len++;
|
|
|
|
|
current->data = charealloc(current->data, line_len + 1);
|
|
|
|
|
current->data[line_len - 1] = ' ';
|
|
|
|
|
current->data[line_len] = '\0';
|
|
|
|
|
totsize++;
|
|
|
|
|
}
|
2004-05-13 21:28:03 +04:00
|
|
|
|
|
2005-03-13 06:28:37 +03:00
|
|
|
|
current->data = charealloc(current->data, line_len +
|
|
|
|
|
next_line_len + 1);
|
|
|
|
|
strcat(current->data, next_line->data + indent_len);
|
|
|
|
|
|
|
|
|
|
/* Don't destroy edittop! */
|
|
|
|
|
if (edittop == next_line)
|
|
|
|
|
edittop = current;
|
2004-06-25 05:52:10 +04:00
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2005-03-13 06:28:37 +03:00
|
|
|
|
/* Adjust the mark coordinates to compensate for the change
|
|
|
|
|
* in the next line. */
|
|
|
|
|
if (mark_beginbuf == next_line) {
|
|
|
|
|
mark_beginbuf = current;
|
2005-03-13 19:05:47 +03:00
|
|
|
|
mark_beginx += line_len - indent_len;
|
2005-03-13 06:28:37 +03:00
|
|
|
|
}
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#endif
|
2005-03-13 06:28:37 +03:00
|
|
|
|
|
|
|
|
|
unlink_node(next_line);
|
|
|
|
|
delete_node(next_line);
|
|
|
|
|
|
|
|
|
|
/* If we've removed the next line, we need to go through
|
|
|
|
|
* this line again. */
|
|
|
|
|
i--;
|
|
|
|
|
|
|
|
|
|
par_len--;
|
|
|
|
|
totlines--;
|
|
|
|
|
totsize--;
|
|
|
|
|
}
|
|
|
|
|
|
2005-03-13 18:48:36 +03:00
|
|
|
|
/* Call justify_format() on the paragraph, which will remove
|
|
|
|
|
* excess spaces from it and change all blank characters to
|
|
|
|
|
* spaces. */
|
2005-03-13 06:28:37 +03:00
|
|
|
|
justify_format(current, quote_len +
|
|
|
|
|
indent_length(current->data + quote_len));
|
|
|
|
|
|
|
|
|
|
while (par_len > 0 && strlenpt(current->data) > fill) {
|
|
|
|
|
size_t line_len = strlen(current->data);
|
|
|
|
|
|
2005-03-13 18:48:36 +03:00
|
|
|
|
indent_len = strlen(indent_string);
|
2005-03-13 06:28:37 +03:00
|
|
|
|
|
|
|
|
|
/* If this line is too long, try to wrap it to the next line
|
|
|
|
|
* to make it short enough. */
|
|
|
|
|
break_pos = break_line(current->data + indent_len,
|
2005-03-20 00:15:30 +03:00
|
|
|
|
fill - strnlenpt(current->data, indent_len), FALSE);
|
2005-03-13 06:28:37 +03:00
|
|
|
|
|
|
|
|
|
/* We can't break the line, or don't need to, so get out. */
|
|
|
|
|
if (break_pos == -1 || break_pos + indent_len == line_len)
|
|
|
|
|
break;
|
|
|
|
|
|
2005-03-22 05:17:36 +03:00
|
|
|
|
/* Move forward to the character after the indentation and
|
|
|
|
|
* just after the space. */
|
|
|
|
|
break_pos += indent_len + 1;
|
2005-03-13 06:28:37 +03:00
|
|
|
|
|
2005-03-22 05:17:36 +03:00
|
|
|
|
assert(break_pos <= line_len);
|
2005-03-13 06:28:37 +03:00
|
|
|
|
|
2005-03-22 04:25:34 +03:00
|
|
|
|
/* Make a new line, and copy the text after where we're
|
|
|
|
|
* going to break this line to the beginning of the new
|
|
|
|
|
* line. */
|
2005-03-13 06:28:37 +03:00
|
|
|
|
splice_node(current, make_new_node(current), current->next);
|
|
|
|
|
|
2005-03-13 09:03:33 +03:00
|
|
|
|
/* If this paragraph is non-quoted, and autoindent isn't
|
|
|
|
|
* turned on, set the indentation length to zero so that the
|
2005-03-13 06:28:37 +03:00
|
|
|
|
* indentation is treated as part of the line. */
|
|
|
|
|
if (quote_len == 0
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2005-03-13 06:28:37 +03:00
|
|
|
|
&& !ISSET(AUTOINDENT)
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#endif
|
2005-03-13 06:28:37 +03:00
|
|
|
|
)
|
|
|
|
|
indent_len = 0;
|
2004-07-03 18:15:58 +04:00
|
|
|
|
|
2005-03-22 05:17:36 +03:00
|
|
|
|
/* Copy the text after where we're going to break the
|
|
|
|
|
* current line to the next line. */
|
|
|
|
|
current->next->data = charalloc(indent_len + 1 + line_len -
|
2005-03-13 06:28:37 +03:00
|
|
|
|
break_pos);
|
2005-06-22 04:24:11 +04:00
|
|
|
|
strncpy(current->next->data, indent_string, indent_len);
|
2005-03-13 06:28:37 +03:00
|
|
|
|
strcpy(current->next->data + indent_len, current->data +
|
2005-03-22 05:17:36 +03:00
|
|
|
|
break_pos);
|
2002-07-19 05:08:59 +04:00
|
|
|
|
|
2005-03-13 06:28:37 +03:00
|
|
|
|
par_len++;
|
|
|
|
|
totlines++;
|
2005-03-22 04:25:34 +03:00
|
|
|
|
totsize += indent_len + 1;
|
2005-02-23 01:24:14 +03:00
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2005-03-13 06:28:37 +03:00
|
|
|
|
/* Adjust the mark coordinates to compensate for the change
|
|
|
|
|
* in the current line. */
|
|
|
|
|
if (mark_beginbuf == current && mark_beginx > break_pos) {
|
|
|
|
|
mark_beginbuf = current->next;
|
2005-03-22 05:17:36 +03:00
|
|
|
|
mark_beginx -= break_pos - indent_len;
|
2005-03-13 06:28:37 +03:00
|
|
|
|
}
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#endif
|
2005-03-13 06:28:37 +03:00
|
|
|
|
|
2005-03-22 05:17:36 +03:00
|
|
|
|
/* Break the current line. */
|
|
|
|
|
null_at(¤t->data, break_pos);
|
2005-03-13 06:28:37 +03:00
|
|
|
|
|
|
|
|
|
/* Go to the next line. */
|
|
|
|
|
par_len--;
|
|
|
|
|
current_y++;
|
|
|
|
|
current = current->next;
|
2004-05-13 21:28:03 +04:00
|
|
|
|
}
|
|
|
|
|
|
2005-03-13 18:48:36 +03:00
|
|
|
|
/* We're done breaking lines, so we don't need indent_string
|
|
|
|
|
* anymore. */
|
|
|
|
|
free(indent_string);
|
|
|
|
|
|
2005-03-13 06:28:37 +03:00
|
|
|
|
/* Go to the next line, the line after the last line of the
|
|
|
|
|
* paragraph. */
|
|
|
|
|
current_y++;
|
|
|
|
|
current = current->next;
|
|
|
|
|
|
2004-05-18 00:32:51 +04:00
|
|
|
|
/* We've just justified a paragraph. If we're not justifying the
|
|
|
|
|
* entire file, break out of the loop. Otherwise, continue the
|
|
|
|
|
* loop so that we justify all the paragraphs in the file. */
|
2004-05-13 21:28:03 +04:00
|
|
|
|
if (!full_justify)
|
|
|
|
|
break;
|
2005-03-12 23:29:22 +03:00
|
|
|
|
}
|
2000-06-20 06:50:33 +04:00
|
|
|
|
|
2004-05-18 00:32:51 +04:00
|
|
|
|
/* We are now done justifying the paragraph or the file, so clean
|
|
|
|
|
* up. totlines, totsize, and current_y have been maintained above.
|
|
|
|
|
* Set last_par_line to the new end of the paragraph, update
|
2004-07-23 16:30:40 +04:00
|
|
|
|
* fileage, and renumber() since edit_refresh() needs the line
|
|
|
|
|
* numbers to be right (but only do the last two if we actually
|
|
|
|
|
* justified something). */
|
2004-11-23 07:08:28 +03:00
|
|
|
|
last_par_line = current;
|
2004-07-23 16:30:40 +04:00
|
|
|
|
if (first_par_line != NULL) {
|
|
|
|
|
if (first_par_line->prev == NULL)
|
|
|
|
|
fileage = first_par_line;
|
|
|
|
|
renumber(first_par_line);
|
|
|
|
|
}
|
2004-05-18 00:32:51 +04:00
|
|
|
|
|
2004-05-17 20:11:18 +04:00
|
|
|
|
edit_refresh();
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2000-11-27 03:23:41 +03:00
|
|
|
|
statusbar(_("Can now UnJustify!"));
|
2004-09-06 01:40:31 +04:00
|
|
|
|
|
2004-05-13 21:28:03 +04:00
|
|
|
|
/* Display the shortcut list with UnJustify. */
|
2004-07-01 22:59:52 +04:00
|
|
|
|
shortcut_init(TRUE);
|
2000-11-28 01:58:23 +03:00
|
|
|
|
display_main_list();
|
2000-11-27 03:23:41 +03:00
|
|
|
|
|
2004-11-28 07:52:57 +03:00
|
|
|
|
/* Now get a keystroke and see if it's unjustify. If not, put back
|
|
|
|
|
* the keystroke and return. */
|
2005-01-12 02:05:05 +03:00
|
|
|
|
kbinput = do_input(&meta_key, &func_key, &s_or_t, &ran_func,
|
|
|
|
|
&finished, FALSE);
|
2004-07-01 22:59:52 +04:00
|
|
|
|
|
2004-12-04 20:41:52 +03:00
|
|
|
|
if (!meta_key && !func_key && s_or_t &&
|
|
|
|
|
kbinput == NANO_UNJUSTIFY_KEY) {
|
2004-08-25 19:39:10 +04:00
|
|
|
|
/* Restore the justify we just did (ungrateful user!). */
|
2002-07-19 05:08:59 +04:00
|
|
|
|
current = current_save;
|
|
|
|
|
current_x = current_x_save;
|
|
|
|
|
current_y = current_y_save;
|
|
|
|
|
edittop = edittop_save;
|
|
|
|
|
|
2004-11-23 07:08:28 +03:00
|
|
|
|
/* Splice the justify buffer back into the file, but only if we
|
2004-07-23 16:30:40 +04:00
|
|
|
|
* actually justified something. */
|
|
|
|
|
if (first_par_line != NULL) {
|
2004-11-23 07:08:28 +03:00
|
|
|
|
filestruct *bot_save;
|
2004-07-23 16:30:40 +04:00
|
|
|
|
|
2004-11-23 07:08:28 +03:00
|
|
|
|
/* Partition the filestruct so that it contains only the
|
|
|
|
|
* text of the justified paragraph. */
|
|
|
|
|
filepart = partition_filestruct(first_par_line, 0,
|
|
|
|
|
last_par_line, 0);
|
2004-05-18 00:32:51 +04:00
|
|
|
|
|
2004-11-23 07:08:28 +03:00
|
|
|
|
/* Remove the text of the justified paragraph, and
|
|
|
|
|
* put the text in the justify buffer in its place. */
|
|
|
|
|
free_filestruct(fileage);
|
|
|
|
|
fileage = jusbuffer;
|
|
|
|
|
filebot = jusbottom;
|
|
|
|
|
|
|
|
|
|
bot_save = filebot;
|
|
|
|
|
|
|
|
|
|
/* Unpartition the filestruct so that it contains all the
|
|
|
|
|
* text again. Note that the justified paragraph has been
|
|
|
|
|
* replaced with the unjustified paragraph. */
|
|
|
|
|
unpartition_filestruct(&filepart);
|
|
|
|
|
|
|
|
|
|
/* Renumber starting with the ending line of the old
|
|
|
|
|
* partition. */
|
|
|
|
|
if (bot_save->next != NULL)
|
|
|
|
|
renumber(bot_save->next);
|
|
|
|
|
|
|
|
|
|
/* Restore global variables from before the justify. */
|
|
|
|
|
totsize = totsize_save;
|
|
|
|
|
totlines = filebot->lineno;
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-11-23 07:08:28 +03:00
|
|
|
|
mark_beginbuf = mark_beginbuf_save;
|
|
|
|
|
mark_beginx = mark_beginx_save;
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#endif
|
2004-11-23 07:08:28 +03:00
|
|
|
|
flags = flags_save;
|
|
|
|
|
|
|
|
|
|
/* Clear the justify buffer. */
|
|
|
|
|
jusbuffer = NULL;
|
|
|
|
|
|
|
|
|
|
if (!ISSET(MODIFIED))
|
|
|
|
|
titlebar(NULL);
|
|
|
|
|
edit_refresh();
|
|
|
|
|
}
|
2004-08-25 19:39:10 +04:00
|
|
|
|
} else {
|
2004-12-04 20:41:52 +03:00
|
|
|
|
unget_kbinput(kbinput, meta_key, func_key);
|
2004-11-24 00:40:26 +03:00
|
|
|
|
|
2004-11-28 06:53:01 +03:00
|
|
|
|
/* Blow away the text in the justify buffer. */
|
2004-11-23 07:08:28 +03:00
|
|
|
|
free_filestruct(jusbuffer);
|
|
|
|
|
jusbuffer = NULL;
|
2000-11-27 03:23:41 +03:00
|
|
|
|
}
|
2004-07-01 22:59:52 +04:00
|
|
|
|
|
2004-05-24 01:11:14 +04:00
|
|
|
|
blank_statusbar();
|
2004-09-06 01:40:31 +04:00
|
|
|
|
|
2004-05-13 21:28:03 +04:00
|
|
|
|
/* Display the shortcut list with UnCut. */
|
2004-07-01 22:59:52 +04:00
|
|
|
|
shortcut_init(FALSE);
|
2000-11-28 01:59:40 +03:00
|
|
|
|
display_main_list();
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
2004-05-13 21:28:03 +04:00
|
|
|
|
|
2004-07-02 18:31:03 +04:00
|
|
|
|
void do_justify_void(void)
|
2004-05-13 21:28:03 +04:00
|
|
|
|
{
|
2004-07-02 18:31:03 +04:00
|
|
|
|
do_justify(FALSE);
|
2004-05-13 21:28:03 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-07-02 18:31:03 +04:00
|
|
|
|
void do_full_justify(void)
|
2004-05-13 21:28:03 +04:00
|
|
|
|
{
|
2004-07-02 18:31:03 +04:00
|
|
|
|
do_justify(TRUE);
|
2004-05-13 21:28:03 +04:00
|
|
|
|
}
|
2004-04-30 08:49:02 +04:00
|
|
|
|
#endif /* !DISABLE_JUSTIFY */
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2004-07-02 18:31:03 +04:00
|
|
|
|
void do_exit(void)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
2002-09-07 00:35:28 +04:00
|
|
|
|
int i;
|
|
|
|
|
|
2004-07-02 18:31:03 +04:00
|
|
|
|
if (!ISSET(MODIFIED))
|
|
|
|
|
i = 0; /* Pretend the user chose not to save. */
|
2004-07-03 07:09:12 +04:00
|
|
|
|
else if (ISSET(TEMP_FILE))
|
2002-09-07 00:35:28 +04:00
|
|
|
|
i = 1;
|
2003-12-24 06:33:09 +03:00
|
|
|
|
else
|
2004-07-02 18:31:03 +04:00
|
|
|
|
i = do_yesno(FALSE,
|
|
|
|
|
_("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
|
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
dump_buffer(fileage);
|
2001-10-22 07:15:31 +04:00
|
|
|
|
#endif
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
2005-05-31 08:28:15 +04:00
|
|
|
|
if (i == 0 || (i == 1 && do_writeout(TRUE) == 0)) {
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
2004-12-01 18:11:27 +03:00
|
|
|
|
/* Exit only if there are no more open file buffers. */
|
2004-10-03 23:18:48 +04:00
|
|
|
|
if (!close_open_file())
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#endif
|
2004-05-25 23:41:11 +04:00
|
|
|
|
finish();
|
2004-07-02 18:31:03 +04:00
|
|
|
|
} else if (i != 1)
|
2002-09-07 00:35:28 +04:00
|
|
|
|
statusbar(_("Cancelled"));
|
|
|
|
|
|
|
|
|
|
display_main_list();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void signal_init(void)
|
|
|
|
|
{
|
2004-04-07 04:44:35 +04:00
|
|
|
|
/* Trap SIGINT and SIGQUIT because we want them to do useful
|
|
|
|
|
* things. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
memset(&act, 0, sizeof(struct sigaction));
|
|
|
|
|
act.sa_handler = SIG_IGN;
|
|
|
|
|
sigaction(SIGINT, &act, NULL);
|
2004-01-26 23:56:20 +03:00
|
|
|
|
sigaction(SIGQUIT, &act, NULL);
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
2004-04-07 04:44:35 +04:00
|
|
|
|
/* Trap SIGHUP and SIGTERM because we want to write the file out. */
|
2002-10-17 06:19:31 +04:00
|
|
|
|
act.sa_handler = handle_hupterm;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
sigaction(SIGHUP, &act, NULL);
|
2002-10-17 06:19:31 +04:00
|
|
|
|
sigaction(SIGTERM, &act, NULL);
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
2002-03-21 08:07:28 +03:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-04-07 04:44:35 +04:00
|
|
|
|
/* Trap SIGWINCH because we want to handle window resizes. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
act.sa_handler = handle_sigwinch;
|
|
|
|
|
sigaction(SIGWINCH, &act, NULL);
|
2004-02-16 23:32:40 +03:00
|
|
|
|
allow_pending_sigwinch(FALSE);
|
2002-03-21 08:07:28 +03:00
|
|
|
|
#endif
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2004-05-18 05:20:36 +04:00
|
|
|
|
/* Trap normal suspend (^Z) so we can handle it ourselves. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
if (!ISSET(SUSPEND)) {
|
|
|
|
|
act.sa_handler = SIG_IGN;
|
|
|
|
|
sigaction(SIGTSTP, &act, NULL);
|
|
|
|
|
} else {
|
2004-04-07 04:44:35 +04:00
|
|
|
|
/* Block all other signals in the suspend and continue handlers.
|
|
|
|
|
* If we don't do this, other stuff interrupts them! */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
sigfillset(&act.sa_mask);
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
act.sa_handler = do_suspend;
|
|
|
|
|
sigaction(SIGTSTP, &act, NULL);
|
2002-05-12 23:52:15 +04:00
|
|
|
|
|
2002-09-07 00:35:28 +04:00
|
|
|
|
act.sa_handler = do_cont;
|
|
|
|
|
sigaction(SIGCONT, &act, NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-09-01 17:32:47 +04:00
|
|
|
|
|
2004-05-18 05:20:36 +04:00
|
|
|
|
/* Handler for SIGHUP (hangup) and SIGTERM (terminate). */
|
2005-01-19 22:52:42 +03:00
|
|
|
|
void handle_hupterm(int signal)
|
2002-09-07 00:35:28 +04:00
|
|
|
|
{
|
2003-02-03 06:32:08 +03:00
|
|
|
|
die(_("Received SIGHUP or SIGTERM\n"));
|
2002-09-07 00:35:28 +04:00
|
|
|
|
}
|
2002-06-21 07:20:06 +04:00
|
|
|
|
|
2004-05-18 05:20:36 +04:00
|
|
|
|
/* Handler for SIGTSTP (suspend). */
|
2005-01-19 22:52:42 +03:00
|
|
|
|
void do_suspend(int signal)
|
2002-09-07 00:35:28 +04:00
|
|
|
|
{
|
|
|
|
|
endwin();
|
2003-02-13 02:54:34 +03:00
|
|
|
|
printf("\n\n\n\n\n%s\n", _("Use \"fg\" to return to nano"));
|
2002-09-07 00:35:28 +04:00
|
|
|
|
fflush(stdout);
|
2000-09-01 17:32:47 +04:00
|
|
|
|
|
2004-05-18 05:20:36 +04:00
|
|
|
|
/* Restore the old terminal settings. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
tcsetattr(0, TCSANOW, &oldterm);
|
2002-02-15 22:17:02 +03:00
|
|
|
|
|
2003-09-29 11:21:11 +04:00
|
|
|
|
/* Trap SIGHUP and SIGTERM so we can properly deal with them while
|
2004-05-18 05:20:36 +04:00
|
|
|
|
* suspended. */
|
2003-09-29 11:21:11 +04:00
|
|
|
|
act.sa_handler = handle_hupterm;
|
|
|
|
|
sigaction(SIGHUP, &act, NULL);
|
|
|
|
|
sigaction(SIGTERM, &act, NULL);
|
|
|
|
|
|
2004-05-18 05:20:36 +04:00
|
|
|
|
/* Do what mutt does: send ourselves a SIGSTOP. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
kill(0, SIGSTOP);
|
|
|
|
|
}
|
2002-06-21 07:20:06 +04:00
|
|
|
|
|
2004-05-18 05:20:36 +04:00
|
|
|
|
/* Handler for SIGCONT (continue after suspend). */
|
2005-01-19 22:52:42 +03:00
|
|
|
|
void do_cont(int signal)
|
2002-09-07 00:35:28 +04:00
|
|
|
|
{
|
2002-04-23 14:56:06 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-05-18 05:20:36 +04:00
|
|
|
|
/* Perhaps the user resized the window while we slept. Handle it
|
|
|
|
|
* and update the screen in the process. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
handle_sigwinch(0);
|
2004-04-07 04:44:35 +04:00
|
|
|
|
#else
|
2004-05-18 05:20:36 +04:00
|
|
|
|
/* Just update the screen. */
|
|
|
|
|
doupdate();
|
2002-09-07 00:35:28 +04:00
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
void handle_sigwinch(int s)
|
|
|
|
|
{
|
|
|
|
|
const char *tty = ttyname(0);
|
2005-03-08 19:41:53 +03:00
|
|
|
|
int fd, result = 0;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
struct winsize win;
|
|
|
|
|
|
2002-12-22 19:30:00 +03:00
|
|
|
|
if (tty == NULL)
|
2002-09-07 00:35:28 +04:00
|
|
|
|
return;
|
|
|
|
|
fd = open(tty, O_RDWR);
|
|
|
|
|
if (fd == -1)
|
|
|
|
|
return;
|
|
|
|
|
result = ioctl(fd, TIOCGWINSZ, &win);
|
|
|
|
|
close(fd);
|
|
|
|
|
if (result == -1)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Could check whether the COLS or LINES changed, and return
|
|
|
|
|
* otherwise. EXCEPT, that COLS and LINES are ncurses global
|
|
|
|
|
* variables, and in some cases ncurses has already updated them.
|
|
|
|
|
* But not in all cases, argh. */
|
|
|
|
|
COLS = win.ws_col;
|
|
|
|
|
LINES = win.ws_row;
|
|
|
|
|
|
2005-01-19 22:52:42 +03:00
|
|
|
|
check_die_too_small();
|
|
|
|
|
resize_variables();
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
2004-11-04 01:03:41 +03:00
|
|
|
|
/* If we've partitioned the filestruct, unpartition it now. */
|
|
|
|
|
if (filepart != NULL)
|
2004-11-22 03:16:23 +03:00
|
|
|
|
unpartition_filestruct(&filepart);
|
2004-11-04 01:03:41 +03:00
|
|
|
|
|
2004-11-23 07:08:28 +03:00
|
|
|
|
#ifndef DISABLE_JUSTIFY
|
2004-11-23 07:17:19 +03:00
|
|
|
|
/* If the justify buffer isn't empty, blow away the text in it and
|
|
|
|
|
* display the shortcut list with UnCut. */
|
2004-11-23 07:08:28 +03:00
|
|
|
|
if (jusbuffer != NULL) {
|
|
|
|
|
free_filestruct(jusbuffer);
|
|
|
|
|
jusbuffer = NULL;
|
|
|
|
|
shortcut_init(FALSE);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-05-18 05:20:36 +04:00
|
|
|
|
#ifdef USE_SLANG
|
|
|
|
|
/* Slang curses emulation brain damage, part 1: If we just do what
|
|
|
|
|
* curses does here, it'll only work properly if the resize made the
|
|
|
|
|
* window smaller. Do what mutt does: Leave and immediately reenter
|
|
|
|
|
* Slang screen management mode. */
|
|
|
|
|
SLsmg_reset_smg();
|
|
|
|
|
SLsmg_init_smg();
|
|
|
|
|
#else
|
|
|
|
|
/* Do the equivalent of what Minimum Profit does: Leave and
|
|
|
|
|
* immediately reenter curses mode. */
|
|
|
|
|
endwin();
|
|
|
|
|
refresh();
|
|
|
|
|
#endif
|
2002-09-07 00:35:28 +04:00
|
|
|
|
|
2004-07-27 20:46:35 +04:00
|
|
|
|
/* Restore the terminal to its previous state. */
|
|
|
|
|
terminal_init();
|
|
|
|
|
|
2005-03-21 00:20:47 +03:00
|
|
|
|
/* Turn the cursor back on for sure. */
|
|
|
|
|
curs_set(1);
|
|
|
|
|
|
2004-05-18 05:20:36 +04:00
|
|
|
|
/* Do the equivalent of what both mutt and Minimum Profit do:
|
|
|
|
|
* Reinitialize all the windows based on the new screen
|
|
|
|
|
* dimensions. */
|
|
|
|
|
window_init();
|
|
|
|
|
|
2004-11-12 03:09:20 +03:00
|
|
|
|
/* Redraw the contents of the windows that need it. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
blank_statusbar();
|
2005-01-17 08:06:55 +03:00
|
|
|
|
currshortcut = main_list;
|
2002-09-07 00:35:28 +04:00
|
|
|
|
total_refresh();
|
|
|
|
|
|
2004-05-28 21:23:33 +04:00
|
|
|
|
/* Reset all the input routines that rely on character sequences. */
|
|
|
|
|
reset_kbinput();
|
|
|
|
|
|
2004-01-30 07:20:28 +03:00
|
|
|
|
/* Jump back to the main loop. */
|
2002-09-07 00:35:28 +04:00
|
|
|
|
siglongjmp(jmpbuf, 1);
|
|
|
|
|
}
|
2004-02-16 23:32:40 +03:00
|
|
|
|
|
2004-08-06 02:10:22 +04:00
|
|
|
|
void allow_pending_sigwinch(bool allow)
|
2004-02-16 23:32:40 +03:00
|
|
|
|
{
|
|
|
|
|
sigset_t winch;
|
|
|
|
|
sigemptyset(&winch);
|
|
|
|
|
sigaddset(&winch, SIGWINCH);
|
|
|
|
|
if (allow)
|
|
|
|
|
sigprocmask(SIG_UNBLOCK, &winch, NULL);
|
|
|
|
|
else
|
|
|
|
|
sigprocmask(SIG_BLOCK, &winch, NULL);
|
|
|
|
|
}
|
2002-04-23 14:56:06 +04:00
|
|
|
|
#endif /* !NANO_SMALL */
|
2002-06-21 07:20:06 +04:00
|
|
|
|
|
2002-04-23 14:56:06 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2002-08-21 20:10:37 +04:00
|
|
|
|
void do_toggle(const toggle *which)
|
2000-09-01 17:32:47 +04:00
|
|
|
|
{
|
2004-08-06 02:10:22 +04:00
|
|
|
|
bool enabled;
|
2000-09-02 22:44:21 +04:00
|
|
|
|
|
2002-02-15 22:17:02 +03:00
|
|
|
|
TOGGLE(which->flag);
|
2000-09-13 03:02:49 +04:00
|
|
|
|
|
2002-02-15 22:17:02 +03:00
|
|
|
|
switch (which->val) {
|
2003-10-04 00:26:25 +04:00
|
|
|
|
#ifndef DISABLE_MOUSE
|
2004-11-27 19:54:00 +03:00
|
|
|
|
case TOGGLE_MOUSE_KEY:
|
|
|
|
|
mouse_init();
|
|
|
|
|
break;
|
2002-12-22 19:30:00 +03:00
|
|
|
|
#endif
|
2005-01-17 08:06:55 +03:00
|
|
|
|
case TOGGLE_MORESPACE_KEY:
|
2004-11-27 19:54:00 +03:00
|
|
|
|
case TOGGLE_NOHELP_KEY:
|
|
|
|
|
window_init();
|
2005-01-17 08:06:55 +03:00
|
|
|
|
total_refresh();
|
2004-11-27 19:54:00 +03:00
|
|
|
|
break;
|
2005-01-17 08:06:55 +03:00
|
|
|
|
case TOGGLE_SUSPEND_KEY:
|
|
|
|
|
signal_init();
|
2004-11-27 19:54:00 +03:00
|
|
|
|
break;
|
2004-05-29 20:25:30 +04:00
|
|
|
|
#ifdef ENABLE_NANORC
|
2004-11-27 19:54:00 +03:00
|
|
|
|
case TOGGLE_WHITESPACE_KEY:
|
2004-12-05 07:18:26 +03:00
|
|
|
|
titlebar(NULL);
|
2004-11-27 19:54:00 +03:00
|
|
|
|
edit_refresh();
|
|
|
|
|
break;
|
2005-01-17 08:06:55 +03:00
|
|
|
|
#endif
|
|
|
|
|
#ifdef ENABLE_COLOR
|
|
|
|
|
case TOGGLE_SYNTAX_KEY:
|
|
|
|
|
edit_refresh();
|
|
|
|
|
break;
|
2002-12-22 19:30:00 +03:00
|
|
|
|
#endif
|
2000-09-01 17:32:47 +04:00
|
|
|
|
}
|
2000-09-13 03:02:49 +04:00
|
|
|
|
|
2002-07-19 05:08:59 +04:00
|
|
|
|
enabled = ISSET(which->flag);
|
2005-06-09 08:00:03 +04:00
|
|
|
|
|
|
|
|
|
if (which->val == TOGGLE_NOHELP_KEY ||
|
|
|
|
|
which->val == TOGGLE_WRAP_KEY)
|
2002-07-19 05:08:59 +04:00
|
|
|
|
enabled = !enabled;
|
2005-06-09 08:00:03 +04:00
|
|
|
|
|
|
|
|
|
statusbar("%s %s", which->desc, enabled ? _("enabled") :
|
|
|
|
|
_("disabled"));
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
2002-04-23 14:56:06 +04:00
|
|
|
|
#endif /* !NANO_SMALL */
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2005-06-09 08:02:57 +04:00
|
|
|
|
void disable_extended_io(void)
|
2004-09-23 02:45:08 +04:00
|
|
|
|
{
|
|
|
|
|
struct termios term;
|
|
|
|
|
|
|
|
|
|
tcgetattr(0, &term);
|
|
|
|
|
term.c_lflag &= ~IEXTEN;
|
2005-06-09 08:02:57 +04:00
|
|
|
|
term.c_oflag &= ~OPOST;
|
2004-09-23 02:45:08 +04:00
|
|
|
|
tcsetattr(0, TCSANOW, &term);
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-18 05:20:36 +04:00
|
|
|
|
void disable_signals(void)
|
|
|
|
|
{
|
|
|
|
|
struct termios term;
|
|
|
|
|
|
|
|
|
|
tcgetattr(0, &term);
|
|
|
|
|
term.c_lflag &= ~ISIG;
|
|
|
|
|
tcsetattr(0, TCSANOW, &term);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
void enable_signals(void)
|
|
|
|
|
{
|
|
|
|
|
struct termios term;
|
|
|
|
|
|
|
|
|
|
tcgetattr(0, &term);
|
|
|
|
|
term.c_lflag |= ISIG;
|
|
|
|
|
tcsetattr(0, TCSANOW, &term);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void disable_flow_control(void)
|
|
|
|
|
{
|
|
|
|
|
struct termios term;
|
|
|
|
|
|
|
|
|
|
tcgetattr(0, &term);
|
2005-06-24 02:28:56 +04:00
|
|
|
|
term.c_iflag &= ~IXON;
|
2004-05-18 05:20:36 +04:00
|
|
|
|
tcsetattr(0, TCSANOW, &term);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void enable_flow_control(void)
|
|
|
|
|
{
|
|
|
|
|
struct termios term;
|
|
|
|
|
|
|
|
|
|
tcgetattr(0, &term);
|
2005-06-24 02:28:56 +04:00
|
|
|
|
term.c_iflag |= IXON;
|
2004-05-18 05:20:36 +04:00
|
|
|
|
tcsetattr(0, TCSANOW, &term);
|
|
|
|
|
}
|
|
|
|
|
|
2004-07-27 20:46:35 +04:00
|
|
|
|
/* Set up the terminal state. Put the terminal in cbreak mode (read one
|
|
|
|
|
* character at a time and interpret the special control keys), disable
|
|
|
|
|
* translation of carriage return (^M) into newline (^J) so that we can
|
|
|
|
|
* tell the difference between the Enter key and Ctrl-J, and disable
|
2004-09-23 02:45:08 +04:00
|
|
|
|
* echoing of characters as they're typed. Finally, disable extended
|
2005-06-09 08:02:57 +04:00
|
|
|
|
* input and output processing, disable interpretation of the special
|
|
|
|
|
* control keys, and if we're not in preserve mode, disable
|
|
|
|
|
* interpretation of the flow control characters too. */
|
2004-07-27 20:46:35 +04:00
|
|
|
|
void terminal_init(void)
|
|
|
|
|
{
|
|
|
|
|
cbreak();
|
|
|
|
|
nonl();
|
|
|
|
|
noecho();
|
2005-06-09 08:02:57 +04:00
|
|
|
|
disable_extended_io();
|
2004-07-27 20:46:35 +04:00
|
|
|
|
disable_signals();
|
|
|
|
|
if (!ISSET(PRESERVE))
|
|
|
|
|
disable_flow_control();
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-04 20:41:52 +03:00
|
|
|
|
int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
|
2005-01-12 02:05:05 +03:00
|
|
|
|
*ran_func, bool *finished, bool allow_funcs)
|
2004-12-04 20:41:52 +03:00
|
|
|
|
{
|
|
|
|
|
int input;
|
|
|
|
|
/* The character we read in. */
|
|
|
|
|
static int *kbinput = NULL;
|
|
|
|
|
/* The input buffer. */
|
|
|
|
|
static size_t kbinput_len = 0;
|
|
|
|
|
/* The length of the input buffer. */
|
|
|
|
|
const shortcut *s;
|
|
|
|
|
bool have_shortcut;
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
const toggle *t;
|
|
|
|
|
bool have_toggle;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
*s_or_t = FALSE;
|
2005-01-12 02:05:05 +03:00
|
|
|
|
*ran_func = FALSE;
|
2005-01-01 10:28:15 +03:00
|
|
|
|
*finished = FALSE;
|
2004-12-04 20:41:52 +03:00
|
|
|
|
|
|
|
|
|
/* Read in a character. */
|
|
|
|
|
input = get_kbinput(edit, meta_key, func_key);
|
|
|
|
|
|
|
|
|
|
#ifndef DISABLE_MOUSE
|
|
|
|
|
/* If we got a mouse click and it was on a shortcut, read in the
|
|
|
|
|
* shortcut character. */
|
2005-01-03 00:13:36 +03:00
|
|
|
|
if (allow_funcs && *func_key == TRUE && input == KEY_MOUSE) {
|
2004-12-04 20:41:52 +03:00
|
|
|
|
if (do_mouse())
|
|
|
|
|
input = get_kbinput(edit, meta_key, func_key);
|
|
|
|
|
else
|
|
|
|
|
input = ERR;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Check for a shortcut in the main list. */
|
|
|
|
|
s = get_shortcut(main_list, &input, meta_key, func_key);
|
|
|
|
|
|
|
|
|
|
/* If we got a shortcut from the main list, or a "universal"
|
|
|
|
|
* edit window shortcut, set have_shortcut to TRUE. */
|
|
|
|
|
have_shortcut = (s != NULL || input == NANO_XON_KEY ||
|
|
|
|
|
input == NANO_XOFF_KEY || input == NANO_SUSPEND_KEY);
|
|
|
|
|
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
/* Check for a toggle in the main list. */
|
|
|
|
|
t = get_toggle(input, *meta_key);
|
|
|
|
|
|
|
|
|
|
/* If we got a toggle from the main list, set have_toggle to
|
|
|
|
|
* TRUE. */
|
|
|
|
|
have_toggle = (t != NULL);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Set s_or_t to TRUE if we got a shortcut or toggle. */
|
|
|
|
|
*s_or_t = (have_shortcut
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
|| have_toggle
|
|
|
|
|
#endif
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (allow_funcs) {
|
2005-03-17 06:52:08 +03:00
|
|
|
|
/* If we got a character, and it isn't a shortcut or toggle,
|
|
|
|
|
* it's a normal text character. Display the warning if we're
|
|
|
|
|
* in view mode, or add the character to the input buffer if
|
|
|
|
|
* we're not. */
|
|
|
|
|
if (input != ERR && *s_or_t == FALSE) {
|
2004-12-04 20:41:52 +03:00
|
|
|
|
if (ISSET(VIEW_MODE))
|
|
|
|
|
print_view_warning();
|
|
|
|
|
else {
|
|
|
|
|
kbinput_len++;
|
|
|
|
|
kbinput = (int *)nrealloc(kbinput, kbinput_len *
|
|
|
|
|
sizeof(int));
|
|
|
|
|
kbinput[kbinput_len - 1] = input;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If we got a shortcut or toggle, or if there aren't any other
|
|
|
|
|
* characters waiting after the one we read in, we need to
|
|
|
|
|
* display all the characters in the input buffer if it isn't
|
|
|
|
|
* empty. Note that it should be empty if we're in view
|
|
|
|
|
* mode. */
|
|
|
|
|
if (*s_or_t == TRUE || get_buffer_len() == 0) {
|
|
|
|
|
if (kbinput != NULL) {
|
|
|
|
|
/* Display all the characters in the input buffer at
|
2005-03-17 06:52:08 +03:00
|
|
|
|
* once, filtering out control characters. */
|
2005-01-12 06:25:57 +03:00
|
|
|
|
char *output = charalloc(kbinput_len + 1);
|
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < kbinput_len; i++)
|
|
|
|
|
output[i] = (char)kbinput[i];
|
|
|
|
|
output[i] = '\0';
|
|
|
|
|
|
2005-03-17 06:52:08 +03:00
|
|
|
|
do_output(output, kbinput_len, FALSE);
|
2005-01-12 06:25:57 +03:00
|
|
|
|
|
|
|
|
|
free(output);
|
2004-12-04 20:41:52 +03:00
|
|
|
|
|
|
|
|
|
/* Empty the input buffer. */
|
|
|
|
|
kbinput_len = 0;
|
|
|
|
|
free(kbinput);
|
|
|
|
|
kbinput = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (have_shortcut) {
|
|
|
|
|
switch (input) {
|
2005-01-12 02:08:36 +03:00
|
|
|
|
/* Handle the "universal" statusbar prompt shortcuts. */
|
2004-12-04 20:41:52 +03:00
|
|
|
|
case NANO_XON_KEY:
|
|
|
|
|
statusbar(_("XON ignored, mumble mumble."));
|
|
|
|
|
break;
|
|
|
|
|
case NANO_XOFF_KEY:
|
|
|
|
|
statusbar(_("XOFF ignored, mumble mumble."));
|
|
|
|
|
break;
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
case NANO_SUSPEND_KEY:
|
|
|
|
|
if (ISSET(SUSPEND))
|
|
|
|
|
do_suspend(0);
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
2005-01-01 10:28:15 +03:00
|
|
|
|
/* Handle the normal edit window shortcuts, setting
|
2005-01-12 02:05:05 +03:00
|
|
|
|
* ran_func to TRUE if we try to run their associated
|
|
|
|
|
* functions and setting finished to TRUE to indicate
|
|
|
|
|
* that we're done after trying to run their associated
|
2005-01-01 10:28:15 +03:00
|
|
|
|
* functions. */
|
2004-12-04 20:41:52 +03:00
|
|
|
|
default:
|
|
|
|
|
/* Blow away the text in the cutbuffer if we aren't
|
|
|
|
|
* cutting text. */
|
|
|
|
|
if (s->func != do_cut_text)
|
|
|
|
|
cutbuffer_reset();
|
|
|
|
|
|
2004-12-20 04:13:55 +03:00
|
|
|
|
if (s->func != NULL) {
|
2005-01-12 02:05:05 +03:00
|
|
|
|
*ran_func = TRUE;
|
2004-12-20 04:13:55 +03:00
|
|
|
|
if (ISSET(VIEW_MODE) && !s->viewok)
|
|
|
|
|
print_view_warning();
|
|
|
|
|
else
|
|
|
|
|
s->func();
|
2004-12-04 20:41:52 +03:00
|
|
|
|
}
|
2005-01-01 10:28:15 +03:00
|
|
|
|
*finished = TRUE;
|
2004-12-04 20:41:52 +03:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
else if (have_toggle) {
|
|
|
|
|
/* Blow away the text in the cutbuffer, since we aren't
|
|
|
|
|
* cutting text. */
|
|
|
|
|
cutbuffer_reset();
|
|
|
|
|
/* Toggle the flag associated with this shortcut. */
|
|
|
|
|
if (allow_funcs)
|
|
|
|
|
do_toggle(t);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
else
|
|
|
|
|
/* Blow away the text in the cutbuffer, since we aren't
|
|
|
|
|
* cutting text. */
|
|
|
|
|
cutbuffer_reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return input;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef DISABLE_MOUSE
|
|
|
|
|
bool do_mouse(void)
|
|
|
|
|
{
|
|
|
|
|
int mouse_x, mouse_y;
|
|
|
|
|
bool retval;
|
|
|
|
|
|
|
|
|
|
retval = get_mouseinput(&mouse_x, &mouse_y, TRUE);
|
|
|
|
|
|
|
|
|
|
if (!retval) {
|
|
|
|
|
/* We can click in the edit window to move the cursor. */
|
|
|
|
|
if (wenclose(edit, mouse_y, mouse_x)) {
|
|
|
|
|
bool sameline;
|
|
|
|
|
/* Did they click on the line with the cursor? If they
|
|
|
|
|
* clicked on the cursor, we set the mark. */
|
|
|
|
|
size_t xcur;
|
|
|
|
|
/* The character they clicked on. */
|
|
|
|
|
|
2005-06-15 11:38:25 +04:00
|
|
|
|
/* Subtract out the size of topwin. */
|
2005-06-15 11:34:09 +04:00
|
|
|
|
mouse_y -= 2 - no_more_space();
|
2004-12-04 20:41:52 +03:00
|
|
|
|
|
|
|
|
|
sameline = (mouse_y == current_y);
|
|
|
|
|
|
|
|
|
|
/* Move to where the click occurred. */
|
|
|
|
|
for (; current_y < mouse_y && current->next != NULL; current_y++)
|
|
|
|
|
current = current->next;
|
|
|
|
|
for (; current_y > mouse_y && current->prev != NULL; current_y--)
|
|
|
|
|
current = current->prev;
|
|
|
|
|
|
|
|
|
|
xcur = actual_x(current->data, get_page_start(xplustabs()) +
|
|
|
|
|
mouse_x);
|
|
|
|
|
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
/* Clicking where the cursor is toggles the mark, as does
|
|
|
|
|
* clicking beyond the line length with the cursor at the
|
|
|
|
|
* end of the line. */
|
|
|
|
|
if (sameline && xcur == current_x) {
|
|
|
|
|
if (ISSET(VIEW_MODE)) {
|
|
|
|
|
print_view_warning();
|
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
do_mark();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
current_x = xcur;
|
|
|
|
|
placewewant = xplustabs();
|
|
|
|
|
edit_refresh();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
#endif /* !DISABLE_MOUSE */
|
|
|
|
|
|
2005-06-26 00:56:36 +04:00
|
|
|
|
/* The user typed ouuput_len multibyte characters. Add them to the edit
|
|
|
|
|
* buffer, filtering out all control characters if allow_cntrls is
|
2005-03-17 06:52:08 +03:00
|
|
|
|
* TRUE. */
|
|
|
|
|
void do_output(char *output, size_t output_len, bool allow_cntrls)
|
2004-12-04 20:41:52 +03:00
|
|
|
|
{
|
2005-05-26 09:17:13 +04:00
|
|
|
|
size_t current_len, i = 0;
|
2005-06-18 01:08:13 +04:00
|
|
|
|
bool old_const_update = ISSET(CONST_UPDATE);
|
2004-12-04 20:41:52 +03:00
|
|
|
|
bool do_refresh = FALSE;
|
|
|
|
|
/* Do we have to call edit_refresh(), or can we get away with
|
|
|
|
|
* update_line()? */
|
|
|
|
|
|
2005-01-12 06:25:57 +03:00
|
|
|
|
char *char_buf = charalloc(mb_cur_max());
|
|
|
|
|
int char_buf_len;
|
2004-12-04 20:41:52 +03:00
|
|
|
|
|
|
|
|
|
assert(current != NULL && current->data != NULL);
|
|
|
|
|
|
2005-05-26 09:17:13 +04:00
|
|
|
|
current_len = strlen(current->data);
|
|
|
|
|
|
2004-12-05 07:18:26 +03:00
|
|
|
|
/* Turn off constant cursor position display. */
|
2005-06-18 01:08:13 +04:00
|
|
|
|
UNSET(CONST_UPDATE);
|
2004-12-04 20:41:52 +03:00
|
|
|
|
|
2005-01-12 06:25:57 +03:00
|
|
|
|
while (i < output_len) {
|
2005-03-17 06:52:08 +03:00
|
|
|
|
/* If allow_cntrls is FALSE, filter out nulls and newlines,
|
|
|
|
|
* since they're control characters. */
|
|
|
|
|
if (allow_cntrls) {
|
|
|
|
|
/* Null to newline, if needed. */
|
|
|
|
|
if (output[i] == '\0')
|
|
|
|
|
output[i] = '\n';
|
|
|
|
|
/* Newline to Enter, if needed. */
|
|
|
|
|
else if (output[i] == '\n') {
|
|
|
|
|
do_enter();
|
|
|
|
|
i++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2004-12-09 02:24:31 +03:00
|
|
|
|
}
|
|
|
|
|
|
2005-01-12 06:25:57 +03:00
|
|
|
|
/* Interpret the next multibyte character. If it's an invalid
|
|
|
|
|
* multibyte character, interpret it as though it's a byte
|
|
|
|
|
* character. */
|
2005-02-11 23:09:11 +03:00
|
|
|
|
char_buf_len = parse_mbchar(output + i, char_buf, NULL, NULL);
|
2005-01-12 06:25:57 +03:00
|
|
|
|
|
|
|
|
|
i += char_buf_len;
|
2004-12-04 20:41:52 +03:00
|
|
|
|
|
2005-03-17 06:52:08 +03:00
|
|
|
|
/* If allow_cntrls is FALSE, filter out a control character. */
|
|
|
|
|
if (!allow_cntrls && is_cntrl_mbchar(output + i - char_buf_len))
|
|
|
|
|
continue;
|
|
|
|
|
|
2004-12-04 20:41:52 +03:00
|
|
|
|
/* When a character is inserted on the current magicline, it
|
|
|
|
|
* means we need a new one! */
|
|
|
|
|
if (filebot == current)
|
|
|
|
|
new_magicline();
|
|
|
|
|
|
|
|
|
|
/* More dangerousness fun =) */
|
2005-01-12 06:25:57 +03:00
|
|
|
|
current->data = charealloc(current->data, current_len +
|
|
|
|
|
(char_buf_len * 2));
|
2004-12-31 07:10:28 +03:00
|
|
|
|
|
2004-12-04 20:41:52 +03:00
|
|
|
|
assert(current_x <= current_len);
|
2004-12-31 07:10:28 +03:00
|
|
|
|
|
2005-01-12 06:25:57 +03:00
|
|
|
|
charmove(¤t->data[current_x + char_buf_len],
|
2004-12-04 20:41:52 +03:00
|
|
|
|
¤t->data[current_x],
|
2005-01-12 06:25:57 +03:00
|
|
|
|
current_len - current_x + char_buf_len);
|
2005-06-22 04:24:11 +04:00
|
|
|
|
strncpy(¤t->data[current_x], char_buf, char_buf_len);
|
2005-01-12 06:25:57 +03:00
|
|
|
|
current_len += char_buf_len;
|
2005-01-27 23:49:07 +03:00
|
|
|
|
totsize++;
|
2004-12-04 20:41:52 +03:00
|
|
|
|
set_modified();
|
|
|
|
|
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
/* Note that current_x has not yet been incremented. */
|
|
|
|
|
if (current == mark_beginbuf && current_x < mark_beginx)
|
2005-01-12 06:25:57 +03:00
|
|
|
|
mark_beginx += char_buf_len;
|
2004-12-04 20:41:52 +03:00
|
|
|
|
#endif
|
|
|
|
|
|
2004-12-23 20:43:27 +03:00
|
|
|
|
do_right(FALSE);
|
2004-12-04 20:41:52 +03:00
|
|
|
|
|
|
|
|
|
#ifndef DISABLE_WRAPPING
|
2005-04-26 21:21:47 +04:00
|
|
|
|
/* If we're wrapping text, we need to call edit_refresh(). */
|
|
|
|
|
if (!ISSET(NO_WRAP)) {
|
2004-12-04 20:41:52 +03:00
|
|
|
|
bool do_refresh_save = do_refresh;
|
|
|
|
|
|
|
|
|
|
do_refresh = do_wrap(current);
|
|
|
|
|
|
|
|
|
|
/* If we needed to call edit_refresh() before this, we'll
|
|
|
|
|
* still need to after this. */
|
|
|
|
|
if (do_refresh_save)
|
|
|
|
|
do_refresh = TRUE;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef ENABLE_COLOR
|
|
|
|
|
/* If color syntaxes are turned on, we need to call
|
|
|
|
|
* edit_refresh(). */
|
2005-03-10 23:55:11 +03:00
|
|
|
|
if (!ISSET(NO_COLOR_SYNTAX))
|
2004-12-04 20:41:52 +03:00
|
|
|
|
do_refresh = TRUE;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-05 07:18:26 +03:00
|
|
|
|
/* Turn constant cursor position display back on if it was on
|
|
|
|
|
* before. */
|
2005-06-18 01:08:13 +04:00
|
|
|
|
if (old_const_update)
|
|
|
|
|
SET(CONST_UPDATE);
|
2004-12-04 20:41:52 +03:00
|
|
|
|
|
2005-01-12 06:25:57 +03:00
|
|
|
|
free(char_buf);
|
2004-12-12 22:04:56 +03:00
|
|
|
|
|
2004-12-04 20:41:52 +03:00
|
|
|
|
if (do_refresh)
|
|
|
|
|
edit_refresh();
|
|
|
|
|
else
|
|
|
|
|
update_line(current, current_x);
|
|
|
|
|
}
|
|
|
|
|
|
2004-08-17 09:23:38 +04:00
|
|
|
|
int main(int argc, char **argv)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
{
|
|
|
|
|
int optchr;
|
2005-05-16 22:38:16 +04:00
|
|
|
|
int startline = 1;
|
2004-09-06 01:40:31 +04:00
|
|
|
|
/* Line to try and start at. */
|
2005-05-16 22:38:16 +04:00
|
|
|
|
ssize_t startcol = 1;
|
|
|
|
|
/* Column to try and start at. */
|
2004-08-12 23:48:21 +04:00
|
|
|
|
#ifndef DISABLE_WRAPJUSTIFY
|
2004-09-06 01:40:31 +04:00
|
|
|
|
bool fill_flag_used = FALSE;
|
|
|
|
|
/* Was the fill option used? */
|
2004-08-12 23:48:21 +04:00
|
|
|
|
#endif
|
2004-09-06 01:40:31 +04:00
|
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
|
|
|
|
bool old_multibuffer;
|
|
|
|
|
/* The old value of the multibuffer option, restored after we
|
|
|
|
|
* load all files on the command line. */
|
|
|
|
|
#endif
|
2000-06-06 09:53:49 +04:00
|
|
|
|
#ifdef HAVE_GETOPT_LONG
|
2002-12-22 19:30:00 +03:00
|
|
|
|
const struct option long_options[] = {
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{"help", 0, NULL, 'h'},
|
2002-06-29 02:45:14 +04:00
|
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{"multibuffer", 0, NULL, 'F'},
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#endif
|
|
|
|
|
#ifdef ENABLE_NANORC
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{"ignorercfiles", 0, NULL, 'I'},
|
2002-06-29 02:45:14 +04:00
|
|
|
|
#endif
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{"morespace", 0, NULL, 'O'},
|
2002-06-29 02:45:14 +04:00
|
|
|
|
#ifndef DISABLE_JUSTIFY
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{"quotestr", 1, NULL, 'Q'},
|
2000-07-07 06:35:34 +04:00
|
|
|
|
#endif
|
2005-06-18 02:53:41 +04:00
|
|
|
|
{"restricted", 0, NULL, 'R'},
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{"tabsize", 1, NULL, 'T'},
|
|
|
|
|
{"version", 0, NULL, 'V'},
|
2002-06-29 02:45:14 +04:00
|
|
|
|
#ifdef ENABLE_COLOR
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{"syntax", 1, NULL, 'Y'},
|
2001-05-21 16:56:25 +04:00
|
|
|
|
#endif
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{"const", 0, NULL, 'c'},
|
|
|
|
|
{"rebinddelete", 0, NULL, 'd'},
|
|
|
|
|
{"nofollow", 0, NULL, 'l'},
|
2003-10-04 00:26:25 +04:00
|
|
|
|
#ifndef DISABLE_MOUSE
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{"mouse", 0, NULL, 'm'},
|
2002-12-22 19:30:00 +03:00
|
|
|
|
#endif
|
2001-09-19 07:19:43 +04:00
|
|
|
|
#ifndef DISABLE_OPERATINGDIR
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{"operatingdir", 1, NULL, 'o'},
|
2001-09-19 07:19:43 +04:00
|
|
|
|
#endif
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{"preserve", 0, NULL, 'p'},
|
2002-06-29 02:45:14 +04:00
|
|
|
|
#ifndef DISABLE_WRAPJUSTIFY
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{"fill", 1, NULL, 'r'},
|
2002-06-29 02:45:14 +04:00
|
|
|
|
#endif
|
|
|
|
|
#ifndef DISABLE_SPELLER
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{"speller", 1, NULL, 's'},
|
2001-07-11 06:08:33 +04:00
|
|
|
|
#endif
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{"tempfile", 0, NULL, 't'},
|
|
|
|
|
{"view", 0, NULL, 'v'},
|
2002-10-17 06:19:31 +04:00
|
|
|
|
#ifndef DISABLE_WRAPPING
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{"nowrap", 0, NULL, 'w'},
|
2002-10-17 06:19:31 +04:00
|
|
|
|
#endif
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{"nohelp", 0, NULL, 'x'},
|
|
|
|
|
{"suspend", 0, NULL, 'z'},
|
2001-09-22 23:02:04 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{"smarthome", 0, NULL, 'A'},
|
|
|
|
|
{"backup", 0, NULL, 'B'},
|
2005-06-16 03:20:56 +04:00
|
|
|
|
{"backupdir", 1, NULL, 'C'},
|
|
|
|
|
{"tabstospaces", 0, NULL, 'E'},
|
2005-06-17 21:37:46 +04:00
|
|
|
|
{"historylog", 0, NULL, 'H'},
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{"noconvert", 0, NULL, 'N'},
|
|
|
|
|
{"smooth", 0, NULL, 'S'},
|
2005-06-17 23:06:25 +04:00
|
|
|
|
{"quickblank", 0, NULL, 'U'},
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{"autoindent", 0, NULL, 'i'},
|
|
|
|
|
{"cut", 0, NULL, 'k'},
|
2002-05-04 08:23:30 +04:00
|
|
|
|
#endif
|
2005-03-27 01:49:08 +03:00
|
|
|
|
{NULL, 0, NULL, 0}
|
2000-06-06 09:53:49 +04:00
|
|
|
|
};
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-12-23 20:43:27 +03:00
|
|
|
|
#ifdef NANO_WIDE
|
|
|
|
|
{
|
2005-06-16 06:09:57 +04:00
|
|
|
|
/* If the locale set exists and includes the case-insensitive
|
|
|
|
|
* string "UTF8" or "UTF-8", we should use UTF-8. */
|
2004-12-23 20:43:27 +03:00
|
|
|
|
char *locale = setlocale(LC_ALL, "");
|
|
|
|
|
|
2005-06-16 06:09:57 +04:00
|
|
|
|
if (locale != NULL && (strcasestr(locale, "UTF8") != NULL ||
|
|
|
|
|
strcasestr(locale, "UTF-8") != NULL)) {
|
|
|
|
|
SET(USE_UTF8);
|
2005-01-28 22:37:23 +03:00
|
|
|
|
#ifdef USE_SLANG
|
2005-03-11 20:46:01 +03:00
|
|
|
|
SLutf8_enable(TRUE);
|
2005-01-28 22:37:23 +03:00
|
|
|
|
#endif
|
2005-06-16 06:09:57 +04:00
|
|
|
|
}
|
2004-12-23 20:43:27 +03:00
|
|
|
|
}
|
|
|
|
|
#else
|
2000-06-06 09:53:49 +04:00
|
|
|
|
setlocale(LC_ALL, "");
|
2004-12-23 20:43:27 +03:00
|
|
|
|
#endif
|
|
|
|
|
|
2004-07-27 19:46:58 +04:00
|
|
|
|
#ifdef ENABLE_NLS
|
2000-06-06 09:53:49 +04:00
|
|
|
|
bindtextdomain(PACKAGE, LOCALEDIR);
|
|
|
|
|
textdomain(PACKAGE);
|
|
|
|
|
#endif
|
|
|
|
|
|
2003-01-13 04:35:15 +03:00
|
|
|
|
#if !defined(ENABLE_NANORC) && defined(DISABLE_ROOTWRAP) && !defined(DISABLE_WRAPPING)
|
2004-09-06 01:40:31 +04:00
|
|
|
|
/* If we don't have rcfile support, we're root, and
|
|
|
|
|
* --disable-wrapping-as-root is used, turn wrapping off. */
|
2004-03-04 09:33:52 +03:00
|
|
|
|
if (geteuid() == NANO_ROOT_UID)
|
2002-10-25 20:08:53 +04:00
|
|
|
|
SET(NO_WRAP);
|
|
|
|
|
#endif
|
2001-04-18 08:28:54 +04:00
|
|
|
|
|
2004-08-08 02:00:02 +04:00
|
|
|
|
while ((optchr =
|
2000-06-06 09:53:49 +04:00
|
|
|
|
#ifdef HAVE_GETOPT_LONG
|
2005-06-12 20:13:44 +04:00
|
|
|
|
getopt_long(argc, argv,
|
2005-06-18 02:53:41 +04:00
|
|
|
|
"h?ABC:EFHINOQ:RST:UVY:abcdefgijklmo:pr:s:tvwxz",
|
2005-06-12 20:13:44 +04:00
|
|
|
|
long_options, NULL)
|
2000-06-06 09:53:49 +04:00
|
|
|
|
#else
|
2005-06-12 20:13:44 +04:00
|
|
|
|
getopt(argc, argv,
|
2005-06-18 02:53:41 +04:00
|
|
|
|
"h?ABC:EFHINOQ:RST:UVY:abcdefgijklmo:pr:s:tvwxz")
|
2000-06-06 09:53:49 +04:00
|
|
|
|
#endif
|
2004-08-08 02:00:02 +04:00
|
|
|
|
) != -1) {
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
|
|
|
|
switch (optchr) {
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'a':
|
|
|
|
|
case 'b':
|
|
|
|
|
case 'e':
|
|
|
|
|
case 'f':
|
|
|
|
|
case 'g':
|
|
|
|
|
case 'j':
|
|
|
|
|
/* Pico compatibility flags. */
|
|
|
|
|
break;
|
2001-09-22 04:42:10 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'A':
|
|
|
|
|
SET(SMART_HOME);
|
|
|
|
|
break;
|
|
|
|
|
case 'B':
|
|
|
|
|
SET(BACKUP_FILE);
|
|
|
|
|
break;
|
2005-06-16 03:20:56 +04:00
|
|
|
|
case 'C':
|
2004-08-08 02:00:02 +04:00
|
|
|
|
backup_dir = mallocstrcpy(backup_dir, optarg);
|
|
|
|
|
break;
|
2005-06-16 03:20:56 +04:00
|
|
|
|
case 'E':
|
|
|
|
|
SET(TABS_TO_SPACES);
|
|
|
|
|
break;
|
2001-09-22 04:42:10 +04:00
|
|
|
|
#endif
|
2001-07-14 23:32:47 +04:00
|
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'F':
|
|
|
|
|
SET(MULTIBUFFER);
|
|
|
|
|
break;
|
2002-07-19 05:08:59 +04:00
|
|
|
|
#endif
|
|
|
|
|
#ifdef ENABLE_NANORC
|
2003-09-07 01:44:37 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'H':
|
|
|
|
|
SET(HISTORYLOG);
|
|
|
|
|
break;
|
2003-09-07 01:44:37 +04:00
|
|
|
|
#endif
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'I':
|
|
|
|
|
SET(NO_RCFILE);
|
|
|
|
|
break;
|
2001-07-11 06:08:33 +04:00
|
|
|
|
#endif
|
2001-09-22 08:20:25 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'N':
|
|
|
|
|
SET(NO_CONVERT);
|
|
|
|
|
break;
|
2002-03-04 01:36:36 +03:00
|
|
|
|
#endif
|
2005-01-17 08:06:55 +03:00
|
|
|
|
case 'O':
|
|
|
|
|
SET(MORE_SPACE);
|
|
|
|
|
break;
|
2002-03-04 01:36:36 +03:00
|
|
|
|
#ifndef DISABLE_JUSTIFY
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'Q':
|
|
|
|
|
quotestr = mallocstrcpy(quotestr, optarg);
|
|
|
|
|
break;
|
2002-02-15 22:17:02 +03:00
|
|
|
|
#endif
|
2005-06-18 02:53:41 +04:00
|
|
|
|
case 'R':
|
|
|
|
|
SET(RESTRICTED);
|
|
|
|
|
break;
|
2001-09-22 23:02:04 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'S':
|
2005-06-16 06:13:10 +04:00
|
|
|
|
SET(SMOOTH_SCROLL);
|
2004-08-08 02:00:02 +04:00
|
|
|
|
break;
|
2000-07-07 06:35:34 +04:00
|
|
|
|
#endif
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'T':
|
|
|
|
|
if (!parse_num(optarg, &tabsize) || tabsize <= 0) {
|
2004-08-11 09:13:08 +04:00
|
|
|
|
fprintf(stderr, _("Requested tab size %s invalid"), optarg);
|
|
|
|
|
fprintf(stderr, "\n");
|
2004-08-08 02:00:02 +04:00
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2005-06-17 23:06:25 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
case 'U':
|
|
|
|
|
SET(QUICK_BLANK);
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'V':
|
|
|
|
|
version();
|
|
|
|
|
exit(0);
|
2002-05-04 08:23:30 +04:00
|
|
|
|
#ifdef ENABLE_COLOR
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'Y':
|
|
|
|
|
syntaxstr = mallocstrcpy(syntaxstr, optarg);
|
|
|
|
|
break;
|
2002-05-04 08:23:30 +04:00
|
|
|
|
#endif
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'c':
|
2005-06-18 01:08:13 +04:00
|
|
|
|
SET(CONST_UPDATE);
|
2004-08-08 02:00:02 +04:00
|
|
|
|
break;
|
|
|
|
|
case 'd':
|
|
|
|
|
SET(REBIND_DELETE);
|
|
|
|
|
break;
|
2001-09-17 17:48:00 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'i':
|
|
|
|
|
SET(AUTOINDENT);
|
|
|
|
|
break;
|
|
|
|
|
case 'k':
|
|
|
|
|
SET(CUT_TO_END);
|
|
|
|
|
break;
|
2000-07-12 22:14:51 +04:00
|
|
|
|
#endif
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'l':
|
|
|
|
|
SET(NOFOLLOW_SYMLINKS);
|
|
|
|
|
break;
|
2003-10-04 00:26:25 +04:00
|
|
|
|
#ifndef DISABLE_MOUSE
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'm':
|
|
|
|
|
SET(USE_MOUSE);
|
|
|
|
|
break;
|
2002-12-22 19:30:00 +03:00
|
|
|
|
#endif
|
2001-09-19 07:19:43 +04:00
|
|
|
|
#ifndef DISABLE_OPERATINGDIR
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'o':
|
|
|
|
|
operating_dir = mallocstrcpy(operating_dir, optarg);
|
|
|
|
|
break;
|
2001-09-19 07:19:43 +04:00
|
|
|
|
#endif
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'p':
|
|
|
|
|
SET(PRESERVE);
|
|
|
|
|
break;
|
2001-05-21 16:56:25 +04:00
|
|
|
|
#ifndef DISABLE_WRAPJUSTIFY
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'r':
|
|
|
|
|
if (!parse_num(optarg, &wrap_at)) {
|
2004-08-11 09:13:08 +04:00
|
|
|
|
fprintf(stderr, _("Requested fill size %s invalid"), optarg);
|
|
|
|
|
fprintf(stderr, "\n");
|
2004-08-08 02:00:02 +04:00
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
fill_flag_used = TRUE;
|
|
|
|
|
break;
|
2001-05-21 16:56:25 +04:00
|
|
|
|
#endif
|
2001-01-12 10:51:05 +03:00
|
|
|
|
#ifndef DISABLE_SPELLER
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 's':
|
|
|
|
|
alt_speller = mallocstrcpy(alt_speller, optarg);
|
|
|
|
|
break;
|
2001-01-12 10:51:05 +03:00
|
|
|
|
#endif
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 't':
|
|
|
|
|
SET(TEMP_FILE);
|
|
|
|
|
break;
|
|
|
|
|
case 'v':
|
|
|
|
|
SET(VIEW_MODE);
|
|
|
|
|
break;
|
2003-01-02 19:32:20 +03:00
|
|
|
|
#ifndef DISABLE_WRAPPING
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'w':
|
|
|
|
|
SET(NO_WRAP);
|
|
|
|
|
break;
|
2002-12-22 19:30:00 +03:00
|
|
|
|
#endif
|
2004-08-08 02:00:02 +04:00
|
|
|
|
case 'x':
|
|
|
|
|
SET(NO_HELP);
|
|
|
|
|
break;
|
|
|
|
|
case 'z':
|
|
|
|
|
SET(SUSPEND);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
usage();
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-29 05:20:17 +04:00
|
|
|
|
/* If the executable filename starts with 'r', we use restricted
|
|
|
|
|
* mode. */
|
2004-04-30 08:49:02 +04:00
|
|
|
|
if (*(tail(argv[0])) == 'r')
|
|
|
|
|
SET(RESTRICTED);
|
|
|
|
|
|
2004-05-29 05:20:17 +04:00
|
|
|
|
/* If we're using restricted mode, disable suspending, backups, and
|
|
|
|
|
* reading rcfiles, since they all would allow reading from or
|
|
|
|
|
* writing to files not specified on the command line. */
|
2004-04-30 08:49:02 +04:00
|
|
|
|
if (ISSET(RESTRICTED)) {
|
|
|
|
|
UNSET(SUSPEND);
|
|
|
|
|
UNSET(BACKUP_FILE);
|
|
|
|
|
SET(NO_RCFILE);
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-13 04:35:15 +03:00
|
|
|
|
/* We've read through the command line options. Now back up the flags
|
2004-09-06 01:40:31 +04:00
|
|
|
|
* and values that are set, and read the rcfile(s). If the values
|
|
|
|
|
* haven't changed afterward, restore the backed-up values. */
|
2003-01-13 04:35:15 +03:00
|
|
|
|
#ifdef ENABLE_NANORC
|
|
|
|
|
if (!ISSET(NO_RCFILE)) {
|
|
|
|
|
#ifndef DISABLE_OPERATINGDIR
|
|
|
|
|
char *operating_dir_cpy = operating_dir;
|
|
|
|
|
#endif
|
2004-08-13 00:06:20 +04:00
|
|
|
|
#ifndef DISABLE_WRAPJUSTIFY
|
2004-07-12 20:07:14 +04:00
|
|
|
|
ssize_t wrap_at_cpy = wrap_at;
|
2003-01-13 04:35:15 +03:00
|
|
|
|
#endif
|
2004-02-28 19:24:31 +03:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
char *backup_dir_cpy = backup_dir;
|
|
|
|
|
#endif
|
2003-01-13 04:35:15 +03:00
|
|
|
|
#ifndef DISABLE_JUSTIFY
|
|
|
|
|
char *quotestr_cpy = quotestr;
|
|
|
|
|
#endif
|
|
|
|
|
#ifndef DISABLE_SPELLER
|
|
|
|
|
char *alt_speller_cpy = alt_speller;
|
|
|
|
|
#endif
|
2004-07-12 20:07:14 +04:00
|
|
|
|
ssize_t tabsize_cpy = tabsize;
|
2005-01-27 23:49:07 +03:00
|
|
|
|
unsigned long flags_cpy = flags;
|
2003-01-13 04:35:15 +03:00
|
|
|
|
|
2003-02-05 05:39:34 +03:00
|
|
|
|
#ifndef DISABLE_OPERATINGDIR
|
2003-01-13 04:35:15 +03:00
|
|
|
|
operating_dir = NULL;
|
2003-02-05 05:39:34 +03:00
|
|
|
|
#endif
|
2004-02-28 19:24:31 +03:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
backup_dir = NULL;
|
|
|
|
|
#endif
|
2003-02-05 05:39:34 +03:00
|
|
|
|
#ifndef DISABLE_JUSTIFY
|
2003-01-13 04:35:15 +03:00
|
|
|
|
quotestr = NULL;
|
2003-02-05 05:39:34 +03:00
|
|
|
|
#endif
|
|
|
|
|
#ifndef DISABLE_SPELLER
|
2003-01-13 04:35:15 +03:00
|
|
|
|
alt_speller = NULL;
|
2003-02-05 05:39:34 +03:00
|
|
|
|
#endif
|
2003-01-13 04:35:15 +03:00
|
|
|
|
|
|
|
|
|
do_rcfile();
|
|
|
|
|
|
|
|
|
|
#ifndef DISABLE_OPERATINGDIR
|
|
|
|
|
if (operating_dir_cpy != NULL) {
|
|
|
|
|
free(operating_dir);
|
|
|
|
|
operating_dir = operating_dir_cpy;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2004-08-12 23:48:21 +04:00
|
|
|
|
#ifndef DISABLE_WRAPJUSTIFY
|
2003-01-13 04:35:15 +03:00
|
|
|
|
if (fill_flag_used)
|
|
|
|
|
wrap_at = wrap_at_cpy;
|
|
|
|
|
#endif
|
2004-02-28 19:24:31 +03:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
if (backup_dir_cpy != NULL) {
|
|
|
|
|
free(backup_dir);
|
|
|
|
|
backup_dir = backup_dir_cpy;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2003-01-13 04:35:15 +03:00
|
|
|
|
#ifndef DISABLE_JUSTIFY
|
|
|
|
|
if (quotestr_cpy != NULL) {
|
|
|
|
|
free(quotestr);
|
|
|
|
|
quotestr = quotestr_cpy;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
#ifndef DISABLE_SPELLER
|
|
|
|
|
if (alt_speller_cpy != NULL) {
|
|
|
|
|
free(alt_speller);
|
|
|
|
|
alt_speller = alt_speller_cpy;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2004-07-18 22:13:54 +04:00
|
|
|
|
if (tabsize_cpy != -1)
|
2003-01-13 04:35:15 +03:00
|
|
|
|
tabsize = tabsize_cpy;
|
|
|
|
|
flags |= flags_cpy;
|
|
|
|
|
}
|
|
|
|
|
#if defined(DISABLE_ROOTWRAP) && !defined(DISABLE_WRAPPING)
|
2004-03-04 09:33:52 +03:00
|
|
|
|
else if (geteuid() == NANO_ROOT_UID)
|
2003-01-13 04:35:15 +03:00
|
|
|
|
SET(NO_WRAP);
|
|
|
|
|
#endif
|
|
|
|
|
#endif /* ENABLE_NANORC */
|
|
|
|
|
|
2003-03-11 06:50:40 +03:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
history_init();
|
|
|
|
|
#ifdef ENABLE_NANORC
|
|
|
|
|
if (!ISSET(NO_RCFILE) && ISSET(HISTORYLOG))
|
|
|
|
|
load_history();
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-02-28 19:24:31 +03:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-05-29 03:45:25 +04:00
|
|
|
|
/* Set up the backup directory (unless we're using restricted mode,
|
2004-05-29 05:20:17 +04:00
|
|
|
|
* in which case backups are disabled, since they would allow
|
|
|
|
|
* reading from or writing to files not specified on the command
|
|
|
|
|
* line). This entails making sure it exists and is a directory, so
|
|
|
|
|
* that backup files will be saved there. */
|
2004-05-29 03:45:25 +04:00
|
|
|
|
if (!ISSET(RESTRICTED))
|
|
|
|
|
init_backup_dir();
|
2004-02-28 19:24:31 +03:00
|
|
|
|
#endif
|
|
|
|
|
|
2002-09-13 22:14:04 +04:00
|
|
|
|
#ifndef DISABLE_OPERATINGDIR
|
2003-01-13 04:35:15 +03:00
|
|
|
|
/* Set up the operating directory. This entails chdir()ing there,
|
2004-05-29 03:45:25 +04:00
|
|
|
|
* so that file reads and writes will be based there. */
|
2002-09-13 22:14:04 +04:00
|
|
|
|
init_operating_dir();
|
|
|
|
|
#endif
|
|
|
|
|
|
2003-01-13 04:35:15 +03:00
|
|
|
|
#ifndef DISABLE_JUSTIFY
|
2004-05-29 20:38:57 +04:00
|
|
|
|
if (punct == NULL)
|
2004-06-13 01:03:14 +04:00
|
|
|
|
punct = mallocstrcpy(punct, ".?!");
|
2004-05-29 20:38:57 +04:00
|
|
|
|
|
|
|
|
|
if (brackets == NULL)
|
2004-06-13 01:03:14 +04:00
|
|
|
|
brackets = mallocstrcpy(brackets, "'\")}]>");
|
2004-05-29 20:38:57 +04:00
|
|
|
|
|
2003-01-13 04:35:15 +03:00
|
|
|
|
if (quotestr == NULL)
|
2004-06-13 01:03:14 +04:00
|
|
|
|
quotestr = mallocstrcpy(NULL,
|
2003-01-13 04:35:15 +03:00
|
|
|
|
#ifdef HAVE_REGEX_H
|
2004-06-13 01:03:14 +04:00
|
|
|
|
"^([ \t]*[|>:}#])+"
|
2003-01-13 04:35:15 +03:00
|
|
|
|
#else
|
2004-06-13 01:03:14 +04:00
|
|
|
|
"> "
|
2003-01-13 04:35:15 +03:00
|
|
|
|
#endif
|
2004-06-13 01:03:14 +04:00
|
|
|
|
);
|
2004-07-30 07:54:34 +04:00
|
|
|
|
#ifdef HAVE_REGEX_H
|
|
|
|
|
quoterc = regcomp("ereg, quotestr, REG_EXTENDED);
|
|
|
|
|
|
|
|
|
|
if (quoterc == 0) {
|
|
|
|
|
/* We no longer need quotestr, just quotereg. */
|
|
|
|
|
free(quotestr);
|
|
|
|
|
quotestr = NULL;
|
|
|
|
|
} else {
|
|
|
|
|
size_t size = regerror(quoterc, "ereg, NULL, 0);
|
|
|
|
|
|
|
|
|
|
quoteerr = charalloc(size);
|
|
|
|
|
regerror(quoterc, "ereg, quoteerr, size);
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
quotelen = strlen(quotestr);
|
|
|
|
|
#endif /* !HAVE_REGEX_H */
|
2003-01-13 04:35:15 +03:00
|
|
|
|
#endif /* !DISABLE_JUSTIFY */
|
2004-02-28 19:24:31 +03:00
|
|
|
|
|
2004-05-29 02:42:41 +04:00
|
|
|
|
#ifndef DISABLE_SPELLER
|
|
|
|
|
/* If we don't have an alternative spell checker after reading the
|
2004-05-29 05:20:17 +04:00
|
|
|
|
* command line and/or rcfile(s), check $SPELL for one, as Pico
|
2004-05-29 03:45:25 +04:00
|
|
|
|
* does (unless we're using restricted mode, in which case spell
|
2004-05-29 05:20:17 +04:00
|
|
|
|
* checking is disabled, since it would allow reading from or
|
|
|
|
|
* writing to files not specified on the command line). */
|
2004-05-29 03:45:25 +04:00
|
|
|
|
if (!ISSET(RESTRICTED) && alt_speller == NULL) {
|
2004-05-29 02:42:41 +04:00
|
|
|
|
char *spellenv = getenv("SPELL");
|
|
|
|
|
if (spellenv != NULL)
|
|
|
|
|
alt_speller = mallocstrcpy(NULL, spellenv);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-05-29 20:25:30 +04:00
|
|
|
|
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
|
2004-09-06 01:40:31 +04:00
|
|
|
|
/* If whitespace wasn't specified, set its default value. */
|
2005-03-11 01:52:21 +03:00
|
|
|
|
if (whitespace == NULL) {
|
2004-05-29 20:25:30 +04:00
|
|
|
|
whitespace = mallocstrcpy(NULL, " ");
|
2005-03-11 01:52:21 +03:00
|
|
|
|
whitespace_len[0] = 1;
|
|
|
|
|
whitespace_len[1] = 1;
|
|
|
|
|
}
|
2004-05-29 20:25:30 +04:00
|
|
|
|
#endif
|
|
|
|
|
|
2004-09-06 01:40:31 +04:00
|
|
|
|
/* If tabsize wasn't specified, set its default value. */
|
2003-01-13 04:35:15 +03:00
|
|
|
|
if (tabsize == -1)
|
2004-09-06 01:40:31 +04:00
|
|
|
|
tabsize = WIDTH_OF_TAB;
|
2002-06-13 04:40:19 +04:00
|
|
|
|
|
2004-05-18 05:20:36 +04:00
|
|
|
|
/* Back up the old terminal settings so that they can be restored. */
|
2002-03-29 19:00:59 +03:00
|
|
|
|
tcgetattr(0, &oldterm);
|
2002-03-29 18:38:17 +03:00
|
|
|
|
|
2004-09-06 01:40:31 +04:00
|
|
|
|
/* Curses initialization stuff: Start curses and set up the
|
|
|
|
|
* terminal state. */
|
2000-06-06 09:53:49 +04:00
|
|
|
|
initscr();
|
2004-07-27 20:46:35 +04:00
|
|
|
|
terminal_init();
|
2004-01-12 06:28:06 +03:00
|
|
|
|
|
2005-03-21 00:20:47 +03:00
|
|
|
|
/* Turn the cursor on for sure. */
|
|
|
|
|
curs_set(1);
|
|
|
|
|
|
2004-02-16 23:32:40 +03:00
|
|
|
|
/* Set up the global variables and the shortcuts. */
|
2004-07-01 22:59:52 +04:00
|
|
|
|
global_init(FALSE);
|
|
|
|
|
shortcut_init(FALSE);
|
2004-02-16 23:32:40 +03:00
|
|
|
|
|
|
|
|
|
/* Set up the signal handlers. */
|
2002-03-29 19:00:59 +03:00
|
|
|
|
signal_init();
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2003-08-05 23:31:12 +04:00
|
|
|
|
fprintf(stderr, "Main: set up windows\n");
|
2000-06-06 09:53:49 +04:00
|
|
|
|
#endif
|
|
|
|
|
|
2001-11-29 05:42:27 +03:00
|
|
|
|
window_init();
|
2003-10-04 00:26:25 +04:00
|
|
|
|
#ifndef DISABLE_MOUSE
|
2001-11-29 05:42:27 +03:00
|
|
|
|
mouse_init();
|
2002-12-22 19:30:00 +03:00
|
|
|
|
#endif
|
2001-11-29 05:42:27 +03:00
|
|
|
|
|
2000-06-06 09:53:49 +04:00
|
|
|
|
#ifdef DEBUG
|
2003-08-05 23:31:12 +04:00
|
|
|
|
fprintf(stderr, "Main: open file\n");
|
2000-06-06 09:53:49 +04:00
|
|
|
|
#endif
|
2004-09-06 01:40:31 +04:00
|
|
|
|
|
2005-05-16 22:38:16 +04:00
|
|
|
|
/* If there's a +LINE or +LINE,COLUMN flag here, it is the first
|
|
|
|
|
* non-option argument, and it is followed by at least one other
|
|
|
|
|
* argument, the filename it applies to. */
|
2004-10-23 00:25:56 +04:00
|
|
|
|
if (0 < optind && optind < argc - 1 && argv[optind][0] == '+') {
|
2005-05-17 03:23:15 +04:00
|
|
|
|
parse_line_column(&argv[optind][1], &startline, &startcol);
|
2004-10-23 00:25:56 +04:00
|
|
|
|
optind++;
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-13 04:35:15 +03:00
|
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
2004-09-06 01:40:31 +04:00
|
|
|
|
old_multibuffer = ISSET(MULTIBUFFER);
|
|
|
|
|
SET(MULTIBUFFER);
|
|
|
|
|
|
|
|
|
|
/* Read all the files after the first one on the command line into
|
|
|
|
|
* new buffers. */
|
|
|
|
|
{
|
2005-05-16 22:38:16 +04:00
|
|
|
|
int i = optind + 1, iline = 1;
|
|
|
|
|
ssize_t icol = 1;
|
|
|
|
|
|
2004-10-23 00:25:56 +04:00
|
|
|
|
for (; i < argc; i++) {
|
2005-05-16 22:38:16 +04:00
|
|
|
|
/* If there's a +LINE or +LINE,COLUMN flag here, it is
|
|
|
|
|
* followed by at least one other argument, the filename it
|
|
|
|
|
* applies to. */
|
|
|
|
|
if (i < argc - 1 && argv[i][0] == '+' && iline == 1 &&
|
2005-05-17 22:06:26 +04:00
|
|
|
|
icol == 1)
|
2005-05-17 03:23:15 +04:00
|
|
|
|
parse_line_column(&argv[i][1], &iline, &icol);
|
2005-05-17 22:06:26 +04:00
|
|
|
|
else {
|
2004-10-23 00:25:56 +04:00
|
|
|
|
load_buffer(argv[i]);
|
2005-05-16 22:38:16 +04:00
|
|
|
|
|
2005-05-17 22:06:26 +04:00
|
|
|
|
if (iline > 1 || icol > 1) {
|
2005-05-25 22:44:37 +04:00
|
|
|
|
do_gotolinecolumn(iline, icol, FALSE, FALSE, FALSE);
|
2005-05-16 22:38:16 +04:00
|
|
|
|
iline = 1;
|
|
|
|
|
icol = 1;
|
2004-10-23 00:25:56 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-09-06 01:40:31 +04:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Read the first file on the command line into either the current
|
|
|
|
|
* buffer or a new buffer, depending on whether multibuffer mode is
|
|
|
|
|
* enabled. */
|
|
|
|
|
if (optind < argc)
|
|
|
|
|
load_buffer(argv[optind]);
|
|
|
|
|
|
|
|
|
|
/* We didn't open any files if all the command line arguments were
|
|
|
|
|
* invalid files like directories or if there were no command line
|
|
|
|
|
* arguments given. In this case, we have to load a blank buffer.
|
|
|
|
|
* Also, we unset view mode to allow editing. */
|
|
|
|
|
if (filename == NULL) {
|
|
|
|
|
filename = mallocstrcpy(NULL, "");
|
|
|
|
|
new_file();
|
|
|
|
|
UNSET(VIEW_MODE);
|
|
|
|
|
|
|
|
|
|
/* Add this new entry to the open_files structure if we have
|
2005-05-16 23:43:04 +04:00
|
|
|
|
* multibuffer support, or to the main filestruct if we
|
|
|
|
|
* don't. */
|
2004-09-06 01:40:31 +04:00
|
|
|
|
load_file();
|
2003-01-13 04:35:15 +03:00
|
|
|
|
}
|
2004-09-06 01:40:31 +04:00
|
|
|
|
|
|
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
|
|
|
|
if (!old_multibuffer)
|
|
|
|
|
UNSET(MULTIBUFFER);
|
2003-01-13 04:35:15 +03:00
|
|
|
|
#endif
|
2000-06-06 09:53:49 +04:00
|
|
|
|
|
2004-09-06 01:40:31 +04:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
fprintf(stderr, "Main: top and bottom win\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
titlebar(NULL);
|
|
|
|
|
display_main_list();
|
|
|
|
|
|
2005-05-17 22:06:26 +04:00
|
|
|
|
if (startline > 1 || startcol > 1)
|
2005-05-25 22:44:37 +04:00
|
|
|
|
do_gotolinecolumn(startline, startcol, FALSE, FALSE, FALSE);
|
2005-05-16 22:38:16 +04:00
|
|
|
|
|
2004-05-18 05:20:36 +04:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
/* Return here after a SIGWINCH. */
|
2001-04-12 07:01:53 +04:00
|
|
|
|
sigsetjmp(jmpbuf, 1);
|
2004-05-18 05:20:36 +04:00
|
|
|
|
#endif
|
2001-01-30 02:37:54 +03:00
|
|
|
|
|
2000-07-08 18:23:32 +04:00
|
|
|
|
edit_refresh();
|
|
|
|
|
|
2004-03-15 23:26:30 +03:00
|
|
|
|
while (TRUE) {
|
2005-01-12 02:05:05 +03:00
|
|
|
|
bool meta_key, func_key, s_or_t, ran_func, finished;
|
2004-12-04 20:41:52 +03:00
|
|
|
|
|
|
|
|
|
/* Make sure the cursor is in the edit window. */
|
2004-07-13 21:09:24 +04:00
|
|
|
|
reset_cursor();
|
2004-12-04 20:41:52 +03:00
|
|
|
|
|
|
|
|
|
/* If constant cursor position display is on, display the cursor
|
|
|
|
|
* position. */
|
2005-06-18 01:08:13 +04:00
|
|
|
|
if (ISSET(CONST_UPDATE))
|
2004-07-01 23:41:09 +04:00
|
|
|
|
do_cursorpos(TRUE);
|
2003-01-28 04:16:47 +03:00
|
|
|
|
|
2001-04-12 07:01:53 +04:00
|
|
|
|
currshortcut = main_list;
|
|
|
|
|
|
2004-12-04 20:41:52 +03:00
|
|
|
|
/* Read in and interpret characters. */
|
2005-01-12 02:05:05 +03:00
|
|
|
|
do_input(&meta_key, &func_key, &s_or_t, &ran_func, &finished,
|
|
|
|
|
TRUE);
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|
2005-03-04 20:09:41 +03:00
|
|
|
|
|
2004-03-20 00:57:56 +03:00
|
|
|
|
assert(FALSE);
|
2000-06-06 09:53:49 +04:00
|
|
|
|
}
|