2000-06-06 05:53:49 +00:00
|
|
|
/**************************************************************************
|
2016-08-29 15:10:49 +00:00
|
|
|
* nano.c -- This file is part of GNU nano. *
|
2000-06-06 05:53:49 +00:00
|
|
|
* *
|
2017-04-09 10:09:23 +00:00
|
|
|
* Copyright (C) 1999-2011, 2013-2017 Free Software Foundation, Inc. *
|
2017-11-12 09:42:29 +00:00
|
|
|
* Copyright (C) 2014-2017 Benno Schulenberg *
|
2016-08-29 13:14:18 +00:00
|
|
|
* *
|
2016-08-29 15:10:49 +00:00
|
|
|
* GNU nano is free software: you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published *
|
|
|
|
* by the Free Software Foundation, either version 3 of the License, *
|
|
|
|
* or (at your option) any later version. *
|
2000-06-06 05:53:49 +00:00
|
|
|
* *
|
2016-08-29 15:10:49 +00:00
|
|
|
* GNU nano 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 05:53:49 +00:00
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
2016-08-29 15:10:49 +00:00
|
|
|
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
2000-06-06 05:53:49 +00:00
|
|
|
* *
|
|
|
|
**************************************************************************/
|
|
|
|
|
2005-12-08 02:47:10 +00:00
|
|
|
#include "proto.h"
|
2016-05-20 10:59:57 +00:00
|
|
|
#include "revision.h"
|
2001-04-28 18:03:52 +00:00
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
#include <ctype.h>
|
2017-08-06 11:32:44 +00:00
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <getopt.h>
|
|
|
|
#ifndef NANO_TINY
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#endif
|
2008-07-12 02:32:19 +00:00
|
|
|
#ifdef ENABLE_UTF8
|
2007-05-25 14:39:40 +00:00
|
|
|
#include <langinfo.h>
|
2008-07-12 02:32:19 +00:00
|
|
|
#endif
|
2017-08-06 17:32:55 +00:00
|
|
|
#include <locale.h>
|
2017-08-06 11:32:44 +00:00
|
|
|
#include <string.h>
|
2017-02-21 22:04:48 +00:00
|
|
|
#ifdef HAVE_TERMIOS_H
|
2005-12-28 05:01:00 +00:00
|
|
|
#include <termios.h>
|
2017-02-21 22:04:48 +00:00
|
|
|
#endif
|
2017-08-06 11:32:44 +00:00
|
|
|
#include <unistd.h>
|
2006-07-12 18:57:04 +00:00
|
|
|
|
2017-05-01 18:45:07 +00:00
|
|
|
#ifdef ENABLE_MOUSE
|
2007-12-04 20:49:09 +00:00
|
|
|
static int oldinterval = -1;
|
|
|
|
/* Used to store the user's original mouse click interval. */
|
|
|
|
#endif
|
2017-05-08 17:42:44 +00:00
|
|
|
#ifdef ENABLE_NANORC
|
2006-04-24 18:54:29 +00:00
|
|
|
static bool no_rcfiles = FALSE;
|
|
|
|
/* Should we ignore all rcfiles? */
|
|
|
|
#endif
|
2017-02-21 22:04:48 +00:00
|
|
|
#ifdef HAVE_TERMIOS_H
|
2005-12-08 07:09:08 +00:00
|
|
|
static struct termios oldterm;
|
2017-04-19 15:38:34 +00:00
|
|
|
/* The user's original terminal settings. */
|
2017-02-21 22:04:48 +00:00
|
|
|
#else
|
|
|
|
# define tcsetattr(...)
|
|
|
|
# define tcgetattr(...)
|
|
|
|
#endif
|
2005-12-08 07:09:08 +00:00
|
|
|
static struct sigaction act;
|
2007-01-01 05:15:32 +00:00
|
|
|
/* Used to set up all our fun signal handlers. */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2017-06-23 07:27:29 +00:00
|
|
|
static bool input_was_aborted = FALSE;
|
|
|
|
/* Whether reading from standard input was aborted via ^C. */
|
|
|
|
|
2017-04-19 15:38:34 +00:00
|
|
|
/* Create a new linestruct node. Note that we do not set prevnode->next
|
2006-08-29 21:18:24 +00:00
|
|
|
* to the new line. */
|
2005-07-08 02:47:05 +00:00
|
|
|
filestruct *make_new_node(filestruct *prevnode)
|
2005-01-19 19:52:42 +00:00
|
|
|
{
|
2017-04-19 15:38:34 +00:00
|
|
|
filestruct *newnode = nmalloc(sizeof(filestruct));
|
2005-07-08 02:47:05 +00:00
|
|
|
|
|
|
|
newnode->data = NULL;
|
|
|
|
newnode->prev = prevnode;
|
|
|
|
newnode->next = NULL;
|
|
|
|
newnode->lineno = (prevnode != NULL) ? prevnode->lineno + 1 : 1;
|
|
|
|
|
2017-11-01 18:45:33 +00:00
|
|
|
#ifdef ENABLE_COLOR
|
2009-02-03 05:05:58 +00:00
|
|
|
newnode->multidata = NULL;
|
2009-01-19 19:10:39 +00:00
|
|
|
#endif
|
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
return newnode;
|
2005-01-19 19:52:42 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 15:38:34 +00:00
|
|
|
/* Make a copy of a linestruct node. */
|
2005-07-08 02:47:05 +00:00
|
|
|
filestruct *copy_node(const filestruct *src)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2017-04-19 15:38:34 +00:00
|
|
|
filestruct *dst = nmalloc(sizeof(filestruct));
|
2003-03-11 03:50:40 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
dst->data = mallocstrcpy(NULL, src->data);
|
|
|
|
dst->next = src->next;
|
|
|
|
dst->prev = src->prev;
|
|
|
|
dst->lineno = src->lineno;
|
2017-04-19 15:38:34 +00:00
|
|
|
|
2017-11-01 18:45:33 +00:00
|
|
|
#ifdef ENABLE_COLOR
|
2009-02-03 05:05:58 +00:00
|
|
|
dst->multidata = NULL;
|
2009-01-25 07:25:17 +00:00
|
|
|
#endif
|
2002-02-27 04:14:16 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
return dst;
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 15:38:34 +00:00
|
|
|
/* Splice a new node into an existing linked list of linestructs. */
|
2015-11-24 13:28:32 +00:00
|
|
|
void splice_node(filestruct *afterthis, filestruct *newnode)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2015-11-24 13:28:32 +00:00
|
|
|
newnode->next = afterthis->next;
|
|
|
|
newnode->prev = afterthis;
|
|
|
|
if (afterthis->next != NULL)
|
|
|
|
afterthis->next->prev = newnode;
|
|
|
|
afterthis->next = newnode;
|
2015-12-08 15:29:56 +00:00
|
|
|
|
|
|
|
/* Update filebot when inserting a node at the end of file. */
|
|
|
|
if (openfile && openfile->filebot == afterthis)
|
|
|
|
openfile->filebot = newnode;
|
2005-07-08 02:47:05 +00:00
|
|
|
}
|
2001-07-11 02:08:33 +00:00
|
|
|
|
2017-04-19 15:38:34 +00:00
|
|
|
/* Disconnect a node from a linked list of linestructs and delete it. */
|
2015-11-22 16:14:42 +00:00
|
|
|
void unlink_node(filestruct *fileptr)
|
2005-07-08 02:47:05 +00:00
|
|
|
{
|
|
|
|
if (fileptr->prev != NULL)
|
|
|
|
fileptr->prev->next = fileptr->next;
|
|
|
|
if (fileptr->next != NULL)
|
|
|
|
fileptr->next->prev = fileptr->prev;
|
2015-11-22 16:14:42 +00:00
|
|
|
|
2015-12-08 16:02:05 +00:00
|
|
|
/* Update filebot when removing a node at the end of file. */
|
|
|
|
if (openfile && openfile->filebot == fileptr)
|
|
|
|
openfile->filebot = fileptr->prev;
|
|
|
|
|
2015-11-22 16:14:42 +00:00
|
|
|
delete_node(fileptr);
|
2005-07-08 02:47:05 +00:00
|
|
|
}
|
2001-07-11 02:08:33 +00:00
|
|
|
|
2015-12-08 16:02:05 +00:00
|
|
|
/* Free the data structures in the given node. */
|
2005-07-08 02:47:05 +00:00
|
|
|
void delete_node(filestruct *fileptr)
|
|
|
|
{
|
2015-06-14 19:14:41 +00:00
|
|
|
free(fileptr->data);
|
2017-11-01 18:45:33 +00:00
|
|
|
#ifdef ENABLE_COLOR
|
2015-06-14 19:14:41 +00:00
|
|
|
free(fileptr->multidata);
|
2009-01-25 07:25:17 +00:00
|
|
|
#endif
|
2005-07-08 02:47:05 +00:00
|
|
|
free(fileptr);
|
2001-07-11 02:08:33 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 15:38:34 +00:00
|
|
|
/* Duplicate an entire linked list of linestructs. */
|
2005-07-08 02:47:05 +00:00
|
|
|
filestruct *copy_filestruct(const filestruct *src)
|
2001-07-11 02:08:33 +00:00
|
|
|
{
|
2005-07-08 02:47:05 +00:00
|
|
|
filestruct *head, *copy;
|
2001-07-11 02:08:33 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
copy = copy_node(src);
|
|
|
|
copy->prev = NULL;
|
|
|
|
head = copy;
|
|
|
|
src = src->next;
|
2004-08-10 23:05:59 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
while (src != NULL) {
|
|
|
|
copy->next = copy_node(src);
|
|
|
|
copy->next->prev = copy;
|
|
|
|
copy = copy->next;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
src = src->next;
|
|
|
|
}
|
2005-07-19 04:50:55 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
copy->next = NULL;
|
2002-02-22 04:30:50 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
return head;
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 15:38:34 +00:00
|
|
|
/* Free an entire linked list of linestructs. */
|
2005-07-08 02:47:05 +00:00
|
|
|
void free_filestruct(filestruct *src)
|
2001-01-14 05:18:27 +00:00
|
|
|
{
|
2016-02-18 19:58:18 +00:00
|
|
|
if (src == NULL)
|
|
|
|
return;
|
2005-07-08 02:47:05 +00:00
|
|
|
|
|
|
|
while (src->next != NULL) {
|
|
|
|
src = src->next;
|
|
|
|
delete_node(src->prev);
|
|
|
|
}
|
2005-07-19 04:50:55 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
delete_node(src);
|
2001-01-14 05:18:27 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 15:38:34 +00:00
|
|
|
/* Renumber the lines in a buffer, starting with fileptr. */
|
2005-07-08 20:59:24 +00:00
|
|
|
void renumber(filestruct *fileptr)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2005-07-08 20:59:24 +00:00
|
|
|
ssize_t line;
|
2005-07-08 02:47:05 +00:00
|
|
|
|
2015-03-14 15:59:01 +00:00
|
|
|
if (fileptr == NULL)
|
|
|
|
return;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2005-07-15 00:08:23 +00:00
|
|
|
line = (fileptr->prev == NULL) ? 0 : fileptr->prev->lineno;
|
2001-01-14 05:18:27 +00:00
|
|
|
|
2005-07-08 20:59:24 +00:00
|
|
|
assert(fileptr != fileptr->next);
|
2005-07-08 02:47:05 +00:00
|
|
|
|
2005-07-08 20:59:24 +00:00
|
|
|
for (; fileptr != NULL; fileptr = fileptr->next)
|
2005-07-14 23:51:52 +00:00
|
|
|
fileptr->lineno = ++line;
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 15:38:34 +00:00
|
|
|
/* Partition the current buffer so that it appears to begin at (top, top_x)
|
|
|
|
* and appears to end at (bot, bot_x). */
|
2005-07-08 02:47:05 +00:00
|
|
|
partition *partition_filestruct(filestruct *top, size_t top_x,
|
|
|
|
filestruct *bot, size_t bot_x)
|
2002-09-06 20:35:28 +00:00
|
|
|
{
|
2005-07-08 02:47:05 +00:00
|
|
|
partition *p;
|
2003-01-26 04:15:56 +00:00
|
|
|
|
2005-07-08 20:09:16 +00:00
|
|
|
assert(top != NULL && bot != NULL && openfile->fileage != NULL && openfile->filebot != NULL);
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* Initialize the partition. */
|
|
|
|
p = (partition *)nmalloc(sizeof(partition));
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* If the top and bottom of the partition are different from the top
|
2017-04-19 15:38:34 +00:00
|
|
|
* and bottom of the buffer, save the latter and then set them
|
2005-07-08 02:47:05 +00:00
|
|
|
* to top and bot. */
|
2005-07-08 20:09:16 +00:00
|
|
|
if (top != openfile->fileage) {
|
|
|
|
p->fileage = openfile->fileage;
|
|
|
|
openfile->fileage = top;
|
2002-09-06 20:35:28 +00:00
|
|
|
} else
|
2005-07-08 02:47:05 +00:00
|
|
|
p->fileage = NULL;
|
2005-07-08 20:09:16 +00:00
|
|
|
if (bot != openfile->filebot) {
|
|
|
|
p->filebot = openfile->filebot;
|
|
|
|
openfile->filebot = bot;
|
2005-07-08 02:47:05 +00:00
|
|
|
} else
|
|
|
|
p->filebot = NULL;
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2016-06-14 09:06:04 +00:00
|
|
|
/* Remember which line is above the top of the partition, detach the
|
|
|
|
* top of the partition from it, and save the text before top_x. */
|
2005-07-08 02:47:05 +00:00
|
|
|
p->top_prev = top->prev;
|
|
|
|
top->prev = NULL;
|
|
|
|
p->top_data = mallocstrncpy(NULL, top->data, top_x + 1);
|
|
|
|
p->top_data[top_x] = '\0';
|
2005-03-30 18:11:59 +00:00
|
|
|
|
2016-06-14 09:06:04 +00:00
|
|
|
/* Remember which line is below the bottom of the partition, detach the
|
|
|
|
* bottom of the partition from it, and save the text after bot_x. */
|
2005-07-08 02:47:05 +00:00
|
|
|
p->bot_next = bot->next;
|
|
|
|
bot->next = NULL;
|
|
|
|
p->bot_data = mallocstrcpy(NULL, bot->data + bot_x);
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* Remove all text after bot_x at the bottom of the partition. */
|
2017-03-20 12:01:37 +00:00
|
|
|
bot->data[bot_x] = '\0';
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* Remove all text before top_x at the top of the partition. */
|
2016-06-14 09:06:04 +00:00
|
|
|
charmove(top->data, top->data + top_x, strlen(top->data) - top_x + 1);
|
2003-02-10 02:32:58 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* Return the partition. */
|
|
|
|
return p;
|
|
|
|
}
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2017-04-19 15:38:34 +00:00
|
|
|
/* Unpartition the current buffer so that it stretches from (fileage, 0)
|
|
|
|
* to (filebot, $) again. */
|
2005-07-08 02:47:05 +00:00
|
|
|
void unpartition_filestruct(partition **p)
|
|
|
|
{
|
2005-07-08 20:09:16 +00:00
|
|
|
assert(p != NULL && openfile->fileage != NULL && openfile->filebot != NULL);
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2005-07-08 02:47:05 +00: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. */
|
2005-07-08 20:09:16 +00:00
|
|
|
openfile->fileage->prev = (*p)->top_prev;
|
|
|
|
if (openfile->fileage->prev != NULL)
|
|
|
|
openfile->fileage->prev->next = openfile->fileage;
|
|
|
|
openfile->fileage->data = charealloc(openfile->fileage->data,
|
2016-06-14 09:06:04 +00:00
|
|
|
strlen((*p)->top_data) + strlen(openfile->fileage->data) + 1);
|
2016-06-14 10:06:58 +00:00
|
|
|
charmove(openfile->fileage->data + strlen((*p)->top_data),
|
|
|
|
openfile->fileage->data, strlen(openfile->fileage->data) + 1);
|
|
|
|
strncpy(openfile->fileage->data, (*p)->top_data, strlen((*p)->top_data));
|
2005-07-08 02:47:05 +00:00
|
|
|
free((*p)->top_data);
|
2005-03-30 18:11:59 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* 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. */
|
2005-07-08 20:09:16 +00:00
|
|
|
openfile->filebot->next = (*p)->bot_next;
|
|
|
|
if (openfile->filebot->next != NULL)
|
|
|
|
openfile->filebot->next->prev = openfile->filebot;
|
|
|
|
openfile->filebot->data = charealloc(openfile->filebot->data,
|
2016-06-14 09:06:04 +00:00
|
|
|
strlen(openfile->filebot->data) + strlen((*p)->bot_data) + 1);
|
2005-07-08 20:09:16 +00:00
|
|
|
strcat(openfile->filebot->data, (*p)->bot_data);
|
2005-07-08 02:47:05 +00:00
|
|
|
free((*p)->bot_data);
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2017-04-19 15:38:34 +00:00
|
|
|
/* Restore the top and bottom of the buffer, if they were
|
2005-07-08 02:47:05 +00:00
|
|
|
* different from the top and bottom of the partition. */
|
|
|
|
if ((*p)->fileage != NULL)
|
2005-07-08 20:09:16 +00:00
|
|
|
openfile->fileage = (*p)->fileage;
|
2005-07-08 02:47:05 +00:00
|
|
|
if ((*p)->filebot != NULL)
|
2005-07-08 20:09:16 +00:00
|
|
|
openfile->filebot = (*p)->filebot;
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* Uninitialize the partition. */
|
|
|
|
free(*p);
|
|
|
|
*p = NULL;
|
|
|
|
}
|
2005-02-25 19:17:57 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* Move all the text between (top, top_x) and (bot, bot_x) in the
|
2017-04-19 15:38:34 +00:00
|
|
|
* current buffer to a new buffer beginning with file_top and ending
|
2005-07-08 02:47:05 +00:00
|
|
|
* with file_bot. If no text is between (top, top_x) and (bot, bot_x),
|
|
|
|
* don't do anything. */
|
2017-02-15 03:35:01 +00:00
|
|
|
void extract_buffer(filestruct **file_top, filestruct **file_bot,
|
2005-07-08 02:47:05 +00:00
|
|
|
filestruct *top, size_t top_x, filestruct *bot, size_t bot_x)
|
|
|
|
{
|
|
|
|
filestruct *top_save;
|
2005-09-02 04:35:58 +00:00
|
|
|
bool edittop_inside;
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2005-07-08 02:47:05 +00:00
|
|
|
bool mark_inside = FALSE;
|
2014-02-22 16:46:27 +00:00
|
|
|
bool same_line = FALSE;
|
2005-07-08 02:47:05 +00:00
|
|
|
#endif
|
2005-02-25 19:17:57 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
assert(file_top != NULL && file_bot != NULL && top != NULL && bot != NULL);
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* If (top, top_x)-(bot, bot_x) doesn't cover any text, get out. */
|
|
|
|
if (top == bot && top_x == bot_x)
|
|
|
|
return;
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2017-04-19 15:38:34 +00:00
|
|
|
/* Partition the buffer so that it contains only the text from
|
2005-07-08 02:47:05 +00:00
|
|
|
* (top, top_x) to (bot, bot_x), keep track of whether the top of
|
2005-09-02 04:35:58 +00:00
|
|
|
* the edit window is inside the partition, and keep track of
|
2005-07-08 02:47:05 +00:00
|
|
|
* whether the mark begins inside the partition. */
|
|
|
|
filepart = partition_filestruct(top, top_x, bot, bot_x);
|
2016-06-14 09:06:04 +00:00
|
|
|
edittop_inside = (openfile->edittop->lineno >= openfile->fileage->lineno &&
|
|
|
|
openfile->edittop->lineno <= openfile->filebot->lineno);
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2017-05-12 16:07:32 +00:00
|
|
|
if (openfile->mark) {
|
|
|
|
mark_inside = (openfile->mark->lineno >=
|
2005-07-08 20:09:16 +00:00
|
|
|
openfile->fileage->lineno &&
|
2017-05-12 16:07:32 +00:00
|
|
|
openfile->mark->lineno <=
|
2005-07-08 20:09:16 +00:00
|
|
|
openfile->filebot->lineno &&
|
2017-05-12 16:07:32 +00:00
|
|
|
(openfile->mark != openfile->fileage ||
|
|
|
|
openfile->mark_x >= top_x) &&
|
|
|
|
(openfile->mark != openfile->filebot ||
|
|
|
|
openfile->mark_x <= bot_x));
|
|
|
|
same_line = (openfile->mark == openfile->fileage);
|
2014-02-22 16:46:27 +00:00
|
|
|
}
|
2005-07-08 02:47:05 +00:00
|
|
|
#endif
|
2005-02-25 19:17:57 +00:00
|
|
|
|
2016-06-14 09:06:04 +00:00
|
|
|
/* Subtract the number of characters in the text from the file size. */
|
2005-07-17 01:44:35 +00:00
|
|
|
openfile->totsize -= get_totsize(top, bot);
|
2005-02-25 19:17:57 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
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. */
|
2005-07-08 20:09:16 +00:00
|
|
|
*file_top = openfile->fileage;
|
|
|
|
*file_bot = openfile->filebot;
|
2005-07-17 01:44:35 +00:00
|
|
|
|
2016-06-14 09:06:04 +00:00
|
|
|
/* Renumber, starting with file_top. */
|
2005-07-17 01:44:35 +00:00
|
|
|
renumber(*file_top);
|
2005-07-08 02:47:05 +00:00
|
|
|
} else {
|
2005-07-17 01:44:35 +00:00
|
|
|
filestruct *file_bot_save = *file_bot;
|
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* Otherwise, tack the text in top onto the text at the end of
|
|
|
|
* file_bot. */
|
|
|
|
(*file_bot)->data = charealloc((*file_bot)->data,
|
2005-07-08 20:09:16 +00:00
|
|
|
strlen((*file_bot)->data) +
|
|
|
|
strlen(openfile->fileage->data) + 1);
|
|
|
|
strcat((*file_bot)->data, openfile->fileage->data);
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* 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. */
|
2005-07-08 20:09:16 +00:00
|
|
|
(*file_bot)->next = openfile->fileage->next;
|
2005-07-08 02:47:05 +00:00
|
|
|
if ((*file_bot)->next != NULL) {
|
|
|
|
(*file_bot)->next->prev = *file_bot;
|
2005-07-08 20:09:16 +00:00
|
|
|
*file_bot = openfile->filebot;
|
2004-09-11 21:41:13 +00:00
|
|
|
}
|
2005-07-17 01:44:35 +00:00
|
|
|
|
2016-02-18 19:58:18 +00:00
|
|
|
delete_node(openfile->fileage);
|
2014-07-16 08:46:42 +00:00
|
|
|
|
2016-06-14 09:06:04 +00:00
|
|
|
/* Renumber, starting with the line after the original file_bot. */
|
2015-03-14 15:59:01 +00:00
|
|
|
renumber(file_bot_save->next);
|
2005-07-08 02:47:05 +00:00
|
|
|
}
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2017-04-19 15:38:34 +00:00
|
|
|
/* Since the text has now been saved, remove it from the buffer. */
|
2017-02-09 22:00:07 +00:00
|
|
|
openfile->fileage = make_new_node(NULL);
|
2005-07-08 20:09:16 +00:00
|
|
|
openfile->fileage->data = mallocstrcpy(NULL, "");
|
|
|
|
openfile->filebot = openfile->fileage;
|
2007-08-07 19:55:06 +00:00
|
|
|
|
|
|
|
/* Restore the current line and cursor position. If the mark begins
|
|
|
|
* inside the partition, set the beginning of the mark to where the
|
|
|
|
* saved text used to start. */
|
|
|
|
openfile->current = openfile->fileage;
|
|
|
|
openfile->current_x = top_x;
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2005-07-08 02:47:05 +00:00
|
|
|
if (mark_inside) {
|
2017-05-12 16:07:32 +00:00
|
|
|
openfile->mark = openfile->current;
|
|
|
|
openfile->mark_x = openfile->current_x;
|
2014-02-22 16:46:27 +00:00
|
|
|
} else if (same_line)
|
2015-11-22 16:08:28 +00:00
|
|
|
/* Update the pointer to this partially cut line. */
|
2017-05-12 16:07:32 +00:00
|
|
|
openfile->mark = openfile->current;
|
2005-07-08 02:47:05 +00:00
|
|
|
#endif
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2005-07-08 20:09:16 +00:00
|
|
|
top_save = openfile->fileage;
|
2005-02-25 19:17:57 +00:00
|
|
|
|
2017-04-19 15:38:34 +00:00
|
|
|
/* Unpartition the buffer so that it contains all the text
|
2005-07-08 02:47:05 +00:00
|
|
|
* again, minus the saved text. */
|
|
|
|
unpartition_filestruct(&filepart);
|
2005-02-25 19:17:57 +00:00
|
|
|
|
2005-09-02 04:35:58 +00:00
|
|
|
/* If the top of the edit window was inside the old partition, put
|
|
|
|
* it in range of current. */
|
2016-04-25 18:05:21 +00:00
|
|
|
if (edittop_inside) {
|
2016-10-20 19:11:11 +00:00
|
|
|
adjust_viewport(STATIONARY);
|
2016-04-25 19:14:18 +00:00
|
|
|
refresh_needed = TRUE;
|
2016-04-25 18:05:21 +00:00
|
|
|
}
|
2005-09-02 04:35:58 +00:00
|
|
|
|
2016-06-14 09:06:04 +00:00
|
|
|
/* Renumber, starting with the beginning line of the old partition. */
|
2005-07-08 02:47:05 +00:00
|
|
|
renumber(top_save);
|
2005-06-13 14:00:22 +00:00
|
|
|
|
2016-06-14 09:06:04 +00:00
|
|
|
/* If the text doesn't end with a magicline, and it should, add one. */
|
2005-11-05 17:35:44 +00:00
|
|
|
if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0')
|
2005-07-08 02:47:05 +00:00
|
|
|
new_magicline();
|
|
|
|
}
|
2005-03-04 17:09:41 +00:00
|
|
|
|
2017-02-10 06:17:33 +00:00
|
|
|
/* Meld the given buffer into the current file buffer
|
2014-04-14 09:14:39 +00:00
|
|
|
* at the current cursor position. */
|
2017-02-10 06:17:33 +00:00
|
|
|
void ingraft_buffer(filestruct *somebuffer)
|
2005-07-08 02:47:05 +00:00
|
|
|
{
|
|
|
|
filestruct *top_save;
|
2007-08-16 03:23:30 +00:00
|
|
|
size_t current_x_save = openfile->current_x;
|
2005-09-02 04:35:58 +00:00
|
|
|
bool edittop_inside;
|
2007-08-07 20:21:39 +00:00
|
|
|
#ifndef NANO_TINY
|
2007-08-16 14:45:17 +00:00
|
|
|
bool right_side_up = FALSE, single_line = FALSE;
|
2007-08-07 20:21:39 +00:00
|
|
|
#endif
|
2005-03-04 17:09:41 +00:00
|
|
|
|
2014-04-14 09:14:39 +00:00
|
|
|
assert(somebuffer != NULL);
|
2005-02-25 19:17:57 +00:00
|
|
|
|
2007-08-16 14:45:17 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
/* Keep track of whether the mark begins inside the partition and
|
|
|
|
* will need adjustment. */
|
2017-05-12 16:07:32 +00:00
|
|
|
if (openfile->mark) {
|
2007-08-16 14:45:17 +00:00
|
|
|
filestruct *top, *bot;
|
|
|
|
size_t top_x, bot_x;
|
|
|
|
|
|
|
|
mark_order((const filestruct **)&top, &top_x,
|
2016-06-14 09:06:04 +00:00
|
|
|
(const filestruct **)&bot, &bot_x, &right_side_up);
|
2007-08-16 14:45:17 +00:00
|
|
|
|
|
|
|
single_line = (top == bot);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-04-19 15:38:34 +00:00
|
|
|
/* Partition the buffer so that it contains no text, and remember
|
2016-06-16 09:54:11 +00:00
|
|
|
* whether the current line is at the top of the edit window. */
|
2016-06-14 09:06:04 +00:00
|
|
|
filepart = partition_filestruct(openfile->current, openfile->current_x,
|
|
|
|
openfile->current, openfile->current_x);
|
2007-08-08 00:05:49 +00:00
|
|
|
edittop_inside = (openfile->edittop == openfile->fileage);
|
2016-06-16 09:54:11 +00:00
|
|
|
free_filestruct(openfile->fileage);
|
2007-08-07 20:21:39 +00:00
|
|
|
|
2017-04-19 15:38:34 +00:00
|
|
|
/* Put the top and bottom of the current buffer at the top and
|
2017-02-10 06:17:33 +00:00
|
|
|
* bottom of the passed buffer. */
|
|
|
|
openfile->fileage = somebuffer;
|
2005-07-08 20:09:16 +00:00
|
|
|
openfile->filebot = openfile->fileage;
|
|
|
|
while (openfile->filebot->next != NULL)
|
|
|
|
openfile->filebot = openfile->filebot->next;
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2015-10-31 20:17:09 +00:00
|
|
|
/* Put the cursor at the end of the pasted text. */
|
2005-07-08 20:09:16 +00:00
|
|
|
openfile->current = openfile->filebot;
|
|
|
|
openfile->current_x = strlen(openfile->filebot->data);
|
2015-10-31 20:17:09 +00:00
|
|
|
|
|
|
|
/* Refresh the mark's pointer, and compensate the mark's
|
|
|
|
* x coordinate for the change in the current line. */
|
2007-08-07 20:21:39 +00:00
|
|
|
if (openfile->fileage == openfile->filebot) {
|
|
|
|
#ifndef NANO_TINY
|
2017-05-12 16:07:32 +00:00
|
|
|
if (openfile->mark && single_line) {
|
|
|
|
openfile->mark = openfile->current;
|
2007-08-16 14:45:17 +00:00
|
|
|
if (!right_side_up)
|
2017-05-12 16:07:32 +00:00
|
|
|
openfile->mark_x += openfile->current_x;
|
2007-08-07 20:21:39 +00:00
|
|
|
}
|
|
|
|
#endif
|
2015-10-31 20:17:09 +00:00
|
|
|
/* When the pasted stuff contains no newline, adjust the cursor's
|
|
|
|
* x coordinate for the text that is before the pasted stuff. */
|
2007-08-16 03:23:30 +00:00
|
|
|
openfile->current_x += current_x_save;
|
2007-08-07 20:21:39 +00:00
|
|
|
}
|
2007-08-16 03:23:30 +00:00
|
|
|
#ifndef NANO_TINY
|
2017-05-12 16:07:32 +00:00
|
|
|
else if (openfile->mark && single_line) {
|
2015-10-31 20:17:09 +00:00
|
|
|
if (right_side_up)
|
2017-05-12 16:07:32 +00:00
|
|
|
openfile->mark = openfile->fileage;
|
2015-10-31 20:17:09 +00:00
|
|
|
else {
|
2017-05-12 16:07:32 +00:00
|
|
|
openfile->mark = openfile->current;
|
|
|
|
openfile->mark_x += openfile->current_x - current_x_save;
|
2007-08-16 14:45:17 +00:00
|
|
|
}
|
|
|
|
}
|
2007-08-16 03:23:30 +00:00
|
|
|
#endif
|
2005-05-14 20:52:20 +00:00
|
|
|
|
2016-06-14 09:06:04 +00:00
|
|
|
/* Add the number of characters in the copied text to the file size. */
|
|
|
|
openfile->totsize += get_totsize(openfile->fileage, openfile->filebot);
|
2005-05-14 20:52:20 +00:00
|
|
|
|
2016-06-16 09:54:11 +00:00
|
|
|
/* If we pasted onto the first line of the edit window, the corresponding
|
|
|
|
* struct has been freed, so... point at the start of the copied text. */
|
2005-09-02 04:35:58 +00:00
|
|
|
if (edittop_inside)
|
|
|
|
openfile->edittop = openfile->fileage;
|
|
|
|
|
2016-06-16 09:54:11 +00:00
|
|
|
top_save = openfile->fileage;
|
|
|
|
|
2017-04-19 15:38:34 +00:00
|
|
|
/* Unpartition the buffer so that it contains all the text
|
2005-09-02 04:35:58 +00:00
|
|
|
* again, plus the copied text. */
|
2005-07-08 02:47:05 +00:00
|
|
|
unpartition_filestruct(&filepart);
|
2005-03-04 17:09:41 +00:00
|
|
|
|
2016-06-14 09:06:04 +00:00
|
|
|
/* Renumber, starting with the beginning line of the old partition. */
|
2005-07-08 02:47:05 +00:00
|
|
|
renumber(top_save);
|
2005-03-04 17:09:41 +00:00
|
|
|
|
2016-06-14 09:06:04 +00:00
|
|
|
/* If the text doesn't end with a magicline, and it should, add one. */
|
2005-11-05 17:35:44 +00:00
|
|
|
if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0')
|
2005-07-08 02:47:05 +00:00
|
|
|
new_magicline();
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
|
2017-02-10 06:17:33 +00:00
|
|
|
/* Meld a copy of the given buffer into the current file buffer. */
|
|
|
|
void copy_from_buffer(filestruct *somebuffer)
|
|
|
|
{
|
|
|
|
filestruct *the_copy = copy_filestruct(somebuffer);
|
|
|
|
|
|
|
|
ingraft_buffer(the_copy);
|
|
|
|
}
|
|
|
|
|
2017-04-19 15:38:34 +00:00
|
|
|
/* Create a new openfile node. */
|
2005-07-20 21:08:38 +00:00
|
|
|
openfilestruct *make_new_opennode(void)
|
|
|
|
{
|
2015-08-16 15:21:32 +00:00
|
|
|
return (openfilestruct *)nmalloc(sizeof(openfilestruct));
|
2005-07-20 21:08:38 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 15:38:34 +00:00
|
|
|
/* Unlink a node from the rest of the circular list, and delete it. */
|
2005-07-20 21:08:38 +00:00
|
|
|
void unlink_opennode(openfilestruct *fileptr)
|
|
|
|
{
|
2016-12-15 19:26:47 +00:00
|
|
|
assert(fileptr != fileptr->prev && fileptr != fileptr->next);
|
2005-07-20 21:08:38 +00:00
|
|
|
|
2017-09-01 16:47:19 +00:00
|
|
|
if (fileptr == firstfile)
|
|
|
|
firstfile = firstfile->next;
|
|
|
|
|
2005-07-20 21:08:38 +00:00
|
|
|
fileptr->prev->next = fileptr->next;
|
|
|
|
fileptr->next->prev = fileptr->prev;
|
|
|
|
|
|
|
|
delete_opennode(fileptr);
|
|
|
|
}
|
|
|
|
|
2016-02-22 09:02:58 +00:00
|
|
|
/* Free all the memory in the given open-file node. */
|
2005-07-20 21:08:38 +00:00
|
|
|
void delete_opennode(openfilestruct *fileptr)
|
|
|
|
{
|
|
|
|
free(fileptr->filename);
|
|
|
|
free_filestruct(fileptr->fileage);
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2015-06-14 19:14:41 +00:00
|
|
|
free(fileptr->current_stat);
|
2015-07-10 15:54:06 +00:00
|
|
|
free(fileptr->lock_filename);
|
2016-01-15 16:44:50 +00:00
|
|
|
/* Free the undo stack. */
|
|
|
|
discard_until(NULL, fileptr);
|
2005-07-20 21:08:38 +00:00
|
|
|
#endif
|
|
|
|
free(fileptr);
|
|
|
|
}
|
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Display a warning about a key disabled in view mode. */
|
2005-07-08 02:47:05 +00:00
|
|
|
void print_view_warning(void)
|
2002-09-06 20:35:28 +00:00
|
|
|
{
|
2015-07-30 18:10:16 +00:00
|
|
|
statusbar(_("Key is invalid in view mode"));
|
2002-09-06 20:35:28 +00:00
|
|
|
}
|
|
|
|
|
2015-07-30 18:10:16 +00:00
|
|
|
/* Indicate that something is disabled in restricted mode. */
|
|
|
|
void show_restricted_warning(void)
|
|
|
|
{
|
|
|
|
statusbar(_("This function is disabled in restricted mode"));
|
|
|
|
beep();
|
|
|
|
}
|
|
|
|
|
2017-04-25 15:51:45 +00:00
|
|
|
#ifndef ENABLE_HELP
|
2015-07-30 18:10:16 +00:00
|
|
|
/* Indicate that help texts are unavailable. */
|
|
|
|
void say_there_is_no_help(void)
|
|
|
|
{
|
2015-08-09 18:12:32 +00:00
|
|
|
statusbar(_("Help is not available"));
|
2015-07-30 18:10:16 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-01-09 22:56:56 +00:00
|
|
|
/* Make nano exit gracefully. */
|
2005-07-08 02:47:05 +00:00
|
|
|
void finish(void)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2015-08-09 18:10:13 +00:00
|
|
|
/* Blank the statusbar and (if applicable) the shortcut list,
|
|
|
|
* and move the cursor to the last line of the screen. */
|
|
|
|
blank_statusbar();
|
|
|
|
blank_bottombars();
|
2005-07-29 03:28:09 +00:00
|
|
|
wrefresh(bottomwin);
|
2005-07-08 02:47:05 +00:00
|
|
|
endwin();
|
2002-04-10 02:31:20 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* Restore the old terminal settings. */
|
|
|
|
tcsetattr(0, TCSANOW, &oldterm);
|
2005-03-04 17:09:41 +00:00
|
|
|
|
2017-10-29 18:42:12 +00:00
|
|
|
#ifdef ENABLE_HISTORIES
|
2017-09-17 18:06:04 +00:00
|
|
|
/* If the user wants history persistence, write the relevant files. */
|
2014-06-19 15:09:23 +00:00
|
|
|
if (ISSET(HISTORYLOG))
|
2005-07-08 02:47:05 +00:00
|
|
|
save_history();
|
2014-06-19 15:09:23 +00:00
|
|
|
if (ISSET(POS_HISTORY)) {
|
2014-06-04 16:02:51 +00:00
|
|
|
update_poshistory(openfile->filename, openfile->current->lineno, xplustabs() + 1);
|
2011-02-18 07:30:57 +00:00
|
|
|
}
|
2005-07-08 02:47:05 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
thanks_for_all_the_fish();
|
|
|
|
#endif
|
|
|
|
|
2007-01-09 22:56:56 +00:00
|
|
|
/* Get out. */
|
2005-07-08 02:47:05 +00:00
|
|
|
exit(0);
|
2002-04-10 02:31:20 +00:00
|
|
|
}
|
|
|
|
|
2007-01-09 22:56:56 +00:00
|
|
|
/* Make nano die gracefully. */
|
2005-07-08 02:47:05 +00:00
|
|
|
void die(const char *msg, ...)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2005-07-08 02:47:05 +00:00
|
|
|
va_list ap;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
endwin();
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* Restore the old terminal settings. */
|
|
|
|
tcsetattr(0, TCSANOW, &oldterm);
|
2005-05-14 20:52:20 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
va_start(ap, msg);
|
|
|
|
vfprintf(stderr, msg, ap);
|
|
|
|
va_end(ap);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2016-08-02 15:11:50 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
/* If the current buffer has a lockfile, remove it. */
|
2016-08-16 14:56:25 +00:00
|
|
|
if (openfile && ISSET(LOCKING) && openfile->lock_filename)
|
2016-08-02 15:11:50 +00:00
|
|
|
delete_lockfile(openfile->lock_filename);
|
|
|
|
#endif
|
|
|
|
|
2016-08-02 15:26:25 +00:00
|
|
|
/* If the current file buffer was modified, save it. */
|
2008-05-31 22:23:16 +00:00
|
|
|
if (openfile && openfile->modified) {
|
2017-04-19 15:38:34 +00:00
|
|
|
/* If the buffer is partitioned, unpartition it first. */
|
2005-07-08 02:47:05 +00:00
|
|
|
if (filepart != NULL)
|
|
|
|
unpartition_filestruct(&filepart);
|
|
|
|
|
2016-08-02 15:26:25 +00:00
|
|
|
die_save_file(openfile->filename, openfile->current_stat);
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
|
2017-05-01 18:20:34 +00:00
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
2005-07-08 02:47:05 +00:00
|
|
|
/* Save all of the other modified file buffers, if any. */
|
2005-07-08 19:57:25 +00:00
|
|
|
if (openfile != NULL) {
|
2016-08-02 15:26:25 +00:00
|
|
|
openfilestruct *firstone = openfile;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2016-08-02 15:26:25 +00:00
|
|
|
while (openfile->next != firstone) {
|
2005-07-08 19:57:25 +00:00
|
|
|
openfile = openfile->next;
|
2004-11-25 04:39:07 +00:00
|
|
|
|
2016-08-02 15:11:50 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
if (ISSET(LOCKING) && openfile->lock_filename)
|
|
|
|
delete_lockfile(openfile->lock_filename);
|
|
|
|
#endif
|
2005-07-08 20:09:16 +00:00
|
|
|
if (openfile->modified)
|
2016-08-02 15:26:25 +00:00
|
|
|
die_save_file(openfile->filename, openfile->current_stat);
|
2005-07-08 02:47:05 +00:00
|
|
|
}
|
2002-04-10 02:31:20 +00:00
|
|
|
}
|
2005-07-08 02:47:05 +00:00
|
|
|
#endif
|
|
|
|
|
2016-08-02 15:26:25 +00:00
|
|
|
/* Abandon the building. */
|
2005-07-08 02:47:05 +00:00
|
|
|
exit(1);
|
2002-04-10 02:31:20 +00:00
|
|
|
}
|
|
|
|
|
2016-05-27 19:43:39 +00:00
|
|
|
/* Save the current file under the name specified in die_filename, which
|
2005-12-08 07:09:08 +00:00
|
|
|
* is modified to be unique if necessary. */
|
2016-08-02 15:26:25 +00:00
|
|
|
void die_save_file(const char *die_filename, struct stat *die_stat)
|
2004-11-03 22:03:41 +00:00
|
|
|
{
|
2016-05-27 19:43:39 +00:00
|
|
|
char *targetname;
|
2005-07-08 02:47:05 +00:00
|
|
|
bool failed = TRUE;
|
2005-03-04 17:09:41 +00:00
|
|
|
|
2005-07-08 02:47:05 +00: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. */
|
|
|
|
if (ISSET(RESTRICTED))
|
|
|
|
return;
|
2004-11-03 22:03:41 +00:00
|
|
|
|
2007-01-09 22:56:56 +00:00
|
|
|
/* If we can't save, we have really bad problems, but we might as
|
|
|
|
* well try. */
|
2007-07-01 21:33:17 +00:00
|
|
|
if (*die_filename == '\0')
|
2005-07-08 02:47:05 +00:00
|
|
|
die_filename = "nano";
|
2004-11-03 22:03:41 +00:00
|
|
|
|
2016-05-27 19:43:39 +00:00
|
|
|
targetname = get_next_filename(die_filename, ".save");
|
|
|
|
|
|
|
|
if (*targetname != '\0')
|
|
|
|
failed = !write_file(targetname, NULL, TRUE, OVERWRITE, TRUE);
|
2004-11-03 22:03:41 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
if (!failed)
|
2016-05-27 19:43:39 +00:00
|
|
|
fprintf(stderr, _("\nBuffer written to %s\n"), targetname);
|
|
|
|
else if (*targetname != '\0')
|
|
|
|
fprintf(stderr, _("\nBuffer not written to %s: %s\n"), targetname,
|
2005-07-08 02:47:05 +00:00
|
|
|
strerror(errno));
|
|
|
|
else
|
|
|
|
fprintf(stderr, _("\nBuffer not written: %s\n"),
|
|
|
|
_("Too many backup files?"));
|
2004-11-03 22:03:41 +00:00
|
|
|
|
2009-11-22 21:35:56 +00:00
|
|
|
#ifndef NANO_TINY
|
2015-03-27 13:46:50 +00:00
|
|
|
/* Try and chmod/chown the save file to the values of the original file,
|
|
|
|
* but don't worry if it fails because we're supposed to be bailing as
|
|
|
|
* fast as possible. */
|
2009-11-20 05:09:12 +00:00
|
|
|
if (die_stat) {
|
2016-05-27 19:48:38 +00:00
|
|
|
IGNORE_CALL_RESULT(chmod(targetname, die_stat->st_mode));
|
|
|
|
IGNORE_CALL_RESULT(chown(targetname, die_stat->st_uid,
|
|
|
|
die_stat->st_gid));
|
2009-11-20 05:09:12 +00:00
|
|
|
}
|
2009-11-22 21:35:56 +00:00
|
|
|
#endif
|
2009-11-20 05:09:12 +00:00
|
|
|
|
2016-05-27 19:43:39 +00:00
|
|
|
free(targetname);
|
2005-07-08 02:47:05 +00:00
|
|
|
}
|
2004-11-03 22:03:41 +00:00
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Initialize the three window portions nano uses. */
|
2005-07-25 22:54:16 +00:00
|
|
|
void window_init(void)
|
2005-07-08 02:47:05 +00:00
|
|
|
{
|
2017-05-18 08:16:52 +00:00
|
|
|
/* When resizing, first delete the existing windows. */
|
|
|
|
if (edit != NULL) {
|
|
|
|
if (topwin != NULL)
|
|
|
|
delwin(topwin);
|
|
|
|
delwin(edit);
|
|
|
|
delwin(bottomwin);
|
|
|
|
}
|
2016-08-15 12:55:59 +00:00
|
|
|
|
2016-08-15 17:44:49 +00:00
|
|
|
/* If the terminal is very flat, don't set up a titlebar. */
|
|
|
|
if (LINES < 3) {
|
2017-05-18 08:16:52 +00:00
|
|
|
topwin = NULL;
|
2016-08-15 17:44:49 +00:00
|
|
|
editwinrows = 1;
|
|
|
|
/* Set up two subwindows. If the terminal is just one line,
|
|
|
|
* edit window and statusbar window will cover each other. */
|
|
|
|
edit = newwin(1, COLS, 0, 0);
|
|
|
|
bottomwin = newwin(1, COLS, LINES - 1, 0);
|
|
|
|
} else {
|
|
|
|
int toprows = (ISSET(MORE_SPACE) ? 1 : (LINES < 6) ? 1 : 2);
|
|
|
|
int bottomrows = (ISSET(NO_HELP) ? 1 : (LINES < 5) ? 1 : 3);
|
2016-08-15 10:55:03 +00:00
|
|
|
|
2016-08-15 17:44:49 +00:00
|
|
|
editwinrows = LINES - toprows - bottomrows;
|
2005-07-10 02:37:38 +00:00
|
|
|
|
2016-08-15 17:44:49 +00:00
|
|
|
/* Set up the normal three subwindows. */
|
|
|
|
topwin = newwin(toprows, COLS, 0, 0);
|
|
|
|
edit = newwin(editwinrows, COLS, toprows, 0);
|
|
|
|
bottomwin = newwin(bottomrows, COLS, toprows + editwinrows, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* In case the terminal shrunk, make sure the status line is clear. */
|
|
|
|
blank_statusbar();
|
|
|
|
wnoutrefresh(bottomwin);
|
2004-11-03 22:03:41 +00:00
|
|
|
|
2005-08-14 19:25:16 +00:00
|
|
|
/* Turn the keypad on for the windows, if necessary. */
|
2005-08-10 21:22:15 +00:00
|
|
|
if (!ISSET(REBIND_KEYPAD)) {
|
2005-08-14 19:25:16 +00:00
|
|
|
keypad(topwin, TRUE);
|
2005-08-10 21:22:15 +00:00
|
|
|
keypad(edit, TRUE);
|
|
|
|
keypad(bottomwin, TRUE);
|
|
|
|
}
|
2016-08-15 12:55:59 +00:00
|
|
|
|
2017-10-31 16:39:30 +00:00
|
|
|
#ifdef ENABLED_WRAPORJUSTIFY
|
2016-08-15 12:55:59 +00:00
|
|
|
/* Set up the wrapping point, accounting for screen width when negative. */
|
|
|
|
fill = wrap_at;
|
|
|
|
if (fill <= 0)
|
|
|
|
fill += COLS;
|
|
|
|
if (fill < 0)
|
|
|
|
fill = 0;
|
|
|
|
#endif
|
2004-11-03 22:03:41 +00:00
|
|
|
}
|
|
|
|
|
2017-05-01 18:45:07 +00:00
|
|
|
#ifdef ENABLE_MOUSE
|
2006-06-09 18:24:37 +00:00
|
|
|
void disable_mouse_support(void)
|
|
|
|
{
|
|
|
|
mousemask(0, NULL);
|
2007-12-04 20:49:09 +00:00
|
|
|
mouseinterval(oldinterval);
|
2006-06-09 18:24:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void enable_mouse_support(void)
|
|
|
|
{
|
2006-06-28 21:54:55 +00:00
|
|
|
mousemask(ALL_MOUSE_EVENTS, NULL);
|
2007-12-04 20:49:09 +00:00
|
|
|
oldinterval = mouseinterval(50);
|
2006-06-09 18:24:37 +00:00
|
|
|
}
|
|
|
|
|
2017-05-01 18:45:07 +00:00
|
|
|
/* Switch mouse support on or off, as needed. */
|
2005-07-08 02:47:05 +00:00
|
|
|
void mouse_init(void)
|
2004-11-23 04:08:28 +00:00
|
|
|
{
|
2006-06-09 18:24:37 +00:00
|
|
|
if (ISSET(USE_MOUSE))
|
|
|
|
enable_mouse_support();
|
|
|
|
else
|
|
|
|
disable_mouse_support();
|
2005-07-08 02:47:05 +00:00
|
|
|
}
|
2017-05-01 18:45:07 +00:00
|
|
|
#endif /* ENABLE_MOUSE */
|
2004-11-23 04:08:28 +00:00
|
|
|
|
2004-08-05 15:16:19 +00:00
|
|
|
/* Print one usage string to the screen. This cuts down on duplicate
|
2005-03-21 07:24:47 +00:00
|
|
|
* strings to translate, and leaves out the parts that shouldn't be
|
2007-01-09 22:56:56 +00:00
|
|
|
* translatable (i.e. the flag names). */
|
2017-02-21 22:04:40 +00:00
|
|
|
void print_opt(const char *shortflag, const char *longflag, const char *desc)
|
2002-03-09 18:51:58 +00:00
|
|
|
{
|
|
|
|
printf(" %s\t", shortflag);
|
2007-12-18 22:00:17 +00:00
|
|
|
if (strlenpt(shortflag) < 8)
|
2002-03-09 18:51:58 +00:00
|
|
|
printf("\t");
|
|
|
|
|
|
|
|
printf("%s\t", longflag);
|
2007-12-18 22:00:17 +00:00
|
|
|
if (strlenpt(longflag) < 8)
|
2002-03-09 18:51:58 +00:00
|
|
|
printf("\t\t");
|
2007-12-18 22:00:17 +00:00
|
|
|
else if (strlenpt(longflag) < 16)
|
2002-03-09 18:51:58 +00:00
|
|
|
printf("\t");
|
|
|
|
|
2005-04-14 03:13:49 +00:00
|
|
|
if (desc != NULL)
|
|
|
|
printf("%s", _(desc));
|
|
|
|
printf("\n");
|
2002-03-09 18:51:58 +00:00
|
|
|
}
|
|
|
|
|
2014-05-28 15:44:11 +00:00
|
|
|
/* Explain how to properly use nano and its command-line options. */
|
2002-08-21 16:10:37 +00:00
|
|
|
void usage(void)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2017-02-25 13:05:07 +00:00
|
|
|
printf(_("Usage: nano [OPTIONS] [[+LINE[,COLUMN]] FILE]...\n\n"));
|
|
|
|
/* TRANSLATORS: The next two strings are part of the --help output.
|
|
|
|
* It's best to keep its lines within 80 characters. */
|
|
|
|
printf(_("To place the cursor on a specific line of a file, put the line number with\n"
|
|
|
|
"a '+' before the filename. The column number can be added after a comma.\n"));
|
2017-06-29 19:27:37 +00:00
|
|
|
printf(_("When a filename is '-', nano reads data from standard input.\n\n"));
|
2016-10-23 20:00:45 +00:00
|
|
|
printf(_("Option\t\tGNU long option\t\tMeaning\n"));
|
2017-02-25 13:05:07 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
print_opt("-A", "--smarthome",
|
2014-05-28 15:44:11 +00:00
|
|
|
/* TRANSLATORS: The next forty or so strings are option descriptions
|
|
|
|
* for the --help output. Try to keep them at most 40 characters. */
|
2017-02-25 13:05:07 +00:00
|
|
|
N_("Enable smart home key"));
|
2015-07-29 19:31:50 +00:00
|
|
|
if (!ISSET(RESTRICTED)) {
|
2015-07-30 11:29:45 +00:00
|
|
|
print_opt("-B", "--backup", N_("Save backups of existing files"));
|
|
|
|
print_opt(_("-C <dir>"), _("--backupdir=<dir>"),
|
|
|
|
N_("Directory for saving unique backup files"));
|
2015-07-29 19:31:50 +00:00
|
|
|
}
|
2006-05-13 13:02:14 +00:00
|
|
|
#endif
|
2015-05-03 13:56:51 +00:00
|
|
|
print_opt("-D", "--boldtext", N_("Use bold instead of reverse video text"));
|
2006-05-13 13:02:14 +00:00
|
|
|
#ifndef NANO_TINY
|
2015-05-03 13:56:51 +00:00
|
|
|
print_opt("-E", "--tabstospaces", N_("Convert typed tabs to spaces"));
|
2001-09-22 00:42:10 +00:00
|
|
|
#endif
|
2017-05-01 18:20:34 +00:00
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
2015-07-29 19:31:50 +00:00
|
|
|
if (!ISSET(RESTRICTED))
|
2015-07-30 11:29:45 +00:00
|
|
|
print_opt("-F", "--multibuffer",
|
|
|
|
N_("Read a file into a new buffer by default"));
|
2002-07-19 01:08:59 +00:00
|
|
|
#endif
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2015-05-03 13:56:51 +00:00
|
|
|
print_opt("-G", "--locking", N_("Use (vim-style) lock files"));
|
2014-06-19 20:05:24 +00:00
|
|
|
#endif
|
2017-10-29 18:42:12 +00:00
|
|
|
#ifdef ENABLE_HISTORIES
|
2015-07-29 19:31:50 +00:00
|
|
|
if (!ISSET(RESTRICTED))
|
2015-07-30 11:29:45 +00:00
|
|
|
print_opt("-H", "--historylog",
|
|
|
|
N_("Log & read search/replace string history"));
|
2014-07-02 19:57:23 +00:00
|
|
|
#endif
|
2017-05-08 17:42:44 +00:00
|
|
|
#ifdef ENABLE_NANORC
|
2015-07-29 19:31:50 +00:00
|
|
|
if (!ISSET(RESTRICTED))
|
2015-07-30 11:29:45 +00:00
|
|
|
print_opt("-I", "--ignorercfiles", N_("Don't look at nanorc files"));
|
2001-09-22 04:20:25 +00:00
|
|
|
#endif
|
2006-05-12 19:30:28 +00:00
|
|
|
print_opt("-K", "--rebindkeypad",
|
2005-08-10 21:22:15 +00:00
|
|
|
N_("Fix numeric keypad key confusion problem"));
|
2006-05-12 19:30:28 +00:00
|
|
|
print_opt("-L", "--nonewlines",
|
2005-11-05 17:35:44 +00:00
|
|
|
N_("Don't add newlines to the ends of files"));
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2006-05-12 19:30:28 +00:00
|
|
|
print_opt("-N", "--noconvert",
|
2005-05-21 17:15:46 +00:00
|
|
|
N_("Don't convert files from DOS/Mac format"));
|
2002-03-03 22:36:36 +00:00
|
|
|
#endif
|
2006-07-31 01:30:31 +00:00
|
|
|
print_opt("-O", "--morespace", N_("Use one more line for editing"));
|
2017-10-29 18:42:12 +00:00
|
|
|
#ifdef ENABLE_HISTORIES
|
2015-07-29 19:31:50 +00:00
|
|
|
if (!ISSET(RESTRICTED))
|
2015-07-30 11:29:45 +00:00
|
|
|
print_opt("-P", "--positionlog",
|
|
|
|
N_("Log & read location of cursor position"));
|
2011-02-16 06:52:30 +00:00
|
|
|
#endif
|
2017-10-31 16:34:07 +00:00
|
|
|
#ifdef ENABLE_JUSTIFY
|
2015-05-03 13:56:51 +00:00
|
|
|
print_opt(_("-Q <str>"), _("--quotestr=<str>"), N_("Quoting string"));
|
2001-07-14 19:32:47 +00:00
|
|
|
#endif
|
2015-07-29 19:31:50 +00:00
|
|
|
if (!ISSET(RESTRICTED))
|
2015-07-30 11:29:45 +00:00
|
|
|
print_opt("-R", "--restricted", N_("Restricted mode"));
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2015-05-03 13:56:51 +00:00
|
|
|
print_opt("-S", "--smooth", N_("Scroll by line instead of half-screen"));
|
2001-09-22 19:02:04 +00:00
|
|
|
#endif
|
2006-05-14 15:19:38 +00:00
|
|
|
print_opt(_("-T <#cols>"), _("--tabsize=<#cols>"),
|
2006-07-31 01:30:31 +00:00
|
|
|
N_("Set width of a tab to #cols columns"));
|
2006-05-12 19:30:28 +00:00
|
|
|
print_opt("-U", "--quickblank", N_("Do quick statusbar blanking"));
|
2015-05-03 13:56:51 +00:00
|
|
|
print_opt("-V", "--version", N_("Print version information and exit"));
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2006-05-12 19:30:28 +00:00
|
|
|
print_opt("-W", "--wordbounds",
|
2005-08-10 22:12:28 +00:00
|
|
|
N_("Detect word boundaries more accurately"));
|
2016-08-07 15:02:02 +00:00
|
|
|
print_opt(_("-X <str>"), _("--wordchars=<str>"),
|
2016-06-30 16:02:45 +00:00
|
|
|
N_("Which other characters are word parts"));
|
2005-08-10 22:12:28 +00:00
|
|
|
#endif
|
2017-11-01 18:45:33 +00:00
|
|
|
#ifdef ENABLE_COLOR
|
2015-07-29 19:31:50 +00:00
|
|
|
if (!ISSET(RESTRICTED))
|
2017-02-25 13:05:07 +00:00
|
|
|
print_opt(_("-Y <name>"), _("--syntax=<name>"),
|
2015-07-30 11:29:45 +00:00
|
|
|
N_("Syntax definition to use for coloring"));
|
2017-06-28 14:57:46 +00:00
|
|
|
#endif
|
|
|
|
#ifndef NANO_TINY
|
|
|
|
print_opt("-a", "--atblanks", N_("When soft-wrapping, do it at whitespace"));
|
2002-05-04 04:23:30 +00:00
|
|
|
#endif
|
2015-07-15 19:40:37 +00:00
|
|
|
print_opt("-c", "--constantshow", N_("Constantly show cursor position"));
|
2006-05-12 19:30:28 +00:00
|
|
|
print_opt("-d", "--rebinddelete",
|
2005-05-21 17:15:46 +00:00
|
|
|
N_("Fix Backspace/Delete confusion problem"));
|
2017-05-08 17:08:23 +00:00
|
|
|
#ifdef ENABLE_BROWSER
|
2017-03-04 18:04:15 +00:00
|
|
|
if (!ISSET(RESTRICTED))
|
|
|
|
print_opt("-g", "--showcursor", N_("Show cursor in file browser"));
|
|
|
|
#endif
|
2015-08-01 08:47:38 +00:00
|
|
|
print_opt("-h", "--help", N_("Show this help text and exit"));
|
2014-06-19 20:05:24 +00:00
|
|
|
#ifndef NANO_TINY
|
2015-05-03 13:56:51 +00:00
|
|
|
print_opt("-i", "--autoindent", N_("Automatically indent new lines"));
|
2017-07-14 14:06:52 +00:00
|
|
|
print_opt("-k", "--cutfromcursor", N_("Cut from cursor to end of line"));
|
2005-03-26 22:49:46 +00:00
|
|
|
#endif
|
2016-10-20 08:44:29 +00:00
|
|
|
#ifdef ENABLE_LINENUMBERS
|
|
|
|
print_opt("-l", "--linenumbers", N_("Show line numbers in front of the text"));
|
|
|
|
#endif
|
2017-05-01 18:45:07 +00:00
|
|
|
#ifdef ENABLE_MOUSE
|
2006-06-08 02:37:45 +00:00
|
|
|
print_opt("-m", "--mouse", N_("Enable the use of the mouse"));
|
2000-06-06 05:53:49 +00:00
|
|
|
#endif
|
2014-04-08 18:59:30 +00:00
|
|
|
print_opt("-n", "--noread", N_("Do not read the file (only write it)"));
|
2017-10-29 20:08:07 +00:00
|
|
|
#ifdef ENABLE_OPERATINGDIR
|
2006-05-14 15:19:38 +00:00
|
|
|
print_opt(_("-o <dir>"), _("--operatingdir=<dir>"),
|
2005-05-21 17:15:46 +00:00
|
|
|
N_("Set operating directory"));
|
2000-06-06 05:53:49 +00:00
|
|
|
#endif
|
2015-05-03 13:56:51 +00:00
|
|
|
print_opt("-p", "--preserve", N_("Preserve XON (^Q) and XOFF (^S) keys"));
|
2017-10-31 16:39:30 +00:00
|
|
|
#ifdef ENABLED_WRAPORJUSTIFY
|
2006-05-14 15:19:38 +00:00
|
|
|
print_opt(_("-r <#cols>"), _("--fill=<#cols>"),
|
2014-04-23 20:42:55 +00:00
|
|
|
N_("Set hard-wrapping point at column #cols"));
|
2001-05-21 12:56:25 +00:00
|
|
|
#endif
|
2017-10-31 18:32:42 +00:00
|
|
|
#ifdef ENABLE_SPELLER
|
2015-07-29 19:31:50 +00:00
|
|
|
if (!ISSET(RESTRICTED))
|
2015-07-30 11:29:45 +00:00
|
|
|
print_opt(_("-s <prog>"), _("--speller=<prog>"),
|
|
|
|
N_("Enable alternate speller"));
|
2001-01-12 07:51:05 +00:00
|
|
|
#endif
|
2015-05-03 13:56:51 +00:00
|
|
|
print_opt("-t", "--tempfile", N_("Auto save on exit, don't prompt"));
|
2015-08-09 16:31:01 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
print_opt("-u", "--unix", N_("Save a file by default in Unix format"));
|
|
|
|
#endif
|
2006-07-31 01:30:31 +00:00
|
|
|
print_opt("-v", "--view", N_("View mode (read-only)"));
|
2017-10-29 20:00:09 +00:00
|
|
|
#ifdef ENABLE_WRAPPING
|
2014-04-23 20:42:55 +00:00
|
|
|
print_opt("-w", "--nowrap", N_("Don't hard-wrap long lines"));
|
2000-06-06 05:53:49 +00:00
|
|
|
#endif
|
2006-06-08 02:37:45 +00:00
|
|
|
print_opt("-x", "--nohelp", N_("Don't show the two help lines"));
|
2015-07-29 19:31:50 +00:00
|
|
|
if (!ISSET(RESTRICTED))
|
2015-07-30 11:29:45 +00:00
|
|
|
print_opt("-z", "--suspend", N_("Enable suspension"));
|
2014-03-03 21:30:50 +00:00
|
|
|
#ifndef NANO_TINY
|
2009-08-17 07:52:10 +00:00
|
|
|
print_opt("-$", "--softwrap", N_("Enable soft line wrapping"));
|
2014-03-03 21:30:50 +00:00
|
|
|
#endif
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Display the current version of nano, the date and time it was
|
|
|
|
* compiled, contact information for it, and the configuration options
|
|
|
|
* it was compiled with. */
|
2002-08-21 16:10:37 +00:00
|
|
|
void version(void)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2016-04-08 08:22:09 +00:00
|
|
|
#ifdef REVISION
|
2016-08-14 19:18:00 +00:00
|
|
|
printf(" GNU nano from git, %s\n", REVISION);
|
2016-04-08 08:22:09 +00:00
|
|
|
#else
|
2016-08-14 19:18:00 +00:00
|
|
|
printf(_(" GNU nano, version %s\n"), VERSION);
|
2016-04-08 08:22:09 +00:00
|
|
|
#endif
|
2017-04-11 11:52:53 +00:00
|
|
|
printf(" (C) 1999-2011, 2013-2017 Free Software Foundation, Inc.\n");
|
|
|
|
printf(_(" (C) 2014-%s the contributors to nano\n"), "2017");
|
|
|
|
printf(_(" Email: nano@nano-editor.org Web: https://nano-editor.org/"));
|
2000-11-24 20:45:14 +00:00
|
|
|
printf(_("\n Compiled options:"));
|
2000-12-01 18:46:01 +00:00
|
|
|
|
2014-04-05 19:57:17 +00:00
|
|
|
#ifdef NANO_TINY
|
|
|
|
printf(" --enable-tiny");
|
2017-05-08 17:08:23 +00:00
|
|
|
#ifdef ENABLE_BROWSER
|
2014-04-05 19:57:17 +00:00
|
|
|
printf(" --enable-browser");
|
|
|
|
#endif
|
2017-11-01 18:45:33 +00:00
|
|
|
#ifdef ENABLE_COLOR
|
2014-04-05 19:57:17 +00:00
|
|
|
printf(" --enable-color");
|
|
|
|
#endif
|
2017-11-01 19:33:14 +00:00
|
|
|
#ifdef ENABLE_EXTRA
|
2014-04-05 19:57:17 +00:00
|
|
|
printf(" --enable-extra");
|
|
|
|
#endif
|
2017-04-25 15:51:45 +00:00
|
|
|
#ifdef ENABLE_HELP
|
2014-04-05 19:57:17 +00:00
|
|
|
printf(" --enable-help");
|
|
|
|
#endif
|
2017-10-29 18:42:12 +00:00
|
|
|
#ifdef ENABLE_HISTORIES
|
2014-06-19 20:05:24 +00:00
|
|
|
printf(" --enable-histories");
|
|
|
|
#endif
|
2017-10-31 16:34:07 +00:00
|
|
|
#ifdef ENABLE_JUSTIFY
|
2014-04-05 19:57:17 +00:00
|
|
|
printf(" --enable-justify");
|
|
|
|
#endif
|
2014-04-13 19:54:47 +00:00
|
|
|
#ifdef HAVE_LIBMAGIC
|
|
|
|
printf(" --enable-libmagic");
|
|
|
|
#endif
|
2016-10-20 08:44:29 +00:00
|
|
|
#ifdef ENABLE_LINENUMBERS
|
|
|
|
printf(" --enable-linenumbers");
|
|
|
|
#endif
|
2017-05-01 18:45:07 +00:00
|
|
|
#ifdef ENABLE_MOUSE
|
2014-04-05 19:57:17 +00:00
|
|
|
printf(" --enable-mouse");
|
|
|
|
#endif
|
2017-05-08 17:42:44 +00:00
|
|
|
#ifdef ENABLE_NANORC
|
2014-04-13 20:50:20 +00:00
|
|
|
printf(" --enable-nanorc");
|
|
|
|
#endif
|
2017-05-01 18:20:34 +00:00
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
2014-04-05 19:57:17 +00:00
|
|
|
printf(" --enable-multibuffer");
|
|
|
|
#endif
|
2017-10-29 20:08:07 +00:00
|
|
|
#ifdef ENABLE_OPERATINGDIR
|
2014-04-05 19:57:17 +00:00
|
|
|
printf(" --enable-operatingdir");
|
|
|
|
#endif
|
2017-10-31 18:32:42 +00:00
|
|
|
#ifdef ENABLE_SPELLER
|
2014-04-05 19:57:17 +00:00
|
|
|
printf(" --enable-speller");
|
|
|
|
#endif
|
2017-05-08 17:15:51 +00:00
|
|
|
#ifdef ENABLE_TABCOMP
|
2014-04-05 19:57:17 +00:00
|
|
|
printf(" --enable-tabcomp");
|
|
|
|
#endif
|
2017-10-29 20:00:09 +00:00
|
|
|
#ifdef ENABLE_WRAPPING
|
2014-04-05 19:57:17 +00:00
|
|
|
printf(" --enable-wrapping");
|
|
|
|
#endif
|
|
|
|
#else /* !NANO_TINY */
|
2017-05-08 17:08:23 +00:00
|
|
|
#ifndef ENABLE_BROWSER
|
2001-01-05 05:41:07 +00:00
|
|
|
printf(" --disable-browser");
|
2001-04-12 03:01:53 +00:00
|
|
|
#endif
|
2017-11-01 18:45:33 +00:00
|
|
|
#ifndef ENABLE_COLOR
|
2014-04-05 19:57:17 +00:00
|
|
|
printf(" --disable-color");
|
|
|
|
#endif
|
2016-05-25 20:13:50 +00:00
|
|
|
#ifndef ENABLE_COMMENT
|
|
|
|
printf(" --disable-comment");
|
|
|
|
#endif
|
2017-11-01 19:33:14 +00:00
|
|
|
#ifndef ENABLE_EXTRA
|
2014-04-03 20:57:44 +00:00
|
|
|
printf(" --disable-extra");
|
|
|
|
#endif
|
2017-04-25 15:51:45 +00:00
|
|
|
#ifndef ENABLE_HELP
|
2002-09-06 20:35:28 +00:00
|
|
|
printf(" --disable-help");
|
2001-04-12 03:01:53 +00:00
|
|
|
#endif
|
2017-10-29 18:42:12 +00:00
|
|
|
#ifndef ENABLE_HISTORIES
|
2014-06-19 20:05:24 +00:00
|
|
|
printf(" --disable-histories");
|
|
|
|
#endif
|
2017-10-31 16:34:07 +00:00
|
|
|
#ifndef ENABLE_JUSTIFY
|
2000-12-01 18:46:01 +00:00
|
|
|
printf(" --disable-justify");
|
2001-04-12 03:01:53 +00:00
|
|
|
#endif
|
2014-04-13 19:54:47 +00:00
|
|
|
#ifndef HAVE_LIBMAGIC
|
|
|
|
printf(" --disable-libmagic");
|
|
|
|
#endif
|
2016-10-20 08:44:29 +00:00
|
|
|
#ifndef ENABLE_LINENUMBERS
|
|
|
|
printf(" --disable-linenumbers");
|
|
|
|
#endif
|
2017-05-01 18:45:07 +00:00
|
|
|
#ifndef ENABLE_MOUSE
|
2001-04-12 14:51:48 +00:00
|
|
|
printf(" --disable-mouse");
|
2000-12-18 05:36:51 +00:00
|
|
|
#endif
|
2017-05-01 18:20:34 +00:00
|
|
|
#ifndef ENABLE_MULTIBUFFER
|
2014-04-03 20:23:07 +00:00
|
|
|
printf(" --disable-multibuffer");
|
|
|
|
#endif
|
2017-05-08 17:42:44 +00:00
|
|
|
#ifndef ENABLE_NANORC
|
2014-04-13 20:50:20 +00:00
|
|
|
printf(" --disable-nanorc");
|
|
|
|
#endif
|
2017-10-29 20:08:07 +00:00
|
|
|
#ifndef ENABLE_OPERATINGDIR
|
2001-09-19 03:19:43 +00:00
|
|
|
printf(" --disable-operatingdir");
|
|
|
|
#endif
|
2017-10-31 18:32:42 +00:00
|
|
|
#ifndef ENABLE_SPELLER
|
2002-09-06 20:35:28 +00:00
|
|
|
printf(" --disable-speller");
|
|
|
|
#endif
|
2017-05-08 17:15:51 +00:00
|
|
|
#ifndef ENABLE_TABCOMP
|
2002-09-06 20:35:28 +00:00
|
|
|
printf(" --disable-tabcomp");
|
|
|
|
#endif
|
2016-12-15 11:38:47 +00:00
|
|
|
#ifndef ENABLE_WORDCOMPLETION
|
|
|
|
printf(" --disable-wordcomp");
|
|
|
|
#endif
|
2017-10-29 20:00:09 +00:00
|
|
|
#ifndef ENABLE_WRAPPING
|
2002-09-06 20:35:28 +00:00
|
|
|
printf(" --disable-wrapping");
|
|
|
|
#endif
|
2014-04-05 19:57:17 +00:00
|
|
|
#endif /* !NANO_TINY */
|
|
|
|
|
2006-07-19 15:50:19 +00:00
|
|
|
#ifdef DISABLE_ROOTWRAPPING
|
2002-10-25 16:08:53 +00:00
|
|
|
printf(" --disable-wrapping-as-root");
|
|
|
|
#endif
|
2005-06-29 17:10:58 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
printf(" --enable-debug");
|
|
|
|
#endif
|
2014-04-05 19:57:17 +00:00
|
|
|
#ifndef ENABLE_NLS
|
|
|
|
printf(" --disable-nls");
|
2005-06-29 17:10:58 +00:00
|
|
|
#endif
|
2005-07-17 02:40:07 +00:00
|
|
|
#ifdef ENABLE_UTF8
|
2005-06-29 17:10:58 +00:00
|
|
|
printf(" --enable-utf8");
|
2014-04-05 19:57:17 +00:00
|
|
|
#else
|
|
|
|
printf(" --disable-utf8");
|
2007-12-18 15:55:48 +00:00
|
|
|
#endif
|
|
|
|
#ifdef USE_SLANG
|
|
|
|
printf(" --with-slang");
|
2000-11-24 20:45:14 +00:00
|
|
|
#endif
|
|
|
|
printf("\n");
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
|
2007-01-09 22:56:56 +00:00
|
|
|
/* If the current file buffer has been modified, and the TEMP_FILE flag
|
|
|
|
* isn't set, ask whether or not to save the file buffer. If the
|
2014-06-16 20:44:34 +00:00
|
|
|
* TEMP_FILE flag is set and the current file has a name, save it
|
|
|
|
* unconditionally. Then, if more than one file buffer is open, close
|
|
|
|
* the current file buffer and switch to the next one. If only one file
|
|
|
|
* buffer is open, exit from nano. */
|
2004-07-02 14:31:03 +00:00
|
|
|
void do_exit(void)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2002-09-06 20:35:28 +00:00
|
|
|
int i;
|
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* If the file hasn't been modified, pretend the user chose not to
|
|
|
|
* save. */
|
2005-07-08 20:09:16 +00:00
|
|
|
if (!openfile->modified)
|
2005-11-07 21:45:44 +00:00
|
|
|
i = 0;
|
2014-06-16 20:44:34 +00:00
|
|
|
/* If the TEMP_FILE flag is set and the current file has a name,
|
|
|
|
* pretend the user chose to save. */
|
|
|
|
else if (openfile->filename[0] != '\0' && ISSET(TEMP_FILE))
|
2002-09-06 20:35:28 +00:00
|
|
|
i = 1;
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Otherwise, ask the user whether or not to save. */
|
2014-06-16 20:44:34 +00:00
|
|
|
else {
|
|
|
|
/* If the TEMP_FILE flag is set, and the current file doesn't
|
2015-10-29 10:36:07 +00:00
|
|
|
* have a name, warn the user before prompting for a name. */
|
|
|
|
if (ISSET(TEMP_FILE))
|
2016-11-27 21:01:54 +00:00
|
|
|
warn_and_shortly_pause(_("No file name"));
|
2014-06-16 20:44:34 +00:00
|
|
|
|
2016-05-30 07:09:36 +00:00
|
|
|
i = do_yesno_prompt(FALSE, _("Save modified buffer? "
|
|
|
|
"(Answering \"No\" will DISCARD changes.) "));
|
2014-06-16 20:44:34 +00:00
|
|
|
}
|
2004-07-02 14:31:03 +00:00
|
|
|
|
2002-09-06 20:35:28 +00:00
|
|
|
#ifdef DEBUG
|
2005-07-08 20:09:16 +00:00
|
|
|
dump_filestruct(openfile->fileage);
|
2001-10-22 03:15:31 +00:00
|
|
|
#endif
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* If the user chose not to save, or if the user chose to save and
|
|
|
|
* the save succeeded, we're ready to exit. */
|
2017-09-27 20:42:48 +00:00
|
|
|
if (i == 0 || (i == 1 && do_writeout(TRUE, TRUE) > 0))
|
2015-12-23 16:34:44 +00:00
|
|
|
close_and_go();
|
|
|
|
else if (i != 1)
|
|
|
|
statusbar(_("Cancelled"));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Close the current buffer, and terminate nano if it was the last. */
|
|
|
|
void close_and_go(void)
|
|
|
|
{
|
2013-01-01 03:24:39 +00:00
|
|
|
#ifndef NANO_TINY
|
2015-12-23 16:34:44 +00:00
|
|
|
/* If there is a lockfile, remove it. */
|
|
|
|
if (ISSET(LOCKING) && openfile->lock_filename)
|
|
|
|
delete_lockfile(openfile->lock_filename);
|
2014-03-17 14:15:57 +00:00
|
|
|
#endif
|
2017-05-01 18:20:34 +00:00
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
2015-12-23 16:34:44 +00:00
|
|
|
/* If there are no more open file buffers, jump off a cliff. */
|
2016-05-17 11:37:53 +00:00
|
|
|
if (!close_buffer())
|
2002-09-06 20:35:28 +00:00
|
|
|
#endif
|
2015-12-23 16:34:44 +00:00
|
|
|
finish();
|
2002-09-06 20:35:28 +00:00
|
|
|
}
|
|
|
|
|
2014-04-08 18:38:45 +00:00
|
|
|
/* Another placeholder for function mapping. */
|
2011-02-07 14:45:56 +00:00
|
|
|
void do_cancel(void)
|
|
|
|
{
|
|
|
|
;
|
|
|
|
}
|
2009-01-30 17:37:44 +00:00
|
|
|
|
2017-06-23 07:27:29 +00:00
|
|
|
/* Make a note that reading from stdin was concluded with ^C. */
|
|
|
|
RETSIGTYPE make_a_note(int signal)
|
2009-01-30 17:37:44 +00:00
|
|
|
{
|
2017-06-23 07:27:29 +00:00
|
|
|
input_was_aborted = TRUE;
|
2009-01-30 17:37:44 +00:00
|
|
|
}
|
|
|
|
|
2017-06-23 06:27:06 +00:00
|
|
|
/* Read whatever comes from standard input into a new buffer. */
|
|
|
|
bool scoop_stdin(void)
|
2009-01-30 17:37:44 +00:00
|
|
|
{
|
2017-06-23 07:00:15 +00:00
|
|
|
struct sigaction oldaction, newaction;
|
|
|
|
/* Original and temporary handlers for SIGINT. */
|
|
|
|
bool setup_failed = FALSE;
|
|
|
|
/* Whether setting up the SIGINT handler failed. */
|
2017-06-07 13:42:05 +00:00
|
|
|
FILE *stream;
|
|
|
|
int thetty;
|
|
|
|
|
2017-06-23 07:00:15 +00:00
|
|
|
/* Exit from curses mode and put the terminal into its original state. */
|
2009-01-30 17:37:44 +00:00
|
|
|
endwin();
|
2017-06-23 07:00:15 +00:00
|
|
|
tcsetattr(0, TCSANOW, &oldterm);
|
2017-06-07 13:42:05 +00:00
|
|
|
|
2009-01-30 17:37:44 +00:00
|
|
|
fprintf(stderr, _("Reading from stdin, ^C to abort\n"));
|
|
|
|
|
2016-09-03 10:14:08 +00:00
|
|
|
#ifndef NANO_TINY
|
2014-03-24 21:48:23 +00:00
|
|
|
/* Enable interpretation of the special control keys so that
|
|
|
|
* we get SIGINT when Ctrl-C is pressed. */
|
2009-01-30 17:37:44 +00:00
|
|
|
enable_signals();
|
2009-02-01 00:04:42 +00:00
|
|
|
#endif
|
2009-01-30 17:37:44 +00:00
|
|
|
|
2017-06-23 07:00:15 +00:00
|
|
|
/* Set things up so that SIGINT will cancel the reading. */
|
|
|
|
if (sigaction(SIGINT, NULL, &newaction) == -1) {
|
|
|
|
setup_failed = TRUE;
|
2009-01-30 17:37:44 +00:00
|
|
|
nperror("sigaction");
|
|
|
|
} else {
|
2017-06-23 07:27:29 +00:00
|
|
|
newaction.sa_handler = make_a_note;
|
2017-06-23 07:00:15 +00:00
|
|
|
if (sigaction(SIGINT, &newaction, &oldaction) == -1) {
|
|
|
|
setup_failed = TRUE;
|
2009-01-30 17:37:44 +00:00
|
|
|
nperror("sigaction");
|
|
|
|
}
|
|
|
|
}
|
2010-03-21 05:31:43 +00:00
|
|
|
|
2017-06-07 13:42:05 +00:00
|
|
|
/* Open standard input. */
|
|
|
|
stream = fopen("/dev/stdin", "rb");
|
2017-06-08 08:40:19 +00:00
|
|
|
if (stream == NULL) {
|
|
|
|
int errnumber = errno;
|
|
|
|
|
|
|
|
terminal_init();
|
|
|
|
doupdate();
|
|
|
|
statusline(ALERT, _("Failed to open stdin: %s"), strerror(errnumber));
|
2017-06-23 06:27:06 +00:00
|
|
|
return FALSE;
|
2017-06-08 08:40:19 +00:00
|
|
|
}
|
2017-06-07 13:42:05 +00:00
|
|
|
|
|
|
|
/* Read the input into a new buffer. */
|
2009-01-30 17:37:44 +00:00
|
|
|
open_buffer("", FALSE);
|
2017-06-07 13:42:05 +00:00
|
|
|
read_file(stream, 0, "stdin", TRUE, FALSE);
|
|
|
|
openfile->edittop = openfile->fileage;
|
|
|
|
|
|
|
|
/* Reconnect the tty as the input source. */
|
|
|
|
thetty = open("/dev/tty", O_RDONLY);
|
|
|
|
if (!thetty)
|
|
|
|
die(_("Couldn't reopen stdin from keyboard, sorry\n"));
|
|
|
|
dup2(thetty, 0);
|
|
|
|
close(thetty);
|
|
|
|
|
2017-06-23 07:27:29 +00:00
|
|
|
/* If things went well, store the current state of the terminal. */
|
|
|
|
if (!input_was_aborted)
|
2017-06-07 13:42:05 +00:00
|
|
|
tcgetattr(0, &oldterm);
|
2017-06-23 07:27:29 +00:00
|
|
|
|
|
|
|
/* If it was changed, restore the handler for SIGINT. */
|
2017-06-23 07:00:15 +00:00
|
|
|
if (!setup_failed && sigaction(SIGINT, &oldaction, NULL) == -1)
|
2017-06-07 13:42:05 +00:00
|
|
|
nperror("sigaction");
|
|
|
|
|
|
|
|
terminal_init();
|
|
|
|
doupdate();
|
2017-06-23 07:51:58 +00:00
|
|
|
|
2017-06-23 08:43:52 +00:00
|
|
|
if (!ISSET(VIEW_MODE) && openfile->totsize > 0)
|
2017-06-23 07:51:58 +00:00
|
|
|
set_modified();
|
|
|
|
|
2017-06-23 06:27:06 +00:00
|
|
|
return TRUE;
|
2009-01-30 17:37:44 +00:00
|
|
|
}
|
|
|
|
|
2017-06-06 15:57:15 +00:00
|
|
|
/* Register half a dozen signal handlers. */
|
2002-09-06 20:35:28 +00:00
|
|
|
void signal_init(void)
|
|
|
|
{
|
2015-05-03 13:56:51 +00:00
|
|
|
/* Trap SIGINT and SIGQUIT because we want them to do useful things. */
|
2002-09-06 20:35:28 +00:00
|
|
|
memset(&act, 0, sizeof(struct sigaction));
|
|
|
|
act.sa_handler = SIG_IGN;
|
|
|
|
sigaction(SIGINT, &act, NULL);
|
2017-02-21 22:04:47 +00:00
|
|
|
#ifdef SIGQUIT
|
2004-01-26 20:56:20 +00:00
|
|
|
sigaction(SIGQUIT, &act, NULL);
|
2017-02-21 22:04:47 +00:00
|
|
|
#endif
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2004-04-07 00:44:35 +00:00
|
|
|
/* Trap SIGHUP and SIGTERM because we want to write the file out. */
|
2002-10-17 02:19:31 +00:00
|
|
|
act.sa_handler = handle_hupterm;
|
2017-02-21 22:04:47 +00:00
|
|
|
#ifdef SIGHUP
|
2002-09-06 20:35:28 +00:00
|
|
|
sigaction(SIGHUP, &act, NULL);
|
2017-02-21 22:04:47 +00:00
|
|
|
#endif
|
2002-10-17 02:19:31 +00:00
|
|
|
sigaction(SIGTERM, &act, NULL);
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2004-04-07 00:44:35 +00:00
|
|
|
/* Trap SIGWINCH because we want to handle window resizes. */
|
2002-09-06 20:35:28 +00:00
|
|
|
act.sa_handler = handle_sigwinch;
|
|
|
|
sigaction(SIGWINCH, &act, NULL);
|
2002-03-21 05:07:28 +00:00
|
|
|
#endif
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2017-05-24 08:20:23 +00:00
|
|
|
if (ISSET(SUSPEND)) {
|
2004-04-07 00:44:35 +00:00
|
|
|
/* Block all other signals in the suspend and continue handlers.
|
|
|
|
* If we don't do this, other stuff interrupts them! */
|
2002-09-06 20:35:28 +00:00
|
|
|
sigfillset(&act.sa_mask);
|
2017-02-21 22:04:47 +00:00
|
|
|
#ifdef SIGTSTP
|
2017-06-06 15:57:15 +00:00
|
|
|
/* Trap a normal suspend (^Z) so we can handle it ourselves. */
|
2017-05-24 08:20:23 +00:00
|
|
|
act.sa_handler = do_suspend;
|
2002-09-06 20:35:28 +00:00
|
|
|
sigaction(SIGTSTP, &act, NULL);
|
2017-02-21 22:04:47 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGCONT
|
2017-05-24 08:20:23 +00:00
|
|
|
act.sa_handler = do_continue;
|
2002-09-06 20:35:28 +00:00
|
|
|
sigaction(SIGCONT, &act, NULL);
|
2017-05-24 08:20:23 +00:00
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
#ifdef SIGTSTP
|
|
|
|
act.sa_handler = SIG_IGN;
|
|
|
|
sigaction(SIGTSTP, &act, NULL);
|
2017-02-21 22:04:47 +00:00
|
|
|
#endif
|
2002-09-06 20:35:28 +00:00
|
|
|
}
|
|
|
|
}
|
2000-09-01 13:32:47 +00:00
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
/* Handler for SIGHUP (hangup) and SIGTERM (terminate). */
|
2005-12-06 19:39:56 +00:00
|
|
|
RETSIGTYPE handle_hupterm(int signal)
|
2002-09-06 20:35:28 +00:00
|
|
|
{
|
2003-02-03 03:32:08 +00:00
|
|
|
die(_("Received SIGHUP or SIGTERM\n"));
|
2002-09-06 20:35:28 +00:00
|
|
|
}
|
2002-06-21 03:20:06 +00:00
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
/* Handler for SIGTSTP (suspend). */
|
2005-12-06 19:39:56 +00:00
|
|
|
RETSIGTYPE do_suspend(int signal)
|
2002-09-06 20:35:28 +00:00
|
|
|
{
|
2017-05-01 18:45:07 +00:00
|
|
|
#ifdef ENABLE_MOUSE
|
2006-06-09 18:24:37 +00:00
|
|
|
disable_mouse_support();
|
|
|
|
#endif
|
|
|
|
|
2009-11-29 06:24:10 +00:00
|
|
|
/* Move the cursor to the last line of the screen. */
|
2006-06-09 16:04:19 +00:00
|
|
|
move(LINES - 1, 0);
|
2009-11-28 03:01:30 +00:00
|
|
|
endwin();
|
2006-06-03 17:31:52 +00:00
|
|
|
|
2006-06-09 16:04:19 +00:00
|
|
|
/* Display our helpful message. */
|
|
|
|
printf(_("Use \"fg\" to return to nano.\n"));
|
2002-09-06 20:35:28 +00:00
|
|
|
fflush(stdout);
|
2000-09-01 13:32:47 +00:00
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
/* Restore the old terminal settings. */
|
2002-09-06 20:35:28 +00:00
|
|
|
tcsetattr(0, TCSANOW, &oldterm);
|
2002-02-15 19:17:02 +00:00
|
|
|
|
2017-02-21 22:04:47 +00:00
|
|
|
#ifdef SIGSTOP
|
2017-05-24 08:20:23 +00:00
|
|
|
/* Do what mutt does: send ourselves a SIGSTOP. */
|
2002-09-06 20:35:28 +00:00
|
|
|
kill(0, SIGSTOP);
|
2017-02-21 22:04:47 +00:00
|
|
|
#endif
|
2002-09-06 20:35:28 +00:00
|
|
|
}
|
2002-06-21 03:20:06 +00:00
|
|
|
|
2017-06-06 15:57:15 +00:00
|
|
|
/* Put nano to sleep (if suspension is enabled). */
|
2010-11-12 06:22:12 +00:00
|
|
|
void do_suspend_void(void)
|
2008-03-13 08:23:52 +00:00
|
|
|
{
|
|
|
|
if (ISSET(SUSPEND))
|
|
|
|
do_suspend(0);
|
2015-07-30 20:15:01 +00:00
|
|
|
else {
|
|
|
|
statusbar(_("Suspension is not enabled"));
|
|
|
|
beep();
|
|
|
|
}
|
2008-03-13 08:23:52 +00:00
|
|
|
}
|
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
/* Handler for SIGCONT (continue after suspend). */
|
2005-12-06 19:39:56 +00:00
|
|
|
RETSIGTYPE do_continue(int signal)
|
2002-09-06 20:35:28 +00:00
|
|
|
{
|
2017-05-01 18:45:07 +00:00
|
|
|
#ifdef ENABLE_MOUSE
|
2006-06-09 18:24:37 +00:00
|
|
|
if (ISSET(USE_MOUSE))
|
|
|
|
enable_mouse_support();
|
|
|
|
#endif
|
|
|
|
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2017-06-02 11:19:19 +00:00
|
|
|
/* Perhaps the user resized the window while we slept. */
|
2017-05-31 12:44:42 +00:00
|
|
|
the_window_resized = TRUE;
|
2004-04-07 00:44:35 +00:00
|
|
|
#else
|
2017-06-06 15:57:15 +00:00
|
|
|
/* Put the terminal in the desired state again. */
|
2006-06-09 16:04:19 +00:00
|
|
|
terminal_init();
|
2002-09-06 20:35:28 +00:00
|
|
|
#endif
|
2017-06-02 11:19:19 +00:00
|
|
|
/* Tickle the input routine so it will update the screen. */
|
2017-07-16 11:14:16 +00:00
|
|
|
ungetch(KEY_FLUSH);
|
2002-09-06 20:35:28 +00:00
|
|
|
}
|
|
|
|
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Handler for SIGWINCH (window size change). */
|
2005-12-06 19:39:56 +00:00
|
|
|
RETSIGTYPE handle_sigwinch(int signal)
|
2015-05-28 13:02:29 +00:00
|
|
|
{
|
|
|
|
/* Let the input routine know that a SIGWINCH has occurred. */
|
2016-12-14 19:37:03 +00:00
|
|
|
the_window_resized = TRUE;
|
2015-05-28 13:02:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Reinitialize and redraw the screen completely. */
|
|
|
|
void regenerate_screen(void)
|
2002-09-06 20:35:28 +00:00
|
|
|
{
|
|
|
|
const char *tty = ttyname(0);
|
2005-03-08 16:41:53 +00:00
|
|
|
int fd, result = 0;
|
2002-09-06 20:35:28 +00:00
|
|
|
struct winsize win;
|
|
|
|
|
2016-12-14 19:37:03 +00:00
|
|
|
/* Reset the trigger. */
|
|
|
|
the_window_resized = FALSE;
|
|
|
|
|
2002-12-22 16:30:00 +00:00
|
|
|
if (tty == NULL)
|
2002-09-06 20:35:28 +00:00
|
|
|
return;
|
|
|
|
fd = open(tty, O_RDWR);
|
|
|
|
if (fd == -1)
|
|
|
|
return;
|
|
|
|
result = ioctl(fd, TIOCGWINSZ, &win);
|
|
|
|
close(fd);
|
|
|
|
if (result == -1)
|
|
|
|
return;
|
|
|
|
|
2006-03-20 04:46:48 +00:00
|
|
|
/* We could check whether the COLS or LINES changed, and return
|
|
|
|
* otherwise. However, COLS and LINES are curses global variables,
|
|
|
|
* and in some cases curses has already updated them. But not in
|
|
|
|
* all cases. Argh. */
|
2014-03-26 10:45:07 +00:00
|
|
|
#ifdef REDEFINING_MACROS_OK
|
2002-09-06 20:35:28 +00:00
|
|
|
COLS = win.ws_col;
|
|
|
|
LINES = win.ws_row;
|
2010-03-07 19:35:46 +00:00
|
|
|
#endif
|
2016-10-20 08:44:29 +00:00
|
|
|
editwincols = COLS - margin;
|
2002-09-06 20:35:28 +00:00
|
|
|
|
softwrap: adjust firstcolumn when the window width changes
If the number of columns in the edit window changes (which currently
only happens in two places: in regenerate_screen(), called when the
window is resized; and in main(), when line numbering mode is toggled),
the display will break if we're in softwrap mode and firstcolumn is
nonzero. This is because the column width of softwrapped chunks has
changed, and firstcolumn is no longer the starting column of a chunk,
an assumption that all code using firstcolumn relies on.
To fix this problem, add a new function, ensure_firstcolumn_is_aligned(),
to adjust firstcolumn to the starting column of the chunk it's on, and
use it when the number of columns in the edit window changes.
(Note that this function uses the simplest possible fix, and could
probably be made more sophisticated.)
2017-01-23 19:40:03 +00:00
|
|
|
/* Ensure that firstcolumn is the starting column of its chunk. */
|
|
|
|
ensure_firstcolumn_is_aligned();
|
|
|
|
|
2007-12-18 15:55:48 +00: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
|
2017-06-06 15:57:15 +00:00
|
|
|
/* Do the equivalent of what Minimum Profit does: leave and immediately
|
|
|
|
* reenter curses mode. */
|
2004-05-18 01:20:36 +00:00
|
|
|
endwin();
|
2005-08-14 20:08:49 +00:00
|
|
|
doupdate();
|
2007-12-18 15:55:48 +00:00
|
|
|
#endif
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2017-06-06 15:57:15 +00:00
|
|
|
/* Put the terminal in the desired state again, recreate the subwindows
|
|
|
|
* with their (new) sizes, and redraw the contents of these windows. */
|
2004-07-27 16:46:35 +00:00
|
|
|
terminal_init();
|
2004-05-18 01:20:36 +00:00
|
|
|
window_init();
|
2002-09-06 20:35:28 +00:00
|
|
|
total_refresh();
|
|
|
|
}
|
2004-02-16 20:32:40 +00:00
|
|
|
|
2016-01-04 10:37:11 +00:00
|
|
|
/* If allow is FALSE, block any SIGWINCH signal. If allow is TRUE,
|
|
|
|
* unblock SIGWINCH so any pending ones can be dealt with. */
|
|
|
|
void allow_sigwinch(bool allow)
|
2004-02-16 20:32:40 +00:00
|
|
|
{
|
|
|
|
sigset_t winch;
|
2015-07-28 19:39:34 +00:00
|
|
|
|
2004-02-16 20:32:40 +00:00
|
|
|
sigemptyset(&winch);
|
|
|
|
sigaddset(&winch, SIGWINCH);
|
2005-07-01 22:58:47 +00:00
|
|
|
sigprocmask(allow ? SIG_UNBLOCK : SIG_BLOCK, &winch, NULL);
|
2004-02-16 20:32:40 +00:00
|
|
|
}
|
2002-06-21 03:20:06 +00:00
|
|
|
|
2014-03-24 21:48:23 +00:00
|
|
|
/* Handle the global toggle specified in flag. */
|
2008-03-05 07:34:01 +00:00
|
|
|
void do_toggle(int flag)
|
2000-09-01 13:32:47 +00:00
|
|
|
{
|
2004-08-05 22:10:22 +00:00
|
|
|
bool enabled;
|
2000-09-02 18:44:21 +00:00
|
|
|
|
2015-07-29 20:21:45 +00:00
|
|
|
if (ISSET(RESTRICTED) && (flag == SUSPEND || flag == MULTIBUFFER ||
|
|
|
|
flag == BACKUP_FILE || flag == NO_COLOR_SYNTAX)) {
|
2015-07-30 18:10:16 +00:00
|
|
|
show_restricted_warning();
|
2015-07-29 20:21:45 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-03-05 07:34:01 +00:00
|
|
|
TOGGLE(flag);
|
2000-09-12 23:02:49 +00:00
|
|
|
|
2008-03-05 07:34:01 +00:00
|
|
|
switch (flag) {
|
2017-05-01 18:45:07 +00:00
|
|
|
#ifdef ENABLE_MOUSE
|
2008-03-05 07:34:01 +00:00
|
|
|
case USE_MOUSE:
|
2004-11-27 16:54:00 +00:00
|
|
|
mouse_init();
|
|
|
|
break;
|
2002-12-22 16:30:00 +00:00
|
|
|
#endif
|
2008-03-05 07:34:01 +00:00
|
|
|
case MORE_SPACE:
|
|
|
|
case NO_HELP:
|
2004-11-27 16:54:00 +00:00
|
|
|
window_init();
|
2017-05-05 20:48:54 +00:00
|
|
|
focusing = FALSE;
|
2005-01-17 05:06:55 +00:00
|
|
|
total_refresh();
|
2004-11-27 16:54:00 +00:00
|
|
|
break;
|
2008-03-05 07:34:01 +00:00
|
|
|
case SUSPEND:
|
2005-01-17 05:06:55 +00:00
|
|
|
signal_init();
|
2004-11-27 16:54:00 +00:00
|
|
|
break;
|
2017-01-21 16:54:47 +00:00
|
|
|
case SOFTWRAP:
|
|
|
|
if (!ISSET(SOFTWRAP))
|
|
|
|
openfile->firstcolumn = 0;
|
|
|
|
refresh_needed = TRUE;
|
|
|
|
break;
|
2008-03-05 07:34:01 +00:00
|
|
|
case WHITESPACE_DISPLAY:
|
2016-12-03 16:00:28 +00:00
|
|
|
titlebar(NULL); /* Fall through. */
|
2017-11-01 18:45:33 +00:00
|
|
|
#ifdef ENABLE_COLOR
|
2008-03-05 07:34:01 +00:00
|
|
|
case NO_COLOR_SYNTAX:
|
2002-12-22 16:30:00 +00:00
|
|
|
#endif
|
2016-10-21 11:52:40 +00:00
|
|
|
refresh_needed = TRUE;
|
2009-08-17 07:52:10 +00:00
|
|
|
break;
|
2000-09-01 13:32:47 +00:00
|
|
|
}
|
2000-09-12 23:02:49 +00:00
|
|
|
|
2008-03-05 07:34:01 +00:00
|
|
|
enabled = ISSET(flag);
|
2005-06-09 04:00:03 +00:00
|
|
|
|
2016-12-03 19:25:16 +00:00
|
|
|
if (flag == NO_HELP || flag == NO_WRAP || flag == NO_COLOR_SYNTAX)
|
2002-07-19 01:08:59 +00:00
|
|
|
enabled = !enabled;
|
2005-06-09 04:00:03 +00:00
|
|
|
|
2016-04-30 15:31:43 +00:00
|
|
|
statusline(HUSH, "%s %s", _(flagtostr(flag)),
|
2017-04-22 16:27:01 +00:00
|
|
|
enabled ? _("enabled") : _("disabled"));
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
2011-02-07 14:45:56 +00:00
|
|
|
|
2014-04-08 18:38:45 +00:00
|
|
|
/* Bleh. */
|
2011-02-07 14:45:56 +00:00
|
|
|
void do_toggle_void(void)
|
|
|
|
{
|
2014-04-08 18:38:45 +00:00
|
|
|
;
|
2011-02-07 14:45:56 +00:00
|
|
|
}
|
2016-09-01 07:36:47 +00:00
|
|
|
#endif /* !NANO_TINY */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Disable extended input and output processing in our terminal
|
|
|
|
* settings. */
|
2005-06-09 04:02:57 +00:00
|
|
|
void disable_extended_io(void)
|
2004-09-22 22:45:08 +00:00
|
|
|
{
|
2017-02-21 22:04:48 +00:00
|
|
|
#ifdef HAVE_TERMIOS_H
|
2004-09-22 22:45:08 +00:00
|
|
|
struct termios term;
|
|
|
|
|
|
|
|
tcgetattr(0, &term);
|
|
|
|
term.c_lflag &= ~IEXTEN;
|
2005-06-09 04:02:57 +00:00
|
|
|
term.c_oflag &= ~OPOST;
|
2004-09-22 22:45:08 +00:00
|
|
|
tcsetattr(0, TCSANOW, &term);
|
2017-02-21 22:04:48 +00:00
|
|
|
#endif
|
2004-09-22 22:45:08 +00:00
|
|
|
}
|
|
|
|
|
2007-12-18 15:55:48 +00:00
|
|
|
/* Disable interpretation of the special control keys in our terminal
|
|
|
|
* settings. */
|
|
|
|
void disable_signals(void)
|
|
|
|
{
|
2017-02-21 22:04:48 +00:00
|
|
|
#ifdef HAVE_TERMIOS_H
|
2007-12-18 15:55:48 +00:00
|
|
|
struct termios term;
|
|
|
|
|
|
|
|
tcgetattr(0, &term);
|
|
|
|
term.c_lflag &= ~ISIG;
|
|
|
|
tcsetattr(0, TCSANOW, &term);
|
2017-02-21 22:04:48 +00:00
|
|
|
#endif
|
2007-12-18 15:55:48 +00:00
|
|
|
}
|
|
|
|
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Enable interpretation of the special control keys in our terminal
|
|
|
|
* settings. */
|
2004-05-18 01:20:36 +00:00
|
|
|
void enable_signals(void)
|
|
|
|
{
|
2017-02-21 22:04:48 +00:00
|
|
|
#ifdef HAVE_TERMIOS_H
|
2004-05-18 01:20:36 +00:00
|
|
|
struct termios term;
|
|
|
|
|
|
|
|
tcgetattr(0, &term);
|
|
|
|
term.c_lflag |= ISIG;
|
|
|
|
tcsetattr(0, TCSANOW, &term);
|
2017-02-21 22:04:48 +00:00
|
|
|
#endif
|
2004-05-18 01:20:36 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Disable interpretation of the flow control characters in our terminal
|
|
|
|
* settings. */
|
2004-05-18 01:20:36 +00:00
|
|
|
void disable_flow_control(void)
|
|
|
|
{
|
2017-02-21 22:04:48 +00:00
|
|
|
#ifdef HAVE_TERMIOS_H
|
2004-05-18 01:20:36 +00:00
|
|
|
struct termios term;
|
|
|
|
|
|
|
|
tcgetattr(0, &term);
|
2005-06-23 22:28:56 +00:00
|
|
|
term.c_iflag &= ~IXON;
|
2004-05-18 01:20:36 +00:00
|
|
|
tcsetattr(0, TCSANOW, &term);
|
2017-02-21 22:04:48 +00:00
|
|
|
#endif
|
2004-05-18 01:20:36 +00:00
|
|
|
}
|
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Enable interpretation of the flow control characters in our terminal
|
|
|
|
* settings. */
|
2004-05-18 01:20:36 +00:00
|
|
|
void enable_flow_control(void)
|
|
|
|
{
|
2017-02-21 22:04:48 +00:00
|
|
|
#ifdef HAVE_TERMIOS_H
|
2004-05-18 01:20:36 +00:00
|
|
|
struct termios term;
|
|
|
|
|
|
|
|
tcgetattr(0, &term);
|
2005-06-23 22:28:56 +00:00
|
|
|
term.c_iflag |= IXON;
|
2004-05-18 01:20:36 +00:00
|
|
|
tcsetattr(0, TCSANOW, &term);
|
2017-02-21 22:04:48 +00:00
|
|
|
#endif
|
2004-05-18 01:20:36 +00:00
|
|
|
}
|
|
|
|
|
2007-12-18 02:03:00 +00:00
|
|
|
/* Set up the terminal state. Put the terminal in raw mode (read one
|
|
|
|
* character at a time, disable the special control keys, and disable
|
|
|
|
* the flow control characters), 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 echoing of characters as they're
|
|
|
|
* typed. Finally, disable extended input and output processing, and,
|
|
|
|
* if we're not in preserve mode, reenable interpretation of the flow
|
|
|
|
* control characters. */
|
2004-07-27 16:46:35 +00:00
|
|
|
void terminal_init(void)
|
|
|
|
{
|
2007-12-18 15:55:48 +00:00
|
|
|
#ifdef USE_SLANG
|
|
|
|
/* Slang curses emulation brain damage, part 2: Slang doesn't
|
|
|
|
* implement raw(), nonl(), or noecho() properly, so there's no way
|
|
|
|
* to properly reinitialize the terminal using them. We have to
|
2007-12-18 16:51:48 +00:00
|
|
|
* disable the special control keys and interpretation of the flow
|
|
|
|
* control characters using termios, save the terminal state after
|
|
|
|
* the first call, and restore it on subsequent calls. */
|
2007-12-18 15:55:48 +00:00
|
|
|
static struct termios newterm;
|
|
|
|
static bool newterm_set = FALSE;
|
|
|
|
|
|
|
|
if (!newterm_set) {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
raw();
|
|
|
|
nonl();
|
|
|
|
noecho();
|
|
|
|
disable_extended_io();
|
|
|
|
if (ISSET(PRESERVE))
|
|
|
|
enable_flow_control();
|
|
|
|
|
|
|
|
disable_signals();
|
2008-09-06 06:52:47 +00:00
|
|
|
#ifdef USE_SLANG
|
2007-12-18 16:47:06 +00:00
|
|
|
if (!ISSET(PRESERVE))
|
|
|
|
disable_flow_control();
|
2007-12-18 15:55:48 +00:00
|
|
|
|
|
|
|
tcgetattr(0, &newterm);
|
|
|
|
newterm_set = TRUE;
|
|
|
|
} else
|
|
|
|
tcsetattr(0, TCSANOW, &newterm);
|
|
|
|
#endif
|
2004-07-27 16:46:35 +00:00
|
|
|
}
|
|
|
|
|
2016-08-16 08:49:55 +00:00
|
|
|
/* Ask ncurses for a keycode, or assign a default one. */
|
|
|
|
int get_keycode(const char *keyname, const int standard)
|
|
|
|
{
|
2016-11-17 16:32:28 +00:00
|
|
|
#ifdef HAVE_KEY_DEFINED
|
2016-08-16 08:49:55 +00:00
|
|
|
const char *keyvalue = tigetstr(keyname);
|
|
|
|
|
2016-11-17 16:32:28 +00:00
|
|
|
if (keyvalue != 0 && keyvalue != (char *)-1)
|
2016-08-16 08:49:55 +00:00
|
|
|
return key_defined(keyvalue);
|
2016-11-17 16:32:28 +00:00
|
|
|
else
|
2016-08-16 08:49:55 +00:00
|
|
|
#endif
|
2016-11-17 16:32:28 +00:00
|
|
|
return standard;
|
|
|
|
}
|
2016-08-16 08:49:55 +00:00
|
|
|
|
2016-04-27 12:37:31 +00:00
|
|
|
/* Say that an unbound key was struck, and if possible which one. */
|
|
|
|
void unbound_key(int code)
|
|
|
|
{
|
2016-07-13 14:22:56 +00:00
|
|
|
if (!is_byte(code))
|
2016-04-30 15:31:43 +00:00
|
|
|
statusline(ALERT, _("Unbound key"));
|
2016-04-27 12:37:31 +00:00
|
|
|
else if (meta_key) {
|
2016-07-14 20:01:55 +00:00
|
|
|
if (code == '[')
|
|
|
|
statusline(ALERT, _("Unbindable key: M-["));
|
|
|
|
else
|
|
|
|
statusline(ALERT, _("Unbound key: M-%c"), toupper(code));
|
2016-04-27 12:37:31 +00:00
|
|
|
} else if (code < 0x20)
|
2016-04-30 15:31:43 +00:00
|
|
|
statusline(ALERT, _("Unbound key: ^%c"), code + 0x40);
|
2017-04-22 16:27:01 +00:00
|
|
|
else if (currmenu != MHELP)
|
2016-04-30 15:31:43 +00:00
|
|
|
statusline(ALERT, _("Unbound key: %c"), code);
|
2016-04-27 12:37:31 +00:00
|
|
|
}
|
|
|
|
|
2016-06-24 20:45:41 +00:00
|
|
|
/* Read in a keystroke. Act on the keystroke if it is a shortcut or a toggle;
|
|
|
|
* otherwise, insert it into the edit buffer. If allow_funcs is FALSE, don't
|
|
|
|
* do anything with the keystroke -- just return it. */
|
2014-06-30 18:04:33 +00:00
|
|
|
int do_input(bool allow_funcs)
|
2004-12-04 17:41:52 +00:00
|
|
|
{
|
|
|
|
int input;
|
2016-06-24 20:45:41 +00:00
|
|
|
/* The keystroke we read in: a character or a shortcut. */
|
2016-06-26 12:08:05 +00:00
|
|
|
static char *puddle = NULL;
|
2016-06-24 20:45:41 +00:00
|
|
|
/* The input buffer for actual characters. */
|
|
|
|
static size_t depth = 0;
|
2004-12-04 17:41:52 +00:00
|
|
|
/* The length of the input buffer. */
|
2017-09-24 19:06:08 +00:00
|
|
|
bool retain_cuts = FALSE;
|
|
|
|
/* Whether to conserve the current contents of the cutbuffer. */
|
2008-03-05 07:34:01 +00:00
|
|
|
const sc *s;
|
2004-12-04 17:41:52 +00:00
|
|
|
bool have_shortcut;
|
|
|
|
|
2017-09-20 20:20:18 +00:00
|
|
|
/* Read in a keystroke, and show the cursor while waiting. */
|
|
|
|
input = get_kbinput(edit, VISIBLE);
|
2017-09-18 18:34:57 +00:00
|
|
|
|
2015-05-28 13:02:29 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
if (input == KEY_WINCH)
|
|
|
|
return KEY_WINCH;
|
|
|
|
#endif
|
|
|
|
|
2017-05-01 18:45:07 +00:00
|
|
|
#ifdef ENABLE_MOUSE
|
2016-07-13 14:22:56 +00:00
|
|
|
if (input == KEY_MOUSE) {
|
2014-06-13 12:07:18 +00:00
|
|
|
/* We received a mouse click. */
|
2014-06-16 12:30:35 +00:00
|
|
|
if (do_mouse() == 1)
|
2014-06-13 12:07:18 +00:00
|
|
|
/* The click was on a shortcut -- read in the character
|
|
|
|
* that it was converted into. */
|
2017-09-20 20:20:18 +00:00
|
|
|
input = get_kbinput(edit, BLIND);
|
2014-06-16 12:30:35 +00:00
|
|
|
else
|
|
|
|
/* The click was invalid or has been handled -- get out. */
|
2014-06-11 18:23:29 +00:00
|
|
|
return ERR;
|
2006-05-10 12:48:47 +00:00
|
|
|
}
|
2004-12-04 17:41:52 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Check for a shortcut in the main list. */
|
2014-07-01 10:41:10 +00:00
|
|
|
s = get_shortcut(&input);
|
2004-12-04 17:41:52 +00:00
|
|
|
|
|
|
|
/* If we got a shortcut from the main list, or a "universal"
|
|
|
|
* edit window shortcut, set have_shortcut to TRUE. */
|
2008-03-13 08:23:52 +00:00
|
|
|
have_shortcut = (s != NULL);
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2006-05-25 21:39:25 +00:00
|
|
|
/* If we got a non-high-bit control key, a meta key sequence, or a
|
|
|
|
* function key, and it's not a shortcut or toggle, throw it out. */
|
2008-03-05 07:34:01 +00:00
|
|
|
if (!have_shortcut) {
|
2016-07-13 14:22:56 +00:00
|
|
|
if (is_ascii_cntrl_char(input) || meta_key || !is_byte(input)) {
|
2016-04-27 12:37:31 +00:00
|
|
|
unbound_key(input);
|
2006-05-24 19:48:03 +00:00
|
|
|
input = ERR;
|
2006-05-24 17:36:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-28 19:00:13 +00:00
|
|
|
if (!allow_funcs)
|
|
|
|
return input;
|
|
|
|
|
2016-08-28 19:18:34 +00:00
|
|
|
/* If the keystroke isn't a shortcut nor a toggle, it's a normal text
|
|
|
|
* character: add the character to the input buffer -- or display a
|
|
|
|
* warning when we're in view mode. */
|
2017-05-05 20:48:54 +00:00
|
|
|
if (input != ERR && !have_shortcut) {
|
2016-08-28 19:18:34 +00:00
|
|
|
if (ISSET(VIEW_MODE))
|
|
|
|
print_view_warning();
|
|
|
|
else {
|
|
|
|
/* Store the byte, and leave room for a terminating zero. */
|
|
|
|
puddle = charealloc(puddle, depth + 2);
|
|
|
|
puddle[depth++] = (char)input;
|
2004-12-04 17:41:52 +00:00
|
|
|
}
|
2016-08-30 08:41:28 +00:00
|
|
|
#ifndef NANO_TINY
|
2017-05-12 16:07:32 +00:00
|
|
|
if (openfile->mark && openfile->kind_of_mark == SOFTMARK) {
|
|
|
|
openfile->mark = NULL;
|
2016-08-30 08:41:28 +00:00
|
|
|
refresh_needed = TRUE;
|
|
|
|
}
|
|
|
|
#endif
|
2016-08-28 19:18:34 +00:00
|
|
|
}
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2016-08-28 19:18:34 +00:00
|
|
|
/* 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 output
|
|
|
|
* all available characters in the input puddle. Note that this
|
|
|
|
* puddle will be empty if we're in view mode. */
|
|
|
|
if (have_shortcut || get_key_buffer_len() == 0) {
|
2017-10-29 20:00:09 +00:00
|
|
|
#ifdef ENABLE_WRAPPING
|
2016-08-28 19:18:34 +00:00
|
|
|
/* If we got a shortcut or toggle, and it's not the shortcut
|
|
|
|
* for verbatim input, turn off prepending of wrapped text. */
|
|
|
|
if (have_shortcut && s->scfunc != do_verbatim_input)
|
|
|
|
wrap_reset();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (puddle != NULL) {
|
|
|
|
/* Insert all bytes in the input buffer into the edit buffer
|
|
|
|
* at once, filtering out any low control codes. */
|
|
|
|
puddle[depth] = '\0';
|
|
|
|
do_output(puddle, depth, FALSE);
|
|
|
|
|
|
|
|
/* Empty the input buffer. */
|
|
|
|
free(puddle);
|
|
|
|
puddle = NULL;
|
|
|
|
depth = 0;
|
2004-12-04 17:41:52 +00:00
|
|
|
}
|
2016-08-28 19:18:34 +00:00
|
|
|
}
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2016-12-07 12:10:40 +00:00
|
|
|
if (!have_shortcut)
|
|
|
|
pletion_line = NULL;
|
|
|
|
else {
|
2016-08-28 19:18:34 +00:00
|
|
|
const subnfunc *f = sctofunc(s);
|
2016-08-28 19:00:13 +00:00
|
|
|
|
2016-08-28 19:18:34 +00:00
|
|
|
if (ISSET(VIEW_MODE) && f && !f->viewok) {
|
|
|
|
print_view_warning();
|
|
|
|
return ERR;
|
|
|
|
}
|
2016-08-28 19:00:13 +00:00
|
|
|
|
2016-08-28 19:18:34 +00:00
|
|
|
/* If the function associated with this shortcut is
|
|
|
|
* cutting or copying text, remember this. */
|
|
|
|
if (s->scfunc == do_cut_text_void
|
2006-04-25 02:23:28 +00:00
|
|
|
#ifndef NANO_TINY
|
2014-06-30 20:39:27 +00:00
|
|
|
|| s->scfunc == do_copy_text || s->scfunc == do_cut_till_eof
|
2006-04-25 02:23:28 +00:00
|
|
|
#endif
|
2014-06-11 18:34:35 +00:00
|
|
|
)
|
2017-09-24 19:06:08 +00:00
|
|
|
retain_cuts = TRUE;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2016-12-07 12:10:40 +00:00
|
|
|
#ifdef ENABLE_WORDCOMPLETION
|
2016-12-07 04:13:47 +00:00
|
|
|
if (s->scfunc != complete_a_word)
|
|
|
|
pletion_line = NULL;
|
2016-12-07 12:10:40 +00:00
|
|
|
#endif
|
|
|
|
#ifndef NANO_TINY
|
2016-08-28 19:18:34 +00:00
|
|
|
if (s->scfunc == do_toggle_void) {
|
|
|
|
do_toggle(s->toggle);
|
2017-07-14 14:14:02 +00:00
|
|
|
if (s->toggle != CUT_FROM_CURSOR)
|
2017-09-24 19:06:08 +00:00
|
|
|
retain_cuts = TRUE;
|
2016-08-28 19:18:34 +00:00
|
|
|
} else
|
2016-01-03 17:37:05 +00:00
|
|
|
#endif
|
2016-08-28 19:18:34 +00:00
|
|
|
{
|
2016-04-24 09:28:28 +00:00
|
|
|
#ifndef NANO_TINY
|
2016-08-28 19:18:34 +00:00
|
|
|
/* If Shifted movement occurs, set the mark. */
|
2017-05-12 16:07:32 +00:00
|
|
|
if (shift_held && !openfile->mark) {
|
|
|
|
openfile->mark = openfile->current;
|
|
|
|
openfile->mark_x = openfile->current_x;
|
2016-08-28 19:18:34 +00:00
|
|
|
openfile->kind_of_mark = SOFTMARK;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
/* Execute the function of the shortcut. */
|
|
|
|
s->scfunc();
|
2016-04-24 09:28:28 +00:00
|
|
|
#ifndef NANO_TINY
|
2016-08-28 19:18:34 +00:00
|
|
|
/* If Shiftless movement occurred, discard a soft mark. */
|
2017-05-12 16:07:32 +00:00
|
|
|
if (!shift_held && openfile->mark &&
|
2016-04-24 09:28:28 +00:00
|
|
|
openfile->kind_of_mark == SOFTMARK) {
|
2017-05-12 16:07:32 +00:00
|
|
|
openfile->mark = NULL;
|
2016-08-28 19:18:34 +00:00
|
|
|
refresh_needed = TRUE;
|
|
|
|
}
|
2016-04-24 09:28:28 +00:00
|
|
|
#endif
|
2017-11-01 18:45:33 +00:00
|
|
|
#ifdef ENABLE_COLOR
|
2016-08-28 19:18:34 +00:00
|
|
|
if (f && !f->viewok)
|
2017-02-13 18:11:04 +00:00
|
|
|
check_the_multis(openfile->current);
|
2009-11-22 21:35:56 +00:00
|
|
|
#endif
|
2016-10-21 11:52:40 +00:00
|
|
|
if (!refresh_needed && (s->scfunc == do_delete || s->scfunc == do_backspace))
|
2016-08-28 19:18:34 +00:00
|
|
|
update_line(openfile->current, openfile->current_x);
|
2004-12-04 17:41:52 +00:00
|
|
|
}
|
2016-08-28 19:18:34 +00:00
|
|
|
}
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2014-06-13 12:28:33 +00:00
|
|
|
/* If we aren't cutting or copying text, and the key wasn't a toggle,
|
|
|
|
* blow away the text in the cutbuffer upon the next cutting action. */
|
2017-09-24 19:06:08 +00:00
|
|
|
if (!retain_cuts)
|
2006-05-21 20:03:43 +00:00
|
|
|
cutbuffer_reset();
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
2017-05-01 18:45:07 +00:00
|
|
|
#ifdef ENABLE_MOUSE
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Handle a mouse click on the edit window or the shortcut list. */
|
2007-05-20 23:41:56 +00:00
|
|
|
int do_mouse(void)
|
2004-12-04 17:41:52 +00:00
|
|
|
{
|
2017-02-02 03:10:49 +00:00
|
|
|
int mouse_col, mouse_row;
|
|
|
|
int retval = get_mouseinput(&mouse_col, &mouse_row, TRUE);
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2017-01-03 14:04:22 +00:00
|
|
|
/* If the click is wrong or already handled, we're done. */
|
2014-06-13 12:19:44 +00:00
|
|
|
if (retval != 0)
|
|
|
|
return retval;
|
|
|
|
|
2017-01-03 14:04:22 +00:00
|
|
|
/* If the click was in the edit window, put the cursor in that spot. */
|
2017-02-02 03:10:49 +00:00
|
|
|
if (wmouse_trafo(edit, &mouse_row, &mouse_col, FALSE)) {
|
2009-01-25 07:25:17 +00:00
|
|
|
filestruct *current_save = openfile->current;
|
2017-01-20 02:19:36 +00:00
|
|
|
ssize_t row_count = mouse_row - openfile->current_y;
|
|
|
|
size_t leftedge;
|
2014-04-04 16:06:27 +00:00
|
|
|
#ifndef NANO_TINY
|
2007-06-28 16:00:50 +00:00
|
|
|
size_t current_x_save = openfile->current_x;
|
2017-05-01 18:45:07 +00:00
|
|
|
bool sameline = (mouse_row == openfile->current_y);
|
|
|
|
/* Whether the click was on the row where the cursor is. */
|
2017-01-20 02:19:36 +00:00
|
|
|
|
|
|
|
if (ISSET(SOFTWRAP))
|
2017-07-09 19:07:38 +00:00
|
|
|
leftedge = leftedge_for(xplustabs(), openfile->current);
|
2017-01-20 02:19:36 +00:00
|
|
|
else
|
2014-04-04 16:06:27 +00:00
|
|
|
#endif
|
2017-01-20 02:19:36 +00:00
|
|
|
leftedge = get_page_start(xplustabs());
|
2007-06-28 16:00:50 +00:00
|
|
|
|
2017-01-20 02:19:36 +00:00
|
|
|
/* Move current up or down to the row corresponding to mouse_row. */
|
|
|
|
if (row_count < 0)
|
|
|
|
go_back_chunks(-row_count, &openfile->current, &leftedge);
|
|
|
|
else
|
|
|
|
go_forward_chunks(row_count, &openfile->current, &leftedge);
|
2009-11-13 20:38:32 +00:00
|
|
|
|
2017-01-20 02:19:36 +00:00
|
|
|
openfile->current_x = actual_x(openfile->current->data,
|
2017-02-22 18:59:32 +00:00
|
|
|
actual_last_column(leftedge, mouse_col));
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2017-01-03 14:04:22 +00:00
|
|
|
/* Clicking where the cursor is toggles the mark, as does clicking
|
|
|
|
* beyond the line length with the cursor at the end of the line. */
|
2007-06-28 16:00:50 +00:00
|
|
|
if (sameline && openfile->current_x == current_x_save)
|
|
|
|
do_mark();
|
2014-06-16 12:30:35 +00:00
|
|
|
else
|
2004-12-04 17:41:52 +00:00
|
|
|
#endif
|
2014-06-16 12:30:35 +00:00
|
|
|
/* The cursor moved; clean the cutbuffer on the next cut. */
|
|
|
|
cutbuffer_reset();
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2017-08-18 19:46:14 +00:00
|
|
|
edit_redraw(current_save, CENTERING);
|
2004-12-04 17:41:52 +00:00
|
|
|
}
|
|
|
|
|
2014-06-16 12:30:35 +00:00
|
|
|
/* No more handling is needed. */
|
2014-06-13 12:19:44 +00:00
|
|
|
return 2;
|
2004-12-04 17:41:52 +00:00
|
|
|
}
|
2017-05-01 18:45:07 +00:00
|
|
|
#endif /* ENABLE_MOUSE */
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2006-05-22 02:08:49 +00:00
|
|
|
/* The user typed output_len multibyte characters. Add them to the edit
|
2006-05-27 17:39:19 +00:00
|
|
|
* buffer, filtering out all ASCII control characters if allow_cntrls is
|
2005-03-17 03:52:08 +00:00
|
|
|
* TRUE. */
|
|
|
|
void do_output(char *output, size_t output_len, bool allow_cntrls)
|
2004-12-04 17:41:52 +00:00
|
|
|
{
|
2017-03-30 19:56:31 +00:00
|
|
|
char onechar[MAXCHARLEN];
|
2016-12-19 18:58:15 +00:00
|
|
|
int char_len;
|
2017-03-29 19:35:56 +00:00
|
|
|
size_t current_len = strlen(openfile->current->data);
|
|
|
|
size_t i = 0;
|
2014-06-09 20:26:54 +00:00
|
|
|
#ifndef NANO_TINY
|
2017-07-09 19:11:01 +00:00
|
|
|
size_t original_row = 0, old_amount = 0;
|
2017-03-29 19:35:56 +00:00
|
|
|
|
2017-03-07 22:54:40 +00:00
|
|
|
if (ISSET(SOFTWRAP)) {
|
|
|
|
if (openfile->current_y == editwinrows - 1)
|
2017-07-09 19:07:38 +00:00
|
|
|
original_row = chunk_for(xplustabs(), openfile->current);
|
2017-07-09 19:11:01 +00:00
|
|
|
old_amount = number_of_chunks_in(openfile->current);
|
2017-03-07 22:54:40 +00:00
|
|
|
}
|
2014-06-09 20:26:54 +00:00
|
|
|
#endif
|
2005-05-26 05:17:13 +00:00
|
|
|
|
2005-01-12 03:25:57 +00:00
|
|
|
while (i < output_len) {
|
2016-12-27 11:20:20 +00:00
|
|
|
/* Encode an embedded NUL byte as 0x0A. */
|
|
|
|
if (output[i] == '\0')
|
|
|
|
output[i] = '\n';
|
2004-12-08 23:24:31 +00:00
|
|
|
|
2016-06-14 09:06:04 +00:00
|
|
|
/* Get the next multibyte character. */
|
2017-03-30 18:57:28 +00:00
|
|
|
char_len = parse_mbchar(output + i, onechar, NULL);
|
2005-01-12 03:25:57 +00:00
|
|
|
|
2016-12-19 18:58:15 +00:00
|
|
|
i += char_len;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2016-06-14 09:06:04 +00:00
|
|
|
/* If controls are not allowed, ignore an ASCII control character. */
|
2016-12-19 18:58:15 +00:00
|
|
|
if (!allow_cntrls && is_ascii_cntrl_char(*(output + i - char_len)))
|
2005-03-17 03:52:08 +00:00
|
|
|
continue;
|
|
|
|
|
2016-06-14 09:06:04 +00:00
|
|
|
/* If we're adding to the magicline, create a new magicline. */
|
2016-10-21 13:59:16 +00:00
|
|
|
if (!ISSET(NO_NEWLINES) && openfile->filebot == openfile->current) {
|
2004-12-04 17:41:52 +00:00
|
|
|
new_magicline();
|
2016-10-21 13:59:16 +00:00
|
|
|
if (margin > 0)
|
|
|
|
refresh_needed = TRUE;
|
|
|
|
}
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2016-06-14 09:06:04 +00:00
|
|
|
/* Make room for the new character and copy it into the line. */
|
|
|
|
openfile->current->data = charealloc(openfile->current->data,
|
2016-12-19 18:58:15 +00:00
|
|
|
current_len + char_len + 1);
|
|
|
|
charmove(openfile->current->data + openfile->current_x + char_len,
|
2015-12-04 21:11:10 +00:00
|
|
|
openfile->current->data + openfile->current_x,
|
2016-06-14 12:39:56 +00:00
|
|
|
current_len - openfile->current_x + 1);
|
2017-03-30 18:57:28 +00:00
|
|
|
strncpy(openfile->current->data + openfile->current_x, onechar,
|
2016-12-19 18:58:15 +00:00
|
|
|
char_len);
|
|
|
|
current_len += char_len;
|
2005-07-08 20:09:16 +00:00
|
|
|
openfile->totsize++;
|
2004-12-04 17:41:52 +00:00
|
|
|
set_modified();
|
|
|
|
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2014-05-15 20:00:46 +00:00
|
|
|
add_undo(ADD);
|
2008-07-10 20:13:04 +00:00
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
/* Note that current_x has not yet been incremented. */
|
2017-05-12 16:07:32 +00:00
|
|
|
if (openfile->current == openfile->mark &&
|
|
|
|
openfile->current_x < openfile->mark_x)
|
|
|
|
openfile->mark_x += char_len;
|
2017-08-13 09:30:10 +00:00
|
|
|
|
|
|
|
/* When the cursor is on the top row and not on the first chunk
|
|
|
|
* of a line, adding text there might change the preceding chunk
|
|
|
|
* and thus require an adjustment of firstcolumn. */
|
|
|
|
if (openfile->current == openfile->edittop &&
|
|
|
|
openfile->firstcolumn > 0) {
|
|
|
|
ensure_firstcolumn_is_aligned();
|
|
|
|
refresh_needed = TRUE;
|
|
|
|
}
|
2004-12-04 17:41:52 +00:00
|
|
|
#endif
|
|
|
|
|
2016-12-19 18:58:15 +00:00
|
|
|
openfile->current_x += char_len;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2014-05-15 20:00:46 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
update_undo(ADD);
|
|
|
|
#endif
|
|
|
|
|
2017-10-29 20:00:09 +00:00
|
|
|
#ifdef ENABLE_WRAPPING
|
2016-12-02 16:37:11 +00:00
|
|
|
/* If text gets wrapped, the edit window needs a refresh. */
|
|
|
|
if (!ISSET(NO_WRAP) && do_wrap(openfile->current))
|
|
|
|
refresh_needed = TRUE;
|
2004-12-04 17:41:52 +00:00
|
|
|
#endif
|
2015-11-25 09:10:02 +00:00
|
|
|
}
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2014-06-09 20:26:54 +00:00
|
|
|
#ifndef NANO_TINY
|
2017-03-07 22:54:40 +00:00
|
|
|
/* If the number of screen rows that a softwrapped line occupies has
|
|
|
|
* changed, we need a full refresh. And if we were on the last line
|
|
|
|
* of the edit window, and we moved one screen row, we're now below
|
|
|
|
* the last line of the edit window, so we need a full refresh too. */
|
2017-03-29 17:30:37 +00:00
|
|
|
if (ISSET(SOFTWRAP) && refresh_needed == FALSE &&
|
2017-07-09 19:11:01 +00:00
|
|
|
(number_of_chunks_in(openfile->current) != old_amount ||
|
2017-03-07 22:54:40 +00:00
|
|
|
(openfile->current_y == editwinrows - 1 &&
|
2017-07-09 19:07:38 +00:00
|
|
|
chunk_for(xplustabs(), openfile->current) != original_row)))
|
2017-03-29 17:30:37 +00:00
|
|
|
refresh_needed = TRUE;
|
2014-06-09 20:26:54 +00:00
|
|
|
#endif
|
2009-12-12 22:21:20 +00:00
|
|
|
|
2005-07-16 23:36:10 +00:00
|
|
|
openfile->placewewant = xplustabs();
|
|
|
|
|
2017-11-01 18:45:33 +00:00
|
|
|
#ifdef ENABLE_COLOR
|
2017-02-13 18:11:04 +00:00
|
|
|
check_the_multis(openfile->current);
|
2009-01-26 07:55:01 +00:00
|
|
|
#endif
|
2016-01-03 16:21:04 +00:00
|
|
|
|
2016-10-21 11:52:40 +00:00
|
|
|
if (!refresh_needed)
|
2005-07-08 20:09:16 +00:00
|
|
|
update_line(openfile->current, openfile->current_x);
|
2004-12-04 17:41:52 +00:00
|
|
|
}
|
|
|
|
|
2004-08-17 05:23:38 +00:00
|
|
|
int main(int argc, char **argv)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2017-11-08 05:49:48 +00:00
|
|
|
int stdin_flags, optchr;
|
2017-11-01 19:08:55 +00:00
|
|
|
#if defined(ENABLED_WRAPORJUSTIFY) && defined(ENABLE_NANORC)
|
2005-07-25 22:54:16 +00:00
|
|
|
bool fill_used = FALSE;
|
2015-11-21 19:44:27 +00:00
|
|
|
/* Was the fill option used on the command line? */
|
2017-11-01 19:08:55 +00:00
|
|
|
#endif
|
2017-10-29 20:00:09 +00:00
|
|
|
#ifdef ENABLE_WRAPPING
|
2015-11-21 19:44:27 +00:00
|
|
|
bool forced_wrapping = FALSE;
|
|
|
|
/* Should long lines be automatically hard wrapped? */
|
2004-08-12 19:48:21 +00:00
|
|
|
#endif
|
2017-05-01 18:20:34 +00:00
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
2017-06-18 19:37:42 +00:00
|
|
|
bool is_multibuffer;
|
|
|
|
/* The actual value of the multibuffer option, restored after
|
|
|
|
* we've loaded all files given on the command line. */
|
2004-09-05 21:40:31 +00:00
|
|
|
#endif
|
2002-12-22 16:30:00 +00:00
|
|
|
const struct option long_options[] = {
|
2006-04-12 15:27:40 +00:00
|
|
|
{"boldtext", 0, NULL, 'D'},
|
2017-05-01 18:20:34 +00:00
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
2005-03-26 22:49:08 +00:00
|
|
|
{"multibuffer", 0, NULL, 'F'},
|
2002-07-19 01:08:59 +00:00
|
|
|
#endif
|
2017-05-08 17:42:44 +00:00
|
|
|
#ifdef ENABLE_NANORC
|
2005-03-26 22:49:08 +00:00
|
|
|
{"ignorercfiles", 0, NULL, 'I'},
|
2002-06-28 22:45:14 +00:00
|
|
|
#endif
|
2005-08-10 21:22:15 +00:00
|
|
|
{"rebindkeypad", 0, NULL, 'K'},
|
2005-11-05 17:35:44 +00:00
|
|
|
{"nonewlines", 0, NULL, 'L'},
|
2005-03-26 22:49:08 +00:00
|
|
|
{"morespace", 0, NULL, 'O'},
|
2017-10-31 16:34:07 +00:00
|
|
|
#ifdef ENABLE_JUSTIFY
|
2005-03-26 22:49:08 +00:00
|
|
|
{"quotestr", 1, NULL, 'Q'},
|
2000-07-07 02:35:34 +00:00
|
|
|
#endif
|
2005-06-17 22:53:41 +00:00
|
|
|
{"restricted", 0, NULL, 'R'},
|
2005-03-26 22:49:08 +00:00
|
|
|
{"tabsize", 1, NULL, 'T'},
|
2017-04-19 11:44:00 +00:00
|
|
|
{"quickblank", 0, NULL, 'U'},
|
2005-03-26 22:49:08 +00:00
|
|
|
{"version", 0, NULL, 'V'},
|
2017-11-01 18:45:33 +00:00
|
|
|
#ifdef ENABLE_COLOR
|
2005-03-26 22:49:08 +00:00
|
|
|
{"syntax", 1, NULL, 'Y'},
|
2001-05-21 12:56:25 +00:00
|
|
|
#endif
|
2015-07-15 19:40:37 +00:00
|
|
|
{"constantshow", 0, NULL, 'c'},
|
2005-03-26 22:49:08 +00:00
|
|
|
{"rebinddelete", 0, NULL, 'd'},
|
2017-05-08 17:08:23 +00:00
|
|
|
#ifdef ENABLE_BROWSER
|
2016-10-23 10:56:47 +00:00
|
|
|
{"showcursor", 0, NULL, 'g'},
|
|
|
|
#endif
|
2015-06-20 18:48:43 +00:00
|
|
|
{"help", 0, NULL, 'h'},
|
2016-10-20 08:44:29 +00:00
|
|
|
#ifdef ENABLE_LINENUMBERS
|
|
|
|
{"linenumbers", 0, NULL, 'l'},
|
|
|
|
#endif
|
2017-05-01 18:45:07 +00:00
|
|
|
#ifdef ENABLE_MOUSE
|
2005-03-26 22:49:08 +00:00
|
|
|
{"mouse", 0, NULL, 'm'},
|
2002-12-22 16:30:00 +00:00
|
|
|
#endif
|
2014-04-08 18:59:30 +00:00
|
|
|
{"noread", 0, NULL, 'n'},
|
2017-10-29 20:08:07 +00:00
|
|
|
#ifdef ENABLE_OPERATINGDIR
|
2005-03-26 22:49:08 +00:00
|
|
|
{"operatingdir", 1, NULL, 'o'},
|
2001-09-19 03:19:43 +00:00
|
|
|
#endif
|
2005-03-26 22:49:08 +00:00
|
|
|
{"preserve", 0, NULL, 'p'},
|
2009-02-09 04:03:20 +00:00
|
|
|
{"quiet", 0, NULL, 'q'},
|
2017-10-31 16:39:30 +00:00
|
|
|
#ifdef ENABLED_WRAPORJUSTIFY
|
2005-03-26 22:49:08 +00:00
|
|
|
{"fill", 1, NULL, 'r'},
|
2002-06-28 22:45:14 +00:00
|
|
|
#endif
|
2017-10-31 18:32:42 +00:00
|
|
|
#ifdef ENABLE_SPELLER
|
2005-03-26 22:49:08 +00:00
|
|
|
{"speller", 1, NULL, 's'},
|
2001-07-11 02:08:33 +00:00
|
|
|
#endif
|
2005-03-26 22:49:08 +00:00
|
|
|
{"tempfile", 0, NULL, 't'},
|
|
|
|
{"view", 0, NULL, 'v'},
|
2017-10-29 20:00:09 +00:00
|
|
|
#ifdef ENABLE_WRAPPING
|
2005-03-26 22:49:08 +00:00
|
|
|
{"nowrap", 0, NULL, 'w'},
|
2002-10-17 02:19:31 +00:00
|
|
|
#endif
|
2005-03-26 22:49:08 +00:00
|
|
|
{"nohelp", 0, NULL, 'x'},
|
|
|
|
{"suspend", 0, NULL, 'z'},
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2005-03-26 22:49:08 +00:00
|
|
|
{"smarthome", 0, NULL, 'A'},
|
|
|
|
{"backup", 0, NULL, 'B'},
|
2005-06-15 23:20:56 +00:00
|
|
|
{"backupdir", 1, NULL, 'C'},
|
|
|
|
{"tabstospaces", 0, NULL, 'E'},
|
2013-01-01 03:24:39 +00:00
|
|
|
{"locking", 0, NULL, 'G'},
|
2005-06-17 17:37:46 +00:00
|
|
|
{"historylog", 0, NULL, 'H'},
|
2005-03-26 22:49:08 +00:00
|
|
|
{"noconvert", 0, NULL, 'N'},
|
2015-07-15 19:50:55 +00:00
|
|
|
{"poslog", 0, NULL, 'P'}, /* deprecated form, remove in 2018 */
|
|
|
|
{"positionlog", 0, NULL, 'P'},
|
2005-03-26 22:49:08 +00:00
|
|
|
{"smooth", 0, NULL, 'S'},
|
2005-08-10 22:12:28 +00:00
|
|
|
{"wordbounds", 0, NULL, 'W'},
|
2016-06-30 16:02:45 +00:00
|
|
|
{"wordchars", 1, NULL, 'X'},
|
2017-06-28 14:57:46 +00:00
|
|
|
{"atblanks", 0, NULL, 'a'},
|
2005-03-26 22:49:08 +00:00
|
|
|
{"autoindent", 0, NULL, 'i'},
|
2017-07-14 14:06:52 +00:00
|
|
|
{"cutfromcursor", 0, NULL, 'k'},
|
2015-08-09 16:31:01 +00:00
|
|
|
{"unix", 0, NULL, 'u'},
|
2009-08-17 07:52:10 +00:00
|
|
|
{"softwrap", 0, NULL, '$'},
|
2002-05-04 04:23:30 +00:00
|
|
|
#endif
|
2005-03-26 22:49:08 +00:00
|
|
|
{NULL, 0, NULL, 0}
|
2000-06-06 05:53:49 +00:00
|
|
|
};
|
2015-08-06 09:01:33 +00:00
|
|
|
|
2016-06-12 09:13:45 +00:00
|
|
|
/* Back up the terminal settings so that they can be restored. */
|
|
|
|
tcgetattr(0, &oldterm);
|
|
|
|
|
2017-11-08 05:49:48 +00:00
|
|
|
/* Get the state of standard input and ensure it uses blocking mode. */
|
|
|
|
stdin_flags = fcntl(0, F_GETFL, 0);
|
|
|
|
if (stdin_flags != -1)
|
|
|
|
fcntl(0, F_SETFL, stdin_flags & ~O_NONBLOCK);
|
|
|
|
|
2005-07-17 02:40:07 +00:00
|
|
|
#ifdef ENABLE_UTF8
|
2017-03-30 19:32:48 +00:00
|
|
|
/* If setting the locale is successful and it uses UTF-8, we need
|
|
|
|
* to use the multibyte functions for text processing. */
|
|
|
|
if (setlocale(LC_ALL, "") != NULL &&
|
|
|
|
strcmp(nl_langinfo(CODESET), "UTF-8") == 0) {
|
2005-01-28 19:37:23 +00:00
|
|
|
#ifdef USE_SLANG
|
2017-03-30 19:32:48 +00:00
|
|
|
SLutf8_enable(1);
|
2005-01-28 19:37:23 +00:00
|
|
|
#endif
|
2017-03-30 19:32:48 +00:00
|
|
|
utf8_init();
|
2004-12-23 17:43:27 +00:00
|
|
|
}
|
|
|
|
#else
|
2000-06-06 05:53:49 +00:00
|
|
|
setlocale(LC_ALL, "");
|
2004-12-23 17:43:27 +00:00
|
|
|
#endif
|
|
|
|
|
2004-07-27 15:46:58 +00:00
|
|
|
#ifdef ENABLE_NLS
|
2000-06-06 05:53:49 +00:00
|
|
|
bindtextdomain(PACKAGE, LOCALEDIR);
|
|
|
|
textdomain(PACKAGE);
|
|
|
|
#endif
|
|
|
|
|
2017-05-16 18:17:14 +00:00
|
|
|
#if defined(ENABLE_UTF8) && !defined(NANO_TINY)
|
2017-03-30 19:56:31 +00:00
|
|
|
if (MB_CUR_MAX > MAXCHARLEN)
|
|
|
|
fprintf(stderr, "Unexpected large character size: %i bytes"
|
2017-04-06 04:03:35 +00:00
|
|
|
" -- please report a bug\n", (int)MB_CUR_MAX);
|
2017-04-30 09:14:02 +00:00
|
|
|
#endif
|
2017-03-30 19:56:31 +00:00
|
|
|
|
2017-05-08 17:42:44 +00:00
|
|
|
#if !defined(ENABLE_NANORC) && defined(DISABLE_ROOTWRAPPING)
|
2014-04-07 20:05:05 +00:00
|
|
|
/* If we don't have rcfile support, --disable-wrapping-as-root is
|
|
|
|
* used, and we're root, turn wrapping off. */
|
2004-03-04 06:33:52 +00:00
|
|
|
if (geteuid() == NANO_ROOT_UID)
|
2002-10-25 16:08:53 +00:00
|
|
|
SET(NO_WRAP);
|
|
|
|
#endif
|
2001-04-18 04:28:54 +00:00
|
|
|
|
2016-11-17 17:05:09 +00:00
|
|
|
/* If the executable's name starts with 'r', activate restricted mode. */
|
|
|
|
if (*(tail(argv[0])) == 'r')
|
|
|
|
SET(RESTRICTED);
|
|
|
|
|
2004-08-07 22:00:02 +00:00
|
|
|
while ((optchr =
|
2005-06-12 16:13:44 +00:00
|
|
|
getopt_long(argc, argv,
|
2016-06-30 16:02:45 +00:00
|
|
|
"ABC:DEFGHIKLNOPQ:RST:UVWX:Y:abcdefghijklmno:pqr:s:tuvwxz$",
|
2017-02-21 22:04:40 +00:00
|
|
|
long_options, NULL)) != -1) {
|
2000-06-06 05:53:49 +00:00
|
|
|
switch (optchr) {
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'b':
|
|
|
|
case 'e':
|
|
|
|
case 'f':
|
|
|
|
case 'j':
|
|
|
|
/* Pico compatibility flags. */
|
|
|
|
break;
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'A':
|
|
|
|
SET(SMART_HOME);
|
|
|
|
break;
|
|
|
|
case 'B':
|
|
|
|
SET(BACKUP_FILE);
|
|
|
|
break;
|
2005-06-15 23:20:56 +00:00
|
|
|
case 'C':
|
2004-08-07 22:00:02 +00:00
|
|
|
backup_dir = mallocstrcpy(backup_dir, optarg);
|
|
|
|
break;
|
2006-04-12 15:27:40 +00:00
|
|
|
#endif
|
|
|
|
case 'D':
|
|
|
|
SET(BOLD_TEXT);
|
|
|
|
break;
|
|
|
|
#ifndef NANO_TINY
|
2005-06-15 23:20:56 +00:00
|
|
|
case 'E':
|
|
|
|
SET(TABS_TO_SPACES);
|
|
|
|
break;
|
2001-09-22 00:42:10 +00:00
|
|
|
#endif
|
2017-05-01 18:20:34 +00:00
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'F':
|
|
|
|
SET(MULTIBUFFER);
|
|
|
|
break;
|
2002-07-19 01:08:59 +00:00
|
|
|
#endif
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2013-01-01 03:24:39 +00:00
|
|
|
case 'G':
|
|
|
|
SET(LOCKING);
|
|
|
|
break;
|
2014-06-19 20:05:24 +00:00
|
|
|
#endif
|
2017-10-29 18:42:12 +00:00
|
|
|
#ifdef ENABLE_HISTORIES
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'H':
|
|
|
|
SET(HISTORYLOG);
|
|
|
|
break;
|
2003-09-06 21:44:37 +00:00
|
|
|
#endif
|
2017-05-08 17:42:44 +00:00
|
|
|
#ifdef ENABLE_NANORC
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'I':
|
2006-04-24 18:54:29 +00:00
|
|
|
no_rcfiles = TRUE;
|
2004-08-07 22:00:02 +00:00
|
|
|
break;
|
2001-07-11 02:08:33 +00:00
|
|
|
#endif
|
2005-08-10 21:22:15 +00:00
|
|
|
case 'K':
|
|
|
|
SET(REBIND_KEYPAD);
|
|
|
|
break;
|
2005-11-05 17:35:44 +00:00
|
|
|
case 'L':
|
|
|
|
SET(NO_NEWLINES);
|
|
|
|
break;
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'N':
|
|
|
|
SET(NO_CONVERT);
|
|
|
|
break;
|
2002-03-03 22:36:36 +00:00
|
|
|
#endif
|
2005-01-17 05:06:55 +00:00
|
|
|
case 'O':
|
|
|
|
SET(MORE_SPACE);
|
|
|
|
break;
|
2017-10-29 18:42:12 +00:00
|
|
|
#ifdef ENABLE_HISTORIES
|
2011-02-16 06:52:30 +00:00
|
|
|
case 'P':
|
|
|
|
SET(POS_HISTORY);
|
|
|
|
break;
|
|
|
|
#endif
|
2017-10-31 16:34:07 +00:00
|
|
|
#ifdef ENABLE_JUSTIFY
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'Q':
|
|
|
|
quotestr = mallocstrcpy(quotestr, optarg);
|
|
|
|
break;
|
2002-02-15 19:17:02 +00:00
|
|
|
#endif
|
2005-06-17 22:53:41 +00:00
|
|
|
case 'R':
|
|
|
|
SET(RESTRICTED);
|
|
|
|
break;
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'S':
|
2005-06-16 02:13:10 +00:00
|
|
|
SET(SMOOTH_SCROLL);
|
2004-08-07 22:00:02 +00:00
|
|
|
break;
|
2000-07-07 02:35:34 +00:00
|
|
|
#endif
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'T':
|
|
|
|
if (!parse_num(optarg, &tabsize) || tabsize <= 0) {
|
2006-06-08 02:54:20 +00:00
|
|
|
fprintf(stderr, _("Requested tab size \"%s\" is invalid"), optarg);
|
2004-08-11 05:13:08 +00:00
|
|
|
fprintf(stderr, "\n");
|
2004-08-07 22:00:02 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
2005-06-17 19:06:25 +00:00
|
|
|
case 'U':
|
|
|
|
SET(QUICK_BLANK);
|
|
|
|
break;
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'V':
|
|
|
|
version();
|
|
|
|
exit(0);
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2005-08-10 22:12:28 +00:00
|
|
|
case 'W':
|
|
|
|
SET(WORD_BOUNDS);
|
|
|
|
break;
|
2016-06-30 16:02:45 +00:00
|
|
|
case 'X':
|
|
|
|
word_chars = mallocstrcpy(word_chars, optarg);
|
|
|
|
break;
|
2005-08-10 22:12:28 +00:00
|
|
|
#endif
|
2017-11-01 18:45:33 +00:00
|
|
|
#ifdef ENABLE_COLOR
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'Y':
|
|
|
|
syntaxstr = mallocstrcpy(syntaxstr, optarg);
|
|
|
|
break;
|
2017-06-28 14:57:46 +00:00
|
|
|
#endif
|
|
|
|
#ifndef NANO_TINY
|
|
|
|
case 'a':
|
|
|
|
SET(AT_BLANKS);
|
|
|
|
break;
|
2002-05-04 04:23:30 +00:00
|
|
|
#endif
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'c':
|
2017-04-17 09:51:48 +00:00
|
|
|
SET(CONSTANT_SHOW);
|
2004-08-07 22:00:02 +00:00
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
SET(REBIND_DELETE);
|
|
|
|
break;
|
2016-10-23 10:56:47 +00:00
|
|
|
case 'g':
|
|
|
|
SET(SHOW_CURSOR);
|
|
|
|
break;
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'i':
|
|
|
|
SET(AUTOINDENT);
|
|
|
|
break;
|
|
|
|
case 'k':
|
2017-07-14 14:14:02 +00:00
|
|
|
SET(CUT_FROM_CURSOR);
|
2004-08-07 22:00:02 +00:00
|
|
|
break;
|
2000-07-12 18:14:51 +00:00
|
|
|
#endif
|
2017-05-01 18:45:07 +00:00
|
|
|
#ifdef ENABLE_MOUSE
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'm':
|
|
|
|
SET(USE_MOUSE);
|
|
|
|
break;
|
2002-12-22 16:30:00 +00:00
|
|
|
#endif
|
2014-04-08 18:59:30 +00:00
|
|
|
case 'n':
|
|
|
|
SET(NOREAD_MODE);
|
|
|
|
break;
|
2017-10-29 20:08:07 +00:00
|
|
|
#ifdef ENABLE_OPERATINGDIR
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'o':
|
|
|
|
operating_dir = mallocstrcpy(operating_dir, optarg);
|
|
|
|
break;
|
2001-09-19 03:19:43 +00:00
|
|
|
#endif
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'p':
|
|
|
|
SET(PRESERVE);
|
|
|
|
break;
|
2017-05-08 17:42:44 +00:00
|
|
|
#ifdef ENABLE_NANORC
|
2017-10-07 14:45:17 +00:00
|
|
|
case 'q': /* obsolete, ignored */
|
2009-02-09 04:03:20 +00:00
|
|
|
break;
|
2014-07-02 19:57:23 +00:00
|
|
|
#endif
|
2017-10-31 16:39:30 +00:00
|
|
|
#ifdef ENABLED_WRAPORJUSTIFY
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'r':
|
|
|
|
if (!parse_num(optarg, &wrap_at)) {
|
2006-06-08 02:54:20 +00:00
|
|
|
fprintf(stderr, _("Requested fill size \"%s\" is invalid"), optarg);
|
2004-08-11 05:13:08 +00:00
|
|
|
fprintf(stderr, "\n");
|
2004-08-07 22:00:02 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
2017-11-01 19:08:55 +00:00
|
|
|
#ifdef ENABLE_NANORC
|
2005-07-25 22:54:16 +00:00
|
|
|
fill_used = TRUE;
|
2017-11-01 19:08:55 +00:00
|
|
|
#endif
|
2017-10-29 20:00:09 +00:00
|
|
|
#ifdef ENABLE_WRAPPING
|
2015-11-21 19:44:27 +00:00
|
|
|
forced_wrapping = TRUE;
|
2016-05-15 13:18:47 +00:00
|
|
|
#endif
|
2004-08-07 22:00:02 +00:00
|
|
|
break;
|
2001-05-21 12:56:25 +00:00
|
|
|
#endif
|
2017-10-31 18:32:42 +00:00
|
|
|
#ifdef ENABLE_SPELLER
|
2004-08-07 22:00:02 +00:00
|
|
|
case 's':
|
|
|
|
alt_speller = mallocstrcpy(alt_speller, optarg);
|
|
|
|
break;
|
2001-01-12 07:51:05 +00:00
|
|
|
#endif
|
2004-08-07 22:00:02 +00:00
|
|
|
case 't':
|
|
|
|
SET(TEMP_FILE);
|
|
|
|
break;
|
2015-08-09 16:31:01 +00:00
|
|
|
#ifndef NANO_TINY
|
2015-08-04 18:49:57 +00:00
|
|
|
case 'u':
|
|
|
|
SET(MAKE_IT_UNIX);
|
|
|
|
break;
|
2015-08-09 16:31:01 +00:00
|
|
|
#endif
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'v':
|
|
|
|
SET(VIEW_MODE);
|
|
|
|
break;
|
2017-10-29 20:00:09 +00:00
|
|
|
#ifdef ENABLE_WRAPPING
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'w':
|
|
|
|
SET(NO_WRAP);
|
2014-03-24 21:48:23 +00:00
|
|
|
/* If both --fill and --nowrap are given on the
|
|
|
|
* command line, the last given option wins. */
|
2015-11-21 19:44:27 +00:00
|
|
|
forced_wrapping = FALSE;
|
2004-08-07 22:00:02 +00:00
|
|
|
break;
|
2002-12-22 16:30:00 +00:00
|
|
|
#endif
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'x':
|
|
|
|
SET(NO_HELP);
|
|
|
|
break;
|
|
|
|
case 'z':
|
|
|
|
SET(SUSPEND);
|
|
|
|
break;
|
2009-08-17 07:52:10 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
case '$':
|
|
|
|
SET(SOFTWRAP);
|
|
|
|
break;
|
2016-10-20 08:44:29 +00:00
|
|
|
#endif
|
|
|
|
#ifdef ENABLE_LINENUMBERS
|
|
|
|
case 'l':
|
|
|
|
SET(LINE_NUMBERS);
|
|
|
|
break;
|
2009-08-17 07:52:10 +00:00
|
|
|
#endif
|
2014-04-27 12:13:26 +00:00
|
|
|
case 'h':
|
2004-08-07 22:00:02 +00:00
|
|
|
usage();
|
2014-04-27 12:13:26 +00:00
|
|
|
exit(0);
|
|
|
|
default:
|
|
|
|
printf(_("Type '%s -h' for a list of available options.\n"), argv[0]);
|
|
|
|
exit(1);
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-19 15:09:23 +00:00
|
|
|
/* If we're using restricted mode, disable suspending, backups,
|
|
|
|
* rcfiles, and history files, since they all would allow reading
|
|
|
|
* from or writing to files not specified on the command line. */
|
2004-04-30 04:49:02 +00:00
|
|
|
if (ISSET(RESTRICTED)) {
|
|
|
|
UNSET(SUSPEND);
|
|
|
|
UNSET(BACKUP_FILE);
|
2017-05-08 17:42:44 +00:00
|
|
|
#ifdef ENABLE_NANORC
|
2006-04-24 18:54:29 +00:00
|
|
|
no_rcfiles = TRUE;
|
2014-06-19 15:09:23 +00:00
|
|
|
UNSET(HISTORYLOG);
|
|
|
|
UNSET(POS_HISTORY);
|
2006-04-24 20:17:50 +00:00
|
|
|
#endif
|
2004-04-30 04:49:02 +00:00
|
|
|
}
|
|
|
|
|
2014-04-07 09:24:10 +00:00
|
|
|
/* Set up the function and shortcut lists. This needs to be done
|
|
|
|
* before reading the rcfile, to be able to rebind/unbind keys. */
|
|
|
|
shortcut_init();
|
2008-03-05 07:34:01 +00:00
|
|
|
|
2017-05-08 17:42:44 +00:00
|
|
|
#ifdef ENABLE_NANORC
|
2006-04-24 18:54:29 +00:00
|
|
|
if (!no_rcfiles) {
|
2017-05-08 17:42:44 +00:00
|
|
|
/* Back up the command-line options, then read the rcfile(s). */
|
2017-10-29 20:08:07 +00:00
|
|
|
#ifdef ENABLE_OPERATINGDIR
|
2003-01-13 01:35:15 +00:00
|
|
|
char *operating_dir_cpy = operating_dir;
|
|
|
|
#endif
|
2017-10-31 16:39:30 +00:00
|
|
|
#ifdef ENABLED_WRAPORJUSTIFY
|
2004-07-12 16:07:14 +00:00
|
|
|
ssize_t wrap_at_cpy = wrap_at;
|
2003-01-13 01:35:15 +00:00
|
|
|
#endif
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2004-02-28 16:24:31 +00:00
|
|
|
char *backup_dir_cpy = backup_dir;
|
2016-06-30 16:02:45 +00:00
|
|
|
char *word_chars_cpy = word_chars;
|
2004-02-28 16:24:31 +00:00
|
|
|
#endif
|
2017-10-31 16:34:07 +00:00
|
|
|
#ifdef ENABLE_JUSTIFY
|
2003-01-13 01:35:15 +00:00
|
|
|
char *quotestr_cpy = quotestr;
|
|
|
|
#endif
|
2017-10-31 18:32:42 +00:00
|
|
|
#ifdef ENABLE_SPELLER
|
2003-01-13 01:35:15 +00:00
|
|
|
char *alt_speller_cpy = alt_speller;
|
|
|
|
#endif
|
2004-07-12 16:07:14 +00:00
|
|
|
ssize_t tabsize_cpy = tabsize;
|
2009-08-14 03:18:29 +00:00
|
|
|
unsigned flags_cpy[sizeof(flags) / sizeof(flags[0])];
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
memcpy(flags_cpy, flags, sizeof(flags_cpy));
|
2003-01-13 01:35:15 +00:00
|
|
|
|
2017-10-29 20:08:07 +00:00
|
|
|
#ifdef ENABLE_OPERATINGDIR
|
2003-01-13 01:35:15 +00:00
|
|
|
operating_dir = NULL;
|
2003-02-05 02:39:34 +00:00
|
|
|
#endif
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2004-02-28 16:24:31 +00:00
|
|
|
backup_dir = NULL;
|
2016-06-30 16:02:45 +00:00
|
|
|
word_chars = NULL;
|
2004-02-28 16:24:31 +00:00
|
|
|
#endif
|
2017-10-31 16:34:07 +00:00
|
|
|
#ifdef ENABLE_JUSTIFY
|
2003-01-13 01:35:15 +00:00
|
|
|
quotestr = NULL;
|
2003-02-05 02:39:34 +00:00
|
|
|
#endif
|
2017-10-31 18:32:42 +00:00
|
|
|
#ifdef ENABLE_SPELLER
|
2003-01-13 01:35:15 +00:00
|
|
|
alt_speller = NULL;
|
2003-02-05 02:39:34 +00:00
|
|
|
#endif
|
2003-01-13 01:35:15 +00:00
|
|
|
|
2016-11-27 17:21:04 +00:00
|
|
|
do_rcfiles();
|
2003-01-13 01:35:15 +00:00
|
|
|
|
2008-03-05 07:34:01 +00:00
|
|
|
#ifdef DEBUG
|
2015-03-27 13:46:50 +00:00
|
|
|
fprintf(stderr, "After rebinding keys...\n");
|
|
|
|
print_sclist();
|
2008-03-05 07:34:01 +00:00
|
|
|
#endif
|
|
|
|
|
2017-05-08 17:42:44 +00:00
|
|
|
/* If the backed-up command-line options have a value, restore them. */
|
2017-10-29 20:08:07 +00:00
|
|
|
#ifdef ENABLE_OPERATINGDIR
|
2003-01-13 01:35:15 +00:00
|
|
|
if (operating_dir_cpy != NULL) {
|
|
|
|
free(operating_dir);
|
|
|
|
operating_dir = operating_dir_cpy;
|
|
|
|
}
|
|
|
|
#endif
|
2017-10-31 16:39:30 +00:00
|
|
|
#ifdef ENABLED_WRAPORJUSTIFY
|
2005-07-25 22:54:16 +00:00
|
|
|
if (fill_used)
|
2003-01-13 01:35:15 +00:00
|
|
|
wrap_at = wrap_at_cpy;
|
|
|
|
#endif
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2004-02-28 16:24:31 +00:00
|
|
|
if (backup_dir_cpy != NULL) {
|
|
|
|
free(backup_dir);
|
|
|
|
backup_dir = backup_dir_cpy;
|
|
|
|
}
|
2016-06-30 16:02:45 +00:00
|
|
|
if (word_chars_cpy != NULL) {
|
|
|
|
free(word_chars);
|
|
|
|
word_chars = word_chars_cpy;
|
|
|
|
}
|
2007-12-10 17:59:26 +00:00
|
|
|
#endif
|
2017-10-31 16:34:07 +00:00
|
|
|
#ifdef ENABLE_JUSTIFY
|
2003-01-13 01:35:15 +00:00
|
|
|
if (quotestr_cpy != NULL) {
|
|
|
|
free(quotestr);
|
|
|
|
quotestr = quotestr_cpy;
|
|
|
|
}
|
|
|
|
#endif
|
2017-10-31 18:32:42 +00:00
|
|
|
#ifdef ENABLE_SPELLER
|
2003-01-13 01:35:15 +00:00
|
|
|
if (alt_speller_cpy != NULL) {
|
|
|
|
free(alt_speller);
|
|
|
|
alt_speller = alt_speller_cpy;
|
|
|
|
}
|
|
|
|
#endif
|
2004-07-18 18:13:54 +00:00
|
|
|
if (tabsize_cpy != -1)
|
2003-01-13 01:35:15 +00:00
|
|
|
tabsize = tabsize_cpy;
|
2009-08-14 03:18:29 +00:00
|
|
|
|
2017-05-08 17:42:44 +00:00
|
|
|
/* Simply OR the boolean flags from rcfile and command line. */
|
2009-08-14 03:18:29 +00:00
|
|
|
for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++)
|
|
|
|
flags[i] |= flags_cpy[i];
|
2003-01-13 01:35:15 +00:00
|
|
|
}
|
2014-04-07 20:05:05 +00:00
|
|
|
#ifdef DISABLE_ROOTWRAPPING
|
|
|
|
/* If we don't have any rcfiles, --disable-wrapping-as-root is used,
|
|
|
|
* and we're root, turn wrapping off. */
|
|
|
|
else if (geteuid() == NANO_ROOT_UID)
|
|
|
|
SET(NO_WRAP);
|
|
|
|
#endif
|
2017-05-08 17:42:44 +00:00
|
|
|
#endif /* ENABLE_NANORC */
|
2003-01-13 01:35:15 +00:00
|
|
|
|
2017-10-29 20:00:09 +00:00
|
|
|
#ifdef ENABLE_WRAPPING
|
2015-11-21 19:44:27 +00:00
|
|
|
/* Override a "set nowrap" in an rcfile (or a --disable-wrapping-as-root)
|
|
|
|
* if --fill was given on the command line and not undone by --nowrap. */
|
|
|
|
if (forced_wrapping)
|
2009-11-18 12:39:47 +00:00
|
|
|
UNSET(NO_WRAP);
|
2009-11-22 21:35:56 +00:00
|
|
|
#endif
|
2009-11-18 12:39:47 +00:00
|
|
|
|
2017-09-17 18:06:04 +00:00
|
|
|
/* If the user wants bold instead of reverse video for hilited text... */
|
2006-04-12 15:27:40 +00:00
|
|
|
if (ISSET(BOLD_TEXT))
|
2014-05-04 08:53:06 +00:00
|
|
|
hilite_attribute = A_BOLD;
|
2006-04-12 15:27:40 +00:00
|
|
|
|
2017-10-29 18:42:12 +00:00
|
|
|
#ifdef ENABLE_HISTORIES
|
2017-09-17 18:06:04 +00:00
|
|
|
/* Initialize the pointers for the Search/Replace/Execute histories. */
|
2003-03-11 03:50:40 +00:00
|
|
|
history_init();
|
2017-09-17 18:06:04 +00:00
|
|
|
|
2017-11-09 20:38:19 +00:00
|
|
|
/* If we need history files, verify that we have a directory for them,
|
|
|
|
* and when not, cancel the options. */
|
|
|
|
if ((ISSET(HISTORYLOG) || ISSET(POS_HISTORY)) && !have_statedir()) {
|
|
|
|
UNSET(HISTORYLOG);
|
|
|
|
UNSET(POS_HISTORY);
|
2011-02-16 06:52:30 +00:00
|
|
|
}
|
2017-09-17 18:06:04 +00:00
|
|
|
|
|
|
|
/* If the user wants history persistence, read the relevant files. */
|
2014-06-19 15:09:23 +00:00
|
|
|
if (ISSET(HISTORYLOG))
|
|
|
|
load_history();
|
|
|
|
if (ISSET(POS_HISTORY))
|
|
|
|
load_poshistory();
|
2017-10-29 18:42:12 +00:00
|
|
|
#endif /* ENABLE_HISTORIES */
|
2003-03-11 03:50:40 +00:00
|
|
|
|
2014-06-19 20:05:24 +00:00
|
|
|
#ifndef NANO_TINY
|
2017-08-05 19:55:03 +00:00
|
|
|
/* If backups are enabled and a backup directory was specified and
|
|
|
|
* we're not in restricted mode, make sure the path exists and is
|
|
|
|
* a directory, so that backup files can be saved there. */
|
|
|
|
if (ISSET(BACKUP_FILE) && backup_dir != NULL && !ISSET(RESTRICTED))
|
2004-05-28 23:45:25 +00:00
|
|
|
init_backup_dir();
|
2014-06-19 20:05:24 +00:00
|
|
|
#endif
|
2004-02-28 16:24:31 +00:00
|
|
|
|
2017-10-29 20:08:07 +00:00
|
|
|
#ifdef ENABLE_OPERATINGDIR
|
2016-06-12 09:13:45 +00:00
|
|
|
/* Set up the operating directory. This entails chdir()ing there,
|
|
|
|
* so that file reads and writes will be based there. */
|
2017-08-05 19:30:27 +00:00
|
|
|
if (operating_dir != NULL)
|
|
|
|
init_operating_dir();
|
2016-06-12 09:13:45 +00:00
|
|
|
#endif
|
|
|
|
|
2017-10-31 16:34:07 +00:00
|
|
|
#ifdef ENABLE_JUSTIFY
|
2006-01-06 21:51:10 +00:00
|
|
|
/* If punct wasn't specified, set its default value. */
|
2004-05-29 16:38:57 +00:00
|
|
|
if (punct == NULL)
|
2006-01-03 04:53:41 +00:00
|
|
|
punct = mallocstrcpy(NULL, "!.?");
|
2004-05-29 16:38:57 +00:00
|
|
|
|
2006-01-06 21:51:10 +00:00
|
|
|
/* If brackets wasn't specified, set its default value. */
|
2004-05-29 16:38:57 +00:00
|
|
|
if (brackets == NULL)
|
2006-01-03 04:53:41 +00:00
|
|
|
brackets = mallocstrcpy(NULL, "\"')>]}");
|
2004-05-29 16:38:57 +00:00
|
|
|
|
2006-01-06 21:51:10 +00:00
|
|
|
/* If quotestr wasn't specified, set its default value. */
|
2003-01-13 01:35:15 +00:00
|
|
|
if (quotestr == NULL)
|
2017-02-21 22:04:39 +00:00
|
|
|
quotestr = mallocstrcpy(NULL, "^([ \t]*[#:>|}])+");
|
2016-03-22 10:42:28 +00:00
|
|
|
quoterc = regcomp("ereg, quotestr, NANO_REG_EXTENDED);
|
2004-07-30 03:54:34 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2017-10-31 16:34:07 +00:00
|
|
|
#endif /* ENABLE_JUSTIFY */
|
2004-02-28 16:24:31 +00:00
|
|
|
|
2017-10-31 18:32:42 +00:00
|
|
|
#ifdef ENABLE_SPELLER
|
2004-05-28 22:42:41 +00:00
|
|
|
/* If we don't have an alternative spell checker after reading the
|
2004-05-29 01:20:17 +00:00
|
|
|
* command line and/or rcfile(s), check $SPELL for one, as Pico
|
2004-05-28 23:45:25 +00:00
|
|
|
* does (unless we're using restricted mode, in which case spell
|
2004-05-29 01:20:17 +00:00
|
|
|
* checking is disabled, since it would allow reading from or
|
|
|
|
* writing to files not specified on the command line). */
|
2004-05-28 23:45:25 +00:00
|
|
|
if (!ISSET(RESTRICTED) && alt_speller == NULL) {
|
2017-11-09 19:58:15 +00:00
|
|
|
const char *spellenv = getenv("SPELL");
|
2004-05-28 22:42:41 +00:00
|
|
|
if (spellenv != NULL)
|
|
|
|
alt_speller = mallocstrcpy(NULL, spellenv);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-01-06 21:51:10 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
/* If matchbrackets wasn't specified, set its default value. */
|
|
|
|
if (matchbrackets == NULL)
|
|
|
|
matchbrackets = mallocstrcpy(NULL, "(<[{)>]}");
|
|
|
|
|
2017-06-18 19:37:42 +00:00
|
|
|
/* If the whitespace option wasn't specified, set its default value. */
|
2014-03-24 13:35:50 +00:00
|
|
|
if (whitespace == NULL) {
|
2014-03-27 11:06:16 +00:00
|
|
|
#ifdef ENABLE_UTF8
|
2014-03-16 13:19:41 +00:00
|
|
|
if (using_utf8()) {
|
2017-06-18 19:37:42 +00:00
|
|
|
/* A tab is shown as a Right-Pointing Double Angle Quotation Mark
|
|
|
|
* (U+00BB), and a space as a Middle Dot (U+00B7). */
|
2014-04-08 12:24:52 +00:00
|
|
|
whitespace = mallocstrcpy(NULL, "\xC2\xBB\xC2\xB7");
|
2014-03-16 13:19:41 +00:00
|
|
|
whitespace_len[0] = 2;
|
|
|
|
whitespace_len[1] = 2;
|
2014-03-27 11:06:16 +00:00
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
2014-03-16 13:19:41 +00:00
|
|
|
whitespace = mallocstrcpy(NULL, ">.");
|
|
|
|
whitespace_len[0] = 1;
|
|
|
|
whitespace_len[1] = 1;
|
|
|
|
}
|
2014-03-24 13:35:50 +00:00
|
|
|
}
|
2014-04-05 20:28:29 +00:00
|
|
|
#endif /* !NANO_TINY */
|
2004-05-29 16:25:30 +00:00
|
|
|
|
2016-03-28 19:14:33 +00:00
|
|
|
/* Initialize the search string. */
|
2015-04-21 18:42:11 +00:00
|
|
|
last_search = mallocstrcpy(NULL, "");
|
2017-10-14 18:49:12 +00:00
|
|
|
UNSET(BACKWARDS_SEARCH);
|
2015-04-21 18:42:11 +00:00
|
|
|
|
2004-09-05 21:40:31 +00:00
|
|
|
/* If tabsize wasn't specified, set its default value. */
|
2003-01-13 01:35:15 +00:00
|
|
|
if (tabsize == -1)
|
2004-09-05 21:40:31 +00:00
|
|
|
tabsize = WIDTH_OF_TAB;
|
2002-06-13 00:40:19 +00:00
|
|
|
|
2007-12-10 17:59:26 +00:00
|
|
|
/* Initialize curses mode. If this fails, get out. */
|
|
|
|
if (initscr() == NULL)
|
|
|
|
exit(1);
|
2005-07-10 02:37:38 +00:00
|
|
|
|
|
|
|
/* Set up the terminal state. */
|
2004-07-27 16:46:35 +00:00
|
|
|
terminal_init();
|
2004-01-12 03:28:06 +00:00
|
|
|
|
2016-09-08 19:00:51 +00:00
|
|
|
#ifdef __linux__
|
2016-07-29 07:15:07 +00:00
|
|
|
/* Check whether we're running on a Linux console. */
|
|
|
|
console = (getenv("DISPLAY") == NULL);
|
2016-08-11 10:37:11 +00:00
|
|
|
#endif
|
2016-08-28 19:00:13 +00:00
|
|
|
|
2005-07-25 22:54:16 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "Main: set up windows\n");
|
|
|
|
#endif
|
2005-07-10 02:37:38 +00:00
|
|
|
|
2017-06-18 19:37:42 +00:00
|
|
|
/* Create the three subwindows, based on the current screen dimensions. */
|
2005-07-25 22:54:16 +00:00
|
|
|
window_init();
|
2017-10-04 19:34:44 +00:00
|
|
|
curs_set(0);
|
2004-02-16 20:32:40 +00:00
|
|
|
|
2016-10-28 08:50:06 +00:00
|
|
|
editwincols = COLS;
|
|
|
|
|
2004-02-16 20:32:40 +00:00
|
|
|
/* Set up the signal handlers. */
|
2002-03-29 16:00:59 +00:00
|
|
|
signal_init();
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2017-05-01 18:45:07 +00:00
|
|
|
#ifdef ENABLE_MOUSE
|
2006-06-09 18:24:37 +00:00
|
|
|
/* Initialize mouse support. */
|
2001-11-29 02:42:27 +00:00
|
|
|
mouse_init();
|
2002-12-22 16:30:00 +00:00
|
|
|
#endif
|
2001-11-29 02:42:27 +00:00
|
|
|
|
2017-11-01 18:45:33 +00:00
|
|
|
#ifdef ENABLE_COLOR
|
2014-05-03 18:24:45 +00:00
|
|
|
set_colorpairs();
|
|
|
|
#else
|
2016-07-12 07:35:48 +00:00
|
|
|
interface_color_pair[TITLE_BAR] = hilite_attribute;
|
2016-10-20 08:07:48 +00:00
|
|
|
interface_color_pair[LINE_NUMBER] = hilite_attribute;
|
2017-07-29 18:24:42 +00:00
|
|
|
interface_color_pair[SELECTED_TEXT] = hilite_attribute;
|
2016-07-12 07:35:48 +00:00
|
|
|
interface_color_pair[STATUS_BAR] = hilite_attribute;
|
|
|
|
interface_color_pair[KEY_COMBO] = hilite_attribute;
|
|
|
|
interface_color_pair[FUNCTION_TAG] = A_NORMAL;
|
2014-05-03 18:24:45 +00:00
|
|
|
#endif
|
|
|
|
|
2016-06-25 13:16:52 +00:00
|
|
|
/* Ask ncurses for the key codes for Control+Left/Right/Up/Down. */
|
2016-08-16 08:49:55 +00:00
|
|
|
controlleft = get_keycode("kLFT5", CONTROL_LEFT);
|
|
|
|
controlright = get_keycode("kRIT5", CONTROL_RIGHT);
|
|
|
|
controlup = get_keycode("kUP5", CONTROL_UP);
|
|
|
|
controldown = get_keycode("kDN5", CONTROL_DOWN);
|
2017-04-05 09:22:35 +00:00
|
|
|
/* Ask for the codes for Control+Home/End. */
|
|
|
|
controlhome = get_keycode("kHOM5", CONTROL_HOME);
|
|
|
|
controlend = get_keycode("kEND5", CONTROL_END);
|
2016-11-17 16:32:28 +00:00
|
|
|
#ifndef NANO_TINY
|
2016-04-24 09:28:28 +00:00
|
|
|
/* Ask for the codes for Shift+Control+Left/Right/Up/Down. */
|
|
|
|
shiftcontrolleft = get_keycode("kLFT6", SHIFT_CONTROL_LEFT);
|
|
|
|
shiftcontrolright = get_keycode("kRIT6", SHIFT_CONTROL_RIGHT);
|
|
|
|
shiftcontrolup = get_keycode("kUP6", SHIFT_CONTROL_UP);
|
|
|
|
shiftcontroldown = get_keycode("kDN6", SHIFT_CONTROL_DOWN);
|
2017-04-05 09:22:35 +00:00
|
|
|
/* Ask for the codes for Shift+Control+Home/End. */
|
|
|
|
shiftcontrolhome = get_keycode("kHOM6", SHIFT_CONTROL_HOME);
|
|
|
|
shiftcontrolend = get_keycode("kEND6", SHIFT_CONTROL_END);
|
2017-08-11 12:23:56 +00:00
|
|
|
/* Ask for the codes for Alt+Left/Right/Up/Down. */
|
|
|
|
altleft = get_keycode("kLFT3", ALT_LEFT);
|
|
|
|
altright = get_keycode("kRIT3", ALT_RIGHT);
|
|
|
|
altup = get_keycode("kUP3", ALT_UP);
|
|
|
|
altdown = get_keycode("kDN3", ALT_DOWN);
|
2016-04-24 09:28:28 +00:00
|
|
|
/* Ask for the codes for Shift+Alt+Left/Right/Up/Down. */
|
|
|
|
shiftaltleft = get_keycode("kLFT4", SHIFT_ALT_LEFT);
|
|
|
|
shiftaltright = get_keycode("kRIT4", SHIFT_ALT_RIGHT);
|
|
|
|
shiftaltup = get_keycode("kUP4", SHIFT_ALT_UP);
|
|
|
|
shiftaltdown = get_keycode("kDN4", SHIFT_ALT_DOWN);
|
2015-11-23 08:52:23 +00:00
|
|
|
#endif
|
|
|
|
|
2017-02-21 22:04:45 +00:00
|
|
|
#ifdef HAVE_SET_ESCDELAY
|
2016-07-11 12:21:38 +00:00
|
|
|
/* Tell ncurses to pass the Esc key quickly. */
|
|
|
|
set_escdelay(50);
|
|
|
|
#endif
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
#ifdef DEBUG
|
2003-08-05 19:31:12 +00:00
|
|
|
fprintf(stderr, "Main: open file\n");
|
2000-06-06 05:53:49 +00:00
|
|
|
#endif
|
2004-09-05 21:40:31 +00:00
|
|
|
|
2017-05-01 18:20:34 +00:00
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
2017-06-18 19:37:42 +00:00
|
|
|
is_multibuffer = ISSET(MULTIBUFFER);
|
2004-09-05 21:40:31 +00:00
|
|
|
SET(MULTIBUFFER);
|
2017-06-10 19:37:21 +00:00
|
|
|
#endif
|
2004-09-05 21:40:31 +00:00
|
|
|
|
2017-06-20 09:06:40 +00:00
|
|
|
/* Read the files mentioned on the command line into new buffers. */
|
2017-06-18 09:12:49 +00:00
|
|
|
while (optind < argc && (!openfile || ISSET(MULTIBUFFER))) {
|
|
|
|
ssize_t givenline = 0, givencol = 0;
|
|
|
|
|
|
|
|
/* If there's a +LINE[,COLUMN] argument here, eat it up. */
|
|
|
|
if (optind < argc - 1 && argv[optind][0] == '+') {
|
|
|
|
if (!parse_line_column(&argv[optind++][1], &givenline, &givencol))
|
|
|
|
statusline(ALERT, _("Invalid line or column number"));
|
|
|
|
}
|
|
|
|
|
2017-06-23 06:27:06 +00:00
|
|
|
/* If the filename is a dash, read from standard input; otherwise,
|
|
|
|
* open the file; skip positioning the cursor if either failed. */
|
2017-06-20 09:06:40 +00:00
|
|
|
if (strcmp(argv[optind], "-") == 0) {
|
2017-06-23 06:27:06 +00:00
|
|
|
if (!scoop_stdin())
|
|
|
|
continue;
|
2017-06-20 09:06:40 +00:00
|
|
|
optind++;
|
|
|
|
} else if (!open_buffer(argv[optind++], FALSE))
|
2017-06-18 09:12:49 +00:00
|
|
|
continue;
|
2005-05-16 18:38:16 +00:00
|
|
|
|
2017-06-18 09:12:49 +00:00
|
|
|
/* If a position was given on the command line, go there. */
|
2017-06-23 08:25:12 +00:00
|
|
|
if (givenline != 0 || givencol != 0)
|
2017-06-18 09:12:49 +00:00
|
|
|
do_gotolinecolumn(givenline, givencol, FALSE, FALSE);
|
2017-10-29 18:42:12 +00:00
|
|
|
#ifdef ENABLE_HISTORIES
|
2017-06-30 07:49:25 +00:00
|
|
|
else if (ISSET(POS_HISTORY) && openfile->filename[0] != '\0') {
|
2017-06-18 09:12:49 +00:00
|
|
|
ssize_t savedline, savedcol;
|
|
|
|
/* If edited before, restore the last cursor position. */
|
|
|
|
if (has_old_position(argv[optind - 1], &savedline, &savedcol))
|
|
|
|
do_gotolinecolumn(savedline, savedcol, FALSE, FALSE);
|
2004-10-22 20:25:56 +00:00
|
|
|
}
|
2017-06-18 09:12:49 +00:00
|
|
|
#endif
|
2004-09-05 21:40:31 +00:00
|
|
|
}
|
|
|
|
|
2017-06-10 19:37:21 +00:00
|
|
|
/* If no filenames were given, or all of them were invalid things like
|
|
|
|
* directories, then open a blank buffer and allow editing. Otherwise,
|
|
|
|
* switch from the last opened file to the next, that is: the first. */
|
2005-07-08 20:09:16 +00:00
|
|
|
if (openfile == NULL) {
|
2008-08-03 04:48:05 +00:00
|
|
|
open_buffer("", FALSE);
|
2004-09-05 21:40:31 +00:00
|
|
|
UNSET(VIEW_MODE);
|
2017-06-18 19:37:42 +00:00
|
|
|
}
|
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
|
|
|
else
|
2017-06-10 19:37:21 +00:00
|
|
|
openfile = openfile->next;
|
2004-09-05 21:40:31 +00:00
|
|
|
|
2017-06-18 19:37:42 +00:00
|
|
|
if (!is_multibuffer)
|
2004-09-05 21:40:31 +00:00
|
|
|
UNSET(MULTIBUFFER);
|
2003-01-13 01:35:15 +00:00
|
|
|
#endif
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2016-02-23 12:37:10 +00:00
|
|
|
#ifdef DEBUG
|
2017-05-01 14:48:13 +00:00
|
|
|
fprintf(stderr, "Main: show title bar, and enter main loop\n");
|
2016-02-23 12:37:10 +00:00
|
|
|
#endif
|
|
|
|
|
2017-05-01 14:48:13 +00:00
|
|
|
prepare_for_display();
|
2000-07-08 14:23:32 +00:00
|
|
|
|
2017-10-28 12:18:37 +00:00
|
|
|
if (rcfile_with_errors != NULL)
|
|
|
|
statusline(ALERT, _("Mistakes in '%s'"), rcfile_with_errors);
|
|
|
|
|
2004-03-15 20:26:30 +00:00
|
|
|
while (TRUE) {
|
2016-10-21 12:31:37 +00:00
|
|
|
#ifdef ENABLE_LINENUMBERS
|
|
|
|
int needed_margin = digits(openfile->filebot->lineno) + 1;
|
|
|
|
|
2017-06-18 19:37:42 +00:00
|
|
|
/* Suppress line numbers when there is not enough room for them. */
|
2017-02-09 16:20:04 +00:00
|
|
|
if (!ISSET(LINE_NUMBERS) || needed_margin > COLS - 4)
|
|
|
|
needed_margin = 0;
|
|
|
|
|
|
|
|
if (needed_margin != margin) {
|
|
|
|
margin = needed_margin;
|
|
|
|
editwincols = COLS - margin;
|
softwrap: adjust firstcolumn when the window width changes
If the number of columns in the edit window changes (which currently
only happens in two places: in regenerate_screen(), called when the
window is resized; and in main(), when line numbering mode is toggled),
the display will break if we're in softwrap mode and firstcolumn is
nonzero. This is because the column width of softwrapped chunks has
changed, and firstcolumn is no longer the starting column of a chunk,
an assumption that all code using firstcolumn relies on.
To fix this problem, add a new function, ensure_firstcolumn_is_aligned(),
to adjust firstcolumn to the starting column of the chunk it's on, and
use it when the number of columns in the edit window changes.
(Note that this function uses the simplest possible fix, and could
probably be made more sophisticated.)
2017-01-23 19:40:03 +00:00
|
|
|
|
2017-05-05 10:33:25 +00:00
|
|
|
#ifndef NANO_TINY
|
softwrap: adjust firstcolumn when the window width changes
If the number of columns in the edit window changes (which currently
only happens in two places: in regenerate_screen(), called when the
window is resized; and in main(), when line numbering mode is toggled),
the display will break if we're in softwrap mode and firstcolumn is
nonzero. This is because the column width of softwrapped chunks has
changed, and firstcolumn is no longer the starting column of a chunk,
an assumption that all code using firstcolumn relies on.
To fix this problem, add a new function, ensure_firstcolumn_is_aligned(),
to adjust firstcolumn to the starting column of the chunk it's on, and
use it when the number of columns in the edit window changes.
(Note that this function uses the simplest possible fix, and could
probably be made more sophisticated.)
2017-01-23 19:40:03 +00:00
|
|
|
/* Ensure that firstcolumn is the starting column of its chunk. */
|
|
|
|
ensure_firstcolumn_is_aligned();
|
2017-05-05 10:33:25 +00:00
|
|
|
#endif
|
2017-02-09 16:20:04 +00:00
|
|
|
/* The margin has changed -- schedule a full refresh. */
|
|
|
|
refresh_needed = TRUE;
|
2016-10-21 12:31:37 +00:00
|
|
|
}
|
2017-02-09 16:20:04 +00:00
|
|
|
#endif
|
2016-10-24 15:38:24 +00:00
|
|
|
|
2017-07-13 08:55:02 +00:00
|
|
|
if (currmenu != MMAIN)
|
|
|
|
display_main_list();
|
2016-05-08 10:01:33 +00:00
|
|
|
|
2016-11-13 19:00:31 +00:00
|
|
|
lastmessage = HUSH;
|
2016-12-20 18:27:41 +00:00
|
|
|
as_an_at = TRUE;
|
2016-11-13 19:00:31 +00:00
|
|
|
|
|
|
|
/* Update the displayed current cursor position only when there
|
|
|
|
* are no keys waiting in the input buffer. */
|
2017-04-17 09:51:48 +00:00
|
|
|
if (ISSET(CONSTANT_SHOW) && get_key_buffer_len() == 0)
|
2017-02-23 17:31:36 +00:00
|
|
|
do_cursorpos(FALSE);
|
2016-11-13 19:00:31 +00:00
|
|
|
|
2016-12-03 16:47:37 +00:00
|
|
|
/* Refresh just the cursor position or the entire edit window. */
|
2016-11-12 16:59:28 +00:00
|
|
|
if (!refresh_needed) {
|
2017-07-22 04:26:59 +00:00
|
|
|
place_the_cursor();
|
2016-11-12 16:59:28 +00:00
|
|
|
wnoutrefresh(edit);
|
|
|
|
} else
|
|
|
|
edit_refresh();
|
|
|
|
|
2016-04-12 08:24:57 +00:00
|
|
|
focusing = TRUE;
|
2003-01-28 01:16:47 +00:00
|
|
|
|
2016-04-17 13:24:05 +00:00
|
|
|
/* Forget any earlier statusbar x position. */
|
|
|
|
reinit_statusbar_x();
|
|
|
|
|
2016-06-24 20:45:41 +00:00
|
|
|
/* Read in and interpret keystrokes. */
|
2014-06-30 18:04:33 +00:00
|
|
|
do_input(TRUE);
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
2005-03-04 17:09:41 +00:00
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* We should never get here. */
|
2004-03-19 21:57:56 +00:00
|
|
|
assert(FALSE);
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|