354 lines
7.8 KiB
C
354 lines
7.8 KiB
C
/* $Id$ */
|
|
/**************************************************************************
|
|
* utils.c *
|
|
* *
|
|
* Copyright (C) 1999-2002 Chris Allegretta *
|
|
* 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 *
|
|
* the Free Software Foundation; either version 2, or (at your option) *
|
|
* any later version. *
|
|
* *
|
|
* 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. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program; if not, write to the Free Software *
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
|
* *
|
|
**************************************************************************/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#include "nano.h"
|
|
#include "proto.h"
|
|
|
|
#ifndef NANO_SMALL
|
|
#include <libintl.h>
|
|
#define _(string) gettext(string)
|
|
#else
|
|
#define _(string) (string)
|
|
#endif
|
|
|
|
int num_of_digits(int n)
|
|
{
|
|
int i = 1;
|
|
|
|
if (n < 0)
|
|
n = 0 - n;
|
|
|
|
while (n > 10) {
|
|
n /= 10;
|
|
i++;
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
/* Lower case a string - must be null terminated */
|
|
void lowercase(char *src)
|
|
{
|
|
long i = 0;
|
|
|
|
while (src[i] != 0) {
|
|
src[i] = (char) tolower(src[i]);
|
|
i++;
|
|
}
|
|
}
|
|
|
|
/* None of this is needed if we're using NANO_SMALL! */
|
|
#ifndef NANO_SMALL
|
|
char *revstrstr(char *haystack, char *needle, char *rev_start)
|
|
{
|
|
char *p, *q, *r;
|
|
|
|
for(p = rev_start ; p >= haystack ; --p) {
|
|
for (r = p, q = needle ; (*q == *r) && (*q != '\0') ; r++, q++)
|
|
;
|
|
if (*q == '\0')
|
|
return p;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
char *revstristr(char *haystack, char *needle, char *rev_start)
|
|
{
|
|
char *p, *q, *r;
|
|
|
|
for(p = rev_start ; p >= haystack ; --p) {
|
|
for (r = p, q = needle ; (tolower(*q) == tolower(*r)) && (*q != '\0') ; r++, q++)
|
|
;
|
|
if (*q == '\0')
|
|
return p;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif /* NANO_SMALL */
|
|
|
|
/* This is now mutt's version (called mutt_stristr) because it doesn't
|
|
use memory allocation to do a simple search (yuck). */
|
|
char *stristr(char *haystack, char *needle)
|
|
{
|
|
const char *p, *q;
|
|
|
|
if (!haystack)
|
|
return NULL;
|
|
if (!needle)
|
|
return (haystack);
|
|
|
|
while (*(p = haystack)) {
|
|
for (q = needle; *p && *q && tolower (*p) == tolower (*q); p++, q++)
|
|
;
|
|
if (!*q)
|
|
return (haystack);
|
|
haystack++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
char *strstrwrapper(char *haystack, char *needle, char *rev_start)
|
|
{
|
|
|
|
#ifdef HAVE_REGEX_H
|
|
int result;
|
|
|
|
if (ISSET(USE_REGEXP)) {
|
|
if (!ISSET(REVERSE_SEARCH)) {
|
|
result = regexec(&search_regexp, haystack, 10, regmatches, 0);
|
|
if (!result)
|
|
return haystack + regmatches[0].rm_so;
|
|
#ifndef NANO_SMALL
|
|
} else {
|
|
char *i, *j;
|
|
|
|
/* do a quick search forward first */
|
|
if (!(regexec(&search_regexp, haystack, 10, regmatches, 0))) {
|
|
/* there's a match somewhere in the line - now search for it backwards, much slower */
|
|
for(i = rev_start ; i >= haystack ; --i)
|
|
if (!(result = regexec(&search_regexp, i, 10, regmatches, 0))) {
|
|
j = i + regmatches[0].rm_so;
|
|
if (j <= rev_start)
|
|
return j;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
#ifndef NANO_SMALL
|
|
if (ISSET(CASE_SENSITIVE)) {
|
|
if (ISSET(REVERSE_SEARCH))
|
|
return revstrstr(haystack, needle, rev_start);
|
|
else
|
|
return strstr(haystack,needle);
|
|
|
|
} else {
|
|
if (ISSET(REVERSE_SEARCH))
|
|
return revstristr(haystack, needle, rev_start);
|
|
else
|
|
#endif
|
|
return stristr(haystack, needle);
|
|
#ifndef NANO_SMALL
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* This is a wrapper for the perror function. The wrapper takes care of
|
|
* ncurses, calls perror (which writes to STDERR), then refreshes the
|
|
* screen. Note that nperror causes the window to flicker once.
|
|
*/
|
|
void nperror(const char *s) {
|
|
/* leave ncurses mode, go to the terminal */
|
|
if (endwin() != ERR) {
|
|
perror(s); /* print the error */
|
|
total_refresh(); /* return to ncurses and repaint */
|
|
}
|
|
}
|
|
|
|
/* Thanks BG, many ppl have been asking for this... */
|
|
void *nmalloc(size_t howmuch)
|
|
{
|
|
void *r;
|
|
|
|
/* Panic save? */
|
|
|
|
if (!(r = malloc(howmuch)))
|
|
die(_("nano: malloc: out of memory!"));
|
|
|
|
return r;
|
|
}
|
|
|
|
/* We're going to need this too - Hopefully this will minimize
|
|
the transition cost of moving to the apropriate function. */
|
|
char *charalloc(size_t howmuch)
|
|
{
|
|
void *r;
|
|
|
|
/* Panic save? */
|
|
|
|
if (!(r = calloc(howmuch, sizeof (char))))
|
|
die(_("nano: calloc: out of memory!"));
|
|
|
|
return (char *) r;
|
|
}
|
|
|
|
void *nrealloc(void *ptr, size_t howmuch)
|
|
{
|
|
void *r;
|
|
|
|
if (!(r = realloc(ptr, howmuch)))
|
|
die(_("nano: realloc: out of memory!"));
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Copy one malloc()ed string to another pointer.
|
|
|
|
Should be used as dest = mallocstrcpy(dest, src);
|
|
*/
|
|
void *mallocstrcpy(char *dest, char *src)
|
|
{
|
|
|
|
|
|
if (src == dest)
|
|
return src;
|
|
|
|
if (dest != NULL)
|
|
free(dest);
|
|
|
|
if (src == NULL) {
|
|
dest = NULL;
|
|
return(dest);
|
|
}
|
|
|
|
dest = charalloc(strlen(src) + 1);
|
|
strcpy(dest, src);
|
|
|
|
return dest;
|
|
}
|
|
|
|
|
|
/* Append a new magic-line to filebot */
|
|
void new_magicline(void)
|
|
{
|
|
filebot->next = nmalloc(sizeof(filestruct));
|
|
filebot->next->data = charalloc(1);
|
|
filebot->next->data[0] = '\0';
|
|
filebot->next->prev = filebot;
|
|
filebot->next->next = NULL;
|
|
filebot->next->lineno = filebot->lineno + 1;
|
|
filebot = filebot->next;
|
|
totlines++;
|
|
totsize++;
|
|
}
|
|
|
|
#ifndef DISABLE_TABCOMP
|
|
/*
|
|
* Routine to see if a text string is matched by a wildcard pattern.
|
|
* Returns TRUE if the text is matched, or FALSE if it is not matched
|
|
* or if the pattern is invalid.
|
|
* * matches zero or more characters
|
|
* ? matches a single character
|
|
* [abc] matches 'a', 'b' or 'c'
|
|
* \c quotes character c
|
|
* Adapted from code written by Ingo Wilken, and
|
|
* then taken from sash, Copyright (c) 1999 by David I. Bell
|
|
* Permission is granted to use, distribute, or modify this source,
|
|
* provided that this copyright notice remains intact.
|
|
* Permission to distribute this code under the GPL has been granted.
|
|
*/
|
|
int check_wildcard_match(const char *text, const char *pattern)
|
|
{
|
|
const char *retryPat;
|
|
const char *retryText;
|
|
int ch;
|
|
int found;
|
|
int len;
|
|
|
|
retryPat = NULL;
|
|
retryText = NULL;
|
|
|
|
while (*text || *pattern) {
|
|
ch = *pattern++;
|
|
|
|
switch (ch) {
|
|
case '*':
|
|
retryPat = pattern;
|
|
retryText = text;
|
|
break;
|
|
|
|
case '[':
|
|
found = FALSE;
|
|
|
|
while ((ch = *pattern++) != ']') {
|
|
if (ch == '\\')
|
|
ch = *pattern++;
|
|
|
|
if (ch == '\0')
|
|
return FALSE;
|
|
|
|
if (*text == ch)
|
|
found = TRUE;
|
|
}
|
|
len = strlen(text);
|
|
if (found == FALSE && len != 0) {
|
|
return FALSE;
|
|
}
|
|
if (found == TRUE) {
|
|
if (strlen(pattern) == 0 && len == 1) {
|
|
return TRUE;
|
|
}
|
|
if (len != 0) {
|
|
text++;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/* fall into next case */
|
|
|
|
case '?':
|
|
if (*text++ == '\0')
|
|
return FALSE;
|
|
|
|
break;
|
|
|
|
case '\\':
|
|
ch = *pattern++;
|
|
|
|
if (ch == '\0')
|
|
return FALSE;
|
|
|
|
/* fall into next case */
|
|
|
|
default:
|
|
if (*text == ch) {
|
|
if (*text)
|
|
text++;
|
|
break;
|
|
}
|
|
|
|
if (*text) {
|
|
pattern = retryPat;
|
|
text = ++retryText;
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (pattern == NULL)
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
#endif
|