[comp.sources.misc] v05i082: rsed -- simple in-core editor

doug@letni.UUCP (Doug Davis at letni.UUCP) (12/14/88)

Posting-number: Volume 5, Issue 82
Submitted-by: "Doug Davis at letni.UUCP" <doug@letni.UUCP>
Archive-name: rsed

The attached shar file is source of a simple user-friendly(?) text file
editor that I was commissioned to write for a bunch of computer illiterate's
to edit mail messages.  The editor makes use of an in-memory linked list
for storing each line, this gives it the ability to edit any size text
file that a machine has user process space for.  I'm sending it to
you to post, mostly because it shows a good simple example of using a linked
list, as well as in the hopes that someone will take it further along 
the evolutionary scale, and perhaps turn it into a real editor.

As usual I will gladly accept all of patches for suggested changes
or porting problems. Flames however will cheerfully be ignored.

Doug Davis
Lawnet
1030 Pleasent Valley Lane
Arlington Texas 76015
(817)-467-3740

{ killer!texbell, sys1.tandy.com, lawnet, motown!sys1 } letni!doug


#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  README rsedhelp Makefile defs.h externs.h command.c edit.c
#   find.c globals.c input.c main.c mem.c multi.c stuff.c
# Wrapped by doug@letni on Mon Dec 12 02:07:29 1988
PATH=/bin:/usr/bin:/usr/local/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(3961 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X
Real Simple Ed 
X
Rsed is a real simple editor program designed for people who are calling
into a machine to be able to edit files on a variaty of differen't 
terminals and/or computers WITHOUT haveing to learn an editor.  Rsed
is very easy to use and tries to be as "user friendly" as possable.
X
Defines:
WSEDHELP          Where the help file resieds.
MAXREPLACE        malloc size for the replacement string
BEGINDOTS         size of file to warrent nifty-userfriendly dots to show
X                  that we are doing something.
X
Options:
X    -a ##	load file and append after line ##
X    -w 		write the file out when you quit the editor (silent)
X    -D		debug (used for fiddling with the linked list)
X
X
Porting:
X    rsed usese curses just for turning off echo and setting crmod, 
X    if you don't want to fool with that, or don't have curses you will
X    have to fix up your own terminal handler. The following are the
X    function calls to worry about.
X    	savetty() save the current modes of the terminal for later recall
X    	initscr() sets up curses.
X    	crmode()  puts the terminal into One Charicter At A Time mode.
X    	resetty() restores the previously saved tty information.
X	
X    rsed also uses getopt() most later version unix's have this, if
X    yours does not, a public domain version of it is available thru
X    comp.sources.unix.
X    
X    Othewise rsed has been known to compile without changes on 4.1 BSD (vax),
X    4.2 BSD (vax) 4.3 BSD (vax), Ultrix (vax) sco (%d86) micro, Tandy 6000,
X    Masscomp, NCR tower, ATT 3b2 and a logic processes Mpulse. So it ought
X    to compile on yours.  If your compiler can't handle macros you will
X    need to work on the RANGE marco in multi.c.  Otherwise
X    please let me know of any problems and may the source be with you %s.
X
X
Author:
X    Douglas L. Davis
X    (Lawnet, Texas R&D office)
X    1030 Pleasent Valley Lane
X    Arlington Texas  76015
X    (817)-467-3740
X    { sys1 || texbell || lawnet }!letni!doug
X    
X
XFunction call        Description
main            Main routine, parses args, calls edit.
add             adds a char array below line number specified.
append          asks user for lines to add().
boom            debug sigint routine.
change          asks user for a replacement line.
clear_stuff     frees the entire linked list.
command         does the command prompting
edit            if nessasary creates the file, then loads it.
find            returns a line with a pre-specified string
getline         returns a LINE pointer for the specified line number.
getlineno       gets a line number from the tty.
getstring       gets a string from the tty.
global_replace  replaces a specified string with another full file.
go_fish         asks user for a search string then calls find with it.
go_global       asks user for a search string and a replacement string.
help            concatinate the rsedhelp file.
insert          asks user for a line.
loadem          reads a file into the editor buffer.
makenum         convert a string to a numeric entry.
printline       prints a line out of the editor.
replace         replace the text of a specified line with a user buf
reset_find      clears the global search stuff.
saveem          saves the editor buf to a file.
setfind         sets up the global search stuff.
setline         set the current line to a specified line number.
srch_n_replace  do a search / replace within a (LINE *) struct
srchrep         user interface for srch_n_replace.
strappend       like strcat() but returns then end of it's string.
strindex        returns a pointer to a string found in another string.
subtract        removes a spacified line from the buffer.
yesno           asks for a yes or no answer from the user.
multi_print     ask for starting line / ending line then for()'s printline()
multi_delete    ask for starting line / ending line then for()'s subtract()
multi_change    ask for starting line / ending line then for()'s change()
END_OF_FILE
if test 3961 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'rsedhelp' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rsedhelp'\"
else
echo shar: Extracting \"'rsedhelp'\" \(1086 characters\)
sed "s/^X//" >'rsedhelp' <<'END_OF_FILE'
X
X  Keys             Action
X ------          ---------
X [0-9]  .........change the current line.
X   $    .........go to the bottom of the file.
X   ^    .........go to the top of the file.
X+ or ;  .........advance to the next line.
X   -    .........backup to the previous line.
X   a    .........append text after the current line.
X   c    .........change (i.e. replace) the current line.
X   d    .........delete (i.e. remove) the current line.
f or /  .........find and advance to a line with a specified string.
X   g    .........global replacement (entire file) of a string with another.
X   i    .........insert text before the current line.
X   n    .........advance to the next occurence of a string (re: f option)
X   p    .........print (i.e. display) the current line.
X   q    .........quit the editor.
X   s    .........search and replace a string on the current line.
X   w    .........write out all changes.
X   P    .........asks for and then prints a range of lines.
X   ?    .........display this file.
X
Note: input(s) can be ended or aborted by entering a '.' on a line by itself.
END_OF_FILE
if test 1086 -ne `wc -c <'rsedhelp'`; then
    echo shar: \"'rsedhelp'\" unpacked with wrong size!
fi
# end of 'rsedhelp'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(960 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# in an '86 environment this better be compiled in large model
SHELL=/bin/sh
X
X# defines for curses that needs termcap BSD,  xenix,  etc....
X# CURSNAME  = -lcurses -ltermlib
X# CURSNAME	= -lcurses -ltermcap
X# defines for sysV curses needs cbreak() function call.
X# if yours has crmode() instead, you will have to hack defs.h
X# CURSNAME	= -lcurses 
X
X# if your machine has strchr
X# DEFINES=-DSTRCHR=strchr
X# if your machine has index / rindex
X# DEFINES=-DSTRCHR=index
X
X 
X# for 286 uncomment the line below
X# CFLAGS	=	-O -AL $(DEFINES)
X# LDFLAGS =	-AL -i
X# for most other systems
X# CFLAGS	=	-O $(DEFINES)
X# LDFLAGS	=	-n
OBJECTS =	globals.o main.o mem.o command.o edit.o input.o stuff.o \
X		find.o multi.o
CC=/bin/cc
X
all: rsed
X
rsed:	${OBJECTS}
X		$(CC) ${LDFLAGS} ${OBJECTS} -o rsed $(CURSNAME)
X
tags: *.h *.c
X	ctags *.h *.c
X
shar:
X	shar -n 1 -e 1 -t 'Now read the README file and edit the Makefile for your system' \
X		README rsedhelp Makefile *.h *.c > rsed.shar
END_OF_FILE
if test 960 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'defs.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'defs.h'\"
else
echo shar: Extracting \"'defs.h'\" \(984 characters\)
sed "s/^X//" >'defs.h' <<'END_OF_FILE'
X/*
X * This code copyright 1988 by Doug Davis (doug@letni.lawnet.com) 
X *  You are free to modify, hack, fold, spindle, or mutlate this code in
X *  any maner provided you give credit where credit is due and don't pretend
X *  you wrote it.
X *  If you do my lawyers (and I have a lot of lawyers) will teach you a lesson
X *  in copyright law that you will never ever forget.
X */
X#include <sys/types.h>
X#include <signal.h>
X#include <fcntl.h>
X#include <ctype.h>
X#include <sys/stat.h>
X#include <stdio.h>
X#include <errno.h>
X#include "curses.h"
X
X#define WSEDHELP	"/usr/lib/rsedhelp";
X#define	MAXREPLACE	4096 /* biggest tmp line size for global replacement */
X#define	BEGINDOTS	24L * 1024L /* size of file to warrent dots to show
X					that we are doing something */
X
typedef struct line {
X	struct line *previous;
X	struct line *next;
X	char text[1]; /* has to be end */
X} LINE;
X
X#ifndef MSDOS
X	#ifdef CBREAK
X	#define One_Char()	crmode();
X	#else
X	#define One_Char()	cbreak();
X	#endif
X#endif MSDOS
END_OF_FILE
if test 984 -ne `wc -c <'defs.h'`; then
    echo shar: \"'defs.h'\" unpacked with wrong size!
fi
# end of 'defs.h'
fi
if test -f 'externs.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'externs.h'\"
else
echo shar: Extracting \"'externs.h'\" \(1116 characters\)
sed "s/^X//" >'externs.h' <<'END_OF_FILE'
X
X/*
X * This code copyright 1988 by Doug Davis (doug@letni.lawnet.com) 
X *  You are free to modify, hack, fold, spindle, or mutlate this code in
X *  any maner provided you give credit where credit is due and don't pretend
X *  you wrote it.
X *  If you do my lawyers (and I have a lot of lawyers) will teach you a lesson
X *  in copyright law that you will never ever forget.
X */
extern	FILE	*EditFile;
extern	LINE	*current;
extern	LINE	*find_work;
extern	LINE	*getline();
extern	LINE	*l_end;
extern	LINE	*l_start;
extern	LINE	*setline();
extern	char	*Bottom;
extern	char	*Eof;
extern	char	*HelpName;
extern	char	*Progname;
extern	char	*STRCHR();
extern	char	*Top;
extern	char	*find_string;
extern	char	*getstring();
extern	char	*malloc();
extern	char	*strappend();
extern	char	*strindex();
extern	char	Dots;
extern	char	WriteOnQuit;
extern	char	buf[BUFSIZ];
extern	char	yesno();
extern	int	Debug;
extern	int	errno;
extern	int	getopt();
extern	long	CurrentLine;
extern	long	NumberLines;
extern	long	atol();
extern	long	find();
extern	long	find_line;
extern	long	getlineno();
extern	long	loadem();
extern	long	makenum();
END_OF_FILE
if test 1116 -ne `wc -c <'externs.h'`; then
    echo shar: \"'externs.h'\" unpacked with wrong size!
fi
# end of 'externs.h'
fi
if test -f 'command.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'command.c'\"
else
echo shar: Extracting \"'command.c'\" \(4136 characters\)
sed "s/^X//" >'command.c' <<'END_OF_FILE'
X
X/*
X * This code copyright 1988 by Doug Davis (doug@letni.lawnet.com) 
X *  You are free to modify, hack, fold, spindle, or mutlate this code in
X *  any maner provided you give credit where credit is due and don't pretend
X *  you wrote it.
X *  If you do my lawyers (and I have a lot of lawyers) will teach you a lesson
X *  in copyright law that you will never ever forget.
X */
X#include "defs.h"
X#include "externs.h"
X
command(file, sline)
char *file;
char *sline;
X{
X	char c;
X	long start;
X	char changed='N';
X	if (*sline != '\0') {
X		start=makenum(sline);
X		fputs("appending ", stdout);
X		if (start >= NumberLines) 
X			fputs("to the bottom", stdout);
X		else 
X			printf("below line %ld", start);
X		puts(", enter text now:");
X		append(start <= NumberLines ? start : NumberLines);
X		start=NumberLines;
X	} else
X		start = 1L;
X	
X	if (NumberLines > 0L)
X		setline(start);
X	for (;;) {
X		if (NumberLines < 1L || CurrentLine < 1L) {
X			puts("Buffer empty, begin entering new text.");
X			append(0L);
X			continue;
X		}
X		if (Debug) {
X			printf("address             l_start: 0x%lx\n",
X				l_start);
X			printf("address             current: 0x%lx\n",
X				current);
X			printf("address               l_end: 0x%lx\n",
X				l_end);
X			printf("address l_start -> previous: 0x%lx\n", 
X				l_start->previous);
X			printf("address       l_end -> next: 0x%lx\n",
X				l_end->next);
X		}
X		printf("Line %ld>", CurrentLine);
X#ifdef MSDOS
X		c=getch();
X#else 
X		c=getchar();
X#endif MSDOS
X		switch(c) {
X			case '0':
X			case '1':
X			case '2':
X			case '3':
X			case '4':
X			case '5':
X			case '6':
X			case '7':
X			case '8':
X			case '9':
X				fputs("Enter new line :", stdout);
X				getstring(buf, 10, c);
X				if ((start=makenum(buf)) > 0L && 
X						start <= NumberLines) {
X					if (setline(start) == (LINE *) NULL) 
X						puts("Sorry..");
X				}
X				break;
X			case '+':
X			case ';':
X				putchar('\n');
X				if (CurrentLine < NumberLines) {
X					CurrentLine++;
X					printline(CurrentLine);
X				} else
X					puts(Bottom);
X				break;
X			case '-':
X				putchar('\n');
X				if (CurrentLine > 1) {
X					CurrentLine--;
X					printline(CurrentLine);
X				} else 
X					puts(Top);
X				break;
X			case '$':
X				putchar('\n');
X				CurrentLine = NumberLines;
X				setline(CurrentLine);
X				puts(Bottom);
X				break;
X			case '^':
X				putchar('\n');
X				CurrentLine = 1L;
X				setline(CurrentLine);
X				puts(Top);
X				break;
X			case 'C':
X				puts("Change lines.");
X				multi_change();
X				changed = 'Y';
X				break;
X			case 'D':
X				puts("Delete lines.");
X				multi_delete();
X				changed = 'Y';
X				break;
X			case 'P':
X				puts("Print.");
X				multi_print();
X				break;
X			case 'a':
X				printf("Appending after line # %ld\n", CurrentLine);
X				append(CurrentLine);
X				changed = 'Y';
X				break;
X			case 'c':
X				printf("Change line # %ld\n", CurrentLine);
X				change(CurrentLine);
X				changed = 'Y';
X				break;
X			case 'd':
X				printf("Deleted line # %ld\n", CurrentLine);
X				subtract(CurrentLine);
X				changed = 'Y';
X				break;
X			case 'f':
X			case '/':
X				puts("Find string.");
X				go_fish(CurrentLine);
X				break;
X			case 'g':
X				puts("Global.");
X				go_global(CurrentLine);
X				changed = 'Y';
X				break;
X			case 'i':
X				printf("Inserting before line %ld.\n", CurrentLine);
X				insert(CurrentLine);
X				changed = 'Y';
X				break;
X			case 'n': /* next occurence */
X				puts("Next.");
X				find('v');
X				break;
X			case 'p':
X				puts("print.");
X				printline(CurrentLine);
X				break;
X			case 'q':
X				puts("quit.");
X				if (WriteOnQuit == 'Y') {
X					if(saveem(file) == OK) {
X						return(OK);
X					} else {
X						fprintf(stderr, "%s: Write on quit set, but save failed.\n", Progname);
X						WriteOnQuit='N';
X						break;
X					}
X					
X				}
X				if (changed == 'Y') {
X					fputs("File changed, are you sure (y/n) ? ", stdout);
X					c=yesno();
X					if (c == 'N') 
X						break;
X				}
X				return(OK);
X				break;
X			case 's':
X				puts("search/replace");
X				srchrep(CurrentLine);
X				changed = 'Y';
X				break;
X			case 'w':
X				puts("Saveing.");
X				saveem(file);
X				changed = 'N';
X				break;
X			case '?':
X				puts("Help.");
X				help();
X				break;
X			default:
X				puts("? - for help");
X				break;
X				
X		}
X	}
X}
END_OF_FILE
if test 4136 -ne `wc -c <'command.c'`; then
    echo shar: \"'command.c'\" unpacked with wrong size!
fi
# end of 'command.c'
fi
if test -f 'edit.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'edit.c'\"
else
echo shar: Extracting \"'edit.c'\" \(2656 characters\)
sed "s/^X//" >'edit.c' <<'END_OF_FILE'
X
X/*
X * This code copyright 1988 by Doug Davis (doug@letni.lawnet.com) 
X *  You are free to modify, hack, fold, spindle, or mutlate this code in
X *  any maner provided you give credit where credit is due and don't pretend
X *  you wrote it.
X *  If you do my lawyers (and I have a lot of lawyers) will teach you a lesson
X *  in copyright law that you will never ever forget.
X */
X#include "defs.h"
X#include "externs.h"
X
append(number)
long number;
X{
X	puts("Enter a single period on a blank line to return to the editor");
X	for (;;number++) {
X		getstring(buf, BUFSIZ, '\0');
X		if (*buf == '.' && strlen(buf) == 1) 
X			return(OK);
X		add(buf, number);
X	}
X}
X		
change(number)
long number;
X{
X	printf("Currently line %ld looks like:\n", number);
X	printline(number);
X	printf("Type the new line %ld\n", number);
X	getstring(buf, BUFSIZ, '\0');
X	if (*buf == '.' && strlen(buf) == 1)  {
X		puts("Aborted.");
X		return(!OK);
X	}
X	return(replace(number, buf));
X}
srchrep(number)
long number;
X{
X	char old[81], new[81], c='\0';
X	printf("Line %ld looks like :\n", number);
X	printline(number);
X	fputs("     Search string: ", stdout);
X	if (getstring(old, 81, '\0') == NULL)
X		return(!OK);
X	fputs("Replacement string: ", stdout);
X	if (getstring(new, 81, '\0') == NULL)
X		return(!OK);
X	while (c != 'N' && c != 'Y') {
X		fputs("Global replacement? ", stdout);
X		c=getchar();
X		if (islower(c)) 
X			c=toupper(c);
X		if (c == '\n') 
X			c='N';
X		switch(c) {
X			case 'N':
X				puts("No.");
X			break;
X			case 'Y':
X				puts("Yes.");
X			break;
X			case 'Q':
X				return(!OK);
X			break;
X			default:
X				fputs("\007<Y>es, <N>o or <Q>uit please.\n", stdout);
X			break;
X		}
X	}
X	srch_n_replace(number, old, new, c);
X	printline(number);
X	return(OK);
X}
go_fish(number)
long number;
X{
X	char sstring[81];
X	fputs("String to search for : ", stdout);
X	if(getstring(sstring, 80, '\0') == NULL)
X		return(!OK);
X	if (setfind(number, sstring) == OK) 
X		return(find('v') > 0L ? OK : !OK);
X	return(!OK);
X}
go_global(number)
long number;
X{
X	char old[81], new[81];
X	fputs("     Search string: ", stdout);
X	if (getstring(old, 80, '\0') == NULL)
X		return(!OK);
X	fputs("Replacement string: ", stdout);
X	if (getstring(new, 80, '\0') == NULL)
X		return(!OK);
X	return(global_replace(number, old, new));
X}
global_replace(number, old, new)
long number;
char *old, *new;
X{
X	long line, count=0L;
X	if (setfind(number, old) == OK) {
X		while ((line=find('n')) > 0L)  {
X			if (srch_n_replace(line, old, new, 'Y') == OK) 
X				count++;
X		}
X		printf("Replaced \"%s\" with \"%s\" %ld times.\n",
X			old, new, count);
X
X		return(count > 0L ? OK : !OK);
X	}
X	return(!OK);
X}
insert(number)
long number;
X{
X	number--;
X	return(append(number));
X}
END_OF_FILE
if test 2656 -ne `wc -c <'edit.c'`; then
    echo shar: \"'edit.c'\" unpacked with wrong size!
fi
# end of 'edit.c'
fi
if test -f 'find.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'find.c'\"
else
echo shar: Extracting \"'find.c'\" \(1349 characters\)
sed "s/^X//" >'find.c' <<'END_OF_FILE'
X
X/*
X * This code copyright 1988 by Doug Davis (doug@letni.lawnet.com) 
X *  You are free to modify, hack, fold, spindle, or mutlate this code in
X *  any maner provided you give credit where credit is due and don't pretend
X *  you wrote it.
X *  If you do my lawyers (and I have a lot of lawyers) will teach you a lesson
X *  in copyright law that you will never ever forget.
X */
X#include "defs.h"
X#include "externs.h"
X
X#define __FILE__	"find.c"
X
long
find(c)
char c;
X{
X	if (find_work == (LINE *) NULL || find_line >= NumberLines) {
X		puts(Eof);
X		reset_find();
X		return(-1L);
X	}
X	while (find_work != (LINE *) NULL) {
X		if (strindex(find_work->text, find_string) != NULL) {
X			CurrentLine=find_line;
X			if (c == 'v') printline(CurrentLine);
X			find_work = find_work -> next;
X			find_line++;
X			return(CurrentLine);
X		}
X		find_work = find_work -> next;
X		find_line++;
X	}
X	puts(Eof);
X	return(-1L);
X}
reset_find()
X{
X	find_work = l_start;
X	find_line = 1L;
X}
setfind(number, string)
long number;
char *string;
X{
X	if (find_string != NULL)
X		free(find_string);
X	find_string = malloc(strlen(string) + 1);
X	if (find_string == NULL) {
X		fprintf(stderr, "%s: malloc(%d) failed\n", __FILE__,
X				strlen(string));
X		return(!OK);
X	}
X	strcpy(find_string, string);
X	find_line = number;
X	find_work = setline(find_line);
X	return(find_work != (LINE *) NULL ? OK : !OK);
X}
END_OF_FILE
if test 1349 -ne `wc -c <'find.c'`; then
    echo shar: \"'find.c'\" unpacked with wrong size!
fi
# end of 'find.c'
fi
if test -f 'globals.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'globals.c'\"
else
echo shar: Extracting \"'globals.c'\" \(834 characters\)
sed "s/^X//" >'globals.c' <<'END_OF_FILE'
X
X/*
X * This code copyright 1988 by Doug Davis (doug@letni.lawnet.com) 
X *  You are free to modify, hack, fold, spindle, or mutlate this code in
X *  any maner provided you give credit where credit is due and don't pretend
X *  you wrote it.
X *  If you do my lawyers (and I have a lot of lawyers) will teach you a lesson
X *  in copyright law that you will never ever forget.
X */
X#include "defs.h"
X
XFILE	*EditFile;
LINE	*current	= (LINE *) NULL;
LINE	*find_work	= (LINE *) NULL;
LINE	*l_end		= (LINE *) NULL;
LINE	*l_start	= (LINE *) NULL; 
char	*Bottom="Bottom of file.";
char	*Eof="Search ending, bottom of file.";
char	*Progname;
char	*Top="Top of file.";
char	*find_string = NULL;
char	Dots		= 'N';
char	WriteOnQuit	= 'N';
char	buf[BUFSIZ];
int	Debug;
long	CurrentLine;
long	NumberLines;
long	find_line = 1L;
char	*HelpName=WSEDHELP;
END_OF_FILE
if test 834 -ne `wc -c <'globals.c'`; then
    echo shar: \"'globals.c'\" unpacked with wrong size!
fi
# end of 'globals.c'
fi
if test -f 'input.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'input.c'\"
else
echo shar: Extracting \"'input.c'\" \(1511 characters\)
sed "s/^X//" >'input.c' <<'END_OF_FILE'
X
X/*
X * This code copyright 1988 by Doug Davis (doug@letni.lawnet.com) 
X *  You are free to modify, hack, fold, spindle, or mutlate this code in
X *  any maner provided you give credit where credit is due and don't pretend
X *  you wrote it.
X *  If you do my lawyers (and I have a lot of lawyers) will teach you a lesson
X *  in copyright law that you will never ever forget.
X */
X#include "defs.h"
X#include "externs.h"
X
long
getlnum()
X{
X	getstring(buf, 10, '\0');
X	return(makenum(buf));
X}
X
char
yesno()
X{
X	char c;
X	for (;;) {
X#ifdef MSDOS
X		c=getch();
X#else MSDOS
X		c=getchar();
X#endif MSDOS
X		if (islower(c))
X			c=toupper(c);
X		switch (c) {
X			case 'Y':
X				puts("Yes.");
X				return(c);
X			break;
X			case 'N':
X				puts("No.");
X				return(c);
X			break;
X			default:
X				puts("<Y>es or <N>o please.");
X			break;
X		}
X	}
X}
X/*
X *	This routine gets a string..
X *
X */
char *
getstring(str, len, first)
char	*str;
int	len;
char	first;
X{
X	char *p, c;
X	p = str;
X	if (first != '\0')  {
X		*(p++) = first;
X		putchar(first);
X	}		
X	for ( ;; ) {
X#ifdef MSDOS
X		c = getch();
X#else
X		c = getchar();
X#endif MSDOS
X		switch(c) {
X			case '\b': {
X				if (p > str) {
X					*p='\0';
X					fputs("\010 \010", stdout);
X					*(p--)='\0';
X				} else {
X					putchar('\007');
X					}
X				}
X				break;
X			case '\n':
X			case '\r': {
X				*p='\0';
X				putchar('\n');
X				return(*str != '\0' ? str : NULL);
X				} break;
X			default: {
X				if (p < str+len) {
X					*(p++) = c;
X					putchar(c);
X				} else { 
X					putchar('\007');
X				}
X			} break;
X		}
X	}
X}
END_OF_FILE
if test 1511 -ne `wc -c <'input.c'`; then
    echo shar: \"'input.c'\" unpacked with wrong size!
fi
# end of 'input.c'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(2419 characters\)
sed "s/^X//" >'main.c' <<'END_OF_FILE'
X
X/*
X * This code copyright 1988 by Doug Davis (doug@letni.lawnet.com) 
X *  You are free to modify, hack, fold, spindle, or mutlate this code in
X *  any maner provided you give credit where credit is due and don't pretend
X *  you wrote it.
X *  If you do my lawyers (and I have a lot of lawyers) will teach you a lesson
X *  in copyright law that you will never ever forget.
X */
X#include "defs.h"
X#include "externs.h"
X
main(argc, argv)
int argc;
char **argv;
X{
X	int c;
X	char start_line[80];
X	extern char *optarg;
X	extern int optind, opterr;
X	opterr=1;
X	Progname = *argv;
X#ifndef MSDOS
X	savetty();
X	initscr();
X#endif MSDOS
X	signal(SIGINT, SIG_IGN);
X	while ((c=getopt(argc, argv, "Dwa:")) != EOF) {
X		switch (c) {
X		case 'D': Debug = 1;			break;
X		case 'a': strcpy(start_line,optarg);	break;
X		case 'w': WriteOnQuit='Y';		break;
X		}
X	}
X	if (Debug) printf("extra args %d\n", optind);
X	if (argc < 2) {
X		fprintf(stderr, "%s: usage: %s [options] file [ file file]\n",
X				Progname, Progname);
X		exit(-1);
X	}
X	for (;optind < argc; optind++) {
X		errno=0;
X		edit(argv[optind], start_line);
X		*start_line = '\0';
X	}
X	resetty();
X	exit(errno);
X}
X
edit(file, sline)
char *file;
char *sline;
X{
X	struct stat stbuff, *s;
X	char c;
X	int new=!OK;
X	s=(struct stat *) &stbuff;
X	clear_stuff();
X	noecho();
X	One_Char();
X	if ((EditFile=fopen(file, "r")) == (FILE *) NULL) {
X		if (errno == ENOENT) {
X			printf("File %s doesn't exist, create (y/n) ? ",
X				file);
X			c=yesno();
X			switch(c) {
X				case 'Y':
X					close(creat(file, 0666));
X					if ((EditFile=fopen(file, "r")) == (FILE *) NULL) {
X						/* give up... */
X						fprintf(stderr, "%s: could not create %s\n", Progname, file);
X						return(!OK);
X					}
X					new=OK;
X					break;
X				case 'N':
X				default:
X					return(OK);
X					break;	
X			}
X		} else {
X		fprintf(stderr, "%s: Could not read %s",
X			Progname, file);
X			perror("");
X			return(!OK);
X		}
X	}
X	if (fstat(fileno(EditFile), s) < 0) {
X		fprintf(stderr, "%s: fstat(%d) failed",
X			Progname, fileno(EditFile));
X			perror("");
X			return(!OK);
X		}
X	if (s->st_size > BEGINDOTS)
X		Dots = 'Y';
X	if (new != OK && s->st_size > 0L)  {
X		if (loadem(EditFile, 0L) > 0L) {
X			printf("File: \"%s\"   lines=%ld, charicters=%ld\n",
X				file, NumberLines, s->st_size);
X			fclose(EditFile);
X			command(file, sline);
X		}
X	} else {
X		printf("File: \"%s\" is new, begin entering new text\n", file);
X		append(0L);
X		command(file, "\0");
X	}
X	return(OK);
X}
END_OF_FILE
if test 2419 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
fi
# end of 'main.c'
fi
if test -f 'mem.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mem.c'\"
else
echo shar: Extracting \"'mem.c'\" \(5810 characters\)
sed "s/^X//" >'mem.c' <<'END_OF_FILE'
X	
X/*
X * This code copyright 1988 by Doug Davis (doug@letni.lawnet.com) 
X *  You are free to modify, hack, fold, spindle, or mutlate this code in
X *  any maner provided you give credit where credit is due and don't pretend
X *  you wrote it.
X *  If you do my lawyers (and I have a lot of lawyers) will teach you a lesson
X *  in copyright law that you will never ever forget.
X */
X#include "defs.h"
X#include "externs.h"
X
X#define __FILE__	"mem.c"
X
clear_stuff()
X{
X	LINE *temp, *next;
X	if (l_start != (LINE *) NULL) {
X		/* something inside, clear 'em out */
X		for (temp = l_end; temp != l_start ;) {
X			next = temp->previous;
X			free(temp);
X			temp = next;
X		}
X	}
X	l_start = (LINE *) malloc(sizeof(LINE) + 2);
X	l_start -> previous 	= (LINE *) NULL;
X	l_start -> next		= (LINE *) NULL;
X	l_end 			= l_start;
X	current			= l_start;
X	CurrentLine		= 0L;
X	NumberLines		= 0L;
X}
long
loadem(inputfile, place)
XFILE *inputfile;
long place;
X{
X	while ((fgets(buf, BUFSIZ, inputfile)) != NULL) {
X		if(add(buf, place++) != OK) {
X			fprintf(stderr, "%s:%d loadem() add() failure\n", 
X				__FILE__, __LINE__);
X			return(!OK);
X		}
X		if (Dots == 'Y' || Debug) {
X			putchar('.');
X			fflush(stdout);
X		}
X	}
X	putchar('\n');
X	return(NumberLines);
X}
LINE *
setline(number)
long number;
X{
X	LINE *tmp;
X	tmp=getline(number);
X	if (tmp != (LINE *) NULL)  {
X		CurrentLine = number;
X		current = tmp;
X	}
X
X	return(tmp);
X}
LINE *
getline(number)
long number;
X{
X	LINE *inc;
X	long i;
X	if (number > NumberLines) {
X		printf("%s-%s: getline(%ld) > NumberLines == %ld\n",
X			Progname, __FILE__, number, NumberLines);
X		return((LINE *)NULL);
X	}
X	if (number == 0L) 
X		return(l_start);
X	for (i=1L, inc=l_start; i<number ; i++, inc=inc->next);
X	return(inc);
X}
printline(number)
long number;
X{
X	LINE *tmp;
X	if ((tmp=setline(number)) != (LINE *) NULL) {
X		fputs(tmp->text, stdout);
X		fflush(stdout);
X		return(OK);
X	}
X	fprintf(stderr, "%s: printline(%ld) Bad line number\n", __FILE__, number);
X	fflush(stderr);
X	return(!OK);
X}
X
X
X
add(buf, number)
char *buf;
long number;
X{
X	LINE *new, *temp;
X	if (Debug) printf("add(%ld)\n", number);
X	new = (LINE *) malloc(sizeof(LINE) + strlen(buf));
X	if (number > 0L) {
X		temp=getline(number);
X		if (temp == (LINE *) NULL)  {
X			fprintf(stderr, "%s: add(%ld) bad line number\n",
X				__FILE__, number);
X			return(!OK);
X		}
X		new -> previous = temp;
X		if (temp->next != (LINE *) NULL)  {
X			temp->next->previous = new;
X			new -> next = temp->next;
X		} else {
X			new->next = (LINE *) NULL;
X			l_end = new;
X		}
X		temp -> next = new;
X	} else {
X		new -> previous = (LINE *) NULL;
X		if (NumberLines < 1L) {
X			new -> next = (LINE *) NULL;
X			l_end = new;
X		} else 
X			new -> next = l_end;
X
X		/* Now, blow away anything nasty, still hanging around */
X		if (l_start != (LINE *) NULL)
X			free(l_start); 
X
X		l_start = new;
X		current = new;
X	}
X	/* make sure line has a newline on the end.. */
X	if (buf[strlen(buf)-1] != '\n')
X		strcat(buf, "\n");
X	strcpy(new->text, buf);
X	NumberLines++;
X	current=new;
X	CurrentLine=NumberLines;
X	return(OK);
X}
subtract(number)
long number;
X{
X	LINE *tmp;
X	tmp = getline(number);
X	if (tmp == (LINE *)NULL) {
X		fprintf(stderr, "%s: subtract(%ld) bad line number\n", 
X			__FILE__, number);
X		return(!OK);
X	}
X	if (l_end == tmp) {
X		l_end = l_end -> previous;
X	}
X	if (tmp -> previous != (LINE *) NULL) 
X		tmp -> previous -> next = tmp -> next; 
X	 else {
X		if (tmp -> next != (LINE *) NULL) {
X			tmp -> next -> previous = (LINE *) NULL;
X			l_start = tmp -> next;
X		}
X	}
X
X	if (tmp -> next != (LINE *) NULL)
X		tmp -> next -> previous  = tmp -> previous;
X	 else {
X		if (tmp -> previous != (LINE *) NULL) {
X			tmp -> previous -> next = (LINE *) NULL;
X			l_end = tmp -> previous;
X		}
X	}
X	if (NumberLines-- > 1L)
X		free(tmp);
X	current=setline(number < NumberLines ? number : NumberLines);
X	return(current != (LINE *) NULL ? OK : !OK);
X}
X	
replace(number, buf)
char *buf;
long number;
X{
X	LINE *old, *new;
X	old=getline(number);
X	if (old == (LINE *) NULL)  {
X		fprintf(stderr, "%s: replace(%ld) bad line number\n", __FILE__, number);
X		return(!OK);
X	}
X	new = (LINE *) malloc(sizeof(LINE) + strlen(buf));
X	new -> previous		= old -> previous;
X	new -> next		= old -> next;
X	if (new -> previous != (LINE *) NULL)  
X		new -> previous -> next = new;
X	else 
X		l_start = new;
X
X	if (new -> next != (LINE *) NULL)  
X		new -> next -> previous = new;
X	else 
X		l_end = new;
X
X	if (STRCHR(buf, '\n') == NULL)
X		strcat(buf, "\n");
X	strcpy(new->text, buf);
X	free(old);
X	current=setline(number);
X	return(current != (LINE *) NULL ? OK : !OK );
X}
srch_n_replace(number, old_str, new_str, glob)
long number;
char *old_str, *new_str;
char glob;
X{
X	LINE *work;
X	char *p, *b, *buff;
X	int len_old, cnt=0;
X	work = getline(number);
X	if (work == (LINE *) NULL) {
X		fprintf(stderr, "%s: srch_n_replace(%ld) bad line number\n",
X			__FILE__, number);
X		return(!OK);
X	}
X	len_old = strlen(old_str);
X	buff = malloc(MAXREPLACE);
X	if (buff == NULL)
X		return(!OK);
X	p=work->text;
X	b=buff;
X	do {
X		cnt++;
X		if (*p == *old_str)  {
X			if (!strncmp(p, old_str, len_old)) {
X				p += (len_old-1); /* advance past string */
X				b = strappend(b, new_str);
X				if (glob == 'N')  {
X					p++;
X					strcat(b, p);
X					break;
X				}
X			} else
X			*(b++) = *p;
X		} else 
X			*(b++) = *p;
X	} while ((*(p++) != '\0') && cnt < MAXREPLACE);
X	replace(number, buff);
X	free(buff);
X	return(OK);
X}
saveem(file)
char *file;
X{
X	LINE *work;
X	int out;
X	long count=0L;
X	out = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
X	if (out < 0) {
X		fprintf(stderr, "%s: Could not open \"%s\" for writing",
X			Progname, file);
X		perror("");
X		return(!OK);
X	}
X	work = l_start;
X	while (work != (LINE *) NULL && count < NumberLines)  {
X		count++;
X		write(out, work->text, strlen(work->text));
X		work = work-> next;
X		if (WriteOnQuit != 'Y') putchar('.');
X	}
X	close(out);
X	putchar('\n');
X	return(OK);
X}
END_OF_FILE
if test 5810 -ne `wc -c <'mem.c'`; then
    echo shar: \"'mem.c'\" unpacked with wrong size!
fi
# end of 'mem.c'
fi
if test -f 'multi.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'multi.c'\"
else
echo shar: Extracting \"'multi.c'\" \(1593 characters\)
sed "s/^X//" >'multi.c' <<'END_OF_FILE'
X
X/*
X * This code copyright 1988 by Doug Davis (doug@letni.lawnet.com) 
X *  You are free to modify, hack, fold, spindle, or mutlate this code in
X *  any maner provided you give credit where credit is due and don't pretend
X *  you wrote it.
X *  If you do my lawyers (and I have a lot of lawyers) will teach you a lesson
X *  in copyright law that you will never ever forget.
X */
X#include "defs.h"
X#include "externs.h"
X
X#define RANGE(x)	(x > 0 && x <= NumberLines)
static char *Start="Starting line number ";
static char *End=  "  Ending line number ";
multi_change()
X{
X	long start, end, count;
X	char *string="for changes :";
X	fputs(Start, stdout);
X	fputs(string, stdout);
X	start=getlnum();
X	if (!RANGE(start)) 
X		return(!OK);
X	fputs(End, stdout);
X	fputs(string, stdout);
X	end=getlnum();
X	if (!RANGE(end))
X		return(!OK);
X	for(count = start ; count <= end ; count++) 
X		change(count);
X	return(OK);
X}
multi_delete()
X{
X	long start, end, count;
X	char *string="to delete : ";
X	fputs(Start, stdout);
X	fputs(string, stdout);
X	start=getlnum();
X	if (!RANGE(start)) 
X		return(!OK);
X	fputs(End, stdout);
X	fputs(string, stdout);
X	end=getlnum();
X	if (!RANGE(end))
X		return(!OK);
X	for(count = end ; count >= start ; count--) 
X		subtract(count);
X	return(OK);
X}
multi_print()
X{
X	long start, end, count;
X	char *string="to be printed : ";
X	fputs(Start, stdout);
X	fputs(string, stdout);
X	start=getlnum();
X	if (!RANGE(start)) 
X		return(!OK);
X	fputs(End, stdout);
X	fputs(string, stdout);
X	end=getlnum();
X	if (!RANGE(end))
X		return(!OK);
X	for(count = start ; count <= end ; count++) 
X		printline(count);
X	return(OK);
X}
END_OF_FILE
if test 1593 -ne `wc -c <'multi.c'`; then
    echo shar: \"'multi.c'\" unpacked with wrong size!
fi
# end of 'multi.c'
fi
if test -f 'stuff.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stuff.c'\"
else
echo shar: Extracting \"'stuff.c'\" \(1773 characters\)
sed "s/^X//" >'stuff.c' <<'END_OF_FILE'
X/*
X * This code copyright 1988 by Doug Davis (doug@letni.lawnet.com) 
X *  You are free to modify, hack, fold, spindle, or mutlate this code in
X *  any maner provided you give credit where credit is due and don't pretend
X *  you wrote it.
X *  If you do my lawyers (and I have a lot of lawyers) will teach you a lesson
X *  in copyright law that you will never ever forget.
X */
X#include "defs.h"    /* just for the #define of a NULL */
X#include "externs.h" /* for the strings things. */
X
X/* append  s2 unto s1, returning a pointer to the new "end" of s1 */
char *
strappend(s1, s2)
char *s1, *s2;
X{
X	register char *p, *r;
X	p = s1;
X	r = s2;
X	do {
X		*(p++) = *r;
X	} while ( *(r++) != '\0');
X	p--;
X	return(p);
X}
X/* return a pointer to the first occurence of s2 in s1 otherwise NULL */
char *
strindex(s1, s2)
char *s1, *s2;
X{
X	register char *p, *s;
X	register int len;
X	p=s1;
X	len = strlen(s2);
X	/* quick test to blow away short lines */
X	if (len > strlen(s1))
X		return(NULL);
X	while ((s=STRCHR(p, *s2)) != NULL) {
X		if (!strncmp(s, s2, len))  {
X			return(s);
X		}
X		p= (++s);
X	}
X	return(NULL);
X}
long
makenum(buf)
char *buf;
X{
X	switch (*buf) {
X		case '\0':
X			return(-1L);
X		break;
X		case '$':
X			return(NumberLines);
X		break;
X		case '^':
X			return(1L);
X		break;
X		case '0':
X		case '1':
X		case '2':
X		case '3':
X		case '4':
X		case '5':
X		case '6':
X		case '7':
X		case '8':
X		case '9':
X			return(atol(buf) > 1L ? atol(buf) : 1L);
X		break;
X		default:
X			return(-1L);
X	}
X	return(-1L);
X}
help()
X{
X	register int input, amount;
X	if ((input = open (HelpName, O_RDONLY)) < 0) {
X		fprintf(stderr, "%s: Could not open file \"%s\"",
X		    Progname, HelpName);
X		perror("");
X		return(!OK);
X	}
X	while((amount=read(input, buf, BUFSIZ)) > 0)
X		write(1, buf, amount);
X	close(input);
X	return(OK);
X}
END_OF_FILE
if test 1773 -ne `wc -c <'stuff.c'`; then
    echo shar: \"'stuff.c'\" unpacked with wrong size!
fi
# end of 'stuff.c'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    echo "Now read the README file and edit the Makefile for your system"
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0