Split nano.c up more

git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@27 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
master
Chris Allegretta 2000-06-19 04:22:15 +00:00
parent b0b367e05d
commit bceb1b21a6
8 changed files with 1133 additions and 1003 deletions

View File

@ -1,9 +1,12 @@
bin_PROGRAMS = nano
nano_SOURCES = cut.c \
files.c \
global.c \
move.c \
nano.c \
nano.h \
proto.h \
search.c \
utils.c \
winio.c

View File

@ -88,7 +88,7 @@ VERSION = @VERSION@
l = @l@
bin_PROGRAMS = nano
nano_SOURCES = cut.c global.c nano.c nano.h proto.h utils.c winio.c
nano_SOURCES = cut.c files.c global.c move.c nano.c nano.h proto.h search.c utils.c winio.c
man_MANS = nano.1
@ -112,7 +112,8 @@ DEFS = @DEFS@ -I. -I$(srcdir) -I.
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
nano_OBJECTS = cut.o global.o nano.o utils.o winio.o
nano_OBJECTS = cut.o files.o global.o move.o nano.o search.o utils.o \
winio.o
nano_DEPENDENCIES =
nano_LDFLAGS =
CFLAGS = @CFLAGS@
@ -398,7 +399,7 @@ distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \

470
files.c Normal file
View File

@ -0,0 +1,470 @@
/**************************************************************************
* files.c *
* *
* Copyright (C) 1999 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 1, 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 <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include "config.h"
#include "proto.h"
#include "nano.h"
#ifndef NANO_SMALL
#include <libintl.h>
#define _(string) gettext(string)
#else
#define _(string) (string)
#endif
/* Load file into edit buffer - takes data from file struct */
void load_file(void)
{
current = fileage;
wmove(edit, current_y, current_x);
}
/* What happens when there is no file to open? aiee! */
void new_file(void)
{
fileage = nmalloc(sizeof(filestruct));
fileage->data = nmalloc(1);
strcpy(fileage->data, "");
fileage->prev = NULL;
fileage->next = NULL;
fileage->lineno = 1;
filebot = fileage;
edittop = fileage;
editbot = fileage;
current = fileage;
totlines = 1;
UNSET(VIEW_MODE);
}
int read_byte(int fd, char *filename, char *input)
{
static char buf[BUFSIZ];
static int index = 0;
static int size = 0;
if (index == size) {
index = 0;
size = read(fd, buf, BUFSIZ);
if (size == -1) {
clear();
refresh();
resetty();
endwin();
perror(filename);
}
if (!size)
return 0;
}
*input = buf[index++];
return 1;
}
filestruct *read_line(char *buf, filestruct * prev, int *line1ins)
{
filestruct *fileptr;
fileptr = nmalloc(sizeof(filestruct));
fileptr->data = nmalloc(strlen(buf) + 2);
strcpy(fileptr->data, buf);
if (*line1ins) {
/* Special case, insert with cursor on 1st line. */
fileptr->prev = NULL;
fileptr->next = fileage;
fileptr->lineno = 1;
*line1ins = 0;
/* If we're inserting into the first line of the file, then
we want to make sure that our edit buffer stays on the
first line (and that fileage stays up to date!) */
fileage = fileptr;
edittop = fileptr;
} else if (fileage == NULL) {
fileage = fileptr;
fileage->lineno = 1;
fileage->next = fileage->prev = NULL;
fileptr = filebot = fileage;
} else if (prev) {
fileptr->prev = prev;
fileptr->next = NULL;
fileptr->lineno = prev->lineno + 1;
prev->next = fileptr;
} else {
die(_("read_line: not on first line and prev is NULL"));
}
return fileptr;
}
int read_file(int fd, char *filename)
{
long size, lines = 0, linetemp = 0;
char input[2]; /* buffer */
char *buf;
long i = 0, bufx = 128;
filestruct *fileptr = current, *tmp = NULL;
int line1ins = 0;
buf = nmalloc(bufx);
if (fileptr != NULL && fileptr->prev != NULL) {
fileptr = fileptr->prev;
tmp = fileptr;
} else if (fileptr != NULL && fileptr->prev == NULL) {
tmp = fileage;
current = fileage;
line1ins = 1;
}
input[1] = 0;
/* Read the entire file into file struct */
while ((size = read_byte(fd, filename, input)) > 0) {
linetemp = 0;
if (input[0] == '\n') {
fileptr = read_line(buf, fileptr, &line1ins);
lines++;
buf[0] = 0;
i = 0;
} else {
/* Now we allocate a bigger buffer 128 characters at a time.
If we allocate a lot of space for one line, we may indeed
have to use a buffer this big later on, so we don't
decrease it at all. We do free it at the end though. */
if (i >= bufx - 1) {
buf = nrealloc(buf, bufx + 128);
bufx += 128;
}
buf[i] = input[0];
buf[i + 1] = 0;
i++;
}
totsize += size;
}
/* Did we not get a newline but still have stuff to do? */
if (buf[0]) {
fileptr = read_line(buf, fileptr, &line1ins);
lines++;
buf[0] = 0;
}
/* Did we even GET a file? */
if (totsize == 0) {
new_file();
statusbar(_("Read %d lines"), lines);
return 1;
}
if (current != NULL) {
fileptr->next = current;
current->prev = fileptr;
renumber(current);
current_x = 0;
placewewant = 0;
} else if (fileptr->next == NULL) {
filebot = fileptr;
load_file();
}
statusbar(_("Read %d lines"), lines);
totlines += lines;
free(buf);
close(fd);
return 1;
}
/* Open the file (and decide if it exists) */
int open_file(char *filename, int insert, int quiet)
{
int fd;
struct stat fileinfo;
if (!strcmp(filename, "") || stat(filename, &fileinfo) == -1) {
if (insert) {
if (!quiet)
statusbar(_("\"%s\" not found"), filename);
return -1;
} else {
/* We have a new file */
statusbar(_("New File"));
new_file();
}
} else if ((fd = open(filename, O_RDONLY)) == -1) {
if (!quiet)
statusbar("%s: %s", strerror(errno), filename);
return -1;
} else { /* File is A-OK */
if (S_ISDIR(fileinfo.st_mode)) {
statusbar(_("File \"%s\" is a directory"), filename);
new_file();
return -1;
}
if (!quiet)
statusbar(_("Reading File"));
read_file(fd, filename);
}
return 1;
}
int do_insertfile(void)
{
int i;
wrap_reset();
i = statusq(writefile_list, WRITEFILE_LIST_LEN, "",
_("File to insert [from ./] "));
if (i != -1) {
#ifdef DEBUG
fprintf(stderr, "filename is %s", answer);
#endif
i = open_file(answer, 1, 0);
dump_buffer(fileage);
set_modified();
/* Here we want to rebuild the edit window */
for(i = 0, editbot = edittop;
i <= editwinrows - 1
&& i <= totlines
&& editbot->next != NULL;
editbot = editbot->next, i++);
/* If we've gone off the bottom, recenter, otherwise just redraw */
if(current->lineno > editbot->lineno)
edit_update(current);
else
edit_refresh();
UNSET(KEEP_CUTBUFFER);
display_main_list();
return i;
} else {
statusbar(_("Cancelled"));
UNSET(KEEP_CUTBUFFER);
display_main_list();
return 0;
}
}
/*
* Write a file out. If tmp is nonzero, we set the umask to 0600,
* we don't set the global variable filename to it's name, and don't
* print out how many lines we wrote on the statusbar.
*
* Note that tmp is only set to 1 for storing temporary files internal
* to the editor, and is completely different from temp_opt.
*/
int write_file(char *name, int tmp)
{
long size, lineswritten = 0;
char buf[PATH_MAX + 1];
filestruct *fileptr;
int fd, mask = 0;
struct stat st;
if (!strcmp(name, "")) {
statusbar(_("Cancelled"));
return -1;
}
titlebar();
fileptr = fileage;
/* Open the file and truncate it. Trust the symlink. */
if (ISSET(FOLLOW_SYMLINKS) && !tmp) {
if ((fd = open(name, O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH |
S_IWOTH)) == -1) {
statusbar(_("Could not open file for writing: %s"),
strerror(errno));
return -1;
}
}
/* Don't follow symlink. Create new file. */
else {
if (strlen(name) > (PATH_MAX - 7)) {
statusbar(_("Could not open file: Path length exceeded."));
return -1;
}
memset(buf, 0x00, PATH_MAX + 1);
strcat(buf, name);
strcat(buf, ".XXXXXX");
if ((fd = mkstemp(buf)) == -1) {
statusbar(_("Could not open file for writing: %s"),
strerror(errno));
return -1;
}
}
dump_buffer(fileage);
while (fileptr != NULL && fileptr->next != NULL) {
size = write(fd, fileptr->data, strlen(fileptr->data));
if (size == -1) {
statusbar(_("Could not open file for writing: %s"),
strerror(errno));
return -1;
} else {
#ifdef DEBUG
fprintf(stderr, _("Wrote >%s\n"), fileptr->data);
#endif
}
write(fd, "\n", 1);
fileptr = fileptr->next;
lineswritten++;
}
if (fileptr != NULL) {
size = write(fd, fileptr->data, strlen(fileptr->data));
if (size == -1) {
statusbar(_("Could not open file for writing: %s"),
strerror(errno));
return -1;
} else if (size > 0) {
size = write(fd, "\n", 1);
if (size == -1) {
statusbar(_("Could not open file for writing: %s"),
strerror(errno));
return -1;
}
}
}
if (close(fd) == -1) {
statusbar(_("Could not close %s: %s"), name, strerror(errno));
unlink(buf);
return -1;
}
if (!ISSET(FOLLOW_SYMLINKS) || tmp) {
if (stat(name, &st) == -1) {
/* Use default umask as file permisions if file is a new file. */
mask = umask(0);
umask(mask);
if (tmp) /* We don't want anyone reading our temporary file! */
mask = 0600;
else
mask = 0666 & ~mask;
} else {
/* Use permissions from file we are overwriting. */
mask = st.st_mode;
if (unlink(name) == -1) {
if (errno != ENOENT) {
statusbar(_("Could not open %s for writing: %s"),
name, strerror(errno));
unlink(buf);
return -1;
}
}
}
if (link(buf, name) != -1)
unlink(buf);
else if (errno != EPERM) {
statusbar(_("Could not open %s for writing: %s"),
name, strerror(errno));
unlink(buf);
return -1;
} else if (rename(buf, name) == -1) { /* Try a rename?? */
statusbar(_("Could not open %s for writing: %s"),
name, strerror(errno));
unlink(buf);
return -1;
}
if (chmod(name, mask) == -1) {
statusbar(_("Could not set permissions %o on %s: %s"),
mask, name, strerror(errno));
}
}
if (!tmp) {
strncpy(filename, name, 132);
statusbar(_("Wrote %d lines"), lineswritten);
}
UNSET(MODIFIED);
titlebar();
return 1;
}
int do_writeout(int exiting)
{
int i = 0;
strncpy(answer, filename, 132);
if ((exiting) && (temp_opt) && (filename)) {
i = write_file(answer, 0);
display_main_list();
return i;
}
while (1) {
i = statusq(writefile_list, WRITEFILE_LIST_LEN, answer,
_("File Name to write"));
if (i != -1) {
#ifdef DEBUG
fprintf(stderr, _("filename is %s"), answer);
#endif
if (strncmp(answer, filename, 132)) {
struct stat st;
if (!stat(answer, &st)) {
i = do_yesno(0, 0, _("File exists, OVERWRITE ?"));
if (!i || (i == -1))
continue;
}
}
i = write_file(answer, 0);
display_main_list();
return i;
} else {
statusbar(_("Cancelled"));
display_main_list();
return 0;
}
}
}
int do_writeout_void(void)
{
return do_writeout(0);
}

195
move.c Normal file
View File

@ -0,0 +1,195 @@
/**************************************************************************
* move.c *
* *
* Copyright (C) 1999 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 1, 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 <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "config.h"
#include "proto.h"
#include "nano.h"
#ifndef NANO_SMALL
#include <libintl.h>
#define _(string) gettext(string)
#else
#define _(string) (string)
#endif
void page_down_center(void)
{
if (editbot->next != NULL && editbot->next != filebot) {
edit_update(editbot->next);
center_cursor();
} else if (editbot != filebot) {
edit_update(editbot);
center_cursor();
} else {
while (current != filebot)
current = current->next;
edit_update(current);
}
update_cursor();
}
int page_down(void)
{
wrap_reset();
current_x = 0;
placewewant = 0;
if (current == filebot)
return 0;
if (editbot != filebot) {
current_y = 0;
current = editbot;
} else
while (current != filebot) {
current = current->next;
current_y++;
}
edit_update_top(current);
update_cursor();
UNSET(KEEP_CUTBUFFER);
check_statblank();
return 1;
}
int do_home(void)
{
current_x = 0;
placewewant = 0;
update_line(current, current_x);
return 1;
}
int do_end(void)
{
current_x = strlen(current->data);
placewewant = xplustabs();
update_line(current, current_x);
return 1;
}
/* What happens when we want to go past the bottom of the buffer */
int do_down(void)
{
wrap_reset();
if (current->next != NULL) {
update_line(current->prev, 0);
if (placewewant > 0)
current_x = actual_x(current->next, placewewant);
if (current_x > strlen(current->next->data))
current_x = strlen(current->next->data);
} else {
UNSET(KEEP_CUTBUFFER);
check_statblank();
return 0;
}
if (current_y < editwinrows - 1 && current != editbot)
current_y++;
else
page_down_center();
update_cursor();
update_line(current->prev, 0);
update_line(current, current_x);
UNSET(KEEP_CUTBUFFER);
check_statblank();
return 1;
}
void page_up_center(void)
{
if (edittop != fileage) {
edit_update(edittop);
center_cursor();
} else
current_y = 0;
update_cursor();
}
int do_up(void)
{
wrap_reset();
if (current->prev != NULL) {
update_line(current, 0);
if (placewewant > 0)
current_x = actual_x(current->prev, placewewant);
if (current_x > strlen(current->prev->data))
current_x = strlen(current->prev->data);
}
if (current_y > 0)
current_y--;
else
page_up_center();
update_cursor();
update_line(current->next, 0);
update_line(current, current_x);
UNSET(KEEP_CUTBUFFER);
check_statblank();
return 1;
}
int do_right(void)
{
if (current_x < strlen(current->data)) {
current_x++;
} else {
if (do_down())
current_x = 0;
}
placewewant = xplustabs();
update_cursor();
update_line(current, current_x);
UNSET(KEEP_CUTBUFFER);
check_statblank();
return 1;
}
int do_left(void)
{
if (current_x > 0)
current_x--;
else if (current != fileage) {
placewewant = 0;
current_x = strlen(current->prev->data);
do_up();
}
placewewant = xplustabs();
update_cursor();
update_line(current, current_x);
UNSET(KEEP_CUTBUFFER);
check_statblank();
return 1;
}

1006
nano.c

File diff suppressed because it is too large Load Diff

16
proto.h
View File

@ -58,6 +58,16 @@ int write_file(char *name, int tmpfile);
int do_cut_text(void);
int do_uncut_text(void);
int no_help(void);
int renumber_all(void);
int open_file(char *filename, int insert, int quiet);
int do_writeout(int exiting);
int do_gotoline(long defline);
/* Now in move.c */
int do_up(void);
int do_down(void);
int do_left(void);
int do_right(void);
void shortcut_init(void);
void lowercase(char *src);
@ -86,6 +96,12 @@ void *nmalloc (size_t howmuch);
void wrap_reset(void);
void display_main_list(void);
void nano_small_msg(void);
void do_early_abort(void);
void *nmalloc(size_t howmuch);
void *nrealloc(void *ptr, size_t howmuch);
void die(char *msg, ...);
void new_file(void);
int do_writeout_void(void), do_exit(void), do_gotoline_void(void);
int do_insertfile(void), do_search(void), page_up(void), page_down(void);

408
search.c Normal file
View File

@ -0,0 +1,408 @@
/**************************************************************************
* search.c *
* *
* Copyright (C) 2000 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 1, 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 <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "config.h"
#include "proto.h"
#include "nano.h"
#ifndef NANO_SMALL
#include <libintl.h>
#define _(string) gettext(string)
#else
#define _(string) (string)
#endif
/* Set up the system variables for a search or replace. Returns -1 on
abort, 0 on success, and 1 on rerun calling program
Return -2 to run opposite program (searchg -> replace, replace -> search)
replacing = 1 if we call from do_replace, 0 if called from do_search func.
*/
int search_init(int replacing)
{
int i;
char buf[135];
if (last_search[0]) {
sprintf(buf, " [%s]", last_search);
} else {
buf[0] = '\0';
}
i = statusq(replacing ? replace_list : whereis_list,
replacing ? REPLACE_LIST_LEN : WHEREIS_LIST_LEN, "",
ISSET(CASE_SENSITIVE) ? _("Case Sensitive Search%s") :
_("Search%s"), buf);
/* Cancel any search, or just return with no previous search */
if ((i == -1) || (i < 0 && !last_search[0])) {
statusbar(_("Search Cancelled"));
reset_cursor();
return -1;
} else if (i == -2) { /* Same string */
strncpy(answer, last_search, 132);
} else if (i == 0) { /* They entered something new */
strncpy(last_search, answer, 132);
/* Blow away last_replace because they entered a new search
string....uh, right? =) */
last_replace[0] = '\0';
} else if (i == NANO_CASE_KEY) { /* They want it case sensitive */
if (ISSET(CASE_SENSITIVE))
UNSET(CASE_SENSITIVE);
else
SET(CASE_SENSITIVE);
return 1;
} else if (i == NANO_OTHERSEARCH_KEY) {
return -2; /* Call the opposite search function */
} else { /* First line key, etc. */
do_early_abort();
return -3;
}
return 0;
}
filestruct *findnextstr(int quiet, filestruct * begin, char *needle)
{
filestruct *fileptr;
char *searchstr, *found = NULL, *tmp;
fileptr = current;
searchstr = &current->data[current_x + 1];
/* Look for searchstr until EOF */
while (fileptr != NULL &&
(found = strstrwrapper(searchstr, needle)) == NULL) {
fileptr = fileptr->next;
if (fileptr == begin)
return NULL;
if (fileptr != NULL)
searchstr = fileptr->data;
}
/* If we're not at EOF, we found an instance */
if (fileptr != NULL) {
current = fileptr;
current_x = 0;
for (tmp = fileptr->data; tmp != found; tmp++)
current_x++;
edit_update(current);
reset_cursor();
} else { /* We're at EOF, go back to the top, once */
fileptr = fileage;
while (fileptr != current && fileptr != begin &&
(found = strstrwrapper(fileptr->data, needle)) == NULL)
fileptr = fileptr->next;
if (fileptr == begin) {
if (!quiet)
statusbar(_("\"%s\" not found"), needle);
return NULL;
}
if (fileptr != current) { /* We found something */
current = fileptr;
current_x = 0;
for (tmp = fileptr->data; tmp != found; tmp++)
current_x++;
edit_update(current);
reset_cursor();
if (!quiet)
statusbar(_("Search Wrapped"));
} else { /* Nada */
if (!quiet)
statusbar(_("\"%s\" not found"), needle);
return NULL;
}
}
return fileptr;
}
void search_abort(void)
{
UNSET(KEEP_CUTBUFFER);
display_main_list();
wrefresh(bottomwin);
}
/* Search for a string */
int do_search(void)
{
int i;
filestruct *fileptr = current;
wrap_reset();
if ((i = search_init(0)) == -1) {
current = fileptr;
search_abort();
return 0;
} else if (i == -3) {
search_abort();
return 0;
} else if (i == -2) {
search_abort();
do_replace();
return 0;
} else if (i == 1) {
do_search();
search_abort();
return 1;
}
findnextstr(0, current, answer);
search_abort();
return 1;
}
void print_replaced(int num)
{
if (num > 1)
statusbar(_("Replaced %d occurences"), num);
else if (num == 1)
statusbar(_("Replaced 1 occurence"));
}
void replace_abort(void)
{
UNSET(KEEP_CUTBUFFER);
display_main_list();
reset_cursor();
}
/* Search for a string */
int do_replace(void)
{
int i, replaceall = 0, numreplaced = 0, beginx;
filestruct *fileptr, *begin;
char *tmp, *copy, prevanswer[132] = "";
if ((i = search_init(1)) == -1) {
statusbar(_("Replace Cancelled"));
replace_abort();
return 0;
} else if (i == 1) {
do_replace();
return 1;
} else if (i == -2) {
replace_abort();
do_search();
return 0;
} else if (i == -3) {
replace_abort();
return 0;
}
strncpy(prevanswer, answer, 132);
if (strcmp(last_replace, "")) { /* There's a previous replace str */
i = statusq(replace_list, REPLACE_LIST_LEN, "",
_("Replace with [%s]"), last_replace);
if (i == -1) { /* Aborted enter */
strncpy(answer, last_replace, 132);
statusbar(_("Replace Cancelled"));
replace_abort();
return 0;
} else if (i == 0) /* They actually entered something */
strncpy(last_replace, answer, 132);
else if (i == NANO_CASE_KEY) { /* They asked for case sensitivity */
if (ISSET(CASE_SENSITIVE))
UNSET(CASE_SENSITIVE);
else
SET(CASE_SENSITIVE);
do_replace();
return 0;
} else { /* First page, last page, for example could get here */
do_early_abort();
replace_abort();
return 0;
}
} else { /* last_search is empty */
i = statusq(replace_list, REPLACE_LIST_LEN, "", _("Replace with"));
if (i == -1) {
statusbar(_("Replace Cancelled"));
reset_cursor();
replace_abort();
return 0;
} else if (i == 0) /* They entered something new */
strncpy(last_replace, answer, 132);
else if (i == NANO_CASE_KEY) { /* They want it case sensitive */
if (ISSET(CASE_SENSITIVE))
UNSET(CASE_SENSITIVE);
else
SET(CASE_SENSITIVE);
do_replace();
return 1;
} else { /* First line key, etc. */
do_early_abort();
replace_abort();
return 0;
}
}
/* save where we are */
begin = current;
beginx = current_x;
while (1) {
if (replaceall)
fileptr = findnextstr(1, begin, prevanswer);
else
fileptr = findnextstr(0, begin, prevanswer);
/* No more matches. Done! */
if (!fileptr)
break;
/* If we're here, we've found the search string */
if (!replaceall)
i = do_yesno(1, 1, _("Replace this instance?"));
if (i > 0 || replaceall) { /* Yes, replace it!!!! */
if (i == 2)
replaceall = 1;
/* Create buffer */
copy = nmalloc(strlen(current->data) - strlen(last_search) +
strlen(last_replace) + 1);
/* Head of Original Line */
strncpy(copy, current->data, current_x);
copy[current_x] = 0;
/* Replacement Text */
strcat(copy, last_replace);
/* The tail of the original line */
/* This may expose other bugs, because it no longer
goes through each character on the string
and tests for string goodness. But because
we can assume the invariant that current->data
is less than current_x + strlen(last_search) long,
this should be safe. Or it will expose bugs ;-) */
tmp = current->data + current_x + strlen(last_search);
strcat(copy, tmp);
/* Cleanup */
free(current->data);
current->data = copy;
/* Stop bug where we replace a substring of the replacement text */
current_x += strlen(last_replace);
edit_refresh();
set_modified();
numreplaced++;
} else if (i == -1) /* Abort, else do nothing and continue loop */
break;
}
current = begin;
current_x = beginx;
renumber_all();
edit_update(current);
print_replaced(numreplaced);
replace_abort();
return 1;
}
void goto_abort(void)
{
UNSET(KEEP_CUTBUFFER);
display_main_list();
}
int do_gotoline(long defline)
{
long line, i = 1, j = 0;
filestruct *fileptr;
if (defline > 0) /* We already know what line we want to go to */
line = defline;
else { /* Ask for it */
j = statusq(goto_list, GOTO_LIST_LEN, "", _("Enter line number"));
if (j == -1) {
statusbar(_("Aborted"));
goto_abort();
return 0;
} else if (j != 0) {
do_early_abort();
goto_abort();
return 0;
}
if (!strcmp(answer, "$")) {
current = filebot;
current_x = 0;
edit_update(current);
goto_abort();
return 1;
}
line = atoi(answer);
}
/* Bounds check */
if (line <= 0) {
statusbar(_("Come on, be reasonable"));
goto_abort();
return 0;
}
if (line > totlines) {
statusbar(_("Only %d lines available, skipping to last line"),
filebot->lineno);
current = filebot;
current_x = 0;
edit_update(current);
} else {
for (fileptr = fileage; fileptr != NULL && i < line; i++)
fileptr = fileptr->next;
current = fileptr;
current_x = 0;
edit_update(current);
}
goto_abort();
return 1;
}
int do_gotoline_void(void)
{
return do_gotoline(0);
}

31
utils.c
View File

@ -26,6 +26,13 @@
#include "nano.h"
#include "proto.h"
#ifndef NANO_SMALL
#include <libintl.h>
#define _(string) gettext(string)
#else
#define _(string) (string)
#endif
/* Lower case a string - must be null terminated */
void lowercase(char *src)
{
@ -79,3 +86,27 @@ char *strstrwrapper(char *haystack, char *needle)
else
return strcasestr(haystack, needle);
}
/* 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;
}
void *nrealloc(void *ptr, size_t howmuch)
{
void *r;
if (!(r = realloc(ptr, howmuch)))
die("nano: realloc: out of memory!");
return r;
}