home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / misc / volume04 / sp < prev    next >
Encoding:
Internet Message Format  |  1991-08-27  |  29.1 KB

  1. Path: wucfua!wucs1!uunet!seismo!sundc!pitstop!sun!decwrl!labrea!rutgers!tut.cis.ohio-state.edu!cwjcc!hal!ncoast!allbery
  2. From: predict@charon.unm.edu (Andrew R. Large)
  3. Newsgroups: comp.sources.misc
  4. Subject: v04i124: Another (almost real) spelling program
  5. Message-ID: <3521.8810130726@charon.unm.edu>
  6. Date: 14 Oct 88 23:36:06 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Reply-To: predict@charon.unm.edu (Andrew R. Large)
  9. Lines: 1119
  10. Approved: allbery@ncoast.UUCP
  11.  
  12. Posting-number: Volume 4, Issue 124
  13. Submitted-by: "Andrew R. Large" <predict@charon.unm.edu>
  14. Archive-name: sp
  15.  
  16. Here is my simple UNIX(tm) spelling program.  Nothing terribly exciting,
  17. just gives a curses interface to spell, (f)grep, and ex.  Should be fairly
  18. stable for BSD environment.  Don't have a (yuck) [right back at you!  ++bsa]
  19. SYSV machine handy to test it on.  Needs getopt and the -w option of grep.
  20. Other than that, fairly vanilla (I hope).
  21.  
  22. Thought I'd send it in given the current craze over spelling programs.
  23.  
  24.  -=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-
  25.    *                          Andrew R. Large                              *
  26.   **  (work) 505/255-8611 ------|     Univ of New Mexico EECE Department   **
  27.  ***  (home) 505/888-4010       |---> Management Sciences, Inc. [MSI]      ***
  28. ****                            _Babooshka!_                               ****
  29.  ***  Usenet: {convex,gatech,ucbvax,csu-cs,anl-mcs}!unmvax!charon!predict  ***
  30.   **  Internet: predict@charon.UNM.EDU                                     **
  31.    *          If I am quoted, my employers will deny my existence.         *
  32.  -=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-
  33.  
  34. #!/bin/sh
  35. # shar:    Shell Archiver
  36. #    Run the following text with /bin/sh to create:
  37. #    sp
  38. # This archive created: Thu Oct 13 01:15:11 1988
  39. # By:    Andrew R. Large (University of New Mexico, Albuquerque)
  40. echo shar: creating directory sp
  41. mkdir sp
  42. cd sp
  43. echo shar: extracting Makefile '(498 characters)'
  44. sed 's/^XX//' << \SHAR_EOF > Makefile
  45. XX#! /bin/sh
  46. XX#
  47. XX# Makefile for sp
  48. XX# Written by Andrew Large
  49. XX#
  50. XX
  51. XXBIN = /u1/staff/andy/bin
  52. XXMAN = /u1/staff/andy/man
  53. XX
  54. XXEXEC = sp
  55. XXMANPAGE = $(EXEC).1
  56. XXHDRS = $(EXEC).h
  57. XX
  58. XXOBJS = $(EXEC).o doc_correct.o local_add.o parse.o spell.o tools.o user_input.o\
  59. XX    user_tools.o
  60. XXLIBS = -lcurses -ltermlib
  61. XXCC = cc
  62. XX
  63. XXCFLAGS = -O
  64. XX
  65. XX$(EXEC): $(OBJS)
  66. XX    $(CC) $(CFLAGS) $(OBJS) -o $@ $(LIBS)
  67. XX
  68. XXinstall: $(EXEC)
  69. XX    strip $(EXEC)
  70. XX    cp $(EXEC) $(BIN)
  71. XX    cp $(MANPAGE) $(MAN)/man1
  72. XX
  73. XX$(OBJS): $(HDRS)
  74. XX
  75. XXclean:
  76. XX    /bin/rm -f $(EXEC) core *.o *.out
  77. SHAR_EOF
  78. if test 498 -ne "`wc -c Makefile`"
  79. then
  80. echo shar: error transmitting Makefile '(should have been 498 characters)'
  81. fi
  82. echo shar: extracting README '(1617 characters)'
  83. sed 's/^XX//' << \SHAR_EOF > README
  84. XXSp is a visual spelling program.  It may be run on one or more files, and
  85. XXfor each file, it presents a word-by-word list of the words spell(1) thinks
  86. XXare misspelled.  You may then take any of a host of actions.
  87. XX
  88. XXThis program has come through many stages during its development.  When it was
  89. XXoriginally written, it was designed around a shell script posted in net.sources
  90. XXin 1985 that put all misspelled words into a file, had you correct the file,
  91. XXand then, from the difference between the files, made the corrections.
  92. XX
  93. XXThe current version is so different from the original shell script that I don't
  94. XXcredit the original authors any more.  After completing this program, I have
  95. XXnoticed a resemblance to both ispell and correct.  However, this was written
  96. XXbefore I ever saw either of those programs, and no code was taken from either
  97. XXone when writing this.
  98. XX
  99. XXTo install:
  100. XX
  101. XX1) Edit 'sp.h' to reflect your current situation (mainly locations of system
  102. XX   programs).
  103. XX2) Edit 'Makefile' and change 'BIN', 'MAN', and 'CC' to reflect your situation
  104. XX3) Type 'make'
  105. XX4) If everything looks OK, type 'make install'
  106. XX
  107. XXCopyright (C) 1988 Andrew Large
  108. XX
  109. XXThis software may be used and/or modified on any machine by anyone, as long
  110. XXas you don't violate the following conditions:
  111. XX
  112. XX    1) This copyright notice and the one in the program are left intact.
  113. XX
  114. XX    2) You credit me with original authorship.
  115. XX
  116. XX    3) No monetary gain is made by selling or distributing this software.
  117. XX
  118. XXI will be more than willing to try and support any additions/bug-fixes, but I
  119. XXWILL NOT ACCEPT RESPONSIBILITY FOR ANY HARM CAUSED DIRECTLY OR INDIRECTLY BY
  120. XXTHIS PROGRAM.
  121. SHAR_EOF
  122. if test 1617 -ne "`wc -c README`"
  123. then
  124. echo shar: error transmitting README '(should have been 1617 characters)'
  125. fi
  126. echo shar: extracting local_add.c '(1054 characters)'
  127. sed 's/^XX//' << \SHAR_EOF > local_add.c
  128. XX# include    "sp.h"
  129. XX
  130. XX/*
  131. XX** local_add
  132. XX** Add all words in correct list to personal dictionary
  133. XX** and sort the dictionary.
  134. XX*/
  135. XXlocal_add () {
  136. XX    char    *mktemp (),
  137. XX        string[256];
  138. XX    FILE    *fopen (),
  139. XX        *tmp_ptr;
  140. XX    register int    loop;
  141. XX
  142. XX    if ( access (dict, 0) == 0 && access (dict, 2) != 0 ) {
  143. XX        sprintf (string,
  144. XX            "Your local dictionary \"%s\" is not writable!", dict);
  145. XX        message (True, string);
  146. XX        return;
  147. XX    }
  148. XX
  149. XX    if ((tmp_ptr = fopen (mktemp (tmp_file), "w")) == NULL) {
  150. XX        sprintf (string,
  151. XX            "Your local dictionary \"%s\" is not writable!", dict);
  152. XX        message (True, string);
  153. XX        return;
  154. XX    }
  155. XX
  156. XX    for (loop = 0; loop < num_correct; loop++)
  157. XX        fprintf (tmp_ptr, "%s\n", correct[loop]);
  158. XX
  159. XX    fclose (tmp_ptr);
  160. XX
  161. XX    if (vfork () == 0) {
  162. XX        if (local)
  163. XX            execl (SORT, "sort", "-f", "-m", "-o", dict, dict,
  164. XX                tmp_file, (char *) 0);
  165. XX        else
  166. XX            execl (SORT, "sort", "-f", "-m", "-o", dict, tmp_file,
  167. XX                (char *) 0);
  168. XX        perror (SORT);
  169. XX        _exit (-1);
  170. XX    }
  171. XX
  172. XX    wait (0);
  173. XX    sprintf (string, "%d %s added to %s", num_correct,
  174. XX        (num_correct == 1 ? "word" : "words"), dict);
  175. XX    message (False, string);
  176. XX}
  177. SHAR_EOF
  178. if test 1054 -ne "`wc -c local_add.c`"
  179. then
  180. echo shar: error transmitting local_add.c '(should have been 1054 characters)'
  181. fi
  182. echo shar: extracting parse.c '(1156 characters)'
  183. sed 's/^XX//' << \SHAR_EOF > parse.c
  184. XX# include    "sp.h"
  185. XX
  186. XX/*
  187. XX** parse
  188. XX** Parse input for -d option and establish whether
  189. XX** or not a personal dictionary exists
  190. XX*/
  191. XXparse (argc, argv, place)
  192. XXint    argc, *place;
  193. XXchar    *argv[];
  194. XX{
  195. XX    extern    char    *optarg;
  196. XX    extern    int    optind;
  197. XX    char    *getenv (), getopt ();
  198. XX    int    option;
  199. XX
  200. XX    if (argc < 2)
  201. XX        usage (argv[0]);
  202. XX
  203. XX    local = False;
  204. XX    while ((option = getopt (argc, argv, "d:")) != EOF)
  205. XX        switch (option) {
  206. XX            case 'd':
  207. XX                sprintf (dict, "%s", optarg);
  208. XX                local = True;
  209. XX                break;
  210. XX            case '?':
  211. XX            default:
  212. XX                usage (argv[0]);
  213. XX        }
  214. XX
  215. XX    if (argv[optind] == NULL)
  216. XX        usage (argv[0]);
  217. XX
  218. XX    if (!local)
  219. XX        if (getenv ("DICT") != NULL)
  220. XX            strcpy (dict, getenv ("DICT"));
  221. XX        else
  222. XX            strcpy (dict, "./spelldict");
  223. XX
  224. XX    switch (check_dict ()) {
  225. XX        case 1:
  226. XX            local = True;
  227. XX            break;
  228. XX        case 0:
  229. XX            local = False;
  230. XX            printf ("\nYour local dictionary %s does not exist.",
  231. XX                dict);
  232. XX            printf ("\nI may try to create it later ...");
  233. XX            fflush (stdout);
  234. XX            sleep (1);
  235. XX            break;
  236. XX        case -1:
  237. XX            local = False;
  238. XX            printf ("\nYour local dictionary %s is not readable.",
  239. XX                dict);
  240. XX            printf ("\nI may try to write to it later ...");
  241. XX            fflush (stdout);
  242. XX            sleep (1);
  243. XX            break;
  244. XX    }
  245. XX    *place = optind;
  246. XX}
  247. SHAR_EOF
  248. if test 1156 -ne "`wc -c parse.c`"
  249. then
  250. echo shar: error transmitting parse.c '(should have been 1156 characters)'
  251. fi
  252. echo shar: extracting sp.1 '(3717 characters)'
  253. sed 's/^XX//' << \SHAR_EOF > sp.1
  254. XX.\"
  255. XX.\" Copyright (C) 1988 Andrew Large
  256. XX.\"
  257. XX.TH SP 1 "Version 3.4"
  258. XX.DA May 1988
  259. XX.SH NAME
  260. XXsp \- check spelling of a document and fix any mistakes
  261. XX.SH SYNOPSIS
  262. XX.B sp
  263. XX[
  264. XX.B \-d
  265. XX.B dictionary
  266. XX]
  267. XX.B file
  268. XX[
  269. XX.B file2
  270. XX.B ...
  271. XX]
  272. XX.SH DESCRIPTION
  273. XX.IR sp
  274. XXcalls spell(1) to check the spelling of a document.  If you specify a
  275. XXpersonal dictionary (with the \-d option), this is searched in addition
  276. XXto the system dictionary for proper spellings of words.  If you do not
  277. XXspecify a personal dictionary,
  278. XX.IR sp
  279. XXchecks for an environment variable called DICT.  If it exists, it is taken
  280. XXto be the full path to your personal dictionary.  If you do not
  281. XXspecify a personal dictionary or have $DICT defined, the file ``spelldict''
  282. XXin your current directory will be established as your personal dictionary.
  283. XX.PP
  284. XXOnce the mis-spelled words are identified, you are prompted word by
  285. XXword for an action to take.  Your choices are given in brackets and
  286. XXexplained below.
  287. XX.IP A
  288. XXMark the word for addition to your personal dictionary.
  289. XX.IP C
  290. XXMark the word for correction.  You will be asked for the correct spelling.
  291. XX.IP I
  292. XXIgnore the word in question.  This is the default option and is
  293. XXgenerally used when a word is spelled correctly for its usage, but
  294. XXyou don't want it added to your personal dictionary.
  295. XX.IP L
  296. XXLook up a string in the system dictionary.  This is appropriate for
  297. XXobtaining the proper spelling of the word.  You will be prompted for a string
  298. XXthat look(1) will use on the system dictionary.
  299. XX.IP W
  300. XXShow where the word occurs in the document.  Runs grep(1) on the document
  301. XXfile searching for occurrences of the word and prints out lines that
  302. XXcontain the word.
  303. XX.IP ^
  304. XXGo to previous document (given on command line).  If your current document
  305. XXis the first given on the command line, this will re-run spell(1) on your
  306. XXcurrent document.  If you have marked any words for correction or
  307. XXaddition to your personal dictionary, you will be
  308. XXasked whether or not you want to save your changes.
  309. XX.IP #
  310. XXGo to next document (given on command line).  If your current document is
  311. XXthe last given on the command line, this exits the program.  If you
  312. XXhave marked any words for correction or addition to your personal
  313. XXdictionary, you will be asked whether or not you want to save your changes.
  314. XX.IP +
  315. XXGo to next word.  If you haven't taken action with the current word, this
  316. XXoption is equivalent to an ignore (don't correct or add to personal
  317. XXdictionary).  Otherwise, previous actions hold true, i.e. if you correct
  318. XXa word, hit a '-' to go back to it, and hit a '+' to skip forward past it,
  319. XXthe correction would still be the course taken.  However, if you hit an
  320. XX'I' to skip forward past it, no correction would take place.
  321. XX.IP -
  322. XXGo to previous word.  This is the course of action to take if you
  323. XXmess up a correction or change your mind in some way.
  324. XX.IP ?
  325. XXThis will display a short help menu.
  326. XX.IP ^L
  327. XXThis will redraw the screen (as in vi(1)).
  328. XX.PP
  329. XXAfter you have processed all the words, you are prompted for an
  330. XXadditional action.  You may go to either the previous or the next document.
  331. XXIn either case, you will be asked whether or not you wish to save your changes.
  332. XXIn this manner, you can make corrections to a file, and then back up to check
  333. XXyour corrections.  Corrections are made to the documents via
  334. XX.B ex(1).
  335. XX.PP
  336. XXThe spelling checking is done one file at a time, so if you have the same
  337. XXmis-spelled word in several files, you will have to correct it for each file.
  338. XXHowever, the personal dictionary is updated between the checks on each file,
  339. XXso additions to it will be available when the next file is checked.
  340. XX.SH AUTHOR
  341. XXAndrew Large
  342. XX.SH FILES
  343. XX.nf
  344. XX$DICT, spelldict -- default personal dictionaries
  345. XX.fi
  346. XX.SH "SEE ALSO"
  347. XXex(1), grep(1), look(1), spell(1)
  348. SHAR_EOF
  349. if test 3717 -ne "`wc -c sp.1`"
  350. then
  351. echo shar: error transmitting sp.1 '(should have been 3717 characters)'
  352. fi
  353. echo shar: extracting sp.c '(1836 characters)'
  354. sed 's/^XX//' << \SHAR_EOF > sp.c
  355. XX# include    "sp.h"
  356. XX# include    <signal.h>
  357. XX
  358. XX/*
  359. XX** sp(1) -- uses spell(1) to check the spelling of a document.
  360. XX** The user is prompted with each of the mis-spelled words and
  361. XX** can ignore them, add them to a personal dictionary, correct
  362. XX** them, look up words in the dictionary, or find out where in
  363. XX** the file the word is found.  Corrections are made to the
  364. XX** document via ex(1).
  365. XX**
  366. XX** Author: Andrew Large
  367. XX**    December 1986    (First Edition)
  368. XX**    May 1988    (Current Version)
  369. XX*/
  370. XX
  371. XXchar    *id = "@(#)sp.c\t3.4\t5/88";
  372. XX
  373. XXchar    *tmp_file = "/tmp/spXXXXXX";
  374. XXchar    dict[FILE_NAME_LEN], doc[FILE_NAME_LEN],
  375. XX    *new[MAX_WORDS], *correct[MAX_WORDS],
  376. XX    *orig[MAX_WORDS];
  377. XX
  378. XXboolean    local;
  379. XX
  380. XXint    num_found, num_correct, num_ignored;
  381. XX
  382. XXmain (argc, argv)
  383. XXint    argc;
  384. XXchar    *argv[];
  385. XX{
  386. XX    int    place,
  387. XX        spell_val,
  388. XX        start_place;
  389. XX
  390. XX    parse (argc, argv, &place);    /* Parse input arguments */
  391. XX    start_place = place;
  392. XX
  393. XX    /*
  394. XX    ** Initialization
  395. XX    */
  396. XX    signal (SIGINT, leave); signal (SIGQUIT, leave);
  397. XX    initscr (); crmode (); noecho ();
  398. XX    mvaddstr (9, 30, VERSION1);
  399. XX    mvaddstr (10, 28, VERSION2);
  400. XX    mvaddstr (11, 31, VERSION3);
  401. XX    move (0, 0); refresh (); sleep (1);
  402. XX
  403. XX    for (; place < argc; place++) {
  404. XX        sprintf (doc, "%s", argv[place]);
  405. XX        num_found = num_correct = num_ignored = 0;
  406. XX        clean_lists ();
  407. XX
  408. XX        if (check_dict () == 1)
  409. XX            local = True;
  410. XX        else
  411. XX            local = False;
  412. XX
  413. XX        if ( (spell_val = spell ()) >= 0 )
  414. XX            switch (user_input ()) {
  415. XX                case -2:    /* previous doc, no save */
  416. XX                    if (place > start_place)
  417. XX                        place -= 2;
  418. XX                    else
  419. XX                        --place;
  420. XX                    break;
  421. XX                case -1:    /* previous doc, save */
  422. XX                    save (spell_val);
  423. XX                    if (place > start_place)
  424. XX                        place -= 2;
  425. XX                    else
  426. XX                        --place;
  427. XX                    break;
  428. XX                case 0:        /* normal exit with save */
  429. XX                case 1:        /* early exit with save */
  430. XX                    save (spell_val);
  431. XX                case 2:        /* early exit, no save */
  432. XX                default:
  433. XX                    break;
  434. XX            }
  435. XX    }
  436. XX    leave ();
  437. XX}
  438. SHAR_EOF
  439. if test 1836 -ne "`wc -c sp.c`"
  440. then
  441. echo shar: error transmitting sp.c '(should have been 1836 characters)'
  442. fi
  443. echo shar: extracting spell.c '(1884 characters)'
  444. sed 's/^XX//' << \SHAR_EOF > spell.c
  445. XX# include    "sp.h"
  446. XX
  447. XX/*
  448. XX** spell
  449. XX** Run spell(1) on the file and check personal dictionary also.
  450. XX** Establishes the original list of mis-spelled words
  451. XX*/
  452. XXspell () {
  453. XX    char    command[256];
  454. XX    int    ypos, xpos, ret_val;
  455. XX    FILE    *popen (), *fopen (), *spell_out;
  456. XX
  457. XX    clear (); fname ();
  458. XX
  459. XX    ret_val = 0;
  460. XX
  461. XX    if (access (doc, 0) != 0) {    /* Check for existence */
  462. XX        sprintf (command, "Cannot access file %s!", doc);
  463. XX        message (True, command);
  464. XX        return (-1);
  465. XX    }
  466. XX
  467. XX    if (access (doc, 6) != 0) {        /* Read and write */
  468. XX        if (access (doc, 4) != 0) {    /* Read */
  469. XX            sprintf (command, "You are unable to read %s!", doc);
  470. XX            message (True, command);
  471. XX            return (-1);
  472. XX        }
  473. XX        mvaddstr (3, 0, "You are unable to write to this file");
  474. XX        mvaddstr (4, 0, "I will check spelling, but you will not be ");
  475. XX        addstr ("able to save any corrections");
  476. XX        ret_val = 1;
  477. XX        move (0,0); refresh (); sleep (3); fname ();
  478. XX    }
  479. XX
  480. XX    message (False, "Checking spelling ...");
  481. XX
  482. XX    /*
  483. XX    ** Get the list of mis-spelled words
  484. XX    */
  485. XX    if (local)
  486. XX        sprintf (command, "%s %s | %s -v -f %s", SPELL, doc, FGREP,
  487. XX        dict);
  488. XX    else
  489. XX        sprintf (command, "%s %s", SPELL, doc);
  490. XX
  491. XX    spell_out = popen (command, "r");
  492. XX
  493. XX    for (num_found = 0; num_found < MAX_WORDS; num_found++) {
  494. XX        orig[num_found] = sfalloc ((unsigned) WORD_LENGTH);
  495. XX        if (fgets (orig[num_found], WORD_LENGTH, spell_out) == NULL)
  496. XX            break;
  497. XX        else
  498. XX            orig[num_found][strlen (orig[num_found]) - 1] = '\0';
  499. XX    }
  500. XX    fclose (spell_out);
  501. XX
  502. XX    if (num_found >= MAX_WORDS) {
  503. XX        getyx (stdscr, ypos, xpos);
  504. XX        sprintf (command, "You have more than %d mis-spelled words",
  505. XX            MAX_WORDS);
  506. XX        mvaddstr (5, 10, command);
  507. XX        sprintf (command, "Run this again after corrections are made");
  508. XX        mvaddstr (6, 10, command);
  509. XX        move (ypos, xpos); refresh (); sleep (2);
  510. XX    }
  511. XX
  512. XX    addstr (" done");
  513. XX    refresh (); sleep (1);
  514. XX
  515. XX    if (num_found <= 0) {
  516. XX        mvaddstr (5, 0, "No spelling errors");
  517. XX        move (0, 0); refresh (); sleep (1);
  518. XX    }
  519. XX    return (ret_val);
  520. XX}
  521. SHAR_EOF
  522. if test 1884 -ne "`wc -c spell.c`"
  523. then
  524. echo shar: error transmitting spell.c '(should have been 1884 characters)'
  525. fi
  526. echo shar: extracting user_input.c '(1921 characters)'
  527. sed 's/^XX//' << \SHAR_EOF > user_input.c
  528. XX# include    "sp.h"
  529. XX
  530. XX/*
  531. XX** user_input -- user interface for correcting mis-spelled words
  532. XX*/
  533. XXuser_input () {
  534. XX    char    string[WORD_LENGTH + 20];
  535. XX    boolean    done;
  536. XX    register int    loop;
  537. XX
  538. XX    for (loop = 0; loop < num_found; loop++) {
  539. XX        page_clear (loop + 1, False);
  540. XX        sprintf (string, "Word ``%s'' is not in the dictionary",
  541. XX            orig[loop]);
  542. XX        mvaddstr (3, 0, string); refresh ();
  543. XX
  544. XX        done = False;
  545. XX        do {
  546. XX            sprintf (string, "(%s) [ilwac^#+-?] ", orig[loop]);
  547. XX            mvaddstr (5, 0, string); refresh ();
  548. XX
  549. XX            switch (getch ()) {
  550. XX                case 'I':
  551. XX                case 'i':
  552. XX                case ' ':
  553. XX                case '\n':
  554. XX                case '\r':
  555. XX                    addstr ("Ignore"); refresh ();
  556. XX                    done = True; ignore (loop);
  557. XX                    break;
  558. XX                case 'L':
  559. XX                case 'l':
  560. XX                    addstr ("Lookup"); refresh ();
  561. XX                    lookup (loop);
  562. XX                    break;
  563. XX                case 'W':
  564. XX                case 'w':
  565. XX                    addstr ("Where"); refresh ();
  566. XX                    where (loop);
  567. XX                    break;
  568. XX                case 'A':
  569. XX                case 'a':
  570. XX                    addstr ("Add"); refresh ();
  571. XX                    done = True; add (loop);
  572. XX                    break;
  573. XX                case 'C':
  574. XX                case 'c':
  575. XX                    addstr ("Correct"); refresh ();
  576. XX                    done = True; word_correct (loop);
  577. XX                    break;
  578. XX                case '^':
  579. XX                    addstr ("Previous Document");
  580. XX                    refresh ();
  581. XX                    if (ask_save (loop) == 1)
  582. XX                        return (-1);
  583. XX                    else
  584. XX                        return (-2);
  585. XX                case '#':
  586. XX                    addstr ("Next Document");
  587. XX                    refresh ();
  588. XX                    if (ask_save (loop) == 1)
  589. XX                        return (1);
  590. XX                    else
  591. XX                        return (2);
  592. XX                case '+':
  593. XX                    addstr ("Next Word");
  594. XX                    refresh ();
  595. XX                    done = True;
  596. XX                    if (new[loop] == NULL)
  597. XX                        ignore (loop);
  598. XX                    break;
  599. XX                case '-':
  600. XX                    addstr ("Previous Word");
  601. XX                    refresh ();
  602. XX                    done = True;
  603. XX                    if (loop > 0) loop -=2;
  604. XX                    else --loop;
  605. XX                    break;
  606. XX                case 'H':
  607. XX                case 'h':
  608. XX                case '?':
  609. XX                    addstr ("Help!"); refresh ();
  610. XX                    help (loop);
  611. XX                    break;
  612. XX                case CTRL_L:
  613. XX                case CTRL_R:
  614. XX                    page_clear (loop + 1, True);
  615. XX                default:
  616. XX                    page_clear (loop + 1, False);
  617. XX                    break;
  618. XX            }
  619. XX        } while (!done);
  620. XX    }
  621. XX    return (ask_action ());
  622. XX}
  623. SHAR_EOF
  624. if test 1921 -ne "`wc -c user_input.c`"
  625. then
  626. echo shar: error transmitting user_input.c '(should have been 1921 characters)'
  627. fi
  628. echo shar: extracting MANIFEST '(610 characters)'
  629. sed 's/^XX//' << \SHAR_EOF > MANIFEST
  630. XXFILE        WHAT
  631. XX--------------------------
  632. XXMANIFEST    This file -- list of files in package
  633. XXMakefile    For making executable
  634. XXREADME        Read this first for installation and copyright information
  635. XXdoc_correct.c    Source for document correction
  636. XXlocal_add.c    Source for adding to personal dictionary
  637. XXparse.c        Command line parser (calls getopt)
  638. XXsp.1        Manual page
  639. XXsp.c        Main program
  640. XXsp.h        Include file (may need editing)
  641. XXspell.c        Runs spell(1) and fgrep(1) to get initial mis-spelling list
  642. XXtools.c        General tools used througout program
  643. XXuser_input.c    Get user input for corrections
  644. XXuser_tools.c    Process option selected in user_input
  645. SHAR_EOF
  646. if test 610 -ne "`wc -c MANIFEST`"
  647. then
  648. echo shar: error transmitting MANIFEST '(should have been 610 characters)'
  649. fi
  650. echo shar: extracting tools.c '(3116 characters)'
  651. sed 's/^XX//' << \SHAR_EOF > tools.c
  652. XX# include    "sp.h"
  653. XX
  654. XX
  655. XX/*
  656. XX** ask_more
  657. XX** Prompt the user to continue.
  658. XX*/
  659. XXask_more () {
  660. XX    standout ();
  661. XX    mvaddstr (23, 29, "Hit any key to continue");
  662. XX    standend ();
  663. XX    refresh (); getch ();
  664. XX}
  665. XX
  666. XX
  667. XX/*
  668. XX** check_dict
  669. XX** Check for existence/read permission on dictionary.
  670. XX*/
  671. XXcheck_dict () {
  672. XX    if ( access (dict, 4) == 0 )        /* Read permission */
  673. XX        return (1);
  674. XX    else
  675. XX        if ( access (dict, 0) != 0 )    /* Existence check */
  676. XX            return (0);
  677. XX        else
  678. XX            return (-1);
  679. XX}
  680. XX
  681. XX
  682. XX/*
  683. XX** clean_lists
  684. XX** Clean up the three lists used in the program.
  685. XX*/
  686. XXclean_lists () {
  687. XX    register int    i;
  688. XX
  689. XX    for (i = 0; i < MAX_WORDS; i++) {
  690. XX        if (orig[i] != NULL) {
  691. XX            free (orig[i]); orig[i] = NULL;
  692. XX        }
  693. XX        if (new[i] != NULL) {
  694. XX            free (new[i]); new[i] = NULL;
  695. XX        }
  696. XX        if (correct[i] != NULL) {
  697. XX            free (correct[i]); correct[i] = NULL;
  698. XX        }
  699. XX    }
  700. XX}
  701. XX
  702. XX
  703. XX/*
  704. XX** curse_die
  705. XX** Die with an explanation when inside of curses
  706. XX*/
  707. XXcurse_die (string)
  708. XXchar    *string;
  709. XX{
  710. XX    extern int    errno;
  711. XX    extern    char    *sys_errlist[];
  712. XX    char    line[256];
  713. XX
  714. XX    sprintf (line, "Fatal Error, %s:%s", string, sys_errlist[errno]);
  715. XX    message (True, line);
  716. XX    leave ();
  717. XX}
  718. XX
  719. XX
  720. XX/*
  721. XX** fname
  722. XX** Print out the page header (file name, etc.)
  723. XX*/
  724. XXfname () {
  725. XX    erase ();
  726. XX    mvaddstr (0, (65 - strlen (doc)) / 2,    /* (80-overhead-len) / 2 */
  727. XX        "[ --- ");
  728. XX    standout ();
  729. XX    addch (' '); addstr (doc); addch (' ');
  730. XX    standend ();
  731. XX    addstr (" --- ]");
  732. XX}
  733. XX
  734. XX
  735. XX/*
  736. XX** leave
  737. XX** Clean up curses and exit.
  738. XX*/
  739. XXvoid    leave () {
  740. XX    unlink (tmp_file);
  741. XX    clear (); move (23, 0); refresh ();
  742. XX    endwin ();
  743. XX    exit (0);
  744. XX}
  745. XX
  746. XX
  747. XX/*
  748. XX** message
  749. XX** Write message on the screen
  750. XX*/
  751. XXmessage (error, line)
  752. XXboolean    error;
  753. XXchar    *line;
  754. XX{
  755. XX    page_clear (0, False);
  756. XX
  757. XX    if (error) {
  758. XX        addch ('\07');
  759. XX        mvaddstr (3, (78 - strlen (line)) / 2, line);
  760. XX        move (0,0);
  761. XX        refresh (); sleep (2);
  762. XX    }
  763. XX    else {
  764. XX        mvaddstr (3, (78 - strlen (line)) / 2, line);
  765. XX        refresh (); sleep (1);
  766. XX    }
  767. XX}
  768. XX
  769. XX
  770. XX/*
  771. XX** page_clear
  772. XX** Clear part of the screen and display the number
  773. XX** of the current word
  774. XX*/
  775. XXpage_clear (word_num, cls)
  776. XXint    word_num;
  777. XXboolean    cls;
  778. XX{
  779. XX    char    str[20];
  780. XX
  781. XX    if (cls)
  782. XX        clear ();
  783. XX    fname ();
  784. XX    if (word_num != 0) {
  785. XX        sprintf (str, "Word #%d of %d", word_num, num_found);
  786. XX        mvaddstr (23, 79 - strlen (str), str);
  787. XX        mvaddstr (23, 0, VERSION1);
  788. XX    }
  789. XX    move (3, 0);
  790. XX    refresh ();
  791. XX}
  792. XX
  793. XX
  794. XX/*
  795. XX** safe_copy
  796. XX** A pre-malloced copy from one string to another
  797. XX*/
  798. XXsafe_copy (string1, string2)
  799. XXchar    **string1,
  800. XX    *string2;
  801. XX{
  802. XX    if (*string1 == NULL)
  803. XX        *string1 = sfalloc ((unsigned) strlen (string2) + 1);
  804. XX    strcpy (*string1, string2);
  805. XX}
  806. XX
  807. XX
  808. XX/*
  809. XX** save
  810. XX** Save changes made to document
  811. XX*/
  812. XXsave (spell_val)
  813. XXint    spell_val;
  814. XX{
  815. XX    if (num_correct > 0)
  816. XX        local_add ();
  817. XX
  818. XX    if (num_found == (num_correct + num_ignored))
  819. XX        message (False, "No corrections made");
  820. XX    else
  821. XX        if (spell_val == 0) doc_correct ();
  822. XX}
  823. XX
  824. XX
  825. XX/*
  826. XX** sfalloc
  827. XX** A safe malloc ()
  828. XX*/
  829. XXchar    *sfalloc (num_bytes)
  830. XXunsigned    num_bytes;
  831. XX{
  832. XX    char    *calloc (), *hold;
  833. XX
  834. XX    if (num_bytes == 0) return ((char *) NULL);
  835. XX
  836. XX    if ( (hold = calloc (1, num_bytes)) == NULL)
  837. XX        curse_die ("calloc");
  838. XX
  839. XX    return (hold);
  840. XX}
  841. XX
  842. XX
  843. XX/*
  844. XX** usage
  845. XX** Print out program usage statement and exit.
  846. XX*/
  847. XXusage (name)
  848. XXchar    *name;
  849. XX{
  850. XX    fprintf (stderr, "Usage: %s [ -d dictionary ] file [ file2 ... ]\n",
  851. XX        name);
  852. XX    exit (1);
  853. XX}
  854. SHAR_EOF
  855. if test 3116 -ne "`wc -c tools.c`"
  856. then
  857. echo shar: error transmitting tools.c '(should have been 3116 characters)'
  858. fi
  859. echo shar: extracting sp.h '(1329 characters)'
  860. sed 's/^XX//' << \SHAR_EOF > sp.h
  861. XX/*
  862. XX** Configuration options for sp
  863. XX*/
  864. XX
  865. XX# include    <curses.h>        /* includes <stdio.h> */
  866. XX
  867. XX# define    True    1
  868. XX# define    False    0
  869. XX
  870. XX# define    VERSION1    "Sp Version 3.4"
  871. XX# define    VERSION2    "Copyright (C) 1988"
  872. XX# define    VERSION3    "Andrew Large"
  873. XX
  874. XX/*
  875. XX** Lookup dictionary -- use /usr/dict/web2 if you have it
  876. XX*/
  877. XX# define    L_DICT    "/usr/dict/words"
  878. XX
  879. XX/*
  880. XX** Location of common programs
  881. XX*/
  882. XX# define    EX    "/usr/ucb/ex"
  883. XX# define    FGREP    "/usr/bin/fgrep"
  884. XX# define    GREP    "/bin/grep"
  885. XX# define    LOOK    "/usr/bin/look"
  886. XX# define    MORE    "/usr/ucb/more"
  887. XX# define    SORT    "/usr/bin/sort"
  888. XX# define    SPELL    "/usr/bin/spell"
  889. XX
  890. XX/*
  891. XX** Constant sizes
  892. XX*/
  893. XX# define    MAX_WORDS    512    /* Max words corrected on one pass */
  894. XX# define    WORD_LENGTH    256    /* Max length of a word */
  895. XX# define    FILE_NAME_LEN    256    /* Max length of a file name */
  896. XX
  897. XX# define    CTRL_R        022
  898. XX# define    CTRL_L        014
  899. XX
  900. XXtypedef    unsigned char    boolean;
  901. XX
  902. XXextern    char    *tmp_file,
  903. XX        dict[FILE_NAME_LEN],    /* Name of personal dictionary */
  904. XX        doc[FILE_NAME_LEN],    /* Name of document you are checking */
  905. XX        *orig[MAX_WORDS],    /* Original list of mis-spelled words */
  906. XX        *new[MAX_WORDS],    /* New list (with corrections, etc) */
  907. XX        *correct[MAX_WORDS];    /* Words to be added to personal dict */
  908. XX
  909. XXextern    boolean    local;            /* Whether we have a personal dict */
  910. XX
  911. XXextern    int    num_found, num_correct, num_ignored;
  912. XX
  913. XXextern    void    leave ();
  914. XXextern    char    *sfalloc ();
  915. SHAR_EOF
  916. if test 1329 -ne "`wc -c sp.h`"
  917. then
  918. echo shar: error transmitting sp.h '(should have been 1329 characters)'
  919. fi
  920. echo shar: extracting user_tools.c '(3572 characters)'
  921. sed 's/^XX//' << \SHAR_EOF > user_tools.c
  922. XX# include    "sp.h"
  923. XX
  924. XX
  925. XX/*
  926. XX** add
  927. XX** Add an entry into list of words to be added to personal dict
  928. XX*/
  929. XXadd (word_num)
  930. XXint    word_num;
  931. XX{
  932. XX    safe_copy (& (correct[num_correct++]), orig[word_num]);
  933. XX    safe_copy (& (new[word_num]), orig[word_num]);
  934. XX}
  935. XX
  936. XX
  937. XX/*
  938. XX** ask_action
  939. XX** Ask the user what to do after processing words
  940. XX*/
  941. XXask_action () {
  942. XX    char    done;
  943. XX
  944. XX    done = False;
  945. XX    while (!done) {
  946. XX        page_clear (0, False);
  947. XX        mvaddstr (3, 0, "Action? [#^?] ");
  948. XX        refresh ();
  949. XX
  950. XX        switch (getch ()) {
  951. XX            case ' ': case '\n': case '\r':
  952. XX            case '#':
  953. XX                done = True;
  954. XX                addstr ("Next Document"); refresh ();
  955. XX                if (ask_save (num_found) == 1) return (0);
  956. XX                else return (2);
  957. XX            case '^':
  958. XX                done = True;
  959. XX                addstr ("Previous Document"); refresh ();
  960. XX                if (ask_save (num_found) == 1) return (-1);
  961. XX                else return (-2);
  962. XX            case '?':
  963. XX                addstr ("Help!"); refresh ();
  964. XX                mvaddstr (5, 10, "# --- Go to next document (or exit)");
  965. XX                mvaddstr (6, 10, "^ --- Go to previous document (or re-spell this one)");
  966. XX                mvaddstr (7, 10, "? --- This help message");
  967. XX                ask_more ();
  968. XX            default:
  969. XX                break;
  970. XX        }
  971. XX    }
  972. XX    return (0);
  973. XX}
  974. XX
  975. XX
  976. XX/*
  977. XX** ask_save
  978. XX** Ask user if he/she wants to save these changes
  979. XX*/
  980. XXask_save (word_num)
  981. XXint    word_num;
  982. XX{
  983. XX    char    ch;
  984. XX
  985. XX    if (word_num == num_ignored) return (0);
  986. XX    mvaddstr (7, 0, "Do you wish to save your changes? [y] ");
  987. XX    refresh ();
  988. XX    if ( (ch = getch ()) == 'n' || ch == 'N' ) return (0);
  989. XX    return (1);
  990. XX}
  991. XX
  992. XX
  993. XX/*
  994. XX** correct
  995. XX** Get correct spelling for a word
  996. XX*/
  997. XXword_correct (word_num)
  998. XXint    word_num;
  999. XX{
  1000. XX    mvaddstr (7, 0, "****** Proper spelling: ");
  1001. XX
  1002. XX    nocrmode (); echo (); refresh ();
  1003. XX
  1004. XX    if (new[word_num] == NULL)
  1005. XX        new[word_num] = sfalloc ((unsigned) WORD_LENGTH + 1);
  1006. XX    gets (new[word_num]);
  1007. XX
  1008. XX    crmode (); noecho ();
  1009. XX    ask_more (); page_clear (word_num + 1, True);
  1010. XX}
  1011. XX
  1012. XX
  1013. XX/*
  1014. XX** help
  1015. XX** Give user some help with commands
  1016. XX*/
  1017. XXhelp (word_num)
  1018. XXint    word_num;
  1019. XX{
  1020. XX    mvaddstr ( 7, 10, "     I --- Ignore all occurrences of word");
  1021. XX    mvaddstr ( 8, 10, "     L --- Lookup a sub-string in the dictionary");
  1022. XX    mvaddstr ( 9, 10, "     W --- show Where word occurs in the document");
  1023. XX    mvaddstr (10, 10, "     A --- Add word to your personal dictionary");
  1024. XX    mvaddstr (11, 10, "     C --- Correct all occurrences of the word");
  1025. XX    mvaddstr (12, 10, "     ^ --- go to previous document (or re-spell this one)");
  1026. XX    mvaddstr (13, 10, "     # --- go to next document (or exit)");
  1027. XX    mvaddstr (14, 10, "     + --- go to next word");
  1028. XX    mvaddstr (15, 10, "     - --- go to previous word");
  1029. XX    mvaddstr (16, 10, " ?,  H --- this help message");
  1030. XX    mvaddstr (17, 10, "^R, ^L --- redraw the screen");
  1031. XX    ask_more ();
  1032. XX    page_clear (word_num + 1, False);
  1033. XX}
  1034. XX
  1035. XX
  1036. XX/*
  1037. XX** ignore
  1038. XX** Ignore the word (i.e. don't substitute for it)
  1039. XX*/
  1040. XXignore (word_num)
  1041. XXint    word_num;
  1042. XX{
  1043. XX    safe_copy (& (new[word_num]), orig[word_num]);
  1044. XX    num_ignored++;
  1045. XX}
  1046. XX
  1047. XX
  1048. XX/*
  1049. XX** lookup
  1050. XX** Look up string in the dictionary
  1051. XX*/
  1052. XXlookup (word_num)
  1053. XXint    word_num;
  1054. XX{
  1055. XX    char    hold_str[WORD_LENGTH + 1],
  1056. XX        command[BUFSIZ];
  1057. XX
  1058. XX    mvaddstr (7, 0, "****** Lookup string: ");
  1059. XX    refresh ();
  1060. XX
  1061. XX    echo (); nocrmode (); gets (hold_str);
  1062. XX    move (8, 0); clrtobot (); move (8, 0); refresh ();
  1063. XX
  1064. XX    sprintf (command, "%s -df %s %s | %s", LOOK, hold_str, L_DICT, MORE);
  1065. XX    system (command);
  1066. XX
  1067. XX    crmode (); noecho (); ask_more ();
  1068. XX    page_clear (word_num + 1, True);
  1069. XX}
  1070. XX
  1071. XX/*
  1072. XX** where
  1073. XX** Show where a word occurs in the document
  1074. XX*/
  1075. XXwhere (word_num)
  1076. XXint    word_num;
  1077. XX{
  1078. XX    char    command[BUFSIZ];
  1079. XX
  1080. XX    move (7, 0); clrtobot (); move (7, 0); echo (); nocrmode (); refresh ();
  1081. XX    sprintf (command, "%s -w %s %s | %s", GREP, orig[word_num], doc, MORE);
  1082. XX    system (command);
  1083. XX
  1084. XX    crmode (); noecho (); ask_more ();
  1085. XX    page_clear (word_num + 1, True);
  1086. XX}
  1087. SHAR_EOF
  1088. if test 3572 -ne "`wc -c user_tools.c`"
  1089. then
  1090. echo shar: error transmitting user_tools.c '(should have been 3572 characters)'
  1091. fi
  1092. echo shar: extracting doc_correct.c '(677 characters)'
  1093. sed 's/^XX//' << \SHAR_EOF > doc_correct.c
  1094. XX# include    "sp.h"
  1095. XX
  1096. XX/*
  1097. XX** doc_correct
  1098. XX** Correct the document, based upon the difference between the
  1099. XX** original list and the new list of words.  Uses EX to make the
  1100. XX** corrections.
  1101. XX*/
  1102. XXdoc_correct () {
  1103. XX    register int    loop;
  1104. XX    FILE    *fopen (), *popen (), *ex_ptr;
  1105. XX    char    command[256];
  1106. XX
  1107. XX    page_clear (0, False);
  1108. XX    mvaddstr (3, 0, "Making changes ..."); refresh ();
  1109. XX
  1110. XX    sprintf (command, "%s - %s", EX, doc);
  1111. XX    ex_ptr = popen (command, "w");
  1112. XX
  1113. XX    for (loop = 0; loop < num_found; loop++)
  1114. XX        if (strcmp (orig[loop], new[loop]) != 0)
  1115. XX            fprintf (ex_ptr, "1,$s/\\<%s\\>/%s/g\n", orig[loop],
  1116. XX                new[loop]);
  1117. XX
  1118. XX    fprintf (ex_ptr, "w\nq\n"); fclose (ex_ptr);
  1119. XX
  1120. XX    addstr (" done"); refresh (); sleep (1);
  1121. XX}
  1122. SHAR_EOF
  1123. if test 677 -ne "`wc -c doc_correct.c`"
  1124. then
  1125. echo shar: error transmitting doc_correct.c '(should have been 677 characters)'
  1126. fi
  1127. echo shar: done with directory sp
  1128. cd ..
  1129. #    End of shell archive
  1130. exit 0
  1131.