home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume5 / sp4 < prev    next >
Internet Message Format  |  1989-02-03  |  38KB

  1. Path: xanth!nic.MR.NET!hal!ncoast!allbery
  2. From: predict%charon.unm.edu@ariel.unm.edu (Andrew R. Large)
  3. Newsgroups: comp.sources.misc
  4. Subject: v05i051: sp version 4.0
  5. Message-ID: <18617.8811140812@charon.unm.edu>
  6. Date: 15 Nov 88 00:36:07 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Reply-To: predict%charon.unm.edu@ariel.unm.edu (Andrew R. Large)
  9. Lines: 1448
  10. Approved: allbery@ncoast.UUCP
  11.  
  12. Posting-number: Volume 5, Issue 51
  13. Submitted-by: "Andrew R. Large" <predict%charon.unm.edu@ariel.unm.edu>
  14. Archive-name: sp4
  15.  
  16. This is the new version of my visual spelling checker.
  17.  
  18. I've incorporated a few bug fixes (including the pclose one) and a warning
  19. about one I couldn't take care of (spell and ex have slightly different
  20. ideas of what makes a word).
  21.  
  22. I found out that SYSV didn't have a -w flag on their grep.  This brought
  23. the usefulness of the `where' function down, so ... I wrote an in-line search
  24. routine that carries with it a context window, so you can see the lines before
  25. and after the word.  You can change the default number of lines in the context
  26. window with a new command line -w option (see the man page).  Enjoy!
  27.  
  28. [Of course, you could always use "context" (plug plug ;-)  ++bsa]
  29.  
  30.  -=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-
  31.    *                          Andrew R. Large                              *
  32.   **  (work) 505/255-8611 ------|     Univ of New Mexico EECE Department   **
  33.  ***  (home) 505/888-4010       |---> Management Sciences, Inc. [MSI]      ***
  34. ****                            _Babooshka!_                               ****
  35.  ***  Usenet: {convex,gatech,ucbvax,csu-cs,anl-mcs}!unmvax!charon!predict  ***
  36.   **  Internet: predict@charon.UNM.EDU                                     **
  37.    *          If I am quoted, my employers will deny my existence.         *
  38.  -=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-
  39.  
  40. --------------------------------- CUT HERE -----------------------------------
  41. #!/bin/sh
  42. # shar:    Shell Archiver
  43. #    Run the following text with /bin/sh to create:
  44. #    sp
  45. # This archive created: Mon Nov 14 01:00:49 1988
  46. # By:    Andrew R. Large (University of New Mexico, Albuquerque)
  47. echo shar: creating directory sp
  48. mkdir sp
  49. cd sp
  50. echo shar: extracting Makefile '(607 characters)'
  51. sed 's/^XX//' << \SHAR_EOF > Makefile
  52. XX#! /bin/sh
  53. XX#
  54. XX# Makefile for sp
  55. XX# Written by Andrew Large
  56. XX#
  57. XX# Edit BIN, MAN, CC and CFLAGS
  58. XX#
  59. XX
  60. XXBIN = /u1/staff/andy/bin
  61. XXMAN = /u1/staff/andy/man
  62. XX
  63. XXEXEC = sp
  64. XXMANPAGE = $(EXEC).1
  65. XXHDRS = $(EXEC).h
  66. XX
  67. XXOBJS = $(EXEC).o add_local.o doc_correct.o externs.o parse.o spell.o tools.o\
  68. XX    user_input.o user_tools.o where.o
  69. XXLIBS = -lcurses -ltermlib
  70. XXCC = cc
  71. XX
  72. XX#
  73. XX# If you are a BSD system, then BSD
  74. XX# CFLAGS = -O
  75. XXCFLAGS = -O -DBSD
  76. XX
  77. XX$(EXEC): $(OBJS)
  78. XX    $(CC) $(CFLAGS) $(OBJS) -o $@ $(LIBS)
  79. XX
  80. XXinstall: $(EXEC)
  81. XX    strip $(EXEC)
  82. XX    cp $(EXEC) $(BIN)
  83. XX    cp $(MANPAGE) $(MAN)/man1
  84. XX
  85. XX$(OBJS): $(HDRS)
  86. XX
  87. XXclean:
  88. XX    /bin/rm -f $(EXEC) core *.o *.out
  89. SHAR_EOF
  90. if test 607 -ne "`wc -c Makefile`"
  91. then
  92. echo shar: error transmitting Makefile '(should have been 607 characters)'
  93. fi
  94. echo shar: extracting README '(1682 characters)'
  95. sed 's/^XX//' << \SHAR_EOF > README
  96. XX** SP **
  97. XX
  98. XXSp is a visual spelling program that is based upon existing UN*X utilites.
  99. XXIt may be run on one or more files, and for each file, it presents a
  100. XXword-by-word list of the words received from spell(1).  You may then take
  101. XXany of a host of actions.
  102. XX
  103. XXThis program has come through many stages during its development.  When it was
  104. XXoriginally written, it was designed around a shell script posted in net.sources
  105. XXin 1985 that put all misspelled words into a file, had you correct the file,
  106. XXand then, from the difference between the files, made the corrections.
  107. XX
  108. XXThe current version is so different from the original shell script that I don't
  109. XXcredit the original authors any more.  After completing this program, I have
  110. XXnoticed a resemblance to both `ispell' and `correct'.  However, this was written
  111. XXbefore I ever saw either of those programs, and no code was taken from either
  112. XXone when writing this.
  113. XX
  114. XXTo install:
  115. XX
  116. XX    1) Edit `sp.h' to reflect your current situation (mainly locations
  117. XX    of system programs).
  118. XX
  119. XX    2) Edit Makefile and change `BIN', `MAN', `CC', and `CFLAGS' to
  120. XX    their proper values.
  121. XX
  122. XX    3) Type `make'.
  123. XX
  124. XX    4) If everything tests out ok, type `make install'.
  125. XX
  126. XXCopyright (C) 1988 Andrew Large
  127. XX
  128. XXThis software may be used and/or modified on any machine by anyone, as long
  129. XXas you don't violate the following conditions:
  130. XX
  131. XX    1) This copyright notice and the one in the program are left intact.
  132. XX
  133. XX    2) You credit me with original authorship.
  134. XX
  135. XX    3) No monetary gain is made by selling or distributing this software.
  136. XX
  137. XXI will be more than willing to try and support any additions/bug-fixes, but I
  138. XXWILL NOT ACCEPT RESPONSIBILITY FOR ANY HARM CAUSED DIRECTLY OR INDIRECTLY BY
  139. XXTHIS PROGRAM.
  140. SHAR_EOF
  141. if test 1682 -ne "`wc -c README`"
  142. then
  143. echo shar: error transmitting README '(should have been 1682 characters)'
  144. fi
  145. echo shar: extracting where.c '(3717 characters)'
  146. sed 's/^XX//' << \SHAR_EOF > where.c
  147. XX# include "sp.h"
  148. XX# include <ctype.h>
  149. XX# define    LEAVE    {\
  150. XX    fclose (fp); free2 (window, window_size);\
  151. XX    page_clear (word_num+1, True); return;\
  152. XX}
  153. XX# define    letter(ch)    (isalpha (ch) || ch == '.')
  154. XX
  155. XX/*
  156. XX** where
  157. XX** Show where a word occurs in the document with surrounding context.
  158. XX*/
  159. XXwhere (word_num)
  160. XXint    word_num;
  161. XX{
  162. XX    extern    char    *bad_words[], *spell_doc;
  163. XX    extern    char    sys_errlist[];
  164. XX    extern    int    errno, window_size;
  165. XX    FILE    *fp;
  166. XX    char    *window[MAX_WINDOW], line[BUFSIZ], *word;
  167. XX    boolean    done = False;
  168. XX    int    mid;
  169. XX    register int    i, nlines;
  170. XX
  171. XX    move (7,0); clrtobot (); move (7,0); refresh ();
  172. XX    if ((fp = fopen (spell_doc, "r")) == NULL) {
  173. XX        sprintf (line, "Can't open %s for read: %s", spell_doc,
  174. XX            sys_errlist[errno]);
  175. XX        message (True, line);
  176. XX        ask_more (); page_clear (word_num + 1, True); return;
  177. XX    }
  178. XX
  179. XX    for (i=0; i < window_size; window[i++] = NULL);
  180. XX    word = bad_words[word_num];
  181. XX    nlines = ctx_open (fp, window, window_size);
  182. XX    mid = nlines / 2;
  183. XX
  184. XX    for (i=0; i < mid; i++)
  185. XX        if (ctx_display (window, word, nlines, i)) LEAVE
  186. XX
  187. XX    while (!done) {
  188. XX        if (ctx_display (window, word, nlines, mid)) LEAVE
  189. XX        done = ctx_step (fp, window, window_size);
  190. XX    }
  191. XX
  192. XX    for (i=mid+1; i < nlines; i++)
  193. XX        if (ctx_display (window, word, nlines, i)) LEAVE
  194. XX    LEAVE
  195. XX}
  196. XX
  197. XX
  198. XX/*
  199. XX** ctx_display
  200. XX** If the interest line has the word in it, then display the identified
  201. XX** window with the word in reverse video.  Return True if the user doesn't
  202. XX** want to see any more occurances.
  203. XX*/
  204. XXctx_display (window, word, nlines, chkline)
  205. XXchar    *window[], *word;
  206. XXint    nlines, chkline;
  207. XX{
  208. XX    int    beg, end;
  209. XX    register int    line, ch;
  210. XX    char    c;
  211. XX
  212. XX    word_in (window[chkline], word, &beg, &end);
  213. XX    if (beg != -1) {
  214. XX        for (line = 0; line < chkline; line++)
  215. XX            mvaddstr (line+7, 0, window[line]);
  216. XX
  217. XX        for (ch = 0; ch < beg; ch++)
  218. XX            mvaddch (chkline+7, ch, window[chkline][ch]);
  219. XX        standout ();
  220. XX        for (ch = beg; ch <= end; ch++)
  221. XX            mvaddch (chkline+7, ch, window[chkline][ch]);
  222. XX        standend ();
  223. XX        for (ch = end+1; window[chkline][ch]; ch++)
  224. XX            mvaddch (chkline+7, ch, window[chkline][ch]);
  225. XX
  226. XX        for (line = chkline + 1; line < nlines; line++)
  227. XX            mvaddstr (line+7, 0, window[line]);
  228. XX
  229. XX        mvaddstr (23,0,
  230. XX            "Hit any key for next occurrence, <Esc> to return: ");
  231. XX        refresh ();
  232. XX
  233. XX        if (getch() != ESC)
  234. XX            return False;
  235. XX        else
  236. XX            return True;
  237. XX    }
  238. XX    return False;
  239. XX}
  240. XX
  241. XX
  242. XX/*
  243. XX** ctx_open
  244. XX** Open a context window of n lines.  Return the number of
  245. XX** lines read in.
  246. XX*/
  247. XXctx_open (fp, window, n)
  248. XXFILE    *fp;
  249. XXchar    *window[];
  250. XXint    n;
  251. XX{
  252. XX    register int    i;
  253. XX    char    line[BUFSIZ+1];
  254. XX
  255. XX    for (i=0; i < n; i++) {
  256. XX        if (fgets (line, BUFSIZ+1, fp) == NULL) return i;
  257. XX        safe_copy (&window[i], line);
  258. XX    }
  259. XX    return n;
  260. XX}
  261. XX
  262. XX
  263. XX/*
  264. XX** ctx_step
  265. XX** Move down the context window by one line
  266. XX*/
  267. XXctx_step (fp, window, n)
  268. XXFILE    *fp;
  269. XXchar    *window[];
  270. XXint    n;
  271. XX{
  272. XX    char    line[BUFSIZ+1];
  273. XX    register int    i;
  274. XX
  275. XX    if (fgets (line, BUFSIZ+1, fp) == NULL) return True;
  276. XX
  277. XX    free (window[0]);
  278. XX    for (i=0; i < (n-1); i++)
  279. XX        window[i] = window[i+1];
  280. XX
  281. XX    window[n-1] = NULL;
  282. XX    safe_copy (&window[n-1], line);
  283. XX
  284. XX    return False;
  285. XX}
  286. XX
  287. XX
  288. XX/*
  289. XX** word_in
  290. XX** If the given word occurs in the string, return the starting
  291. XX** and ending indices.  May show a few occurances _not_ found
  292. XX** by spell.
  293. XX*/
  294. XXword_in (line, word, beg, end)
  295. XXchar    *line, *word;
  296. XXint    *beg, *end;
  297. XX{
  298. XX    register int    i, len;
  299. XX
  300. XX    *beg = *end = -1;
  301. XX    len = strlen (word);
  302. XX
  303. XX    if (strncmp (line, word, len) == 0 && !letter (line[len])) {
  304. XX        *beg = 0; *end = len - 1;
  305. XX        return;
  306. XX    }
  307. XX
  308. XX    /*
  309. XX    ** 1. Skip past current word
  310. XX    ** 2. Skip to beginning of next word
  311. XX    ** 3. If this is not the correct word, go back to 1.
  312. XX    */
  313. XX    i=0;
  314. XX    while (line[i]) {
  315. XX        while (letter (line[i])) i++;
  316. XX        while (line[i] && !letter (line[i])) i++;
  317. XX        if (line[i] && strncmp (&line[i], word, len) == 0 &&
  318. XX            !letter (line[i+len])) {
  319. XX            *beg = i; *end = i + len - 1;
  320. XX            return;
  321. XX        }
  322. XX    }
  323. XX}
  324. SHAR_EOF
  325. if test 3717 -ne "`wc -c where.c`"
  326. then
  327. echo shar: error transmitting where.c '(should have been 3717 characters)'
  328. fi
  329. echo shar: extracting parse.c '(1463 characters)'
  330. sed 's/^XX//' << \SHAR_EOF > parse.c
  331. XX# include    "sp.h"
  332. XX
  333. XX/*
  334. XX** parse
  335. XX** Parse input for -d and -w options and establish whether
  336. XX** or not a personal dictionary exists
  337. XX*/
  338. XXparse (argc, argv, place)
  339. XXint    argc, *place;
  340. XXchar    *argv[];
  341. XX{
  342. XX    extern    char    *optarg, *local_dict;
  343. XX    extern    int    optind, window_size;
  344. XX    extern    boolean    local;
  345. XX    char    *getenv (), getopt ();
  346. XX    int    option;
  347. XX
  348. XX    if (argc < 2) usage (argv[0]);
  349. XX
  350. XX    local = False; window_size = 5;
  351. XX    while ((option = getopt (argc, argv, "d:w:")) != EOF)
  352. XX        switch (option) {
  353. XX            case 'd':
  354. XX                local_dict =
  355. XX                    sfalloc ((unsigned) strlen (optarg) + 1);
  356. XX                strcpy (local_dict, optarg);
  357. XX                local = True;
  358. XX                break;
  359. XX            case 'w':
  360. XX                if ((window_size = atoi (optarg)) < 1)
  361. XX                    window_size = 1;
  362. XX                else if (window_size > MAX_WINDOW)
  363. XX                    window_size = MAX_WINDOW;
  364. XX                break;
  365. XX            case '?':
  366. XX            default:
  367. XX                usage (argv[0]);
  368. XX        }
  369. XX
  370. XX    if (argv[optind] == NULL)
  371. XX        usage (argv[0]);
  372. XX
  373. XX    if (!local)
  374. XX        if (getenv ("DICT") != NULL)
  375. XX            local_dict = getenv ("DICT");
  376. XX        else
  377. XX            local_dict = "./spelldict";
  378. XX
  379. XX    switch (check_dict ()) {
  380. XX        case 1:
  381. XX            local = True;
  382. XX            break;
  383. XX        case 0:
  384. XX            local = False;
  385. XX            printf ("\nYour local dictionary %s does not exist.",
  386. XX                local_dict);
  387. XX            printf ("\nI may try to create it later ...");
  388. XX            fflush (stdout);
  389. XX            sleep (2);
  390. XX            break;
  391. XX        case -1:
  392. XX            local = False;
  393. XX            printf ("\nYour local dictionary %s is not readable.",
  394. XX                local_dict);
  395. XX            printf ("\nI may try to write to it later ...");
  396. XX            fflush (stdout);
  397. XX            sleep (2);
  398. XX            break;
  399. XX    }
  400. XX    *place = optind;
  401. XX}
  402. SHAR_EOF
  403. if test 1463 -ne "`wc -c parse.c`"
  404. then
  405. echo shar: error transmitting parse.c '(should have been 1463 characters)'
  406. fi
  407. echo shar: extracting sp.1 '(4358 characters)'
  408. sed 's/^XX//' << \SHAR_EOF > sp.1
  409. XX.\"
  410. XX.\" Copyright (C) 1988 Andrew Large
  411. XX.\"
  412. XX.de Cm
  413. XX\fI\\$1\fP(\fI\\$2\fP)\\$3
  414. XX..
  415. XX.TH SP 1 "Version 4.0"
  416. XX.DA 13 November 1988
  417. XX.SH NAME
  418. XXsp \- check spelling of a document and fix any mistakes
  419. XX.SH SYNOPSIS
  420. XX.B sp
  421. XX[
  422. XX.B \-d
  423. XX.B dictionary
  424. XX]
  425. XX[
  426. XX.B \-w
  427. XX.B window_size
  428. XX]
  429. XX.B file
  430. XX[
  431. XX.B file2
  432. XX.B ...
  433. XX]
  434. XX.SH DESCRIPTION
  435. XX.PP
  436. XX.IR sp
  437. XXcalls
  438. XX.Cm spell 1
  439. XXto check the spelling of your document(s).
  440. XXIt then presents you with a list of the mis-spelled words and allows
  441. XXyou to ignore the word, correct it, or add it to your personal dictionary.
  442. XX.PP
  443. XXYour personal dictionary is searched for words
  444. XX.I after
  445. XXthe system dictionary.  You may specify a personal dictionary in two
  446. XXdifferent ways:
  447. XX.RS
  448. XX.IP 1. 5n
  449. XXOn the command line (with the \-d option).
  450. XX.IP 2. 5n
  451. XXSet the environment variable DICT to the name of your personal dictionary.
  452. XX.RE
  453. XX.PP
  454. XXIf you don't explicitly set your personal dictionary, then the file
  455. XX``spelldict'' in your current directory will be used.
  456. XX.PP
  457. XXOnce the mis-spelled words are identified, you are prompted word by
  458. XXword for an action to take.  Your choices are given in brackets and
  459. XXexplained below.
  460. XX.IP A
  461. XXMark the word for addition to your personal dictionary.
  462. XX.IP C
  463. XXMark the word for correction.  You will be asked for the correct spelling.
  464. XX.IP I
  465. XXIgnore the word in question.  This is the default option and is
  466. XXused when a word is spelled correctly, but you don't want it added
  467. XXto your personal dictionary.
  468. XX.IP L
  469. XXLook up a string in the system dictionary.  This is appropriate for
  470. XXobtaining the proper spelling of the word.  You will be prompted for a string
  471. XXthat
  472. XX.Cm look 1
  473. XXwill use on the system dictionary.
  474. XX.IP W
  475. XXShow where the word occurs in the document.  This shows the line the word
  476. XXoccurred on plus some additional lines to show the context.  The size of
  477. XXthe context window is set to 5 by default (two lines above, two lines below).
  478. XXYou can change the context window size with the \-w option.  The window
  479. XXsize may be set to anything from 1 to 15.
  480. XX.IP ^
  481. XXGo to previous document (given on command line).  If your current document
  482. XXis the first given on the command line, this will re-run
  483. XX.Cm spell 1
  484. XXon your current document.  If you have marked any words for correction or
  485. XXaddition to your personal dictionary, you will be
  486. XXasked whether or not you want to save your changes.
  487. XX.IP #
  488. XXGo to next document (given on command line).  If your current document is
  489. XXthe last given on the command line, this exits the program.  If you
  490. XXhave marked any words for correction or addition to your personal
  491. XXdictionary, you will be asked whether or not you want to save your changes.
  492. XX.IP +
  493. XXGo to next word.  If you haven't taken action with the current word, this
  494. XXoption is equivalent to an ignore (don't correct or add to personal
  495. XXdictionary).  Otherwise, previous actions hold true, i.e. if you correct
  496. XXa word, hit a '-' to go back to it, and hit a '+' to skip forward past it,
  497. XXthe correction would still be the course taken.  However, if you hit an
  498. XX'I' to skip forward past it, no correction would take place.
  499. XX.IP -
  500. XXGo to previous word.  This is the course of action to take if you
  501. XXmess up a correction or change your mind in some way.
  502. XX.IP ?
  503. XXThis will display a short help menu.
  504. XX.IP ^L
  505. XXThis will redraw the screen (as with
  506. XX.Cm vi 1 ).
  507. XX.PP
  508. XXAfter you have processed all the words, you are prompted for an
  509. XXadditional action.  You may go to either the previous or the next document.
  510. XXIn either case, you will be asked whether or not you wish to save your changes.
  511. XXIn this manner, you can make corrections to a file, and then back up to check
  512. XXyour corrections.  Corrections are made to the documents via
  513. XX.Cm ex 1 .
  514. XX.PP
  515. XXThe spell checking is done one file at a time, so if you have the same
  516. XXmis-spelled word in several files, you will have to correct it for each file.
  517. XXHowever, the personal dictionary is updated between the checks on each file,
  518. XXso additions to it will be available when the next file is checked.
  519. XX.SH AUTHOR
  520. XXAndrew Large
  521. XX.SH FILES
  522. XX$DICT, spelldict \- default personal dictionaries
  523. XX.SH BUGS
  524. XX.PP
  525. XX.Cm spell 1
  526. XXand
  527. XX.Cm ex 1
  528. XXhave different ideas of what constitutes a word.  Most notably,
  529. XX.Cm spell 1
  530. XXconsiders ``_'' to be a word separation character.  For those cases,
  531. XXcorrect the word by hand.  Trying to correct it via
  532. XX.B sp
  533. XXwill cause
  534. XX.Cm ex 1
  535. XXto fail, and all your corrections will be lost.
  536. XX.SH "SEE ALSO"
  537. XX.Cm ex 1 ,
  538. XX.Cm grep 1 ,
  539. XX.Cm look 1 ,
  540. XXand
  541. XX.Cm spell 1 .
  542. SHAR_EOF
  543. if test 4358 -ne "`wc -c sp.1`"
  544. then
  545. echo shar: error transmitting sp.1 '(should have been 4358 characters)'
  546. fi
  547. echo shar: extracting sp.c '(1416 characters)'
  548. sed 's/^XX//' << \SHAR_EOF > sp.c
  549. XX# include    "sp.h"
  550. XX
  551. XX/*
  552. XX** sp main program
  553. XX** Uses spell(1) to check the spelling of a document.
  554. XX** The user is prompted with each of the mis-spelled words and
  555. XX** can ignore them, add them to a personal dictionary, correct
  556. XX** them, look up words in the dictionary, or find out where in
  557. XX** the file the word is found.  Corrections are made to the
  558. XX** document via ex(1).
  559. XX**
  560. XX** Author: Andrew Large
  561. XX**    December 1986    (First Edition)
  562. XX**    October 1988    (Current Version)
  563. XX*/
  564. XX
  565. XXmain (argc, argv)
  566. XXint    argc;
  567. XXchar    *argv[];
  568. XX{
  569. XX    extern    int    exit_val;
  570. XX    extern    char    *spell_doc;
  571. XX    int    spell_val, start_pos;
  572. XX    register int    pos;
  573. XX
  574. XX    /*
  575. XX    ** Parse input arguments and initialize
  576. XX    ** curses and signals
  577. XX    */
  578. XX    parse (argc, argv, &start_pos);
  579. XX    init ();
  580. XX
  581. XX    /*
  582. XX    ** Main loop.  Keep going until user leaves the last document.
  583. XX    */
  584. XX    pos = start_pos;
  585. XX    while (pos < argc) {
  586. XX        reset_data ();        /* Clean lists and reset globals */
  587. XX        spell_doc = argv[pos];
  588. XX
  589. XX        if ( (spell_val = spell ()) >= 0 ) {
  590. XX            switch (user_input ()) {
  591. XX                case -1:    /* previous doc, save */
  592. XX                    rest_ignore ();
  593. XX                    save (spell_val);
  594. XX                case -2:    /* previous doc, no save */
  595. XX                    if (pos > start_pos) --pos;
  596. XX                    break;
  597. XX                case 0:        /* normal exit with save */
  598. XX                case 1:        /* early exit with save */
  599. XX                    rest_ignore ();
  600. XX                    save (spell_val);
  601. XX                case 2:        /* early exit, no save */
  602. XX                default:
  603. XX                    ++pos;
  604. XX                    break;
  605. XX            }
  606. XX        }
  607. XX        else {
  608. XX            ++pos;
  609. XX            exit_val = Error;
  610. XX        }
  611. XX    }
  612. XX    leave ();
  613. XX}
  614. SHAR_EOF
  615. if test 1416 -ne "`wc -c sp.c`"
  616. then
  617. echo shar: error transmitting sp.c '(should have been 1416 characters)'
  618. fi
  619. echo shar: extracting spell.c '(2033 characters)'
  620. sed 's/^XX//' << \SHAR_EOF > spell.c
  621. XX# include    "sp.h"
  622. XX
  623. XX/*
  624. XX** spell
  625. XX** Run spell(1) on the file and check personal dictionary also.
  626. XX** Establishes the original list of mis-spelled words
  627. XX*/
  628. XXspell () {
  629. XX    extern    char    *bad_words[], *spell_doc, *local_dict;
  630. XX    extern    int    num_bad;
  631. XX    extern    boolean    local;
  632. XX    FILE    *popen (), *spell_out;
  633. XX    char    command[256];
  634. XX    int    ypos, xpos, ret_val;
  635. XX    register int    i;
  636. XX
  637. XX    clear (); fname ();
  638. XX
  639. XX    if (access (spell_doc, 0) != 0) {    /* Check for existence */
  640. XX        sprintf (command, "Cannot access file %s!", spell_doc);
  641. XX        message (True, command);
  642. XX        return (-1);
  643. XX    }
  644. XX
  645. XX    ret_val = 0;
  646. XX    if (access (spell_doc, 6) != 0) {        /* Read and write */
  647. XX        if (access (spell_doc, 4) != 0) {    /* Read */
  648. XX            sprintf (command, "You are unable to read %s!",
  649. XX                spell_doc);
  650. XX            message (True, command);
  651. XX            return (-1);
  652. XX        }
  653. XX        message (True, "You are unable to write to this file!");
  654. XX        mvaddstr (5,22, "I will check spelling, but you will");
  655. XX        mvaddstr (6,22, "not be able to save any corrections.");
  656. XX        ret_val = 1;
  657. XX        move (0,0); refresh (); sleep (3); fname ();
  658. XX    }
  659. XX
  660. XX    mvaddstr (3,0, "Checking spelling ..."); refresh ();
  661. XX
  662. XX    /*
  663. XX    ** Get the list of mis-spelled words
  664. XX    */
  665. XX    if (local)
  666. XX        sprintf (command, "%s %s | %s -v -f %s", SPELL, spell_doc,
  667. XX            FGREP, local_dict);
  668. XX    else
  669. XX        sprintf (command, "%s %s", SPELL, spell_doc);
  670. XX
  671. XX    spell_out = popen (command, "r");
  672. XX
  673. XX    for (i = 0; i < MAX_WORDS; i++) {
  674. XX        bad_words[i] = sfalloc ((unsigned) MAX_WORD_LEN);
  675. XX        if (fgets (bad_words[i], MAX_WORD_LEN, spell_out) == NULL)
  676. XX            break;
  677. XX        else
  678. XX            bad_words[i][strlen (bad_words[i]) - 1] = '\0';
  679. XX    }
  680. XX    fflush (spell_out); pclose (spell_out);
  681. XX
  682. XX    if ((num_bad = i) >= MAX_WORDS) {
  683. XX        getyx (stdscr, ypos, xpos);
  684. XX        sprintf (command, "You have more than %d mis-spelled words.",
  685. XX            MAX_WORDS);
  686. XX        mvaddstr (5, 10, command);
  687. XX        strcpy (command, "Run this again after corrections are made.");
  688. XX        mvaddstr (6, 10, command);
  689. XX        move (ypos, xpos); refresh (); sleep (2);
  690. XX    }
  691. XX
  692. XX    addstr (" done"); refresh ();
  693. XX
  694. XX    if (num_bad <= 0) {
  695. XX        mvaddstr (5,0, "No spelling errors.");
  696. XX        move (0,0); refresh (); sleep (1);
  697. XX    }
  698. XX    return (ret_val);
  699. XX}
  700. SHAR_EOF
  701. if test 2033 -ne "`wc -c spell.c`"
  702. then
  703. echo shar: error transmitting spell.c '(should have been 2033 characters)'
  704. fi
  705. echo shar: extracting user_input.c '(2012 characters)'
  706. sed 's/^XX//' << \SHAR_EOF > user_input.c
  707. XX# include    "sp.h"
  708. XX
  709. XX/*
  710. XX** user_input -- user interface for correcting mis-spelled words
  711. XX*/
  712. XXuser_input () {
  713. XX    extern    char    *bad_words[], *good_words[];
  714. XX    extern    int    num_bad;
  715. XX    char    string[MAX_WORD_LEN + 64];
  716. XX    boolean    done;
  717. XX    register int    loop;
  718. XX
  719. XX    for (loop = 0; loop < num_bad; loop++) {
  720. XX        page_clear (loop + 1, False);
  721. XX        sprintf (string, "Word ``%s'' is not in the dictionary",
  722. XX            bad_words[loop]);
  723. XX        mvaddstr (3, 0, string); refresh ();
  724. XX
  725. XX        done = False;
  726. XX        do {
  727. XX            sprintf (string, "(%s) [ilwac^#+-?] ", bad_words[loop]);
  728. XX            mvaddstr (5, 0, string); refresh ();
  729. XX
  730. XX            switch (getch ()) {
  731. XX                case 'I':
  732. XX                case 'i':
  733. XX                case ' ':
  734. XX                case '\n':
  735. XX                case '\r':
  736. XX                    addstr ("Ignore"); refresh ();
  737. XX                    done = True; ignore (loop);
  738. XX                    break;
  739. XX                case 'L':
  740. XX                case 'l':
  741. XX                    addstr ("Lookup"); refresh ();
  742. XX                    lookup (loop);
  743. XX                    break;
  744. XX                case 'W':
  745. XX                case 'w':
  746. XX                    addstr ("Where"); refresh ();
  747. XX                    where (loop);
  748. XX                    break;
  749. XX                case 'A':
  750. XX                case 'a':
  751. XX                    addstr ("Add"); refresh ();
  752. XX                    done = True; add (loop);
  753. XX                    break;
  754. XX                case 'C':
  755. XX                case 'c':
  756. XX                    addstr ("Correct"); refresh ();
  757. XX                    done = True; word_correct (loop);
  758. XX                    break;
  759. XX                case '^':
  760. XX                    addstr ("Previous Document");
  761. XX                    refresh ();
  762. XX                    if (ask_save (loop) == 1)
  763. XX                        return (-1);
  764. XX                    else
  765. XX                        return (-2);
  766. XX                case '#':
  767. XX                    addstr ("Next Document");
  768. XX                    refresh ();
  769. XX                    if (ask_save (loop) == 1)
  770. XX                        return (1);
  771. XX                    else
  772. XX                        return (2);
  773. XX                case '+':
  774. XX                    addstr ("Next Word");
  775. XX                    refresh ();
  776. XX                    done = True;
  777. XX                    if (good_words[loop] == NULL)
  778. XX                        ignore (loop);
  779. XX                    break;
  780. XX                case '-':
  781. XX                    addstr ("Previous Word");
  782. XX                    refresh ();
  783. XX                    done = True;
  784. XX                    if (loop > 0) loop -=2;
  785. XX                    else --loop;
  786. XX                    break;
  787. XX                case 'H':
  788. XX                case 'h':
  789. XX                case '?':
  790. XX                    addstr ("Help!"); refresh ();
  791. XX                    help (loop);
  792. XX                    break;
  793. XX                case CTRL_L:
  794. XX                case CTRL_R:
  795. XX                    page_clear (loop + 1, True);
  796. XX                    break;
  797. XX                default:
  798. XX                    page_clear (loop + 1, False);
  799. XX                    break;
  800. XX            }
  801. XX        } while (!done);
  802. XX    }
  803. XX    return (ask_action ());
  804. XX}
  805. SHAR_EOF
  806. if test 2012 -ne "`wc -c user_input.c`"
  807. then
  808. echo shar: error transmitting user_input.c '(should have been 2012 characters)'
  809. fi
  810. echo shar: extracting MANIFEST '(785 characters)'
  811. sed 's/^XX//' << \SHAR_EOF > MANIFEST
  812. XXFile        Explanation
  813. XX------------------------------------------------------------------------------
  814. XXMANIFEST    This file -- list of files in package
  815. XXMakefile    For compiling ``sp''.
  816. XXREADME        Read this first for installation and copyright information
  817. XXadd_local.c    Routine for adding words to personal dictionary
  818. XXdoc_correct.c    Routine for correcting the document
  819. XXexterns.c    Declarations of global data structures
  820. XXparse.c        Command line parser (uses getopt)
  821. XXsp.1        Manual page
  822. XXsp.c        Main program
  823. XXsp.h        Include file (may need editing)
  824. XXspell.c        Runs spell(1) and fgrep(1) to get initial mis-spelling list
  825. XXtools.c        General tools used througout program
  826. XXuser_input.c    Get user input for corrections
  827. XXuser_tools.c    Process option selected in user_input
  828. XXwhere.c        For showing context-surrounded word occurences
  829. SHAR_EOF
  830. if test 785 -ne "`wc -c MANIFEST`"
  831. then
  832. echo shar: error transmitting MANIFEST '(should have been 785 characters)'
  833. fi
  834. echo shar: extracting tools.c '(4427 characters)'
  835. sed 's/^XX//' << \SHAR_EOF > tools.c
  836. XX# include    "sp.h"
  837. XX# include    <signal.h>
  838. XX
  839. XX
  840. XX/*
  841. XX** ask_more
  842. XX** Prompt the user to continue.
  843. XX*/
  844. XXask_more () {
  845. XX    move (23,0); clrtoeol ();
  846. XX    standout ();
  847. XX    mvaddstr (23, 29, "Hit any key to continue");
  848. XX    standend ();
  849. XX    refresh (); getch ();
  850. XX}
  851. XX
  852. XX
  853. XX/*
  854. XX** check_dict
  855. XX** Check for existence/read permission on dictionary.
  856. XX*/
  857. XXcheck_dict () {
  858. XX    extern    char    *local_dict;
  859. XX
  860. XX    if ( access (local_dict, 4) == 0 )        /* Read permission */
  861. XX        return (1);
  862. XX    else
  863. XX        if ( access (local_dict, 0) != 0 )    /* Existence check */
  864. XX            return (0);
  865. XX        else
  866. XX            return (-1);
  867. XX}
  868. XX
  869. XX
  870. XX/*
  871. XX** curse_die
  872. XX** Die with an explanation when inside of curses
  873. XX*/
  874. XXcurse_die (string)
  875. XXchar    *string;
  876. XX{
  877. XX    extern    int    errno, exit_val;
  878. XX    extern    char    *sys_errlist[];
  879. XX    char    line[256];
  880. XX
  881. XX    sprintf (line, "Fatal Error, %s:%s", string, sys_errlist[errno]);
  882. XX    message (True, line);
  883. XX    exit_val = Error; leave ();
  884. XX}
  885. XX
  886. XX
  887. XX/*
  888. XX** fname
  889. XX** Print out the page header (file name, etc.)
  890. XX*/
  891. XXfname () {
  892. XX    extern    char    *spell_doc;
  893. XX    erase ();
  894. XX    mvaddstr (0, (65 - strlen (spell_doc)) / 2, /* (80-overhead-len) / 2 */
  895. XX        "[ --- ");
  896. XX    standout ();
  897. XX    addch (' '); addstr (spell_doc); addch (' ');
  898. XX    standend ();
  899. XX    addstr (" --- ]");
  900. XX}
  901. XX
  902. XX
  903. XX/*
  904. XX** free2
  905. XX** Free a list of strings
  906. XX*/
  907. XXfree2 (args, max)
  908. XXregister char    **args;
  909. XXregister int    max;
  910. XX{
  911. XX    while (*args && max-- > 0) free (*args++);
  912. XX}
  913. XX
  914. XX
  915. XX/*
  916. XX** init
  917. XX** Initialize the screen and take care of nasty signals
  918. XX*/
  919. XXinit () {
  920. XX    extern    char    *bad_words[], *good_words[], *add_words[];
  921. XX    register int    i;
  922. XX
  923. XX    for (i=0; i < MAX_WORDS; i++) {
  924. XX        bad_words[i] = good_words[i] = add_words[i] = NULL;
  925. XX    }
  926. XX
  927. XX    signal (SIGINT, leave); signal (SIGQUIT, leave);
  928. XX
  929. XX    initscr (); crmode (); noecho ();
  930. XX
  931. XX    mvaddstr ( 9,30, VERSION1);
  932. XX    mvaddstr (10,28, VERSION2);
  933. XX    mvaddstr (11,31, VERSION3);
  934. XX
  935. XX    move (0,0); refresh (); sleep (1);
  936. XX}
  937. XX
  938. XX
  939. XX/*
  940. XX** leave
  941. XX** Clean up curses and exit.
  942. XX*/
  943. XXvoid    leave () {
  944. XX    extern    char    tmp_file[];
  945. XX    extern    int    exit_val;
  946. XX
  947. XX    unlink (tmp_file);
  948. XX    clear (); move (23,0); refresh (); endwin ();
  949. XX    exit (exit_val);
  950. XX}
  951. XX
  952. XX
  953. XX/*
  954. XX** message
  955. XX** Write message on the screen
  956. XX*/
  957. XXmessage (error, line)
  958. XXboolean    error;
  959. XXchar    *line;
  960. XX{
  961. XX    page_clear (0, False);
  962. XX
  963. XX    if (error) {
  964. XX        addch ('\07');
  965. XX        mvaddstr (3, (78 - strlen (line)) / 2, line);
  966. XX        move (0,0);
  967. XX        refresh (); sleep (3);
  968. XX    }
  969. XX    else {
  970. XX        mvaddstr (3, (78 - strlen (line)) / 2, line);
  971. XX        refresh (); sleep (2);
  972. XX    }
  973. XX}
  974. XX
  975. XX
  976. XX/*
  977. XX** page_clear
  978. XX** Clear part of the screen and display the number
  979. XX** of the current word
  980. XX*/
  981. XXpage_clear (word_num, cls)
  982. XXint    word_num;
  983. XXboolean    cls;
  984. XX{
  985. XX    extern    int    num_bad;
  986. XX    char    str[20];
  987. XX
  988. XX    if (cls)
  989. XX        clear ();
  990. XX    fname ();
  991. XX    if (word_num) {
  992. XX        sprintf (str, "Word #%d of %d", word_num, num_bad);
  993. XX        mvaddstr (23, 79 - strlen (str), str);
  994. XX        mvaddstr (23, 0, VERSION1);
  995. XX    }
  996. XX    move (3, 0);
  997. XX    refresh ();
  998. XX}
  999. XX
  1000. XX
  1001. XX/*
  1002. XX** reset_data
  1003. XX** Reset all global data
  1004. XX*/
  1005. XXreset_data () {
  1006. XX    extern    char    *bad_words[], *good_words[], *add_words[];
  1007. XX    extern    int    num_bad, num_added, num_ignored;
  1008. XX    register int    i;
  1009. XX
  1010. XX    for (i = 0; i < MAX_WORDS; i++) {
  1011. XX        if (bad_words[i] != NULL) {
  1012. XX            free (bad_words[i]); bad_words[i] = NULL;
  1013. XX        }
  1014. XX        if (good_words[i] != NULL) {
  1015. XX            free (good_words[i]); good_words[i] = NULL;
  1016. XX        }
  1017. XX        if (add_words[i] != NULL) {
  1018. XX            free (add_words[i]); add_words[i] = NULL;
  1019. XX        }
  1020. XX    }
  1021. XX
  1022. XX    num_bad = num_added = num_ignored = 0;
  1023. XX}
  1024. XX
  1025. XX
  1026. XX/*
  1027. XX** safe_copy
  1028. XX** A pre-malloc'd copy from one string to another
  1029. XX*/
  1030. XXsafe_copy (string1, string2)
  1031. XXchar    **string1,
  1032. XX    *string2;
  1033. XX{
  1034. XX    if (*string1 == NULL)
  1035. XX        *string1 = sfalloc ((unsigned) strlen (string2) + 1);
  1036. XX    strcpy (*string1, string2);
  1037. XX}
  1038. XX
  1039. XX
  1040. XX/*
  1041. XX** save
  1042. XX** Save changes made to document
  1043. XX*/
  1044. XXsave (spell_val)
  1045. XXint    spell_val;
  1046. XX{
  1047. XX    extern    int    num_bad, num_added, num_ignored;
  1048. XX
  1049. XX    if (num_added)
  1050. XX        add_local ();
  1051. XX    if (num_bad == (num_added + num_ignored))
  1052. XX        message (False, "No corrections made");
  1053. XX    else
  1054. XX        if (spell_val == 0) doc_correct ();
  1055. XX}
  1056. XX
  1057. XX
  1058. XX/*
  1059. XX** rest_ignore
  1060. XX** When user exits before viewing all the words, set the rest
  1061. XX** of the words to ignore.
  1062. XX*/
  1063. XXrest_ignore () {
  1064. XX    extern    char    *bad_words[], *good_words[];
  1065. XX    extern    int    num_bad;
  1066. XX    register int    i;
  1067. XX
  1068. XX    for (i = num_bad - 1; !good_words[i]; ignore (i--));
  1069. XX}
  1070. XX
  1071. XX
  1072. XX/*
  1073. XX** sfalloc
  1074. XX** A safe malloc ()
  1075. XX*/
  1076. XXchar    *sfalloc (num_bytes)
  1077. XXunsigned    num_bytes;
  1078. XX{
  1079. XX    char    *calloc (), *hold;
  1080. XX
  1081. XX    if (num_bytes == 0) return ((char *) NULL);
  1082. XX
  1083. XX    if ( (hold = calloc (1, num_bytes)) == NULL)
  1084. XX        curse_die ("calloc");
  1085. XX
  1086. XX    return (hold);
  1087. XX}
  1088. XX
  1089. XX
  1090. XX/*
  1091. XX** usage
  1092. XX** Print out program usage statement and exit.
  1093. XX*/
  1094. XXusage (name)
  1095. XXchar    *name;
  1096. XX{
  1097. XX    fprintf (stderr,
  1098. XX    "Usage: %s [ -d dictionary ] [ -w window_size ] file [ file2 ... ]\n",
  1099. XX        name);
  1100. XX    exit (1);
  1101. XX}
  1102. SHAR_EOF
  1103. if test 4427 -ne "`wc -c tools.c`"
  1104. then
  1105. echo shar: error transmitting tools.c '(should have been 4427 characters)'
  1106. fi
  1107. echo shar: extracting sp.h '(992 characters)'
  1108. sed 's/^XX//' << \SHAR_EOF > sp.h
  1109. XX/*
  1110. XX** Configuration information for sp
  1111. XX*/
  1112. XX
  1113. XX# include    <curses.h>
  1114. XX
  1115. XX# define    True    1
  1116. XX# define    False    0
  1117. XX
  1118. XX# define    Error    1
  1119. XX# define    Okay    0
  1120. XX
  1121. XX# define    VERSION1    "Sp Version 4.0"
  1122. XX# define    VERSION2    "Copyright (C) 1988"
  1123. XX# define    VERSION3    "Andrew Large"
  1124. XX
  1125. XX/*
  1126. XX** Lookup dictionary -- use /usr/dict/web2 if you have it
  1127. XX*/
  1128. XX# define    LOOK_DICT    "/usr/dict/words"
  1129. XX
  1130. XX/*
  1131. XX** Location of common programs
  1132. XX*/
  1133. XX# define    EX    "/usr/ucb/ex"
  1134. XX# define    FGREP    "/usr/bin/fgrep"
  1135. XX# define    LOOK    "/usr/bin/look"
  1136. XX# define    MORE    "/usr/ucb/more"
  1137. XX# define    SORT    "/usr/bin/sort"
  1138. XX# define    SPELL    "/usr/bin/spell"
  1139. XX
  1140. XX/*
  1141. XX** Constant sizes
  1142. XX*/
  1143. XX# define    MAX_WORDS    512    /* Max words corrected on one pass */
  1144. XX# define    MAX_WORD_LEN    256    /* Max length of a word */
  1145. XX# define    MAX_WINDOW    15    /* Maximum window size (for where) */
  1146. XX
  1147. XX# define    CTRL_R        022    /* Ascii value of ^R -- for redraw */
  1148. XX# define    CTRL_L        014    /* Ascii value of ^L -- for redraw */
  1149. XX# define    ESC        033    /* Ascii value of Escape */
  1150. XX
  1151. XX
  1152. XXtypedef    unsigned char    boolean;
  1153. XX
  1154. XXvoid    leave ();
  1155. XXchar    *sfalloc ();
  1156. SHAR_EOF
  1157. if test 992 -ne "`wc -c sp.h`"
  1158. then
  1159. echo shar: error transmitting sp.h '(should have been 992 characters)'
  1160. fi
  1161. echo shar: extracting user_tools.c '(3592 characters)'
  1162. sed 's/^XX//' << \SHAR_EOF > user_tools.c
  1163. XX# include    "sp.h"
  1164. XX
  1165. XX
  1166. XX/*
  1167. XX** add
  1168. XX** Add an entry into list of words to be added to personal dict
  1169. XX*/
  1170. XXadd (word_num)
  1171. XXint    word_num;
  1172. XX{
  1173. XX    extern    char    *add_words[], *bad_words[], *good_words[];
  1174. XX    extern    int    num_added;
  1175. XX
  1176. XX    safe_copy (& (add_words[num_added++]), bad_words[word_num]);
  1177. XX    safe_copy (& (good_words[word_num]), bad_words[word_num]);
  1178. XX}
  1179. XX
  1180. XX
  1181. XX/*
  1182. XX** ask_action
  1183. XX** Ask the user what to do after processing words
  1184. XX*/
  1185. XXask_action () {
  1186. XX    extern    int    num_bad;
  1187. XX    boolean    done;
  1188. XX
  1189. XX    done = False;
  1190. XX    while (!done) {
  1191. XX        page_clear (0, False);
  1192. XX        mvaddstr (3, 0, "Action? [#^?] ");
  1193. XX        refresh ();
  1194. XX
  1195. XX        switch (getch ()) {
  1196. XX            case ' ': case '\n': case '\r':
  1197. XX            case '#':
  1198. XX                done = True;
  1199. XX                addstr ("Next Document"); refresh ();
  1200. XX                if (ask_save (num_bad) == 1) return (0);
  1201. XX                else return (2);
  1202. XX            case '^':
  1203. XX                done = True;
  1204. XX                addstr ("Previous Document"); refresh ();
  1205. XX                if (ask_save (num_bad) == 1) return (-1);
  1206. XX                else return (-2);
  1207. XX            case '?':
  1208. XX                addstr ("Help!"); refresh ();
  1209. XX                mvaddstr (5, 10, "# --- Go to next document (or exit)");
  1210. XX                mvaddstr (6, 10, "^ --- Go to previous document (or re-spell this one)");
  1211. XX                mvaddstr (7, 10, "? --- This help message");
  1212. XX                ask_more ();
  1213. XX            default:
  1214. XX                break;
  1215. XX        }
  1216. XX    }
  1217. XX    return (0);
  1218. XX}
  1219. XX
  1220. XX
  1221. XX/*
  1222. XX** ask_save
  1223. XX** Ask user if he/she wants to save these changes
  1224. XX*/
  1225. XXask_save (word_num)
  1226. XXint    word_num;
  1227. XX{
  1228. XX    extern    int    num_ignored;
  1229. XX    char    ch;
  1230. XX
  1231. XX    if (word_num == num_ignored) return (0);
  1232. XX    mvaddstr (7, 0, "Do you wish to save your changes? [y] ");
  1233. XX    refresh ();
  1234. XX    if ( (ch = getch ()) == 'n' || ch == 'N' ) return (0);
  1235. XX    return (1);
  1236. XX}
  1237. XX
  1238. XX
  1239. XX/*
  1240. XX** correct
  1241. XX** Get correct spelling for a word
  1242. XX*/
  1243. XXword_correct (word_num)
  1244. XXint    word_num;
  1245. XX{
  1246. XX    extern    char    *good_words[];
  1247. XX
  1248. XX    mvaddstr (7, 0, "****** Proper spelling: "); refresh();
  1249. XX    echo(); nocrmode(); refresh ();
  1250. XX
  1251. XX    if (good_words[word_num] == NULL)
  1252. XX        good_words[word_num] = sfalloc ((unsigned) MAX_WORD_LEN + 1);
  1253. XX    fgets (good_words[word_num], MAX_WORD_LEN + 1, stdin);
  1254. XX    good_words[word_num][strlen (good_words[word_num]) - 1] = '\0';
  1255. XX
  1256. XX    crmode (); noecho ();
  1257. XX    ask_more (); page_clear (word_num + 1, True);
  1258. XX}
  1259. XX
  1260. XX
  1261. XX/*
  1262. XX** help
  1263. XX** Give user some help with commands
  1264. XX*/
  1265. XXhelp (word_num)
  1266. XXint    word_num;
  1267. XX{
  1268. XX    mvaddstr ( 7, 10, "     I --- Ignore all occurrences of word");
  1269. XX    mvaddstr ( 8, 10, "     L --- Lookup a sub-string in the dictionary");
  1270. XX    mvaddstr ( 9, 10, "     W --- show Where word occurs in the document");
  1271. XX    mvaddstr (10, 10, "     A --- Add word to your personal dictionary");
  1272. XX    mvaddstr (11, 10, "     C --- Correct all occurrences of the word");
  1273. XX    mvaddstr (12, 10, "     ^ --- go to previous document (or re-spell this one)");
  1274. XX    mvaddstr (13, 10, "     # --- go to next document (or exit)");
  1275. XX    mvaddstr (14, 10, "     + --- go to next word");
  1276. XX    mvaddstr (15, 10, "     - --- go to previous word");
  1277. XX    mvaddstr (16, 10, " ?,  H --- this help message");
  1278. XX    mvaddstr (17, 10, "^R, ^L --- redraw the screen");
  1279. XX    ask_more ();
  1280. XX    page_clear (word_num + 1, False);
  1281. XX}
  1282. XX
  1283. XX
  1284. XX/*
  1285. XX** ignore
  1286. XX** Ignore the word (i.e. don't substitute for it)
  1287. XX*/
  1288. XXignore (word_num)
  1289. XXint    word_num;
  1290. XX{
  1291. XX    extern    char    *good_words[], *bad_words[];
  1292. XX    extern    int    num_ignored;
  1293. XX
  1294. XX    safe_copy (& (good_words[word_num]), bad_words[word_num]);
  1295. XX    num_ignored++;
  1296. XX}
  1297. XX
  1298. XX
  1299. XX/*
  1300. XX** lookup
  1301. XX** Look up string in the dictionary
  1302. XX*/
  1303. XXlookup (word_num)
  1304. XXint    word_num;
  1305. XX{
  1306. XX    char    hold_str[MAX_WORD_LEN + 1],
  1307. XX        command[BUFSIZ];
  1308. XX
  1309. XX    mvaddstr (7, 0, "****** Lookup string: ");
  1310. XX    refresh ();
  1311. XX
  1312. XX    echo (); nocrmode (); gets (hold_str);
  1313. XX    move (8, 0); clrtobot (); move (8, 0); refresh ();
  1314. XX
  1315. XX    sprintf (command, "%s -df %s %s | %s", LOOK, hold_str, LOOK_DICT,
  1316. XX        MORE);
  1317. XX    system (command);
  1318. XX
  1319. XX    crmode (); noecho (); ask_more ();
  1320. XX    page_clear (word_num + 1, True);
  1321. XX}
  1322. SHAR_EOF
  1323. if test 3592 -ne "`wc -c user_tools.c`"
  1324. then
  1325. echo shar: error transmitting user_tools.c '(should have been 3592 characters)'
  1326. fi
  1327. echo shar: extracting doc_correct.c '(846 characters)'
  1328. sed 's/^XX//' << \SHAR_EOF > doc_correct.c
  1329. XX# include    "sp.h"
  1330. XX
  1331. XX/*
  1332. XX** doc_correct
  1333. XX** Correct the document, based upon the difference between the
  1334. XX** original and new lists of words.  Uses EX to make the corrections.
  1335. XX*/
  1336. XXdoc_correct () {
  1337. XX    extern    char    *bad_words[], *good_words[], *spell_doc;
  1338. XX    extern    int    num_bad;
  1339. XX    FILE    *popen (), *ex_ptr;
  1340. XX    char    command[256];
  1341. XX    register int    loop;
  1342. XX
  1343. XX    page_clear (0, False);
  1344. XX    mvaddstr (3,0, "Making changes ..."); refresh ();
  1345. XX
  1346. XX    sprintf (command, "%s - %s", EX, spell_doc);
  1347. XX    ex_ptr = popen (command, "w");
  1348. XX
  1349. XX    fprintf (ex_ptr, "set nomagic\n");    /* Don't match '.' */
  1350. XX    for (loop = 0; loop < num_bad; loop++)
  1351. XX        if (strcmp (bad_words[loop], good_words[loop]) != 0) {
  1352. XX            fprintf (ex_ptr, "%%s/\\<%s\\>/%s/g\n", bad_words[loop],
  1353. XX                good_words[loop]);
  1354. XX            fflush (ex_ptr);
  1355. XX        }
  1356. XX    fprintf (ex_ptr, "w\nq\n");
  1357. XX    fflush (ex_ptr); pclose (ex_ptr);
  1358. XX
  1359. XX    addstr (" done"); refresh ();
  1360. XX}
  1361. SHAR_EOF
  1362. if test 846 -ne "`wc -c doc_correct.c`"
  1363. then
  1364. echo shar: error transmitting doc_correct.c '(should have been 846 characters)'
  1365. fi
  1366. echo shar: extracting externs.c '(774 characters)'
  1367. sed 's/^XX//' << \SHAR_EOF > externs.c
  1368. XX# include    "sp.h"
  1369. XX
  1370. XX/*
  1371. XX** Global data use throughout the program
  1372. XX*/
  1373. XXchar    *id = "@(#)SP\t4.0\t88/11/13";    /* Identification string for what(1) */
  1374. XX
  1375. XXchar    *bad_words[MAX_WORDS],        /* Words obtained from spell(1) */
  1376. XX    *good_words[MAX_WORDS],        /* Words to correct in document */
  1377. XX    *add_words[MAX_WORDS],        /* Words to add to local dictionary */
  1378. XX    *local_dict,            /* Local dictionary */
  1379. XX    *spell_doc,            /* Document we are currently spelling */
  1380. XX    tmp_file[16];            /* Temporary file used for */
  1381. XX
  1382. XXint    num_bad,            /* Number of bad words */
  1383. XX    num_added,            /* Number added to local dict */
  1384. XX    num_ignored,            /* Number bad words ignored */
  1385. XX    exit_val,            /* Program exit value (for leave ()) */
  1386. XX    window_size;            /* Context window size (for where ()) */
  1387. XX
  1388. XXboolean    local;                /* Is the local dict available? */
  1389. SHAR_EOF
  1390. if test 774 -ne "`wc -c externs.c`"
  1391. then
  1392. echo shar: error transmitting externs.c '(should have been 774 characters)'
  1393. fi
  1394. echo shar: extracting add_local.c '(1293 characters)'
  1395. sed 's/^XX//' << \SHAR_EOF > add_local.c
  1396. XX# include    "sp.h"
  1397. XX
  1398. XX/*
  1399. XX** add_local
  1400. XX** Add all words in correct list to personal dictionary
  1401. XX** and sort the dictionary.
  1402. XX*/
  1403. XXadd_local () {
  1404. XX    extern    char    *add_words[], *local_dict, tmp_file[];
  1405. XX    extern    int    num_added;
  1406. XX    extern    boolean    local;
  1407. XX    char    *mktemp (), string[256];
  1408. XX    FILE    *fopen (), *tmp_ptr;
  1409. XX    register int    loop;
  1410. XX
  1411. XX    if ( access (local_dict, 0) == 0 && access (local_dict, 2) != 0 ) {
  1412. XX        sprintf (string,
  1413. XX            "Your local dictionary \"%s\" is not writable!",
  1414. XX            local_dict);
  1415. XX        message (True, string);
  1416. XX        return;
  1417. XX    }
  1418. XX
  1419. XX    strcpy (tmp_file, "/tmp/spXXXXXX");
  1420. XX    if ((tmp_ptr = fopen (mktemp (tmp_file), "w")) == NULL) {
  1421. XX        sprintf (string, "Can't open tmp file \"%s\" for writing!",
  1422. XX            tmp_file);
  1423. XX        message (True, string);
  1424. XX        return;
  1425. XX    }
  1426. XX
  1427. XX    for (loop = 0; loop < num_added; loop++)
  1428. XX        fprintf (tmp_ptr, "%s\n", add_words[loop]);
  1429. XX    fflush (tmp_ptr); fclose (tmp_ptr);
  1430. XX
  1431. XX# ifdef BSD
  1432. XX    if (vfork () == 0) {
  1433. XX# else
  1434. XX    if (fork () == 0) {
  1435. XX# endif
  1436. XX        if (local)
  1437. XX            execl (SORT, "sort", "-f", "-m", "-o", local_dict,
  1438. XX                local_dict, tmp_file, (char *) NULL);
  1439. XX        else
  1440. XX            execl (SORT, "sort", "-f", "-m", "-o", local_dict,
  1441. XX                tmp_file, (char *) NULL);
  1442. XX        perror (SORT);
  1443. XX        _exit (-1);
  1444. XX    }
  1445. XX
  1446. XX    wait (0);
  1447. XX    sprintf (string, "%d %s added to %s", num_added,
  1448. XX        (num_added == 1 ? "word" : "words"), local_dict);
  1449. XX    message (False, string);
  1450. XX}
  1451. SHAR_EOF
  1452. if test 1293 -ne "`wc -c add_local.c`"
  1453. then
  1454. echo shar: error transmitting add_local.c '(should have been 1293 characters)'
  1455. fi
  1456. echo shar: done with directory sp
  1457. cd ..
  1458. #    End of shell archive
  1459. exit 0
  1460.