2 * ========================================================================
3 * Copyright 2006-2007 University of Washington
4 * Copyright 2013-2022 Eduardo Chappa
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * ========================================================================
21 #include "../headers.h"
23 #include "../estruct.h"
28 #include "../keydefs.h"
31 #include "../../pith/charconv/filesys.h"
40 int movetoword(UCS
*);
43 static char *spellhelp
[] = {
44 /* TRANSLATORS: Some help text. The ~ characters cause
45 the characters they are in front of to be bold. */
46 N_("Spell Check Help"),
48 N_(" The spell checker examines all words in the text. It then"),
49 N_(" offers each misspelled word for correction while simultaneously"),
50 N_(" highlighting it in the text. To leave a word unchanged simply"),
51 N_("~ hit ~R~e~t~u~r~n at the edit prompt. If a word has been corrected,"),
52 N_(" each occurrence of the incorrect word is offered for replacement."),
54 N_("~ Spell checking can be cancelled at any time by typing ~^~C (~F~3)"),
55 N_(" after exiting help."),
57 N_("End of Spell Check Help"),
63 static char *pinespellhelp
[] = {
64 N_("Spell Check Help"),
66 N_("\tThe spell checker examines all words in the text. It then"),
67 N_("\toffers each misspelled word for correction while simultaneously"),
68 N_("\thighlighting it in the text. To leave a word unchanged simply"),
69 N_("\thit Return at the edit prompt. If a word has been corrected,"),
70 N_("\teach occurrence of the incorrect word is offered for replacement."),
72 N_("\tSpell checking can be cancelled at any time by typing ^C (F3)"),
73 N_("\tafter exiting help."),
75 N_("End of Spell Check Help"),
82 * spell() - check for potentially missspelled words and offer them for
88 int status
, next
, ret
;
89 char ccb
[NLINE
], *sp
, *fn
, *lp
, *wsp
, c
, spc
[NLINE
];
91 UCS wb
[NLINE
], cb
[NLINE
];
95 emlwrite(_("Checking spelling..."), NULL
); /* greetings */
98 return(alt_editor(1, 0)); /* f == 1 means fork speller */
100 if((fn
= writetmp(0, NULL
)) == NULL
){
101 emlwrite(_("Can't write temp file for spell checker"), NULL
);
105 if((sp
= (char *)getenv("SPELL")) == NULL
)
109 ret
= (strlen(sp
) + 1);
110 snprintf(spc
, sizeof(spc
), "%s", sp
);
112 for(lp
= spc
, ret
= FIOERR
; *lp
; lp
++){
113 if((wsp
= strpbrk(lp
, " \t")) != NULL
){
119 ret
= fexist(lp
, "x", (off_t
*)NULL
);
122 char *path
, fname
[MAXPATH
+1];
124 if(!(path
= getenv("PATH")))
125 path
= ":/bin:/usr/bin";
128 while(ret
!= FIOSUC
&& *path
&& pathcat(fname
, &path
, lp
))
129 ret
= fexist(fname
, "x", (off_t
*)NULL
);
141 emlwwrite(_("Spell-checking file \"%s\" not found"), &eml
);
145 snprintf(ccb
, sizeof(ccb
), "( %s ) < %s", sp
, fn
);
146 if(P_open(ccb
) != FIOSUC
){ /* read output from command */
148 emlwrite(_("Can't fork spell checker"), NULL
);
153 while(ffgetline(wb
, NLINE
, NULL
, 0) == FIOSUC
&& ret
){
154 if((b
= ucs4_strchr(wb
, (UCS
) '\n')) != NULL
)
157 ucs4_strncpy(cb
, wb
, NLINE
);
167 if(movetoword(wb
) != TRUE
)
172 pputs(wb
, 1); /* highlight word */
175 if(ucs4_strcmp(cb
, wb
)){
176 char prompt
[2*NLINE
+ 32];
179 wbu
= ucs4_to_utf8_cpystr(wb
);
180 cbu
= ucs4_to_utf8_cpystr(cb
);
182 snprintf(prompt
, sizeof(prompt
), _("Replace \"%s\" with \"%s\""), wbu
, cbu
);
183 status
=mlyesno_utf8(prompt
, TRUE
);
185 fs_give((void **) &wbu
);
187 fs_give((void **) &cbu
);
192 p
= utf8_to_ucs4_cpystr(_("Edit a replacement: "));
193 status
=mlreplyd(p
, cb
, NLINE
, QDEFLT
, NULL
);
195 fs_give((void **) &p
);
199 curwp
->w_flag
|= WFMOVE
; /* put cursor back */
200 sgarbk
= 0; /* fake no-keymenu-change! */
202 pputs(wb
, 0); /* un-highlight */
206 chword(wb
, cb
, 0); /* correct word */
208 update(); /* place cursor */
211 emlwrite(_("Spell Checking Cancelled"), NULL
);
217 VARS_TO_SAVE
*saved_state
;
219 saved_state
= save_pico_state();
220 (*Pmaster
->helper
)(pinespellhelp
,
221 _("Help with Spelling Checker"), 1);
223 restore_pico_state(saved_state
);
224 free_pico_state(saved_state
);
228 pico_help(spellhelp
, _("Help with Spelling Checker"), 1);
231 next
= 0; /* don't get next word */
232 sgarbf
= TRUE
; /* repaint full screen */
237 emlwrite("Huh?", NULL
); /* shouldn't get here, but.. */
243 forwword(0, 1); /* goto next word */
247 P_close(); /* clean up */
250 curwp
->w_flag
|= WFHARD
|WFMODE
;
254 emlwrite(_("Done checking spelling"), NULL
);
264 * movetoword() - move to the first occurance of the word w
277 register int off
; /* curwp offset */
278 register LINE
*lp
; /* curwp line */
280 olddoto
= curwp
->w_doto
; /* save where we are */
281 olddotp
= curwp
->w_dotp
;
283 curwp
->w_bufp
->b_mode
|= MDEXACT
; /* case sensitive */
284 while(forscan(&i
, w
, SR_FORWARD
, NULL
, 0, 1) == TRUE
){
286 break; /* wrap NOT allowed! */
288 lp
= curwp
->w_dotp
; /* for convenience */
292 * We want to minimize the number of substrings that we report
293 * as matching a misspelled word...
295 if(off
== 0 || !ucs4_isalpha(lgetc(lp
, off
- 1).c
)){
296 off
+= ucs4_strlen(w
);
297 if((!ucs4_isalpha(lgetc(lp
, off
).c
) || off
== llength(lp
))
298 && lgetc(lp
, 0).c
!= '>'){
304 forwchar(0, 1); /* move on... */
307 curwp
->w_bufp
->b_mode
^= MDEXACT
; /* case insensitive */
310 curwp
->w_dotp
= olddotp
;
311 curwp
->w_doto
= olddoto
;
314 curwp
->w_flag
|= WFHARD
;