Mercurial > pidgin.yaz
comparison pidgin/plugins/spellchk.c @ 15374:5fe8042783c1
Rename gtk/ and libgaim/ to pidgin/ and libpurple/
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Sat, 20 Jan 2007 02:32:10 +0000 |
parents | |
children | d75099d2567e |
comparison
equal
deleted
inserted
replaced
15373:f79e0f4df793 | 15374:5fe8042783c1 |
---|---|
1 /* | |
2 * Gaim - Replace certain misspelled words with their correct form. | |
3 * | |
4 * Signification changes were made by Benjamin Kahn ("xkahn") and | |
5 * Richard Laager ("rlaager") in April 2005--you may want to contact | |
6 * them if you have questions. | |
7 * | |
8 * Gaim is the legal property of its developers, whose names are too numerous | |
9 * to list here. Please refer to the COPYRIGHT file distributed with this | |
10 * source distribution. | |
11 * | |
12 * This program is free software; you can redistribute it and/or modify | |
13 * it under the terms of the GNU General Public License as published by | |
14 * the Free Software Foundation; either version 2 of the License, or | |
15 * (at your option) any later version. | |
16 * | |
17 * This program is distributed in the hope that it will be useful, | |
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 * GNU General Public License for more details. | |
21 * | |
22 * You should have received a copy of the GNU General Public License | |
23 * along with this program; if not, write to the Free Software | |
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
25 * | |
26 */ | |
27 | |
28 /* | |
29 * A lot of this code (especially the config code) was taken directly | |
30 * or nearly directly from xchat, version 1.4.2 by Peter Zelezny and others. | |
31 */ | |
32 | |
33 #include "internal.h" | |
34 #include "gtkgaim.h" | |
35 | |
36 #include "debug.h" | |
37 #include "notify.h" | |
38 #include "signals.h" | |
39 #include "util.h" | |
40 #include "version.h" | |
41 | |
42 #include "gtkplugin.h" | |
43 #include "gtkprefs.h" | |
44 #include "gtkutils.h" | |
45 | |
46 #include <stdio.h> | |
47 #include <string.h> | |
48 #ifndef _WIN32 | |
49 #include <strings.h> | |
50 #endif | |
51 #include <sys/types.h> | |
52 #include <sys/stat.h> | |
53 | |
54 #define SPELLCHECK_PLUGIN_ID "gtk-spellcheck" | |
55 #define SPELLCHK_OBJECT_KEY "spellchk" | |
56 | |
57 enum { | |
58 BAD_COLUMN, | |
59 GOOD_COLUMN, | |
60 WORD_ONLY_COLUMN, | |
61 CASE_SENSITIVE_COLUMN, | |
62 N_COLUMNS | |
63 }; | |
64 | |
65 struct _spellchk { | |
66 GtkTextView *view; | |
67 GtkTextMark *mark_insert_start; | |
68 GtkTextMark *mark_insert_end; | |
69 | |
70 const gchar *word; | |
71 gboolean inserting; | |
72 gboolean ignore_correction; | |
73 gboolean ignore_correction_on_send; | |
74 gint pos; | |
75 }; | |
76 | |
77 typedef struct _spellchk spellchk; | |
78 | |
79 static GtkListStore *model; | |
80 | |
81 static gboolean | |
82 is_word_uppercase(const gchar *word) | |
83 { | |
84 for (; word[0] != '\0'; word = g_utf8_find_next_char (word, NULL)) { | |
85 gunichar c = g_utf8_get_char(word); | |
86 | |
87 if (!(g_unichar_isupper(c) || | |
88 g_unichar_ispunct(c) || | |
89 g_unichar_isspace(c))) | |
90 return FALSE; | |
91 } | |
92 | |
93 return TRUE; | |
94 } | |
95 | |
96 static gboolean | |
97 is_word_lowercase(const gchar *word) | |
98 { | |
99 for (; word[0] != '\0'; word = g_utf8_find_next_char(word, NULL)) { | |
100 gunichar c = g_utf8_get_char(word); | |
101 | |
102 if (!(g_unichar_islower(c) || | |
103 g_unichar_ispunct(c) || | |
104 g_unichar_isspace(c))) | |
105 return FALSE; | |
106 } | |
107 | |
108 return TRUE; | |
109 } | |
110 | |
111 static gboolean | |
112 is_word_proper(const gchar *word) | |
113 { | |
114 if (word[0] == '\0') | |
115 return FALSE; | |
116 | |
117 if (!g_unichar_isupper(g_utf8_get_char_validated(word, -1))) | |
118 return FALSE; | |
119 | |
120 return is_word_lowercase(g_utf8_offset_to_pointer(word, 1)); | |
121 } | |
122 | |
123 static gchar * | |
124 make_word_proper(const gchar *word) | |
125 { | |
126 char buf[7]; | |
127 gchar *lower = g_utf8_strdown(word, -1); | |
128 gint bytes; | |
129 gchar *ret; | |
130 | |
131 bytes = g_unichar_to_utf8(g_unichar_toupper(g_utf8_get_char(word)), buf); | |
132 buf[MIN(bytes, sizeof(buf) - 1)] = '\0'; | |
133 | |
134 ret = g_strconcat(buf, g_utf8_offset_to_pointer(lower, 1), NULL); | |
135 g_free(lower); | |
136 | |
137 return ret; | |
138 } | |
139 | |
140 static gboolean | |
141 substitute_simple_buffer(GtkTextBuffer *buffer) | |
142 { | |
143 GtkTextIter start; | |
144 GtkTextIter end; | |
145 GtkTreeIter treeiter; | |
146 gchar *text = NULL; | |
147 | |
148 gtk_text_buffer_get_iter_at_offset(buffer, &start, 0); | |
149 gtk_text_buffer_get_iter_at_offset(buffer, &end, 0); | |
150 gtk_text_iter_forward_to_end(&end); | |
151 | |
152 text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE); | |
153 | |
154 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &treeiter) && text) { | |
155 do { | |
156 GValue val1; | |
157 const gchar *bad; | |
158 gchar *cursor; | |
159 glong char_pos; | |
160 | |
161 val1.g_type = 0; | |
162 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &treeiter, WORD_ONLY_COLUMN, &val1); | |
163 if (g_value_get_boolean(&val1)) | |
164 { | |
165 g_value_unset(&val1); | |
166 continue; | |
167 } | |
168 g_value_unset(&val1); | |
169 | |
170 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &treeiter, BAD_COLUMN, &val1); | |
171 bad = g_value_get_string(&val1); | |
172 | |
173 /* using g_utf8_* to get /character/ offsets instead of byte offsets for buffer */ | |
174 if ((cursor = g_strrstr(text, bad))) | |
175 { | |
176 GValue val2; | |
177 const gchar *good; | |
178 | |
179 val2.g_type = 0; | |
180 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &treeiter, GOOD_COLUMN, &val2); | |
181 good = g_value_get_string(&val2); | |
182 | |
183 char_pos = g_utf8_pointer_to_offset(text, cursor); | |
184 gtk_text_buffer_get_iter_at_offset(buffer, &start, char_pos); | |
185 gtk_text_buffer_get_iter_at_offset(buffer, &end, char_pos + g_utf8_strlen(bad, -1)); | |
186 gtk_text_buffer_delete(buffer, &start, &end); | |
187 | |
188 gtk_text_buffer_get_iter_at_offset(buffer, &start, char_pos); | |
189 gtk_text_buffer_insert(buffer, &start, good, -1); | |
190 | |
191 g_value_unset(&val2); | |
192 g_free(text); | |
193 | |
194 g_value_unset(&val1); | |
195 return TRUE; | |
196 } | |
197 | |
198 g_value_unset(&val1); | |
199 } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &treeiter)); | |
200 } | |
201 | |
202 g_free(text); | |
203 return FALSE; | |
204 } | |
205 | |
206 static gchar * | |
207 substitute_word(gchar *word) | |
208 { | |
209 GtkTreeIter iter; | |
210 gchar *outword; | |
211 gchar *lowerword; | |
212 gchar *foldedword; | |
213 | |
214 if (word == NULL) | |
215 return NULL; | |
216 | |
217 lowerword = g_utf8_strdown(word, -1); | |
218 foldedword = g_utf8_casefold(word, -1); | |
219 | |
220 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) { | |
221 do { | |
222 GValue val1; | |
223 gboolean case_sensitive; | |
224 const char *bad; | |
225 gchar *tmpbad = NULL; | |
226 | |
227 val1.g_type = 0; | |
228 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, WORD_ONLY_COLUMN, &val1); | |
229 if (!g_value_get_boolean(&val1)) { | |
230 g_value_unset(&val1); | |
231 continue; | |
232 } | |
233 g_value_unset(&val1); | |
234 | |
235 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, CASE_SENSITIVE_COLUMN, &val1); | |
236 case_sensitive = g_value_get_boolean(&val1); | |
237 g_value_unset(&val1); | |
238 | |
239 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, BAD_COLUMN, &val1); | |
240 bad = g_value_get_string(&val1); | |
241 | |
242 if ((case_sensitive && !strcmp(bad, word)) || | |
243 (!case_sensitive && (!strcmp(bad, lowerword) || | |
244 (!is_word_lowercase(bad) && | |
245 !strcmp((tmpbad = g_utf8_casefold(bad, -1)), foldedword))))) | |
246 { | |
247 GValue val2; | |
248 const char *good; | |
249 | |
250 g_free(tmpbad); | |
251 | |
252 val2.g_type = 0; | |
253 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, GOOD_COLUMN, &val2); | |
254 good = g_value_get_string(&val2); | |
255 | |
256 if (!case_sensitive && is_word_lowercase(bad) && is_word_lowercase(good)) | |
257 { | |
258 if (is_word_uppercase(word)) | |
259 outword = g_utf8_strup(good, -1); | |
260 else if (is_word_proper(word)) | |
261 outword = make_word_proper(good); | |
262 else | |
263 outword = g_strdup(good); | |
264 } | |
265 else | |
266 outword = g_strdup(good); | |
267 | |
268 g_value_unset(&val1); | |
269 g_value_unset(&val2); | |
270 | |
271 g_free(foldedword); | |
272 return outword; | |
273 } | |
274 | |
275 g_value_unset(&val1); | |
276 g_free(tmpbad); | |
277 | |
278 } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter)); | |
279 } | |
280 g_free(foldedword); | |
281 | |
282 return NULL; | |
283 } | |
284 | |
285 static void | |
286 spellchk_free(spellchk *spell) | |
287 { | |
288 GtkTextBuffer *buffer; | |
289 | |
290 g_return_if_fail(spell != NULL); | |
291 | |
292 buffer = gtk_text_view_get_buffer(spell->view); | |
293 | |
294 g_signal_handlers_disconnect_matched(buffer, | |
295 G_SIGNAL_MATCH_DATA, | |
296 0, 0, NULL, NULL, | |
297 spell); | |
298 g_free(spell); | |
299 } | |
300 | |
301 /* Pango doesn't know about the "'" character. Let's fix that. */ | |
302 static gboolean | |
303 spellchk_inside_word(GtkTextIter *iter) | |
304 { | |
305 gunichar ucs4_char = gtk_text_iter_get_char(iter); | |
306 gchar *utf8_str; | |
307 gchar c = 0; | |
308 | |
309 utf8_str = g_ucs4_to_utf8(&ucs4_char, 1, NULL, NULL, NULL); | |
310 if (utf8_str != NULL) | |
311 { | |
312 c = utf8_str[0]; | |
313 g_free(utf8_str); | |
314 } | |
315 | |
316 /* Hack because otherwise typing things like U.S. gets difficult | |
317 * if you have 'u' -> 'you' set as a correction... | |
318 * | |
319 * Part 1 of 2: This marks . as being an inside-word character. */ | |
320 if (c == '.') | |
321 return TRUE; | |
322 | |
323 /* Avoid problems with \r, for example (SF #1289031). */ | |
324 if (c == '\\') | |
325 return TRUE; | |
326 | |
327 if (gtk_text_iter_inside_word (iter) == TRUE) | |
328 return TRUE; | |
329 | |
330 if (c == '\'') { | |
331 gboolean result = gtk_text_iter_backward_char(iter); | |
332 gboolean output = gtk_text_iter_inside_word(iter); | |
333 | |
334 if (result) | |
335 { | |
336 /* | |
337 * Hack so that "u'll" will correct correctly. | |
338 */ | |
339 ucs4_char = gtk_text_iter_get_char(iter); | |
340 utf8_str = g_ucs4_to_utf8(&ucs4_char, 1, NULL, NULL, NULL); | |
341 if (utf8_str != NULL) | |
342 { | |
343 c = utf8_str[0]; | |
344 g_free(utf8_str); | |
345 | |
346 if (c == 'u' || c == 'U') | |
347 { | |
348 gtk_text_iter_forward_char(iter); | |
349 return FALSE; | |
350 } | |
351 } | |
352 | |
353 gtk_text_iter_forward_char(iter); | |
354 } | |
355 | |
356 return output; | |
357 } | |
358 else if (c == '&') | |
359 return TRUE; | |
360 | |
361 return FALSE; | |
362 } | |
363 | |
364 static gboolean | |
365 spellchk_backward_word_start(GtkTextIter *iter) | |
366 { | |
367 int output; | |
368 int result; | |
369 | |
370 output = gtk_text_iter_backward_word_start(iter); | |
371 | |
372 /* It didn't work... */ | |
373 if (!output) | |
374 return FALSE; | |
375 | |
376 while (spellchk_inside_word(iter)) { | |
377 result = gtk_text_iter_backward_char(iter); | |
378 | |
379 /* We can't go backwards anymore? We're at the beginning of the word. */ | |
380 if (!result) | |
381 return TRUE; | |
382 | |
383 if (!spellchk_inside_word(iter)) { | |
384 gtk_text_iter_forward_char(iter); | |
385 return TRUE; | |
386 } | |
387 | |
388 output = gtk_text_iter_backward_word_start(iter); | |
389 if (!output) | |
390 return FALSE; | |
391 } | |
392 | |
393 return TRUE; | |
394 } | |
395 | |
396 static gboolean | |
397 check_range(spellchk *spell, GtkTextBuffer *buffer, | |
398 GtkTextIter start, GtkTextIter end, gboolean sending) | |
399 { | |
400 gboolean replaced; | |
401 gboolean result; | |
402 gchar *tmp; | |
403 int period_count = 0; | |
404 gchar *word; | |
405 GtkTextMark *mark; | |
406 GtkTextIter pos; | |
407 | |
408 if ((replaced = substitute_simple_buffer(buffer))) | |
409 { | |
410 mark = gtk_text_buffer_get_insert(buffer); | |
411 gtk_text_buffer_get_iter_at_mark(buffer, &pos, mark); | |
412 spell->pos = gtk_text_iter_get_offset(&pos); | |
413 | |
414 gtk_text_buffer_get_iter_at_mark(buffer, &start, mark); | |
415 gtk_text_buffer_get_iter_at_mark(buffer, &end, mark); | |
416 } | |
417 | |
418 if (!sending) | |
419 { | |
420 /* We need to go backwords to find out if we are inside a word or not. */ | |
421 gtk_text_iter_backward_char(&end); | |
422 | |
423 if (spellchk_inside_word(&end)) | |
424 { | |
425 gtk_text_iter_forward_char(&end); | |
426 return replaced; /* We only pay attention to whole words. */ | |
427 } | |
428 } | |
429 | |
430 /* We could be in the middle of a whitespace block. Check for that. */ | |
431 result = gtk_text_iter_backward_char(&end); | |
432 | |
433 if (!spellchk_inside_word(&end)) | |
434 { | |
435 if (result) | |
436 gtk_text_iter_forward_char(&end); | |
437 return replaced; | |
438 } | |
439 | |
440 if (result) | |
441 gtk_text_iter_forward_char(&end); | |
442 | |
443 /* Move backwards to the beginning of the word. */ | |
444 spellchk_backward_word_start(&start); | |
445 | |
446 spell->word = gtk_text_iter_get_text(&start, &end); | |
447 | |
448 /* Hack because otherwise typing things like U.S. gets difficult | |
449 * if you have 'u' -> 'you' set as a correction... | |
450 * | |
451 * Part 2 of 2: This chops periods off the end of the word so | |
452 * the right substitution entry is found. */ | |
453 tmp = g_strdup(spell->word); | |
454 if (tmp != NULL && *tmp != '\0') { | |
455 gchar *c; | |
456 for (c = tmp + strlen(tmp) - 1 ; c != tmp ; c--) { | |
457 if (*c == '.') { | |
458 *c = '\0'; | |
459 period_count++; | |
460 } else | |
461 break; | |
462 } | |
463 } | |
464 | |
465 if ((word = substitute_word(tmp))) { | |
466 GtkTextMark *mark; | |
467 GtkTextIter pos; | |
468 gchar *tmp2; | |
469 int i; | |
470 | |
471 for (i = 1 ; i <= period_count ; i++) { | |
472 tmp2 = g_strconcat(word, ".", NULL); | |
473 g_free(word); | |
474 word = tmp2; | |
475 } | |
476 | |
477 gtk_text_buffer_delete(buffer, &start, &end); | |
478 gtk_text_buffer_insert(buffer, &start, word, -1); | |
479 | |
480 mark = gtk_text_buffer_get_insert(buffer); | |
481 gtk_text_buffer_get_iter_at_mark(buffer, &pos, mark); | |
482 spell->pos = gtk_text_iter_get_offset(&pos); | |
483 | |
484 g_free(word); | |
485 g_free(tmp); | |
486 return TRUE; | |
487 } | |
488 g_free(tmp); | |
489 | |
490 spell->word = NULL; | |
491 | |
492 return replaced; | |
493 } | |
494 | |
495 /* insertion works like this: | |
496 * - before the text is inserted, we mark the position in the buffer. | |
497 * - after the text is inserted, we see where our mark is and use that and | |
498 * the current position to check the entire range of inserted text. | |
499 * | |
500 * this may be overkill for the common case (inserting one character). */ | |
501 static void | |
502 insert_text_before(GtkTextBuffer *buffer, GtkTextIter *iter, | |
503 gchar *text, gint len, spellchk *spell) | |
504 { | |
505 if (spell->inserting == TRUE) | |
506 return; | |
507 | |
508 spell->inserting = TRUE; | |
509 | |
510 spell->word = NULL; | |
511 | |
512 gtk_text_buffer_move_mark(buffer, spell->mark_insert_start, iter); | |
513 } | |
514 | |
515 static void | |
516 insert_text_after(GtkTextBuffer *buffer, GtkTextIter *iter, | |
517 gchar *text, gint len, spellchk *spell) | |
518 { | |
519 GtkTextIter start, end; | |
520 GtkTextMark *mark; | |
521 | |
522 spell->ignore_correction_on_send = FALSE; | |
523 | |
524 if (spell->ignore_correction) { | |
525 spell->ignore_correction = FALSE; | |
526 return; | |
527 } | |
528 | |
529 /* we need to check a range of text. */ | |
530 gtk_text_buffer_get_iter_at_mark(buffer, &start, spell->mark_insert_start); | |
531 | |
532 if (len == 1) | |
533 check_range(spell, buffer, start, *iter, FALSE); | |
534 | |
535 /* if check_range modified the buffer, iter has been invalidated */ | |
536 mark = gtk_text_buffer_get_insert(buffer); | |
537 gtk_text_buffer_get_iter_at_mark(buffer, &end, mark); | |
538 gtk_text_buffer_move_mark(buffer, spell->mark_insert_end, &end); | |
539 | |
540 spell->inserting = FALSE; | |
541 } | |
542 | |
543 static void | |
544 delete_range_after(GtkTextBuffer *buffer, | |
545 GtkTextIter *start, GtkTextIter *end, spellchk *spell) | |
546 { | |
547 GtkTextIter start2, end2; | |
548 GtkTextMark *mark; | |
549 GtkTextIter pos; | |
550 gint place; | |
551 | |
552 spell->ignore_correction_on_send = FALSE; | |
553 | |
554 if (!spell->word) | |
555 return; | |
556 | |
557 if (spell->inserting == TRUE) | |
558 return; | |
559 | |
560 spell->inserting = TRUE; | |
561 | |
562 mark = gtk_text_buffer_get_insert(buffer); | |
563 gtk_text_buffer_get_iter_at_mark(buffer, &pos, mark); | |
564 place = gtk_text_iter_get_offset(&pos); | |
565 | |
566 if ((place + 1) != spell->pos) { | |
567 spell->word = NULL; | |
568 return; | |
569 } | |
570 | |
571 gtk_text_buffer_get_iter_at_mark(buffer, &start2, spell->mark_insert_start); | |
572 gtk_text_buffer_get_iter_at_mark(buffer, &end2, spell->mark_insert_end); | |
573 | |
574 gtk_text_buffer_delete(buffer, &start2, &end2); | |
575 gtk_text_buffer_insert(buffer, &start2, spell->word, -1); | |
576 spell->ignore_correction = TRUE; | |
577 spell->ignore_correction_on_send = TRUE; | |
578 | |
579 spell->inserting = FALSE; | |
580 spell->word = NULL; | |
581 } | |
582 | |
583 static void | |
584 message_send_cb(GtkWidget *widget, spellchk *spell) | |
585 { | |
586 GtkTextBuffer *buffer; | |
587 GtkTextIter start, end; | |
588 GtkTextMark *mark; | |
589 gboolean replaced; | |
590 | |
591 if (spell->ignore_correction_on_send) | |
592 { | |
593 spell->ignore_correction_on_send = FALSE; | |
594 return; | |
595 } | |
596 | |
597 #if 0 | |
598 if (!gaim_prefs_get_bool("/plugins/gtk/spellchk/last_word_replace")) | |
599 return; | |
600 #endif | |
601 | |
602 buffer = gtk_text_view_get_buffer(spell->view); | |
603 | |
604 gtk_text_buffer_get_end_iter(buffer, &start); | |
605 gtk_text_buffer_get_end_iter(buffer, &end); | |
606 spell->inserting = TRUE; | |
607 replaced = check_range(spell, buffer, start, end, TRUE); | |
608 spell->inserting = FALSE; | |
609 | |
610 /* if check_range modified the buffer, iter has been invalidated */ | |
611 mark = gtk_text_buffer_get_insert(buffer); | |
612 gtk_text_buffer_get_iter_at_mark(buffer, &end, mark); | |
613 gtk_text_buffer_move_mark(buffer, spell->mark_insert_end, &end); | |
614 | |
615 if (replaced) | |
616 { | |
617 g_signal_stop_emission_by_name(widget, "message_send"); | |
618 spell->ignore_correction_on_send = TRUE; | |
619 } | |
620 } | |
621 | |
622 static void | |
623 spellchk_new_attach(GaimConversation *conv) | |
624 { | |
625 spellchk *spell; | |
626 GtkTextBuffer *buffer; | |
627 GtkTextIter start, end; | |
628 GaimGtkConversation *gtkconv; | |
629 GtkTextView *view; | |
630 | |
631 gtkconv = GAIM_GTK_CONVERSATION(conv); | |
632 | |
633 view = GTK_TEXT_VIEW(gtkconv->entry); | |
634 | |
635 spell = g_object_get_data(G_OBJECT(view), SPELLCHK_OBJECT_KEY); | |
636 if (spell != NULL) | |
637 return; | |
638 | |
639 /* attach to the widget */ | |
640 spell = g_new0(spellchk, 1); | |
641 spell->view = view; | |
642 | |
643 g_object_set_data_full(G_OBJECT(view), SPELLCHK_OBJECT_KEY, spell, | |
644 (GDestroyNotify)spellchk_free); | |
645 | |
646 buffer = gtk_text_view_get_buffer(view); | |
647 | |
648 /* we create the mark here, but we don't use it until text is | |
649 * inserted, so we don't really care where iter points. */ | |
650 gtk_text_buffer_get_bounds(buffer, &start, &end); | |
651 spell->mark_insert_start = gtk_text_buffer_create_mark(buffer, | |
652 "spellchk-insert-start", | |
653 &start, TRUE); | |
654 spell->mark_insert_end = gtk_text_buffer_create_mark(buffer, | |
655 "spellchk-insert-end", | |
656 &start, TRUE); | |
657 | |
658 g_signal_connect_after(G_OBJECT(buffer), | |
659 "delete-range", | |
660 G_CALLBACK(delete_range_after), spell); | |
661 g_signal_connect(G_OBJECT(buffer), | |
662 "insert-text", | |
663 G_CALLBACK(insert_text_before), spell); | |
664 g_signal_connect_after(G_OBJECT(buffer), | |
665 "insert-text", | |
666 G_CALLBACK(insert_text_after), spell); | |
667 | |
668 g_signal_connect(G_OBJECT(gtkconv->entry), "message_send", | |
669 G_CALLBACK(message_send_cb), spell); | |
670 return; | |
671 } | |
672 | |
673 static int buf_get_line(char *ibuf, char **buf, int *position, int len) | |
674 { | |
675 int pos = *position; | |
676 int spos = pos; | |
677 | |
678 if (pos == len) | |
679 return 0; | |
680 | |
681 while (!(ibuf[pos] == '\n' || | |
682 (ibuf[pos] == '\r' && ibuf[pos + 1] != '\n'))) | |
683 { | |
684 pos++; | |
685 if (pos == len) | |
686 return 0; | |
687 } | |
688 | |
689 if (pos != 0 && ibuf[pos] == '\n' && ibuf[pos - 1] == '\r') | |
690 ibuf[pos - 1] = '\0'; | |
691 | |
692 ibuf[pos] = '\0'; | |
693 *buf = &ibuf[spos]; | |
694 | |
695 pos++; | |
696 *position = pos; | |
697 | |
698 return 1; | |
699 } | |
700 | |
701 static void load_conf() | |
702 { | |
703 /* Corrections to change "...", "(c)", "(r)", and "(tm)" to their | |
704 * Unicode character equivalents were not added here even though | |
705 * they existed in the source list(s). I think these corrections | |
706 * would be more trouble than they're worth. | |
707 */ | |
708 const char * const defaultconf = | |
709 "BAD abbout\nGOOD about\n" | |
710 "BAD abotu\nGOOD about\n" | |
711 "BAD abouta\nGOOD about a\n" | |
712 "BAD aboutit\nGOOD about it\n" | |
713 "BAD aboutthe\nGOOD about the\n" | |
714 "BAD abscence\nGOOD absence\n" | |
715 "BAD accesories\nGOOD accessories\n" | |
716 "BAD accidant\nGOOD accident\n" | |
717 "BAD accomodate\nGOOD accommodate\n" | |
718 "BAD accordingto\nGOOD according to\n" | |
719 "BAD accross\nGOOD across\n" | |
720 "BAD acheive\nGOOD achieve\n" | |
721 "BAD acheived\nGOOD achieved\n" | |
722 "BAD acheiving\nGOOD achieving\n" | |
723 "BAD acn\nGOOD can\n" | |
724 "BAD acommodate\nGOOD accommodate\n" | |
725 "BAD acomodate\nGOOD accommodate\n" | |
726 "BAD actualyl\nGOOD actually\n" | |
727 "BAD additinal\nGOOD additional\n" | |
728 "BAD addtional\nGOOD additional\n" | |
729 "BAD adequit\nGOOD adequate\n" | |
730 "BAD adequite\nGOOD adequate\n" | |
731 "BAD adn\nGOOD and\n" | |
732 "BAD advanage\nGOOD advantage\n" | |
733 "BAD affraid\nGOOD afraid\n" | |
734 "BAD afterthe\nGOOD after the\n" | |
735 "COMPLETE 0\nBAD againstt he \nGOOD against the \n" | |
736 "BAD aganist\nGOOD against\n" | |
737 "BAD aggresive\nGOOD aggressive\n" | |
738 "BAD agian\nGOOD again\n" | |
739 "BAD agreemeent\nGOOD agreement\n" | |
740 "BAD agreemeents\nGOOD agreements\n" | |
741 "BAD agreemnet\nGOOD agreement\n" | |
742 "BAD agreemnets\nGOOD agreements\n" | |
743 "BAD agressive\nGOOD aggressive\n" | |
744 "BAD agressiveness\nGOOD aggressiveness\n" | |
745 "BAD ahd\nGOOD had\n" | |
746 "BAD ahold\nGOOD a hold\n" | |
747 "BAD ahppen\nGOOD happen\n" | |
748 "BAD ahve\nGOOD have\n" | |
749 "BAD allready\nGOOD already\n" | |
750 "BAD allwasy\nGOOD always\n" | |
751 "BAD allwyas\nGOOD always\n" | |
752 "BAD almots\nGOOD almost\n" | |
753 "BAD almsot\nGOOD almost\n" | |
754 "BAD alomst\nGOOD almost\n" | |
755 "BAD alot\nGOOD a lot\n" | |
756 "BAD alraedy\nGOOD already\n" | |
757 "BAD alreayd\nGOOD already\n" | |
758 "BAD alreday\nGOOD already\n" | |
759 "BAD alwasy\nGOOD always\n" | |
760 "BAD alwats\nGOOD always\n" | |
761 "BAD alway\nGOOD always\n" | |
762 "BAD alwyas\nGOOD always\n" | |
763 "BAD amde\nGOOD made\n" | |
764 "BAD Ameria\nGOOD America\n" | |
765 "BAD amke\nGOOD make\n" | |
766 "BAD amkes\nGOOD makes\n" | |
767 "BAD anbd\nGOOD and\n" | |
768 "BAD andone\nGOOD and one\n" | |
769 "BAD andteh\nGOOD and the\n" | |
770 "BAD andthe\nGOOD and the\n" | |
771 "COMPLETE 0\nBAD andt he \nGOOD and the \n" | |
772 "BAD anothe\nGOOD another\n" | |
773 "BAD anual\nGOOD annual\n" | |
774 "BAD any1\nGOOD anyone\n" | |
775 "BAD apparant\nGOOD apparent\n" | |
776 "BAD apparrent\nGOOD apparent\n" | |
777 "BAD appearence\nGOOD appearance\n" | |
778 "BAD appeares\nGOOD appears\n" | |
779 "BAD applicaiton\nGOOD application\n" | |
780 "BAD applicaitons\nGOOD applications\n" | |
781 "BAD applyed\nGOOD applied\n" | |
782 "BAD appointiment\nGOOD appointment\n" | |
783 "BAD approrpiate\nGOOD appropriate\n" | |
784 "BAD approrpriate\nGOOD appropriate\n" | |
785 "BAD aquisition\nGOOD acquisition\n" | |
786 "BAD aquisitions\nGOOD acquisitions\n" | |
787 "BAD arent\nGOOD aren't\n" | |
788 "COMPLETE 0\nBAD aren;t \nGOOD aren't \n" | |
789 "BAD arguement\nGOOD argument\n" | |
790 "BAD arguements\nGOOD arguments\n" | |
791 "COMPLETE 0\nBAD arn't \nGOOD aren't \n" | |
792 "BAD arond\nGOOD around\n" | |
793 "BAD artical\nGOOD article\n" | |
794 "BAD articel\nGOOD article\n" | |
795 "BAD asdvertising\nGOOD advertising\n" | |
796 "COMPLETE 0\nBAD askt he \nGOOD ask the \n" | |
797 "BAD assistent\nGOOD assistant\n" | |
798 "BAD asthe\nGOOD as the\n" | |
799 "BAD atention\nGOOD attention\n" | |
800 "BAD atmospher\nGOOD atmosphere\n" | |
801 "BAD attentioin\nGOOD attention\n" | |
802 "BAD atthe\nGOOD at the\n" | |
803 "BAD audeince\nGOOD audience\n" | |
804 "BAD audiance\nGOOD audience\n" | |
805 "BAD authentification\nGOOD authentication\n" | |
806 "BAD availalbe\nGOOD available\n" | |
807 "BAD awya\nGOOD away\n" | |
808 "BAD aywa\nGOOD away\n" | |
809 "BAD b4\nGOOD before\n" | |
810 "BAD bakc\nGOOD back\n" | |
811 "BAD balence\nGOOD balance\n" | |
812 "BAD ballance\nGOOD balance\n" | |
813 "BAD baout\nGOOD about\n" | |
814 "BAD bcak\nGOOD back\n" | |
815 "BAD bcuz\nGOOD because\n" | |
816 "BAD beacuse\nGOOD because\n" | |
817 "BAD becasue\nGOOD because\n" | |
818 "BAD becaus\nGOOD because\n" | |
819 "BAD becausea\nGOOD because a\n" | |
820 "BAD becauseof\nGOOD because of\n" | |
821 "BAD becausethe\nGOOD because the\n" | |
822 "BAD becauseyou\nGOOD because you\n" | |
823 "COMPLETE 0\nBAD beckon call\nGOOD beck and call\n" | |
824 "BAD becomeing\nGOOD becoming\n" | |
825 "BAD becomming\nGOOD becoming\n" | |
826 "BAD becuase\nGOOD because\n" | |
827 "BAD becuse\nGOOD because\n" | |
828 "BAD befoer\nGOOD before\n" | |
829 "BAD beggining\nGOOD beginning\n" | |
830 "BAD begining\nGOOD beginning\n" | |
831 "BAD beginining\nGOOD beginning\n" | |
832 "BAD beleiev\nGOOD believe\n" | |
833 "BAD beleieve\nGOOD believe\n" | |
834 "BAD beleif\nGOOD belief\n" | |
835 "BAD beleive\nGOOD believe\n" | |
836 "BAD beleived\nGOOD believed\n" | |
837 "BAD beleives\nGOOD believes\n" | |
838 "BAD belive\nGOOD believe\n" | |
839 "BAD belived\nGOOD believed\n" | |
840 "BAD belives\nGOOD believes\n" | |
841 "BAD benifit\nGOOD benefit\n" | |
842 "BAD benifits\nGOOD benefits\n" | |
843 "BAD betwen\nGOOD between\n" | |
844 "BAD beutiful\nGOOD beautiful\n" | |
845 "BAD blase\nGOOD blas\303\251\n" | |
846 "BAD boxs\nGOOD boxes\n" | |
847 "BAD brodcast\nGOOD broadcast\n" | |
848 "BAD butthe\nGOOD but the\n" | |
849 "BAD bve\nGOOD be\n" | |
850 "COMPLETE 0\nBAD byt he \nGOOD by the \n" | |
851 "BAD cafe\nGOOD caf\303\251\n" | |
852 "BAD caharcter\nGOOD character\n" | |
853 "BAD calcullated\nGOOD calculated\n" | |
854 "BAD calulated\nGOOD calculated\n" | |
855 "BAD candidtae\nGOOD candidate\n" | |
856 "BAD candidtaes\nGOOD candidates\n" | |
857 "COMPLETE 0\nBAD case and point\nGOOD case in point\n" | |
858 "BAD cant\nGOOD can't\n" | |
859 "COMPLETE 0\nBAD can;t \nGOOD can't \n" | |
860 "COMPLETE 0\nBAD can't of been\nGOOD can't have been\n" | |
861 "BAD catagory\nGOOD category\n" | |
862 "BAD categiory\nGOOD category\n" | |
863 "BAD certian\nGOOD certain\n" | |
864 "BAD challange\nGOOD challenge\n" | |
865 "BAD challanges\nGOOD challenges\n" | |
866 "BAD chaneg\nGOOD change\n" | |
867 "BAD chanegs\nGOOD changes\n" | |
868 "BAD changable\nGOOD changeable\n" | |
869 "BAD changeing\nGOOD changing\n" | |
870 "BAD changng\nGOOD changing\n" | |
871 "BAD charachter\nGOOD character\n" | |
872 "BAD charachters\nGOOD characters\n" | |
873 "BAD charactor\nGOOD character\n" | |
874 "BAD charecter\nGOOD character\n" | |
875 "BAD charector\nGOOD character\n" | |
876 "BAD cheif\nGOOD chief\n" | |
877 "BAD chekc\nGOOD check\n" | |
878 "BAD chnage\nGOOD change\n" | |
879 "BAD cieling\nGOOD ceiling\n" | |
880 "BAD circut\nGOOD circuit\n" | |
881 "BAD claer\nGOOD clear\n" | |
882 "BAD claered\nGOOD cleared\n" | |
883 "BAD claerly\nGOOD clearly\n" | |
884 "BAD cliant\nGOOD client\n" | |
885 "BAD cliche\nGOOD clich\303\251\n" | |
886 "BAD cna\nGOOD can\n" | |
887 "BAD colection\nGOOD collection\n" | |
888 "BAD comanies\nGOOD companies\n" | |
889 "BAD comany\nGOOD company\n" | |
890 "BAD comapnies\nGOOD companies\n" | |
891 "BAD comapny\nGOOD company\n" | |
892 "BAD combintation\nGOOD combination\n" | |
893 "BAD comited\nGOOD committed\n" | |
894 "BAD comittee\nGOOD committee\n" | |
895 "BAD commadn\nGOOD command\n" | |
896 "BAD comming\nGOOD coming\n" | |
897 "BAD commitee\nGOOD committee\n" | |
898 "BAD committe\nGOOD committee\n" | |
899 "BAD committment\nGOOD commitment\n" | |
900 "BAD committments\nGOOD commitments\n" | |
901 "BAD committy\nGOOD committee\n" | |
902 "BAD comntain\nGOOD contain\n" | |
903 "BAD comntains\nGOOD contains\n" | |
904 "BAD compair\nGOOD compare\n" | |
905 "COMPLETE 0\nBAD company;s \nGOOD company's \n" | |
906 "BAD competetive\nGOOD competitive\n" | |
907 "BAD compleated\nGOOD completed\n" | |
908 "BAD compleatly\nGOOD completely\n" | |
909 "BAD compleatness\nGOOD completeness\n" | |
910 "BAD completly\nGOOD completely\n" | |
911 "BAD completness\nGOOD completeness\n" | |
912 "BAD composate\nGOOD composite\n" | |
913 "BAD comtain\nGOOD contain\n" | |
914 "BAD comtains\nGOOD contains\n" | |
915 "BAD comunicate\nGOOD communicate\n" | |
916 "BAD comunity\nGOOD community\n" | |
917 "BAD condolances\nGOOD condolences\n" | |
918 "BAD conected\nGOOD connected\n" | |
919 "BAD conferance\nGOOD conference\n" | |
920 "BAD confirmmation\nGOOD confirmation\n" | |
921 "BAD congradulations\nGOOD congratulations\n" | |
922 "BAD considerit\nGOOD considerate\n" | |
923 "BAD considerite\nGOOD considerate\n" | |
924 "BAD consonent\nGOOD consonant\n" | |
925 "BAD conspiricy\nGOOD conspiracy\n" | |
926 "BAD consultent\nGOOD consultant\n" | |
927 "BAD convertable\nGOOD convertible\n" | |
928 "BAD cooparate\nGOOD cooperate\n" | |
929 "BAD cooporate\nGOOD cooperate\n" | |
930 "BAD corproation\nGOOD corporation\n" | |
931 "BAD corproations\nGOOD corporations\n" | |
932 "BAD corruptable\nGOOD corruptible\n" | |
933 "BAD cotten\nGOOD cotton\n" | |
934 "BAD coudl\nGOOD could\n" | |
935 "COMPLETE 0\nBAD coudln't \nGOOD couldn't \n" | |
936 "COMPLETE 0\nBAD coudn't \nGOOD couldn't \n" | |
937 "BAD couldnt\nGOOD couldn't\n" | |
938 "COMPLETE 0\nBAD couldn;t \nGOOD couldn't \n" | |
939 "COMPLETE 0\nBAD could of been\nGOOD could have been\n" | |
940 "COMPLETE 0\nBAD could of had\nGOOD could have had\n" | |
941 "BAD couldthe\nGOOD could the\n" | |
942 "BAD couldve\nGOOD could've\n" | |
943 "BAD cpoy\nGOOD copy\n" | |
944 "BAD creme\nGOOD cr\303\250me\n" | |
945 "BAD ctaegory\nGOOD category\n" | |
946 "BAD cu\nGOOD see you\n" | |
947 "BAD cusotmer\nGOOD customer\n" | |
948 "BAD cusotmers\nGOOD customers\n" | |
949 "BAD cutsomer\nGOOD customer\n" | |
950 "BAD cutsomers\nGOOD customer\n" | |
951 "BAD cuz\nGOOD because\n" | |
952 "BAD cxan\nGOOD can\n" | |
953 "BAD danceing\nGOOD dancing\n" | |
954 "BAD dcument\nGOOD document\n" | |
955 "BAD deatils\nGOOD details\n" | |
956 "BAD decison\nGOOD decision\n" | |
957 "BAD decisons\nGOOD decisions\n" | |
958 "BAD decor\nGOOD d\303\251cor\n" | |
959 "BAD defendent\nGOOD defendant\n" | |
960 "BAD definately\nGOOD definitely\n" | |
961 "COMPLETE 0\nBAD deja vu\nGOOD d\303\251j\303\240 vu\n" | |
962 "BAD deptartment\nGOOD department\n" | |
963 "BAD desicion\nGOOD decision\n" | |
964 "BAD desicions\nGOOD decisions\n" | |
965 "BAD desision\nGOOD decision\n" | |
966 "BAD desisions\nGOOD decisions\n" | |
967 "BAD detente\nGOOD d\303\251tente\n" | |
968 "BAD develeoprs\nGOOD developers\n" | |
969 "BAD devellop\nGOOD develop\n" | |
970 "BAD develloped\nGOOD developed\n" | |
971 "BAD develloper\nGOOD developer\n" | |
972 "BAD devellopers\nGOOD developers\n" | |
973 "BAD develloping\nGOOD developing\n" | |
974 "BAD devellopment\nGOOD development\n" | |
975 "BAD devellopments\nGOOD developments\n" | |
976 "BAD devellops\nGOOD develop\n" | |
977 "BAD develope\nGOOD develop\n" | |
978 "BAD developement\nGOOD development\n" | |
979 "BAD developements\nGOOD developments\n" | |
980 "BAD developor\nGOOD developer\n" | |
981 "BAD developors\nGOOD developers\n" | |
982 "BAD develpment\nGOOD development\n" | |
983 "BAD diaplay\nGOOD display\n" | |
984 "BAD didint\nGOOD didn't\n" | |
985 "BAD didnot\nGOOD did not\n" | |
986 "BAD didnt\nGOOD didn't\n" | |
987 "COMPLETE 0\nBAD didn;t \nGOOD didn't \n" | |
988 "BAD difefrent\nGOOD different\n" | |
989 "BAD diferences\nGOOD differences\n" | |
990 "BAD differance\nGOOD difference\n" | |
991 "BAD differances\nGOOD differences\n" | |
992 "BAD differant\nGOOD different\n" | |
993 "BAD differemt\nGOOD different\n" | |
994 "BAD differnt\nGOOD different\n" | |
995 "BAD diffrent\nGOOD different\n" | |
996 "BAD directer\nGOOD director\n" | |
997 "BAD directers\nGOOD directors\n" | |
998 "BAD directiosn\nGOOD direction\n" | |
999 "BAD disatisfied\nGOOD dissatisfied\n" | |
1000 "BAD discoverd\nGOOD discovered\n" | |
1001 "BAD disign\nGOOD design\n" | |
1002 "BAD dispaly\nGOOD display\n" | |
1003 "BAD dissonent\nGOOD dissonant\n" | |
1004 "BAD distribusion\nGOOD distribution\n" | |
1005 "BAD divsion\nGOOD division\n" | |
1006 "BAD docuement\nGOOD documents\n" | |
1007 "BAD docuemnt\nGOOD document\n" | |
1008 "BAD documetn\nGOOD document\n" | |
1009 "BAD documnet\nGOOD document\n" | |
1010 "BAD documnets\nGOOD documents\n" | |
1011 "COMPLETE 0\nBAD doens't \nGOOD doesn't \n" | |
1012 "BAD doese\nGOOD does\n" | |
1013 "COMPLETE 0\nBAD doe snot \nGOOD does not \n" | |
1014 "BAD doesnt\nGOOD doesn't\n" | |
1015 "COMPLETE 0\nBAD doesn;t \nGOOD doesn't \n" | |
1016 "BAD doign\nGOOD doing\n" | |
1017 "BAD doimg\nGOOD doing\n" | |
1018 "BAD doind\nGOOD doing\n" | |
1019 "BAD dollers\nGOOD dollars\n" | |
1020 "BAD donig\nGOOD doing\n" | |
1021 "BAD donno\nGOOD don't know\n" | |
1022 "BAD dont\nGOOD don't\n" | |
1023 "COMPLETE 0\nBAD do'nt \nGOOD don't \n" | |
1024 "COMPLETE 0\nBAD don;t \nGOOD don't \n" | |
1025 "COMPLETE 0\nBAD don't no \nGOOD don't know \n" | |
1026 "COMPLETE 0\nBAD dosn't \nGOOD doesn't \n" | |
1027 "BAD driveing\nGOOD driving\n" | |
1028 "BAD drnik\nGOOD drink\n" | |
1029 "BAD dunno\nGOOD don't know\n" | |
1030 "BAD eclair\nGOOD \303\251clair\n" | |
1031 "BAD efel\nGOOD feel\n" | |
1032 "BAD effecient\nGOOD efficient\n" | |
1033 "BAD efort\nGOOD effort\n" | |
1034 "BAD eforts\nGOOD efforts\n" | |
1035 "BAD ehr\nGOOD her\n" | |
1036 "BAD eligable\nGOOD eligible\n" | |
1037 "BAD embarass\nGOOD embarrass\n" | |
1038 "BAD emigre\nGOOD \303\251migr\303\251\n" | |
1039 "BAD enought\nGOOD enough\n" | |
1040 "BAD entree\nGOOD entr\303\251e\n" | |
1041 "BAD enuf\nGOOD enough\n" | |
1042 "BAD equippment\nGOOD equipment\n" | |
1043 "BAD equivalant\nGOOD equivalent\n" | |
1044 "BAD esle\nGOOD else\n" | |
1045 "BAD especally\nGOOD especially\n" | |
1046 "BAD especialyl\nGOOD especially\n" | |
1047 "BAD espesially\nGOOD especially\n" | |
1048 "BAD essense\nGOOD essence\n" | |
1049 "BAD excellance\nGOOD excellence\n" | |
1050 "BAD excellant\nGOOD excellent\n" | |
1051 "BAD excercise\nGOOD exercise\n" | |
1052 "BAD exchagne\nGOOD exchange\n" | |
1053 "BAD exchagnes\nGOOD exchanges\n" | |
1054 "BAD excitment\nGOOD excitement\n" | |
1055 "BAD exhcange\nGOOD exchange\n" | |
1056 "BAD exhcanges\nGOOD exchanges\n" | |
1057 "BAD experiance\nGOOD experience\n" | |
1058 "BAD experienc\nGOOD experience\n" | |
1059 "BAD exprience\nGOOD experience\n" | |
1060 "BAD exprienced\nGOOD experienced\n" | |
1061 "BAD eyt\nGOOD yet\n" | |
1062 "BAD facade\nGOOD fa\303\247ade\n" | |
1063 "BAD faeture\nGOOD feature\n" | |
1064 "BAD faetures\nGOOD feature\n" | |
1065 "BAD familair\nGOOD familiar\n" | |
1066 "BAD familar\nGOOD familiar\n" | |
1067 "BAD familliar\nGOOD familiar\n" | |
1068 "BAD fammiliar\nGOOD familiar\n" | |
1069 "BAD feild\nGOOD field\n" | |
1070 "BAD feilds\nGOOD fields\n" | |
1071 "BAD fianlly\nGOOD finally\n" | |
1072 "BAD fidn\nGOOD find\n" | |
1073 "BAD finalyl\nGOOD finally\n" | |
1074 "BAD firends\nGOOD friends\n" | |
1075 "BAD firts\nGOOD first\n" | |
1076 "BAD follwo\nGOOD follow\n" | |
1077 "BAD follwoing\nGOOD following\n" | |
1078 "BAD fora\nGOOD for a\n" | |
1079 "COMPLETE 0\nBAD for all intensive purposes\nfor all intents and purposes\n" | |
1080 "BAD foriegn\nGOOD foreign\n" | |
1081 "BAD forthe\nGOOD for the\n" | |
1082 "BAD forwrd\nGOOD forward\n" | |
1083 "BAD forwrds\nGOOD forwards\n" | |
1084 "BAD foudn\nGOOD found\n" | |
1085 "BAD foward\nGOOD forward\n" | |
1086 "BAD fowards\nGOOD forwards\n" | |
1087 "BAD freind\nGOOD friend\n" | |
1088 "BAD freindly\nGOOD friendly\n" | |
1089 "BAD freinds\nGOOD friends\n" | |
1090 "BAD friday\nGOOD Friday\n" | |
1091 "BAD frmo\nGOOD from\n" | |
1092 "BAD fromthe\nGOOD from the\n" | |
1093 "COMPLETE 0\nBAD fromt he \nGOOD from the \n" | |
1094 "BAD furneral\nGOOD funeral\n" | |
1095 "BAD fwe\nGOOD few\n" | |
1096 "BAD garantee\nGOOD guarantee\n" | |
1097 "BAD gaurd\nGOOD guard\n" | |
1098 "BAD gemeral\nGOOD general\n" | |
1099 "BAD gerat\nGOOD great\n" | |
1100 "BAD geting\nGOOD getting\n" | |
1101 "BAD gettin\nGOOD getting\n" | |
1102 "BAD gievn\nGOOD given\n" | |
1103 "BAD giveing\nGOOD giving\n" | |
1104 "BAD gloabl\nGOOD global\n" | |
1105 "BAD goign\nGOOD going\n" | |
1106 "BAD gonig\nGOOD going\n" | |
1107 "BAD govenment\nGOOD government\n" | |
1108 "BAD goverment\nGOOD government\n" | |
1109 "BAD gruop\nGOOD group\n" | |
1110 "BAD gruops\nGOOD groups\n" | |
1111 "BAD grwo\nGOOD grow\n" | |
1112 "BAD guidlines\nGOOD guidelines\n" | |
1113 "BAD hadbeen\nGOOD had been\n" | |
1114 "BAD hadnt\nGOOD hadn't\n" | |
1115 "COMPLETE 0\nBAD hadn;t \nGOOD hadn't \n" | |
1116 "BAD haev\nGOOD have\n" | |
1117 "BAD hapen\nGOOD happen\n" | |
1118 "BAD hapened\nGOOD happened\n" | |
1119 "BAD hapening\nGOOD happening\n" | |
1120 "BAD hapens\nGOOD happens\n" | |
1121 "BAD happend\nGOOD happened\n" | |
1122 "BAD hasbeen\nGOOD has been\n" | |
1123 "BAD hasnt\nGOOD hasn't\n" | |
1124 "COMPLETE 0\nBAD hasn;t \nGOOD hasn't \n" | |
1125 "BAD havebeen\nGOOD have been\n" | |
1126 "BAD haveing\nGOOD having\n" | |
1127 "BAD havent\nGOOD haven't\n" | |
1128 "COMPLETE 0\nBAD haven;t \nGOOD haven't \n" | |
1129 "BAD hda\nGOOD had\n" | |
1130 "BAD hearign\nGOOD hearing\n" | |
1131 "COMPLETE 0\nBAD he;d \nGOOD he'd \n" | |
1132 "BAD heirarchy\nGOOD hierarchy\n" | |
1133 "BAD hel\nGOOD he'll\n" | |
1134 "COMPLETE 0\nBAD he;ll \nGOOD he'll \n" | |
1135 "BAD helpfull\nGOOD helpful\n" | |
1136 "BAD herat\nGOOD heart\n" | |
1137 "BAD heres\nGOOD here's\n" | |
1138 "COMPLETE 0\nBAD here;s \nGOOD here's \n" | |
1139 "BAD hes\nGOOD he's\n" | |
1140 "COMPLETE 0\nBAD he;s \nGOOD he's \n" | |
1141 "BAD hesaid\nGOOD he said\n" | |
1142 "BAD hewas\nGOOD he was\n" | |
1143 "BAD hge\nGOOD he\n" | |
1144 "BAD hismelf\nGOOD himself\n" | |
1145 "BAD hlep\nGOOD help\n" | |
1146 "BAD hott\nGOOD hot\n" | |
1147 "BAD hows\nGOOD how's\n" | |
1148 "BAD hsa\nGOOD has\n" | |
1149 "BAD hse\nGOOD she\n" | |
1150 "BAD hsi\nGOOD his\n" | |
1151 "BAD hte\nGOOD the\n" | |
1152 "BAD htere\nGOOD there\n" | |
1153 "BAD htese\nGOOD these\n" | |
1154 "BAD htey\nGOOD they\n" | |
1155 "BAD hting\nGOOD thing\n" | |
1156 "BAD htink\nGOOD think\n" | |
1157 "BAD htis\nGOOD this\n" | |
1158 "COMPLETE 0\nBAD htp:\nGOOD http:\n" | |
1159 "COMPLETE 0\nBAD http:\\\\nGOOD http://\n" | |
1160 "BAD httpL\nGOOD http:\n" | |
1161 "BAD hvae\nGOOD have\n" | |
1162 "BAD hvaing\nGOOD having\n" | |
1163 "BAD hwich\nGOOD which\n" | |
1164 "BAD i\nGOOD I\n" | |
1165 "COMPLETE 0\nBAD i c \nGOOD I see \n" | |
1166 "COMPLETE 0\nBAD i;d \nGOOD I'd \n" | |
1167 "COMPLETE 0\nBAD i'd \nGOOD I'd \n" | |
1168 "COMPLETE 0\nBAD I;d \nGOOD I'd \n" | |
1169 "BAD idae\nGOOD idea\n" | |
1170 "BAD idaes\nGOOD ideas\n" | |
1171 "BAD identofy\nGOOD identify\n" | |
1172 "BAD ihs\nGOOD his\n" | |
1173 "BAD iits the\nGOOD it's the\n" | |
1174 "COMPLETE 0\nBAD i'll \nGOOD I'll \n" | |
1175 "COMPLETE 0\nBAD I;ll \nGOOD I'll \n" | |
1176 "COMPLETE 0\nBAD i;m \nGOOD I'm \n" | |
1177 "COMPLETE 0\nBAD i'm \nGOOD I'm \n" | |
1178 "COMPLETE 0\nBAD I\"m \nGOOD I'm \n" | |
1179 "BAD imediate\nGOOD immediate\n" | |
1180 "BAD imediatly\nGOOD immediately\n" | |
1181 "BAD immediatly\nGOOD immediately\n" | |
1182 "BAD importent\nGOOD important\n" | |
1183 "BAD importnat\nGOOD important\n" | |
1184 "BAD impossable\nGOOD impossible\n" | |
1185 "BAD improvemnt\nGOOD improvement\n" | |
1186 "BAD improvment\nGOOD improvement\n" | |
1187 "BAD includ\nGOOD include\n" | |
1188 "BAD indecate\nGOOD indicate\n" | |
1189 "BAD indenpendence\nGOOD independence\n" | |
1190 "BAD indenpendent\nGOOD independent\n" | |
1191 "BAD indepedent\nGOOD independent\n" | |
1192 "BAD independance\nGOOD independence\n" | |
1193 "BAD independant\nGOOD independent\n" | |
1194 "BAD influance\nGOOD influence\n" | |
1195 "BAD infomation\nGOOD information\n" | |
1196 "BAD informatoin\nGOOD information\n" | |
1197 "BAD inital\nGOOD initial\n" | |
1198 "BAD instaleld\nGOOD installed\n" | |
1199 "BAD insted\nGOOD instead\n" | |
1200 "BAD insurence\nGOOD insurance\n" | |
1201 "BAD inteh\nGOOD in the\n" | |
1202 "BAD interum\nGOOD interim\n" | |
1203 "BAD inthe\nGOOD in the\n" | |
1204 "COMPLETE 0\nBAD int he \nGOOD in the \n" | |
1205 "BAD inturn\nGOOD intern\n" | |
1206 "BAD inwhich\nGOOD in which\n" | |
1207 "COMPLETE 0\nBAD i snot \nGOOD is not \n" | |
1208 "BAD isnt\nGOOD isn't\n" | |
1209 "COMPLETE 0\nBAD isn;t \nGOOD isn't \n" | |
1210 "BAD isthe\nGOOD is the\n" | |
1211 "BAD itd\nGOOD it'd\n" | |
1212 "COMPLETE 0\nBAD it;d \nGOOD it'd \n" | |
1213 "BAD itis\nGOOD it is\n" | |
1214 "BAD ititial\nGOOD initial\n" | |
1215 "BAD itll\nGOOD it'll\n" | |
1216 "COMPLETE 0\nBAD it;ll \nGOOD it'll \n" | |
1217 "BAD itnerest\nGOOD interest\n" | |
1218 "BAD itnerested\nGOOD interested\n" | |
1219 "BAD itneresting\nGOOD interesting\n" | |
1220 "BAD itnerests\nGOOD interests\n" | |
1221 "COMPLETE 0\nBAD it;s \nGOOD it's \n" | |
1222 "BAD itsa\nGOOD it's a\n" | |
1223 "COMPLETE 0\nBAD its a \nGOOD it's a \n" | |
1224 "COMPLETE 0\nBAD it snot \nGOOD it's not \n" | |
1225 "COMPLETE 0\nBAD it' snot \nGOOD it's not \n" | |
1226 "COMPLETE 0\nBAD its the \nGOOD it's the \n" | |
1227 "BAD itwas\nGOOD it was\n" | |
1228 "BAD ive\nGOOD I've\n" | |
1229 "COMPLETE 0\nBAD i;ve \nGOOD I've \n" | |
1230 "COMPLETE 0\nBAD i've \nGOOD I've \n" | |
1231 "BAD iwll\nGOOD will\n" | |
1232 "BAD iwth\nGOOD with\n" | |
1233 "BAD jsut\nGOOD just\n" | |
1234 "BAD jugment\nGOOD judgment\n" | |
1235 "BAD kno\nGOOD know\n" | |
1236 "BAD knowldge\nGOOD knowledge\n" | |
1237 "BAD knowlege\nGOOD knowledge\n" | |
1238 "BAD knwo\nGOOD know\n" | |
1239 "BAD knwon\nGOOD known\n" | |
1240 "BAD knwos\nGOOD knows\n" | |
1241 "BAD konw\nGOOD know\n" | |
1242 "BAD konwn\nGOOD known\n" | |
1243 "BAD konws\nGOOD knows\n" | |
1244 "BAD labratory\nGOOD laboratory\n" | |
1245 "BAD labtop\nGOOD laptop\n" | |
1246 "BAD lastyear\nGOOD last year\n" | |
1247 "BAD laterz\nGOOD later\n" | |
1248 "BAD learnign\nGOOD learning\n" | |
1249 "BAD lenght\nGOOD length\n" | |
1250 "COMPLETE 0\nBAD let;s \nGOOD let's \n" | |
1251 "COMPLETE 0\nBAD let's him \nGOOD lets him \n" | |
1252 "COMPLETE 0\nBAD let's it \nGOOD lets it \n" | |
1253 "BAD levle\nGOOD level\n" | |
1254 "BAD libary\nGOOD library\n" | |
1255 "BAD librarry\nGOOD library\n" | |
1256 "BAD librery\nGOOD library\n" | |
1257 "BAD liek\nGOOD like\n" | |
1258 "BAD liekd\nGOOD liked\n" | |
1259 "BAD lieutenent\nGOOD lieutenant\n" | |
1260 "BAD liev\nGOOD live\n" | |
1261 "BAD likly\nGOOD likely\n" | |
1262 "BAD lisense\nGOOD license\n" | |
1263 "BAD littel\nGOOD little\n" | |
1264 "BAD litttle\nGOOD little\n" | |
1265 "BAD liuke\nGOOD like\n" | |
1266 "BAD liveing\nGOOD living\n" | |
1267 "BAD loev\nGOOD love\n" | |
1268 "BAD lonly\nGOOD lonely\n" | |
1269 "BAD lookign\nGOOD looking\n" | |
1270 "BAD m\nGOOD am\n" | |
1271 "BAD maintainence\nGOOD maintenance\n" | |
1272 "BAD maintenence\nGOOD maintenance\n" | |
1273 "BAD makeing\nGOOD making\n" | |
1274 "BAD managment\nGOOD management\n" | |
1275 "BAD mantain\nGOOD maintain\n" | |
1276 "BAD marraige\nGOOD marriage\n" | |
1277 "COMPLETE 0\nBAD may of been\nGOOD may have been\n" | |
1278 "COMPLETE 0\nBAD may of had\nGOOD may have had\n" | |
1279 "BAD memeber\nGOOD member\n" | |
1280 "BAD merchent\nGOOD merchant\n" | |
1281 "BAD mesage\nGOOD message\n" | |
1282 "BAD mesages\nGOOD messages\n" | |
1283 "COMPLETE 0\nBAD might of been\nGOOD might have been\n" | |
1284 "COMPLETE 0\nBAD might of had\nGOOD might have had\n" | |
1285 "BAD mispell\nGOOD misspell\n" | |
1286 "BAD mispelling\nGOOD misspelling\n" | |
1287 "BAD mispellings\nGOOD misspellings\n" | |
1288 "BAD mkae\nGOOD make\n" | |
1289 "BAD mkaes\nGOOD makes\n" | |
1290 "BAD mkaing\nGOOD making\n" | |
1291 "BAD moeny\nGOOD money\n" | |
1292 "BAD monday\nGOOD Monday\n" | |
1293 "BAD morgage\nGOOD mortgage\n" | |
1294 "BAD mroe\nGOOD more\n" | |
1295 "COMPLETE 0\nBAD must of been\nGOOD must have been\n" | |
1296 "COMPLETE 0\nBAD must of had\nGOOD must have had\n" | |
1297 "COMPLETE 0\nBAD mute point\nGOOD moot point\n" | |
1298 "BAD mysefl\nGOOD myself\n" | |
1299 "BAD myu\nGOOD my\n" | |
1300 "BAD naive\nGOOD naïve\n" | |
1301 "BAD ne1\nGOOD anyone\n" | |
1302 "BAD neway\nGOOD anyway\n" | |
1303 "BAD neways\nGOOD anyways\n" | |
1304 "BAD necassarily\nGOOD necessarily\n" | |
1305 "BAD necassary\nGOOD necessary\n" | |
1306 "BAD neccessarily\nGOOD necessarily\n" | |
1307 "BAD neccessary\nGOOD necessary\n" | |
1308 "BAD necesarily\nGOOD necessarily\n" | |
1309 "BAD necesary\nGOOD necessary\n" | |
1310 "BAD negotiaing\nGOOD negotiating\n" | |
1311 "BAD nkow\nGOOD know\n" | |
1312 "BAD nothign\nGOOD nothing\n" | |
1313 "BAD nto\nGOOD not\n" | |
1314 "BAD nver\nGOOD never\n" | |
1315 "BAD nwe\nGOOD new\n" | |
1316 "BAD nwo\nGOOD now\n" | |
1317 "BAD obediant\nGOOD obedient\n" | |
1318 "BAD ocasion\nGOOD occasion\n" | |
1319 "BAD occassion\nGOOD occasion\n" | |
1320 "BAD occurance\nGOOD occurrence\n" | |
1321 "BAD occured\nGOOD occurred\n" | |
1322 "BAD occurence\nGOOD occurrence\n" | |
1323 "BAD occurrance\nGOOD occurrence\n" | |
1324 "BAD oclock\nGOOD o'clock\n" | |
1325 "BAD oculd\nGOOD could\n" | |
1326 "BAD ocur\nGOOD occur\n" | |
1327 "BAD oeprator\nGOOD operator\n" | |
1328 "BAD ofits\nGOOD of its\n" | |
1329 "BAD ofthe\nGOOD of the\n" | |
1330 "BAD oft he\nGOOD of the\n" | |
1331 "BAD oging\nGOOD going\n" | |
1332 "BAD ohter\nGOOD other\n" | |
1333 "BAD omre\nGOOD more\n" | |
1334 "BAD oneof\nGOOD one of\n" | |
1335 "BAD onepoint\nGOOD one point\n" | |
1336 "BAD onthe\nGOOD on the\n" | |
1337 "COMPLETE 0\nBAD ont he \nGOOD on the \n" | |
1338 "BAD onyl\nGOOD only\n" | |
1339 "BAD oppasite\nGOOD opposite\n" | |
1340 "BAD opperation\nGOOD operation\n" | |
1341 "BAD oppertunity\nGOOD opportunity\n" | |
1342 "BAD opposate\nGOOD opposite\n" | |
1343 "BAD opposible\nGOOD opposable\n" | |
1344 "BAD opposit\nGOOD opposite\n" | |
1345 "BAD oppotunities\nGOOD opportunities\n" | |
1346 "BAD oppotunity\nGOOD opportunity\n" | |
1347 "BAD orginization\nGOOD organization\n" | |
1348 "BAD orginized\nGOOD organized\n" | |
1349 "BAD otehr\nGOOD other\n" | |
1350 "BAD otu\nGOOD out\n" | |
1351 "BAD outof\nGOOD out of\n" | |
1352 "BAD overthe\nGOOD over the\n" | |
1353 "BAD owrk\nGOOD work\n" | |
1354 "BAD owuld\nGOOD would\n" | |
1355 "BAD oxident\nGOOD oxidant\n" | |
1356 "BAD papaer\nGOOD paper\n" | |
1357 "BAD passe\nGOOD pass\303\251\n" | |
1358 "BAD parliment\nGOOD parliament\n" | |
1359 "BAD partof\nGOOD part of\n" | |
1360 "BAD paymetn\nGOOD payment\n" | |
1361 "BAD paymetns\nGOOD payments\n" | |
1362 "BAD pciture\nGOOD picture\n" | |
1363 "BAD peice\nGOOD piece\n" | |
1364 "BAD peices\nGOOD pieces\n" | |
1365 "BAD peolpe\nGOOD people\n" | |
1366 "BAD peopel\nGOOD people\n" | |
1367 "BAD percentof\nGOOD percent of\n" | |
1368 "BAD percentto\nGOOD percent to\n" | |
1369 "BAD performence\nGOOD performance\n" | |
1370 "BAD perhasp\nGOOD perhaps\n" | |
1371 "BAD perhpas\nGOOD perhaps\n" | |
1372 "BAD permanant\nGOOD permanent\n" | |
1373 "BAD perminent\nGOOD permanent\n" | |
1374 "BAD personalyl\nGOOD personally\n" | |
1375 "BAD pleasent\nGOOD pleasant\n" | |
1376 "BAD pls\nGOOD please\n" | |
1377 "BAD plz\nGOOD please\n" | |
1378 "BAD poeple\nGOOD people\n" | |
1379 "BAD porblem\nGOOD problem\n" | |
1380 "BAD porblems\nGOOD problems\n" | |
1381 "BAD porvide\nGOOD provide\n" | |
1382 "BAD possable\nGOOD possible\n" | |
1383 "BAD postition\nGOOD position\n" | |
1384 "BAD potatoe\nGOOD potato\n" | |
1385 "BAD potatos\nGOOD potatoes\n" | |
1386 "BAD potentialy\nGOOD potentially\n" | |
1387 "BAD ppl\nGOOD people\n" | |
1388 "BAD pregnent\nGOOD pregnant\n" | |
1389 "BAD presance\nGOOD presence\n" | |
1390 "BAD primative\nGOOD primitive\n" | |
1391 "BAD probally\nGOOD probably\n" | |
1392 "BAD probelm\nGOOD problem\n" | |
1393 "BAD probelms\nGOOD problems\n" | |
1394 "BAD probly\nGOOD probably\n" | |
1395 "BAD prolly\nGOOD probably\n" | |
1396 "BAD proly\nGOOD probably\n" | |
1397 "BAD prominant\nGOOD prominent\n" | |
1398 "BAD proposterous\nGOOD preposterous\n" | |
1399 "BAD protege\nGOOD prot\303\251g\303\251\n" | |
1400 "BAD protoge\nGOOD prot\303\251g\303\251\n" | |
1401 "BAD psoition\nGOOD position\n" | |
1402 "BAD ptogress\nGOOD progress\n" | |
1403 "BAD pursuade\nGOOD persuade\n" | |
1404 "BAD puting\nGOOD putting\n" | |
1405 "BAD pwoer\nGOOD power\n" | |
1406 "BAD quater\nGOOD quarter\n" | |
1407 "BAD quaters\nGOOD quarters\n" | |
1408 "BAD quesion\nGOOD question\n" | |
1409 "BAD quesions\nGOOD questions\n" | |
1410 "BAD questioms\nGOOD questions\n" | |
1411 "BAD questiosn\nGOOD questions\n" | |
1412 "BAD questoin\nGOOD question\n" | |
1413 "BAD quetion\nGOOD question\n" | |
1414 "BAD quetions\nGOOD questions\n" | |
1415 "BAD r\nGOOD are\n" | |
1416 "BAD raeson\nGOOD reason\n" | |
1417 "BAD realyl\nGOOD really\n" | |
1418 "BAD reccomend\nGOOD recommend\n" | |
1419 "BAD reccommend\nGOOD recommend\n" | |
1420 "BAD receieve\nGOOD receive\n" | |
1421 "BAD recieve\nGOOD receive\n" | |
1422 "BAD recieved\nGOOD received\n" | |
1423 "BAD recieving\nGOOD receiving\n" | |
1424 "BAD recomend\nGOOD recommend\n" | |
1425 "BAD recomendation\nGOOD recommendation\n" | |
1426 "BAD recomendations\nGOOD recommendations\n" | |
1427 "BAD recomended\nGOOD recommended\n" | |
1428 "BAD reconize\nGOOD recognize\n" | |
1429 "BAD recrod\nGOOD record\n" | |
1430 "BAD rediculous\nGOOD ridiculous\n" | |
1431 "BAD rediculus\nGOOD ridiculous\n" | |
1432 "BAD reguard\nGOOD regard\n" | |
1433 "BAD religous\nGOOD religious\n" | |
1434 "BAD reluctent\nGOOD reluctant\n" | |
1435 "BAD remeber\nGOOD remember\n" | |
1436 "BAD reommend\nGOOD recommend\n" | |
1437 "BAD representativs\nGOOD representatives\n" | |
1438 "BAD representives\nGOOD representatives\n" | |
1439 "BAD represetned\nGOOD represented\n" | |
1440 "BAD represnt\nGOOD represent\n" | |
1441 "BAD reserach\nGOOD research\n" | |
1442 "BAD resollution\nGOOD resolution\n" | |
1443 "BAD resorces\nGOOD resources\n" | |
1444 "BAD respomd\nGOOD respond\n" | |
1445 "BAD respomse\nGOOD response\n" | |
1446 "BAD responce\nGOOD response\n" | |
1447 "BAD responsability\nGOOD responsibility\n" | |
1448 "BAD responsable\nGOOD responsible\n" | |
1449 "BAD responsibile\nGOOD responsible\n" | |
1450 "BAD responsiblity\nGOOD responsibility\n" | |
1451 "BAD restaraunt\nGOOD restaurant\n" | |
1452 "BAD restuarant\nGOOD restaurant\n" | |
1453 "BAD reult\nGOOD result\n" | |
1454 "BAD reveiw\nGOOD review\n" | |
1455 "BAD reveiwing\nGOOD reviewing\n" | |
1456 "BAD rumers\nGOOD rumors\n" | |
1457 "BAD rwite\nGOOD write\n" | |
1458 "BAD rythm\nGOOD rhythm\n" | |
1459 "BAD saidhe\nGOOD said he\n" | |
1460 "BAD saidit\nGOOD said it\n" | |
1461 "BAD saidthat\nGOOD said that\n" | |
1462 "BAD saidthe\nGOOD said the\n" | |
1463 "COMPLETE 0\nBAD saidt he \nGOOD said the \n" | |
1464 "BAD sandwhich\nGOOD sandwich\n" | |
1465 "BAD sandwitch\nGOOD sandwich\n" | |
1466 "BAD saturday\nGOOD Saturday\n" | |
1467 "BAD scedule\nGOOD schedule\n" | |
1468 "BAD sceduled\nGOOD scheduled\n" | |
1469 "BAD seance\nGOOD s\303\251ance\n" | |
1470 "BAD secratary\nGOOD secretary\n" | |
1471 "BAD sectino\nGOOD section\n" | |
1472 "BAD seh\nGOOD she\n" | |
1473 "BAD selectoin\nGOOD selection\n" | |
1474 "BAD sence\nGOOD sense\n" | |
1475 "BAD sentance\nGOOD sentence\n" | |
1476 "BAD separeate\nGOOD separate\n" | |
1477 "BAD seperate\nGOOD separate\n" | |
1478 "BAD sercumstances\nGOOD circumstances\n" | |
1479 "BAD shcool\nGOOD school\n" | |
1480 "COMPLETE 0\nBAD she;d \nGOOD she'd \n" | |
1481 "COMPLETE 0\nBAD she;ll \nGOOD she'll \n" | |
1482 "BAD shes\nGOOD she's\n" | |
1483 "COMPLETE 0\nBAD she;s \nGOOD she's \n" | |
1484 "BAD shesaid\nGOOD she said\n" | |
1485 "BAD shineing\nGOOD shining\n" | |
1486 "BAD shiped\nGOOD shipped\n" | |
1487 "BAD shoudl\nGOOD should\n" | |
1488 "COMPLETE 0\nBAD shoudln't \nGOOD shouldn't \n" | |
1489 "BAD shouldent\nGOOD shouldn't\n" | |
1490 "BAD shouldnt\nGOOD shouldn't\n" | |
1491 "COMPLETE 0\nBAD shouldn;t \nGOOD shouldn't \n" | |
1492 "COMPLETE 0\nBAD should of been\nGOOD should have been\n" | |
1493 "COMPLETE 0\nBAD should of had\nGOOD should have had\n" | |
1494 "BAD shouldve\nGOOD should've\n" | |
1495 "BAD showinf\nGOOD showing\n" | |
1496 "BAD signifacnt\nGOOD significant\n" | |
1497 "BAD simalar\nGOOD similar\n" | |
1498 "BAD similiar\nGOOD similar\n" | |
1499 "BAD simpyl\nGOOD simply\n" | |
1500 "BAD sincerly\nGOOD sincerely\n" | |
1501 "BAD sitll\nGOOD still\n" | |
1502 "BAD smae\nGOOD same\n" | |
1503 "BAD smoe\nGOOD some\n" | |
1504 "BAD soem\nGOOD some\n" | |
1505 "BAD sohw\nGOOD show\n" | |
1506 "BAD soical\nGOOD social\n" | |
1507 "BAD some1\nGOOD someone\n" | |
1508 "BAD somethign\nGOOD something\n" | |
1509 "BAD someting\nGOOD something\n" | |
1510 "BAD somewaht\nGOOD somewhat\n" | |
1511 "BAD somthing\nGOOD something\n" | |
1512 "BAD somtimes\nGOOD sometimes\n" | |
1513 "COMPLETE 0\nBAD sot hat \nGOOD so that \n" | |
1514 "BAD soudn\nGOOD sound\n" | |
1515 "BAD soudns\nGOOD sounds\n" | |
1516 "BAD speach\nGOOD speech\n" | |
1517 "BAD specificaly\nGOOD specifically\n" | |
1518 "BAD specificalyl\nGOOD specifically\n" | |
1519 "BAD spelt\nGOOD spelled\n" | |
1520 "BAD sry\nGOOD sorry\n" | |
1521 "COMPLETE 0\nBAD state of the ark\nGOOD state of the art\n" | |
1522 "BAD statment\nGOOD statement\n" | |
1523 "BAD statments\nGOOD statements\n" | |
1524 "BAD stnad\nGOOD stand\n" | |
1525 "BAD stopry\nGOOD story\n" | |
1526 "BAD stoyr\nGOOD story\n" | |
1527 "BAD stpo\nGOOD stop\n" | |
1528 "BAD strentgh\nGOOD strength\n" | |
1529 "BAD stroy\nGOOD story\n" | |
1530 "BAD struggel\nGOOD struggle\n" | |
1531 "BAD strugle\nGOOD struggle\n" | |
1532 "BAD studnet\nGOOD student\n" | |
1533 "BAD successfull\nGOOD successful\n" | |
1534 "BAD successfuly\nGOOD successfully\n" | |
1535 "BAD successfulyl\nGOOD successfully\n" | |
1536 "BAD sucess\nGOOD success\n" | |
1537 "BAD sucessfull\nGOOD successful\n" | |
1538 "BAD sufficiant\nGOOD sufficient\n" | |
1539 "BAD sum1\nGOOD someone\n" | |
1540 "BAD sunday\nGOOD Sunday\n" | |
1541 "BAD suposed\nGOOD supposed\n" | |
1542 "BAD supposably\nGOOD supposedly\n" | |
1543 "BAD suppossed\nGOOD supposed\n" | |
1544 "BAD suprise\nGOOD surprise\n" | |
1545 "BAD suprised\nGOOD surprised\n" | |
1546 "BAD sux\nGOOD sucks\n" | |
1547 "BAD swiming\nGOOD swimming\n" | |
1548 "BAD tahn\nGOOD than\n" | |
1549 "BAD taht\nGOOD that\n" | |
1550 "COMPLETE 0\nBAD take it for granite\nGOOD take it for granted\n" | |
1551 "COMPLETE 0\nBAD taken for granite\nGOOD taken for granted\n" | |
1552 "BAD talekd\nGOOD talked\n" | |
1553 "BAD talkign\nGOOD talking\n" | |
1554 "BAD tath\nGOOD that\n" | |
1555 "BAD tecnical\nGOOD technical\n" | |
1556 "BAD teh\nGOOD the\n" | |
1557 "BAD tehy\nGOOD they\n" | |
1558 "COMPLETE 0\nBAD tellt he \nGOOD tell the \n" | |
1559 "BAD termoil\nGOOD turmoil\n" | |
1560 "BAD tets\nGOOD test\n" | |
1561 "BAD tghe\nGOOD the\n" | |
1562 "BAD tghis\nGOOD this\n" | |
1563 "BAD thansk\nGOOD thanks\n" | |
1564 "BAD thanx\nGOOD thanks\n" | |
1565 "BAD thats\nGOOD that's\n" | |
1566 "BAD thatthe\nGOOD that the\n" | |
1567 "COMPLETE 0\nBAD thatt he \nGOOD that the \n" | |
1568 "BAD thecompany\nGOOD the company\n" | |
1569 "BAD thefirst\nGOOD the first\n" | |
1570 "BAD thegovernment\nGOOD the government\n" | |
1571 "COMPLETE 0\nBAD their are \nGOOD there are \n" | |
1572 "COMPLETE 0\nBAD their aren't \nGOOD there aren't \n" | |
1573 "COMPLETE 0\nBAD their is \nGOOD there is \n" | |
1574 "BAD themself\nGOOD themselves\n" | |
1575 "BAD themselfs\nGOOD themselves\n" | |
1576 "BAD thenew\nGOOD the new\n" | |
1577 "BAD theres\nGOOD there's\n" | |
1578 "COMPLETE 0\nBAD there's is \nGOOD theirs is \n" | |
1579 "COMPLETE 0\nBAD there's isn't \nGOOD theirs isn't \n" | |
1580 "BAD theri\nGOOD their\n" | |
1581 "BAD thesame\nGOOD the same\n" | |
1582 "BAD thetwo\nGOOD the two\n" | |
1583 "BAD theyd\nGOOD they'd\n" | |
1584 "COMPLETE 0\nBAD they;d \nGOOD they'd \n" | |
1585 "COMPLETE 0\nBAD they;l \nGOOD they'll \n" | |
1586 "BAD theyll\nGOOD they'll\n" | |
1587 "COMPLETE 0\nBAD they;ll \nGOOD they'll \n" | |
1588 "COMPLETE 0\nBAD they;r \nGOOD they're \n" | |
1589 "COMPLETE 0\nBAD theyre \nGOOD they're \n" | |
1590 "COMPLETE 0\nBAD they;re \nGOOD they're \n" | |
1591 "COMPLETE 0\nBAD they're are \nGOOD there are \n" | |
1592 "COMPLETE 0\nBAD they're is \nGOOD there is \n" | |
1593 "COMPLETE 0\nBAD they;v \nGOOD they've \n" | |
1594 "BAD theyve\nGOOD they've\n" | |
1595 "COMPLETE 0\nBAD they;ve \nGOOD they've \n" | |
1596 "BAD thgat\nGOOD that\n" | |
1597 "BAD thge\nGOOD the\n" | |
1598 "BAD thier\nGOOD their \n" | |
1599 "BAD thigsn\nGOOD things\n" | |
1600 "BAD thisyear\nGOOD this year\n" | |
1601 "BAD thme\nGOOD them\n" | |
1602 "BAD thna\nGOOD than\n" | |
1603 "BAD thne\nGOOD then\n" | |
1604 "BAD thnig\nGOOD thing\n" | |
1605 "BAD thnigs\nGOOD things\n" | |
1606 "BAD tho\nGOOD though\n" | |
1607 "BAD threatend\nGOOD threatened\n" | |
1608 "BAD thsi\nGOOD this\n" | |
1609 "BAD thsoe\nGOOD those\n" | |
1610 "BAD thta\nGOOD that\n" | |
1611 "BAD thursday\nGOOD Thursday\n" | |
1612 "BAD thx\nGOOD thanks\n" | |
1613 "BAD tihs\nGOOD this\n" | |
1614 "BAD timne\nGOOD time\n" | |
1615 "BAD tiogether\nGOOD together\n" | |
1616 "BAD tje\nGOOD the\n" | |
1617 "BAD tjhe\nGOOD the\n" | |
1618 "BAD tkae\nGOOD take\n" | |
1619 "BAD tkaes\nGOOD takes\n" | |
1620 "BAD tkaing\nGOOD taking\n" | |
1621 "BAD tlaking\nGOOD talking\n" | |
1622 "BAD tnx\nGOOD thanks\n" | |
1623 "BAD todya\nGOOD today\n" | |
1624 "BAD togehter\nGOOD together\n" | |
1625 "COMPLETE 0\nBAD toldt he \nGOOD told the \n" | |
1626 "BAD tomorow\nGOOD tomorrow\n" | |
1627 "BAD tongiht\nGOOD tonight\n" | |
1628 "BAD tonihgt\nGOOD tonight\n" | |
1629 "BAD tonite\nGOOD tonight\n" | |
1630 "BAD totaly\nGOOD totally\n" | |
1631 "BAD totalyl\nGOOD totally\n" | |
1632 "BAD tothe\nGOOD to the\n" | |
1633 "COMPLETE 0\nBAD tot he \nGOOD to the \n" | |
1634 "BAD touche\nGOOD touch\303\251\n" | |
1635 "BAD towrad\nGOOD toward\n" | |
1636 "BAD traditionalyl\nGOOD traditionally\n" | |
1637 "BAD transfered\nGOOD transferred\n" | |
1638 "BAD truely\nGOOD truly\n" | |
1639 "BAD truley\nGOOD truly\n" | |
1640 "BAD tryed\nGOOD tried\n" | |
1641 "BAD tthe\nGOOD the\n" | |
1642 "BAD tuesday\nGOOD Tuesday\n" | |
1643 "BAD tyhat\nGOOD that\n" | |
1644 "BAD tyhe\nGOOD the\n" | |
1645 "BAD u\nGOOD you\n" | |
1646 "BAD udnerstand\nGOOD understand\n" | |
1647 "BAD understnad\nGOOD understand\n" | |
1648 "COMPLETE 0\nBAD undert he \nGOOD under the \n" | |
1649 "BAD unforseen\nGOOD unforeseen\n" | |
1650 "BAD UnitedStates\nGOOD United States\n" | |
1651 "BAD unliek\nGOOD unlike\n" | |
1652 "BAD unpleasently\nGOOD unpleasantly\n" | |
1653 "BAD untill\nGOOD until\n" | |
1654 "BAD untilll\nGOOD until\n" | |
1655 "BAD ur\nGOOD you are\n" | |
1656 "BAD useing\nGOOD using\n" | |
1657 "BAD usualyl\nGOOD usually\n" | |
1658 "BAD veyr\nGOOD very\n" | |
1659 "BAD virtualyl\nGOOD virtually\n" | |
1660 "BAD visavis\nGOOD vis-a-vis\n" | |
1661 "COMPLETE 0\nBAD vis-a-vis\nGOOD vis-\303\240-vis\n" | |
1662 "BAD vrey\nGOOD very\n" | |
1663 "BAD vulnerible\nGOOD vulnerable\n" | |
1664 "BAD waht\nGOOD what\n" | |
1665 "BAD warrent\nGOOD warrant\n" | |
1666 "COMPLETE 0\nBAD wa snot \nGOOD was not \n" | |
1667 "COMPLETE 0\nBAD wasnt \nGOOD wasn't \n" | |
1668 "COMPLETE 0\nBAD wasn;t \nGOOD wasn't \n" | |
1669 "BAD wat\nGOOD what\n" | |
1670 "BAD watn\nGOOD want\n" | |
1671 "COMPLETE 0\nBAD we;d \nGOOD we'd \n" | |
1672 "BAD wednesday\nGOOD Wednesday\n" | |
1673 "BAD wehn\nGOOD when\n" | |
1674 "COMPLETE 0\nBAD we'l \nGOOD we'll \n" | |
1675 "COMPLETE 0\nBAD we;ll \nGOOD we'll \n" | |
1676 "COMPLETE 0\nBAD we;re \nGOOD we're \n" | |
1677 "BAD werent\nGOOD weren't\n" | |
1678 "COMPLETE 0\nBAD weren;t \nGOOD weren't \n" | |
1679 "COMPLETE 0\nBAD wern't \nGOOD weren't \n" | |
1680 "BAD werre\nGOOD were\n" | |
1681 "BAD weve\nGOOD we've\n" | |
1682 "COMPLETE 0\nBAD we;ve \nGOOD we've \n" | |
1683 "BAD whats\nGOOD what's\n" | |
1684 "COMPLETE 0\nBAD what;s \nGOOD what's \n" | |
1685 "BAD whcih\nGOOD which\n" | |
1686 "COMPLETE 0\nBAD whent he \nGOOD when the \n" | |
1687 "BAD wheres\nGOOD where's\n" | |
1688 "COMPLETE 0\nBAD where;s \nGOOD where's \n" | |
1689 "BAD wherre\nGOOD where\n" | |
1690 "BAD whic\nGOOD which\n" | |
1691 "COMPLETE 0\nBAD whicht he \nGOOD which the \n" | |
1692 "BAD whihc\nGOOD which\n" | |
1693 "BAD wholl\nGOOD who'll\n" | |
1694 "BAD whos\nGOOD who's\n" | |
1695 "COMPLETE 0\nBAD who;s \nGOOD who's \n" | |
1696 "BAD whove\nGOOD who've\n" | |
1697 "COMPLETE 0\nBAD who;ve \nGOOD who've \n" | |
1698 "BAD whta\nGOOD what\n" | |
1699 "BAD whys\nGOOD why's\n" | |
1700 "BAD wief\nGOOD wife\n" | |
1701 "BAD wierd\nGOOD weird\n" | |
1702 "BAD wihch\nGOOD which\n" | |
1703 "BAD wiht\nGOOD with\n" | |
1704 "BAD willbe\nGOOD will be\n" | |
1705 "COMPLETE 0\nBAD will of been\nGOOD will have been\n" | |
1706 "COMPLETE 0\nBAD will of had\nGOOD will have had\n" | |
1707 "BAD windoes\nGOOD windows\n" | |
1708 "BAD witha\nGOOD with a\n" | |
1709 "BAD withdrawl\nGOOD withdrawal\n" | |
1710 "BAD withe\nGOOD with\n" | |
1711 "COMPLETE 0\nBAD withthe \nGOOD with the \n" | |
1712 "BAD witht he\nGOOD with the\n" | |
1713 "BAD wiull\nGOOD will\n" | |
1714 "BAD wnat\nGOOD want\n" | |
1715 "BAD wnated\nGOOD wanted\n" | |
1716 "BAD wnats\nGOOD wants\n" | |
1717 "BAD woh\nGOOD who\n" | |
1718 "BAD wohle\nGOOD whole\n" | |
1719 "BAD wokr\nGOOD work\n" | |
1720 "BAD wont\nGOOD won't\n" | |
1721 "COMPLETE 0\nBAD wo'nt \nGOOD won't \n" | |
1722 "COMPLETE 0\nBAD won;t \nGOOD won't \n" | |
1723 "BAD woudl\nGOOD would\n" | |
1724 "COMPLETE 0\nBAD woudln't \nGOOD wouldn't \n" | |
1725 "BAD wouldbe\nGOOD would be\n" | |
1726 "BAD wouldnt\nGOOD wouldn't\n" | |
1727 "COMPLETE 0\nBAD wouldn;t \nGOOD wouldn't \n" | |
1728 "COMPLETE 0\nBAD would of been\nGOOD would have been\n" | |
1729 "COMPLETE 0\nBAD would of had\nGOOD would have had\n" | |
1730 "BAD wouldve\nGOOD would've\n" | |
1731 "BAD wriet\nGOOD write\n" | |
1732 "BAD writting\nGOOD writing\n" | |
1733 "BAD wrod\nGOOD word\n" | |
1734 "BAD wroet\nGOOD wrote\n" | |
1735 "BAD wroking\nGOOD working\n" | |
1736 "BAD wtih\nGOOD with\n" | |
1737 "BAD wuould\nGOOD would\n" | |
1738 "BAD wut\nGOOD what\n" | |
1739 "BAD wya\nGOOD way\n" | |
1740 "BAD y\nGOOD why\n" | |
1741 "BAD yeh\nGOOD yeah\n" | |
1742 "BAD yera\nGOOD year\n" | |
1743 "BAD yeras\nGOOD years\n" | |
1744 "BAD yersa\nGOOD years\n" | |
1745 "BAD yoiu\nGOOD you\n" | |
1746 "BAD youare\nGOOD you are\n" | |
1747 "BAD youd\nGOOD you'd\n" | |
1748 "COMPLETE 0\nBAD you;d \nGOOD you'd \n" | |
1749 "BAD youll\nGOOD you'll\n" | |
1750 "COMPLETE 0\nBAD your a \nGOOD you're a \n" | |
1751 "COMPLETE 0\nBAD your an \nGOOD you're an \n" | |
1752 "BAD youre\nGOOD you're\n" | |
1753 "COMPLETE 0\nBAD you;re \nGOOD you're \n" | |
1754 "COMPLETE 0\nBAD you're own \nGOOD your own \n" | |
1755 "COMPLETE 0\nBAD your her \nGOOD you're her \n" | |
1756 "COMPLETE 0\nBAD your here \nGOOD you're here \n" | |
1757 "COMPLETE 0\nBAD your his \nGOOD you're his \n" | |
1758 "COMPLETE 0\nBAD your my \nGOOD you're my \n" | |
1759 "COMPLETE 0\nBAD your the \nGOOD you're the \n" | |
1760 "COMPLETE 0\nBAD your their \nGOOD you're their \n" | |
1761 "COMPLETE 0\nBAD your your \nGOOD you're your \n" | |
1762 "BAD youve\nGOOD you've\n" | |
1763 "COMPLETE 0\nBAD you;ve \nGOOD you've \n" | |
1764 "BAD ytou\nGOOD you\n" | |
1765 "BAD yuo\nGOOD you\n" | |
1766 "BAD yuor\nGOOD your\n"; | |
1767 gchar *buf; | |
1768 gchar *ibuf; | |
1769 GHashTable *hashes; | |
1770 char bad[82] = ""; | |
1771 char good[256] = ""; | |
1772 int pnt = 0; | |
1773 gsize size; | |
1774 gboolean complete = TRUE; | |
1775 gboolean case_sensitive = FALSE; | |
1776 | |
1777 buf = g_build_filename(gaim_user_dir(), "dict", NULL); | |
1778 g_file_get_contents(buf, &ibuf, &size, NULL); | |
1779 g_free(buf); | |
1780 if (!ibuf) { | |
1781 ibuf = g_strdup(defaultconf); | |
1782 size = strlen(defaultconf); | |
1783 } | |
1784 | |
1785 model = gtk_list_store_new((gint)N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN); | |
1786 hashes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); | |
1787 | |
1788 while (buf_get_line(ibuf, &buf, &pnt, size)) { | |
1789 if (*buf != '#') { | |
1790 if (!strncasecmp(buf, "BAD ", 4)) | |
1791 { | |
1792 strncpy(bad, buf + 4, 81); | |
1793 } | |
1794 else if(!strncasecmp(buf, "CASE ", 5)) | |
1795 { | |
1796 case_sensitive = *(buf+5) == '0' ? FALSE : TRUE; | |
1797 } | |
1798 else if(!strncasecmp(buf, "COMPLETE ", 9)) | |
1799 { | |
1800 complete = *(buf+9) == '0' ? FALSE : TRUE; | |
1801 } | |
1802 else if (!strncasecmp(buf, "GOOD ", 5)) | |
1803 { | |
1804 strncpy(good, buf + 5, 255); | |
1805 | |
1806 if (*bad && *good && g_hash_table_lookup(hashes, bad) == NULL) { | |
1807 GtkTreeIter iter; | |
1808 | |
1809 /* We don't actually need to store the good string, since this | |
1810 * hash is just being used to eliminate duplicate bad strings. | |
1811 * The value has to be non-NULL so the lookup above will work. | |
1812 */ | |
1813 g_hash_table_insert(hashes, g_strdup(bad), GINT_TO_POINTER(1)); | |
1814 | |
1815 if (!complete) | |
1816 case_sensitive = TRUE; | |
1817 | |
1818 gtk_list_store_append(model, &iter); | |
1819 gtk_list_store_set(model, &iter, | |
1820 BAD_COLUMN, bad, | |
1821 GOOD_COLUMN, good, | |
1822 WORD_ONLY_COLUMN, complete, | |
1823 CASE_SENSITIVE_COLUMN, case_sensitive, | |
1824 -1); | |
1825 } | |
1826 bad[0] = '\0'; | |
1827 complete = TRUE; | |
1828 case_sensitive = FALSE; | |
1829 } | |
1830 } | |
1831 } | |
1832 g_free(ibuf); | |
1833 g_hash_table_destroy(hashes); | |
1834 | |
1835 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model), | |
1836 0, GTK_SORT_ASCENDING); | |
1837 } | |
1838 | |
1839 static GtkWidget *tree; | |
1840 static GtkWidget *bad_entry; | |
1841 static GtkWidget *good_entry; | |
1842 static GtkWidget *complete_toggle; | |
1843 static GtkWidget *case_toggle; | |
1844 | |
1845 static void save_list(void); | |
1846 | |
1847 static void on_edited(GtkCellRendererText *cellrenderertext, | |
1848 gchar *path, gchar *arg2, gpointer data) | |
1849 { | |
1850 GtkTreeIter iter; | |
1851 GValue val; | |
1852 | |
1853 if (arg2[0] == '\0') { | |
1854 gdk_beep(); | |
1855 return; | |
1856 } | |
1857 | |
1858 g_return_if_fail(gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(model), &iter, path)); | |
1859 val.g_type = 0; | |
1860 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, GPOINTER_TO_INT(data), &val); | |
1861 | |
1862 if (strcmp(arg2, g_value_get_string(&val))) { | |
1863 gtk_list_store_set(model, &iter, GPOINTER_TO_INT(data), arg2, -1); | |
1864 save_list(); | |
1865 } | |
1866 g_value_unset(&val); | |
1867 } | |
1868 | |
1869 | |
1870 static void word_only_toggled(GtkCellRendererToggle *cellrenderertoggle, | |
1871 gchar *path, gpointer data){ | |
1872 GtkTreeIter iter; | |
1873 gboolean enabled; | |
1874 | |
1875 g_return_if_fail(gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(model), &iter, path)); | |
1876 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, | |
1877 WORD_ONLY_COLUMN, &enabled, | |
1878 -1); | |
1879 | |
1880 gtk_list_store_set(GTK_LIST_STORE(model), &iter, | |
1881 WORD_ONLY_COLUMN, !enabled, | |
1882 -1); | |
1883 | |
1884 /* I want to be sure that the above change has happened to the GtkTreeView first. */ | |
1885 gtk_list_store_set(GTK_LIST_STORE(model), &iter, | |
1886 CASE_SENSITIVE_COLUMN, enabled, | |
1887 -1); | |
1888 | |
1889 save_list(); | |
1890 } | |
1891 | |
1892 static void case_sensitive_toggled(GtkCellRendererToggle *cellrenderertoggle, | |
1893 gchar *path, gpointer data){ | |
1894 GtkTreeIter iter; | |
1895 gboolean enabled; | |
1896 | |
1897 g_return_if_fail(gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(model), &iter, path)); | |
1898 | |
1899 /* Prevent the case sensitive column from changing on non-whole word replacements. | |
1900 * Ideally, the column would be set insensitive in the word_only_toggled callback. */ | |
1901 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, | |
1902 WORD_ONLY_COLUMN, &enabled, | |
1903 -1); | |
1904 if (!enabled) | |
1905 return; | |
1906 | |
1907 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, | |
1908 CASE_SENSITIVE_COLUMN, &enabled, | |
1909 -1); | |
1910 | |
1911 gtk_list_store_set(GTK_LIST_STORE(model), &iter, | |
1912 CASE_SENSITIVE_COLUMN, !enabled, | |
1913 -1); | |
1914 | |
1915 save_list(); | |
1916 } | |
1917 | |
1918 static void list_add_new() | |
1919 { | |
1920 GtkTreeIter iter; | |
1921 const char *word = gtk_entry_get_text(GTK_ENTRY(bad_entry)); | |
1922 gboolean case_sensitive = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(case_toggle)); | |
1923 | |
1924 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) { | |
1925 char *tmpword = g_utf8_casefold(word, -1); | |
1926 | |
1927 do { | |
1928 GValue bad_val; | |
1929 gboolean match; | |
1930 | |
1931 bad_val.g_type = 0; | |
1932 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, BAD_COLUMN, &bad_val); | |
1933 | |
1934 if (case_sensitive) | |
1935 { | |
1936 GValue case_sensitive_val; | |
1937 case_sensitive_val.g_type = 0; | |
1938 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, CASE_SENSITIVE_COLUMN, &case_sensitive_val); | |
1939 | |
1940 /* If they're both case-sensitive, then compare directly. | |
1941 * Otherwise, they overlap. */ | |
1942 if (g_value_get_boolean(&case_sensitive_val)) | |
1943 { | |
1944 match = !strcmp(g_value_get_string(&bad_val), word); | |
1945 } | |
1946 else | |
1947 { | |
1948 char *bad = g_utf8_casefold(g_value_get_string(&bad_val), -1); | |
1949 match = !strcmp(bad, tmpword); | |
1950 g_free(bad); | |
1951 } | |
1952 g_value_unset(&case_sensitive_val); | |
1953 } | |
1954 else | |
1955 { | |
1956 char *bad = g_utf8_casefold(g_value_get_string(&bad_val), -1); | |
1957 match = !strcmp(bad, tmpword); | |
1958 g_free(bad); | |
1959 } | |
1960 | |
1961 if (match) { | |
1962 g_value_unset(&bad_val); | |
1963 g_free(tmpword); | |
1964 | |
1965 gaim_notify_error(NULL, _("Duplicate Correction"), | |
1966 _("The specified word already exists in the correction list."), | |
1967 gtk_entry_get_text(GTK_ENTRY(bad_entry))); | |
1968 return; | |
1969 } | |
1970 | |
1971 g_value_unset(&bad_val); | |
1972 | |
1973 } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter)); | |
1974 | |
1975 g_free(tmpword); | |
1976 } | |
1977 | |
1978 | |
1979 gtk_list_store_append(model, &iter); | |
1980 gtk_list_store_set(model, &iter, | |
1981 BAD_COLUMN, word, | |
1982 GOOD_COLUMN, gtk_entry_get_text(GTK_ENTRY(good_entry)), | |
1983 WORD_ONLY_COLUMN, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(complete_toggle)), | |
1984 CASE_SENSITIVE_COLUMN, case_sensitive, | |
1985 -1); | |
1986 | |
1987 gtk_editable_delete_text(GTK_EDITABLE(bad_entry), 0, -1); | |
1988 gtk_editable_delete_text(GTK_EDITABLE(good_entry), 0, -1); | |
1989 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(complete_toggle), TRUE); | |
1990 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(case_toggle), FALSE); | |
1991 gtk_widget_grab_focus(bad_entry); | |
1992 | |
1993 save_list(); | |
1994 } | |
1995 | |
1996 static void add_selected_row_to_list(GtkTreeModel *model, GtkTreePath *path, | |
1997 GtkTreeIter *iter, gpointer data) | |
1998 { | |
1999 GtkTreeRowReference *row_reference; | |
2000 GSList **list = (GSList **)data; | |
2001 row_reference = gtk_tree_row_reference_new(model, path); | |
2002 *list = g_slist_prepend(*list, row_reference); | |
2003 } | |
2004 | |
2005 static void remove_row(void *data1, gpointer data2) | |
2006 { | |
2007 GtkTreeRowReference *row_reference; | |
2008 GtkTreePath *path; | |
2009 GtkTreeIter iter; | |
2010 | |
2011 row_reference = (GtkTreeRowReference *)data1; | |
2012 path = gtk_tree_row_reference_get_path(row_reference); | |
2013 | |
2014 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path)) | |
2015 gtk_list_store_remove(model, &iter); | |
2016 | |
2017 gtk_tree_path_free(path); | |
2018 gtk_tree_row_reference_free(row_reference); | |
2019 } | |
2020 | |
2021 static void list_delete() | |
2022 { | |
2023 GtkTreeSelection *sel; | |
2024 GSList *list = NULL; | |
2025 | |
2026 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)); | |
2027 gtk_tree_selection_selected_foreach(sel, add_selected_row_to_list, &list); | |
2028 | |
2029 g_slist_foreach(list, remove_row, NULL); | |
2030 g_slist_free(list); | |
2031 | |
2032 save_list(); | |
2033 } | |
2034 | |
2035 static void save_list() | |
2036 { | |
2037 GString *data; | |
2038 GtkTreeIter iter; | |
2039 | |
2040 data = g_string_new(""); | |
2041 | |
2042 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) { | |
2043 do { | |
2044 GValue val0; | |
2045 GValue val1; | |
2046 GValue val2; | |
2047 GValue val3; | |
2048 | |
2049 val0.g_type = 0; | |
2050 val1.g_type = 0; | |
2051 val2.g_type = 0; | |
2052 val3.g_type = 0; | |
2053 | |
2054 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, BAD_COLUMN, &val0); | |
2055 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, GOOD_COLUMN, &val1); | |
2056 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, WORD_ONLY_COLUMN, &val2); | |
2057 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, CASE_SENSITIVE_COLUMN, &val3); | |
2058 | |
2059 g_string_append_printf(data, "COMPLETE %d\nCASE %d\nBAD %s\nGOOD %s\n\n", | |
2060 g_value_get_boolean(&val2), | |
2061 g_value_get_boolean(&val3), | |
2062 g_value_get_string(&val0), | |
2063 g_value_get_string(&val1)); | |
2064 | |
2065 g_value_unset(&val0); | |
2066 g_value_unset(&val1); | |
2067 g_value_unset(&val2); | |
2068 g_value_unset(&val3); | |
2069 | |
2070 } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter)); | |
2071 } | |
2072 | |
2073 gaim_util_write_data_to_file("dict", data->str, -1); | |
2074 | |
2075 g_string_free(data, TRUE); | |
2076 } | |
2077 | |
2078 #if !GTK_CHECK_VERSION(2,2,0) | |
2079 static void | |
2080 count_selected_helper(GtkTreeModel *model, GtkTreePath *path, | |
2081 GtkTreeIter *iter, gpointer user_data) | |
2082 { | |
2083 (*(gint *)user_data)++; | |
2084 } | |
2085 #endif | |
2086 | |
2087 static void on_selection_changed(GtkTreeSelection *sel, | |
2088 gpointer data) | |
2089 { | |
2090 gint num_selected; | |
2091 #if GTK_CHECK_VERSION(2,2,0) | |
2092 num_selected = gtk_tree_selection_count_selected_rows(sel); | |
2093 #else | |
2094 gtk_tree_selection_selected_foreach(sel, count_selected_helper, &num_selected); | |
2095 #endif | |
2096 gtk_widget_set_sensitive((GtkWidget*)data, (num_selected > 0)); | |
2097 } | |
2098 | |
2099 static gboolean non_empty(const char *s) | |
2100 { | |
2101 while (*s && g_ascii_isspace(*s)) | |
2102 s++; | |
2103 return *s; | |
2104 } | |
2105 | |
2106 static void on_entry_changed(GtkEditable *editable, gpointer data) | |
2107 { | |
2108 gtk_widget_set_sensitive((GtkWidget*)data, | |
2109 non_empty(gtk_entry_get_text(GTK_ENTRY(bad_entry))) && | |
2110 non_empty(gtk_entry_get_text(GTK_ENTRY(good_entry)))); | |
2111 } | |
2112 | |
2113 /* | |
2114 * EXPORTED FUNCTIONS | |
2115 */ | |
2116 | |
2117 static gboolean | |
2118 plugin_load(GaimPlugin *plugin) | |
2119 { | |
2120 void *conv_handle = gaim_conversations_get_handle(); | |
2121 GList *convs; | |
2122 | |
2123 load_conf(); | |
2124 | |
2125 /* Attach to existing conversations */ | |
2126 for (convs = gaim_get_conversations(); convs != NULL; convs = convs->next) | |
2127 { | |
2128 spellchk_new_attach((GaimConversation *)convs->data); | |
2129 } | |
2130 | |
2131 gaim_signal_connect(conv_handle, "conversation-created", | |
2132 plugin, GAIM_CALLBACK(spellchk_new_attach), NULL); | |
2133 | |
2134 return TRUE; | |
2135 } | |
2136 | |
2137 static gboolean | |
2138 plugin_unload(GaimPlugin *plugin) | |
2139 { | |
2140 GList *convs; | |
2141 | |
2142 /* Detach from existing conversations */ | |
2143 for (convs = gaim_get_conversations(); convs != NULL; convs = convs->next) | |
2144 { | |
2145 GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION((GaimConversation *)convs->data); | |
2146 spellchk *spell = g_object_get_data(G_OBJECT(gtkconv->entry), SPELLCHK_OBJECT_KEY); | |
2147 | |
2148 g_signal_handlers_disconnect_by_func(gtkconv->entry, message_send_cb, spell); | |
2149 g_object_set_data(G_OBJECT(gtkconv->entry), SPELLCHK_OBJECT_KEY, NULL); | |
2150 } | |
2151 | |
2152 return TRUE; | |
2153 } | |
2154 | |
2155 static void whole_words_button_toggled(GtkToggleButton *complete_toggle, GtkToggleButton *case_toggle) | |
2156 { | |
2157 gboolean enabled = gtk_toggle_button_get_active(complete_toggle); | |
2158 | |
2159 gtk_toggle_button_set_active(case_toggle, !enabled); | |
2160 gtk_widget_set_sensitive(GTK_WIDGET(case_toggle), enabled); | |
2161 } | |
2162 | |
2163 static GtkWidget * | |
2164 get_config_frame(GaimPlugin *plugin) | |
2165 { | |
2166 GtkWidget *ret, *vbox, *win; | |
2167 GtkWidget *hbox, *label; | |
2168 GtkWidget *button; | |
2169 GtkSizeGroup *sg; | |
2170 GtkSizeGroup *sg2; | |
2171 GtkCellRenderer *renderer; | |
2172 GtkTreeViewColumn *column; | |
2173 GtkWidget *vbox2; | |
2174 GtkWidget *hbox2; | |
2175 GtkWidget *vbox3; | |
2176 | |
2177 ret = gtk_vbox_new(FALSE, GAIM_HIG_CAT_SPACE); | |
2178 gtk_container_set_border_width (GTK_CONTAINER(ret), GAIM_HIG_BORDER); | |
2179 | |
2180 vbox = gaim_gtk_make_frame(ret, _("Text Replacements")); | |
2181 gtk_container_set_border_width(GTK_CONTAINER(vbox), 4); | |
2182 gtk_widget_show(vbox); | |
2183 | |
2184 win = gtk_scrolled_window_new(0, 0); | |
2185 gtk_box_pack_start(GTK_BOX(vbox), win, TRUE, TRUE, 0); | |
2186 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(win), | |
2187 GTK_SHADOW_IN); | |
2188 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(win), | |
2189 GTK_POLICY_NEVER, | |
2190 GTK_POLICY_ALWAYS); | |
2191 gtk_widget_show(win); | |
2192 | |
2193 tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model)); | |
2194 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree), TRUE); | |
2195 gtk_widget_set_size_request(tree, -1, 200); | |
2196 | |
2197 renderer = gtk_cell_renderer_text_new(); | |
2198 g_object_set(G_OBJECT(renderer), | |
2199 "editable", TRUE, | |
2200 NULL); | |
2201 g_signal_connect(G_OBJECT(renderer), "edited", | |
2202 G_CALLBACK(on_edited), GINT_TO_POINTER(0)); | |
2203 column = gtk_tree_view_column_new_with_attributes(_("You type"), renderer, | |
2204 "text", BAD_COLUMN, | |
2205 NULL); | |
2206 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); | |
2207 gtk_tree_view_column_set_fixed_width(column, 150); | |
2208 gtk_tree_view_column_set_resizable(column, TRUE); | |
2209 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); | |
2210 | |
2211 renderer = gtk_cell_renderer_text_new(); | |
2212 g_object_set(G_OBJECT(renderer), | |
2213 "editable", TRUE, | |
2214 NULL); | |
2215 g_signal_connect(G_OBJECT(renderer), "edited", | |
2216 G_CALLBACK(on_edited), GINT_TO_POINTER(1)); | |
2217 column = gtk_tree_view_column_new_with_attributes(_("You send"), renderer, | |
2218 "text", GOOD_COLUMN, | |
2219 NULL); | |
2220 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); | |
2221 gtk_tree_view_column_set_fixed_width(column, 150); | |
2222 gtk_tree_view_column_set_resizable(column, TRUE); | |
2223 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); | |
2224 | |
2225 renderer = gtk_cell_renderer_toggle_new(); | |
2226 g_object_set(G_OBJECT(renderer), | |
2227 "activatable", TRUE, | |
2228 NULL); | |
2229 g_signal_connect(G_OBJECT(renderer), "toggled", | |
2230 G_CALLBACK(word_only_toggled), NULL); | |
2231 column = gtk_tree_view_column_new_with_attributes(_("Whole words only"), renderer, | |
2232 "active", WORD_ONLY_COLUMN, | |
2233 NULL); | |
2234 gtk_tree_view_column_set_resizable(column, TRUE); | |
2235 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); | |
2236 | |
2237 renderer = gtk_cell_renderer_toggle_new(); | |
2238 g_object_set(G_OBJECT(renderer), | |
2239 "activatable", TRUE, | |
2240 NULL); | |
2241 g_signal_connect(G_OBJECT(renderer), "toggled", | |
2242 G_CALLBACK(case_sensitive_toggled), NULL); | |
2243 column = gtk_tree_view_column_new_with_attributes(_("Case sensitive"), renderer, | |
2244 "active", CASE_SENSITIVE_COLUMN, | |
2245 NULL); | |
2246 gtk_tree_view_column_set_resizable(column, TRUE); | |
2247 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); | |
2248 | |
2249 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)), | |
2250 GTK_SELECTION_MULTIPLE); | |
2251 gtk_container_add(GTK_CONTAINER(win), tree); | |
2252 gtk_widget_show(tree); | |
2253 | |
2254 hbox = gtk_hbutton_box_new(); | |
2255 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); | |
2256 gtk_widget_show(hbox); | |
2257 | |
2258 button = gtk_button_new_from_stock(GTK_STOCK_DELETE); | |
2259 g_signal_connect(G_OBJECT(button), "clicked", | |
2260 G_CALLBACK(list_delete), NULL); | |
2261 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); | |
2262 gtk_widget_set_sensitive(button, FALSE); | |
2263 | |
2264 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree))), | |
2265 "changed", G_CALLBACK(on_selection_changed), button); | |
2266 | |
2267 gtk_widget_show(button); | |
2268 | |
2269 vbox = gaim_gtk_make_frame(ret, _("Add a new text replacement")); | |
2270 | |
2271 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE); | |
2272 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); | |
2273 gtk_widget_show(hbox); | |
2274 vbox2 = gtk_vbox_new(FALSE, GAIM_HIG_BOX_SPACE); | |
2275 gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 0); | |
2276 gtk_widget_show(vbox2); | |
2277 | |
2278 sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); | |
2279 sg2 = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); | |
2280 | |
2281 hbox2 = gtk_hbox_new(FALSE, 2); | |
2282 gtk_box_pack_start(GTK_BOX(vbox2), hbox2, FALSE, FALSE, 0); | |
2283 gtk_widget_show(hbox2); | |
2284 | |
2285 label = gtk_label_new_with_mnemonic(_("You _type:")); | |
2286 gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); | |
2287 gtk_size_group_add_widget(sg, label); | |
2288 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); | |
2289 | |
2290 bad_entry = gtk_entry_new(); | |
2291 /* Set a minimum size. Since they're in a size group, the other entry will match up. */ | |
2292 gtk_widget_set_size_request(bad_entry, 350, -1); | |
2293 gtk_box_pack_start(GTK_BOX(hbox2), bad_entry, TRUE, TRUE, 0); | |
2294 gtk_size_group_add_widget(sg2, bad_entry); | |
2295 gtk_label_set_mnemonic_widget(GTK_LABEL(label), bad_entry); | |
2296 gtk_widget_show(bad_entry); | |
2297 | |
2298 hbox2 = gtk_hbox_new(FALSE, 2); | |
2299 gtk_box_pack_start(GTK_BOX(vbox2), hbox2, FALSE, FALSE, 0); | |
2300 gtk_widget_show(hbox2); | |
2301 | |
2302 label = gtk_label_new_with_mnemonic(_("You _send:")); | |
2303 gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); | |
2304 gtk_size_group_add_widget(sg, label); | |
2305 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); | |
2306 | |
2307 good_entry = gtk_entry_new(); | |
2308 gtk_box_pack_start(GTK_BOX(hbox2), good_entry, TRUE, TRUE, 0); | |
2309 gtk_size_group_add_widget(sg2, good_entry); | |
2310 gtk_label_set_mnemonic_widget(GTK_LABEL(label), good_entry); | |
2311 gtk_widget_show(good_entry); | |
2312 | |
2313 /* Created here so it can be passed to whole_words_button_toggled. */ | |
2314 case_toggle = gtk_check_button_new_with_mnemonic(_("_Exact case match (uncheck for automatic case handling)")); | |
2315 | |
2316 complete_toggle = gtk_check_button_new_with_mnemonic(_("Only replace _whole words")); | |
2317 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(complete_toggle), TRUE); | |
2318 g_signal_connect(G_OBJECT(complete_toggle), "clicked", | |
2319 G_CALLBACK(whole_words_button_toggled), case_toggle); | |
2320 gtk_widget_show(complete_toggle); | |
2321 gtk_box_pack_start(GTK_BOX(vbox2), complete_toggle, FALSE, FALSE, 0); | |
2322 | |
2323 /* The button is created above so it can be passed to whole_words_button_toggled. */ | |
2324 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(case_toggle), FALSE); | |
2325 gtk_widget_show(case_toggle); | |
2326 gtk_box_pack_start(GTK_BOX(vbox2), case_toggle, FALSE, FALSE, 0); | |
2327 | |
2328 button = gtk_button_new_from_stock(GTK_STOCK_ADD); | |
2329 g_signal_connect(G_OBJECT(button), "clicked", | |
2330 G_CALLBACK(list_add_new), NULL); | |
2331 vbox3 = gtk_vbox_new(FALSE, 0); | |
2332 gtk_box_pack_start(GTK_BOX(hbox), vbox3, TRUE, FALSE, 0); | |
2333 gtk_widget_show(vbox3); | |
2334 gtk_box_pack_end(GTK_BOX(vbox3), button, FALSE, FALSE, 0); | |
2335 g_signal_connect(G_OBJECT(bad_entry), "changed", G_CALLBACK(on_entry_changed), button); | |
2336 g_signal_connect(G_OBJECT(good_entry), "changed", G_CALLBACK(on_entry_changed), button); | |
2337 gtk_widget_set_sensitive(button, FALSE); | |
2338 gtk_widget_show(button); | |
2339 | |
2340 #if 0 | |
2341 vbox = gaim_gtk_make_frame(ret, _("General Text Replacement Options")); | |
2342 gaim_gtk_prefs_checkbox(_("Enable replacement of last word on send"), | |
2343 "/plugins/gtk/spellchk/last_word_replace", vbox); | |
2344 #endif | |
2345 | |
2346 gtk_widget_show_all(ret); | |
2347 return ret; | |
2348 } | |
2349 | |
2350 static GaimGtkPluginUiInfo ui_info = | |
2351 { | |
2352 get_config_frame, | |
2353 0 /* page_num (Reserved) */ | |
2354 }; | |
2355 | |
2356 static GaimPluginInfo info = | |
2357 { | |
2358 GAIM_PLUGIN_MAGIC, | |
2359 GAIM_MAJOR_VERSION, | |
2360 GAIM_MINOR_VERSION, | |
2361 GAIM_PLUGIN_STANDARD, | |
2362 GAIM_GTK_PLUGIN_TYPE, | |
2363 0, | |
2364 NULL, | |
2365 GAIM_PRIORITY_DEFAULT, | |
2366 SPELLCHECK_PLUGIN_ID, | |
2367 N_("Text replacement"), | |
2368 VERSION, | |
2369 N_("Replaces text in outgoing messages according to user-defined rules."), | |
2370 N_("Replaces text in outgoing messages according to user-defined rules."), | |
2371 "Eric Warmenhoven <eric@warmenhoven.org>", | |
2372 GAIM_WEBSITE, | |
2373 plugin_load, | |
2374 plugin_unload, | |
2375 NULL, | |
2376 &ui_info, | |
2377 NULL, | |
2378 NULL, | |
2379 NULL | |
2380 }; | |
2381 | |
2382 static void | |
2383 init_plugin(GaimPlugin *plugin) | |
2384 { | |
2385 #if 0 | |
2386 gaim_prefs_add_none("/plugins"); | |
2387 gaim_prefs_add_none("/plugins/gtk"); | |
2388 gaim_prefs_add_none("/plugins/gtk/spellchk"); | |
2389 gaim_prefs_add_bool("/plugins/gtk/spellchk/last_word_replace", TRUE); | |
2390 #endif | |
2391 } | |
2392 | |
2393 GAIM_INIT_PLUGIN(spellcheck, init_plugin, info) |