(defun
    (get-word			; three or more letters
	(re-search-forward "[A-Za-z'][A-Za-z'][A-Za-z'][A-Za-z']*")
	(region-around-match 0)
	(region-to-string)
    )
    (delete-duplicates candidate
	(beginning-of-file)
	(while (! (eobp))
	    (set-mark)
	    (next-line)
	    (setq candidate (region-to-string))
	    (save-excursion
		(error-occured (replace-string candidate "")))
	)
    )
    (do-alternatives badword buffer result
	(setq badword (arg 1))
	(setq buffer (current-buffer-name))
	(pop-to-buffer "Spellings")
	(setq needs-checkpointing 0)
	(if (suggest-spellings badword "Spellings")
	    (progn continue action
		(delete-duplicates)
		(beginning-of-file)
		(insert-string
		    (concat "	Suggested spellings for \"" badword "\""))
		(newline)
		(insert-string "' ', 'n': next line; 'p': previous line; ")
		(insert-string "'a': accept; '^G', 'e': exit") (newline)
		(insert-string "-----------------------------------------")
		(insert-string "----------------------------")
		(newline)
		(setq continue 1)
		(message "")
		(while continue
		    (setq action (get-tty-character))
		    (if
			(| (= action ' ') (= action 'n'))
			(progn
			    (next-line)
			    (if (eobp) (previous-line)))
			(= action 'p')
			(progn
			    (previous-line)
			    (if (looking-at "---------") (next-line)))
			(= action 'a')
			(progn
			    (beginning-of-line)
			    (set-mark)
			    (end-of-line)
			    (setq result (region-to-string))
			    (setq continue 0))
			(| (= action '^G') (= action 'e')) (setq continue 0))
		)
		(pop-to-buffer buffer))
	    (progn
		(delete-window)
		(pop-to-buffer buffer)
		(message "No suggestions found!")
		(sit-for 10)
		(setq result "")))
	result
    )
    (#typo-help
	(save-excursion
	    (pop-to-buffer "Spellings")
	    (setq needs-checkpointing 0)
	    (erase-buffer)
	    (insert-string (concat
			       "\n' ', 'n':	skip to next typo\n"
			       "'r':		replace using query-replace\n"
			       "'s':		suggest alternatives\n"
			       "'a':		add word to spelling table\n"
			       "'^G', 'e':	exit from sweep-typos\n"
			   ))
	    (beginning-of-file)
	)
    )
    (next-typo continue place word
	(setq continue 1)
	(setq place (dot))
	(while continue
	    (if (error-occured (setq word (get-word)))
		(progn
		    (goto-character place)
		    (message "No more typos!")
		    (setq word "")
		    (setq continue 0))
		(progn
		    (if (! spelltab-loaded)
			(message "Loading spelling table...")
			(sit-for 0))
		    (if (! (check-spelling word))
			(setq continue 0)))
	    )
	)
	(if (interactive)
	    (novalue)
	    word)
    )
    (sweep-typos word action replacement continue place
	(setq continue 1)
	(while (& continue (!= (setq word (next-typo)) ""))
	    (setq place (dot))
	    (search-reverse word)
	    (message word " ? ")
	    (setq action (get-tty-character))
	    (if
		(| (= action '^G') (= action 'e'))
		(progn
		    (message "Sweep complete")
		    (setq continue 0))
		(= action 'r')
		(error-occured
		    (query-replace-string ""
			(get-tty-string
			    (concat word " => "))))
		(= action 's')
		(progn
		    (setq replacement (do-alternatives word))
		    (if (!= replacement "")
			(query-replace-string "" replacement)
			(setq place (dot))))
		(| (= action ' ') (= action 'n')) (setq continue 1)
		(= action 'a') (assert-spelling word)
		(progn
		    (#typo-help)
		    (setq place (dot))))
	    (goto-character place)
	)
	(novalue)
    )
)

(bind-to-key "next-typo" "\^X\^T")
(bind-to-key "sweep-typos" "\et")
