1 #if !defined(lint) && !defined(DOS)
2 static char rcsid
[] = "$Id: spell.c 854 2007-12-07 17:44:43Z hubert@u.washington.edu $";
6 * ========================================================================
7 * Copyright 2006-2007 University of Washington
8 * Copyright 2013-2015 Eduardo Chappa
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
25 #include "../headers.h"
27 #include "../estruct.h"
32 #include "../keydefs.h"
35 #include "../../pith/charconv/filesys.h"
44 int movetoword(UCS
*);
47 static char *spellhelp
[] = {
48 /* TRANSLATORS: Some help text. The ~ characters cause
49 the characters they are in front of to be bold. */
50 N_("Spell Check Help"),
52 N_(" The spell checker examines all words in the text. It then"),
53 N_(" offers each misspelled word for correction while simultaneously"),
54 N_(" highlighting it in the text. To leave a word unchanged simply"),
55 N_("~ hit ~R~e~t~u~r~n at the edit prompt. If a word has been corrected,"),
56 N_(" each occurrence of the incorrect word is offered for replacement."),
58 N_("~ Spell checking can be cancelled at any time by typing ~^~C (~F~3)"),
59 N_(" after exiting help."),
61 N_("End of Spell Check Help"),
67 static char *pinespellhelp
[] = {
68 N_("Spell Check Help"),
70 N_("\tThe spell checker examines all words in the text. It then"),
71 N_("\toffers each misspelled word for correction while simultaneously"),
72 N_("\thighlighting it in the text. To leave a word unchanged simply"),
73 N_("\thit Return at the edit prompt. If a word has been corrected,"),
74 N_("\teach occurrence of the incorrect word is offered for replacement."),
76 N_("\tSpell checking can be cancelled at any time by typing ^C (F3)"),
77 N_("\tafter exiting help."),
79 N_("End of Spell Check Help"),
86 * spell() - check for potentially missspelled words and offer them for
92 int status
, next
, ret
;
93 char ccb
[NLINE
], *sp
, *fn
, *lp
, *wsp
, c
, spc
[NLINE
];
95 UCS wb
[NLINE
], cb
[NLINE
];
99 emlwrite(_("Checking spelling..."), NULL
); /* greetings */
102 return(alt_editor(1, 0)); /* f == 1 means fork speller */
104 if((fn
= writetmp(0, NULL
)) == NULL
){
105 emlwrite(_("Can't write temp file for spell checker"), NULL
);
109 if((sp
= (char *)getenv("SPELL")) == NULL
)
113 ret
= (strlen(sp
) + 1);
114 snprintf(spc
, sizeof(spc
), "%s", sp
);
116 for(lp
= spc
, ret
= FIOERR
; *lp
; lp
++){
117 if((wsp
= strpbrk(lp
, " \t")) != NULL
){
123 ret
= fexist(lp
, "x", (off_t
*)NULL
);
126 char *path
, fname
[MAXPATH
+1];
128 if(!(path
= getenv("PATH")))
129 path
= ":/bin:/usr/bin";
132 while(ret
!= FIOSUC
&& *path
&& pathcat(fname
, &path
, lp
))
133 ret
= fexist(fname
, "x", (off_t
*)NULL
);
145 emlwrite(_("\007Spell-checking file \"%s\" not found"), &eml
);
149 snprintf(ccb
, sizeof(ccb
), "( %s ) < %s", sp
, fn
);
150 if(P_open(ccb
) != FIOSUC
){ /* read output from command */
152 emlwrite(_("Can't fork spell checker"), NULL
);
157 while(ffgetline(wb
, NLINE
, NULL
, 0) == FIOSUC
&& ret
){
158 if((b
= ucs4_strchr(wb
, (UCS
) '\n')) != NULL
)
161 ucs4_strncpy(cb
, wb
, NLINE
);
171 if(movetoword(wb
) != TRUE
)
176 pputs(wb
, 1); /* highlight word */
179 if(ucs4_strcmp(cb
, wb
)){
180 char prompt
[2*NLINE
+ 32];
183 wbu
= ucs4_to_utf8_cpystr(wb
);
184 cbu
= ucs4_to_utf8_cpystr(cb
);
186 snprintf(prompt
, sizeof(prompt
), _("Replace \"%s\" with \"%s\""), wbu
, cbu
);
187 status
=mlyesno_utf8(prompt
, TRUE
);
189 fs_give((void **) &wbu
);
191 fs_give((void **) &cbu
);
196 p
= utf8_to_ucs4_cpystr(_("Edit a replacement: "));
197 status
=mlreplyd(p
, cb
, NLINE
, QDEFLT
, NULL
);
199 fs_give((void **) &p
);
203 curwp
->w_flag
|= WFMOVE
; /* put cursor back */
204 sgarbk
= 0; /* fake no-keymenu-change! */
206 pputs(wb
, 0); /* un-highlight */
210 chword(wb
, cb
, 0); /* correct word */
212 update(); /* place cursor */
215 emlwrite(_("Spell Checking Cancelled"), NULL
);
221 VARS_TO_SAVE
*saved_state
;
223 saved_state
= save_pico_state();
224 (*Pmaster
->helper
)(pinespellhelp
,
225 _("Help with Spelling Checker"), 1);
227 restore_pico_state(saved_state
);
228 free_pico_state(saved_state
);
232 pico_help(spellhelp
, _("Help with Spelling Checker"), 1);
235 next
= 0; /* don't get next word */
236 sgarbf
= TRUE
; /* repaint full screen */
241 emlwrite("Huh?", NULL
); /* shouldn't get here, but.. */
247 forwword(0, 1); /* goto next word */
251 P_close(); /* clean up */
254 curwp
->w_flag
|= WFHARD
|WFMODE
;
258 emlwrite(_("Done checking spelling"), NULL
);
268 * movetoword() - move to the first occurance of the word w
281 register int off
; /* curwp offset */
282 register LINE
*lp
; /* curwp line */
284 olddoto
= curwp
->w_doto
; /* save where we are */
285 olddotp
= curwp
->w_dotp
;
287 curwp
->w_bufp
->b_mode
|= MDEXACT
; /* case sensitive */
288 while(forscan(&i
, w
, SR_FORWARD
, NULL
, 0, 1) == TRUE
){
290 break; /* wrap NOT allowed! */
292 lp
= curwp
->w_dotp
; /* for convenience */
296 * We want to minimize the number of substrings that we report
297 * as matching a misspelled word...
299 if(off
== 0 || !ucs4_isalpha(lgetc(lp
, off
- 1).c
)){
300 off
+= ucs4_strlen(w
);
301 if((!ucs4_isalpha(lgetc(lp
, off
).c
) || off
== llength(lp
))
302 && lgetc(lp
, 0).c
!= '>'){
308 forwchar(0, 1); /* move on... */
311 curwp
->w_bufp
->b_mode
^= MDEXACT
; /* case insensitive */
314 curwp
->w_dotp
= olddotp
;
315 curwp
->w_doto
= olddoto
;
318 curwp
->w_flag
|= WFHARD
;