2000-06-06 05:53:49 +00:00
|
|
|
/**************************************************************************
|
|
|
|
* nano.c *
|
|
|
|
* *
|
2009-12-02 03:36:22 +00:00
|
|
|
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
2014-04-30 20:18:26 +00:00
|
|
|
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
2000-06-06 05:53:49 +00:00
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
2007-08-11 05:17:36 +00:00
|
|
|
* the Free Software Foundation; either version 3, or (at your option) *
|
2000-06-06 05:53:49 +00:00
|
|
|
* any later version. *
|
|
|
|
* *
|
2005-05-15 19:57:17 +00:00
|
|
|
* This program is distributed in the hope that it will be useful, but *
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
|
|
|
* General Public License for more details. *
|
2000-06-06 05:53:49 +00:00
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
|
|
|
* along with this program; if not, write to the Free Software *
|
2005-05-15 19:57:17 +00:00
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
|
|
|
* 02110-1301, USA. *
|
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 <stdio.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <locale.h>
|
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
|
2005-12-28 05:01:00 +00:00
|
|
|
#include <termios.h>
|
2000-06-06 05:53:49 +00:00
|
|
|
#ifdef HAVE_GETOPT_H
|
|
|
|
#include <getopt.h>
|
|
|
|
#endif
|
2006-07-12 18:57:04 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#endif
|
|
|
|
|
2007-12-04 20:49:09 +00:00
|
|
|
#ifndef DISABLE_MOUSE
|
|
|
|
static int oldinterval = -1;
|
|
|
|
/* Used to store the user's original mouse click interval. */
|
|
|
|
#endif
|
2014-04-13 20:50:20 +00:00
|
|
|
#ifndef DISABLE_NANORC
|
2006-04-24 18:54:29 +00:00
|
|
|
static bool no_rcfiles = FALSE;
|
|
|
|
/* Should we ignore all rcfiles? */
|
|
|
|
#endif
|
2005-12-08 07:09:08 +00:00
|
|
|
static struct termios oldterm;
|
|
|
|
/* The user's original terminal settings. */
|
|
|
|
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
|
|
|
|
2006-08-29 21:18:24 +00:00
|
|
|
/* Create a new filestruct node. Note that we do not set prevnode->next
|
|
|
|
* 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
|
|
|
{
|
2005-07-08 02:47:05 +00:00
|
|
|
filestruct *newnode = (filestruct *)nmalloc(sizeof(filestruct));
|
|
|
|
|
|
|
|
newnode->data = NULL;
|
|
|
|
newnode->prev = prevnode;
|
|
|
|
newnode->next = NULL;
|
|
|
|
newnode->lineno = (prevnode != NULL) ? prevnode->lineno + 1 : 1;
|
|
|
|
|
2014-04-04 11:59:03 +00:00
|
|
|
#ifndef DISABLE_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
|
|
|
}
|
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* Make a copy of a filestruct node. */
|
|
|
|
filestruct *copy_node(const filestruct *src)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2005-07-08 02:47:05 +00:00
|
|
|
filestruct *dst;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
assert(src != NULL);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
dst = (filestruct *)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;
|
2014-04-04 11:59:03 +00:00
|
|
|
#ifndef DISABLE_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
|
|
|
}
|
|
|
|
|
2015-11-24 13:28:32 +00:00
|
|
|
/* Splice a new node into an existing linked list of filestructs. */
|
|
|
|
void splice_node(filestruct *afterthis, filestruct *newnode)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2015-11-24 13:28:32 +00:00
|
|
|
assert(afterthis != NULL && newnode != NULL);
|
2005-06-06 16:27:18 +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
|
|
|
|
2015-12-08 16:02:05 +00:00
|
|
|
/* Disconnect a node from a linked list of filestructs and delete it. */
|
2015-11-22 16:14:42 +00:00
|
|
|
void unlink_node(filestruct *fileptr)
|
2005-07-08 02:47:05 +00:00
|
|
|
{
|
|
|
|
assert(fileptr != NULL);
|
2001-07-11 02:08:33 +00:00
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
assert(fileptr != NULL && fileptr->data != NULL);
|
2001-07-11 02:08:33 +00:00
|
|
|
|
2015-06-14 19:14:41 +00:00
|
|
|
free(fileptr->data);
|
2014-04-04 11:59:03 +00:00
|
|
|
#ifndef DISABLE_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
|
|
|
}
|
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* Duplicate a whole filestruct. */
|
|
|
|
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
|
|
|
assert(src != NULL);
|
2004-04-30 04:49:02 +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
|
|
|
}
|
|
|
|
|
2016-02-18 19:58:18 +00:00
|
|
|
/* Free a whole linked list of filestructs. */
|
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
|
|
|
}
|
|
|
|
|
2005-07-17 01:44:35 +00:00
|
|
|
/* Renumber all entries in a filestruct, 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
|
|
|
}
|
|
|
|
|
2007-01-11 22:54:55 +00:00
|
|
|
/* Partition a filestruct so that it begins at (top, top_x) and ends 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
|
|
|
|
* and bottom of the filestruct, save the latter and then set them
|
|
|
|
* 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. */
|
|
|
|
null_at(&bot->data, bot_x);
|
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);
|
2005-07-08 02:47:05 +00:00
|
|
|
align(&top->data);
|
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
|
|
|
|
2007-01-11 22:54:55 +00:00
|
|
|
/* Unpartition a filestruct so that it begins at (fileage, 0) and ends
|
|
|
|
* at (filebot, strlen(filebot->data)) 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
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* Restore the top and bottom of the filestruct, if they were
|
|
|
|
* 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
|
|
|
|
* current filestruct to a filestruct beginning with file_top and ending
|
|
|
|
* with file_bot. If no text is between (top, top_x) and (bot, bot_x),
|
|
|
|
* don't do anything. */
|
|
|
|
void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
|
|
|
|
filestruct *top, size_t top_x, filestruct *bot, size_t bot_x)
|
|
|
|
{
|
|
|
|
filestruct *top_save;
|
2005-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
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* Partition the filestruct so that it contains only the text from
|
|
|
|
* (top, top_x) to (bot, bot_x), keep track of whether the top of
|
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
|
2014-02-22 16:46:27 +00:00
|
|
|
if (openfile->mark_set) {
|
2005-07-12 17:40:16 +00:00
|
|
|
mark_inside = (openfile->mark_begin->lineno >=
|
2005-07-08 20:09:16 +00:00
|
|
|
openfile->fileage->lineno &&
|
2005-07-12 17:40:16 +00:00
|
|
|
openfile->mark_begin->lineno <=
|
2005-07-08 20:09:16 +00:00
|
|
|
openfile->filebot->lineno &&
|
2005-07-12 17:40:16 +00:00
|
|
|
(openfile->mark_begin != openfile->fileage ||
|
|
|
|
openfile->mark_begin_x >= top_x) &&
|
|
|
|
(openfile->mark_begin != openfile->filebot ||
|
|
|
|
openfile->mark_begin_x <= bot_x));
|
2014-02-22 16:46:27 +00:00
|
|
|
same_line = (openfile->mark_begin == openfile->fileage);
|
|
|
|
}
|
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
|
|
|
|
2016-06-14 09:06:04 +00:00
|
|
|
/* Since the text has now been saved, remove it from the filestruct. */
|
2005-07-08 20:09:16 +00:00
|
|
|
openfile->fileage = (filestruct *)nmalloc(sizeof(filestruct));
|
|
|
|
openfile->fileage->data = mallocstrcpy(NULL, "");
|
|
|
|
openfile->filebot = openfile->fileage;
|
2007-08-07 19:55:06 +00:00
|
|
|
|
2014-04-04 11:59:03 +00:00
|
|
|
#ifndef DISABLE_COLOR
|
2009-02-03 05:05:58 +00:00
|
|
|
openfile->fileage->multidata = NULL;
|
2009-01-31 23:36:00 +00:00
|
|
|
#endif
|
|
|
|
|
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) {
|
2007-08-07 19:55:06 +00:00
|
|
|
openfile->mark_begin = openfile->current;
|
|
|
|
openfile->mark_begin_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. */
|
2014-02-22 16:46:27 +00:00
|
|
|
openfile->mark_begin = 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
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* Unpartition the filestruct so that it contains all the text
|
|
|
|
* 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-04-07 11:58:51 +00:00
|
|
|
edit_update(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
|
|
|
|
2014-04-14 09:14:39 +00:00
|
|
|
/* Copy all text from the given filestruct to the current filestruct
|
|
|
|
* at the current cursor position. */
|
|
|
|
void copy_from_filestruct(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. */
|
|
|
|
if (openfile->mark_set) {
|
|
|
|
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
|
|
|
|
|
2016-06-14 09:06:04 +00:00
|
|
|
/* Partition the filestruct 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
|
|
|
|
2014-04-14 09:14:39 +00:00
|
|
|
/* Put the top and bottom of the current filestruct at the top and
|
|
|
|
* bottom of a copy of the passed buffer. */
|
|
|
|
openfile->fileage = copy_filestruct(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
|
2015-10-31 19:03:53 +00:00
|
|
|
if (openfile->mark_set && single_line) {
|
2007-08-07 20:21:39 +00:00
|
|
|
openfile->mark_begin = openfile->current;
|
2007-08-16 14:45:17 +00:00
|
|
|
if (!right_side_up)
|
2007-08-07 20:21:39 +00:00
|
|
|
openfile->mark_begin_x += openfile->current_x;
|
|
|
|
}
|
|
|
|
#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
|
2015-10-31 20:17:09 +00:00
|
|
|
else if (openfile->mark_set && single_line) {
|
|
|
|
if (right_side_up)
|
|
|
|
openfile->mark_begin = openfile->fileage;
|
|
|
|
else {
|
|
|
|
openfile->mark_begin = openfile->current;
|
|
|
|
openfile->mark_begin_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
|
|
|
|
2005-09-02 04:35:58 +00:00
|
|
|
/* Update the current y-coordinate to account for the number of
|
|
|
|
* lines the copied text has, less one since the first line will be
|
|
|
|
* tacked onto the current line. */
|
2005-07-17 01:44:35 +00:00
|
|
|
openfile->current_y += openfile->filebot->lineno - 1;
|
2002-09-06 20:35:28 +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;
|
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* Unpartition the filestruct 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
|
|
|
}
|
|
|
|
|
2005-07-20 21:08:38 +00:00
|
|
|
/* Create a new openfilestruct node. */
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
/* Unlink a node from the rest of the openfilestruct, and delete it. */
|
|
|
|
void unlink_opennode(openfilestruct *fileptr)
|
|
|
|
{
|
2015-05-03 13:56:51 +00:00
|
|
|
assert(fileptr != NULL && fileptr->prev != NULL && fileptr->next != NULL &&
|
2016-05-30 07:09:36 +00:00
|
|
|
fileptr != fileptr->prev && fileptr != fileptr->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)
|
|
|
|
{
|
|
|
|
assert(fileptr != NULL && fileptr->filename != NULL && fileptr->fileage != NULL);
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DISABLE_HELP
|
|
|
|
/* 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
|
|
|
|
2014-06-19 20:05:24 +00:00
|
|
|
#ifndef DISABLE_HISTORIES
|
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-16 06:52:30 +00:00
|
|
|
save_poshistory();
|
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
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* Save the current file buffer if it's been modified. */
|
2008-05-31 22:23:16 +00:00
|
|
|
if (openfile && openfile->modified) {
|
2005-07-08 02:47:05 +00:00
|
|
|
/* If we've partitioned the filestruct, unpartition it now. */
|
|
|
|
if (filepart != NULL)
|
|
|
|
unpartition_filestruct(&filepart);
|
|
|
|
|
2009-11-22 21:35:56 +00:00
|
|
|
die_save_file(openfile->filename
|
|
|
|
#ifndef NANO_TINY
|
|
|
|
, openfile->current_stat
|
|
|
|
#endif
|
|
|
|
);
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
|
2014-04-03 20:23:07 +00:00
|
|
|
#ifndef DISABLE_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) {
|
|
|
|
openfilestruct *tmp = openfile;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2005-07-08 19:57:25 +00:00
|
|
|
while (tmp != openfile->next) {
|
|
|
|
openfile = openfile->next;
|
2004-11-25 04:39:07 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* Save the current file buffer if it's been modified. */
|
2005-07-08 20:09:16 +00:00
|
|
|
if (openfile->modified)
|
2009-11-22 21:35:56 +00:00
|
|
|
die_save_file(openfile->filename
|
|
|
|
#ifndef NANO_TINY
|
|
|
|
, openfile->current_stat
|
|
|
|
#endif
|
|
|
|
);
|
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
|
|
|
|
|
|
|
|
/* Get out. */
|
|
|
|
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. */
|
2009-11-22 21:35:56 +00:00
|
|
|
void die_save_file(const char *die_filename
|
|
|
|
#ifndef NANO_TINY
|
|
|
|
, struct stat *die_stat
|
|
|
|
#endif
|
|
|
|
)
|
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
|
|
|
{
|
2005-07-25 22:54:16 +00:00
|
|
|
/* If the screen height is too small, get out. */
|
2014-06-19 11:58:11 +00:00
|
|
|
editwinrows = LINES - 5 + more_space() + no_help();
|
2005-10-26 23:14:59 +00:00
|
|
|
if (COLS < MIN_EDITOR_COLS || editwinrows < MIN_EDITOR_ROWS)
|
2005-07-08 02:47:05 +00:00
|
|
|
die(_("Window size is too small for nano...\n"));
|
2005-07-10 02:37:38 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
#ifndef DISABLE_WRAPJUSTIFY
|
2005-07-25 22:54:16 +00:00
|
|
|
/* Set up fill, based on the screen width. */
|
2005-07-08 02:47:05 +00:00
|
|
|
fill = wrap_at;
|
|
|
|
if (fill <= 0)
|
|
|
|
fill += COLS;
|
|
|
|
if (fill < 0)
|
|
|
|
fill = 0;
|
|
|
|
#endif
|
2004-11-03 22:03:41 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
if (topwin != NULL)
|
|
|
|
delwin(topwin);
|
|
|
|
if (edit != NULL)
|
|
|
|
delwin(edit);
|
|
|
|
if (bottomwin != NULL)
|
|
|
|
delwin(bottomwin);
|
2004-11-03 22:03:41 +00:00
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
/* Set up the windows. */
|
2014-06-19 11:58:11 +00:00
|
|
|
topwin = newwin(2 - more_space(), COLS, 0, 0);
|
|
|
|
edit = newwin(editwinrows, COLS, 2 - more_space(), 0);
|
2005-07-21 05:56:42 +00:00
|
|
|
bottomwin = newwin(3 - no_help(), COLS, editwinrows + (2 -
|
2014-06-19 11:58:11 +00:00
|
|
|
more_space()), 0);
|
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);
|
|
|
|
}
|
2004-11-03 22:03:41 +00:00
|
|
|
}
|
|
|
|
|
2005-07-08 02:47:05 +00:00
|
|
|
#ifndef DISABLE_MOUSE
|
2006-06-09 18:24:37 +00:00
|
|
|
/* Disable mouse support. */
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
/* Enable mouse support. */
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialize mouse support. Enable it if the USE_MOUSE flag is set,
|
|
|
|
* and disable it otherwise. */
|
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
|
|
|
}
|
2006-06-09 18:24:37 +00:00
|
|
|
#endif /* !DISABLE_MOUSE */
|
2004-11-23 04:08:28 +00:00
|
|
|
|
2005-03-22 20:17:38 +00:00
|
|
|
#ifdef HAVE_GETOPT_LONG
|
2006-05-12 19:30:28 +00:00
|
|
|
#define print_opt(shortflag, longflag, desc) print_opt_full(shortflag, longflag, desc)
|
2005-03-22 20:17:38 +00:00
|
|
|
#else
|
2006-05-12 19:30:28 +00:00
|
|
|
#define print_opt(shortflag, longflag, desc) print_opt_full(shortflag, desc)
|
2005-03-22 20:17:38 +00:00
|
|
|
#endif
|
|
|
|
|
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). */
|
2006-05-12 19:30:28 +00:00
|
|
|
void print_opt_full(const char *shortflag
|
2005-03-21 07:24:47 +00:00
|
|
|
#ifdef HAVE_GETOPT_LONG
|
|
|
|
, const char *longflag
|
|
|
|
#endif
|
|
|
|
, 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");
|
|
|
|
|
|
|
|
#ifdef HAVE_GETOPT_LONG
|
|
|
|
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");
|
|
|
|
#endif
|
|
|
|
|
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
|
|
|
{
|
2006-06-26 04:39:31 +00:00
|
|
|
printf(_("Usage: nano [OPTIONS] [[+LINE,COLUMN] FILE]...\n\n"));
|
2005-05-21 17:15:46 +00:00
|
|
|
printf(
|
2006-05-08 19:55:18 +00:00
|
|
|
#ifdef HAVE_GETOPT_LONG
|
|
|
|
_("Option\t\tGNU long option\t\tMeaning\n")
|
2000-06-06 05:53:49 +00:00
|
|
|
#else
|
2006-05-08 19:55:18 +00:00
|
|
|
_("Option\t\tMeaning\n")
|
2004-08-07 22:00:02 +00:00
|
|
|
#endif
|
2006-05-08 19:55:18 +00:00
|
|
|
);
|
2006-06-26 04:39:31 +00:00
|
|
|
print_opt(_("+LINE,COLUMN"), "",
|
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. */
|
2005-05-21 17:15:46 +00:00
|
|
|
N_("Start at line LINE, column COLUMN"));
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2006-05-12 19:30:28 +00:00
|
|
|
print_opt("-A", "--smarthome", 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
|
2014-04-03 20:23:07 +00:00
|
|
|
#ifndef DISABLE_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
|
|
|
|
#ifndef DISABLE_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
|
|
|
|
#ifndef DISABLE_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"));
|
2014-06-19 20:05:24 +00:00
|
|
|
#ifndef DISABLE_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
|
2002-03-03 22:36:36 +00:00
|
|
|
#ifndef DISABLE_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"));
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2006-05-12 19:30:28 +00:00
|
|
|
print_opt("-U", "--quickblank", N_("Do quick statusbar blanking"));
|
2005-06-17 19:09:18 +00:00
|
|
|
#endif
|
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-06-30 16:02:45 +00:00
|
|
|
print_opt("-X", "--wordchars",
|
|
|
|
N_("Which other characters are word parts"));
|
2005-08-10 22:12:28 +00:00
|
|
|
#endif
|
2014-04-04 11:59:03 +00:00
|
|
|
#ifndef DISABLE_COLOR
|
2015-07-29 19:31:50 +00:00
|
|
|
if (!ISSET(RESTRICTED))
|
2015-07-30 11:29:45 +00:00
|
|
|
print_opt(_("-Y <str>"), _("--syntax=<str>"),
|
|
|
|
N_("Syntax definition to use for coloring"));
|
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"));
|
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"));
|
2006-05-12 19:30:28 +00:00
|
|
|
print_opt("-k", "--cut", N_("Cut from cursor to end of line"));
|
2005-03-26 22:49:46 +00:00
|
|
|
#endif
|
2003-10-03 20:26:25 +00:00
|
|
|
#ifndef DISABLE_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)"));
|
2001-09-19 03:19:43 +00:00
|
|
|
#ifndef DISABLE_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"));
|
2014-07-02 19:57:23 +00:00
|
|
|
#ifndef DISABLE_NANORC
|
2015-07-29 19:31:50 +00:00
|
|
|
if (!ISSET(RESTRICTED))
|
2015-07-30 11:29:45 +00:00
|
|
|
print_opt("-q", "--quiet",
|
|
|
|
N_("Silently ignore startup issues like rc file errors"));
|
2014-07-02 19:57:23 +00:00
|
|
|
#endif
|
2001-05-21 12:56:25 +00:00
|
|
|
#ifndef DISABLE_WRAPJUSTIFY
|
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
|
2001-01-12 07:51:05 +00:00
|
|
|
#ifndef DISABLE_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)"));
|
2001-04-02 05:36:08 +00:00
|
|
|
#ifndef DISABLE_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-05-20 10:59:57 +00:00
|
|
|
printf(" nano from git, %s\n", REVISION);
|
2016-04-08 08:22:09 +00:00
|
|
|
#else
|
2016-06-13 10:17:13 +00:00
|
|
|
printf(_(" nano, version %s\n"), VERSION);
|
2016-04-08 08:22:09 +00:00
|
|
|
#endif
|
2016-01-10 16:18:43 +00:00
|
|
|
printf(" (C) 1999..2016 Free Software Foundation, Inc.\n");
|
2016-06-14 11:01:50 +00:00
|
|
|
printf(_(" (C) 2014..%s the contributors to nano\n"), "2016");
|
2005-03-11 04:22:34 +00:00
|
|
|
printf(
|
2016-06-20 17:44:56 +00:00
|
|
|
_(" 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");
|
|
|
|
#ifndef DISABLE_BROWSER
|
|
|
|
printf(" --enable-browser");
|
|
|
|
#endif
|
|
|
|
#ifndef DISABLE_COLOR
|
|
|
|
printf(" --enable-color");
|
|
|
|
#endif
|
|
|
|
#ifndef DISABLE_EXTRA
|
|
|
|
printf(" --enable-extra");
|
|
|
|
#endif
|
|
|
|
#ifndef DISABLE_HELP
|
|
|
|
printf(" --enable-help");
|
|
|
|
#endif
|
2014-06-19 20:05:24 +00:00
|
|
|
#ifndef DISABLE_HISTORIES
|
|
|
|
printf(" --enable-histories");
|
|
|
|
#endif
|
2014-04-05 19:57:17 +00:00
|
|
|
#ifndef DISABLE_JUSTIFY
|
|
|
|
printf(" --enable-justify");
|
|
|
|
#endif
|
2014-04-13 19:54:47 +00:00
|
|
|
#ifdef HAVE_LIBMAGIC
|
|
|
|
printf(" --enable-libmagic");
|
|
|
|
#endif
|
2014-04-05 19:57:17 +00:00
|
|
|
#ifndef DISABLE_MOUSE
|
|
|
|
printf(" --enable-mouse");
|
|
|
|
#endif
|
2014-04-13 20:50:20 +00:00
|
|
|
#ifndef DISABLE_NANORC
|
|
|
|
printf(" --enable-nanorc");
|
|
|
|
#endif
|
2014-04-05 19:57:17 +00:00
|
|
|
#ifndef DISABLE_MULTIBUFFER
|
|
|
|
printf(" --enable-multibuffer");
|
|
|
|
#endif
|
|
|
|
#ifndef DISABLE_OPERATINGDIR
|
|
|
|
printf(" --enable-operatingdir");
|
|
|
|
#endif
|
|
|
|
#ifndef DISABLE_SPELLER
|
|
|
|
printf(" --enable-speller");
|
|
|
|
#endif
|
|
|
|
#ifndef DISABLE_TABCOMP
|
|
|
|
printf(" --enable-tabcomp");
|
|
|
|
#endif
|
|
|
|
#ifndef DISABLE_WRAPPING
|
|
|
|
printf(" --enable-wrapping");
|
|
|
|
#endif
|
|
|
|
#else /* !NANO_TINY */
|
2001-04-12 03:01:53 +00:00
|
|
|
#ifdef DISABLE_BROWSER
|
2001-01-05 05:41:07 +00:00
|
|
|
printf(" --disable-browser");
|
2001-04-12 03:01:53 +00:00
|
|
|
#endif
|
2014-04-05 19:57:17 +00:00
|
|
|
#ifdef DISABLE_COLOR
|
|
|
|
printf(" --disable-color");
|
|
|
|
#endif
|
2016-05-25 20:13:50 +00:00
|
|
|
#ifndef ENABLE_COMMENT
|
|
|
|
printf(" --disable-comment");
|
|
|
|
#endif
|
2014-04-03 20:57:44 +00:00
|
|
|
#ifdef DISABLE_EXTRA
|
|
|
|
printf(" --disable-extra");
|
|
|
|
#endif
|
2002-09-06 20:35:28 +00:00
|
|
|
#ifdef DISABLE_HELP
|
|
|
|
printf(" --disable-help");
|
2001-04-12 03:01:53 +00:00
|
|
|
#endif
|
2014-06-19 20:05:24 +00:00
|
|
|
#ifdef DISABLE_HISTORIES
|
|
|
|
printf(" --disable-histories");
|
|
|
|
#endif
|
2001-04-12 03:01:53 +00:00
|
|
|
#ifdef DISABLE_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
|
2003-10-03 20:26:25 +00:00
|
|
|
#ifdef DISABLE_MOUSE
|
2001-04-12 14:51:48 +00:00
|
|
|
printf(" --disable-mouse");
|
2000-12-18 05:36:51 +00:00
|
|
|
#endif
|
2014-04-03 20:23:07 +00:00
|
|
|
#ifdef DISABLE_MULTIBUFFER
|
|
|
|
printf(" --disable-multibuffer");
|
|
|
|
#endif
|
2014-04-13 20:50:20 +00:00
|
|
|
#ifdef DISABLE_NANORC
|
|
|
|
printf(" --disable-nanorc");
|
|
|
|
#endif
|
2001-09-19 03:19:43 +00:00
|
|
|
#ifdef DISABLE_OPERATINGDIR
|
|
|
|
printf(" --disable-operatingdir");
|
|
|
|
#endif
|
2002-09-06 20:35:28 +00:00
|
|
|
#ifdef DISABLE_SPELLER
|
|
|
|
printf(" --disable-speller");
|
|
|
|
#endif
|
|
|
|
#ifdef DISABLE_TABCOMP
|
|
|
|
printf(" --disable-tabcomp");
|
|
|
|
#endif
|
|
|
|
#ifdef DISABLE_WRAPPING
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Return 1 if the MORE_SPACE flag is set, and 0 otherwise. This is
|
2014-06-19 11:58:11 +00:00
|
|
|
* used to calculate the sizes and Y coordinates of the subwindows. */
|
|
|
|
int more_space(void)
|
2005-01-17 05:06:55 +00:00
|
|
|
{
|
|
|
|
return ISSET(MORE_SPACE) ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Return 2 if the NO_HELP flag is set, and 0 otherwise. This is used
|
2014-06-19 11:58:11 +00:00
|
|
|
* to calculate the sizes and Y coordinates of the subwindows, because
|
|
|
|
* having NO_HELP adds two lines to the edit window. */
|
2000-06-06 05:53:49 +00:00
|
|
|
int no_help(void)
|
|
|
|
{
|
2002-07-19 01:08:59 +00:00
|
|
|
return ISSET(NO_HELP) ? 2 : 0;
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
|
2015-10-29 10:36:07 +00:00
|
|
|
/* Indicate that the current file has no name, in a way that gets the
|
|
|
|
* user's attention. This is used when trying to save a file with no
|
|
|
|
* name with the TEMP_FILE flag set, just before the filename prompt. */
|
|
|
|
void no_current_file_name_warning(void)
|
|
|
|
{
|
|
|
|
/* Warn that the current file has no name. */
|
|
|
|
statusbar(_("No file name"));
|
|
|
|
beep();
|
|
|
|
|
|
|
|
/* Ensure that we see the warning. */
|
|
|
|
napms(1800);
|
|
|
|
|
|
|
|
curs_set(1);
|
|
|
|
}
|
|
|
|
|
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))
|
|
|
|
no_current_file_name_warning();
|
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. */
|
2015-12-23 16:34:44 +00:00
|
|
|
if (i == 0 || (i == 1 && do_writeout(TRUE)))
|
|
|
|
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
|
2014-04-03 20:23:07 +00:00
|
|
|
#ifndef DISABLE_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
|
|
|
|
2015-05-03 13:56:51 +00:00
|
|
|
static struct sigaction pager_oldaction, pager_newaction;
|
|
|
|
/* Original and temporary handlers for SIGINT. */
|
|
|
|
static bool pager_sig_failed = FALSE;
|
|
|
|
/* Did sigaction() fail without changing the signal handlers? */
|
|
|
|
static bool pager_input_aborted = FALSE;
|
|
|
|
/* Did someone invoke the pager and abort it via ^C? */
|
2010-03-21 05:31:43 +00:00
|
|
|
|
2009-01-30 17:37:44 +00:00
|
|
|
/* Things which need to be run regardless of whether
|
2014-03-24 21:48:23 +00:00
|
|
|
* we finished the stdin pipe correctly or not. */
|
2009-01-30 17:37:44 +00:00
|
|
|
void finish_stdin_pager(void)
|
|
|
|
{
|
|
|
|
FILE *f;
|
|
|
|
int ttystdin;
|
|
|
|
|
2014-03-24 21:48:23 +00:00
|
|
|
/* Read whatever we did get from stdin. */
|
2009-01-30 17:37:44 +00:00
|
|
|
f = fopen("/dev/stdin", "rb");
|
2015-03-20 11:18:22 +00:00
|
|
|
if (f == NULL)
|
|
|
|
nperror("fopen");
|
2009-01-30 17:37:44 +00:00
|
|
|
|
2009-12-09 16:51:43 +00:00
|
|
|
read_file(f, 0, "stdin", TRUE, FALSE);
|
2016-04-25 13:44:52 +00:00
|
|
|
openfile->edittop = openfile->fileage;
|
|
|
|
|
2009-01-30 17:37:44 +00:00
|
|
|
ttystdin = open("/dev/tty", O_RDONLY);
|
|
|
|
if (!ttystdin)
|
2015-03-20 11:18:22 +00:00
|
|
|
die(_("Couldn't reopen stdin from keyboard, sorry\n"));
|
2009-01-30 17:37:44 +00:00
|
|
|
|
|
|
|
dup2(ttystdin,0);
|
|
|
|
close(ttystdin);
|
2010-03-21 05:31:43 +00:00
|
|
|
if (!pager_input_aborted)
|
|
|
|
tcgetattr(0, &oldterm);
|
2009-01-30 17:37:44 +00:00
|
|
|
if (!pager_sig_failed && sigaction(SIGINT, &pager_oldaction, NULL) == -1)
|
2015-03-20 11:18:22 +00:00
|
|
|
nperror("sigaction");
|
2009-01-30 17:37:44 +00:00
|
|
|
terminal_init();
|
|
|
|
doupdate();
|
|
|
|
}
|
|
|
|
|
2014-03-24 21:48:23 +00:00
|
|
|
/* Cancel reading from stdin like a pager. */
|
2009-01-30 17:37:44 +00:00
|
|
|
RETSIGTYPE cancel_stdin_pager(int signal)
|
|
|
|
{
|
2010-03-21 05:31:43 +00:00
|
|
|
pager_input_aborted = TRUE;
|
2009-01-30 17:37:44 +00:00
|
|
|
}
|
|
|
|
|
2014-03-24 21:48:23 +00:00
|
|
|
/* Let nano read stdin for the first file at least. */
|
2009-01-30 17:37:44 +00:00
|
|
|
void stdin_pager(void)
|
|
|
|
{
|
|
|
|
endwin();
|
2010-03-21 05:31:43 +00:00
|
|
|
if (!pager_input_aborted)
|
|
|
|
tcsetattr(0, TCSANOW, &oldterm);
|
2009-01-30 17:37:44 +00:00
|
|
|
fprintf(stderr, _("Reading from stdin, ^C to abort\n"));
|
|
|
|
|
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-02-01 00:04:42 +00:00
|
|
|
#ifndef NANO_TINY
|
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
|
|
|
|
2015-03-20 11:18:22 +00:00
|
|
|
/* Set things up so that SIGINT will cancel the new process. */
|
2009-01-30 17:37:44 +00:00
|
|
|
if (sigaction(SIGINT, NULL, &pager_newaction) == -1) {
|
|
|
|
pager_sig_failed = TRUE;
|
|
|
|
nperror("sigaction");
|
|
|
|
} else {
|
|
|
|
pager_newaction.sa_handler = cancel_stdin_pager;
|
|
|
|
if (sigaction(SIGINT, &pager_newaction, &pager_oldaction) == -1) {
|
|
|
|
pager_sig_failed = TRUE;
|
|
|
|
nperror("sigaction");
|
|
|
|
}
|
|
|
|
}
|
2010-03-21 05:31:43 +00:00
|
|
|
|
2009-01-30 17:37:44 +00:00
|
|
|
open_buffer("", FALSE);
|
|
|
|
finish_stdin_pager();
|
|
|
|
}
|
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Initialize the 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);
|
2004-01-26 20:56:20 +00:00
|
|
|
sigaction(SIGQUIT, &act, NULL);
|
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;
|
2002-09-06 20:35:28 +00:00
|
|
|
sigaction(SIGHUP, &act, NULL);
|
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
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
/* Trap normal suspend (^Z) so we can handle it ourselves. */
|
2002-09-06 20:35:28 +00:00
|
|
|
if (!ISSET(SUSPEND)) {
|
|
|
|
act.sa_handler = SIG_IGN;
|
|
|
|
sigaction(SIGTSTP, &act, NULL);
|
|
|
|
} else {
|
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);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2002-09-06 20:35:28 +00:00
|
|
|
act.sa_handler = do_suspend;
|
|
|
|
sigaction(SIGTSTP, &act, NULL);
|
2002-05-12 19:52:15 +00:00
|
|
|
|
2005-12-06 19:39:56 +00:00
|
|
|
act.sa_handler = do_continue;
|
2002-09-06 20:35:28 +00:00
|
|
|
sigaction(SIGCONT, &act, NULL);
|
|
|
|
}
|
|
|
|
}
|
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
|
|
|
{
|
2006-06-09 18:24:37 +00:00
|
|
|
#ifndef DISABLE_MOUSE
|
|
|
|
/* Turn mouse support off. */
|
|
|
|
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
|
|
|
|
2003-09-29 07:21:11 +00:00
|
|
|
/* Trap SIGHUP and SIGTERM so we can properly deal with them while
|
2004-05-18 01:20:36 +00:00
|
|
|
* suspended. */
|
2003-09-29 07:21:11 +00:00
|
|
|
act.sa_handler = handle_hupterm;
|
|
|
|
sigaction(SIGHUP, &act, NULL);
|
|
|
|
sigaction(SIGTERM, &act, NULL);
|
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
/* Do what mutt does: send ourselves a SIGSTOP. */
|
2002-09-06 20:35:28 +00:00
|
|
|
kill(0, SIGSTOP);
|
|
|
|
}
|
2002-06-21 03:20:06 +00:00
|
|
|
|
2015-05-03 13:56:51 +00:00
|
|
|
/* The version of above function that is bound to a key. */
|
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
|
|
|
{
|
2006-06-09 18:24:37 +00:00
|
|
|
#ifndef DISABLE_MOUSE
|
|
|
|
/* Turn mouse support back on if it was on before. */
|
|
|
|
if (ISSET(USE_MOUSE))
|
|
|
|
enable_mouse_support();
|
|
|
|
#endif
|
|
|
|
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2016-06-29 13:55:38 +00:00
|
|
|
/* Perhaps the user resized the window while we slept. So act as if,
|
|
|
|
* and restore the terminal to its previous state in the process. */
|
|
|
|
regenerate_screen();
|
2004-04-07 00:44:35 +00:00
|
|
|
#else
|
2006-06-09 16:04:19 +00:00
|
|
|
/* Restore the terminal to its previous state. */
|
|
|
|
terminal_init();
|
|
|
|
|
2006-06-09 16:57:41 +00:00
|
|
|
/* Redraw the contents of the windows that need it. */
|
|
|
|
blank_statusbar();
|
2006-07-05 06:38:47 +00:00
|
|
|
wnoutrefresh(bottomwin);
|
2006-06-09 16:04:19 +00:00
|
|
|
total_refresh();
|
2002-09-06 20:35:28 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
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. */
|
|
|
|
sigwinch_counter++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
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
|
2002-09-06 20:35:28 +00:00
|
|
|
|
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
|
2004-05-18 01:20:36 +00:00
|
|
|
/* Do the equivalent of what Minimum Profit does: Leave and
|
|
|
|
* immediately reenter curses mode. */
|
|
|
|
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
|
|
|
|
2004-07-27 16:46:35 +00:00
|
|
|
/* Restore the terminal to its previous state. */
|
|
|
|
terminal_init();
|
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
/* Do the equivalent of what both mutt and Minimum Profit do:
|
|
|
|
* Reinitialize all the windows based on the new screen
|
|
|
|
* dimensions. */
|
|
|
|
window_init();
|
|
|
|
|
2004-11-12 00:09:20 +00:00
|
|
|
/* Redraw the contents of the windows that need it. */
|
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
|
|
|
}
|
2005-11-15 03:17:35 +00:00
|
|
|
#endif /* !NANO_TINY */
|
2002-06-21 03:20:06 +00:00
|
|
|
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
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) {
|
2003-10-03 20:26:25 +00:00
|
|
|
#ifndef DISABLE_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();
|
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;
|
2008-03-05 07:34:01 +00:00
|
|
|
case WHITESPACE_DISPLAY:
|
2004-12-05 04:18:26 +00:00
|
|
|
titlebar(NULL);
|
2004-11-27 16:54:00 +00:00
|
|
|
edit_refresh();
|
|
|
|
break;
|
2014-04-04 11:59:03 +00:00
|
|
|
#ifndef DISABLE_COLOR
|
2008-03-05 07:34:01 +00:00
|
|
|
case NO_COLOR_SYNTAX:
|
2002-12-22 16:30:00 +00:00
|
|
|
#endif
|
2009-08-17 07:52:10 +00:00
|
|
|
case SOFTWRAP:
|
2014-06-22 19:23:54 +00:00
|
|
|
edit_refresh();
|
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
|
|
|
|
2014-02-22 10:56:52 +00:00
|
|
|
if (flag == NO_HELP
|
2005-06-26 20:05:01 +00:00
|
|
|
#ifndef DISABLE_WRAPPING
|
2008-03-05 07:34:01 +00:00
|
|
|
|| flag == NO_WRAP
|
2005-06-26 20:05:01 +00:00
|
|
|
#endif
|
2014-04-04 11:59:03 +00:00
|
|
|
#ifndef DISABLE_COLOR
|
2008-03-05 07:34:01 +00:00
|
|
|
|| flag == NO_COLOR_SYNTAX
|
2005-06-26 20:05:01 +00:00
|
|
|
#endif
|
|
|
|
)
|
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)),
|
|
|
|
enabled ? _("enabled") : _("disabled"));
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
2015-03-08 12:10:52 +00:00
|
|
|
#endif /* !NANO_TINY */
|
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
|
|
|
}
|
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
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2007-12-18 15:55:48 +00:00
|
|
|
/* Disable interpretation of the special control keys in our terminal
|
|
|
|
* settings. */
|
|
|
|
void disable_signals(void)
|
|
|
|
{
|
|
|
|
struct termios term;
|
|
|
|
|
|
|
|
tcgetattr(0, &term);
|
|
|
|
term.c_lflag &= ~ISIG;
|
|
|
|
tcsetattr(0, TCSANOW, &term);
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
struct termios term;
|
|
|
|
|
|
|
|
tcgetattr(0, &term);
|
|
|
|
term.c_lflag |= ISIG;
|
|
|
|
tcsetattr(0, TCSANOW, &term);
|
|
|
|
}
|
|
|
|
#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)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
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-04-27 12:37:31 +00:00
|
|
|
/* Say that an unbound key was struck, and if possible which one. */
|
|
|
|
void unbound_key(int code)
|
|
|
|
{
|
|
|
|
if (func_key)
|
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);
|
2016-04-27 12:37:31 +00:00
|
|
|
else
|
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. */
|
2014-06-13 12:28:33 +00:00
|
|
|
bool preserve = FALSE;
|
2016-06-24 20:45:41 +00:00
|
|
|
/* Whether to preserve the 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;
|
|
|
|
|
2016-06-24 20:45:41 +00:00
|
|
|
/* Read in a keystroke. */
|
2014-06-30 18:04:33 +00:00
|
|
|
input = get_kbinput(edit);
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2015-05-28 13:02:29 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
if (input == KEY_WINCH)
|
|
|
|
return KEY_WINCH;
|
|
|
|
#endif
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
#ifndef DISABLE_MOUSE
|
2014-06-30 18:04:33 +00:00
|
|
|
if (func_key && 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. */
|
2014-06-30 18:04:33 +00:00
|
|
|
input = get_kbinput(edit);
|
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) {
|
2014-06-30 18:04:33 +00:00
|
|
|
if (is_ascii_cntrl_char(input) || meta_key || func_key) {
|
2016-04-27 12:37:31 +00:00
|
|
|
unbound_key(input);
|
2014-06-30 18:04:33 +00:00
|
|
|
meta_key = FALSE;
|
|
|
|
func_key = FALSE;
|
2006-05-24 19:48:03 +00:00
|
|
|
input = ERR;
|
2006-05-24 17:36:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
if (allow_funcs) {
|
2016-06-24 20:45:41 +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. */
|
2008-03-05 07:34:01 +00:00
|
|
|
if (input != ERR && !have_shortcut) {
|
2004-12-04 17:41:52 +00:00
|
|
|
if (ISSET(VIEW_MODE))
|
|
|
|
print_view_warning();
|
|
|
|
else {
|
2016-06-26 12:08:05 +00:00
|
|
|
/* 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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we got a shortcut or toggle, or if there aren't any other
|
2016-06-24 20:45:41 +00:00
|
|
|
* 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. */
|
2014-06-10 19:12:14 +00:00
|
|
|
if (have_shortcut || get_key_buffer_len() == 0) {
|
2006-05-22 15:45:24 +00:00
|
|
|
#ifndef DISABLE_WRAPPING
|
2006-05-24 18:36:38 +00:00
|
|
|
/* If we got a shortcut or toggle, and it's not the shortcut
|
2014-03-24 21:48:23 +00:00
|
|
|
* for verbatim input, turn off prepending of wrapped text. */
|
2014-06-09 10:28:23 +00:00
|
|
|
if (have_shortcut && s->scfunc != do_verbatim_input)
|
2006-05-22 02:08:49 +00:00
|
|
|
wrap_reset();
|
2006-05-22 15:45:24 +00:00
|
|
|
#endif
|
2006-05-22 02:08:49 +00:00
|
|
|
|
2016-06-24 20:45:41 +00:00
|
|
|
if (puddle != NULL) {
|
2016-06-26 12:08:05 +00:00
|
|
|
/* 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);
|
2004-12-04 17:41:52 +00:00
|
|
|
|
|
|
|
/* Empty the input buffer. */
|
2016-06-24 20:45:41 +00:00
|
|
|
free(puddle);
|
|
|
|
puddle = NULL;
|
|
|
|
depth = 0;
|
2004-12-04 17:41:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (have_shortcut) {
|
2016-01-04 09:52:43 +00:00
|
|
|
const subnfunc *f = sctofunc(s);
|
2014-06-11 18:34:35 +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
|
|
|
)
|
2014-06-13 12:28:33 +00:00
|
|
|
preserve = TRUE;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2016-01-03 17:07:29 +00:00
|
|
|
if (s->scfunc == NULL) {
|
|
|
|
statusbar("Internal error: shortcut without function!");
|
|
|
|
return ERR;
|
|
|
|
}
|
2016-01-03 17:37:05 +00:00
|
|
|
if (ISSET(VIEW_MODE) && f && !f->viewok)
|
|
|
|
print_view_warning();
|
|
|
|
else {
|
2008-03-05 07:34:01 +00:00
|
|
|
#ifndef NANO_TINY
|
2016-01-03 17:37:05 +00:00
|
|
|
if (s->scfunc == do_toggle_void) {
|
|
|
|
do_toggle(s->toggle);
|
|
|
|
if (s->toggle != CUT_TO_END)
|
|
|
|
preserve = TRUE;
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
/* Execute the function of the shortcut. */
|
|
|
|
s->scfunc();
|
2014-04-04 11:59:03 +00:00
|
|
|
#ifndef DISABLE_COLOR
|
2016-01-03 17:37:05 +00:00
|
|
|
if (f && !f->viewok)
|
|
|
|
reset_multis(openfile->current, FALSE);
|
2009-11-22 21:35:56 +00:00
|
|
|
#endif
|
2016-04-25 19:14:18 +00:00
|
|
|
if (refresh_needed) {
|
2009-02-16 23:06:09 +00:00
|
|
|
#ifdef DEBUG
|
2016-04-25 19:14:18 +00:00
|
|
|
fprintf(stderr, "running edit_refresh() as refresh_needed is true\n");
|
2009-02-16 23:06:09 +00:00
|
|
|
#endif
|
2016-01-03 17:37:05 +00:00
|
|
|
edit_refresh();
|
2016-04-25 19:14:18 +00:00
|
|
|
refresh_needed = FALSE;
|
2016-01-03 17:37:05 +00:00
|
|
|
} else if (s->scfunc == do_delete || s->scfunc == do_backspace)
|
|
|
|
update_line(openfile->current, openfile->current_x);
|
2014-06-11 18:34:35 +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. */
|
|
|
|
if (!preserve)
|
2006-05-21 20:03:43 +00:00
|
|
|
cutbuffer_reset();
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
2008-03-05 07:34:01 +00:00
|
|
|
void xon_complaint(void)
|
|
|
|
{
|
|
|
|
statusbar(_("XON ignored, mumble mumble"));
|
|
|
|
}
|
|
|
|
|
|
|
|
void xoff_complaint(void)
|
|
|
|
{
|
|
|
|
statusbar(_("XOFF ignored, mumble mumble"));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
#ifndef DISABLE_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
|
|
|
{
|
|
|
|
int mouse_x, mouse_y;
|
2007-05-20 23:41:56 +00:00
|
|
|
int retval = get_mouseinput(&mouse_x, &mouse_y, TRUE);
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2014-06-13 12:19:44 +00:00
|
|
|
if (retval != 0)
|
|
|
|
/* The click is wrong or already handled. */
|
|
|
|
return retval;
|
|
|
|
|
2007-06-28 16:00:50 +00:00
|
|
|
/* We can click on the edit window to move the cursor. */
|
2014-06-13 12:19:44 +00:00
|
|
|
if (wmouse_trafo(edit, &mouse_y, &mouse_x, FALSE)) {
|
2007-06-28 16:00:50 +00:00
|
|
|
bool sameline;
|
|
|
|
/* Did they click on the line with the cursor? If they
|
|
|
|
* clicked on the cursor, we set the mark. */
|
2009-01-25 07:25:17 +00:00
|
|
|
filestruct *current_save = openfile->current;
|
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;
|
2014-04-04 16:06:27 +00:00
|
|
|
#endif
|
2007-06-28 16:00:50 +00:00
|
|
|
|
|
|
|
sameline = (mouse_y == openfile->current_y);
|
|
|
|
|
2009-11-13 20:38:32 +00:00
|
|
|
#ifdef DEBUG
|
2014-06-09 15:08:59 +00:00
|
|
|
fprintf(stderr, "mouse_y = %d, current_y = %ld\n", mouse_y, (long)openfile->current_y);
|
2009-11-13 20:38:32 +00:00
|
|
|
#endif
|
|
|
|
|
2014-06-09 20:26:54 +00:00
|
|
|
#ifndef NANO_TINY
|
2014-03-17 21:36:37 +00:00
|
|
|
if (ISSET(SOFTWRAP)) {
|
2014-06-09 20:41:15 +00:00
|
|
|
size_t i = 0;
|
2009-11-13 20:38:32 +00:00
|
|
|
for (openfile->current = openfile->edittop;
|
2016-05-30 07:09:36 +00:00
|
|
|
openfile->current->next && i < mouse_y;
|
|
|
|
openfile->current = openfile->current->next, i++) {
|
2009-11-13 20:38:32 +00:00
|
|
|
openfile->current_y = i;
|
|
|
|
i += strlenpt(openfile->current->data) / COLS;
|
|
|
|
}
|
|
|
|
#ifdef DEBUG
|
2014-06-09 20:41:15 +00:00
|
|
|
fprintf(stderr, "do_mouse(): moving to current_y = %ld, index i = %lu\n",
|
|
|
|
(long)openfile->current_y, (unsigned long)i);
|
2009-11-13 20:38:32 +00:00
|
|
|
fprintf(stderr, " openfile->current->data = \"%s\"\n", openfile->current->data);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (i > mouse_y) {
|
|
|
|
openfile->current = openfile->current->prev;
|
|
|
|
openfile->current_x = actual_x(openfile->current->data, mouse_x + (mouse_y - openfile->current_y) * COLS);
|
|
|
|
#ifdef DEBUG
|
2014-06-09 15:08:59 +00:00
|
|
|
fprintf(stderr, "do_mouse(): i > mouse_y, mouse_x = %d, current_x to = %lu\n",
|
|
|
|
mouse_x, (unsigned long)openfile->current_x);
|
2009-11-13 20:38:32 +00:00
|
|
|
#endif
|
|
|
|
} else {
|
2015-03-27 13:46:50 +00:00
|
|
|
openfile->current_x = actual_x(openfile->current->data, mouse_x);
|
2009-11-13 20:38:32 +00:00
|
|
|
#ifdef DEBUG
|
2014-06-09 15:08:59 +00:00
|
|
|
fprintf(stderr, "do_mouse(): i <= mouse_y, mouse_x = %d, setting current_x to = %lu\n",
|
|
|
|
mouse_x, (unsigned long)openfile->current_x);
|
2009-11-13 20:38:32 +00:00
|
|
|
#endif
|
|
|
|
}
|
2014-06-20 18:06:22 +00:00
|
|
|
} else
|
|
|
|
#endif /* NANO_TINY */
|
|
|
|
{
|
2009-11-13 20:38:32 +00:00
|
|
|
/* Move to where the click occurred. */
|
|
|
|
for (; openfile->current_y < mouse_y && openfile->current !=
|
2016-05-30 07:09:36 +00:00
|
|
|
openfile->filebot; openfile->current_y++)
|
2009-11-13 20:38:32 +00:00
|
|
|
openfile->current = openfile->current->next;
|
|
|
|
for (; openfile->current_y > mouse_y && openfile->current !=
|
2016-05-30 07:09:36 +00:00
|
|
|
openfile->fileage; openfile->current_y--)
|
2009-11-13 20:38:32 +00:00
|
|
|
openfile->current = openfile->current->prev;
|
|
|
|
|
|
|
|
openfile->current_x = actual_x(openfile->current->data,
|
2005-07-25 20:36:27 +00:00
|
|
|
get_page_start(xplustabs()) + mouse_x);
|
2009-11-13 20:38:32 +00:00
|
|
|
}
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2007-06-28 16:00:50 +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. */
|
|
|
|
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
|
|
|
|
2016-04-10 19:16:19 +00:00
|
|
|
edit_redraw(current_save);
|
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
|
|
|
}
|
|
|
|
#endif /* !DISABLE_MOUSE */
|
|
|
|
|
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
|
|
|
{
|
2014-06-09 20:26:54 +00:00
|
|
|
size_t current_len, i = 0;
|
|
|
|
#ifndef NANO_TINY
|
|
|
|
size_t orig_lenpt = 0;
|
|
|
|
#endif
|
|
|
|
|
2005-01-12 03:25:57 +00:00
|
|
|
char *char_buf = charalloc(mb_cur_max());
|
|
|
|
int char_buf_len;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2005-07-08 20:09:16 +00:00
|
|
|
assert(openfile->current != NULL && openfile->current->data != NULL);
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2005-07-08 20:09:16 +00:00
|
|
|
current_len = strlen(openfile->current->data);
|
2014-06-09 20:26:54 +00:00
|
|
|
|
|
|
|
#ifndef NANO_TINY
|
2009-12-12 22:21:20 +00:00
|
|
|
if (ISSET(SOFTWRAP))
|
|
|
|
orig_lenpt = strlenpt(openfile->current->data);
|
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-07-03 14:19:27 +00:00
|
|
|
/* If control codes are allowed, encode a verbatim null as a newline,
|
|
|
|
* and let a verbatim ^J create a whole new line. */
|
2006-11-27 04:56:16 +00:00
|
|
|
if (allow_cntrls) {
|
|
|
|
if (output[i] == '\0')
|
2005-03-17 03:52:08 +00:00
|
|
|
output[i] = '\n';
|
2006-11-27 04:56:16 +00:00
|
|
|
else if (output[i] == '\n') {
|
2015-11-11 19:04:31 +00:00
|
|
|
do_enter();
|
2005-03-17 03:52:08 +00:00
|
|
|
i++;
|
|
|
|
continue;
|
|
|
|
}
|
2004-12-08 23:24:31 +00:00
|
|
|
}
|
|
|
|
|
2016-06-14 09:06:04 +00:00
|
|
|
/* Get the next multibyte character. */
|
2005-07-26 06:13:45 +00:00
|
|
|
char_buf_len = parse_mbchar(output + i, char_buf, NULL);
|
2005-01-12 03:25:57 +00:00
|
|
|
|
|
|
|
i += char_buf_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. */
|
2015-12-04 21:11:10 +00:00
|
|
|
if (!allow_cntrls && is_ascii_cntrl_char(*(output + i - char_buf_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. */
|
2015-12-04 21:11:10 +00:00
|
|
|
if (!ISSET(NO_NEWLINES) && openfile->filebot == openfile->current)
|
2004-12-04 17:41:52 +00:00
|
|
|
new_magicline();
|
|
|
|
|
2005-07-08 20:09:16 +00:00
|
|
|
assert(openfile->current_x <= current_len);
|
2004-12-31 04:10:28 +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,
|
|
|
|
current_len + char_buf_len + 1);
|
2015-12-04 21:11:10 +00:00
|
|
|
charmove(openfile->current->data + openfile->current_x + char_buf_len,
|
|
|
|
openfile->current->data + openfile->current_x,
|
2016-06-14 12:39:56 +00:00
|
|
|
current_len - openfile->current_x + 1);
|
2005-11-05 04:59:00 +00:00
|
|
|
strncpy(openfile->current->data + openfile->current_x, char_buf,
|
2016-06-14 09:06:04 +00:00
|
|
|
char_buf_len);
|
2005-01-12 03:25:57 +00:00
|
|
|
current_len += char_buf_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. */
|
2015-12-04 21:11:10 +00:00
|
|
|
if (openfile->mark_set && openfile->current == openfile->mark_begin &&
|
|
|
|
openfile->current_x < openfile->mark_begin_x)
|
2005-07-12 17:40:16 +00:00
|
|
|
openfile->mark_begin_x += char_buf_len;
|
2004-12-04 17:41:52 +00:00
|
|
|
#endif
|
|
|
|
|
2005-07-16 23:36:10 +00:00
|
|
|
openfile->current_x += char_buf_len;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2014-05-15 20:00:46 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
update_undo(ADD);
|
|
|
|
#endif
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
#ifndef DISABLE_WRAPPING
|
2005-04-26 17:21:47 +00:00
|
|
|
/* If we're wrapping text, we need to call edit_refresh(). */
|
2009-12-12 22:21:20 +00:00
|
|
|
if (!ISSET(NO_WRAP))
|
2014-06-09 10:01:54 +00:00
|
|
|
if (do_wrap(openfile->current))
|
2016-04-25 19:14:18 +00:00
|
|
|
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
|
|
|
|
/* Well, we might also need a full refresh if we've changed the
|
2014-03-24 21:48:23 +00:00
|
|
|
* line length to be a new multiple of COLS. */
|
2016-04-25 19:14:18 +00:00
|
|
|
if (ISSET(SOFTWRAP) && refresh_needed == FALSE)
|
2014-06-21 19:01:51 +00:00
|
|
|
if (strlenpt(openfile->current->data) / COLS != orig_lenpt / COLS)
|
2016-04-25 19:14:18 +00:00
|
|
|
refresh_needed = TRUE;
|
2014-06-09 20:26:54 +00:00
|
|
|
#endif
|
2009-12-12 22:21:20 +00:00
|
|
|
|
2005-01-12 03:25:57 +00:00
|
|
|
free(char_buf);
|
2004-12-12 19:04:56 +00:00
|
|
|
|
2005-07-16 23:36:10 +00:00
|
|
|
openfile->placewewant = xplustabs();
|
|
|
|
|
2014-04-04 11:59:03 +00:00
|
|
|
#ifndef DISABLE_COLOR
|
2009-02-16 21:04:00 +00:00
|
|
|
reset_multis(openfile->current, FALSE);
|
2009-01-26 07:55:01 +00:00
|
|
|
#endif
|
2016-01-03 16:21:04 +00:00
|
|
|
|
2016-04-25 19:14:18 +00:00
|
|
|
if (refresh_needed == TRUE) {
|
2004-12-04 17:41:52 +00:00
|
|
|
edit_refresh();
|
2016-04-25 19:14:18 +00:00
|
|
|
refresh_needed = FALSE;
|
2009-02-06 03:41:02 +00:00
|
|
|
} else
|
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
|
|
|
{
|
|
|
|
int optchr;
|
2014-06-20 19:10:24 +00:00
|
|
|
ssize_t startline = 0, startcol = 0;
|
|
|
|
/* Target line and column when specified on the command line. */
|
2004-08-12 19:48:21 +00:00
|
|
|
#ifndef DISABLE_WRAPJUSTIFY
|
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? */
|
2016-05-15 13:18:47 +00:00
|
|
|
#ifndef DISABLE_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
|
2016-05-15 13:18:47 +00:00
|
|
|
#endif
|
2014-04-03 20:23:07 +00:00
|
|
|
#ifndef DISABLE_MULTIBUFFER
|
2004-09-05 21:40:31 +00:00
|
|
|
bool old_multibuffer;
|
|
|
|
/* The old value of the multibuffer option, restored after we
|
|
|
|
* load all files on the command line. */
|
|
|
|
#endif
|
2000-06-06 05:53:49 +00:00
|
|
|
#ifdef HAVE_GETOPT_LONG
|
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'},
|
2014-04-03 20:23:07 +00:00
|
|
|
#ifndef DISABLE_MULTIBUFFER
|
2005-03-26 22:49:08 +00:00
|
|
|
{"multibuffer", 0, NULL, 'F'},
|
2002-07-19 01:08:59 +00:00
|
|
|
#endif
|
2014-04-13 20:50:20 +00:00
|
|
|
#ifndef DISABLE_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'},
|
2002-06-28 22:45:14 +00:00
|
|
|
#ifndef DISABLE_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'},
|
|
|
|
{"version", 0, NULL, 'V'},
|
2014-04-04 11:59:03 +00:00
|
|
|
#ifndef DISABLE_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'},
|
2015-06-20 18:48:43 +00:00
|
|
|
{"help", 0, NULL, 'h'},
|
2003-10-03 20:26:25 +00:00
|
|
|
#ifndef DISABLE_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'},
|
2001-09-19 03:19:43 +00:00
|
|
|
#ifndef DISABLE_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'},
|
2002-06-28 22:45:14 +00:00
|
|
|
#ifndef DISABLE_WRAPJUSTIFY
|
2005-03-26 22:49:08 +00:00
|
|
|
{"fill", 1, NULL, 'r'},
|
2002-06-28 22:45:14 +00:00
|
|
|
#endif
|
|
|
|
#ifndef DISABLE_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'},
|
2002-10-17 02:19:31 +00:00
|
|
|
#ifndef DISABLE_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-06-17 19:06:25 +00:00
|
|
|
{"quickblank", 0, NULL, 'U'},
|
2005-08-10 22:12:28 +00:00
|
|
|
{"wordbounds", 0, NULL, 'W'},
|
2016-06-30 16:02:45 +00:00
|
|
|
{"wordchars", 1, NULL, 'X'},
|
2005-03-26 22:49:08 +00:00
|
|
|
{"autoindent", 0, NULL, 'i'},
|
|
|
|
{"cut", 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
|
|
|
#endif
|
|
|
|
|
2016-06-12 09:13:45 +00:00
|
|
|
/* Back up the terminal settings so that they can be restored. */
|
|
|
|
tcgetattr(0, &oldterm);
|
|
|
|
|
2005-07-17 02:40:07 +00:00
|
|
|
#ifdef ENABLE_UTF8
|
2004-12-23 17:43:27 +00:00
|
|
|
{
|
2007-05-25 14:39:40 +00:00
|
|
|
/* If the locale set exists and uses UTF-8, we should use
|
|
|
|
* UTF-8. */
|
2004-12-23 17:43:27 +00:00
|
|
|
char *locale = setlocale(LC_ALL, "");
|
|
|
|
|
2007-05-25 14:39:40 +00:00
|
|
|
if (locale != NULL && (strcmp(nl_langinfo(CODESET),
|
|
|
|
"UTF-8") == 0)) {
|
2005-01-28 19:37:23 +00:00
|
|
|
#ifdef USE_SLANG
|
2006-07-19 19:40:54 +00:00
|
|
|
SLutf8_enable(1);
|
2005-01-28 19:37:23 +00:00
|
|
|
#endif
|
2006-04-12 15:27:40 +00:00
|
|
|
utf8_init();
|
2005-06-16 02:09:57 +00:00
|
|
|
}
|
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
|
|
|
|
|
2014-04-13 20:50:20 +00:00
|
|
|
#if defined(DISABLE_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
|
|
|
|
2004-08-07 22:00:02 +00:00
|
|
|
while ((optchr =
|
2000-06-06 05:53:49 +00:00
|
|
|
#ifdef HAVE_GETOPT_LONG
|
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$",
|
2005-06-12 16:13:44 +00:00
|
|
|
long_options, NULL)
|
2000-06-06 05:53:49 +00:00
|
|
|
#else
|
2005-06-12 16:13:44 +00:00
|
|
|
getopt(argc, argv,
|
2016-06-30 16:02:45 +00:00
|
|
|
"ABC:DEFGHIKLNOPQ:RST:UVWX:Y:abcdefghijklmno:pqr:s:tuvwxz$")
|
2000-06-06 05:53:49 +00:00
|
|
|
#endif
|
2004-08-07 22:00:02 +00:00
|
|
|
) != -1) {
|
2000-06-06 05:53:49 +00:00
|
|
|
switch (optchr) {
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'a':
|
|
|
|
case 'b':
|
|
|
|
case 'e':
|
|
|
|
case 'f':
|
|
|
|
case 'g':
|
|
|
|
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
|
2014-04-03 20:23:07 +00:00
|
|
|
#ifndef DISABLE_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
|
|
|
|
#ifndef DISABLE_HISTORIES
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'H':
|
|
|
|
SET(HISTORYLOG);
|
|
|
|
break;
|
2003-09-06 21:44:37 +00:00
|
|
|
#endif
|
2014-06-19 20:05:24 +00:00
|
|
|
#ifndef DISABLE_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;
|
2014-06-19 20:05:24 +00:00
|
|
|
#ifndef DISABLE_HISTORIES
|
2011-02-16 06:52:30 +00:00
|
|
|
case 'P':
|
|
|
|
SET(POS_HISTORY);
|
|
|
|
break;
|
|
|
|
#endif
|
2002-03-03 22:36:36 +00:00
|
|
|
#ifndef DISABLE_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-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2005-06-17 19:06:25 +00:00
|
|
|
case 'U':
|
|
|
|
SET(QUICK_BLANK);
|
|
|
|
break;
|
|
|
|
#endif
|
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
|
2014-04-04 11:59:03 +00:00
|
|
|
#ifndef DISABLE_COLOR
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'Y':
|
|
|
|
syntaxstr = mallocstrcpy(syntaxstr, optarg);
|
|
|
|
break;
|
2002-05-04 04:23:30 +00:00
|
|
|
#endif
|
2004-08-07 22:00:02 +00:00
|
|
|
case 'c':
|
2005-06-17 21:08:13 +00:00
|
|
|
SET(CONST_UPDATE);
|
2004-08-07 22:00:02 +00:00
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
SET(REBIND_DELETE);
|
|
|
|
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':
|
|
|
|
SET(CUT_TO_END);
|
|
|
|
break;
|
2000-07-12 18:14:51 +00:00
|
|
|
#endif
|
2003-10-03 20:26:25 +00:00
|
|
|
#ifndef DISABLE_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;
|
2001-09-19 03:19:43 +00:00
|
|
|
#ifndef DISABLE_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;
|
2014-07-02 19:57:23 +00:00
|
|
|
#ifndef DISABLE_NANORC
|
2009-02-09 04:03:20 +00:00
|
|
|
case 'q':
|
|
|
|
SET(QUIET);
|
|
|
|
break;
|
2014-07-02 19:57:23 +00:00
|
|
|
#endif
|
2001-05-21 12:56:25 +00:00
|
|
|
#ifndef DISABLE_WRAPJUSTIFY
|
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);
|
|
|
|
}
|
2005-07-25 22:54:16 +00:00
|
|
|
fill_used = TRUE;
|
2016-05-15 13:18:47 +00:00
|
|
|
#ifndef DISABLE_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
|
2001-01-12 07:51:05 +00:00
|
|
|
#ifndef DISABLE_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;
|
2003-01-02 16:32:20 +00:00
|
|
|
#ifndef DISABLE_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;
|
|
|
|
#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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-26 15:55:39 +00:00
|
|
|
/* If the executable filename starts with 'r', enable restricted
|
2004-05-29 01:20:17 +00:00
|
|
|
* mode. */
|
2004-04-30 04:49:02 +00:00
|
|
|
if (*(tail(argv[0])) == 'r')
|
|
|
|
SET(RESTRICTED);
|
|
|
|
|
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);
|
2014-04-13 20:50:20 +00:00
|
|
|
#ifndef DISABLE_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
|
|
|
|
2003-01-13 01:35:15 +00:00
|
|
|
/* We've read through the command line options. Now back up the flags
|
2004-09-05 21:40:31 +00:00
|
|
|
* and values that are set, and read the rcfile(s). If the values
|
|
|
|
* haven't changed afterward, restore the backed-up values. */
|
2014-04-13 20:50:20 +00:00
|
|
|
#ifndef DISABLE_NANORC
|
2006-04-24 18:54:29 +00:00
|
|
|
if (!no_rcfiles) {
|
2003-01-13 01:35:15 +00:00
|
|
|
#ifndef DISABLE_OPERATINGDIR
|
|
|
|
char *operating_dir_cpy = operating_dir;
|
|
|
|
#endif
|
2004-08-12 20:06:20 +00:00
|
|
|
#ifndef DISABLE_WRAPJUSTIFY
|
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
|
2003-01-13 01:35:15 +00:00
|
|
|
#ifndef DISABLE_JUSTIFY
|
|
|
|
char *quotestr_cpy = quotestr;
|
|
|
|
#endif
|
|
|
|
#ifndef DISABLE_SPELLER
|
|
|
|
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
|
|
|
|
2003-02-05 02:39:34 +00:00
|
|
|
#ifndef DISABLE_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
|
2003-02-05 02:39:34 +00:00
|
|
|
#ifndef DISABLE_JUSTIFY
|
2003-01-13 01:35:15 +00:00
|
|
|
quotestr = NULL;
|
2003-02-05 02:39:34 +00:00
|
|
|
#endif
|
|
|
|
#ifndef DISABLE_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
|
|
|
|
|
|
|
do_rcfile();
|
|
|
|
|
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
|
|
|
|
|
2003-01-13 01:35:15 +00:00
|
|
|
#ifndef DISABLE_OPERATINGDIR
|
|
|
|
if (operating_dir_cpy != NULL) {
|
|
|
|
free(operating_dir);
|
|
|
|
operating_dir = operating_dir_cpy;
|
|
|
|
}
|
|
|
|
#endif
|
2004-08-12 19:48:21 +00:00
|
|
|
#ifndef DISABLE_WRAPJUSTIFY
|
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
|
2003-01-13 01:35:15 +00:00
|
|
|
#ifndef DISABLE_JUSTIFY
|
|
|
|
if (quotestr_cpy != NULL) {
|
|
|
|
free(quotestr);
|
|
|
|
quotestr = quotestr_cpy;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifndef DISABLE_SPELLER
|
|
|
|
if (alt_speller_cpy != NULL) {
|
|
|
|
free(alt_speller);
|
|
|
|
alt_speller = alt_speller_cpy;
|
|
|
|
}
|
|
|
|
#endif
|
2004-07-18 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
|
|
|
|
|
|
|
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
|
2014-04-13 20:50:20 +00:00
|
|
|
#endif /* !DISABLE_NANORC */
|
2003-01-13 01:35:15 +00:00
|
|
|
|
2009-11-22 21:35:56 +00:00
|
|
|
#ifndef DISABLE_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
|
|
|
|
2006-04-12 15:27:40 +00:00
|
|
|
/* If we're using bold text instead of reverse video text, set it up
|
|
|
|
* now. */
|
|
|
|
if (ISSET(BOLD_TEXT))
|
2014-05-04 08:53:06 +00:00
|
|
|
hilite_attribute = A_BOLD;
|
2006-04-12 15:27:40 +00:00
|
|
|
|
2014-06-19 20:05:24 +00:00
|
|
|
#ifndef DISABLE_HISTORIES
|
2006-04-12 15:27:40 +00:00
|
|
|
/* Set up the search/replace history. */
|
2003-03-11 03:50:40 +00:00
|
|
|
history_init();
|
2014-06-19 20:05:24 +00:00
|
|
|
/* Verify that the home directory and ~/.nano subdir exist. */
|
2014-06-19 15:09:23 +00:00
|
|
|
if (ISSET(HISTORYLOG) || ISSET(POS_HISTORY)) {
|
|
|
|
get_homedir();
|
|
|
|
if (homedir == NULL || check_dotnano() == 0) {
|
|
|
|
UNSET(HISTORYLOG);
|
|
|
|
UNSET(POS_HISTORY);
|
2011-02-16 06:52:30 +00:00
|
|
|
}
|
|
|
|
}
|
2014-06-19 15:09:23 +00:00
|
|
|
if (ISSET(HISTORYLOG))
|
|
|
|
load_history();
|
|
|
|
if (ISSET(POS_HISTORY))
|
|
|
|
load_poshistory();
|
2014-06-19 20:05:24 +00:00
|
|
|
#endif /* !DISABLE_HISTORIES */
|
2003-03-11 03:50:40 +00:00
|
|
|
|
2014-06-19 20:05:24 +00:00
|
|
|
#ifndef NANO_TINY
|
2004-05-28 23:45:25 +00:00
|
|
|
/* Set up the backup directory (unless we're using restricted mode,
|
2004-05-29 01:20:17 +00:00
|
|
|
* in which case backups are disabled, since they would allow
|
|
|
|
* reading from or writing to files not specified on the command
|
|
|
|
* line). This entails making sure it exists and is a directory, so
|
|
|
|
* that backup files will be saved there. */
|
2004-05-28 23:45:25 +00:00
|
|
|
if (!ISSET(RESTRICTED))
|
|
|
|
init_backup_dir();
|
2014-06-19 20:05:24 +00:00
|
|
|
#endif
|
2004-02-28 16:24:31 +00:00
|
|
|
|
2016-06-12 09:13:45 +00:00
|
|
|
#ifndef DISABLE_OPERATINGDIR
|
|
|
|
/* Set up the operating directory. This entails chdir()ing there,
|
|
|
|
* so that file reads and writes will be based there. */
|
|
|
|
init_operating_dir();
|
|
|
|
#endif
|
|
|
|
|
2003-01-13 01:35:15 +00:00
|
|
|
#ifndef DISABLE_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)
|
2004-06-12 21:03:14 +00:00
|
|
|
quotestr = mallocstrcpy(NULL,
|
2003-01-13 01:35:15 +00:00
|
|
|
#ifdef HAVE_REGEX_H
|
2006-01-03 04:53:41 +00:00
|
|
|
"^([ \t]*[#:>|}])+"
|
2003-01-13 01:35:15 +00:00
|
|
|
#else
|
2004-06-12 21:03:14 +00:00
|
|
|
"> "
|
2003-01-13 01:35:15 +00:00
|
|
|
#endif
|
2004-06-12 21:03:14 +00:00
|
|
|
);
|
2004-07-30 03:54:34 +00:00
|
|
|
#ifdef HAVE_REGEX_H
|
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);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
quotelen = strlen(quotestr);
|
|
|
|
#endif /* !HAVE_REGEX_H */
|
2003-01-13 01:35:15 +00:00
|
|
|
#endif /* !DISABLE_JUSTIFY */
|
2004-02-28 16:24:31 +00:00
|
|
|
|
2004-05-28 22:42:41 +00:00
|
|
|
#ifndef DISABLE_SPELLER
|
|
|
|
/* 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) {
|
2004-05-28 22:42:41 +00:00
|
|
|
char *spellenv = getenv("SPELL");
|
|
|
|
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, "(<[{)>]}");
|
|
|
|
|
2014-04-08 12:24:52 +00:00
|
|
|
/* If whitespace wasn't specified, set its default value. If we're
|
|
|
|
* using UTF-8, it's Unicode 00BB (Right-Pointing Double Angle
|
|
|
|
* Quotation Mark) and Unicode 00B7 (Middle Dot). Otherwise, it's
|
|
|
|
* ">" and ".". */
|
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()) {
|
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, "");
|
|
|
|
|
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
|
|
|
|
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
|
|
|
|
2005-07-25 22:54:16 +00:00
|
|
|
/* Initialize all the windows based on the current screen
|
|
|
|
* dimensions. */
|
|
|
|
window_init();
|
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
|
|
|
|
2003-10-03 20:26:25 +00:00
|
|
|
#ifndef DISABLE_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
|
|
|
|
2014-05-03 18:24:45 +00:00
|
|
|
#ifndef DISABLE_COLOR
|
|
|
|
set_colorpairs();
|
|
|
|
#else
|
2016-07-12 07:35:48 +00:00
|
|
|
interface_color_pair[TITLE_BAR] = hilite_attribute;
|
|
|
|
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
|
|
|
|
|
2015-12-06 05:21:43 +00:00
|
|
|
#if !defined(NANO_TINY) && defined(HAVE_KEY_DEFINED)
|
2015-12-23 14:05:47 +00:00
|
|
|
const char *keyvalue;
|
2016-06-25 13:16:52 +00:00
|
|
|
/* Ask ncurses for the key codes for Control+Left/Right/Up/Down. */
|
2015-12-23 14:05:47 +00:00
|
|
|
keyvalue = tigetstr("kLFT5");
|
|
|
|
if (keyvalue != 0 && keyvalue != (char *)-1)
|
|
|
|
controlleft = key_defined(keyvalue);
|
|
|
|
keyvalue = tigetstr("kRIT5");
|
|
|
|
if (keyvalue != 0 && keyvalue != (char *)-1)
|
|
|
|
controlright = key_defined(keyvalue);
|
2016-06-25 13:16:52 +00:00
|
|
|
keyvalue = tigetstr("kUP5");
|
|
|
|
if (keyvalue != 0 && keyvalue != (char *)-1)
|
|
|
|
controlup = key_defined(keyvalue);
|
|
|
|
keyvalue = tigetstr("kDN5");
|
|
|
|
if (keyvalue != 0 && keyvalue != (char *)-1)
|
|
|
|
controldown = key_defined(keyvalue);
|
2015-11-23 08:52:23 +00:00
|
|
|
#endif
|
|
|
|
|
2016-07-11 12:21:38 +00:00
|
|
|
#ifndef USE_SLANG
|
|
|
|
/* 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
|
|
|
|
2005-05-16 18:38:16 +00:00
|
|
|
/* If there's a +LINE or +LINE,COLUMN flag here, it is the first
|
|
|
|
* non-option argument, and it is followed by at least one other
|
|
|
|
* argument, the filename it applies to. */
|
2004-10-22 20:25:56 +00:00
|
|
|
if (0 < optind && optind < argc - 1 && argv[optind][0] == '+') {
|
2005-05-16 23:23:15 +00:00
|
|
|
parse_line_column(&argv[optind][1], &startline, &startcol);
|
2004-10-22 20:25:56 +00:00
|
|
|
optind++;
|
|
|
|
}
|
|
|
|
|
2009-01-30 08:34:27 +00:00
|
|
|
if (optind < argc && !strcmp(argv[optind], "-")) {
|
2009-01-30 17:37:44 +00:00
|
|
|
stdin_pager();
|
2009-01-30 08:34:27 +00:00
|
|
|
set_modified();
|
|
|
|
optind++;
|
|
|
|
}
|
|
|
|
|
2014-04-03 20:23:07 +00:00
|
|
|
#ifndef DISABLE_MULTIBUFFER
|
2004-09-05 21:40:31 +00:00
|
|
|
old_multibuffer = ISSET(MULTIBUFFER);
|
|
|
|
SET(MULTIBUFFER);
|
|
|
|
|
|
|
|
/* Read all the files after the first one on the command line into
|
|
|
|
* new buffers. */
|
|
|
|
{
|
2005-06-28 06:25:34 +00:00
|
|
|
int i = optind + 1;
|
2014-06-20 19:10:24 +00:00
|
|
|
ssize_t iline = 0, icol = 0;
|
2005-05-16 18:38:16 +00:00
|
|
|
|
2004-10-22 20:25:56 +00:00
|
|
|
for (; i < argc; i++) {
|
2015-07-19 09:25:25 +00:00
|
|
|
/* If there's a +LINE or +LINE,COLUMN flag here, it is followed
|
|
|
|
* by at least one other argument: the filename it applies to. */
|
2015-07-19 09:01:59 +00:00
|
|
|
if (i < argc - 1 && argv[i][0] == '+')
|
2005-05-16 23:23:15 +00:00
|
|
|
parse_line_column(&argv[i][1], &iline, &icol);
|
2005-05-17 18:06:26 +00:00
|
|
|
else {
|
2015-12-30 10:11:20 +00:00
|
|
|
/* If opening fails, don't try to position the cursor. */
|
|
|
|
if (!open_buffer(argv[i], FALSE))
|
|
|
|
continue;
|
2005-05-16 18:38:16 +00:00
|
|
|
|
2015-07-19 09:25:25 +00:00
|
|
|
/* If a position was given on the command line, go there. */
|
2014-06-20 19:10:24 +00:00
|
|
|
if (iline > 0 || icol > 0) {
|
2015-12-31 19:20:40 +00:00
|
|
|
do_gotolinecolumn(iline, icol, FALSE, FALSE);
|
2015-07-19 09:01:59 +00:00
|
|
|
iline = 0;
|
|
|
|
icol = 0;
|
2004-10-22 20:25:56 +00:00
|
|
|
}
|
2014-06-19 20:05:24 +00:00
|
|
|
#ifndef DISABLE_HISTORIES
|
2016-01-29 16:20:28 +00:00
|
|
|
else if (ISSET(POS_HISTORY)) {
|
2011-02-16 06:52:30 +00:00
|
|
|
ssize_t savedposline, savedposcol;
|
2015-07-19 09:25:25 +00:00
|
|
|
/* If edited before, restore the last cursor position. */
|
2011-02-16 06:52:30 +00:00
|
|
|
if (check_poshistory(argv[i], &savedposline, &savedposcol))
|
2015-12-31 17:20:46 +00:00
|
|
|
do_gotolinecolumn(savedposline, savedposcol,
|
2015-12-31 19:20:40 +00:00
|
|
|
FALSE, FALSE);
|
2011-02-16 06:52:30 +00:00
|
|
|
}
|
2014-02-22 16:26:30 +00:00
|
|
|
#endif
|
2004-10-22 20:25:56 +00:00
|
|
|
}
|
|
|
|
}
|
2004-09-05 21:40:31 +00:00
|
|
|
}
|
2014-04-05 20:28:29 +00:00
|
|
|
#endif /* !DISABLE_MULTIBUFFER */
|
2004-09-05 21:40:31 +00:00
|
|
|
|
2015-07-19 09:25:25 +00:00
|
|
|
/* Now read the first file on the command line into a new buffer. */
|
2004-09-05 21:40:31 +00:00
|
|
|
if (optind < argc)
|
2008-08-03 04:48:05 +00:00
|
|
|
open_buffer(argv[optind], FALSE);
|
2004-09-05 21:40:31 +00:00
|
|
|
|
2015-07-19 09:25:25 +00:00
|
|
|
/* If all the command-line arguments were invalid files like directories,
|
|
|
|
* or if there were no filenames given, we didn't open any file. In this
|
|
|
|
* case, load a blank buffer. Also, unset view mode to allow editing. */
|
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);
|
2003-01-13 01:35:15 +00:00
|
|
|
}
|
2004-09-05 21:40:31 +00:00
|
|
|
|
2014-04-03 20:23:07 +00:00
|
|
|
#ifndef DISABLE_MULTIBUFFER
|
2004-09-05 21:40:31 +00:00
|
|
|
if (!old_multibuffer)
|
|
|
|
UNSET(MULTIBUFFER);
|
2003-01-13 01:35:15 +00:00
|
|
|
#endif
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2015-07-19 09:25:25 +00:00
|
|
|
/* If a starting position was given on the command line, go there. */
|
2014-06-20 19:10:24 +00:00
|
|
|
if (startline > 0 || startcol > 0)
|
2015-12-31 19:20:40 +00:00
|
|
|
do_gotolinecolumn(startline, startcol, FALSE, FALSE);
|
2014-06-19 20:05:24 +00:00
|
|
|
#ifndef DISABLE_HISTORIES
|
2016-01-29 17:18:27 +00:00
|
|
|
else if (ISSET(POS_HISTORY)) {
|
2011-02-16 06:52:30 +00:00
|
|
|
ssize_t savedposline, savedposcol;
|
2015-07-19 09:25:25 +00:00
|
|
|
/* If the file was edited before, restore the last cursor position. */
|
2011-02-16 06:52:30 +00:00
|
|
|
if (check_poshistory(argv[optind], &savedposline, &savedposcol))
|
2015-12-31 19:20:40 +00:00
|
|
|
do_gotolinecolumn(savedposline, savedposcol, FALSE, FALSE);
|
2011-02-16 06:52:30 +00:00
|
|
|
}
|
2014-02-22 16:26:30 +00:00
|
|
|
#endif
|
2005-05-16 18:38:16 +00:00
|
|
|
|
2016-02-23 12:37:10 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "Main: bottom win, top win and edit win\n");
|
|
|
|
#endif
|
|
|
|
|
2007-12-03 18:40:33 +00:00
|
|
|
display_buffer();
|
2000-07-08 14:23:32 +00:00
|
|
|
|
2004-03-15 20:26:30 +00:00
|
|
|
while (TRUE) {
|
2016-05-08 10:01:33 +00:00
|
|
|
if (currmenu != MMAIN)
|
|
|
|
display_main_list();
|
|
|
|
|
2016-04-12 08:24:57 +00:00
|
|
|
focusing = TRUE;
|
2016-05-19 18:43:08 +00:00
|
|
|
lastmessage = HUSH;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2005-07-26 14:42:57 +00:00
|
|
|
/* If constant cursor position display is on, and there are no
|
|
|
|
* keys waiting in the input buffer, display the current cursor
|
|
|
|
* position on the statusbar. */
|
|
|
|
if (ISSET(CONST_UPDATE) && get_key_buffer_len() == 0)
|
2004-07-01 19:41:09 +00:00
|
|
|
do_cursorpos(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-03-29 12:14:00 +00:00
|
|
|
/* Place the cursor in the edit window and make it visible. */
|
|
|
|
reset_cursor();
|
2016-02-13 19:41:12 +00:00
|
|
|
curs_set(1);
|
2016-03-29 12:14:00 +00:00
|
|
|
wnoutrefresh(edit);
|
2016-02-13 19:41:12 +00:00
|
|
|
|
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
|
|
|
}
|