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 () {
51 string prg
= "\"$TEXMACS_PATH/bin/aspell/aspell.exe\"";
52 cmd
= prg
* " --data-dir=.%//data --dict-dir=.%//dict -a";
54 if (exists_in_path ("aspell")) cmd
= "aspell";
56 #if defined (__MINGW__) || defined (__MINGW32__)
57 if (exists (url_system ("C:\\Program Files\\Aspell\\bin\\aspell.exe")))
58 cmd
= "\"C:\\Program Files\\Aspell\\bin\\aspell.exe\"";
62 cmd
<< " -a -d " * ispell_dictionary (lan
) * ispell_extra_args (lan
);
64 ln
= make_pipe_link (cmd
);
66 if (ln
->alive
) return "ok";
67 string message
= ln
->start ();
68 if (DEBUG_IO
) cout
<< "Ispell] Received " << message
<< "\n";
69 if (starts (message
, "Error: ")) {
70 if (ln
->alive
) ln
->stop ();
74 if (DEBUG_IO
) cout
<< "Ispell] Received " << message
<< "\n";
76 if (search_forwards (message
, 0, "@(#)")) return "ok";
78 if (starts (message
, "@(#)")) return "ok";
80 if (ln
->alive
) ln
->stop ();
81 return "Error: no dictionary for#" * lan
;
85 ispeller_rep::retrieve () {
87 while ((ret
!= "\n") && (!ends (ret
, "\n\n")) &&
88 ((!ends (ret
, "\n")) || (!starts (ret
, "@(#)"))))
91 string mess
= ln
->read (LINK_ERR
);
92 string extra
= ln
->read (LINK_OUT
);
93 if (mess
!= "") cerr
<< "TeXmacs] ispell error: " << mess
<< "\n";
96 return "Error: ispell does not respond";
100 return ispell_decode (lan
, ret
);
104 ispeller_rep::send (string cmd
) {
105 ln
->write (ispell_encode (lan
, cmd
) * "\n", LINK_IN
);
108 /******************************************************************************
109 * Ispell dictionaries
110 ******************************************************************************/
112 static hashmap
<string
,string
> the_dict ("");
115 init_dictionary (string lang
, string dict
) {
116 if (the_dict
->contains (lang
)) return;
117 if (exists ("/usr/lib/ispell/" * dict
* ".hash") ||
118 exists ("/usr/lib/aspell/" * dict
) ||
119 exists ("/usr/lib/aspell/" * dict
* ".multi"))
120 the_dict (lang
)= dict
;
124 ispell_dictionary (string lang
) {
125 if (N(the_dict
) == 0) {
126 init_dictionary ("english", "english");
127 init_dictionary ("english", "american");
128 init_dictionary ("danish", "danish");
129 init_dictionary ("danish", "dansk");
130 init_dictionary ("dutch", "dutch");
131 init_dictionary ("dutch", "nederlands");
132 init_dictionary ("french", "french");
133 init_dictionary ("french", "francais");
134 init_dictionary ("german", "german");
135 init_dictionary ("german", "deutsch");
136 init_dictionary ("german", "ngerman");
137 init_dictionary ("german", "ndeutsch");
138 init_dictionary ("german", "ogerman");
139 init_dictionary ("german", "odeutsch");
140 init_dictionary ("german", "swiss");
141 init_dictionary ("portuguese", "portuguese");
142 init_dictionary ("portuguese", "portugues");
143 init_dictionary ("portuguese", "brazilian");
144 init_dictionary ("portuguese", "brasileiro");
145 init_dictionary ("spanish", "spanish");
146 init_dictionary ("spanish", "espaƱol");
147 init_dictionary ("spanish", "espa~nol");
148 init_dictionary ("spanish", "espanol");
149 init_dictionary ("spanish", "castellano");
150 init_dictionary ("swedish", "swedish");
151 init_dictionary ("swedish", "svenska");
153 if (the_dict
->contains (lang
)) return the_dict
[lang
];
157 /******************************************************************************
158 * Language dependent arguments to ispell
159 ******************************************************************************/
162 ispell_extra_args (string lan
) {
169 /******************************************************************************
170 * Internationalization
171 ******************************************************************************/
174 ispell_encode (string lan
, string s
) {
175 if ((lan
== "czech") || (lan
== "hungarian") ||
176 (lan
== "polish") || (lan
== "slovene"))
177 return cork_to_il2 (s
);
178 else if ((lan
== "bulgarian") || (lan
== "russian"))
179 return koi8_to_iso (s
);
180 else if (lan
== "ukrainian")
181 return koi8uk_to_iso (s
);
182 else if (lan
== "spanish")
183 return spanish_to_ispanish (s
);
184 else if (lan
== "german")
185 return german_to_igerman (s
);
190 ispell_decode (string lan
, string s
) {
191 if ((lan
== "czech") || (lan
== "hungarian") ||
192 (lan
== "polish") || (lan
== "slovene"))
193 return il2_to_cork (s
);
194 else if ((lan
== "bulgarian") || (lan
== "russian"))
195 return iso_to_koi8 (s
);
196 else if (lan
== "ukrainian")
197 return iso_to_koi8uk (s
);
198 else if (lan
== "spanish")
199 return ispanish_to_spanish (s
);
200 else if (lan
== "german")
201 return igerman_to_german (s
);
205 /******************************************************************************
207 ******************************************************************************/
210 parse_ispell (string s
) {
211 #if defined (__MINGW__) || defined (__MINGW32__)
212 while (ends (s
, "\r\n")) s
= s (0, N(s
)-2);
214 while (ends (s
, "\n")) s
= s (0, N(s
)-1);
219 for (i
=0, j
=0; j
<N(s
); j
++)
220 if (s
[j
]==':') flag
= false;
221 else if (((s
[j
]==' ') && (flag
|| (j
==i
) || (s
[j
-1]==':'))) || (s
[j
]==','))
223 if (j
>i
) t
<< s (i
, j
);
228 if (N(t
) == 0) return tree (TUPLE
, "0");
229 if ((t
[0] == "+") || (t
[0] == "*") || (t
[0] == "-")) return "ok";
230 if ((N(t
)>=4) && ((t
[0] == "&") || (t
[0]=="?"))) {
231 tree
u (TUPLE
, t
[2]);
232 u
<< A (t (4, N (t
)));
235 return tree (TUPLE
, "0");
239 ispell_send (string lan
, string s
) {
240 ispeller sc
= ispeller (lan
);
241 if ((!is_nil (sc
)) && sc
->ln
->alive
) sc
->send (s
);
245 ispell_eval (string lan
, string s
) {
246 ispeller sc
= ispeller (lan
);
247 if ((!is_nil (sc
)) && sc
->ln
->alive
) {
249 return sc
->retrieve ();
254 /******************************************************************************
255 * Spell checking interface
256 ******************************************************************************/
259 ispell_start (string lan
) {
260 if (DEBUG_IO
) cout
<< "Ispell] Start " << lan
<< "\n";
261 ispeller sc
= ispeller (lan
);
262 if (is_nil (sc
)) sc
= tm_new
<ispeller_rep
> (lan
);
267 ispell_check (string lan
, string s
) {
268 if (DEBUG_IO
) cout
<< "Ispell] Check " << s
<< "\n";
269 ispeller sc
= ispeller (lan
);
270 if (is_nil (sc
) || (!sc
->ln
->alive
)) {
271 string message
= ispell_start (lan
);
272 if (starts (message
, "Error: ")) return message
;
274 string ret_s
= ispell_eval (lan
, "^" * s
);
275 if (starts (ret_s
, "Error: ")) return ret_s
;
276 return parse_ispell (ret_s
);
280 ispell_accept (string lan
, string s
) {
281 if (DEBUG_IO
) cout
<< "Ispell] Accept " << s
<< "\n";
282 ispell_send (lan
, "@" * s
);
286 ispell_insert (string lan
, string s
) {
287 if (DEBUG_IO
) cout
<< "Ispell] Insert " << s
<< "\n";
288 ispell_send (lan
, "*" * s
);
292 ispell_done (string lan
) {
293 if (DEBUG_IO
) cout
<< "Ispell] End " << lan
<< "\n";
294 ispell_send (lan
, "#");