2001-04-18 04:28:54 +00:00
|
|
|
/* $Id$ */
|
|
|
|
/**************************************************************************
|
2001-05-05 15:02:27 +00:00
|
|
|
* rcfile.c *
|
2001-04-18 04:28:54 +00:00
|
|
|
* *
|
2007-10-11 05:01:32 +00:00
|
|
|
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 *
|
|
|
|
* Free Software Foundation, Inc. *
|
2001-04-18 04:28:54 +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) *
|
2001-04-18 04:28:54 +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. *
|
2001-04-18 04:28:54 +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. *
|
2001-04-18 04:28:54 +00:00
|
|
|
* *
|
|
|
|
**************************************************************************/
|
|
|
|
|
2005-12-08 02:47:10 +00:00
|
|
|
#include "proto.h"
|
2002-09-13 18:14:04 +00:00
|
|
|
|
2002-01-22 20:09:20 +00:00
|
|
|
#include <stdarg.h>
|
2001-04-18 04:28:54 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <errno.h>
|
2002-05-11 03:04:44 +00:00
|
|
|
#include <unistd.h>
|
2004-05-13 17:19:54 +00:00
|
|
|
#include <ctype.h>
|
2001-04-18 04:28:54 +00:00
|
|
|
|
|
|
|
#ifdef ENABLE_NANORC
|
|
|
|
|
2006-08-21 21:37:39 +00:00
|
|
|
static const rcoption rcopts[] = {
|
2006-04-12 15:27:40 +00:00
|
|
|
{"boldtext", BOLD_TEXT},
|
2004-05-29 16:38:57 +00:00
|
|
|
#ifndef DISABLE_JUSTIFY
|
|
|
|
{"brackets", 0},
|
2002-06-28 22:45:14 +00:00
|
|
|
#endif
|
2005-06-17 21:08:13 +00:00
|
|
|
{"const", CONST_UPDATE},
|
2002-07-19 01:08:59 +00:00
|
|
|
#ifndef DISABLE_WRAPJUSTIFY
|
2002-06-28 22:45:14 +00:00
|
|
|
{"fill", 0},
|
2002-07-19 01:08:59 +00:00
|
|
|
#endif
|
2003-10-03 20:26:25 +00:00
|
|
|
#ifndef DISABLE_MOUSE
|
2002-01-19 16:52:34 +00:00
|
|
|
{"mouse", USE_MOUSE},
|
2002-06-28 22:45:14 +00:00
|
|
|
#endif
|
|
|
|
#ifdef ENABLE_MULTIBUFFER
|
|
|
|
{"multibuffer", MULTIBUFFER},
|
|
|
|
#endif
|
2005-01-17 05:06:55 +00:00
|
|
|
{"morespace", MORE_SPACE},
|
2002-12-22 16:30:00 +00:00
|
|
|
{"nofollow", NOFOLLOW_SYMLINKS},
|
2002-06-28 22:45:14 +00:00
|
|
|
{"nohelp", NO_HELP},
|
2005-11-05 17:35:44 +00:00
|
|
|
{"nonewlines", NO_NEWLINES},
|
2002-07-19 01:08:59 +00:00
|
|
|
#ifndef DISABLE_WRAPPING
|
2002-06-28 22:45:14 +00:00
|
|
|
{"nowrap", NO_WRAP},
|
2002-07-19 01:08:59 +00:00
|
|
|
#endif
|
2002-06-28 22:45:14 +00:00
|
|
|
#ifndef DISABLE_OPERATINGDIR
|
2002-01-19 16:52:34 +00:00
|
|
|
{"operatingdir", 0},
|
2002-06-28 22:45:14 +00:00
|
|
|
#endif
|
2003-01-13 01:35:15 +00:00
|
|
|
{"preserve", PRESERVE},
|
2002-12-22 16:30:00 +00:00
|
|
|
#ifndef DISABLE_JUSTIFY
|
2004-05-29 16:38:57 +00:00
|
|
|
{"punct", 0},
|
2002-06-28 22:45:14 +00:00
|
|
|
{"quotestr", 0},
|
|
|
|
#endif
|
2004-04-21 22:25:16 +00:00
|
|
|
{"rebinddelete", REBIND_DELETE},
|
2005-08-10 21:22:15 +00:00
|
|
|
{"rebindkeypad", REBIND_KEYPAD},
|
2005-06-16 18:48:30 +00:00
|
|
|
#ifdef HAVE_REGEX_H
|
|
|
|
{"regexp", USE_REGEXP},
|
|
|
|
#endif
|
2002-06-28 22:45:14 +00:00
|
|
|
#ifndef DISABLE_SPELLER
|
2002-01-19 16:52:34 +00:00
|
|
|
{"speller", 0},
|
2002-06-28 22:45:14 +00:00
|
|
|
#endif
|
|
|
|
{"suspend", SUSPEND},
|
|
|
|
{"tabsize", 0},
|
2004-07-03 03:09:12 +00:00
|
|
|
{"tempfile", TEMP_FILE},
|
2002-01-19 16:52:34 +00:00
|
|
|
{"view", VIEW_MODE},
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2005-06-17 19:01:00 +00:00
|
|
|
{"autoindent", AUTOINDENT},
|
|
|
|
{"backup", BACKUP_FILE},
|
|
|
|
{"backupdir", 0},
|
|
|
|
{"backwards", BACKWARDS_SEARCH},
|
|
|
|
{"casesensitive", CASE_SENSITIVE},
|
|
|
|
{"cut", CUT_TO_END},
|
|
|
|
{"historylog", HISTORYLOG},
|
2006-01-06 21:51:10 +00:00
|
|
|
{"matchbrackets", 0},
|
2005-06-17 19:01:00 +00:00
|
|
|
{"noconvert", NO_CONVERT},
|
2005-06-17 19:06:25 +00:00
|
|
|
{"quickblank", QUICK_BLANK},
|
2005-06-17 19:01:00 +00:00
|
|
|
{"smarthome", SMART_HOME},
|
|
|
|
{"smooth", SMOOTH_SCROLL},
|
|
|
|
{"tabstospaces", TABS_TO_SPACES},
|
2004-05-29 16:25:30 +00:00
|
|
|
{"whitespace", 0},
|
2005-08-10 22:12:28 +00:00
|
|
|
{"wordbounds", WORD_BOUNDS},
|
2004-05-29 16:25:30 +00:00
|
|
|
#endif
|
2002-09-13 18:14:04 +00:00
|
|
|
{NULL, 0}
|
2002-01-19 16:52:34 +00:00
|
|
|
};
|
2001-04-18 04:28:54 +00:00
|
|
|
|
2004-07-30 22:52:44 +00:00
|
|
|
static bool errors = FALSE;
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Whether we got any errors while parsing an rcfile. */
|
2005-06-28 06:25:34 +00:00
|
|
|
static size_t lineno = 0;
|
2007-01-01 05:15:32 +00:00
|
|
|
/* If we did, the line number where the last error occurred. */
|
2005-03-10 20:55:11 +00:00
|
|
|
static char *nanorc = NULL;
|
2005-12-08 07:09:08 +00:00
|
|
|
/* The path to the rcfile we're parsing. */
|
2005-03-10 20:55:11 +00:00
|
|
|
#ifdef ENABLE_COLOR
|
|
|
|
static syntaxtype *endsyntax = NULL;
|
|
|
|
/* The end of the list of syntaxes. */
|
2008-09-21 23:02:30 +00:00
|
|
|
static exttype *endheader = NULL;
|
|
|
|
/* End of header list */
|
2005-03-10 20:55:11 +00:00
|
|
|
static colortype *endcolor = NULL;
|
|
|
|
/* The end of the color list for the current syntax. */
|
|
|
|
#endif
|
2002-01-18 21:54:35 +00:00
|
|
|
|
2006-08-21 21:37:39 +00:00
|
|
|
/* We have an error in some part of the rcfile. Print the error message
|
|
|
|
* on stderr, and then make the user hit Enter to continue starting
|
|
|
|
* nano. */
|
2002-08-21 16:10:37 +00:00
|
|
|
void rcfile_error(const char *msg, ...)
|
2001-04-18 04:28:54 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
fprintf(stderr, "\n");
|
2004-07-30 22:52:44 +00:00
|
|
|
if (lineno > 0) {
|
|
|
|
errors = TRUE;
|
2005-08-01 05:54:11 +00:00
|
|
|
fprintf(stderr, _("Error in %s on line %lu: "), nanorc, (unsigned long)lineno);
|
2004-07-30 22:52:44 +00:00
|
|
|
}
|
2002-03-29 19:41:57 +00:00
|
|
|
|
2001-04-18 04:28:54 +00:00
|
|
|
va_start(ap, msg);
|
2004-07-12 03:10:30 +00:00
|
|
|
vfprintf(stderr, _(msg), ap);
|
2001-04-18 04:28:54 +00:00
|
|
|
va_end(ap);
|
2004-08-11 05:13:08 +00:00
|
|
|
|
|
|
|
fprintf(stderr, "\n");
|
2001-04-18 04:28:54 +00:00
|
|
|
}
|
|
|
|
|
2006-08-21 21:37:39 +00:00
|
|
|
/* Parse the next word from the string, null-terminate it, and return
|
|
|
|
* a pointer to the first character after the null terminator. The
|
|
|
|
* returned pointer will point to '\0' if we hit the end of the line. */
|
2002-08-21 16:10:37 +00:00
|
|
|
char *parse_next_word(char *ptr)
|
2001-04-18 04:28:54 +00:00
|
|
|
{
|
2005-06-12 17:48:46 +00:00
|
|
|
while (!isblank(*ptr) && *ptr != '\0')
|
2002-01-19 16:52:34 +00:00
|
|
|
ptr++;
|
|
|
|
|
|
|
|
if (*ptr == '\0')
|
2005-03-10 20:55:11 +00:00
|
|
|
return ptr;
|
2002-01-19 16:52:34 +00:00
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
/* Null-terminate and advance ptr. */
|
|
|
|
*ptr++ = '\0';
|
2002-01-19 16:52:34 +00:00
|
|
|
|
2005-06-12 17:48:46 +00:00
|
|
|
while (isblank(*ptr))
|
2002-01-19 16:52:34 +00:00
|
|
|
ptr++;
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
}
|
2002-01-18 21:54:35 +00:00
|
|
|
|
2006-01-06 21:51:10 +00:00
|
|
|
/* Parse an argument, with optional quotes, after a keyword that takes
|
|
|
|
* one. If the next word starts with a ", we say that it ends with the
|
|
|
|
* last " of the line. Otherwise, we interpret it as usual, so that the
|
|
|
|
* arguments can contain "'s too. */
|
2002-08-21 16:10:37 +00:00
|
|
|
char *parse_argument(char *ptr)
|
|
|
|
{
|
2006-04-05 21:28:52 +00:00
|
|
|
const char *ptr_save = ptr;
|
2002-07-19 01:08:59 +00:00
|
|
|
char *last_quote = NULL;
|
|
|
|
|
|
|
|
assert(ptr != NULL);
|
|
|
|
|
|
|
|
if (*ptr != '"')
|
|
|
|
return parse_next_word(ptr);
|
|
|
|
|
|
|
|
do {
|
|
|
|
ptr++;
|
|
|
|
if (*ptr == '"')
|
|
|
|
last_quote = ptr;
|
2005-03-10 20:55:11 +00:00
|
|
|
} while (*ptr != '\0');
|
2002-07-19 01:08:59 +00:00
|
|
|
|
|
|
|
if (last_quote == NULL) {
|
|
|
|
if (*ptr == '\0')
|
|
|
|
ptr = NULL;
|
|
|
|
else
|
|
|
|
*ptr++ = '\0';
|
2006-06-08 02:50:56 +00:00
|
|
|
rcfile_error(N_("Argument '%s' has an unterminated \""), ptr_save);
|
2002-07-19 01:08:59 +00:00
|
|
|
} else {
|
|
|
|
*last_quote = '\0';
|
|
|
|
ptr = last_quote + 1;
|
|
|
|
}
|
|
|
|
if (ptr != NULL)
|
2005-06-12 17:48:46 +00:00
|
|
|
while (isblank(*ptr))
|
2002-07-19 01:08:59 +00:00
|
|
|
ptr++;
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef ENABLE_COLOR
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Parse the next regex string from the line at ptr, and return it. */
|
2002-09-06 20:35:28 +00:00
|
|
|
char *parse_next_regex(char *ptr)
|
|
|
|
{
|
2005-03-10 20:55:11 +00:00
|
|
|
assert(ptr != NULL);
|
|
|
|
|
|
|
|
/* Continue until the end of the line, or a " followed by a space, a
|
|
|
|
* blank character, or \0. */
|
2005-06-12 17:48:46 +00:00
|
|
|
while ((*ptr != '"' || (!isblank(*(ptr + 1)) &&
|
2005-03-10 20:55:11 +00:00
|
|
|
*(ptr + 1) != '\0')) && *ptr != '\0')
|
2002-09-06 20:35:28 +00:00
|
|
|
ptr++;
|
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
assert(*ptr == '"' || *ptr == '\0');
|
|
|
|
|
|
|
|
if (*ptr == '\0') {
|
2005-03-14 17:47:17 +00:00
|
|
|
rcfile_error(
|
|
|
|
N_("Regex strings must begin and end with a \" character"));
|
2002-09-06 20:35:28 +00:00
|
|
|
return NULL;
|
2005-03-10 20:55:11 +00:00
|
|
|
}
|
2002-09-06 20:35:28 +00:00
|
|
|
|
2006-10-29 21:14:53 +00:00
|
|
|
/* Null-terminate and advance ptr. */
|
2002-09-06 20:35:28 +00:00
|
|
|
*ptr++ = '\0';
|
|
|
|
|
2005-06-12 17:48:46 +00:00
|
|
|
while (isblank(*ptr))
|
2002-09-06 20:35:28 +00:00
|
|
|
ptr++;
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
2005-07-29 21:42:08 +00:00
|
|
|
/* Compile the regular expression regex to see if it's valid. Return
|
|
|
|
* TRUE if it is, or FALSE otherwise. */
|
|
|
|
bool nregcomp(const char *regex, int eflags)
|
2003-02-03 02:56:44 +00:00
|
|
|
{
|
2005-07-29 21:42:08 +00:00
|
|
|
regex_t preg;
|
2008-08-30 05:16:20 +00:00
|
|
|
const char *r = fixbounds(regex);
|
|
|
|
int rc = regcomp(&preg, r, REG_EXTENDED | eflags);
|
2003-02-03 02:56:44 +00:00
|
|
|
|
|
|
|
if (rc != 0) {
|
2005-07-29 21:42:08 +00:00
|
|
|
size_t len = regerror(rc, &preg, NULL, 0);
|
2003-02-03 02:56:44 +00:00
|
|
|
char *str = charalloc(len);
|
|
|
|
|
2005-07-29 21:42:08 +00:00
|
|
|
regerror(rc, &preg, str, len);
|
2008-08-30 05:16:20 +00:00
|
|
|
rcfile_error(N_("Bad regex \"%s\": %s"), r, str);
|
2003-02-03 02:56:44 +00:00
|
|
|
free(str);
|
|
|
|
}
|
2005-03-04 15:09:55 +00:00
|
|
|
|
2005-07-29 21:42:08 +00:00
|
|
|
regfree(&preg);
|
2005-07-13 20:18:46 +00:00
|
|
|
return (rc == 0);
|
2003-02-03 02:56:44 +00:00
|
|
|
}
|
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Parse the next syntax string from the line at ptr, and add it to the
|
|
|
|
* global list of color syntaxes. */
|
2002-08-21 16:10:37 +00:00
|
|
|
void parse_syntax(char *ptr)
|
2002-05-04 03:47:33 +00:00
|
|
|
{
|
2002-07-19 01:08:59 +00:00
|
|
|
const char *fileregptr = NULL, *nameptr = NULL;
|
2006-04-15 16:02:02 +00:00
|
|
|
syntaxtype *tmpsyntax;
|
2003-02-03 02:56:44 +00:00
|
|
|
exttype *endext = NULL;
|
|
|
|
/* The end of the extensions list for this syntax. */
|
2002-05-04 03:47:33 +00:00
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
assert(ptr != NULL);
|
2002-05-04 03:47:33 +00:00
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
if (*ptr == '\0') {
|
|
|
|
rcfile_error(N_("Missing syntax name"));
|
2002-05-04 03:47:33 +00:00
|
|
|
return;
|
2005-03-10 20:55:11 +00:00
|
|
|
}
|
2002-05-04 03:47:33 +00:00
|
|
|
|
|
|
|
if (*ptr != '"') {
|
2005-03-14 17:47:17 +00:00
|
|
|
rcfile_error(
|
|
|
|
N_("Regex strings must begin and end with a \" character"));
|
2002-05-04 04:23:30 +00:00
|
|
|
return;
|
2002-05-04 03:47:33 +00:00
|
|
|
}
|
2005-03-10 20:55:11 +00:00
|
|
|
|
2002-05-04 03:47:33 +00:00
|
|
|
ptr++;
|
|
|
|
|
|
|
|
nameptr = ptr;
|
|
|
|
ptr = parse_next_regex(ptr);
|
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
if (ptr == NULL)
|
2002-05-04 04:23:30 +00:00
|
|
|
return;
|
2002-05-04 03:47:33 +00:00
|
|
|
|
2006-04-15 16:02:02 +00:00
|
|
|
/* Search for a duplicate syntax name. If we find one, free it, so
|
|
|
|
* that we always use the last syntax with a given name. */
|
2005-07-30 21:53:05 +00:00
|
|
|
for (tmpsyntax = syntaxes; tmpsyntax != NULL;
|
|
|
|
tmpsyntax = tmpsyntax->next) {
|
2005-08-01 04:34:27 +00:00
|
|
|
if (strcmp(nameptr, tmpsyntax->desc) == 0) {
|
2006-04-15 16:02:02 +00:00
|
|
|
syntaxtype *prev_syntax = tmpsyntax;
|
|
|
|
|
|
|
|
tmpsyntax = tmpsyntax->next;
|
|
|
|
free(prev_syntax);
|
|
|
|
break;
|
2005-07-30 21:53:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
if (syntaxes == NULL) {
|
|
|
|
syntaxes = (syntaxtype *)nmalloc(sizeof(syntaxtype));
|
2005-03-10 20:55:11 +00:00
|
|
|
endsyntax = syntaxes;
|
2002-07-19 01:08:59 +00:00
|
|
|
} else {
|
2005-03-10 20:55:11 +00:00
|
|
|
endsyntax->next = (syntaxtype *)nmalloc(sizeof(syntaxtype));
|
|
|
|
endsyntax = endsyntax->next;
|
2002-05-04 03:47:33 +00:00
|
|
|
#ifdef DEBUG
|
2005-03-10 20:55:11 +00:00
|
|
|
fprintf(stderr, "Adding new syntax after first one\n");
|
2002-05-04 03:47:33 +00:00
|
|
|
#endif
|
2002-07-19 01:08:59 +00:00
|
|
|
}
|
2005-07-29 21:42:08 +00:00
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
endsyntax->desc = mallocstrcpy(NULL, nameptr);
|
|
|
|
endsyntax->color = NULL;
|
|
|
|
endcolor = NULL;
|
2008-09-21 23:02:30 +00:00
|
|
|
endheader = NULL;
|
2005-03-10 20:55:11 +00:00
|
|
|
endsyntax->extensions = NULL;
|
2008-09-21 23:02:30 +00:00
|
|
|
endsyntax->headers = NULL;
|
2005-03-10 20:55:11 +00:00
|
|
|
endsyntax->next = NULL;
|
2005-07-29 21:42:08 +00:00
|
|
|
|
2002-05-04 03:47:33 +00:00
|
|
|
#ifdef DEBUG
|
2005-03-10 20:55:11 +00:00
|
|
|
fprintf(stderr, "Starting a new syntax type: \"%s\"\n", nameptr);
|
2002-05-04 03:47:33 +00:00
|
|
|
#endif
|
|
|
|
|
2005-08-01 04:59:34 +00:00
|
|
|
/* The "none" syntax is the same as not having a syntax at all, so
|
|
|
|
* we can't assign any extensions or colors to it. */
|
|
|
|
if (strcmp(endsyntax->desc, "none") == 0) {
|
|
|
|
rcfile_error(N_("The \"none\" syntax is reserved"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-08-01 04:23:29 +00:00
|
|
|
/* The default syntax should have no associated extensions. */
|
2005-08-01 04:34:27 +00:00
|
|
|
if (strcmp(endsyntax->desc, "default") == 0 && *ptr != '\0') {
|
2005-08-01 04:59:34 +00:00
|
|
|
rcfile_error(
|
|
|
|
N_("The \"default\" syntax must take no extensions"));
|
2005-08-01 04:23:29 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
/* Now load the extensions into their part of the struct. */
|
|
|
|
while (*ptr != '\0') {
|
2003-02-03 02:56:44 +00:00
|
|
|
exttype *newext;
|
|
|
|
/* The new extension structure. */
|
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
while (*ptr != '"' && *ptr != '\0')
|
2002-05-04 03:47:33 +00:00
|
|
|
ptr++;
|
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
if (*ptr == '\0')
|
2002-05-04 03:47:33 +00:00
|
|
|
return;
|
2005-03-10 20:55:11 +00:00
|
|
|
|
2002-05-04 03:47:33 +00:00
|
|
|
ptr++;
|
|
|
|
|
|
|
|
fileregptr = ptr;
|
|
|
|
ptr = parse_next_regex(ptr);
|
2005-03-10 20:55:11 +00:00
|
|
|
if (ptr == NULL)
|
|
|
|
break;
|
2002-05-04 03:47:33 +00:00
|
|
|
|
2003-02-03 02:56:44 +00:00
|
|
|
newext = (exttype *)nmalloc(sizeof(exttype));
|
2005-07-29 21:42:08 +00:00
|
|
|
|
|
|
|
/* Save the extension regex if it's valid. */
|
|
|
|
if (nregcomp(fileregptr, REG_NOSUB)) {
|
|
|
|
newext->ext_regex = mallocstrcpy(NULL, fileregptr);
|
|
|
|
newext->ext = NULL;
|
|
|
|
|
2003-02-03 02:56:44 +00:00
|
|
|
if (endext == NULL)
|
2005-03-10 20:55:11 +00:00
|
|
|
endsyntax->extensions = newext;
|
2003-02-03 02:56:44 +00:00
|
|
|
else
|
|
|
|
endext->next = newext;
|
|
|
|
endext = newext;
|
|
|
|
endext->next = NULL;
|
2005-07-14 18:33:51 +00:00
|
|
|
} else
|
|
|
|
free(newext);
|
2002-06-28 22:45:14 +00:00
|
|
|
}
|
2002-05-04 03:47:33 +00:00
|
|
|
}
|
|
|
|
|
2008-06-25 03:06:11 +00:00
|
|
|
int check_bad_binding(sc *s)
|
|
|
|
{
|
|
|
|
#define BADLISTLEN 1
|
|
|
|
int badtypes[BADLISTLEN] = {META};
|
|
|
|
int badseqs[BADLISTLEN] = { 91 };
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < BADLISTLEN; i++)
|
|
|
|
if (s->type == badtypes[i] && s->seq == badseqs[i])
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-03-05 07:34:01 +00:00
|
|
|
void parse_keybinding(char *ptr)
|
|
|
|
{
|
|
|
|
char *keyptr = NULL, *keycopy = NULL, *funcptr = NULL, *menuptr = NULL;
|
|
|
|
sc *s, *newsc;
|
|
|
|
int i, menu;
|
|
|
|
|
|
|
|
assert(ptr != NULL);
|
|
|
|
|
|
|
|
if (*ptr == '\0') {
|
|
|
|
rcfile_error(N_("Missing key name"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
keyptr = ptr;
|
|
|
|
ptr = parse_next_word(ptr);
|
|
|
|
keycopy = mallocstrcpy(NULL, keyptr);
|
|
|
|
for (i = 0; i < strlen(keycopy); i++)
|
|
|
|
keycopy[i] = toupper(keycopy[i]);
|
|
|
|
|
2008-07-13 16:44:19 +00:00
|
|
|
if (keycopy[0] != 'M' && keycopy[0] != '^' && keycopy[0] != 'F' && keycopy[0] != 'K') {
|
2008-03-05 07:34:01 +00:00
|
|
|
rcfile_error(
|
|
|
|
N_("keybindings must begin with \"^\", \"M\", or \"F\"\n"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
funcptr = ptr;
|
|
|
|
ptr = parse_next_word(ptr);
|
|
|
|
|
|
|
|
if (funcptr == NULL) {
|
|
|
|
rcfile_error(
|
|
|
|
N_("Must specify function to bind key to\n"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
menuptr = ptr;
|
|
|
|
ptr = parse_next_word(ptr);
|
|
|
|
|
|
|
|
if (menuptr == NULL) {
|
|
|
|
rcfile_error(
|
|
|
|
/* Note to translators, do not translate the word "all"
|
|
|
|
in the sentence below, everything else is fine */
|
|
|
|
N_("Must specify menu bind key to (or \"all\")\n"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
menu = strtomenu(menuptr);
|
|
|
|
if (menu < 1) {
|
|
|
|
rcfile_error(
|
|
|
|
N_("Could not map name \"%s\" to a menu\n"), menuptr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
newsc = strtosc(menu, funcptr);
|
|
|
|
if (newsc == NULL) {
|
|
|
|
rcfile_error(
|
|
|
|
N_("Could not map name \"%s\" to a function\n"), funcptr);
|
|
|
|
return;
|
|
|
|
}
|
2008-06-25 03:06:11 +00:00
|
|
|
|
|
|
|
|
2008-03-11 03:03:53 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "newsc now address %d, menu func assigned = %d, menu = %d\n",
|
2008-07-10 20:13:04 +00:00
|
|
|
&newsc, &newsc->scfunc, menu);
|
2008-03-11 03:03:53 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2008-03-05 07:34:01 +00:00
|
|
|
newsc->keystr = keycopy;
|
|
|
|
newsc->menu = menu;
|
|
|
|
newsc->type = strtokeytype(newsc->keystr);
|
|
|
|
assign_keyinfo(newsc);
|
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "s->keystr = \"%s\"\n", newsc->keystr);
|
|
|
|
fprintf(stderr, "s->seq = \"%d\"\n", newsc->seq);
|
|
|
|
#endif
|
|
|
|
|
2008-06-25 03:06:11 +00:00
|
|
|
if (check_bad_binding(newsc)) {
|
|
|
|
rcfile_error(
|
|
|
|
N_("Sorry, keystr \"%s\" is an illegal binding\n"), newsc->keystr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-05 07:34:01 +00:00
|
|
|
/* now let's have some fun. Try and delete the other entries
|
|
|
|
we found for the same menu, then make this new new
|
|
|
|
beginning */
|
|
|
|
for (s = sclist; s != NULL; s = s->next) {
|
2008-03-09 02:52:40 +00:00
|
|
|
if (((s->menu & newsc->menu)) && s->seq == newsc->seq) {
|
2008-03-05 07:34:01 +00:00
|
|
|
s->menu &= ~newsc->menu;
|
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "replaced menu entry %d\n", s->menu);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
newsc->next = sclist;
|
|
|
|
sclist = newsc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-13 02:43:54 +00:00
|
|
|
/* Read and parse additional syntax files. */
|
|
|
|
void parse_include(char *ptr)
|
|
|
|
{
|
|
|
|
struct stat rcinfo;
|
|
|
|
FILE *rcstream;
|
|
|
|
char *option, *full_option, *nanorc_save = nanorc;
|
|
|
|
size_t lineno_save = lineno;
|
|
|
|
|
|
|
|
option = ptr;
|
|
|
|
if (*option == '"')
|
|
|
|
option++;
|
|
|
|
ptr = parse_argument(ptr);
|
|
|
|
|
|
|
|
/* Get the specified file's full path. */
|
|
|
|
full_option = get_full_path(option);
|
|
|
|
|
2007-04-18 18:22:13 +00:00
|
|
|
if (full_option == NULL)
|
|
|
|
full_option = mallocstrcpy(NULL, option);
|
2006-04-13 02:43:54 +00:00
|
|
|
|
|
|
|
/* Don't open directories, character files, or block files. */
|
2007-04-18 18:22:13 +00:00
|
|
|
if (stat(full_option, &rcinfo) != -1) {
|
2006-04-13 02:43:54 +00:00
|
|
|
if (S_ISDIR(rcinfo.st_mode) || S_ISCHR(rcinfo.st_mode) ||
|
|
|
|
S_ISBLK(rcinfo.st_mode)) {
|
|
|
|
rcfile_error(S_ISDIR(rcinfo.st_mode) ?
|
|
|
|
_("\"%s\" is a directory") :
|
2007-04-18 18:22:13 +00:00
|
|
|
_("\"%s\" is a device file"), option);
|
2006-04-13 02:43:54 +00:00
|
|
|
goto cleanup_include;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Open the new syntax file. */
|
|
|
|
if ((rcstream = fopen(full_option, "rb")) == NULL) {
|
2007-04-18 18:22:13 +00:00
|
|
|
rcfile_error(_("Error reading %s: %s"), option,
|
2006-04-13 02:43:54 +00:00
|
|
|
strerror(errno));
|
|
|
|
goto cleanup_include;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Use the name and line number position of the new syntax file
|
|
|
|
* while parsing it, so we can know where any errors in it are. */
|
|
|
|
nanorc = full_option;
|
|
|
|
lineno = 0;
|
|
|
|
|
2008-03-20 05:41:00 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "Parsing file \"%s\"\n", full_option);
|
|
|
|
#endif
|
|
|
|
|
2006-04-13 02:43:54 +00:00
|
|
|
parse_rcfile(rcstream
|
|
|
|
#ifdef ENABLE_COLOR
|
|
|
|
, TRUE
|
|
|
|
#endif
|
|
|
|
);
|
|
|
|
|
|
|
|
/* We're done with the new syntax file. Restore the original
|
|
|
|
* filename and line number position. */
|
|
|
|
nanorc = nanorc_save;
|
|
|
|
lineno = lineno_save;
|
|
|
|
|
|
|
|
cleanup_include:
|
|
|
|
free(full_option);
|
|
|
|
}
|
|
|
|
|
2006-05-28 19:00:16 +00:00
|
|
|
/* Return the short value corresponding to the color named in colorname,
|
|
|
|
* and set bright to TRUE if that color is bright. */
|
|
|
|
short color_to_short(const char *colorname, bool *bright)
|
|
|
|
{
|
|
|
|
short mcolor = -1;
|
|
|
|
|
|
|
|
assert(colorname != NULL && bright != NULL);
|
|
|
|
|
|
|
|
if (strncasecmp(colorname, "bright", 6) == 0) {
|
|
|
|
*bright = TRUE;
|
|
|
|
colorname += 6;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcasecmp(colorname, "green") == 0)
|
|
|
|
mcolor = COLOR_GREEN;
|
|
|
|
else if (strcasecmp(colorname, "red") == 0)
|
|
|
|
mcolor = COLOR_RED;
|
|
|
|
else if (strcasecmp(colorname, "blue") == 0)
|
|
|
|
mcolor = COLOR_BLUE;
|
|
|
|
else if (strcasecmp(colorname, "white") == 0)
|
|
|
|
mcolor = COLOR_WHITE;
|
|
|
|
else if (strcasecmp(colorname, "yellow") == 0)
|
|
|
|
mcolor = COLOR_YELLOW;
|
|
|
|
else if (strcasecmp(colorname, "cyan") == 0)
|
|
|
|
mcolor = COLOR_CYAN;
|
|
|
|
else if (strcasecmp(colorname, "magenta") == 0)
|
|
|
|
mcolor = COLOR_MAGENTA;
|
|
|
|
else if (strcasecmp(colorname, "black") == 0)
|
|
|
|
mcolor = COLOR_BLACK;
|
|
|
|
else
|
|
|
|
rcfile_error(N_("Color \"%s\" not understood.\n"
|
|
|
|
"Valid colors are \"green\", \"red\", \"blue\",\n"
|
|
|
|
"\"white\", \"yellow\", \"cyan\", \"magenta\" and\n"
|
|
|
|
"\"black\", with the optional prefix \"bright\"\n"
|
|
|
|
"for foreground colors."), colorname);
|
|
|
|
|
|
|
|
return mcolor;
|
|
|
|
}
|
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Parse the color string in the line at ptr, and add it to the current
|
|
|
|
* file's associated colors. If icase is TRUE, treat the color string
|
|
|
|
* as case insensitive. */
|
2005-06-27 03:07:10 +00:00
|
|
|
void parse_colors(char *ptr, bool icase)
|
2001-11-29 02:42:27 +00:00
|
|
|
{
|
2005-07-13 20:18:46 +00:00
|
|
|
short fg, bg;
|
2005-06-08 21:17:32 +00:00
|
|
|
bool bright = FALSE, no_fgcolor = FALSE;
|
2002-07-19 01:08:59 +00:00
|
|
|
char *fgstr;
|
2001-11-29 02:42:27 +00:00
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
assert(ptr != NULL);
|
2001-11-29 02:42:27 +00:00
|
|
|
|
2006-04-13 02:43:54 +00:00
|
|
|
if (syntaxes == NULL) {
|
|
|
|
rcfile_error(
|
2006-04-13 14:09:45 +00:00
|
|
|
N_("Cannot add a color command without a syntax command"));
|
2006-04-13 02:43:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
if (*ptr == '\0') {
|
2004-08-11 05:13:08 +00:00
|
|
|
rcfile_error(N_("Missing color name"));
|
2002-05-04 04:23:30 +00:00
|
|
|
return;
|
2001-11-29 02:42:27 +00:00
|
|
|
}
|
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
fgstr = ptr;
|
|
|
|
ptr = parse_next_word(ptr);
|
|
|
|
|
|
|
|
if (strchr(fgstr, ',') != NULL) {
|
2003-09-06 05:09:32 +00:00
|
|
|
char *bgcolorname;
|
2005-06-08 21:17:32 +00:00
|
|
|
|
2001-11-29 02:42:27 +00:00
|
|
|
strtok(fgstr, ",");
|
2003-09-06 05:09:32 +00:00
|
|
|
bgcolorname = strtok(NULL, ",");
|
2005-06-08 21:17:32 +00:00
|
|
|
if (bgcolorname == NULL) {
|
|
|
|
/* If we have a background color without a foreground color,
|
|
|
|
* parse it properly. */
|
|
|
|
bgcolorname = fgstr + 1;
|
|
|
|
no_fgcolor = TRUE;
|
|
|
|
}
|
2004-07-31 14:10:23 +00:00
|
|
|
if (strncasecmp(bgcolorname, "bright", 6) == 0) {
|
2005-03-14 17:47:17 +00:00
|
|
|
rcfile_error(
|
2006-05-28 19:00:16 +00:00
|
|
|
N_("Background color \"%s\" cannot be bright"),
|
2005-03-14 17:47:17 +00:00
|
|
|
bgcolorname);
|
2003-09-06 05:09:32 +00:00
|
|
|
return;
|
|
|
|
}
|
2005-07-13 20:18:46 +00:00
|
|
|
bg = color_to_short(bgcolorname, &bright);
|
2001-11-29 02:42:27 +00:00
|
|
|
} else
|
2002-07-19 01:08:59 +00:00
|
|
|
bg = -1;
|
2001-11-29 02:42:27 +00:00
|
|
|
|
2005-06-08 21:17:32 +00:00
|
|
|
if (!no_fgcolor) {
|
2005-07-13 20:18:46 +00:00
|
|
|
fg = color_to_short(fgstr, &bright);
|
2001-11-29 02:42:27 +00:00
|
|
|
|
2005-06-08 21:17:32 +00:00
|
|
|
/* Don't try to parse screwed-up foreground colors. */
|
|
|
|
if (fg == -1)
|
|
|
|
return;
|
|
|
|
} else
|
|
|
|
fg = -1;
|
2003-02-07 00:19:05 +00:00
|
|
|
|
2005-06-09 01:09:00 +00:00
|
|
|
if (*ptr == '\0') {
|
2005-06-09 14:04:08 +00:00
|
|
|
rcfile_error(N_("Missing regex string"));
|
2005-06-09 01:09:00 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-06-03 19:10:47 +00:00
|
|
|
/* Now for the fun part. Start adding regexes to individual strings
|
2005-03-10 20:55:11 +00:00
|
|
|
* in the colorstrings array, woo! */
|
|
|
|
while (ptr != NULL && *ptr != '\0') {
|
2003-02-03 02:56:44 +00:00
|
|
|
colortype *newcolor;
|
|
|
|
/* The new color structure. */
|
2005-03-10 20:55:11 +00:00
|
|
|
bool cancelled = FALSE;
|
2003-02-03 02:56:44 +00:00
|
|
|
/* The start expression was bad. */
|
2005-03-10 20:55:11 +00:00
|
|
|
bool expectend = FALSE;
|
|
|
|
/* Do we expect an end= line? */
|
2002-01-19 16:52:34 +00:00
|
|
|
|
2004-07-31 14:10:23 +00:00
|
|
|
if (strncasecmp(ptr, "start=", 6) == 0) {
|
2002-01-19 16:52:34 +00:00
|
|
|
ptr += 6;
|
2005-03-10 20:55:11 +00:00
|
|
|
expectend = TRUE;
|
2002-01-19 16:52:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (*ptr != '"') {
|
2005-03-14 17:47:17 +00:00
|
|
|
rcfile_error(
|
|
|
|
N_("Regex strings must begin and end with a \" character"));
|
2002-09-18 00:28:57 +00:00
|
|
|
ptr = parse_next_regex(ptr);
|
2002-01-19 16:52:34 +00:00
|
|
|
continue;
|
|
|
|
}
|
2005-03-10 20:55:11 +00:00
|
|
|
|
2002-01-19 16:52:34 +00:00
|
|
|
ptr++;
|
2002-01-18 21:54:35 +00:00
|
|
|
|
2003-02-03 02:56:44 +00:00
|
|
|
fgstr = ptr;
|
|
|
|
ptr = parse_next_regex(ptr);
|
2005-03-10 20:55:11 +00:00
|
|
|
if (ptr == NULL)
|
|
|
|
break;
|
|
|
|
|
2005-07-29 21:42:08 +00:00
|
|
|
newcolor = (colortype *)nmalloc(sizeof(colortype));
|
2005-07-13 20:18:46 +00:00
|
|
|
|
2005-07-29 21:42:08 +00:00
|
|
|
/* Save the starting regex string if it's valid, and set up the
|
|
|
|
* color information. */
|
|
|
|
if (nregcomp(fgstr, icase ? REG_ICASE : 0)) {
|
2003-02-03 02:56:44 +00:00
|
|
|
newcolor->fg = fg;
|
|
|
|
newcolor->bg = bg;
|
|
|
|
newcolor->bright = bright;
|
2005-07-13 20:18:46 +00:00
|
|
|
newcolor->icase = icase;
|
2005-07-29 21:42:08 +00:00
|
|
|
|
|
|
|
newcolor->start_regex = mallocstrcpy(NULL, fgstr);
|
|
|
|
newcolor->start = NULL;
|
|
|
|
|
2005-07-14 18:33:51 +00:00
|
|
|
newcolor->end_regex = NULL;
|
2003-02-03 02:56:44 +00:00
|
|
|
newcolor->end = NULL;
|
2005-07-29 21:42:08 +00:00
|
|
|
|
2005-07-13 20:18:46 +00:00
|
|
|
newcolor->next = NULL;
|
2003-02-03 02:56:44 +00:00
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
if (endcolor == NULL) {
|
|
|
|
endsyntax->color = newcolor;
|
2001-11-29 03:49:09 +00:00
|
|
|
#ifdef DEBUG
|
2005-07-13 20:18:46 +00:00
|
|
|
fprintf(stderr, "Starting a new colorstring for fg %hd, bg %hd\n", fg, bg);
|
2001-11-29 03:49:09 +00:00
|
|
|
#endif
|
2003-02-03 02:56:44 +00:00
|
|
|
} else {
|
2002-07-19 01:08:59 +00:00
|
|
|
#ifdef DEBUG
|
2005-07-13 20:18:46 +00:00
|
|
|
fprintf(stderr, "Adding new entry for fg %hd, bg %hd\n", fg, bg);
|
2002-07-19 01:08:59 +00:00
|
|
|
#endif
|
2005-03-10 20:55:11 +00:00
|
|
|
endcolor->next = newcolor;
|
2003-02-03 02:56:44 +00:00
|
|
|
}
|
2005-07-29 21:42:08 +00:00
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
endcolor = newcolor;
|
2005-07-13 20:18:46 +00:00
|
|
|
} else {
|
|
|
|
free(newcolor);
|
|
|
|
cancelled = TRUE;
|
2003-02-03 02:56:44 +00:00
|
|
|
}
|
2002-07-19 01:08:59 +00:00
|
|
|
|
2003-02-03 02:56:44 +00:00
|
|
|
if (expectend) {
|
2004-07-31 14:10:23 +00:00
|
|
|
if (ptr == NULL || strncasecmp(ptr, "end=", 4) != 0) {
|
2005-03-14 17:47:17 +00:00
|
|
|
rcfile_error(
|
|
|
|
N_("\"start=\" requires a corresponding \"end=\""));
|
2002-01-19 16:52:34 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
ptr += 4;
|
|
|
|
if (*ptr != '"') {
|
2005-03-14 17:47:17 +00:00
|
|
|
rcfile_error(
|
|
|
|
N_("Regex strings must begin and end with a \" character"));
|
2002-01-19 16:52:34 +00:00
|
|
|
continue;
|
2001-11-29 02:42:27 +00:00
|
|
|
}
|
2005-03-10 20:55:11 +00:00
|
|
|
|
2001-11-29 02:42:27 +00:00
|
|
|
ptr++;
|
|
|
|
|
2003-02-03 02:56:44 +00:00
|
|
|
fgstr = ptr;
|
2002-01-19 16:52:34 +00:00
|
|
|
ptr = parse_next_regex(ptr);
|
2005-03-10 20:55:11 +00:00
|
|
|
if (ptr == NULL)
|
|
|
|
break;
|
2003-02-03 02:56:44 +00:00
|
|
|
|
|
|
|
/* If the start regex was invalid, skip past the end regex to
|
|
|
|
* stay in sync. */
|
|
|
|
if (cancelled)
|
|
|
|
continue;
|
2005-03-10 20:55:11 +00:00
|
|
|
|
2005-07-29 21:42:08 +00:00
|
|
|
/* Save the ending regex string if it's valid. */
|
|
|
|
newcolor->end_regex = (nregcomp(fgstr, icase ? REG_ICASE :
|
|
|
|
0)) ? mallocstrcpy(NULL, fgstr) : NULL;
|
2002-07-19 01:08:59 +00:00
|
|
|
}
|
2002-01-19 16:52:34 +00:00
|
|
|
}
|
2001-11-29 02:42:27 +00:00
|
|
|
}
|
2008-09-21 23:02:30 +00:00
|
|
|
|
|
|
|
/* Parse the headers (1st line) of the file which may influence the regex used. */
|
|
|
|
void parse_headers(char *ptr)
|
|
|
|
{
|
|
|
|
char *h, *regstr;
|
|
|
|
|
|
|
|
assert(ptr != NULL);
|
|
|
|
|
|
|
|
if (syntaxes == NULL) {
|
|
|
|
rcfile_error(
|
|
|
|
N_("Cannot add a header regex without a syntax command"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*ptr == '\0') {
|
|
|
|
rcfile_error(N_("Missing regex string"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now for the fun part. Start adding regexes to individual strings
|
|
|
|
* in the colorstrings array, woo! */
|
|
|
|
while (ptr != NULL && *ptr != '\0') {
|
|
|
|
exttype *newheader;
|
|
|
|
/* The new color structure. */
|
|
|
|
bool cancelled = FALSE;
|
|
|
|
/* The start expression was bad. */
|
|
|
|
|
|
|
|
if (*ptr != '"') {
|
|
|
|
rcfile_error(
|
|
|
|
N_("Regex strings must begin and end with a \" character"));
|
|
|
|
ptr = parse_next_regex(ptr);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr++;
|
|
|
|
|
|
|
|
regstr = ptr;
|
|
|
|
ptr = parse_next_regex(ptr);
|
|
|
|
if (ptr == NULL)
|
|
|
|
break;
|
|
|
|
|
|
|
|
newheader = (exttype *)nmalloc(sizeof(exttype));
|
|
|
|
|
|
|
|
/* Save the regex string if it's valid */
|
|
|
|
if (nregcomp(regstr, 0)) {
|
|
|
|
newheader->ext_regex = mallocstrcpy(NULL, regstr);
|
|
|
|
newheader->ext = NULL;
|
|
|
|
newheader->next = NULL;
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "Starting a new header entry: %s\n", newheader->ext_regex);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (endheader == NULL) {
|
|
|
|
endsyntax->headers = newheader;
|
|
|
|
} else {
|
|
|
|
endheader->next = newheader;
|
|
|
|
}
|
|
|
|
|
|
|
|
endheader = newheader;
|
|
|
|
} else
|
|
|
|
free(newheader);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2002-06-28 22:45:14 +00:00
|
|
|
#endif /* ENABLE_COLOR */
|
2001-11-29 02:42:27 +00:00
|
|
|
|
2008-03-20 04:45:55 +00:00
|
|
|
/* Check whether the user has unmapped every shortcut for a
|
|
|
|
sequence we consider 'vital', like the exit function */
|
|
|
|
static void check_vitals_mapped(void)
|
|
|
|
{
|
|
|
|
subnfunc *f;
|
|
|
|
int v;
|
|
|
|
#define VITALS 5
|
|
|
|
void *vitals[VITALS] = { do_exit, do_exit, (void *) cancel_msg, (void *) cancel_msg, (void *) cancel_msg };
|
|
|
|
int inmenus[VITALS] = { MMAIN, MHELP, MWHEREIS, MREPLACE, MGOTOLINE };
|
|
|
|
|
|
|
|
for (v = 0; v < VITALS; v++) {
|
|
|
|
for (f = allfuncs; f != NULL; f = f->next) {
|
|
|
|
if (f->scfunc == vitals[v] && f->menus & inmenus[v]) {
|
|
|
|
const sc *s = first_sc_for(inmenus[v], f->scfunc);
|
|
|
|
if (!s) {
|
|
|
|
rcfile_error(N_("Fatal error: no keys mapped for function \"%s\""),
|
|
|
|
f->desc);
|
|
|
|
fprintf(stderr, N_("Exiting. Please use nano with the -I option if needed to adjust your nanorc settings\n"));
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-01 20:23:24 +00:00
|
|
|
/* Parse the rcfile, once it has been opened successfully at rcstream,
|
|
|
|
* and close it afterwards. If syntax_only is TRUE, only allow the file
|
|
|
|
* to contain color syntax commands: syntax, color, and icolor. */
|
2006-04-13 02:43:54 +00:00
|
|
|
void parse_rcfile(FILE *rcstream
|
|
|
|
#ifdef ENABLE_COLOR
|
|
|
|
, bool syntax_only
|
|
|
|
#endif
|
|
|
|
)
|
2001-04-18 04:28:54 +00:00
|
|
|
{
|
2005-03-10 20:55:11 +00:00
|
|
|
char *buf = NULL;
|
|
|
|
ssize_t len;
|
|
|
|
size_t n;
|
|
|
|
|
|
|
|
while ((len = getline(&buf, &n, rcstream)) > 0) {
|
|
|
|
char *ptr, *keyword, *option;
|
2006-05-26 13:38:49 +00:00
|
|
|
int set = 0;
|
|
|
|
size_t i;
|
2005-03-10 20:55:11 +00:00
|
|
|
|
2006-04-12 22:03:47 +00:00
|
|
|
/* Ignore the newline. */
|
2006-05-26 13:49:00 +00:00
|
|
|
if (buf[len - 1] == '\n')
|
|
|
|
buf[len - 1] = '\0';
|
2001-04-18 04:28:54 +00:00
|
|
|
|
|
|
|
lineno++;
|
|
|
|
ptr = buf;
|
2005-06-12 17:48:46 +00:00
|
|
|
while (isblank(*ptr))
|
2001-04-18 04:28:54 +00:00
|
|
|
ptr++;
|
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
/* If we have a blank line or a comment, skip to the next
|
|
|
|
* line. */
|
|
|
|
if (*ptr == '\0' || *ptr == '#')
|
2001-04-18 04:28:54 +00:00
|
|
|
continue;
|
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
/* Otherwise, skip to the next space. */
|
2001-04-18 04:28:54 +00:00
|
|
|
keyword = ptr;
|
|
|
|
ptr = parse_next_word(ptr);
|
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
/* Try to parse the keyword. */
|
2006-04-13 02:43:54 +00:00
|
|
|
if (strcasecmp(keyword, "set") == 0) {
|
2001-11-29 02:42:27 +00:00
|
|
|
#ifdef ENABLE_COLOR
|
2006-04-13 02:43:54 +00:00
|
|
|
if (syntax_only)
|
|
|
|
rcfile_error(
|
2006-05-28 19:00:16 +00:00
|
|
|
N_("Command \"%s\" not allowed in included file"),
|
2006-04-13 02:43:54 +00:00
|
|
|
keyword);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
set = 1;
|
|
|
|
} else if (strcasecmp(keyword, "unset") == 0) {
|
|
|
|
#ifdef ENABLE_COLOR
|
|
|
|
if (syntax_only)
|
|
|
|
rcfile_error(
|
2006-05-28 19:00:16 +00:00
|
|
|
N_("Command \"%s\" not allowed in included file"),
|
2006-04-13 02:43:54 +00:00
|
|
|
keyword);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
set = -1;
|
|
|
|
}
|
|
|
|
#ifdef ENABLE_COLOR
|
|
|
|
else if (strcasecmp(keyword, "include") == 0) {
|
|
|
|
if (syntax_only)
|
|
|
|
rcfile_error(
|
2006-05-28 19:00:16 +00:00
|
|
|
N_("Command \"%s\" not allowed in included file"),
|
2006-04-13 02:43:54 +00:00
|
|
|
keyword);
|
|
|
|
else
|
|
|
|
parse_include(ptr);
|
2006-05-26 13:27:28 +00:00
|
|
|
} else if (strcasecmp(keyword, "syntax") == 0) {
|
|
|
|
if (endsyntax != NULL && endcolor == NULL)
|
2006-05-28 19:00:16 +00:00
|
|
|
rcfile_error(N_("Syntax \"%s\" has no color commands"),
|
2006-05-26 17:06:05 +00:00
|
|
|
endsyntax->desc);
|
2002-07-19 01:08:59 +00:00
|
|
|
parse_syntax(ptr);
|
2008-09-21 23:02:30 +00:00
|
|
|
} else if (strcasecmp(keyword, "header") == 0)
|
|
|
|
parse_headers(ptr);
|
|
|
|
else if (strcasecmp(keyword, "color") == 0)
|
2005-06-27 03:07:10 +00:00
|
|
|
parse_colors(ptr, FALSE);
|
|
|
|
else if (strcasecmp(keyword, "icolor") == 0)
|
|
|
|
parse_colors(ptr, TRUE);
|
2008-03-05 07:34:01 +00:00
|
|
|
else if (strcasecmp(keyword, "bind") == 0)
|
|
|
|
parse_keybinding(ptr);
|
2005-03-10 20:55:11 +00:00
|
|
|
#endif /* ENABLE_COLOR */
|
|
|
|
else
|
2006-05-28 19:00:16 +00:00
|
|
|
rcfile_error(N_("Command \"%s\" not understood"), keyword);
|
2005-03-10 20:55:11 +00:00
|
|
|
|
|
|
|
if (set == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (*ptr == '\0') {
|
|
|
|
rcfile_error(N_("Missing flag"));
|
2001-04-18 04:28:54 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
option = ptr;
|
|
|
|
ptr = parse_next_word(ptr);
|
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
for (i = 0; rcopts[i].name != NULL; i++) {
|
|
|
|
if (strcasecmp(option, rcopts[i].name) == 0) {
|
2001-04-18 04:28:54 +00:00
|
|
|
#ifdef DEBUG
|
2005-03-10 20:55:11 +00:00
|
|
|
fprintf(stderr, "parse_rcfile(): name = \"%s\"\n", rcopts[i].name);
|
|
|
|
#endif
|
|
|
|
if (set == 1) {
|
|
|
|
if (rcopts[i].flag != 0)
|
|
|
|
/* This option has a flag, so it doesn't take an
|
|
|
|
* argument. */
|
|
|
|
SET(rcopts[i].flag);
|
|
|
|
else {
|
|
|
|
/* This option doesn't have a flag, so it takes
|
2006-05-28 18:43:21 +00:00
|
|
|
* an argument. */
|
2005-03-10 20:55:11 +00:00
|
|
|
if (*ptr == '\0') {
|
2005-03-14 17:47:17 +00:00
|
|
|
rcfile_error(
|
2006-05-28 19:00:16 +00:00
|
|
|
N_("Option \"%s\" requires an argument"),
|
2005-03-14 17:47:17 +00:00
|
|
|
rcopts[i].name);
|
2005-03-10 20:55:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
option = ptr;
|
|
|
|
if (*option == '"')
|
|
|
|
option++;
|
|
|
|
ptr = parse_argument(ptr);
|
2005-06-08 19:50:02 +00:00
|
|
|
|
2005-06-13 14:50:32 +00:00
|
|
|
option = mallocstrcpy(NULL, option);
|
2002-07-19 01:08:59 +00:00
|
|
|
#ifdef DEBUG
|
2005-03-10 20:55:11 +00:00
|
|
|
fprintf(stderr, "option = \"%s\"\n", option);
|
2002-07-19 01:08:59 +00:00
|
|
|
#endif
|
2005-06-13 14:50:32 +00:00
|
|
|
|
|
|
|
/* Make sure option is a valid multibyte
|
|
|
|
* string. */
|
|
|
|
if (!is_valid_mbstring(option)) {
|
|
|
|
rcfile_error(
|
|
|
|
N_("Option is not a valid multibyte string"));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
#ifndef DISABLE_OPERATINGDIR
|
2005-03-10 20:55:11 +00:00
|
|
|
if (strcasecmp(rcopts[i].name, "operatingdir") == 0)
|
2005-03-14 18:47:21 +00:00
|
|
|
operating_dir = option;
|
2005-03-10 20:55:11 +00:00
|
|
|
else
|
2002-07-19 01:08:59 +00:00
|
|
|
#endif
|
2001-05-21 12:56:25 +00:00
|
|
|
#ifndef DISABLE_WRAPJUSTIFY
|
2005-03-10 20:55:11 +00:00
|
|
|
if (strcasecmp(rcopts[i].name, "fill") == 0) {
|
|
|
|
if (!parse_num(option, &wrap_at)) {
|
2005-03-14 17:47:17 +00:00
|
|
|
rcfile_error(
|
2006-06-08 02:50:56 +00:00
|
|
|
N_("Requested fill size \"%s\" is invalid"),
|
2005-03-14 17:47:17 +00:00
|
|
|
option);
|
2005-03-10 20:55:11 +00:00
|
|
|
wrap_at = -CHARS_FROM_EOL;
|
2005-03-14 18:47:21 +00:00
|
|
|
} else
|
|
|
|
free(option);
|
2005-03-10 20:55:11 +00:00
|
|
|
} else
|
2002-07-19 01:08:59 +00:00
|
|
|
#endif
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2006-01-06 22:04:38 +00:00
|
|
|
if (strcasecmp(rcopts[i].name,
|
|
|
|
"matchbrackets") == 0) {
|
|
|
|
matchbrackets = option;
|
|
|
|
if (has_blank_mbchars(matchbrackets)) {
|
|
|
|
rcfile_error(
|
|
|
|
N_("Non-blank characters required"));
|
|
|
|
free(matchbrackets);
|
|
|
|
matchbrackets = NULL;
|
|
|
|
}
|
|
|
|
} else if (strcasecmp(rcopts[i].name,
|
|
|
|
"whitespace") == 0) {
|
2005-03-14 18:47:21 +00:00
|
|
|
whitespace = option;
|
2005-06-13 14:50:32 +00:00
|
|
|
if (mbstrlen(whitespace) != 2 ||
|
|
|
|
strlenpt(whitespace) != 2) {
|
2005-03-14 17:47:17 +00:00
|
|
|
rcfile_error(
|
|
|
|
N_("Two single-column characters required"));
|
2005-03-10 20:55:11 +00:00
|
|
|
free(whitespace);
|
|
|
|
whitespace = NULL;
|
2005-03-10 22:52:21 +00:00
|
|
|
} else {
|
|
|
|
whitespace_len[0] =
|
|
|
|
parse_mbchar(whitespace, NULL,
|
2005-07-26 06:13:45 +00:00
|
|
|
NULL);
|
2005-03-10 22:52:21 +00:00
|
|
|
whitespace_len[1] =
|
|
|
|
parse_mbchar(whitespace +
|
2005-07-26 06:13:45 +00:00
|
|
|
whitespace_len[0], NULL, NULL);
|
2005-03-10 20:55:11 +00:00
|
|
|
}
|
|
|
|
} else
|
2004-05-29 16:47:52 +00:00
|
|
|
#endif
|
2002-03-03 22:52:52 +00:00
|
|
|
#ifndef DISABLE_JUSTIFY
|
2005-03-10 20:55:11 +00:00
|
|
|
if (strcasecmp(rcopts[i].name, "punct") == 0) {
|
2005-03-14 18:47:21 +00:00
|
|
|
punct = option;
|
2005-06-14 01:55:56 +00:00
|
|
|
if (has_blank_mbchars(punct)) {
|
2005-03-14 17:47:17 +00:00
|
|
|
rcfile_error(
|
2005-06-14 01:55:56 +00:00
|
|
|
N_("Non-blank characters required"));
|
2005-03-10 20:55:11 +00:00
|
|
|
free(punct);
|
|
|
|
punct = NULL;
|
|
|
|
}
|
2005-03-14 17:47:17 +00:00
|
|
|
} else if (strcasecmp(rcopts[i].name,
|
|
|
|
"brackets") == 0) {
|
2005-03-14 18:47:21 +00:00
|
|
|
brackets = option;
|
2005-06-14 01:55:56 +00:00
|
|
|
if (has_blank_mbchars(brackets)) {
|
2005-03-14 17:47:17 +00:00
|
|
|
rcfile_error(
|
2005-06-14 01:55:56 +00:00
|
|
|
N_("Non-blank characters required"));
|
2005-03-10 20:55:11 +00:00
|
|
|
free(brackets);
|
|
|
|
brackets = NULL;
|
|
|
|
}
|
2005-03-14 17:47:17 +00:00
|
|
|
} else if (strcasecmp(rcopts[i].name,
|
|
|
|
"quotestr") == 0)
|
2005-03-14 18:47:21 +00:00
|
|
|
quotestr = option;
|
2005-03-10 20:55:11 +00:00
|
|
|
else
|
2002-03-03 22:52:52 +00:00
|
|
|
#endif
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2005-03-14 17:47:17 +00:00
|
|
|
if (strcasecmp(rcopts[i].name,
|
|
|
|
"backupdir") == 0)
|
2005-03-14 18:47:21 +00:00
|
|
|
backup_dir = option;
|
2005-03-10 20:55:11 +00:00
|
|
|
else
|
2004-02-28 16:24:31 +00:00
|
|
|
#endif
|
2001-05-21 12:56:25 +00:00
|
|
|
#ifndef DISABLE_SPELLER
|
2005-03-10 20:55:11 +00:00
|
|
|
if (strcasecmp(rcopts[i].name, "speller") == 0)
|
2005-03-14 18:47:21 +00:00
|
|
|
alt_speller = option;
|
2005-03-10 20:55:11 +00:00
|
|
|
else
|
|
|
|
#endif
|
2005-03-14 17:47:17 +00:00
|
|
|
if (strcasecmp(rcopts[i].name,
|
|
|
|
"tabsize") == 0) {
|
|
|
|
if (!parse_num(option, &tabsize) ||
|
|
|
|
tabsize <= 0) {
|
|
|
|
rcfile_error(
|
2006-06-08 02:50:56 +00:00
|
|
|
N_("Requested tab size \"%s\" is invalid"),
|
2005-03-14 17:47:17 +00:00
|
|
|
option);
|
2005-03-10 20:55:11 +00:00
|
|
|
tabsize = -1;
|
2005-03-14 18:47:21 +00:00
|
|
|
} else
|
|
|
|
free(option);
|
2002-01-19 16:52:34 +00:00
|
|
|
} else
|
2005-03-10 20:55:11 +00:00
|
|
|
assert(FALSE);
|
|
|
|
}
|
2001-04-18 04:28:54 +00:00
|
|
|
#ifdef DEBUG
|
2005-03-27 01:34:40 +00:00
|
|
|
fprintf(stderr, "flag = %ld\n", rcopts[i].flag);
|
2001-04-18 04:28:54 +00:00
|
|
|
#endif
|
2005-03-10 20:55:11 +00:00
|
|
|
} else if (rcopts[i].flag != 0)
|
|
|
|
UNSET(rcopts[i].flag);
|
|
|
|
else
|
2006-05-28 19:00:16 +00:00
|
|
|
rcfile_error(N_("Cannot unset flag \"%s\""),
|
2005-03-14 17:47:17 +00:00
|
|
|
rcopts[i].name);
|
2005-03-10 20:55:11 +00:00
|
|
|
break;
|
2001-04-18 04:28:54 +00:00
|
|
|
}
|
|
|
|
}
|
2005-03-10 20:55:11 +00:00
|
|
|
if (rcopts[i].name == NULL)
|
2006-05-28 19:00:16 +00:00
|
|
|
rcfile_error(N_("Unknown flag \"%s\""), option);
|
2001-04-18 04:28:54 +00:00
|
|
|
}
|
2005-03-10 20:55:11 +00:00
|
|
|
|
2006-07-19 00:21:17 +00:00
|
|
|
#ifdef ENABLE_COLOR
|
2006-05-26 12:56:30 +00:00
|
|
|
if (endsyntax != NULL && endcolor == NULL)
|
2006-05-28 19:00:16 +00:00
|
|
|
rcfile_error(N_("Syntax \"%s\" has no color commands"),
|
2006-05-26 17:06:05 +00:00
|
|
|
endsyntax->desc);
|
2006-07-19 00:21:17 +00:00
|
|
|
#endif
|
2006-05-26 12:56:30 +00:00
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
free(buf);
|
2005-03-10 20:55:11 +00:00
|
|
|
fclose(rcstream);
|
|
|
|
lineno = 0;
|
2004-07-30 22:52:44 +00:00
|
|
|
|
2008-03-09 02:52:40 +00:00
|
|
|
check_vitals_mapped();
|
|
|
|
|
2004-07-30 22:52:44 +00:00
|
|
|
if (errors) {
|
|
|
|
errors = FALSE;
|
2006-06-08 02:37:45 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
_("\nPress Enter to continue starting nano.\n"));
|
2004-07-30 22:52:44 +00:00
|
|
|
while (getchar() != '\n')
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2001-04-18 04:28:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-11-04 04:10:09 +00:00
|
|
|
/* The main rcfile function. It tries to open the system-wide rcfile,
|
2006-04-12 21:45:41 +00:00
|
|
|
* followed by the current user's rcfile. */
|
2001-04-18 04:28:54 +00:00
|
|
|
void do_rcfile(void)
|
|
|
|
{
|
2006-04-12 21:44:07 +00:00
|
|
|
struct stat rcinfo;
|
2001-04-18 04:28:54 +00:00
|
|
|
FILE *rcstream;
|
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
nanorc = mallocstrcpy(nanorc, SYSCONFDIR "/nanorc");
|
2006-04-12 21:44:07 +00:00
|
|
|
|
|
|
|
/* Don't open directories, character files, or block files. */
|
|
|
|
if (stat(nanorc, &rcinfo) != -1) {
|
|
|
|
if (S_ISDIR(rcinfo.st_mode) || S_ISCHR(rcinfo.st_mode) ||
|
|
|
|
S_ISBLK(rcinfo.st_mode))
|
|
|
|
rcfile_error(S_ISDIR(rcinfo.st_mode) ?
|
|
|
|
_("\"%s\" is a directory") :
|
|
|
|
_("\"%s\" is a device file"), nanorc);
|
|
|
|
}
|
|
|
|
|
2008-03-20 05:41:00 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "Parsing file \"%s\"\n", nanorc);
|
|
|
|
#endif
|
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
/* Try to open the system-wide nanorc. */
|
2006-04-05 21:25:47 +00:00
|
|
|
rcstream = fopen(nanorc, "rb");
|
2005-03-10 20:55:11 +00:00
|
|
|
if (rcstream != NULL)
|
2006-04-13 02:43:54 +00:00
|
|
|
parse_rcfile(rcstream
|
|
|
|
#ifdef ENABLE_COLOR
|
|
|
|
, FALSE
|
|
|
|
#endif
|
|
|
|
);
|
2002-02-16 20:34:57 +00:00
|
|
|
|
2006-07-19 15:50:19 +00:00
|
|
|
#ifdef DISABLE_ROOTWRAPPING
|
2005-03-10 20:55:11 +00:00
|
|
|
/* We've already read SYSCONFDIR/nanorc, if it's there. If we're
|
2006-07-18 18:16:30 +00:00
|
|
|
* root, and --disable-wrapping-as-root is used, turn wrapping off
|
|
|
|
* now. */
|
2005-03-10 20:55:11 +00:00
|
|
|
if (geteuid() == NANO_ROOT_UID)
|
|
|
|
SET(NO_WRAP);
|
|
|
|
#endif
|
2002-05-11 03:04:44 +00:00
|
|
|
|
2005-02-08 20:37:53 +00:00
|
|
|
get_homedir();
|
2003-02-13 03:36:15 +00:00
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
if (homedir == NULL)
|
2004-08-17 05:23:38 +00:00
|
|
|
rcfile_error(N_("I can't find my home directory! Wah!"));
|
2005-03-10 20:55:11 +00:00
|
|
|
else {
|
2008-08-28 06:13:05 +00:00
|
|
|
#ifndef RCFILE_NAME
|
|
|
|
#define RCFILE_NAME ".nanorc"
|
|
|
|
#endif
|
|
|
|
nanorc = charealloc(nanorc, strlen(homedir) + strlen(RCFILE_NAME) + 2);
|
|
|
|
sprintf(nanorc, "%s/%s", homedir, RCFILE_NAME);
|
2005-03-10 20:55:11 +00:00
|
|
|
|
2006-04-12 21:44:07 +00:00
|
|
|
/* Don't open directories, character files, or block files. */
|
|
|
|
if (stat(nanorc, &rcinfo) != -1) {
|
|
|
|
if (S_ISDIR(rcinfo.st_mode) || S_ISCHR(rcinfo.st_mode) ||
|
|
|
|
S_ISBLK(rcinfo.st_mode))
|
|
|
|
rcfile_error(S_ISDIR(rcinfo.st_mode) ?
|
|
|
|
_("\"%s\" is a directory") :
|
|
|
|
_("\"%s\" is a device file"), nanorc);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Try to open the current user's nanorc. */
|
|
|
|
rcstream = fopen(nanorc, "rb");
|
2004-08-17 05:23:38 +00:00
|
|
|
if (rcstream == NULL) {
|
2005-03-10 20:55:11 +00:00
|
|
|
/* Don't complain about the file's not existing. */
|
|
|
|
if (errno != ENOENT)
|
2005-03-14 17:47:17 +00:00
|
|
|
rcfile_error(N_("Error reading %s: %s"), nanorc,
|
|
|
|
strerror(errno));
|
2005-03-10 20:55:11 +00:00
|
|
|
} else
|
2006-04-13 02:43:54 +00:00
|
|
|
parse_rcfile(rcstream
|
|
|
|
#ifdef ENABLE_COLOR
|
|
|
|
, FALSE
|
|
|
|
#endif
|
|
|
|
);
|
2001-04-18 04:28:54 +00:00
|
|
|
}
|
2005-03-04 15:09:55 +00:00
|
|
|
|
2005-03-10 20:55:11 +00:00
|
|
|
free(nanorc);
|
|
|
|
nanorc = NULL;
|
2001-04-18 04:28:54 +00:00
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
#ifdef ENABLE_COLOR
|
|
|
|
set_colorpairs();
|
|
|
|
#endif
|
2001-04-18 04:28:54 +00:00
|
|
|
}
|
|
|
|
|
2002-06-28 22:45:14 +00:00
|
|
|
#endif /* ENABLE_NANORC */
|