2
/******************************************************************************
4
* DESCRIPTION: interface with the ispell spell checker
5
* COPYRIGHT : (C) 1999 Joris van der Hoeven
6
*******************************************************************************
7
* This software falls under the GNU general public license version 3 or later.
8
* It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9
* in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10
******************************************************************************/
12
#include "Ispell/ispell.hpp"
14
#include "resource.hpp"
15
#include "tm_link.hpp"
16
#include "convert.hpp"
18
string ispell_dictionary (string lang);
19
string ispell_extra_args (string lang);
20
string ispell_encode (string lan, string s);
21
string ispell_decode (string lan, string s);
23
/******************************************************************************
24
* The connection resource
25
******************************************************************************/
28
struct ispeller_rep: rep<ispeller> {
29
string lan; // name of the session
30
tm_link ln; // the pipe
33
ispeller_rep (string lan);
36
void send (string cmd);
38
RESOURCE_CODE(ispeller);
40
/******************************************************************************
41
* Routines for ispellers
42
******************************************************************************/
44
ispeller_rep::ispeller_rep (string lan2): rep<ispeller> (lan2), lan (lan2) {}
47
ispeller_rep::start () {
50
string prg= "\"$TEXMACS_PATH/bin/aspell/aspell.exe\"";
51
string cmd= prg * " --data-dir=.%//data --dict-dir=.%//dict -a";
53
string cmd= "ispell -a -d " * ispell_dictionary (lan)
54
* ispell_extra_args (lan);
55
if (exists_in_path ("aspell")) cmd[0]= 'a';
57
ln= make_pipe_link (cmd);
59
if (ln->alive) return "ok";
60
string message= ln->start ();
61
if (starts (message, "Error: ")) return message;
64
if (search_forwards (message, 0, "@(#)")) return "ok";
66
if (starts (message, "@(#)")) return "ok";
68
return "Error: no dictionary for#" * lan;
72
ispeller_rep::retrieve () {
74
while ((ret != "\n") && (!ends (ret, "\n\n")) &&
75
((!ends (ret, "\n")) || (!starts (ret, "@(#)"))))
78
string mess = ln->read (LINK_ERR);
79
string extra= ln->read (LINK_OUT);
80
if (mess != "") cerr << "TeXmacs] ispell error: " << mess << "\n";
81
if (extra == "") return "Error: ispell does not respond";
84
return ispell_decode(lan,ret);
88
ispeller_rep::send (string cmd) {
89
ln->write (ispell_encode(lan,cmd) * "\n", LINK_IN);
92
/******************************************************************************
94
******************************************************************************/
96
static hashmap<string,string> the_dict ("");
99
init_dictionary (string lang, string dict) {
100
if (the_dict->contains (lang)) return;
101
if (exists ("/usr/lib/ispell/" * dict * ".hash") ||
102
exists ("/usr/lib/aspell/" * dict) ||
103
exists ("/usr/lib/aspell/" * dict * ".multi"))
104
the_dict (lang)= dict;
108
ispell_dictionary (string lang) {
109
if (N(the_dict) == 0) {
110
init_dictionary ("english", "english");
111
init_dictionary ("english", "american");
112
init_dictionary ("danish", "danish");
113
init_dictionary ("danish", "dansk");
114
init_dictionary ("dutch", "dutch");
115
init_dictionary ("dutch", "nederlands");
116
init_dictionary ("french", "french");
117
init_dictionary ("french", "francais");
118
init_dictionary ("german", "german");
119
init_dictionary ("german", "deutsch");
120
init_dictionary ("german", "ngerman");
121
init_dictionary ("german", "ndeutsch");
122
init_dictionary ("german", "ogerman");
123
init_dictionary ("german", "odeutsch");
124
init_dictionary ("german", "swiss");
125
init_dictionary ("portuguese", "portuguese");
126
init_dictionary ("portuguese", "portugues");
127
init_dictionary ("portuguese", "brazilian");
128
init_dictionary ("portuguese", "brasileiro");
129
init_dictionary ("spanish", "spanish");
130
init_dictionary ("spanish", "español");
131
init_dictionary ("spanish", "espa~nol");
132
init_dictionary ("spanish", "espanol");
133
init_dictionary ("spanish", "castellano");
134
init_dictionary ("swedish", "swedish");
135
init_dictionary ("swedish", "svenska");
137
if (the_dict->contains (lang)) return the_dict [lang];
141
/******************************************************************************
142
* Language dependent arguments to ispell
143
******************************************************************************/
146
ispell_extra_args (string lan) {
153
/******************************************************************************
154
* Internationalization
155
******************************************************************************/
158
ispell_encode (string lan, string s) {
159
if ((lan == "czech") || (lan == "hungarian") ||
160
(lan == "polish") || (lan == "slovene"))
161
return cork_to_il2 (s);
162
else if ((lan == "bulgarian") || (lan == "russian"))
163
return koi8_to_iso (s);
164
else if (lan == "ukrainian")
165
return koi8uk_to_iso (s);
166
else if (lan == "spanish")
167
return spanish_to_ispanish (s);
168
else if (lan == "german")
169
return german_to_igerman (s);
174
ispell_decode (string lan, string s) {
175
if ((lan == "czech") || (lan == "hungarian") ||
176
(lan == "polish") || (lan == "slovene"))
177
return il2_to_cork (s);
178
else if ((lan == "bulgarian") || (lan == "russian"))
179
return iso_to_koi8 (s);
180
else if (lan == "ukrainian")
181
return iso_to_koi8uk (s);
182
else if (lan == "spanish")
183
return ispanish_to_spanish (s);
184
else if (lan == "german")
185
return igerman_to_german (s);
189
/******************************************************************************
191
******************************************************************************/
194
parse_ispell (string s) {
195
while (ends (s, "\n")) s= s (0, N(s)-1);
199
for (i=0, j=0; j<N(s); j++)
200
if (s[j]==':') flag= false;
201
else if (((s[j]==' ') && (flag || (j==i) || (s[j-1]==':'))) || (s[j]==','))
203
if (j>i) t << s (i, j);
208
if (N(t) == 0) return tree (TUPLE, "0");
209
if ((t[0] == "+") || (t[0] == "*") || (t[0] == "-")) return "ok";
210
if ((N(t)>=4) && ((t[0] == "&") || (t[0]=="?"))) {
211
tree u (TUPLE, t[2]);
212
u << A (t (4, N (t)));
215
return tree (TUPLE, "0");
219
ispell_send (string lan, string s) {
220
ispeller sc= ispeller (lan);
221
if ((!is_nil (sc)) && sc->ln->alive) sc->send (s);
225
ispell_eval (string lan, string s) {
226
ispeller sc= ispeller (lan);
227
if ((!is_nil (sc)) && sc->ln->alive) {
229
return sc->retrieve ();
234
/******************************************************************************
235
* Spell checking interface
236
******************************************************************************/
239
ispell_start (string lan) {
240
ispeller sc= ispeller (lan);
241
if (is_nil (sc)) sc= tm_new<ispeller_rep> (lan);
246
ispell_check (string lan, string s) {
247
ispeller sc= ispeller (lan);
248
if (is_nil (sc) || (!sc->ln->alive)) {
249
string message= ispell_start (lan);
250
if (starts (message, "Error: ")) return message;
252
string ret_s= ispell_eval (lan, "^" * s);
253
if (starts (ret_s, "Error: ")) return ret_s;
254
return parse_ispell (ret_s);
258
ispell_accept (string lan, string s) {
259
ispell_send (lan, "@" * s);
263
ispell_insert (string lan, string s) {
264
ispell_send (lan, "*" * s);
268
ispell_done (string lan) {
269
ispell_send (lan, "#");