home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume5
/
sp4
< prev
next >
Wrap
Internet Message Format
|
1989-02-03
|
38KB
Path: xanth!nic.MR.NET!hal!ncoast!allbery
From: predict%charon.unm.edu@ariel.unm.edu (Andrew R. Large)
Newsgroups: comp.sources.misc
Subject: v05i051: sp version 4.0
Message-ID: <18617.8811140812@charon.unm.edu>
Date: 15 Nov 88 00:36:07 GMT
Sender: allbery@ncoast.UUCP
Reply-To: predict%charon.unm.edu@ariel.unm.edu (Andrew R. Large)
Lines: 1448
Approved: allbery@ncoast.UUCP
Posting-number: Volume 5, Issue 51
Submitted-by: "Andrew R. Large" <predict%charon.unm.edu@ariel.unm.edu>
Archive-name: sp4
This is the new version of my visual spelling checker.
I've incorporated a few bug fixes (including the pclose one) and a warning
about one I couldn't take care of (spell and ex have slightly different
ideas of what makes a word).
I found out that SYSV didn't have a -w flag on their grep. This brought
the usefulness of the `where' function down, so ... I wrote an in-line search
routine that carries with it a context window, so you can see the lines before
and after the word. You can change the default number of lines in the context
window with a new command line -w option (see the man page). Enjoy!
[Of course, you could always use "context" (plug plug ;-) ++bsa]
-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-
* Andrew R. Large *
** (work) 505/255-8611 ------| Univ of New Mexico EECE Department **
*** (home) 505/888-4010 |---> Management Sciences, Inc. [MSI] ***
**** _Babooshka!_ ****
*** Usenet: {convex,gatech,ucbvax,csu-cs,anl-mcs}!unmvax!charon!predict ***
** Internet: predict@charon.UNM.EDU **
* If I am quoted, my employers will deny my existence. *
-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-
--------------------------------- CUT HERE -----------------------------------
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# sp
# This archive created: Mon Nov 14 01:00:49 1988
# By: Andrew R. Large (University of New Mexico, Albuquerque)
echo shar: creating directory sp
mkdir sp
cd sp
echo shar: extracting Makefile '(607 characters)'
sed 's/^XX//' << \SHAR_EOF > Makefile
XX#! /bin/sh
XX#
XX# Makefile for sp
XX# Written by Andrew Large
XX#
XX# Edit BIN, MAN, CC and CFLAGS
XX#
XX
XXBIN = /u1/staff/andy/bin
XXMAN = /u1/staff/andy/man
XX
XXEXEC = sp
XXMANPAGE = $(EXEC).1
XXHDRS = $(EXEC).h
XX
XXOBJS = $(EXEC).o add_local.o doc_correct.o externs.o parse.o spell.o tools.o\
XX user_input.o user_tools.o where.o
XXLIBS = -lcurses -ltermlib
XXCC = cc
XX
XX#
XX# If you are a BSD system, then BSD
XX# CFLAGS = -O
XXCFLAGS = -O -DBSD
XX
XX$(EXEC): $(OBJS)
XX $(CC) $(CFLAGS) $(OBJS) -o $@ $(LIBS)
XX
XXinstall: $(EXEC)
XX strip $(EXEC)
XX cp $(EXEC) $(BIN)
XX cp $(MANPAGE) $(MAN)/man1
XX
XX$(OBJS): $(HDRS)
XX
XXclean:
XX /bin/rm -f $(EXEC) core *.o *.out
SHAR_EOF
if test 607 -ne "`wc -c Makefile`"
then
echo shar: error transmitting Makefile '(should have been 607 characters)'
fi
echo shar: extracting README '(1682 characters)'
sed 's/^XX//' << \SHAR_EOF > README
XX** SP **
XX
XXSp is a visual spelling program that is based upon existing UN*X utilites.
XXIt may be run on one or more files, and for each file, it presents a
XXword-by-word list of the words received from spell(1). You may then take
XXany of a host of actions.
XX
XXThis program has come through many stages during its development. When it was
XXoriginally written, it was designed around a shell script posted in net.sources
XXin 1985 that put all misspelled words into a file, had you correct the file,
XXand then, from the difference between the files, made the corrections.
XX
XXThe current version is so different from the original shell script that I don't
XXcredit the original authors any more. After completing this program, I have
XXnoticed a resemblance to both `ispell' and `correct'. However, this was written
XXbefore I ever saw either of those programs, and no code was taken from either
XXone when writing this.
XX
XXTo install:
XX
XX 1) Edit `sp.h' to reflect your current situation (mainly locations
XX of system programs).
XX
XX 2) Edit Makefile and change `BIN', `MAN', `CC', and `CFLAGS' to
XX their proper values.
XX
XX 3) Type `make'.
XX
XX 4) If everything tests out ok, type `make install'.
XX
XXCopyright (C) 1988 Andrew Large
XX
XXThis software may be used and/or modified on any machine by anyone, as long
XXas you don't violate the following conditions:
XX
XX 1) This copyright notice and the one in the program are left intact.
XX
XX 2) You credit me with original authorship.
XX
XX 3) No monetary gain is made by selling or distributing this software.
XX
XXI will be more than willing to try and support any additions/bug-fixes, but I
XXWILL NOT ACCEPT RESPONSIBILITY FOR ANY HARM CAUSED DIRECTLY OR INDIRECTLY BY
XXTHIS PROGRAM.
SHAR_EOF
if test 1682 -ne "`wc -c README`"
then
echo shar: error transmitting README '(should have been 1682 characters)'
fi
echo shar: extracting where.c '(3717 characters)'
sed 's/^XX//' << \SHAR_EOF > where.c
XX# include "sp.h"
XX# include <ctype.h>
XX# define LEAVE {\
XX fclose (fp); free2 (window, window_size);\
XX page_clear (word_num+1, True); return;\
XX}
XX# define letter(ch) (isalpha (ch) || ch == '.')
XX
XX/*
XX** where
XX** Show where a word occurs in the document with surrounding context.
XX*/
XXwhere (word_num)
XXint word_num;
XX{
XX extern char *bad_words[], *spell_doc;
XX extern char sys_errlist[];
XX extern int errno, window_size;
XX FILE *fp;
XX char *window[MAX_WINDOW], line[BUFSIZ], *word;
XX boolean done = False;
XX int mid;
XX register int i, nlines;
XX
XX move (7,0); clrtobot (); move (7,0); refresh ();
XX if ((fp = fopen (spell_doc, "r")) == NULL) {
XX sprintf (line, "Can't open %s for read: %s", spell_doc,
XX sys_errlist[errno]);
XX message (True, line);
XX ask_more (); page_clear (word_num + 1, True); return;
XX }
XX
XX for (i=0; i < window_size; window[i++] = NULL);
XX word = bad_words[word_num];
XX nlines = ctx_open (fp, window, window_size);
XX mid = nlines / 2;
XX
XX for (i=0; i < mid; i++)
XX if (ctx_display (window, word, nlines, i)) LEAVE
XX
XX while (!done) {
XX if (ctx_display (window, word, nlines, mid)) LEAVE
XX done = ctx_step (fp, window, window_size);
XX }
XX
XX for (i=mid+1; i < nlines; i++)
XX if (ctx_display (window, word, nlines, i)) LEAVE
XX LEAVE
XX}
XX
XX
XX/*
XX** ctx_display
XX** If the interest line has the word in it, then display the identified
XX** window with the word in reverse video. Return True if the user doesn't
XX** want to see any more occurances.
XX*/
XXctx_display (window, word, nlines, chkline)
XXchar *window[], *word;
XXint nlines, chkline;
XX{
XX int beg, end;
XX register int line, ch;
XX char c;
XX
XX word_in (window[chkline], word, &beg, &end);
XX if (beg != -1) {
XX for (line = 0; line < chkline; line++)
XX mvaddstr (line+7, 0, window[line]);
XX
XX for (ch = 0; ch < beg; ch++)
XX mvaddch (chkline+7, ch, window[chkline][ch]);
XX standout ();
XX for (ch = beg; ch <= end; ch++)
XX mvaddch (chkline+7, ch, window[chkline][ch]);
XX standend ();
XX for (ch = end+1; window[chkline][ch]; ch++)
XX mvaddch (chkline+7, ch, window[chkline][ch]);
XX
XX for (line = chkline + 1; line < nlines; line++)
XX mvaddstr (line+7, 0, window[line]);
XX
XX mvaddstr (23,0,
XX "Hit any key for next occurrence, <Esc> to return: ");
XX refresh ();
XX
XX if (getch() != ESC)
XX return False;
XX else
XX return True;
XX }
XX return False;
XX}
XX
XX
XX/*
XX** ctx_open
XX** Open a context window of n lines. Return the number of
XX** lines read in.
XX*/
XXctx_open (fp, window, n)
XXFILE *fp;
XXchar *window[];
XXint n;
XX{
XX register int i;
XX char line[BUFSIZ+1];
XX
XX for (i=0; i < n; i++) {
XX if (fgets (line, BUFSIZ+1, fp) == NULL) return i;
XX safe_copy (&window[i], line);
XX }
XX return n;
XX}
XX
XX
XX/*
XX** ctx_step
XX** Move down the context window by one line
XX*/
XXctx_step (fp, window, n)
XXFILE *fp;
XXchar *window[];
XXint n;
XX{
XX char line[BUFSIZ+1];
XX register int i;
XX
XX if (fgets (line, BUFSIZ+1, fp) == NULL) return True;
XX
XX free (window[0]);
XX for (i=0; i < (n-1); i++)
XX window[i] = window[i+1];
XX
XX window[n-1] = NULL;
XX safe_copy (&window[n-1], line);
XX
XX return False;
XX}
XX
XX
XX/*
XX** word_in
XX** If the given word occurs in the string, return the starting
XX** and ending indices. May show a few occurances _not_ found
XX** by spell.
XX*/
XXword_in (line, word, beg, end)
XXchar *line, *word;
XXint *beg, *end;
XX{
XX register int i, len;
XX
XX *beg = *end = -1;
XX len = strlen (word);
XX
XX if (strncmp (line, word, len) == 0 && !letter (line[len])) {
XX *beg = 0; *end = len - 1;
XX return;
XX }
XX
XX /*
XX ** 1. Skip past current word
XX ** 2. Skip to beginning of next word
XX ** 3. If this is not the correct word, go back to 1.
XX */
XX i=0;
XX while (line[i]) {
XX while (letter (line[i])) i++;
XX while (line[i] && !letter (line[i])) i++;
XX if (line[i] && strncmp (&line[i], word, len) == 0 &&
XX !letter (line[i+len])) {
XX *beg = i; *end = i + len - 1;
XX return;
XX }
XX }
XX}
SHAR_EOF
if test 3717 -ne "`wc -c where.c`"
then
echo shar: error transmitting where.c '(should have been 3717 characters)'
fi
echo shar: extracting parse.c '(1463 characters)'
sed 's/^XX//' << \SHAR_EOF > parse.c
XX# include "sp.h"
XX
XX/*
XX** parse
XX** Parse input for -d and -w options and establish whether
XX** or not a personal dictionary exists
XX*/
XXparse (argc, argv, place)
XXint argc, *place;
XXchar *argv[];
XX{
XX extern char *optarg, *local_dict;
XX extern int optind, window_size;
XX extern boolean local;
XX char *getenv (), getopt ();
XX int option;
XX
XX if (argc < 2) usage (argv[0]);
XX
XX local = False; window_size = 5;
XX while ((option = getopt (argc, argv, "d:w:")) != EOF)
XX switch (option) {
XX case 'd':
XX local_dict =
XX sfalloc ((unsigned) strlen (optarg) + 1);
XX strcpy (local_dict, optarg);
XX local = True;
XX break;
XX case 'w':
XX if ((window_size = atoi (optarg)) < 1)
XX window_size = 1;
XX else if (window_size > MAX_WINDOW)
XX window_size = MAX_WINDOW;
XX break;
XX case '?':
XX default:
XX usage (argv[0]);
XX }
XX
XX if (argv[optind] == NULL)
XX usage (argv[0]);
XX
XX if (!local)
XX if (getenv ("DICT") != NULL)
XX local_dict = getenv ("DICT");
XX else
XX local_dict = "./spelldict";
XX
XX switch (check_dict ()) {
XX case 1:
XX local = True;
XX break;
XX case 0:
XX local = False;
XX printf ("\nYour local dictionary %s does not exist.",
XX local_dict);
XX printf ("\nI may try to create it later ...");
XX fflush (stdout);
XX sleep (2);
XX break;
XX case -1:
XX local = False;
XX printf ("\nYour local dictionary %s is not readable.",
XX local_dict);
XX printf ("\nI may try to write to it later ...");
XX fflush (stdout);
XX sleep (2);
XX break;
XX }
XX *place = optind;
XX}
SHAR_EOF
if test 1463 -ne "`wc -c parse.c`"
then
echo shar: error transmitting parse.c '(should have been 1463 characters)'
fi
echo shar: extracting sp.1 '(4358 characters)'
sed 's/^XX//' << \SHAR_EOF > sp.1
XX.\"
XX.\" Copyright (C) 1988 Andrew Large
XX.\"
XX.de Cm
XX\fI\\$1\fP(\fI\\$2\fP)\\$3
XX..
XX.TH SP 1 "Version 4.0"
XX.DA 13 November 1988
XX.SH NAME
XXsp \- check spelling of a document and fix any mistakes
XX.SH SYNOPSIS
XX.B sp
XX[
XX.B \-d
XX.B dictionary
XX]
XX[
XX.B \-w
XX.B window_size
XX]
XX.B file
XX[
XX.B file2
XX.B ...
XX]
XX.SH DESCRIPTION
XX.PP
XX.IR sp
XXcalls
XX.Cm spell 1
XXto check the spelling of your document(s).
XXIt then presents you with a list of the mis-spelled words and allows
XXyou to ignore the word, correct it, or add it to your personal dictionary.
XX.PP
XXYour personal dictionary is searched for words
XX.I after
XXthe system dictionary. You may specify a personal dictionary in two
XXdifferent ways:
XX.RS
XX.IP 1. 5n
XXOn the command line (with the \-d option).
XX.IP 2. 5n
XXSet the environment variable DICT to the name of your personal dictionary.
XX.RE
XX.PP
XXIf you don't explicitly set your personal dictionary, then the file
XX``spelldict'' in your current directory will be used.
XX.PP
XXOnce the mis-spelled words are identified, you are prompted word by
XXword for an action to take. Your choices are given in brackets and
XXexplained below.
XX.IP A
XXMark the word for addition to your personal dictionary.
XX.IP C
XXMark the word for correction. You will be asked for the correct spelling.
XX.IP I
XXIgnore the word in question. This is the default option and is
XXused when a word is spelled correctly, but you don't want it added
XXto your personal dictionary.
XX.IP L
XXLook up a string in the system dictionary. This is appropriate for
XXobtaining the proper spelling of the word. You will be prompted for a string
XXthat
XX.Cm look 1
XXwill use on the system dictionary.
XX.IP W
XXShow where the word occurs in the document. This shows the line the word
XXoccurred on plus some additional lines to show the context. The size of
XXthe context window is set to 5 by default (two lines above, two lines below).
XXYou can change the context window size with the \-w option. The window
XXsize may be set to anything from 1 to 15.
XX.IP ^
XXGo to previous document (given on command line). If your current document
XXis the first given on the command line, this will re-run
XX.Cm spell 1
XXon your current document. If you have marked any words for correction or
XXaddition to your personal dictionary, you will be
XXasked whether or not you want to save your changes.
XX.IP #
XXGo to next document (given on command line). If your current document is
XXthe last given on the command line, this exits the program. If you
XXhave marked any words for correction or addition to your personal
XXdictionary, you will be asked whether or not you want to save your changes.
XX.IP +
XXGo to next word. If you haven't taken action with the current word, this
XXoption is equivalent to an ignore (don't correct or add to personal
XXdictionary). Otherwise, previous actions hold true, i.e. if you correct
XXa word, hit a '-' to go back to it, and hit a '+' to skip forward past it,
XXthe correction would still be the course taken. However, if you hit an
XX'I' to skip forward past it, no correction would take place.
XX.IP -
XXGo to previous word. This is the course of action to take if you
XXmess up a correction or change your mind in some way.
XX.IP ?
XXThis will display a short help menu.
XX.IP ^L
XXThis will redraw the screen (as with
XX.Cm vi 1 ).
XX.PP
XXAfter you have processed all the words, you are prompted for an
XXadditional action. You may go to either the previous or the next document.
XXIn either case, you will be asked whether or not you wish to save your changes.
XXIn this manner, you can make corrections to a file, and then back up to check
XXyour corrections. Corrections are made to the documents via
XX.Cm ex 1 .
XX.PP
XXThe spell checking is done one file at a time, so if you have the same
XXmis-spelled word in several files, you will have to correct it for each file.
XXHowever, the personal dictionary is updated between the checks on each file,
XXso additions to it will be available when the next file is checked.
XX.SH AUTHOR
XXAndrew Large
XX.SH FILES
XX$DICT, spelldict \- default personal dictionaries
XX.SH BUGS
XX.PP
XX.Cm spell 1
XXand
XX.Cm ex 1
XXhave different ideas of what constitutes a word. Most notably,
XX.Cm spell 1
XXconsiders ``_'' to be a word separation character. For those cases,
XXcorrect the word by hand. Trying to correct it via
XX.B sp
XXwill cause
XX.Cm ex 1
XXto fail, and all your corrections will be lost.
XX.SH "SEE ALSO"
XX.Cm ex 1 ,
XX.Cm grep 1 ,
XX.Cm look 1 ,
XXand
XX.Cm spell 1 .
SHAR_EOF
if test 4358 -ne "`wc -c sp.1`"
then
echo shar: error transmitting sp.1 '(should have been 4358 characters)'
fi
echo shar: extracting sp.c '(1416 characters)'
sed 's/^XX//' << \SHAR_EOF > sp.c
XX# include "sp.h"
XX
XX/*
XX** sp main program
XX** Uses spell(1) to check the spelling of a document.
XX** The user is prompted with each of the mis-spelled words and
XX** can ignore them, add them to a personal dictionary, correct
XX** them, look up words in the dictionary, or find out where in
XX** the file the word is found. Corrections are made to the
XX** document via ex(1).
XX**
XX** Author: Andrew Large
XX** December 1986 (First Edition)
XX** October 1988 (Current Version)
XX*/
XX
XXmain (argc, argv)
XXint argc;
XXchar *argv[];
XX{
XX extern int exit_val;
XX extern char *spell_doc;
XX int spell_val, start_pos;
XX register int pos;
XX
XX /*
XX ** Parse input arguments and initialize
XX ** curses and signals
XX */
XX parse (argc, argv, &start_pos);
XX init ();
XX
XX /*
XX ** Main loop. Keep going until user leaves the last document.
XX */
XX pos = start_pos;
XX while (pos < argc) {
XX reset_data (); /* Clean lists and reset globals */
XX spell_doc = argv[pos];
XX
XX if ( (spell_val = spell ()) >= 0 ) {
XX switch (user_input ()) {
XX case -1: /* previous doc, save */
XX rest_ignore ();
XX save (spell_val);
XX case -2: /* previous doc, no save */
XX if (pos > start_pos) --pos;
XX break;
XX case 0: /* normal exit with save */
XX case 1: /* early exit with save */
XX rest_ignore ();
XX save (spell_val);
XX case 2: /* early exit, no save */
XX default:
XX ++pos;
XX break;
XX }
XX }
XX else {
XX ++pos;
XX exit_val = Error;
XX }
XX }
XX leave ();
XX}
SHAR_EOF
if test 1416 -ne "`wc -c sp.c`"
then
echo shar: error transmitting sp.c '(should have been 1416 characters)'
fi
echo shar: extracting spell.c '(2033 characters)'
sed 's/^XX//' << \SHAR_EOF > spell.c
XX# include "sp.h"
XX
XX/*
XX** spell
XX** Run spell(1) on the file and check personal dictionary also.
XX** Establishes the original list of mis-spelled words
XX*/
XXspell () {
XX extern char *bad_words[], *spell_doc, *local_dict;
XX extern int num_bad;
XX extern boolean local;
XX FILE *popen (), *spell_out;
XX char command[256];
XX int ypos, xpos, ret_val;
XX register int i;
XX
XX clear (); fname ();
XX
XX if (access (spell_doc, 0) != 0) { /* Check for existence */
XX sprintf (command, "Cannot access file %s!", spell_doc);
XX message (True, command);
XX return (-1);
XX }
XX
XX ret_val = 0;
XX if (access (spell_doc, 6) != 0) { /* Read and write */
XX if (access (spell_doc, 4) != 0) { /* Read */
XX sprintf (command, "You are unable to read %s!",
XX spell_doc);
XX message (True, command);
XX return (-1);
XX }
XX message (True, "You are unable to write to this file!");
XX mvaddstr (5,22, "I will check spelling, but you will");
XX mvaddstr (6,22, "not be able to save any corrections.");
XX ret_val = 1;
XX move (0,0); refresh (); sleep (3); fname ();
XX }
XX
XX mvaddstr (3,0, "Checking spelling ..."); refresh ();
XX
XX /*
XX ** Get the list of mis-spelled words
XX */
XX if (local)
XX sprintf (command, "%s %s | %s -v -f %s", SPELL, spell_doc,
XX FGREP, local_dict);
XX else
XX sprintf (command, "%s %s", SPELL, spell_doc);
XX
XX spell_out = popen (command, "r");
XX
XX for (i = 0; i < MAX_WORDS; i++) {
XX bad_words[i] = sfalloc ((unsigned) MAX_WORD_LEN);
XX if (fgets (bad_words[i], MAX_WORD_LEN, spell_out) == NULL)
XX break;
XX else
XX bad_words[i][strlen (bad_words[i]) - 1] = '\0';
XX }
XX fflush (spell_out); pclose (spell_out);
XX
XX if ((num_bad = i) >= MAX_WORDS) {
XX getyx (stdscr, ypos, xpos);
XX sprintf (command, "You have more than %d mis-spelled words.",
XX MAX_WORDS);
XX mvaddstr (5, 10, command);
XX strcpy (command, "Run this again after corrections are made.");
XX mvaddstr (6, 10, command);
XX move (ypos, xpos); refresh (); sleep (2);
XX }
XX
XX addstr (" done"); refresh ();
XX
XX if (num_bad <= 0) {
XX mvaddstr (5,0, "No spelling errors.");
XX move (0,0); refresh (); sleep (1);
XX }
XX return (ret_val);
XX}
SHAR_EOF
if test 2033 -ne "`wc -c spell.c`"
then
echo shar: error transmitting spell.c '(should have been 2033 characters)'
fi
echo shar: extracting user_input.c '(2012 characters)'
sed 's/^XX//' << \SHAR_EOF > user_input.c
XX# include "sp.h"
XX
XX/*
XX** user_input -- user interface for correcting mis-spelled words
XX*/
XXuser_input () {
XX extern char *bad_words[], *good_words[];
XX extern int num_bad;
XX char string[MAX_WORD_LEN + 64];
XX boolean done;
XX register int loop;
XX
XX for (loop = 0; loop < num_bad; loop++) {
XX page_clear (loop + 1, False);
XX sprintf (string, "Word ``%s'' is not in the dictionary",
XX bad_words[loop]);
XX mvaddstr (3, 0, string); refresh ();
XX
XX done = False;
XX do {
XX sprintf (string, "(%s) [ilwac^#+-?] ", bad_words[loop]);
XX mvaddstr (5, 0, string); refresh ();
XX
XX switch (getch ()) {
XX case 'I':
XX case 'i':
XX case ' ':
XX case '\n':
XX case '\r':
XX addstr ("Ignore"); refresh ();
XX done = True; ignore (loop);
XX break;
XX case 'L':
XX case 'l':
XX addstr ("Lookup"); refresh ();
XX lookup (loop);
XX break;
XX case 'W':
XX case 'w':
XX addstr ("Where"); refresh ();
XX where (loop);
XX break;
XX case 'A':
XX case 'a':
XX addstr ("Add"); refresh ();
XX done = True; add (loop);
XX break;
XX case 'C':
XX case 'c':
XX addstr ("Correct"); refresh ();
XX done = True; word_correct (loop);
XX break;
XX case '^':
XX addstr ("Previous Document");
XX refresh ();
XX if (ask_save (loop) == 1)
XX return (-1);
XX else
XX return (-2);
XX case '#':
XX addstr ("Next Document");
XX refresh ();
XX if (ask_save (loop) == 1)
XX return (1);
XX else
XX return (2);
XX case '+':
XX addstr ("Next Word");
XX refresh ();
XX done = True;
XX if (good_words[loop] == NULL)
XX ignore (loop);
XX break;
XX case '-':
XX addstr ("Previous Word");
XX refresh ();
XX done = True;
XX if (loop > 0) loop -=2;
XX else --loop;
XX break;
XX case 'H':
XX case 'h':
XX case '?':
XX addstr ("Help!"); refresh ();
XX help (loop);
XX break;
XX case CTRL_L:
XX case CTRL_R:
XX page_clear (loop + 1, True);
XX break;
XX default:
XX page_clear (loop + 1, False);
XX break;
XX }
XX } while (!done);
XX }
XX return (ask_action ());
XX}
SHAR_EOF
if test 2012 -ne "`wc -c user_input.c`"
then
echo shar: error transmitting user_input.c '(should have been 2012 characters)'
fi
echo shar: extracting MANIFEST '(785 characters)'
sed 's/^XX//' << \SHAR_EOF > MANIFEST
XXFile Explanation
XX------------------------------------------------------------------------------
XXMANIFEST This file -- list of files in package
XXMakefile For compiling ``sp''.
XXREADME Read this first for installation and copyright information
XXadd_local.c Routine for adding words to personal dictionary
XXdoc_correct.c Routine for correcting the document
XXexterns.c Declarations of global data structures
XXparse.c Command line parser (uses getopt)
XXsp.1 Manual page
XXsp.c Main program
XXsp.h Include file (may need editing)
XXspell.c Runs spell(1) and fgrep(1) to get initial mis-spelling list
XXtools.c General tools used througout program
XXuser_input.c Get user input for corrections
XXuser_tools.c Process option selected in user_input
XXwhere.c For showing context-surrounded word occurences
SHAR_EOF
if test 785 -ne "`wc -c MANIFEST`"
then
echo shar: error transmitting MANIFEST '(should have been 785 characters)'
fi
echo shar: extracting tools.c '(4427 characters)'
sed 's/^XX//' << \SHAR_EOF > tools.c
XX# include "sp.h"
XX# include <signal.h>
XX
XX
XX/*
XX** ask_more
XX** Prompt the user to continue.
XX*/
XXask_more () {
XX move (23,0); clrtoeol ();
XX standout ();
XX mvaddstr (23, 29, "Hit any key to continue");
XX standend ();
XX refresh (); getch ();
XX}
XX
XX
XX/*
XX** check_dict
XX** Check for existence/read permission on dictionary.
XX*/
XXcheck_dict () {
XX extern char *local_dict;
XX
XX if ( access (local_dict, 4) == 0 ) /* Read permission */
XX return (1);
XX else
XX if ( access (local_dict, 0) != 0 ) /* Existence check */
XX return (0);
XX else
XX return (-1);
XX}
XX
XX
XX/*
XX** curse_die
XX** Die with an explanation when inside of curses
XX*/
XXcurse_die (string)
XXchar *string;
XX{
XX extern int errno, exit_val;
XX extern char *sys_errlist[];
XX char line[256];
XX
XX sprintf (line, "Fatal Error, %s:%s", string, sys_errlist[errno]);
XX message (True, line);
XX exit_val = Error; leave ();
XX}
XX
XX
XX/*
XX** fname
XX** Print out the page header (file name, etc.)
XX*/
XXfname () {
XX extern char *spell_doc;
XX erase ();
XX mvaddstr (0, (65 - strlen (spell_doc)) / 2, /* (80-overhead-len) / 2 */
XX "[ --- ");
XX standout ();
XX addch (' '); addstr (spell_doc); addch (' ');
XX standend ();
XX addstr (" --- ]");
XX}
XX
XX
XX/*
XX** free2
XX** Free a list of strings
XX*/
XXfree2 (args, max)
XXregister char **args;
XXregister int max;
XX{
XX while (*args && max-- > 0) free (*args++);
XX}
XX
XX
XX/*
XX** init
XX** Initialize the screen and take care of nasty signals
XX*/
XXinit () {
XX extern char *bad_words[], *good_words[], *add_words[];
XX register int i;
XX
XX for (i=0; i < MAX_WORDS; i++) {
XX bad_words[i] = good_words[i] = add_words[i] = NULL;
XX }
XX
XX signal (SIGINT, leave); signal (SIGQUIT, leave);
XX
XX initscr (); crmode (); noecho ();
XX
XX mvaddstr ( 9,30, VERSION1);
XX mvaddstr (10,28, VERSION2);
XX mvaddstr (11,31, VERSION3);
XX
XX move (0,0); refresh (); sleep (1);
XX}
XX
XX
XX/*
XX** leave
XX** Clean up curses and exit.
XX*/
XXvoid leave () {
XX extern char tmp_file[];
XX extern int exit_val;
XX
XX unlink (tmp_file);
XX clear (); move (23,0); refresh (); endwin ();
XX exit (exit_val);
XX}
XX
XX
XX/*
XX** message
XX** Write message on the screen
XX*/
XXmessage (error, line)
XXboolean error;
XXchar *line;
XX{
XX page_clear (0, False);
XX
XX if (error) {
XX addch ('\07');
XX mvaddstr (3, (78 - strlen (line)) / 2, line);
XX move (0,0);
XX refresh (); sleep (3);
XX }
XX else {
XX mvaddstr (3, (78 - strlen (line)) / 2, line);
XX refresh (); sleep (2);
XX }
XX}
XX
XX
XX/*
XX** page_clear
XX** Clear part of the screen and display the number
XX** of the current word
XX*/
XXpage_clear (word_num, cls)
XXint word_num;
XXboolean cls;
XX{
XX extern int num_bad;
XX char str[20];
XX
XX if (cls)
XX clear ();
XX fname ();
XX if (word_num) {
XX sprintf (str, "Word #%d of %d", word_num, num_bad);
XX mvaddstr (23, 79 - strlen (str), str);
XX mvaddstr (23, 0, VERSION1);
XX }
XX move (3, 0);
XX refresh ();
XX}
XX
XX
XX/*
XX** reset_data
XX** Reset all global data
XX*/
XXreset_data () {
XX extern char *bad_words[], *good_words[], *add_words[];
XX extern int num_bad, num_added, num_ignored;
XX register int i;
XX
XX for (i = 0; i < MAX_WORDS; i++) {
XX if (bad_words[i] != NULL) {
XX free (bad_words[i]); bad_words[i] = NULL;
XX }
XX if (good_words[i] != NULL) {
XX free (good_words[i]); good_words[i] = NULL;
XX }
XX if (add_words[i] != NULL) {
XX free (add_words[i]); add_words[i] = NULL;
XX }
XX }
XX
XX num_bad = num_added = num_ignored = 0;
XX}
XX
XX
XX/*
XX** safe_copy
XX** A pre-malloc'd copy from one string to another
XX*/
XXsafe_copy (string1, string2)
XXchar **string1,
XX *string2;
XX{
XX if (*string1 == NULL)
XX *string1 = sfalloc ((unsigned) strlen (string2) + 1);
XX strcpy (*string1, string2);
XX}
XX
XX
XX/*
XX** save
XX** Save changes made to document
XX*/
XXsave (spell_val)
XXint spell_val;
XX{
XX extern int num_bad, num_added, num_ignored;
XX
XX if (num_added)
XX add_local ();
XX if (num_bad == (num_added + num_ignored))
XX message (False, "No corrections made");
XX else
XX if (spell_val == 0) doc_correct ();
XX}
XX
XX
XX/*
XX** rest_ignore
XX** When user exits before viewing all the words, set the rest
XX** of the words to ignore.
XX*/
XXrest_ignore () {
XX extern char *bad_words[], *good_words[];
XX extern int num_bad;
XX register int i;
XX
XX for (i = num_bad - 1; !good_words[i]; ignore (i--));
XX}
XX
XX
XX/*
XX** sfalloc
XX** A safe malloc ()
XX*/
XXchar *sfalloc (num_bytes)
XXunsigned num_bytes;
XX{
XX char *calloc (), *hold;
XX
XX if (num_bytes == 0) return ((char *) NULL);
XX
XX if ( (hold = calloc (1, num_bytes)) == NULL)
XX curse_die ("calloc");
XX
XX return (hold);
XX}
XX
XX
XX/*
XX** usage
XX** Print out program usage statement and exit.
XX*/
XXusage (name)
XXchar *name;
XX{
XX fprintf (stderr,
XX "Usage: %s [ -d dictionary ] [ -w window_size ] file [ file2 ... ]\n",
XX name);
XX exit (1);
XX}
SHAR_EOF
if test 4427 -ne "`wc -c tools.c`"
then
echo shar: error transmitting tools.c '(should have been 4427 characters)'
fi
echo shar: extracting sp.h '(992 characters)'
sed 's/^XX//' << \SHAR_EOF > sp.h
XX/*
XX** Configuration information for sp
XX*/
XX
XX# include <curses.h>
XX
XX# define True 1
XX# define False 0
XX
XX# define Error 1
XX# define Okay 0
XX
XX# define VERSION1 "Sp Version 4.0"
XX# define VERSION2 "Copyright (C) 1988"
XX# define VERSION3 "Andrew Large"
XX
XX/*
XX** Lookup dictionary -- use /usr/dict/web2 if you have it
XX*/
XX# define LOOK_DICT "/usr/dict/words"
XX
XX/*
XX** Location of common programs
XX*/
XX# define EX "/usr/ucb/ex"
XX# define FGREP "/usr/bin/fgrep"
XX# define LOOK "/usr/bin/look"
XX# define MORE "/usr/ucb/more"
XX# define SORT "/usr/bin/sort"
XX# define SPELL "/usr/bin/spell"
XX
XX/*
XX** Constant sizes
XX*/
XX# define MAX_WORDS 512 /* Max words corrected on one pass */
XX# define MAX_WORD_LEN 256 /* Max length of a word */
XX# define MAX_WINDOW 15 /* Maximum window size (for where) */
XX
XX# define CTRL_R 022 /* Ascii value of ^R -- for redraw */
XX# define CTRL_L 014 /* Ascii value of ^L -- for redraw */
XX# define ESC 033 /* Ascii value of Escape */
XX
XX
XXtypedef unsigned char boolean;
XX
XXvoid leave ();
XXchar *sfalloc ();
SHAR_EOF
if test 992 -ne "`wc -c sp.h`"
then
echo shar: error transmitting sp.h '(should have been 992 characters)'
fi
echo shar: extracting user_tools.c '(3592 characters)'
sed 's/^XX//' << \SHAR_EOF > user_tools.c
XX# include "sp.h"
XX
XX
XX/*
XX** add
XX** Add an entry into list of words to be added to personal dict
XX*/
XXadd (word_num)
XXint word_num;
XX{
XX extern char *add_words[], *bad_words[], *good_words[];
XX extern int num_added;
XX
XX safe_copy (& (add_words[num_added++]), bad_words[word_num]);
XX safe_copy (& (good_words[word_num]), bad_words[word_num]);
XX}
XX
XX
XX/*
XX** ask_action
XX** Ask the user what to do after processing words
XX*/
XXask_action () {
XX extern int num_bad;
XX boolean done;
XX
XX done = False;
XX while (!done) {
XX page_clear (0, False);
XX mvaddstr (3, 0, "Action? [#^?] ");
XX refresh ();
XX
XX switch (getch ()) {
XX case ' ': case '\n': case '\r':
XX case '#':
XX done = True;
XX addstr ("Next Document"); refresh ();
XX if (ask_save (num_bad) == 1) return (0);
XX else return (2);
XX case '^':
XX done = True;
XX addstr ("Previous Document"); refresh ();
XX if (ask_save (num_bad) == 1) return (-1);
XX else return (-2);
XX case '?':
XX addstr ("Help!"); refresh ();
XX mvaddstr (5, 10, "# --- Go to next document (or exit)");
XX mvaddstr (6, 10, "^ --- Go to previous document (or re-spell this one)");
XX mvaddstr (7, 10, "? --- This help message");
XX ask_more ();
XX default:
XX break;
XX }
XX }
XX return (0);
XX}
XX
XX
XX/*
XX** ask_save
XX** Ask user if he/she wants to save these changes
XX*/
XXask_save (word_num)
XXint word_num;
XX{
XX extern int num_ignored;
XX char ch;
XX
XX if (word_num == num_ignored) return (0);
XX mvaddstr (7, 0, "Do you wish to save your changes? [y] ");
XX refresh ();
XX if ( (ch = getch ()) == 'n' || ch == 'N' ) return (0);
XX return (1);
XX}
XX
XX
XX/*
XX** correct
XX** Get correct spelling for a word
XX*/
XXword_correct (word_num)
XXint word_num;
XX{
XX extern char *good_words[];
XX
XX mvaddstr (7, 0, "****** Proper spelling: "); refresh();
XX echo(); nocrmode(); refresh ();
XX
XX if (good_words[word_num] == NULL)
XX good_words[word_num] = sfalloc ((unsigned) MAX_WORD_LEN + 1);
XX fgets (good_words[word_num], MAX_WORD_LEN + 1, stdin);
XX good_words[word_num][strlen (good_words[word_num]) - 1] = '\0';
XX
XX crmode (); noecho ();
XX ask_more (); page_clear (word_num + 1, True);
XX}
XX
XX
XX/*
XX** help
XX** Give user some help with commands
XX*/
XXhelp (word_num)
XXint word_num;
XX{
XX mvaddstr ( 7, 10, " I --- Ignore all occurrences of word");
XX mvaddstr ( 8, 10, " L --- Lookup a sub-string in the dictionary");
XX mvaddstr ( 9, 10, " W --- show Where word occurs in the document");
XX mvaddstr (10, 10, " A --- Add word to your personal dictionary");
XX mvaddstr (11, 10, " C --- Correct all occurrences of the word");
XX mvaddstr (12, 10, " ^ --- go to previous document (or re-spell this one)");
XX mvaddstr (13, 10, " # --- go to next document (or exit)");
XX mvaddstr (14, 10, " + --- go to next word");
XX mvaddstr (15, 10, " - --- go to previous word");
XX mvaddstr (16, 10, " ?, H --- this help message");
XX mvaddstr (17, 10, "^R, ^L --- redraw the screen");
XX ask_more ();
XX page_clear (word_num + 1, False);
XX}
XX
XX
XX/*
XX** ignore
XX** Ignore the word (i.e. don't substitute for it)
XX*/
XXignore (word_num)
XXint word_num;
XX{
XX extern char *good_words[], *bad_words[];
XX extern int num_ignored;
XX
XX safe_copy (& (good_words[word_num]), bad_words[word_num]);
XX num_ignored++;
XX}
XX
XX
XX/*
XX** lookup
XX** Look up string in the dictionary
XX*/
XXlookup (word_num)
XXint word_num;
XX{
XX char hold_str[MAX_WORD_LEN + 1],
XX command[BUFSIZ];
XX
XX mvaddstr (7, 0, "****** Lookup string: ");
XX refresh ();
XX
XX echo (); nocrmode (); gets (hold_str);
XX move (8, 0); clrtobot (); move (8, 0); refresh ();
XX
XX sprintf (command, "%s -df %s %s | %s", LOOK, hold_str, LOOK_DICT,
XX MORE);
XX system (command);
XX
XX crmode (); noecho (); ask_more ();
XX page_clear (word_num + 1, True);
XX}
SHAR_EOF
if test 3592 -ne "`wc -c user_tools.c`"
then
echo shar: error transmitting user_tools.c '(should have been 3592 characters)'
fi
echo shar: extracting doc_correct.c '(846 characters)'
sed 's/^XX//' << \SHAR_EOF > doc_correct.c
XX# include "sp.h"
XX
XX/*
XX** doc_correct
XX** Correct the document, based upon the difference between the
XX** original and new lists of words. Uses EX to make the corrections.
XX*/
XXdoc_correct () {
XX extern char *bad_words[], *good_words[], *spell_doc;
XX extern int num_bad;
XX FILE *popen (), *ex_ptr;
XX char command[256];
XX register int loop;
XX
XX page_clear (0, False);
XX mvaddstr (3,0, "Making changes ..."); refresh ();
XX
XX sprintf (command, "%s - %s", EX, spell_doc);
XX ex_ptr = popen (command, "w");
XX
XX fprintf (ex_ptr, "set nomagic\n"); /* Don't match '.' */
XX for (loop = 0; loop < num_bad; loop++)
XX if (strcmp (bad_words[loop], good_words[loop]) != 0) {
XX fprintf (ex_ptr, "%%s/\\<%s\\>/%s/g\n", bad_words[loop],
XX good_words[loop]);
XX fflush (ex_ptr);
XX }
XX fprintf (ex_ptr, "w\nq\n");
XX fflush (ex_ptr); pclose (ex_ptr);
XX
XX addstr (" done"); refresh ();
XX}
SHAR_EOF
if test 846 -ne "`wc -c doc_correct.c`"
then
echo shar: error transmitting doc_correct.c '(should have been 846 characters)'
fi
echo shar: extracting externs.c '(774 characters)'
sed 's/^XX//' << \SHAR_EOF > externs.c
XX# include "sp.h"
XX
XX/*
XX** Global data use throughout the program
XX*/
XXchar *id = "@(#)SP\t4.0\t88/11/13"; /* Identification string for what(1) */
XX
XXchar *bad_words[MAX_WORDS], /* Words obtained from spell(1) */
XX *good_words[MAX_WORDS], /* Words to correct in document */
XX *add_words[MAX_WORDS], /* Words to add to local dictionary */
XX *local_dict, /* Local dictionary */
XX *spell_doc, /* Document we are currently spelling */
XX tmp_file[16]; /* Temporary file used for */
XX
XXint num_bad, /* Number of bad words */
XX num_added, /* Number added to local dict */
XX num_ignored, /* Number bad words ignored */
XX exit_val, /* Program exit value (for leave ()) */
XX window_size; /* Context window size (for where ()) */
XX
XXboolean local; /* Is the local dict available? */
SHAR_EOF
if test 774 -ne "`wc -c externs.c`"
then
echo shar: error transmitting externs.c '(should have been 774 characters)'
fi
echo shar: extracting add_local.c '(1293 characters)'
sed 's/^XX//' << \SHAR_EOF > add_local.c
XX# include "sp.h"
XX
XX/*
XX** add_local
XX** Add all words in correct list to personal dictionary
XX** and sort the dictionary.
XX*/
XXadd_local () {
XX extern char *add_words[], *local_dict, tmp_file[];
XX extern int num_added;
XX extern boolean local;
XX char *mktemp (), string[256];
XX FILE *fopen (), *tmp_ptr;
XX register int loop;
XX
XX if ( access (local_dict, 0) == 0 && access (local_dict, 2) != 0 ) {
XX sprintf (string,
XX "Your local dictionary \"%s\" is not writable!",
XX local_dict);
XX message (True, string);
XX return;
XX }
XX
XX strcpy (tmp_file, "/tmp/spXXXXXX");
XX if ((tmp_ptr = fopen (mktemp (tmp_file), "w")) == NULL) {
XX sprintf (string, "Can't open tmp file \"%s\" for writing!",
XX tmp_file);
XX message (True, string);
XX return;
XX }
XX
XX for (loop = 0; loop < num_added; loop++)
XX fprintf (tmp_ptr, "%s\n", add_words[loop]);
XX fflush (tmp_ptr); fclose (tmp_ptr);
XX
XX# ifdef BSD
XX if (vfork () == 0) {
XX# else
XX if (fork () == 0) {
XX# endif
XX if (local)
XX execl (SORT, "sort", "-f", "-m", "-o", local_dict,
XX local_dict, tmp_file, (char *) NULL);
XX else
XX execl (SORT, "sort", "-f", "-m", "-o", local_dict,
XX tmp_file, (char *) NULL);
XX perror (SORT);
XX _exit (-1);
XX }
XX
XX wait (0);
XX sprintf (string, "%d %s added to %s", num_added,
XX (num_added == 1 ? "word" : "words"), local_dict);
XX message (False, string);
XX}
SHAR_EOF
if test 1293 -ne "`wc -c add_local.c`"
then
echo shar: error transmitting add_local.c '(should have been 1293 characters)'
fi
echo shar: done with directory sp
cd ..
# End of shell archive
exit 0