• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdespell2
 

tdespell2

  • tdespell2
  • plugins
  • ispell
ispell_checker.cpp
1 /* vim: set sw=8: -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* tdespell2 - adopted from Enchant
3  * Copyright (C) 2003 Dom Lachowicz
4  * Copyright (C) 2004 Zack Rusin <zack@kde.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  * In addition, as a special exception, Dom Lachowicz
22  * gives permission to link the code of this program with
23  * non-LGPL Spelling Provider libraries (eg: a MSFT Office
24  * spell checker backend) and distribute linked combinations including
25  * the two. You must obey the GNU Lesser General Public License in all
26  * respects for all of the code used other than said providers. If you modify
27  * this file, you may extend this exception to your version of the
28  * file, but you are not obligated to do so. If you do not wish to
29  * do so, delete this exception statement from your version.
30  */
31 
32 #include <config.h>
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 #include <string>
39 #include <vector>
40 
41 #include "sp_spell.h"
42 #include "ispell_checker.h"
43 
44 #include <tqmap.h>
45 #include <tqdir.h>
46 #include <tqfileinfo.h>
47 
48 /***************************************************************************/
49 
50 typedef struct str_ispell_map
51 {
52  const char * lang;
53  const char * dict;
54  const char * enc;
55 } IspellMap;
56 
57 static const char *ispell_dirs [] = {
58  "/usr/" SYSTEM_LIBDIR "/ispell",
59  "/usr/lib/ispell",
60  "/usr/local/" SYSTEM_LIBDIR "/ispell",
61  "/usr/local/lib/ispell",
62  "/usr/local/share/ispell",
63  "/usr/share/ispell",
64  "/usr/pkg/lib",
65  0
66 };
67 static const IspellMap ispell_map [] = {
68  {"ca" ,"catala.hash" ,"iso-8859-1" },
69  {"ca_ES" ,"catala.hash" ,"iso-8859-1" },
70  {"cs" ,"czech.hash" ,"iso-8859-2" },
71  {"cs_CZ" ,"czech.hash" ,"iso-8859-2" },
72  {"da" ,"dansk.hash" ,"iso-8859-1" },
73  {"da_DK" ,"dansk.hash" ,"iso-8859-1" },
74  {"de" ,"deutsch.hash" ,"iso-8859-1" },
75  {"de_CH" ,"swiss.hash" ,"iso-8859-1" },
76  {"de_AT" ,"deutsch.hash" ,"iso-8859-1" },
77  {"de_DE" ,"deutsch.hash" ,"iso-8859-1" },
78  {"el" ,"ellhnika.hash" ,"iso-8859-7" },
79  {"el_GR" ,"ellhnika.hash" ,"iso-8859-7" },
80  {"en" ,"british.hash" ,"iso-8859-1" },
81  {"en_AU" ,"british.hash" ,"iso-8859-1" },
82  {"en_BZ" ,"british.hash" ,"iso-8859-1" },
83  {"en_CA" ,"british.hash" ,"iso-8859-1" },
84  {"en_GB" ,"british.hash" ,"iso-8859-1" },
85  {"en_IE" ,"british.hash" ,"iso-8859-1" },
86  {"en_JM" ,"british.hash" ,"iso-8859-1" },
87  {"en_NZ" ,"british.hash" ,"iso-8859-1" },
88  {"en_TT" ,"british.hash" ,"iso-8859-1" },
89  {"en_ZA" ,"british.hash" ,"iso-8859-1" },
90  {"en_ZW" ,"british.hash" ,"iso-8859-1" },
91  {"en_PH" ,"american.hash" ,"iso-8859-1" },
92  {"en_US" ,"american.hash" ,"iso-8859-1" },
93  {"eo" ,"esperanto.hash" ,"iso-8859-3" },
94  {"es" ,"espanol.hash" ,"iso-8859-1" },
95  {"es_AR" ,"espanol.hash" ,"iso-8859-1" },
96  {"es_BO" ,"espanol.hash" ,"iso-8859-1" },
97  {"es_CL" ,"espanol.hash" ,"iso-8859-1" },
98  {"es_CO" ,"espanol.hash" ,"iso-8859-1" },
99  {"es_CR" ,"espanol.hash" ,"iso-8859-1" },
100  {"es_DO" ,"espanol.hash" ,"iso-8859-1" },
101  {"es_EC" ,"espanol.hash" ,"iso-8859-1" },
102  {"es_ES" ,"espanol.hash" ,"iso-8859-1" },
103  {"es_GT" ,"espanol.hash" ,"iso-8859-1" },
104  {"es_HN" ,"espanol.hash" ,"iso-8859-1" },
105  {"es_MX" ,"espanol.hash" ,"iso-8859-1" },
106  {"es_NI" ,"espanol.hash" ,"iso-8859-1" },
107  {"es_PA" ,"espanol.hash" ,"iso-8859-1" },
108  {"es_PE" ,"espanol.hash" ,"iso-8859-1" },
109  {"es_PR" ,"espanol.hash" ,"iso-8859-1" },
110  {"es_PY" ,"espanol.hash" ,"iso-8859-1" },
111  {"es_SV" ,"espanol.hash" ,"iso-8859-1" },
112  {"es_UY" ,"espanol.hash" ,"iso-8859-1" },
113  {"es_VE" ,"espanol.hash" ,"iso-8859-1" },
114  {"fi" ,"finnish.hash" ,"iso-8859-1" },
115  {"fi_FI" ,"finnish.hash" ,"iso-8859-1" },
116  {"fr" ,"francais.hash" ,"iso-8859-1" },
117  {"fr_BE" ,"francais.hash" ,"iso-8859-1" },
118  {"fr_CA" ,"francais.hash" ,"iso-8859-1" },
119  {"fr_CH" ,"francais.hash" ,"iso-8859-1" },
120  {"fr_FR" ,"francais.hash" ,"iso-8859-1" },
121  {"fr_LU" ,"francais.hash" ,"iso-8859-1" },
122  {"fr_MC" ,"francais.hash" ,"iso-8859-1" },
123  {"hu" ,"hungarian.hash" ,"iso-8859-2" },
124  {"hu_HU" ,"hungarian.hash" ,"iso-8859-2" },
125  {"ga" ,"irish.hash" ,"iso-8859-1" },
126  {"ga_IE" ,"irish.hash" ,"iso-8859-1" },
127  {"gl" ,"galician.hash" ,"iso-8859-1" },
128  {"gl_ES" ,"galician.hash" ,"iso-8859-1" },
129  {"ia" ,"interlingua.hash" ,"iso-8859-1" },
130  {"it" ,"italian.hash" ,"iso-8859-1" },
131  {"it_IT" ,"italian.hash" ,"iso-8859-1" },
132  {"it_CH" ,"italian.hash" ,"iso-8859-1" },
133  {"la" ,"mlatin.hash" ,"iso-8859-1" },
134  {"la_IT" ,"mlatin.hash" ,"iso-8859-1" },
135  {"lt" ,"lietuviu.hash" ,"iso-8859-13" },
136  {"lt_LT" ,"lietuviu.hash" ,"iso-8859-13" },
137  {"nl" ,"nederlands.hash" ,"iso-8859-1" },
138  {"nl_NL" ,"nederlands.hash" ,"iso-8859-1" },
139  {"nl_BE" ,"nederlands.hash" ,"iso-8859-1" },
140  {"nb" ,"norsk.hash" ,"iso-8859-1" },
141  {"nb_NO" ,"norsk.hash" ,"iso-8859-1" },
142  {"nn" ,"nynorsk.hash" ,"iso-8859-1" },
143  {"nn_NO" ,"nynorsk.hash" ,"iso-8859-1" },
144  {"no" ,"norsk.hash" ,"iso-8859-1" },
145  {"no_NO" ,"norsk.hash" ,"iso-8859-1" },
146  {"pl" ,"polish.hash" ,"iso-8859-2" },
147  {"pl_PL" ,"polish.hash" ,"iso-8859-2" },
148  {"pt" ,"brazilian.hash" ,"iso-8859-1" },
149  {"pt_BR" ,"brazilian.hash" ,"iso-8859-1" },
150  {"pt_PT" ,"portugues.hash" ,"iso-8859-1" },
151  {"ru" ,"russian.hash" ,"koi8-r" },
152  {"ru_MD" ,"russian.hash" ,"koi8-r" },
153  {"ru_RU" ,"russian.hash" ,"koi8-r" },
154  {"sc" ,"sardinian.hash" ,"iso-8859-1" },
155  {"sc_IT" ,"sardinian.hash" ,"iso-8859-1" },
156  {"sk" ,"slovak.hash" ,"iso-8859-2" },
157  {"sk_SK" ,"slovak.hash" ,"iso-8859-2" },
158  {"sl" ,"slovensko.hash" ,"iso-8859-2" },
159  {"sl_SI" ,"slovensko.hash" ,"iso-8859-2" },
160  {"sv" ,"svenska.hash" ,"iso-8859-1" },
161  {"sv_SE" ,"svenska.hash" ,"iso-8859-1" },
162  {"uk" ,"ukrainian.hash" ,"koi8-u" },
163  {"uk_UA" ,"ukrainian.hash" ,"koi8-u" },
164  {"yi" ,"yiddish-yivo.hash" ,"utf-8" }
165 };
166 
167 static const size_t size_ispell_map = ( sizeof(ispell_map) / sizeof((ispell_map)[0]) );
168 static TQMap<TQString, TQString> ispell_dict_map;
169 
170 
171 void
172 ISpellChecker::try_autodetect_charset(const char * const inEncoding)
173 {
174  if (inEncoding && strlen(inEncoding))
175  {
176  m_translate_in = TQTextCodec::codecForName(inEncoding);
177  }
178 }
179 
180 /***************************************************************************/
181 /***************************************************************************/
182 
183 ISpellChecker::ISpellChecker()
184  : deftflag(-1),
185  prefstringchar(-1),
186  m_bSuccessfulInit(false),
187  m_BC(NULL),
188  m_cd(NULL),
189  m_cl(NULL),
190  m_cm(NULL),
191  m_ho(NULL),
192  m_nd(NULL),
193  m_so(NULL),
194  m_se(NULL),
195  m_ti(NULL),
196  m_te(NULL),
197  m_hashstrings(NULL),
198  m_hashtbl(NULL),
199  m_pflaglist(NULL),
200  m_sflaglist(NULL),
201  m_chartypes(NULL),
202  m_infile(NULL),
203  m_outfile(NULL),
204  m_askfilename(NULL),
205  m_Trynum(0),
206  m_translate_in(0)
207 {
208  memset(m_sflagindex,0,sizeof(m_sflagindex));
209  memset(m_pflagindex,0,sizeof(m_pflagindex));
210 }
211 
212 #ifndef FREEP
213 #define FREEP(p) do { if (p) free(p); } while (0)
214 #endif
215 
216 ISpellChecker::~ISpellChecker()
217 {
218  if (m_bSuccessfulInit) {
219  // only cleanup our mess if we were successfully initialized
220 
221  clearindex (m_pflagindex);
222  clearindex (m_sflagindex);
223  }
224 
225  FREEP(m_hashtbl);
226  FREEP(m_hashstrings);
227  FREEP(m_sflaglist);
228  FREEP(m_chartypes);
229 
230  delete m_translate_in;
231  m_translate_in = 0;
232 }
233 
234 bool
235 ISpellChecker::checkWord( const TQString& utf8Word )
236 {
237  ichar_t iWord[INPUTWORDLEN + MAXAFFIXLEN];
238  if (!m_bSuccessfulInit)
239  return false;
240 
241  if (!utf8Word || utf8Word.length() >= (INPUTWORDLEN + MAXAFFIXLEN) || utf8Word.isEmpty())
242  return false;
243 
244  bool retVal = false;
245  TQCString out;
246  if (!m_translate_in)
247  return false;
248  else {
249  /* convert to 8bit string and null terminate */
250  int len_out = utf8Word.length();
251 
252  out = m_translate_in->fromUnicode( utf8Word, len_out );
253  }
254 
255  if (!strtoichar(iWord, out.data(), INPUTWORDLEN + MAXAFFIXLEN, 0))
256  {
257  if (good(iWord, 0, 0, 1, 0) == 1 ||
258  compoundgood(iWord, 1) == 1)
259  {
260  retVal = true;
261  }
262  }
263 
264  return retVal;
265 }
266 
267 TQStringList
268 ISpellChecker::suggestWord(const TQString& utf8Word)
269 {
270  ichar_t iWord[INPUTWORDLEN + MAXAFFIXLEN];
271  int c;
272 
273  if (!m_bSuccessfulInit)
274  return TQStringList();
275 
276  if (utf8Word.isEmpty() || utf8Word.length() >= (INPUTWORDLEN + MAXAFFIXLEN) ||
277  utf8Word.length() == 0)
278  return TQStringList();
279 
280  TQCString out;
281  if (!m_translate_in)
282  return TQStringList();
283  else
284  {
285  /* convert to 8bit string and null terminate */
286 
287  int len_out = utf8Word.length();
288  out = m_translate_in->fromUnicode( utf8Word, len_out );
289  }
290 
291  if (!strtoichar(iWord, out.data(), INPUTWORDLEN + MAXAFFIXLEN, 0))
292  makepossibilities(iWord);
293  else
294  return TQStringList();
295 
296  TQStringList sugg_arr;
297  for (c = 0; c < m_pcount; c++)
298  {
299  TQString utf8Word;
300 
301  if (!m_translate_in)
302  {
303  /* copy to 8bit string and null terminate */
304  utf8Word = TQString::fromUtf8( m_possibilities[c] );
305  }
306  else
307  {
308  /* convert to 32bit string and null terminate */
309  utf8Word = m_translate_in->toUnicode( m_possibilities[c] );
310  }
311 
312  sugg_arr.append( utf8Word );
313  }
314 
315  return sugg_arr;
316 }
317 
318 static void
319 s_buildHashNames (std::vector<std::string> & names, const char * dict)
320 {
321  const char * tmp = 0;
322  int i = 0;
323 
324  names.clear ();
325 
326  while ( (tmp = ispell_dirs[i++]) ) {
327  TQCString maybeFile = TQCString( tmp ) + '/';
328  maybeFile += dict;
329  names.push_back( maybeFile.data() );
330  }
331 }
332 
333 static void
334 s_allDics()
335 {
336  const char * tmp = 0;
337  int i = 0;
338 
339  while ( (tmp = ispell_dirs[i++]) ) {
340  TQDir dir( tmp );
341  TQStringList lst = dir.entryList( "*.hash" );
342  for ( TQStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) {
343  TQFileInfo info( *it );
344  for (size_t i = 0; i < size_ispell_map; i++)
345  {
346  const IspellMap * mapping = (const IspellMap *)(&(ispell_map[i]));
347  if (!strcmp (info.fileName().latin1(), mapping->dict))
348  {
349  ispell_dict_map.insert( mapping->lang, *it );
350  }
351  }
352  }
353  }
354 }
355 
356 TQValueList<TQString>
357 ISpellChecker::allDics()
358 {
359  if ( ispell_dict_map.empty() )
360  s_allDics();
361 
362  return ispell_dict_map.keys();
363 }
364 
365 TQString
366 ISpellChecker::loadDictionary (const char * szdict)
367 {
368  std::vector<std::string> dict_names;
369 
370  s_buildHashNames (dict_names, szdict);
371 
372  for (size_t i = 0; i < dict_names.size(); i++)
373  {
374  if (linit(const_cast<char*>(dict_names[i].c_str())) >= 0)
375  return dict_names[i].c_str();
376  }
377 
378  return TQString::null;
379 }
380 
387 bool
388 ISpellChecker::loadDictionaryForLanguage ( const char * szLang )
389 {
390  TQString hashname;
391 
392  const char * encoding = NULL;
393  const char * szFile = NULL;
394 
395  for (size_t i = 0; i < size_ispell_map; i++)
396  {
397  const IspellMap * mapping = (const IspellMap *)(&(ispell_map[i]));
398  if (!strcmp (szLang, mapping->lang))
399  {
400  szFile = mapping->dict;
401  encoding = mapping->enc;
402  break;
403  }
404  }
405 
406  if (!szFile || !strlen(szFile))
407  return false;
408 
409  alloc_ispell_struct();
410 
411  hashname = loadDictionary(szFile);
412  if (hashname.isEmpty())
413  return false;
414 
415  // one of the two above calls succeeded
416  setDictionaryEncoding (hashname, encoding);
417 
418  return true;
419 }
420 
421 void
422 ISpellChecker::setDictionaryEncoding( const TQString& hashname, const char * encoding )
423 {
424  /* Get Hash encoding from XML file. This should always work! */
425  try_autodetect_charset(encoding);
426 
427  if (m_translate_in)
428  {
429  /* We still have to setup prefstringchar*/
430  prefstringchar = findfiletype("utf8", 1, deftflag < 0 ? &deftflag
431  : static_cast<int *>(NULL));
432 
433  if (prefstringchar < 0)
434  {
435  std::string teststring;
436  for(int n1 = 1; n1 <= 15; n1++)
437  {
438  teststring = "latin" + n1;
439  prefstringchar = findfiletype(teststring.c_str(), 1,
440  deftflag < 0 ? &deftflag : static_cast<int *>(NULL));
441  if (prefstringchar >= 0)
442  break;
443  }
444  }
445 
446  return; /* success */
447  }
448 
449  /* Test for UTF-8 first */
450  prefstringchar = findfiletype("utf8", 1, deftflag < 0 ? &deftflag : static_cast<int *>(NULL));
451  if (prefstringchar >= 0)
452  {
453  m_translate_in = TQTextCodec::codecForName("utf8");
454  }
455 
456  if (m_translate_in)
457  return; /* success */
458 
459  /* Test for "latinN" */
460  if (!m_translate_in)
461  {
462  /* Look for "altstringtype" names from latin1 to latin15 */
463  for(int n1 = 1; n1 <= 15; n1++)
464  {
465  TQString teststring = TQString("latin%1").arg(n1);
466  prefstringchar = findfiletype(teststring.latin1(), 1,
467  deftflag < 0 ? &deftflag : static_cast<int *>(NULL));
468  if (prefstringchar >= 0)
469  {
470  //FIXME: latin1 might be wrong
471  m_translate_in = TQTextCodec::codecForName( teststring.latin1() );
472  break;
473  }
474  }
475  }
476 
477  /* If nothing found, use latin1 */
478  if (!m_translate_in)
479  {
480  m_translate_in = TQTextCodec::codecForName("latin1");
481  }
482 }
483 
484 bool
485 ISpellChecker::requestDictionary(const char *szLang)
486 {
487  if (!loadDictionaryForLanguage (szLang))
488  {
489  // handle a shortened version of the language tag: en_US => en
490  std::string shortened_dict (szLang);
491  size_t uscore_pos;
492 
493  if ((uscore_pos = shortened_dict.rfind ('_')) != ((size_t)-1)) {
494  shortened_dict = shortened_dict.substr(0, uscore_pos);
495  if (!loadDictionaryForLanguage (shortened_dict.c_str()))
496  return false;
497  } else
498  return false;
499  }
500 
501  m_bSuccessfulInit = true;
502 
503  if (prefstringchar < 0)
504  m_defdupchar = 0;
505  else
506  m_defdupchar = prefstringchar;
507 
508  return true;
509 }

tdespell2

Skip menu "tdespell2"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members

tdespell2

Skip menu "tdespell2"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdespell2 by doxygen 1.8.13
This website is maintained by Timothy Pearson.