Back to index

texmacs  1.0.7.15
edit_spell.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : edit_spell.cpp
00004 * DESCRIPTION: spell checker based on ispell
00005 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "analyze.hpp"
00013 #include "Replace/edit_replace.hpp"
00014 #include "Interface/edit_interface.hpp"
00015 
00016 #ifdef MACOSX_EXTENSIONS
00017 #include "MacOS/mac_spellservice.h"
00018 #define ispell_start mac_spell_start
00019 #define ispell_check mac_spell_check
00020 #define ispell_accept mac_spell_accept
00021 #define ispell_insert mac_spell_insert
00022 #define ispell_done mac_spell_done
00023 #else
00024 #include "Ispell/ispell.hpp"
00025 #endif
00026 
00027 
00028 /******************************************************************************
00029 * Start and end spell checking
00030 ******************************************************************************/
00031 
00032 void
00033 edit_replace_rep::spell_start () {
00034   /********** get paths ***********/
00035   search_at   = start (et, rp);
00036   spell_end_p = end (et, rp);
00037   path spell_p= copy (tp);
00038   if (selection_active_normal ()) {
00039     get_selection (search_at, spell_end_p);
00040     spell_p= copy (search_at);
00041   }
00042 
00043   /********** initialize spell checker ***********/
00044   search_mode = copy (as_string (get_env_value (MODE, spell_p)));
00045   search_lan  =
00046     copy (as_string (get_env_value (MODE_LANGUAGE (search_mode), spell_p)));
00047 
00048   string message= ispell_start (search_lan);
00049   if (starts (message, "Error: ")) {
00050     spell_end ();
00051     set_message (message, "correct text");
00052     return;
00053   }
00054 
00055   /********** start spell checking ***********/
00056   set_input_mode (INPUT_SPELL);
00057   forward      = true;
00058   nr_replaced  = 0;
00059   spell_dicmod = false;
00060 
00061   spell_next ();
00062   if (search_at == rp)
00063     set_message ("no spelling errors found in text", "correct text");
00064 }
00065 
00066 void
00067 edit_replace_rep::spell_end () {
00068   if (spell_dicmod) {
00069     ispell_done (search_lan);
00070     set_message ("personal dictionary has been modified", "correct text");
00071   }
00072   else if (nr_replaced == 1)
00073     set_message ("one spelling error has been corrected", "correct text");
00074   else if (nr_replaced > 1)
00075     set_message (concat (as_string (nr_replaced),
00076                       " spelling errors have been corrected"),
00077                "correct text");
00078   else set_message ("spell checking complete", "correct text");
00079   beep ();
00080   set_input_normal ();
00081 }
00082 
00083 /******************************************************************************
00084 * Find next word to be spelled
00085 ******************************************************************************/
00086 
00087 path
00088 edit_replace_rep::test_spellable (path p) {
00089   tree st= subtree (et, path_up (p));
00090   if (is_compound (st)) return p;
00091   string s= st->label;
00092   int    b= last_item (p);
00093   int    e= b;
00094   if ((e > 0) && ((is_iso_alpha (s[e-1])) || (is_digit (s[e-1])))) return p;
00095   while ((e < N(s)) && (is_iso_alpha (s[e]))) e++;
00096   if ((e < N(s)) && (is_digit (s[e]))) return p;
00097   if (e == b) return p;
00098   spell_s= s (b, e);
00099   return path_add (p, e - b);
00100 }
00101 
00102 static string
00103 message_ispell (tree t) {
00104   int i;
00105   string s= "a: accept, r: replace, i: insert";
00106   for (i=1; i<N(t); i++) {
00107     s << ", " << as_string (i) << ": " << t[i]->label;
00108     if (i==9) return s << ", ...";
00109   }
00110   return s;
00111 }
00112 
00113 void
00114 edit_replace_rep::spell_next () {
00115   while (true) {
00116     if (path_inf (spell_end_p, search_at))
00117       search_at= rp;
00118     if (search_at == rp) {
00119       spell_end ();
00120       return;
00121     }
00122     search_end= test_spellable (search_at);
00123     if (search_end != search_at) {
00124       spell_t= ispell_check (search_lan, spell_s);
00125       if (is_atomic (spell_t) && starts (spell_t->label, "Error: ")) {
00126        spell_end ();
00127        set_message (spell_t->label, "spelling text");
00128        return;
00129       }
00130       if (spell_t != "ok") {
00131        string mode= as_string (get_env_value (MODE, search_at));
00132        string lan =
00133          as_string (get_env_value (MODE_LANGUAGE (mode), search_at));
00134        if ((search_mode == mode) && (search_lan == lan)) {
00135          set_selection (search_at, search_end);
00136          notify_change (THE_SELECTION);
00137          go_to (copy (search_end));
00138          set_message (message_ispell (spell_t), "spelling error");
00139          return;
00140        }
00141       }
00142     }
00143     step_horizontal (forward);
00144   }
00145 }
00146 
00147 /******************************************************************************
00148 * Spell checking commands
00149 ******************************************************************************/
00150 
00151 void
00152 edit_replace_rep::spell_replace (string by) {
00153   go_to (copy (search_at));
00154   cut (search_at, search_end);
00155   insert_tree (copy (by));
00156   nr_replaced++;
00157   spell_next ();
00158 }
00159 
00160 bool
00161 edit_replace_rep::spell_keypress (string s) {
00162   set_message ("", "");
00163   if (s == "space") s= " ";
00164   if ((s == "C-c") || (s == "C-g") || (s == "escape"))
00165     spell_end ();
00166   else if ((s == "a") || (s == "A")) {
00167     ispell_accept (search_lan, spell_s);
00168     step_horizontal (forward);
00169     spell_next ();
00170   }
00171   else if ((s == "r") || (s == "R"))
00172     (void) eval ("(interactive spell-replace \"Replace by\")");
00173   else if ((s == "i") || (s == "I")) {
00174     ispell_insert (search_lan, spell_s);
00175     spell_dicmod= true;
00176     step_horizontal (forward);
00177     spell_next ();
00178   }
00179   else if ((N(s)==1) && (is_digit (s[0])) && (s != "0")) {
00180     int i= as_int (s);
00181     int r= as_int (spell_t[0]);
00182     if (i <= r) {
00183       go_to (copy (search_end));
00184       cut (search_at, search_end);
00185       insert_tree (copy (spell_t[i]));
00186       search_at= copy (tp);
00187       nr_replaced++;
00188       spell_next ();
00189     }
00190     else if (i < N (spell_t)) {
00191       ispell_accept (search_lan, spell_s);
00192       step_horizontal (forward);
00193       spell_next ();
00194     }
00195     else set_message (message_ispell (spell_t), "spelling error");
00196   }
00197   else set_message (message_ispell (spell_t), "spelling error");
00198   return true;
00199 }