comparison plugins/spellchk.c @ 10787:c932d96a7c69

[gaim-migrate @ 12428] " Autocorrect in gaim... um... sucks. The problem is that the correction only happens AFTER you send a message. This means that you don't actually know what message you are sending until it is sent. Horrible. My new patch works AS YOU TYPE with the following rules: * You must be typing, not pasting in text. If you paste in the and there is a rule to correct the to the, it won't be corrected. This is because it would be impossible to go back and check all the text. * Check whole words ONLY. Partial words don't count. * If the dictionary word has capital letters in it, match only words with that capitalization. (FPT -> FTP doesn't match ftp.) * If the dictionary word doesn't have capital letters, preserve the capitalization the user used. (The code assumes three possible capitalization schemes: ALLCAPS, lowercase, and Proper.) Unless the solution has capital letters. In that case, force the capitalization used in the solution. * A word may have quote characters in it and still be a word. * If the user immediately hits the backspace key after a correction, undo the correction." --xkan " This patch is based off xkahn's work available at: http://sf.net/support/tracker.php?aid=300235 Most of the changes are his. I just changed his formatting to match the rest of Gaim more closely. Also, I made a couple coding style changes. The two biggest changes I made were: 1) I added some hash stuff to load_config. This removes duplicates. 2) I imported my list of text replacement strings as the default list in addition to xkahn's list. My list consisted primarily of the autocorrect entries from my copy of OpenOffice.org Writer. There were a few things I've added by hand. (For those familiar with my comments in #gaim, this list does NOT include anything like a pwn -> own replacement. If people want to talk like that, I'm not going to stop them. This list should be useful to anyone.) I also fixed a memory leak in load_config. A GtkListStore stores its own copy of strings, so there is no need to g_strdup them when appending to the GtkListStore. When I get a chance, I need to make it give an error if you try to set a duplicate "You type" word in the preferences. Otherwise, this patch should take care of everything. I would recommend considering this patch over xkahn's because it's a direct superset of his patches. However, I want to be very clear that most of the changes in this patch are his and he deserves the credit for them. " --rlaager committer: Tailor Script <tailor@pidgin.im>
author Luke Schierer <lschiere@pidgin.im>
date Thu, 07 Apr 2005 14:35:25 +0000
parents 0f7452b1f777
children 9cf14a87eedc
comparison
equal deleted inserted replaced
10786:7638c282b1d3 10787:c932d96a7c69
4 */ 4 */
5 #include "internal.h" 5 #include "internal.h"
6 #include "gtkgaim.h" 6 #include "gtkgaim.h"
7 7
8 #include "debug.h" 8 #include "debug.h"
9 #include "notify.h"
9 #include "signals.h" 10 #include "signals.h"
10 #include "util.h" 11 #include "util.h"
11 #include "version.h" 12 #include "version.h"
12 13
13 #include "gtkplugin.h" 14 #include "gtkplugin.h"
20 #endif 21 #endif
21 #include <sys/types.h> 22 #include <sys/types.h>
22 #include <sys/stat.h> 23 #include <sys/stat.h>
23 24
24 #define SPELLCHECK_PLUGIN_ID "gtk-spellcheck" 25 #define SPELLCHECK_PLUGIN_ID "gtk-spellcheck"
26 #define SPELLCHK_OBJECT_KEY "spellchk"
25 27
26 enum { 28 enum {
27 BAD_COLUMN, 29 BAD_COLUMN,
28 GOOD_COLUMN, 30 GOOD_COLUMN,
29 N_COLUMNS 31 N_COLUMNS
30 }; 32 };
31 33
32 static int num_words(const char *); 34 struct _spellchk {
33 static int get_word(char *, int); 35 GtkTextView *view;
34 static char *have_word(char *, int); 36 GtkTextMark *mark_insert_start;
35 static void substitute(char **, int, int, const char *); 37 GtkTextMark *mark_insert_end;
38
39 gchar *word;
40 gboolean inserting;
41 gboolean ignore_correction;
42 gint pos;
43 };
44
45 typedef struct _spellchk spellchk;
46
36 static GtkListStore *model; 47 static GtkListStore *model;
37 48
38 static gboolean 49 static gboolean
39 substitute_words(GaimAccount *account, GaimConversation *conv, 50 is_word_uppercase(gchar *word)
40 char **message, void *data) 51 {
41 { 52 for (; word[0] != '\0'; word = g_utf8_find_next_char (word, NULL)) {
42 int i, l; 53 if (!g_unichar_isupper(g_utf8_get_char(word)) &&
43 int word; 54 !g_unichar_ispunct(g_utf8_get_char(word)))
44 char *tmp; 55 return FALSE;
45 56 }
46 if (message == NULL || *message == NULL) 57
58 return TRUE;
59 }
60
61 static gboolean
62 is_word_lowercase(gchar *word)
63 {
64 for (; word[0] != '\0'; word = g_utf8_find_next_char(word, NULL)) {
65 if (!g_unichar_islower(g_utf8_get_char(word)) &&
66 !g_unichar_ispunct(g_utf8_get_char(word)))
67 return FALSE;
68 }
69
70 return TRUE;
71 }
72
73 static gboolean
74 is_word_proper(gchar *word)
75 {
76 if (word[0] == '\0')
47 return FALSE; 77 return FALSE;
48 78
49 l = num_words(*message); 79 if (!g_unichar_isupper(g_utf8_get_char_validated(word, -1)))
50 for (i = 0; i < l; i++) { 80 return FALSE;
51 GtkTreeIter iter; 81
52 word = get_word(*message, i); 82 return is_word_lowercase(g_utf8_offset_to_pointer(word, 1));
53 if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) { 83 }
54 do { 84
55 GValue val0, val1; 85 static gchar *
56 const char *bad, *good; 86 make_word_proper(gchar *word)
57 memset(&val0, 0, sizeof(val0)); 87 {
58 memset(&val1, 0, sizeof(val1)); 88 gchar *state = g_utf8_strdown(word, -1);
59 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, 0, &val0); 89
60 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, 1, &val1); 90 state[0] = g_unichar_toupper(g_utf8_get_char(word));
61 tmp = have_word(*message, word); 91
62 bad = g_value_get_string(&val0); 92 return state;
63 good = g_value_get_string(&val1); 93 }
64 if (!strcmp(tmp, bad)) { 94
65 substitute(message, word, strlen(bad), 95 static gchar *
66 good); 96 substitute_word(gchar *word)
67 l += num_words(good) - num_words(bad); 97 {
68 i += num_words(good) - num_words(bad); 98 GtkTreeIter iter;
99 gchar *outword;
100 gchar *lowerword;
101
102 if (word == NULL)
103 return NULL;
104
105 lowerword = g_utf8_strdown(word, -1);
106
107 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) {
108 do {
109 GValue val0 = {0, };
110 GValue val1 = {0, };
111 char *bad;
112 char *good;
113 gchar *tmpbad;
114 gchar *tmpword;
115
116 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, 0, &val0);
117 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, 1, &val1);
118
119 bad = (char *) g_value_get_string(&val0);
120 good = (char *) g_value_get_string(&val1);
121
122 tmpbad = g_utf8_casefold(bad, -1);
123 tmpword = g_utf8_casefold(word, -1);
124
125 if (!strcmp(bad, lowerword) || (!is_word_lowercase(bad) && !strcmp(tmpbad, tmpword))) {
126 outword = g_strdup(good);
127
128 if (is_word_lowercase(bad) && is_word_lowercase(good)) {
129
130 if (is_word_uppercase (word)) {
131 char *tmp;
132 tmp = g_utf8_strup(outword, -1);
133 g_free(outword);
134 outword = tmp;
135 }
136
137 if (is_word_proper (word)) {
138 char *tmp;
139 tmp = make_word_proper(outword);
140 g_free(outword);
141 outword = tmp;
142 }
69 } 143 }
70 free(tmp); 144
71 g_value_unset(&val0); 145 g_value_unset(&val0);
72 g_value_unset(&val1); 146 g_value_unset(&val1);
73 } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter)); 147
148 g_free(tmpbad);
149 g_free(tmpword);
150
151 return outword;
152 }
153 g_value_unset(&val0);
154 g_value_unset(&val1);
155
156 g_free(tmpbad);
157 g_free(tmpword);
158
159 } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter));
160 }
161
162 return NULL;
163 }
164
165 static void
166 spellchk_free(spellchk *spell)
167 {
168 GtkTextBuffer *buffer;
169
170 buffer = gtk_text_view_get_buffer(spell->view);
171
172 g_signal_handlers_disconnect_matched(spell->view,
173 G_SIGNAL_MATCH_DATA,
174 0, 0, NULL, NULL,
175 spell);
176 g_signal_handlers_disconnect_matched(buffer,
177 G_SIGNAL_MATCH_DATA,
178 0, 0, NULL, NULL,
179 spell);
180 g_free(spell);
181 }
182
183 /* Pango doesn't know about the "'" character. Let's fix that. */
184 static gboolean
185 spellchk_inside_word(GtkTextIter *iter)
186 {
187 gboolean result;
188 gboolean output;
189
190 if (gtk_text_iter_inside_word (iter) == TRUE)
191 return TRUE;
192
193 if (gtk_text_iter_get_char(iter) == '\'') {
194 result = gtk_text_iter_backward_char(iter);
195 output = gtk_text_iter_inside_word(iter);
196
197 if (result)
198 gtk_text_iter_forward_char(iter);
199
200 return output;
201 }
202
203 return FALSE;
204
205 }
206
207 static gboolean
208 spellchk_backward_word_start(GtkTextIter *iter)
209 {
210 int output;
211 int result;
212
213 output = gtk_text_iter_backward_word_start(iter);
214
215 /* It didn't work... */
216 if (!output)
217 return FALSE;
218
219 while (spellchk_inside_word(iter)) {
220 result = gtk_text_iter_backward_char(iter);
221
222 /* We can't go backwards anymore? We're at the beginning of the word. */
223 if (!result)
224 return TRUE;
225
226 if (!spellchk_inside_word(iter)) {
227 gtk_text_iter_forward_char(iter);
228 return TRUE;
74 } 229 }
75 } 230
76 231 output = gtk_text_iter_backward_word_start(iter);
77 return FALSE; 232 if (!output)
78 } 233 return FALSE;
79 234 }
80 static int buf_get_line(char *ibuf, char **buf, int *position, int len) { 235
81 int pos = *position, spos = pos; 236 return TRUE;
237 }
238
239 static void
240 check_range(spellchk *spell, GtkTextBuffer *buffer,
241 GtkTextIter start, GtkTextIter end) {
242
243 gboolean result;
244 gchar *word;
245
246 /* We need to go backwords to find out if we are inside a word or not. */
247 gtk_text_iter_backward_char(&end);
248
249 if (spellchk_inside_word(&end)) {
250 gtk_text_iter_forward_char(&end);
251 return; /* We only pay attention to whole words. */
252 }
253
254 /* We could be in the middle of a whitespace block. Check for that. */
255 result = gtk_text_iter_backward_char(&end);
256
257 if (!spellchk_inside_word(&end)) {
258 if (result)
259 gtk_text_iter_forward_char(&end);
260 return;
261 }
262
263 if (result)
264 gtk_text_iter_forward_char(&end);
265
266 /* Move backwards to the beginning of the word. */
267 spellchk_backward_word_start(&start);
268
269 spell->word = g_strdup(gtk_text_iter_get_text(&start, &end));
270 if ((word = substitute_word(gtk_text_iter_get_text(&start, &end)))) {
271 GtkTextMark *mark;
272 GtkTextIter pos;
273
274 gtk_text_buffer_delete(buffer, &start, &end);
275 gtk_text_buffer_insert(buffer, &start, word, -1);
276
277 mark = gtk_text_buffer_get_insert(buffer);
278 gtk_text_buffer_get_iter_at_mark(buffer, &pos, mark);
279 spell->pos = gtk_text_iter_get_offset(&pos);
280
281 return;
282 }
283
284 /* g_free(spell->word); */
285 spell->word = NULL;
286
287 }
288
289 /* insertion works like this:
290 * - before the text is inserted, we mark the position in the buffer.
291 * - after the text is inserted, we see where our mark is and use that and
292 * the current position to check the entire range of inserted text.
293 *
294 * this may be overkill for the common case (inserting one character). */
295 static void
296 insert_text_before(GtkTextBuffer *buffer, GtkTextIter *iter,
297 gchar *text, gint len, spellchk *spell)
298 {
299 if (spell->inserting == TRUE)
300 return;
301
302 spell->inserting = TRUE;
303
304 if (spell->word) {
305 /* g_free(spell->word); */
306 spell->word = NULL;
307 }
308
309 gtk_text_buffer_move_mark(buffer, spell->mark_insert_start, iter);
310 }
311
312 static void
313 insert_text_after(GtkTextBuffer *buffer, GtkTextIter *iter,
314 gchar *text, gint len, spellchk *spell)
315 {
316 GtkTextIter start;
317
318 if (spell->ignore_correction) {
319 spell->ignore_correction = FALSE;
320 return;
321 }
322
323 /* we need to check a range of text. */
324 gtk_text_buffer_get_iter_at_mark(buffer, &start, spell->mark_insert_start);
325
326 if (len == 1)
327 check_range(spell, buffer, start, *iter);
328
329 gtk_text_buffer_move_mark(buffer, spell->mark_insert_end, iter);
330
331 spell->inserting = FALSE;
332
333 }
334
335 static void
336 delete_range_after(GtkTextBuffer *buffer,
337 GtkTextIter *start, GtkTextIter *end, spellchk *spell)
338 {
339 GtkTextIter start2, end2;
340 GtkTextMark *mark;
341 GtkTextIter pos;
342 gint place;
343
344 if (!spell->word)
345 return;
346
347 if (spell->inserting == TRUE)
348 return;
349
350
351 spell->inserting = TRUE;
352
353 mark = gtk_text_buffer_get_insert(buffer);
354 gtk_text_buffer_get_iter_at_mark(buffer, &pos, mark);
355 place = gtk_text_iter_get_offset(&pos);
356
357 if ((place + 1) != spell->pos) {
358 /* g_free(spell->word); */
359 spell->word = NULL;
360 return;
361 }
362
363 gtk_text_buffer_get_iter_at_mark(buffer, &start2, spell->mark_insert_start);
364 gtk_text_buffer_get_iter_at_mark(buffer, &end2, spell->mark_insert_end);
365
366 gtk_text_buffer_delete(buffer, &start2, &end2);
367 gtk_text_buffer_insert(buffer, &start2, spell->word, -1);
368 spell->ignore_correction = TRUE;
369
370 /* g_free(spell->word); */
371 spell->inserting = FALSE;
372 spell->word = NULL;
373 }
374
375 spellchk*
376 spellchk_new_attach(GaimConversation *c) {
377 spellchk *spell;
378 GtkTextBuffer *buffer;
379 GtkTextIter start, end;
380 GaimGtkConversation *gtkconv;
381 GtkTextView *view;
382
383 gtkconv = GAIM_GTK_CONVERSATION(c);
384
385 view = GTK_TEXT_VIEW(gtkconv->entry);
386
387 spell = g_object_get_data(G_OBJECT(view), SPELLCHK_OBJECT_KEY);
388 g_assert(spell == NULL);
389
390 /* attach to the widget */
391 spell = g_new0(spellchk, 1);
392 spell->view = view;
393
394 g_object_set_data(G_OBJECT(view), SPELLCHK_OBJECT_KEY, spell);
395
396 g_signal_connect_swapped(G_OBJECT(view), "destroy",
397 G_CALLBACK(spellchk_free), spell);
398
399 buffer = gtk_text_view_get_buffer(view);
400
401 /* we create the mark here, but we don't use it until text is
402 * inserted, so we don't really care where iter points. */
403 gtk_text_buffer_get_bounds(buffer, &start, &end);
404 spell->mark_insert_start = gtk_text_buffer_create_mark(buffer,
405 "spellchk-insert-start",
406 &start, TRUE);
407 spell->mark_insert_end = gtk_text_buffer_create_mark(buffer,
408 "spellchk-insert-end",
409 &start, TRUE);
410
411 g_signal_connect_after(G_OBJECT(buffer),
412 "delete-range",
413 G_CALLBACK(delete_range_after), spell);
414 g_signal_connect(G_OBJECT(buffer),
415 "insert-text",
416 G_CALLBACK(insert_text_before), spell);
417 g_signal_connect_after(G_OBJECT(buffer),
418 "insert-text",
419 G_CALLBACK(insert_text_after), spell);
420
421 return spell;
422 }
423
424 static int buf_get_line(char *ibuf, char **buf, int *position, int len)
425 {
426 int pos = *position;
427 int spos = pos;
82 428
83 if (pos == len) 429 if (pos == len)
84 return 0; 430 return 0;
85 431
86 while (ibuf[pos++] != '\n') { 432 while (ibuf[pos++] != '\n') {
87 if (pos == len) 433 if (pos == len)
88 return 0; 434 return 0;
89 } 435 }
436
90 pos--; 437 pos--;
438
91 ibuf[pos] = 0; 439 ibuf[pos] = 0;
92 *buf = &ibuf[spos]; 440 *buf = &ibuf[spos];
441
93 pos++; 442 pos++;
94 *position = pos; 443 *position = pos;
444
95 return 1; 445 return 1;
96 } 446 }
97 447
98 static void load_conf() { 448 static void load_conf()
99 const char * const defaultconf = "BAD r\nGOOD are\n\n" 449 {
100 "BAD u\nGOOD you\n\n" 450 /* There are things in this word list that the plugin can't yet correct.
101 "BAD teh\nGOOD the\n\n"; 451 * For example, BAD "words" with spaces in them. I've left them in the
102 gchar *buf, *ibuf; 452 * list because if the plugin is enhanced in the future, they'll be
103 char name[82]; 453 * useful corrections.
104 char cmd[256]; 454 *
455 * Corrections to change "...", "(c)", "(r)", and "(tm)" to their
456 * Unicode character equivalents were not added here even though
457 * they existed in the source list(s). This plugin doesn't yet
458 * handle them and it seems that even if it did, those corrections
459 * would be more trouble than they're worth.
460 *
461 * - Richard Laager (rlaager)
462 */
463 const char * const defaultconf =
464 "BAD abbout\nGOOD about\n"
465 "BAD abotu\nGOOD about\n"
466 "BAD abouta\nGOOD about a\n"
467 "BAD aboutit\nGOOD about it\n"
468 "BAD aboutthe\nGOOD about the\n"
469 "BAD abscence\nGOOD absence\n"
470 "BAD accesories\nGOOD accessories\n"
471 "BAD accidant\nGOOD accident\n"
472 "BAD accomodate\nGOOD accommodate\n"
473 "BAD accordingto\nGOOD according to\n"
474 "BAD accross\nGOOD across\n"
475 "BAD acheive\nGOOD achieve\n"
476 "BAD acheived\nGOOD achieved\n"
477 "BAD acheiving\nGOOD achieving\n"
478 "BAD acn\nGOOD can\n"
479 "BAD acommodate\nGOOD accommodate\n"
480 "BAD acomodate\nGOOD accommodate\n"
481 "BAD actualyl\nGOOD actually\n"
482 "BAD additinal\nGOOD additional\n"
483 "BAD addtional\nGOOD additional\n"
484 "BAD adequit\nGOOD adequate\n"
485 "BAD adequite\nGOOD adequate\n"
486 "BAD adn\nGOOD and\n"
487 "BAD advanage\nGOOD advantage\n"
488 "BAD affraid\nGOOD afraid\n"
489 "BAD afterthe\nGOOD after the\n"
490 "BAD againstt he\nGOOD against the\n"
491 "BAD aganist\nGOOD against\n"
492 "BAD aggresive\nGOOD aggressive\n"
493 "BAD agian\nGOOD again\n"
494 "BAD agreemeent\nGOOD agreement\n"
495 "BAD agreemeents\nGOOD agreements\n"
496 "BAD agreemnet\nGOOD agreement\n"
497 "BAD agreemnets\nGOOD agreements\n"
498 "BAD agressive\nGOOD aggressive\n"
499 "BAD agressiveness\nGOOD aggressiveness\n"
500 "BAD ahd\nGOOD had\n"
501 "BAD ahppen\nGOOD happen\n"
502 "BAD ahve\nGOOD have\n"
503 "BAD allready\nGOOD already\n"
504 "BAD allwasy\nGOOD always\n"
505 "BAD allwyas\nGOOD always\n"
506 "BAD almots\nGOOD almost\n"
507 "BAD almsot\nGOOD almost\n"
508 "BAD alomst\nGOOD almost\n"
509 "BAD alot\nGOOD a lot\n"
510 "BAD alraedy\nGOOD already\n"
511 "BAD alreayd\nGOOD already\n"
512 "BAD alreday\nGOOD already\n"
513 "BAD alwasy\nGOOD always\n"
514 "BAD alwats\nGOOD always\n"
515 "BAD alway\nGOOD always\n"
516 "BAD alwyas\nGOOD always\n"
517 "BAD amde\nGOOD made\n"
518 "BAD Ameria\nGOOD America\n"
519 "BAD amke\nGOOD make\n"
520 "BAD amkes\nGOOD makes\n"
521 "BAD anbd\nGOOD and\n"
522 "BAD andone\nGOOD and one\n"
523 "BAD andteh\nGOOD and the\n"
524 "BAD andthe\nGOOD and the\n"
525 "BAD andt he\nGOOD and the\n"
526 "BAD anothe\nGOOD another\n"
527 "BAD anual\nGOOD annual\n"
528 "BAD any1\nGOOD anyone\n"
529 "BAD apparant\nGOOD apparent\n"
530 "BAD apparrent\nGOOD apparent\n"
531 "BAD appearence\nGOOD appearance\n"
532 "BAD appeares\nGOOD appears\n"
533 "BAD applicaiton\nGOOD application\n"
534 "BAD applicaitons\nGOOD applications\n"
535 "BAD applyed\nGOOD applied\n"
536 "BAD appointiment\nGOOD appointment\n"
537 "BAD approrpiate\nGOOD appropriate\n"
538 "BAD approrpriate\nGOOD appropriate\n"
539 "BAD aquisition\nGOOD acquisition\n"
540 "BAD aquisitions\nGOOD acquisitions\n"
541 "BAD arent\nGOOD aren't\n"
542 "BAD aren;t\nGOOD aren't\n"
543 "BAD arguement\nGOOD argument\n"
544 "BAD arguements\nGOOD arguments\n"
545 "BAD arn't\nGOOD aren't\n"
546 "BAD arond\nGOOD around\n"
547 "BAD artical\nGOOD article\n"
548 "BAD articel\nGOOD article\n"
549 "BAD asdvertising\nGOOD advertising\n"
550 "BAD askt he\nGOOD ask the\n"
551 "BAD assistent\nGOOD assistant\n"
552 "BAD asthe\nGOOD as the\n"
553 "BAD atention\nGOOD attention\n"
554 "BAD atmospher\nGOOD atmosphere\n"
555 "BAD attentioin\nGOOD attention\n"
556 "BAD atthe\nGOOD at the\n"
557 "BAD audeince\nGOOD audience\n"
558 "BAD audiance\nGOOD audience\n"
559 "BAD availalbe\nGOOD available\n"
560 "BAD awya\nGOOD away\n"
561 "BAD aywa\nGOOD away\n"
562 "BAD b4\nGOOD before\n"
563 "BAD bakc\nGOOD back\n"
564 "BAD balence\nGOOD balance\n"
565 "BAD ballance\nGOOD balance\n"
566 "BAD baout\nGOOD about\n"
567 "BAD bcak\nGOOD back\n"
568 "BAD bcuz\nGOOD because\n"
569 "BAD beacuse\nGOOD because\n"
570 "BAD becasue\nGOOD because\n"
571 "BAD becaus\nGOOD because\n"
572 "BAD becausea\nGOOD because a\n"
573 "BAD becauseof\nGOOD because of\n"
574 "BAD becausethe\nGOOD because the\n"
575 "BAD becauseyou\nGOOD because you\n"
576 "BAD becomeing\nGOOD becoming\n"
577 "BAD becomming\nGOOD becoming\n"
578 "BAD becuase\nGOOD because\n"
579 "BAD becuse\nGOOD because\n"
580 "BAD befoer\nGOOD before\n"
581 "BAD beggining\nGOOD beginning\n"
582 "BAD begining\nGOOD beginning\n"
583 "BAD beginining\nGOOD beginning\n"
584 "BAD beleiev\nGOOD believe\n"
585 "BAD beleieve\nGOOD believe\n"
586 "BAD beleif\nGOOD belief\n"
587 "BAD beleive\nGOOD believe\n"
588 "BAD beleived\nGOOD believed\n"
589 "BAD beleives\nGOOD believes\n"
590 "BAD belive\nGOOD believe\n"
591 "BAD belived\nGOOD believed\n"
592 "BAD belives\nGOOD believes\n"
593 "BAD benifit\nGOOD benefit\n"
594 "BAD benifits\nGOOD benefits\n"
595 "BAD betwen\nGOOD between\n"
596 "BAD beutiful\nGOOD beautiful\n"
597 "BAD blase\nGOOD blasé\n"
598 "BAD boxs\nGOOD boxes\n"
599 "BAD brodcast\nGOOD broadcast\n"
600 "BAD butthe\nGOOD but the\n"
601 "BAD bve\nGOOD be\n"
602 "BAD byt he\nGOOD by the\n"
603 "BAD cafe\nGOOD café\n"
604 "BAD caharcter\nGOOD character\n"
605 "BAD calcullated\nGOOD calculated\n"
606 "BAD calulated\nGOOD calculated\n"
607 "BAD candidtae\nGOOD candidate\n"
608 "BAD candidtaes\nGOOD candidates\n"
609 "BAD cant\nGOOD can't\n"
610 "BAD can;t\nGOOD can't\n"
611 "BAD can't of been\nGOOD can't have been\n"
612 "BAD catagory\nGOOD category\n"
613 "BAD categiory\nGOOD category\n"
614 "BAD certian\nGOOD certain\n"
615 "BAD challange\nGOOD challenge\n"
616 "BAD challanges\nGOOD challenges\n"
617 "BAD chaneg\nGOOD change\n"
618 "BAD chanegs\nGOOD changes\n"
619 "BAD changable\nGOOD changeable\n"
620 "BAD changeing\nGOOD changing\n"
621 "BAD changng\nGOOD changing\n"
622 "BAD charachter\nGOOD character\n"
623 "BAD charachters\nGOOD characters\n"
624 "BAD charactor\nGOOD character\n"
625 "BAD charecter\nGOOD character\n"
626 "BAD charector\nGOOD character\n"
627 "BAD cheif\nGOOD chief\n"
628 "BAD chekc\nGOOD check\n"
629 "BAD chnage\nGOOD change\n"
630 "BAD cieling\nGOOD ceiling\n"
631 "BAD circut\nGOOD circuit\n"
632 "BAD claer\nGOOD clear\n"
633 "BAD claered\nGOOD cleared\n"
634 "BAD claerly\nGOOD clearly\n"
635 "BAD cliant\nGOOD client\n"
636 "BAD cliche\nGOOD cliché\n"
637 "BAD cna\nGOOD can\n"
638 "BAD colection\nGOOD collection\n"
639 "BAD comanies\nGOOD companies\n"
640 "BAD comany\nGOOD company\n"
641 "BAD comapnies\nGOOD companies\n"
642 "BAD comapny\nGOOD company\n"
643 "BAD combintation\nGOOD combination\n"
644 "BAD comited\nGOOD committed\n"
645 "BAD comittee\nGOOD committee\n"
646 "BAD commadn\nGOOD command\n"
647 "BAD comming\nGOOD coming\n"
648 "BAD commitee\nGOOD committee\n"
649 "BAD committe\nGOOD committee\n"
650 "BAD committment\nGOOD commitment\n"
651 "BAD committments\nGOOD commitments\n"
652 "BAD committy\nGOOD committee\n"
653 "BAD comntain\nGOOD contain\n"
654 "BAD comntains\nGOOD contains\n"
655 "BAD compair\nGOOD compare\n"
656 "BAD company;s\nGOOD company's\n"
657 "BAD competetive\nGOOD competitive\n"
658 "BAD compleated\nGOOD completed\n"
659 "BAD compleatly\nGOOD completely\n"
660 "BAD compleatness\nGOOD completeness\n"
661 "BAD completly\nGOOD completely\n"
662 "BAD completness\nGOOD completeness\n"
663 "BAD composate\nGOOD composite\n"
664 "BAD comtain\nGOOD contain\n"
665 "BAD comtains\nGOOD contains\n"
666 "BAD comunicate\nGOOD communicate\n"
667 "BAD comunity\nGOOD community\n"
668 "BAD condolances\nGOOD condolences\n"
669 "BAD conected\nGOOD connected\n"
670 "BAD conferance\nGOOD conference\n"
671 "BAD confirmmation\nGOOD confirmation\n"
672 "BAD considerit\nGOOD considerate\n"
673 "BAD considerite\nGOOD considerate\n"
674 "BAD consonent\nGOOD consonant\n"
675 "BAD conspiricy\nGOOD conspiracy\n"
676 "BAD consultent\nGOOD consultant\n"
677 "BAD convertable\nGOOD convertible\n"
678 "BAD cooparate\nGOOD cooperate\n"
679 "BAD cooporate\nGOOD cooperate\n"
680 "BAD corproation\nGOOD corporation\n"
681 "BAD corproations\nGOOD corporations\n"
682 "BAD corruptable\nGOOD corruptible\n"
683 "BAD cotten\nGOOD cotton\n"
684 "BAD coudl\nGOOD could\n"
685 "BAD coudln't\nGOOD couldn't\n"
686 "BAD coudn't\nGOOD couldn't\n"
687 "BAD couldnt\nGOOD couldn't\n"
688 "BAD couldn;t\nGOOD couldn't\n"
689 "BAD could of been\nGOOD could have been\n"
690 "BAD could of had\nGOOD could have had\n"
691 "BAD couldthe\nGOOD could the\n"
692 "BAD couldve\nGOOD could've\n"
693 "BAD cpoy\nGOOD copy\n"
694 "BAD creme\nGOOD crème\n"
695 "BAD ctaegory\nGOOD category\n"
696 "BAD cusotmer\nGOOD customer\n"
697 "BAD cusotmers\nGOOD customers\n"
698 "BAD cutsomer\nGOOD customer\n"
699 "BAD cutsomers\nGOOD customer\n"
700 "BAD cuz\nGOOD because\n"
701 "BAD cxan\nGOOD can\n"
702 "BAD danceing\nGOOD dancing\n"
703 "BAD dcument\nGOOD document\n"
704 "BAD deatils\nGOOD details\n"
705 "BAD decison\nGOOD decision\n"
706 "BAD decisons\nGOOD decisions\n"
707 "BAD decor\nGOOD décor\n"
708 "BAD defendent\nGOOD defendant\n"
709 "BAD definately\nGOOD definitely\n"
710 "BAD deja vu\nGOOD déjà vu\n"
711 "BAD deptartment\nGOOD department\n"
712 "BAD desicion\nGOOD decision\n"
713 "BAD desicions\nGOOD decisions\n"
714 "BAD desision\nGOOD decision\n"
715 "BAD desisions\nGOOD decisions\n"
716 "BAD detente\nGOOD détente\n"
717 "BAD develeoprs\nGOOD developers\n"
718 "BAD devellop\nGOOD develop\n"
719 "BAD develloped\nGOOD developed\n"
720 "BAD develloper\nGOOD developer\n"
721 "BAD devellopers\nGOOD developers\n"
722 "BAD develloping\nGOOD developing\n"
723 "BAD devellopment\nGOOD development\n"
724 "BAD devellopments\nGOOD developments\n"
725 "BAD devellops\nGOOD develop\n"
726 "BAD develope\nGOOD develop\n"
727 "BAD developement\nGOOD development\n"
728 "BAD developements\nGOOD developments\n"
729 "BAD developor\nGOOD developer\n"
730 "BAD developors\nGOOD developers\n"
731 "BAD develpment\nGOOD development\n"
732 "BAD diaplay\nGOOD display\n"
733 "BAD didint\nGOOD didn't\n"
734 "BAD didnot\nGOOD did not\n"
735 "BAD didnt\nGOOD didn't\n"
736 "BAD didn;t\nGOOD didn't\n"
737 "BAD difefrent\nGOOD different\n"
738 "BAD diferences\nGOOD differences\n"
739 "BAD differance\nGOOD difference\n"
740 "BAD differances\nGOOD differences\n"
741 "BAD differant\nGOOD different\n"
742 "BAD differemt\nGOOD different\n"
743 "BAD differnt\nGOOD different\n"
744 "BAD diffrent\nGOOD different\n"
745 "BAD directer\nGOOD director\n"
746 "BAD directers\nGOOD directors\n"
747 "BAD directiosn\nGOOD direction\n"
748 "BAD disatisfied\nGOOD dissatisfied\n"
749 "BAD discoverd\nGOOD discovered\n"
750 "BAD disign\nGOOD design\n"
751 "BAD dispaly\nGOOD display\n"
752 "BAD dissonent\nGOOD dissonant\n"
753 "BAD distribusion\nGOOD distribution\n"
754 "BAD divsion\nGOOD division\n"
755 "BAD docuement\nGOOD documents\n"
756 "BAD docuemnt\nGOOD document\n"
757 "BAD documetn\nGOOD document\n"
758 "BAD documnet\nGOOD document\n"
759 "BAD documnets\nGOOD documents\n"
760 "BAD doens't\nGOOD doesn't\n"
761 "BAD doese\nGOOD does\n"
762 "BAD doe snot\nGOOD does not\n"
763 "BAD doesnt\nGOOD doesn't\n"
764 "BAD doesn;t\nGOOD doesn't\n"
765 "BAD doign\nGOOD doing\n"
766 "BAD doimg\nGOOD doing\n"
767 "BAD doind\nGOOD doing\n"
768 "BAD dollers\nGOOD dollars\n"
769 "BAD donig\nGOOD doing\n"
770 "BAD dont\nGOOD don't\n"
771 "BAD do'nt\nGOOD don't\n"
772 "BAD don;t\nGOOD don't\n"
773 "BAD don't no\nGOOD don't know\n"
774 "BAD dosn't\nGOOD doesn't\n"
775 "BAD driveing\nGOOD driving\n"
776 "BAD drnik\nGOOD drink\n"
777 "BAD eclair\nGOOD éclair\n"
778 "BAD efel\nGOOD feel\n"
779 "BAD effecient\nGOOD efficient\n"
780 "BAD efort\nGOOD effort\n"
781 "BAD eforts\nGOOD efforts\n"
782 "BAD ehr\nGOOD her\n"
783 "BAD eligable\nGOOD eligible\n"
784 "BAD embarass\nGOOD embarrass\n"
785 "BAD emigre\nGOOD émigré\n"
786 "BAD enought\nGOOD enough\n"
787 "BAD entree\nGOOD entrée\n"
788 "BAD equippment\nGOOD equipment\n"
789 "BAD equivalant\nGOOD equivalent\n"
790 "BAD esle\nGOOD else\n"
791 "BAD especally\nGOOD especially\n"
792 "BAD especialyl\nGOOD especially\n"
793 "BAD espesially\nGOOD especially\n"
794 "BAD essense\nGOOD essence\n"
795 "BAD excellance\nGOOD excellence\n"
796 "BAD excellant\nGOOD excellent\n"
797 "BAD excercise\nGOOD exercise\n"
798 "BAD exchagne\nGOOD exchange\n"
799 "BAD exchagnes\nGOOD exchanges\n"
800 "BAD excitment\nGOOD excitement\n"
801 "BAD exhcange\nGOOD exchange\n"
802 "BAD exhcanges\nGOOD exchanges\n"
803 "BAD experiance\nGOOD experience\n"
804 "BAD experienc\nGOOD experience\n"
805 "BAD exprience\nGOOD experience\n"
806 "BAD exprienced\nGOOD experienced\n"
807 "BAD eyt\nGOOD yet\n"
808 "BAD facade\nGOOD façade\n"
809 "BAD faeture\nGOOD feature\n"
810 "BAD faetures\nGOOD feature\n"
811 "BAD familair\nGOOD familiar\n"
812 "BAD familar\nGOOD familiar\n"
813 "BAD familliar\nGOOD familiar\n"
814 "BAD fammiliar\nGOOD familiar\n"
815 "BAD feild\nGOOD field\n"
816 "BAD feilds\nGOOD fields\n"
817 "BAD fianlly\nGOOD finally\n"
818 "BAD fidn\nGOOD find\n"
819 "BAD finalyl\nGOOD finally\n"
820 "BAD firends\nGOOD friends\n"
821 "BAD firts\nGOOD first\n"
822 "BAD follwo\nGOOD follow\n"
823 "BAD follwoing\nGOOD following\n"
824 "BAD fora\nGOOD for a\n"
825 "BAD foriegn\nGOOD foreign\n"
826 "BAD forthe\nGOOD for the\n"
827 "BAD forwrd\nGOOD forward\n"
828 "BAD forwrds\nGOOD forwards\n"
829 "BAD foudn\nGOOD found\n"
830 "BAD foward\nGOOD forward\n"
831 "BAD fowards\nGOOD forwards\n"
832 "BAD freind\nGOOD friend\n"
833 "BAD freindly\nGOOD friendly\n"
834 "BAD freinds\nGOOD friends\n"
835 "BAD friday\nGOOD Friday\n"
836 "BAD frmo\nGOOD from\n"
837 "BAD fromthe\nGOOD from the\n"
838 "BAD fromt he\nGOOD from the\n"
839 "BAD furneral\nGOOD funeral\n"
840 "BAD fwe\nGOOD few\n"
841 "BAD garantee\nGOOD guarantee\n"
842 "BAD gaurd\nGOOD guard\n"
843 "BAD gemeral\nGOOD general\n"
844 "BAD gerat\nGOOD great\n"
845 "BAD geting\nGOOD getting\n"
846 "BAD gettin\nGOOD getting\n"
847 "BAD gievn\nGOOD given\n"
848 "BAD giveing\nGOOD giving\n"
849 "BAD gloabl\nGOOD global\n"
850 "BAD goign\nGOOD going\n"
851 "BAD gonig\nGOOD going\n"
852 "BAD govenment\nGOOD government\n"
853 "BAD goverment\nGOOD government\n"
854 "BAD gruop\nGOOD group\n"
855 "BAD gruops\nGOOD groups\n"
856 "BAD grwo\nGOOD grow\n"
857 "BAD guidlines\nGOOD guidelines\n"
858 "BAD hadbeen\nGOOD had been\n"
859 "BAD hadnt\nGOOD hadn't\n"
860 "BAD hadn;t\nGOOD hadn't\n"
861 "BAD haev\nGOOD have\n"
862 "BAD hapen\nGOOD happen\n"
863 "BAD hapened\nGOOD happened\n"
864 "BAD hapening\nGOOD happening\n"
865 "BAD hapens\nGOOD happens\n"
866 "BAD happend\nGOOD happened\n"
867 "BAD hasbeen\nGOOD has been\n"
868 "BAD hasnt\nGOOD hasn't\n"
869 "BAD hasn;t\nGOOD hasn't\n"
870 "BAD havebeen\nGOOD have been\n"
871 "BAD haveing\nGOOD having\n"
872 "BAD havent\nGOOD haven't\n"
873 "BAD haven;t\nGOOD haven't\n"
874 "BAD hda\nGOOD had\n"
875 "BAD hearign\nGOOD hearing\n"
876 "BAD he;d\nGOOD he'd\n"
877 "BAD hel\nGOOD he'll\n"
878 "BAD he;ll\nGOOD he'll\n"
879 "BAD helpfull\nGOOD helpful\n"
880 "BAD herat\nGOOD heart\n"
881 "BAD heres\nGOOD here's\n"
882 "BAD here;s\nGOOD here's\n"
883 "BAD hes\nGOOD he's\n"
884 "BAD he;s\nGOOD he's\n"
885 "BAD hesaid\nGOOD he said\n"
886 "BAD hewas\nGOOD he was\n"
887 "BAD hge\nGOOD he\n"
888 "BAD hismelf\nGOOD himself\n"
889 "BAD hlep\nGOOD help\n"
890 "BAD hows\nGOOD how's\n"
891 "BAD hsa\nGOOD has\n"
892 "BAD hse\nGOOD she\n"
893 "BAD hsi\nGOOD his\n"
894 "BAD hte\nGOOD the\n"
895 "BAD htere\nGOOD there\n"
896 "BAD htese\nGOOD these\n"
897 "BAD htey\nGOOD they\n"
898 "BAD hting\nGOOD thing\n"
899 "BAD htink\nGOOD think\n"
900 "BAD htis\nGOOD this\n"
901 "BAD htp:\nGOOD http:\n"
902 "BAD http:\\\\nGOOD http://\n"
903 "BAD httpL\nGOOD http:\n"
904 "BAD hvae\nGOOD have\n"
905 "BAD hvaing\nGOOD having\n"
906 "BAD hwich\nGOOD which\n"
907 "BAD i\nGOOD I\n"
908 "BAD i;d\nGOOD I'd\n"
909 "BAD i'd\nGOOD I'd\n"
910 "BAD I;d\nGOOD I'd\n"
911 "BAD idae\nGOOD idea\n"
912 "BAD idaes\nGOOD ideas\n"
913 "BAD identofy\nGOOD identify\n"
914 "BAD ihs\nGOOD his\n"
915 "BAD iits the\nGOOD it's the\n"
916 "BAD i'll\nGOOD I'll\n"
917 "BAD I;ll\nGOOD I'll\n"
918 "BAD i;m\nGOOD I'm\n"
919 "BAD i'm\nGOOD I'm\n"
920 "BAD I\"m\nGOOD I'm\n"
921 "BAD imediate\nGOOD immediate\n"
922 "BAD imediatly\nGOOD immediately\n"
923 "BAD immediatly\nGOOD immediately\n"
924 "BAD importent\nGOOD important\n"
925 "BAD importnat\nGOOD important\n"
926 "BAD impossable\nGOOD impossible\n"
927 "BAD improvemnt\nGOOD improvement\n"
928 "BAD improvment\nGOOD improvement\n"
929 "BAD includ\nGOOD include\n"
930 "BAD indecate\nGOOD indicate\n"
931 "BAD indenpendence\nGOOD independence\n"
932 "BAD indenpendent\nGOOD independent\n"
933 "BAD indepedent\nGOOD independent\n"
934 "BAD independance\nGOOD independence\n"
935 "BAD independant\nGOOD independent\n"
936 "BAD influance\nGOOD influence\n"
937 "BAD infomation\nGOOD information\n"
938 "BAD informatoin\nGOOD information\n"
939 "BAD inital\nGOOD initial\n"
940 "BAD instaleld\nGOOD installed\n"
941 "BAD insted\nGOOD instead\n"
942 "BAD insurence\nGOOD insurance\n"
943 "BAD inteh\nGOOD in the\n"
944 "BAD interum\nGOOD interim\n"
945 "BAD inthe\nGOOD in the\n"
946 "BAD int he\nGOOD in the\n"
947 "BAD inturn\nGOOD intern\n"
948 "BAD inwhich\nGOOD in which\n"
949 "BAD i snot\nGOOD is not\n"
950 "BAD isnt\nGOOD isn't\n"
951 "BAD isn;t\nGOOD isn't\n"
952 "BAD isthe\nGOOD is the\n"
953 "BAD itd\nGOOD it'd\n"
954 "BAD it;d\nGOOD it'd\n"
955 "BAD itis\nGOOD it is\n"
956 "BAD ititial\nGOOD initial\n"
957 "BAD itll\nGOOD it'll\n"
958 "BAD it;ll\nGOOD it'll\n"
959 "BAD itnerest\nGOOD interest\n"
960 "BAD itnerested\nGOOD interested\n"
961 "BAD itneresting\nGOOD interesting\n"
962 "BAD itnerests\nGOOD interests\n"
963 "BAD it;s\nGOOD it's\n"
964 "BAD itsa\nGOOD it's a\n"
965 "BAD its a\nGOOD it's a\n"
966 "BAD it snot\nGOOD it's not\n"
967 "BAD it' snot\nGOOD it's not\n"
968 "BAD its the\nGOOD it's the\n"
969 "BAD itwas\nGOOD it was\n"
970 "BAD ive\nGOOD I've\n"
971 "BAD i;ve\nGOOD I've\n"
972 "BAD i've\nGOOD I've\n"
973 "BAD iwll\nGOOD will\n"
974 "BAD iwth\nGOOD with\n"
975 "BAD jsut\nGOOD just\n"
976 "BAD jugment\nGOOD judgment\n"
977 "BAD k\nGOOD okay\n"
978 "BAD kno\nGOOD know\n"
979 "BAD knowldge\nGOOD knowledge\n"
980 "BAD knowlege\nGOOD knowledge\n"
981 "BAD knwo\nGOOD know\n"
982 "BAD knwon\nGOOD known\n"
983 "BAD knwos\nGOOD knows\n"
984 "BAD konw\nGOOD know\n"
985 "BAD konwn\nGOOD known\n"
986 "BAD konws\nGOOD knows\n"
987 "BAD labratory\nGOOD laboratory\n"
988 "BAD lastyear\nGOOD last year\n"
989 "BAD learnign\nGOOD learning\n"
990 "BAD lenght\nGOOD length\n"
991 "BAD let;s\nGOOD let's\n"
992 "BAD let's him\nGOOD lets him\n"
993 "BAD let's it\nGOOD lets it\n"
994 "BAD levle\nGOOD level\n"
995 "BAD libary\nGOOD library\n"
996 "BAD librarry\nGOOD library\n"
997 "BAD librery\nGOOD library\n"
998 "BAD liek\nGOOD like\n"
999 "BAD liekd\nGOOD liked\n"
1000 "BAD lieutenent\nGOOD lieutenant\n"
1001 "BAD liev\nGOOD live\n"
1002 "BAD likly\nGOOD likely\n"
1003 "BAD lisense\nGOOD license\n"
1004 "BAD littel\nGOOD little\n"
1005 "BAD litttle\nGOOD little\n"
1006 "BAD liuke\nGOOD like\n"
1007 "BAD liveing\nGOOD living\n"
1008 "BAD loev\nGOOD love\n"
1009 "BAD lonly\nGOOD lonely\n"
1010 "BAD lookign\nGOOD looking\n"
1011 "BAD m\nGOOD am\n"
1012 "BAD maintainence\nGOOD maintenance\n"
1013 "BAD maintenence\nGOOD maintenance\n"
1014 "BAD makeing\nGOOD making\n"
1015 "BAD managment\nGOOD management\n"
1016 "BAD mantain\nGOOD maintain\n"
1017 "BAD marraige\nGOOD marriage\n"
1018 "BAD may of been\nGOOD may have been\n"
1019 "BAD may of had\nGOOD may have had\n"
1020 "BAD memeber\nGOOD member\n"
1021 "BAD merchent\nGOOD merchant\n"
1022 "BAD mesage\nGOOD message\n"
1023 "BAD mesages\nGOOD messages\n"
1024 "BAD might of been\nGOOD might have been\n"
1025 "BAD might of had\nGOOD might have had\n"
1026 "BAD mispell\nGOOD misspell\n"
1027 "BAD mispelling\nGOOD misspelling\n"
1028 "BAD mispellings\nGOOD misspellings\n"
1029 "BAD mkae\nGOOD make\n"
1030 "BAD mkaes\nGOOD makes\n"
1031 "BAD mkaing\nGOOD making\n"
1032 "BAD moeny\nGOOD money\n"
1033 "BAD monday\nGOOD Monday\n"
1034 "BAD morgage\nGOOD mortgage\n"
1035 "BAD mroe\nGOOD more\n"
1036 "BAD must of been\nGOOD must have been\n"
1037 "BAD must of had\nGOOD must have had\n"
1038 "BAD mysefl\nGOOD myself\n"
1039 "BAD myu\nGOOD my\n"
1040 "BAD naive\nGOOD naïve\n"
1041 "BAD ne1\nGOOD anyone\n"
1042 "BAD necassarily\nGOOD necessarily\n"
1043 "BAD necassary\nGOOD necessary\n"
1044 "BAD neccessarily\nGOOD necessarily\n"
1045 "BAD neccessary\nGOOD necessary\n"
1046 "BAD necesarily\nGOOD necessarily\n"
1047 "BAD necesary\nGOOD necessary\n"
1048 "BAD negotiaing\nGOOD negotiating\n"
1049 "BAD nkow\nGOOD know\n"
1050 "BAD nothign\nGOOD nothing\n"
1051 "BAD nto\nGOOD not\n"
1052 "BAD nver\nGOOD never\n"
1053 "BAD nwe\nGOOD new\n"
1054 "BAD nwo\nGOOD now\n"
1055 "BAD obediant\nGOOD obedient\n"
1056 "BAD ocasion\nGOOD occasion\n"
1057 "BAD occassion\nGOOD occasion\n"
1058 "BAD occured\nGOOD occurred\n"
1059 "BAD occurence\nGOOD occurrence\n"
1060 "BAD occurrance\nGOOD occurrence\n"
1061 "BAD oclock\nGOOD o'clock\n"
1062 "BAD oculd\nGOOD could\n"
1063 "BAD ocur\nGOOD occur\n"
1064 "BAD oeprator\nGOOD operator\n"
1065 "BAD ofits\nGOOD of its\n"
1066 "BAD ofthe\nGOOD of the\n"
1067 "BAD oft he\nGOOD of the\n"
1068 "BAD oging\nGOOD going\n"
1069 "BAD ohter\nGOOD other\n"
1070 "BAD omre\nGOOD more\n"
1071 "BAD oneof\nGOOD one of\n"
1072 "BAD onepoint\nGOOD one point\n"
1073 "BAD onthe\nGOOD on the\n"
1074 "BAD ont he\nGOOD on the\n"
1075 "BAD onyl\nGOOD only\n"
1076 "BAD oppasite\nGOOD opposite\n"
1077 "BAD opperation\nGOOD operation\n"
1078 "BAD oppertunity\nGOOD opportunity\n"
1079 "BAD opposate\nGOOD opposite\n"
1080 "BAD opposible\nGOOD opposable\n"
1081 "BAD opposit\nGOOD opposite\n"
1082 "BAD oppotunities\nGOOD opportunities\n"
1083 "BAD oppotunity\nGOOD opportunity\n"
1084 "BAD orginization\nGOOD organization\n"
1085 "BAD orginized\nGOOD organized\n"
1086 "BAD otehr\nGOOD other\n"
1087 "BAD otu\nGOOD out\n"
1088 "BAD outof\nGOOD out of\n"
1089 "BAD overthe\nGOOD over the\n"
1090 "BAD owrk\nGOOD work\n"
1091 "BAD owuld\nGOOD would\n"
1092 "BAD oxident\nGOOD oxidant\n"
1093 "BAD papaer\nGOOD paper\n"
1094 "BAD parliment\nGOOD parliament\n"
1095 "BAD partof\nGOOD part of\n"
1096 "BAD paymetn\nGOOD payment\n"
1097 "BAD paymetns\nGOOD payments\n"
1098 "BAD pciture\nGOOD picture\n"
1099 "BAD peice\nGOOD piece\n"
1100 "BAD peices\nGOOD pieces\n"
1101 "BAD peolpe\nGOOD people\n"
1102 "BAD peopel\nGOOD people\n"
1103 "BAD percentof\nGOOD percent of\n"
1104 "BAD percentto\nGOOD percent to\n"
1105 "BAD performence\nGOOD performance\n"
1106 "BAD perhasp\nGOOD perhaps\n"
1107 "BAD perhpas\nGOOD perhaps\n"
1108 "BAD permanant\nGOOD permanent\n"
1109 "BAD perminent\nGOOD permanent\n"
1110 "BAD personalyl\nGOOD personally\n"
1111 "BAD pleasent\nGOOD pleasant\n"
1112 "BAD pls\nGOOD please\n"
1113 "BAD plz\nGOOD please\n"
1114 "BAD poeple\nGOOD people\n"
1115 "BAD porblem\nGOOD problem\n"
1116 "BAD porblems\nGOOD problems\n"
1117 "BAD porvide\nGOOD provide\n"
1118 "BAD possable\nGOOD possible\n"
1119 "BAD postition\nGOOD position\n"
1120 "BAD potentialy\nGOOD potentially\n"
1121 "BAD ppl\nGOOD people\n"
1122 "BAD pregnent\nGOOD pregnant\n"
1123 "BAD presance\nGOOD presence\n"
1124 "BAD probelm\nGOOD problem\n"
1125 "BAD probelms\nGOOD problems\n"
1126 "BAD prominant\nGOOD prominent\n"
1127 "BAD protege\nGOOD protégé\n"
1128 "BAD protoge\nGOOD protégé\n"
1129 "BAD psoition\nGOOD position\n"
1130 "BAD ptogress\nGOOD progress\n"
1131 "BAD pursuade\nGOOD persuade\n"
1132 "BAD puting\nGOOD putting\n"
1133 "BAD pwoer\nGOOD power\n"
1134 "BAD quater\nGOOD quarter\n"
1135 "BAD quaters\nGOOD quarters\n"
1136 "BAD quesion\nGOOD question\n"
1137 "BAD quesions\nGOOD questions\n"
1138 "BAD questioms\nGOOD questions\n"
1139 "BAD questiosn\nGOOD questions\n"
1140 "BAD questoin\nGOOD question\n"
1141 "BAD quetion\nGOOD question\n"
1142 "BAD quetions\nGOOD questions\n"
1143 "BAD r\nGOOD are\n"
1144 "BAD realyl\nGOOD really\n"
1145 "BAD reccomend\nGOOD recommend\n"
1146 "BAD reccommend\nGOOD recommend\n"
1147 "BAD receieve\nGOOD receive\n"
1148 "BAD recieve\nGOOD receive\n"
1149 "BAD recieved\nGOOD received\n"
1150 "BAD recieving\nGOOD receiving\n"
1151 "BAD recomend\nGOOD recommend\n"
1152 "BAD recomendation\nGOOD recommendation\n"
1153 "BAD recomendations\nGOOD recommendations\n"
1154 "BAD recomended\nGOOD recommended\n"
1155 "BAD reconize\nGOOD recognize\n"
1156 "BAD recrod\nGOOD record\n"
1157 "BAD rediculous\nGOOD ridiculous\n"
1158 "BAD religous\nGOOD religious\n"
1159 "BAD reluctent\nGOOD reluctant\n"
1160 "BAD remeber\nGOOD remember\n"
1161 "BAD reommend\nGOOD recommend\n"
1162 "BAD representativs\nGOOD representatives\n"
1163 "BAD representives\nGOOD representatives\n"
1164 "BAD represetned\nGOOD represented\n"
1165 "BAD represnt\nGOOD represent\n"
1166 "BAD reserach\nGOOD research\n"
1167 "BAD resollution\nGOOD resolution\n"
1168 "BAD resorces\nGOOD resources\n"
1169 "BAD respomd\nGOOD respond\n"
1170 "BAD respomse\nGOOD response\n"
1171 "BAD responce\nGOOD response\n"
1172 "BAD responsability\nGOOD responsibility\n"
1173 "BAD responsable\nGOOD responsible\n"
1174 "BAD responsibile\nGOOD responsible\n"
1175 "BAD responsiblity\nGOOD responsibility\n"
1176 "BAD restaraunt\nGOOD restaurant\n"
1177 "BAD restuarant\nGOOD restaurant\n"
1178 "BAD reult\nGOOD result\n"
1179 "BAD reveiw\nGOOD review\n"
1180 "BAD reveiwing\nGOOD reviewing\n"
1181 "BAD rumers\nGOOD rumors\n"
1182 "BAD rwite\nGOOD write\n"
1183 "BAD rythm\nGOOD rhythm\n"
1184 "BAD saidhe\nGOOD said he\n"
1185 "BAD saidit\nGOOD said it\n"
1186 "BAD saidthat\nGOOD said that\n"
1187 "BAD saidthe\nGOOD said the\n"
1188 "BAD saidt he\nGOOD said the\n"
1189 "BAD saturday\nGOOD Saturday\n"
1190 "BAD scedule\nGOOD schedule\n"
1191 "BAD sceduled\nGOOD scheduled\n"
1192 "BAD seance\nGOOD séance\n"
1193 "BAD secratary\nGOOD secretary\n"
1194 "BAD sectino\nGOOD section\n"
1195 "BAD seh\nGOOD she\n"
1196 "BAD selectoin\nGOOD selection\n"
1197 "BAD sence\nGOOD sense\n"
1198 "BAD sentance\nGOOD sentence\n"
1199 "BAD separeate\nGOOD separate\n"
1200 "BAD seperate\nGOOD separate\n"
1201 "BAD sercumstances\nGOOD circumstances\n"
1202 "BAD shcool\nGOOD school\n"
1203 "BAD she'\nGOOD she'll\n"
1204 "BAD she;d\nGOOD she'd\n"
1205 "BAD she;ll\nGOOD she'll\n"
1206 "BAD shes\nGOOD she's\n"
1207 "BAD she;s\nGOOD she's\n"
1208 "BAD shesaid\nGOOD she said\n"
1209 "BAD shineing\nGOOD shining\n"
1210 "BAD shiped\nGOOD shipped\n"
1211 "BAD shoudl\nGOOD should\n"
1212 "BAD shoudln't\nGOOD shouldn't\n"
1213 "BAD shouldent\nGOOD shouldn't\n"
1214 "BAD shouldnt\nGOOD shouldn't\n"
1215 "BAD shouldn;t\nGOOD shouldn't\n"
1216 "BAD should of been\nGOOD should have been\n"
1217 "BAD should of had\nGOOD should have had\n"
1218 "BAD shouldve\nGOOD should've\n"
1219 "BAD showinf\nGOOD showing\n"
1220 "BAD signifacnt\nGOOD significant\n"
1221 "BAD simalar\nGOOD similar\n"
1222 "BAD similiar\nGOOD similar\n"
1223 "BAD simpyl\nGOOD simply\n"
1224 "BAD sincerly\nGOOD sincerely\n"
1225 "BAD sitll\nGOOD still\n"
1226 "BAD smae\nGOOD same\n"
1227 "BAD smoe\nGOOD some\n"
1228 "BAD soem\nGOOD some\n"
1229 "BAD sohw\nGOOD show\n"
1230 "BAD soical\nGOOD social\n"
1231 "BAD some1\nGOOD someone\n"
1232 "BAD somethign\nGOOD something\n"
1233 "BAD someting\nGOOD something\n"
1234 "BAD somewaht\nGOOD somewhat\n"
1235 "BAD somthing\nGOOD something\n"
1236 "BAD somtimes\nGOOD sometimes\n"
1237 "BAD sot hat\nGOOD so that\n"
1238 "BAD soudn\nGOOD sound\n"
1239 "BAD soudns\nGOOD sounds\n"
1240 "BAD speach\nGOOD speech\n"
1241 "BAD specificaly\nGOOD specifically\n"
1242 "BAD specificalyl\nGOOD specifically\n"
1243 "BAD sry\nGOOD sorry\n"
1244 "BAD statment\nGOOD statement\n"
1245 "BAD statments\nGOOD statements\n"
1246 "BAD stnad\nGOOD stand\n"
1247 "BAD stopry\nGOOD story\n"
1248 "BAD stoyr\nGOOD story\n"
1249 "BAD stpo\nGOOD stop\n"
1250 "BAD strentgh\nGOOD strength\n"
1251 "BAD stroy\nGOOD story\n"
1252 "BAD struggel\nGOOD struggle\n"
1253 "BAD strugle\nGOOD struggle\n"
1254 "BAD studnet\nGOOD student\n"
1255 "BAD successfull\nGOOD successful\n"
1256 "BAD successfuly\nGOOD successfully\n"
1257 "BAD successfulyl\nGOOD successfully\n"
1258 "BAD sucess\nGOOD success\n"
1259 "BAD sucessfull\nGOOD successful\n"
1260 "BAD sufficiant\nGOOD sufficient\n"
1261 "BAD sum1\nGOOD someone\n"
1262 "BAD sunday\nGOOD Sunday\n"
1263 "BAD suposed\nGOOD supposed\n"
1264 "BAD suppossed\nGOOD supposed\n"
1265 "BAD suprise\nGOOD surprise\n"
1266 "BAD suprised\nGOOD surprised\n"
1267 "BAD swiming\nGOOD swimming\n"
1268 "BAD tahn\nGOOD than\n"
1269 "BAD taht\nGOOD that\n"
1270 "BAD talekd\nGOOD talked\n"
1271 "BAD talkign\nGOOD talking\n"
1272 "BAD tath\nGOOD that\n"
1273 "BAD tecnical\nGOOD technical\n"
1274 "BAD teh\nGOOD the\n"
1275 "BAD tehy\nGOOD they\n"
1276 "BAD tellt he\nGOOD tell the\n"
1277 "BAD termoil\nGOOD turmoil\n"
1278 "BAD tets\nGOOD test\n"
1279 "BAD tghe\nGOOD the\n"
1280 "BAD tghis\nGOOD this\n"
1281 "BAD thansk\nGOOD thanks\n"
1282 "BAD thats\nGOOD that's\n"
1283 "BAD thatthe\nGOOD that the\n"
1284 "BAD thatt he\nGOOD that the\n"
1285 "BAD thecompany\nGOOD the company\n"
1286 "BAD thefirst\nGOOD the first\n"
1287 "BAD thegovernment\nGOOD the government\n"
1288 "BAD their are\nGOOD there are\n"
1289 "BAD their is\nGOOD there is\n"
1290 "BAD themself\nGOOD themselves\n"
1291 "BAD themselfs\nGOOD themselves\n"
1292 "BAD thenew\nGOOD the new\n"
1293 "BAD theres\nGOOD there's\n"
1294 "BAD there's is\nGOOD theirs is\n"
1295 "BAD theri\nGOOD their\n"
1296 "BAD thesame\nGOOD the same\n"
1297 "BAD thetwo\nGOOD the two\n"
1298 "BAD theyd\nGOOD they'd\n"
1299 "BAD they;d\nGOOD they'd\n"
1300 "BAD they;l\nGOOD they'll\n"
1301 "BAD theyll\nGOOD they'll\n"
1302 "BAD they;ll\nGOOD they'll\n"
1303 "BAD they;r\nGOOD they're\n"
1304 "BAD theyre\nGOOD they're\n"
1305 "BAD they;re\nGOOD they're\n"
1306 "BAD they're are\nGOOD there are\n"
1307 "BAD they're is\nGOOD there is\n"
1308 "BAD they;v\nGOOD they've\n"
1309 "BAD theyve\nGOOD they've\n"
1310 "BAD they;ve\nGOOD they've\n"
1311 "BAD thgat\nGOOD that\n"
1312 "BAD thge\nGOOD the\n"
1313 "BAD thier\nGOOD their \n"
1314 "BAD thigsn\nGOOD things\n"
1315 "BAD thisyear\nGOOD this year\n"
1316 "BAD thme\nGOOD them\n"
1317 "BAD thna\nGOOD than\n"
1318 "BAD thne\nGOOD then\n"
1319 "BAD thnig\nGOOD thing\n"
1320 "BAD thnigs\nGOOD things\n"
1321 "BAD threatend\nGOOD threatened\n"
1322 "BAD thsi\nGOOD this\n"
1323 "BAD thsoe\nGOOD those\n"
1324 "BAD thta\nGOOD that\n"
1325 "BAD thursday\nGOOD Thursday\n"
1326 "BAD thx\nGOOD thanks\n"
1327 "BAD tihs\nGOOD this\n"
1328 "BAD timne\nGOOD time\n"
1329 "BAD tiogether\nGOOD together\n"
1330 "BAD tje\nGOOD the\n"
1331 "BAD tjhe\nGOOD the\n"
1332 "BAD tkae\nGOOD take\n"
1333 "BAD tkaes\nGOOD takes\n"
1334 "BAD tkaing\nGOOD taking\n"
1335 "BAD tlaking\nGOOD talking\n"
1336 "BAD tnx\nGOOD thanks\n"
1337 "BAD todya\nGOOD today\n"
1338 "BAD togehter\nGOOD together\n"
1339 "BAD toldt he\nGOOD told the\n"
1340 "BAD tomorow\nGOOD tomorrow\n"
1341 "BAD tongiht\nGOOD tonight\n"
1342 "BAD tonihgt\nGOOD tonight\n"
1343 "BAD totaly\nGOOD totally\n"
1344 "BAD totalyl\nGOOD totally\n"
1345 "BAD tothe\nGOOD to the\n"
1346 "BAD tot he\nGOOD to the\n"
1347 "BAD towrad\nGOOD toward\n"
1348 "BAD traditionalyl\nGOOD traditionally\n"
1349 "BAD transfered\nGOOD transferred\n"
1350 "BAD truely\nGOOD truly\n"
1351 "BAD truley\nGOOD truly\n"
1352 "BAD tryed\nGOOD tried\n"
1353 "BAD tthe\nGOOD the\n"
1354 "BAD tuesday\nGOOD Tuesday\n"
1355 "BAD tyhat\nGOOD that\n"
1356 "BAD tyhe\nGOOD the\n"
1357 "BAD u\nGOOD you\n"
1358 "BAD udnerstand\nGOOD understand\n"
1359 "BAD understnad\nGOOD understand\n"
1360 "BAD undert he\nGOOD under the\n"
1361 "BAD unforseen\nGOOD unforeseen\n"
1362 "BAD UnitedStates\nGOOD United States\n"
1363 "BAD unliek\nGOOD unlike\n"
1364 "BAD unpleasently\nGOOD unpleasantly\n"
1365 "BAD untill\nGOOD until\n"
1366 "BAD untilll\nGOOD until\n"
1367 "BAD ur\nGOOD you are\n"
1368 "BAD useing\nGOOD using\n"
1369 "BAD usualyl\nGOOD usually\n"
1370 "BAD veyr\nGOOD very\n"
1371 "BAD virtualyl\nGOOD virtually\n"
1372 "BAD visavis\nGOOD vis-a-vis\n"
1373 "BAD vis-a-vis\nGOOD vis-à-vis\n"
1374 "BAD vrey\nGOOD very\n"
1375 "BAD vulnerible\nGOOD vulnerable\n"
1376 "BAD waht\nGOOD what\n"
1377 "BAD warrent\nGOOD warrant\n"
1378 "BAD wa snot\nGOOD was not\n"
1379 "BAD wasnt\nGOOD wasn't\n"
1380 "BAD wasn;t\nGOOD wasn't\n"
1381 "BAD watn\nGOOD want\n"
1382 "BAD we;d\nGOOD we'd\n"
1383 "BAD wednesday\nGOOD Wednesday\n"
1384 "BAD wehn\nGOOD when\n"
1385 "BAD wel\nGOOD we'll\n"
1386 "BAD we;ll\nGOOD we'll\n"
1387 "BAD we;re\nGOOD we're\n"
1388 "BAD werent\nGOOD weren't\n"
1389 "BAD weren;t\nGOOD weren't\n"
1390 "BAD wern't\nGOOD weren't\n"
1391 "BAD werre\nGOOD were\n"
1392 "BAD weve\nGOOD we've\n"
1393 "BAD we;ve\nGOOD we've\n"
1394 "BAD whats\nGOOD what's\n"
1395 "BAD what;s\nGOOD what's\n"
1396 "BAD whcih\nGOOD which\n"
1397 "BAD whent he\nGOOD when the\n"
1398 "BAD wheres\nGOOD where's\n"
1399 "BAD where;s\nGOOD where's\n"
1400 "BAD wherre\nGOOD where\n"
1401 "BAD whic\nGOOD which\n"
1402 "BAD whicht he\nGOOD which the\n"
1403 "BAD whihc\nGOOD which\n"
1404 "BAD wholl\nGOOD who'll\n"
1405 "BAD whos\nGOOD who's\n"
1406 "BAD who;s\nGOOD who's\n"
1407 "BAD whove\nGOOD who've\n"
1408 "BAD who;ve\nGOOD who've\n"
1409 "BAD whta\nGOOD what\n"
1410 "BAD whys\nGOOD why's\n"
1411 "BAD wief\nGOOD wife\n"
1412 "BAD wierd\nGOOD weird\n"
1413 "BAD wihch\nGOOD which\n"
1414 "BAD wiht\nGOOD with\n"
1415 "BAD willbe\nGOOD will be\n"
1416 "BAD will of been\nGOOD will have been\n"
1417 "BAD will of had\nGOOD will have had\n"
1418 "BAD windoes\nGOOD windows\n"
1419 "BAD witha\nGOOD with a\n"
1420 "BAD withe\nGOOD with\n"
1421 "BAD withthe\nGOOD with the\n"
1422 "BAD witht he\nGOOD with the\n"
1423 "BAD wiull\nGOOD will\n"
1424 "BAD wnat\nGOOD want\n"
1425 "BAD wnated\nGOOD wanted\n"
1426 "BAD wnats\nGOOD wants\n"
1427 "BAD woh\nGOOD who\n"
1428 "BAD wohle\nGOOD whole\n"
1429 "BAD wokr\nGOOD work\n"
1430 "BAD wont\nGOOD won't\n"
1431 "BAD wo'nt\nGOOD won't\n"
1432 "BAD won;t\nGOOD won't\n"
1433 "BAD woudl\nGOOD would\n"
1434 "BAD woudln't\nGOOD wouldn't\n"
1435 "BAD wouldbe\nGOOD would be\n"
1436 "BAD wouldnt\nGOOD wouldn't\n"
1437 "BAD wouldn;t\nGOOD wouldn't\n"
1438 "BAD would of been\nGOOD would have been\n"
1439 "BAD would of had\nGOOD would have had\n"
1440 "BAD wouldve\nGOOD would've\n"
1441 "BAD wriet\nGOOD write\n"
1442 "BAD writting\nGOOD writing\n"
1443 "BAD wrod\nGOOD word\n"
1444 "BAD wroet\nGOOD wrote\n"
1445 "BAD wroking\nGOOD working\n"
1446 "BAD wtih\nGOOD with\n"
1447 "BAD wuould\nGOOD would\n"
1448 "BAD wut\nGOOD what\n"
1449 "BAD wya\nGOOD way\n"
1450 "BAD y\nGOOD why\n"
1451 "BAD yera\nGOOD year\n"
1452 "BAD yeras\nGOOD years\n"
1453 "BAD yersa\nGOOD years\n"
1454 "BAD yoiu\nGOOD you\n"
1455 "BAD youare\nGOOD you are\n"
1456 "BAD youd\nGOOD you'd\n"
1457 "BAD you;d\nGOOD you'd\n"
1458 "BAD youll\nGOOD you'll\n"
1459 "BAD your a\nGOOD you're a\n"
1460 "BAD your an\nGOOD you're an\n"
1461 "BAD youre\nGOOD you're\n"
1462 "BAD you;re\nGOOD you're\n"
1463 "BAD you're own\nGOOD your own\n"
1464 "BAD your her\nGOOD you're her\n"
1465 "BAD your here\nGOOD you're here\n"
1466 "BAD your his\nGOOD you're his\n"
1467 "BAD your my\nGOOD you're my\n"
1468 "BAD your the\nGOOD you're the\n"
1469 "BAD your their\nGOOD you're their\n"
1470 "BAD your your\nGOOD you're your\n"
1471 "BAD youve\nGOOD you've\n"
1472 "BAD you;ve\nGOOD you've\n"
1473 "BAD ytou\nGOOD you\n"
1474 "BAD yuo\nGOOD you\n"
1475 "BAD yuor\nGOOD your\n";
1476 gchar *buf;
1477 gchar *ibuf;
1478 GHashTable *hashes;
1479 char bad[82] = "";
1480 char good[256] = "";
105 int pnt = 0; 1481 int pnt = 0;
106 gsize size; 1482 gsize size;
107
108 model = gtk_list_store_new((gint)N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
109 1483
110 buf = g_build_filename(gaim_user_dir(), "dict", NULL); 1484 buf = g_build_filename(gaim_user_dir(), "dict", NULL);
111 g_file_get_contents(buf, &ibuf, &size, NULL); 1485 g_file_get_contents(buf, &ibuf, &size, NULL);
112 g_free(buf); 1486 g_free(buf);
113 if(!ibuf) { 1487 if (!ibuf) {
114 ibuf = g_strdup(defaultconf); 1488 ibuf = g_strdup(defaultconf);
115 size = strlen(defaultconf); 1489 size = strlen(defaultconf);
116 } 1490 }
117 1491
118 cmd[0] = 0; 1492 model = gtk_list_store_new((gint)N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
119 name[0] = 0; 1493 hashes = g_hash_table_new(g_str_hash, g_str_equal);
120 1494
121 while(buf_get_line(ibuf, &buf, &pnt, size)) { 1495 while (buf_get_line(ibuf, &buf, &pnt, size)) {
122 if (*buf != '#') { 1496 if (*buf != '#') {
123 if (!strncasecmp(buf, "BAD ", 4)) 1497 if (!strncasecmp(buf, "BAD ", 4))
124 strncpy(name, buf + 4, 81); 1498 strncpy(bad, buf + 4, 81);
125 if (!strncasecmp(buf, "GOOD ", 5)) { 1499 else if (!strncasecmp(buf, "GOOD ", 5)) {
126 strncpy(cmd, buf + 5, 255); 1500 strncpy(good, buf + 5, 255);
127 if (*name) { 1501
1502 if (*bad && *good && g_hash_table_lookup(hashes, bad) == NULL) {
128 GtkTreeIter iter; 1503 GtkTreeIter iter;
1504
1505 /* We don't actually need to store the good string, since this
1506 * hash is just being used to eliminate duplicate bad strings.
1507 */
1508 g_hash_table_insert(hashes, g_strdup(bad), GINT_TO_POINTER(1));
1509
129 gtk_list_store_append(model, &iter); 1510 gtk_list_store_append(model, &iter);
130 gtk_list_store_set(model, &iter, 1511 gtk_list_store_set(model, &iter,
131 0, g_strdup(name), 1512 0, bad,
132 1, g_strdup(cmd), 1513 1, good,
133 -1); 1514 -1);
134 } 1515 }
1516 bad[0] = '\0';
135 } 1517 }
136 } 1518 }
137 } 1519 }
138 g_free(ibuf); 1520 g_free(ibuf);
1521 g_hash_table_foreach(hashes, (GHFunc)g_free, NULL);
1522 g_hash_table_destroy(hashes);
1523
139 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model), 1524 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model),
140 0, GTK_SORT_ASCENDING); 1525 0, GTK_SORT_ASCENDING);
141 }
142
143
144
145 static int num_words(const char *m) {
146 int count = 0;
147 guint pos;
148 int state = 0;
149
150 for (pos = 0; pos < strlen(m); pos++) {
151 switch (state) {
152 case 0: /* expecting word */
153 if (!g_ascii_isspace(m[pos]) && !g_ascii_ispunct(m[pos])) {
154 count++;
155 state = 1;
156 } else if (m[pos] == '<')
157 state = 2;
158 break;
159 case 1: /* inside word */
160 if (m[pos] == '<')
161 state = 2;
162 else if (g_ascii_isspace(m[pos]) || g_ascii_ispunct(m[pos]))
163 state = 0;
164 break;
165 case 2: /* inside HTML tag */
166 if (m[pos] == '>')
167 state = 0;
168 break;
169 }
170 }
171 return count;
172 }
173
174 static int get_word(char *m, int word) {
175 int count = 0;
176 guint pos = 0;
177 int state = 0;
178
179 for (pos = 0; pos < strlen(m) && count <= word; pos++) {
180 switch (state) {
181 case 0:
182 if (!g_ascii_isspace(m[pos]) && !g_ascii_ispunct(m[pos])) {
183 count++;
184 state = 1;
185 } else if (m[pos] == '<')
186 state = 2;
187 break;
188 case 1:
189 if (m[pos] == '<')
190 state = 2;
191 else if (g_ascii_isspace(m[pos]) || g_ascii_ispunct(m[pos]))
192 state = 0;
193 break;
194 case 2:
195 if (m[pos] == '>')
196 state = 0;
197 break;
198 }
199 }
200 return pos - 1;
201 }
202
203 static char *have_word(char *m, int pos) {
204 char *tmp = strpbrk(&m[pos], "' \t\f\r\n\"><.?!-,/");
205 int len = (int)(tmp - &m[pos]);
206
207 if (tmp == NULL) {
208 tmp = strdup(&m[pos]);
209 return tmp;
210 }
211
212 tmp = malloc(len + 1);
213 tmp[0] = 0;
214 strncat(tmp, &m[pos], len);
215
216 return tmp;
217 }
218
219 static void substitute(char **mes, int pos, int m, const char *text) {
220 char *new = g_malloc(strlen(*mes) + strlen(text) + 1);
221 char *tmp;
222 new[0] = 0;
223
224 strncat(new, *mes, pos);
225 strcat(new, text);
226
227 strcat(new, &(*mes)[pos + m]);
228 tmp = *mes;
229 *mes = new;
230 g_free(tmp);
231 } 1526 }
232 1527
233 static GtkWidget *tree; 1528 static GtkWidget *tree;
234 static GtkWidget *bad_entry; 1529 static GtkWidget *bad_entry;
235 static GtkWidget *good_entry; 1530 static GtkWidget *good_entry;
238 1533
239 static void on_edited(GtkCellRendererText *cellrenderertext, 1534 static void on_edited(GtkCellRendererText *cellrenderertext,
240 gchar *path, gchar *arg2, gpointer data) 1535 gchar *path, gchar *arg2, gpointer data)
241 { 1536 {
242 GtkTreeIter iter; 1537 GtkTreeIter iter;
243 GValue val; 1538 GValue val = {0, };
244 if(arg2[0] == '\0') { 1539
1540 if (arg2[0] == '\0') {
245 gdk_beep(); 1541 gdk_beep();
246 return; 1542 return;
247 } 1543 }
248 memset(&val, 0, sizeof(val)); 1544
249 g_return_if_fail(gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(model), &iter, path)); 1545 g_return_if_fail(gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(model), &iter, path));
250 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, GPOINTER_TO_INT(data), &val); 1546 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, GPOINTER_TO_INT(data), &val);
251 if(strcmp(arg2, g_value_get_string(&val))) { 1547
1548 if (strcmp(arg2, g_value_get_string(&val))) {
252 gtk_list_store_set(model, &iter, GPOINTER_TO_INT(data), arg2, -1); 1549 gtk_list_store_set(model, &iter, GPOINTER_TO_INT(data), arg2, -1);
253 save_list(); 1550 save_list();
254 } 1551 }
255 g_value_unset(&val); 1552 g_value_unset(&val);
256 } 1553 }
257 1554
258 static void list_add_new() 1555 static void list_add_new()
259 { 1556 {
260 GtkTreeIter iter; 1557 GtkTreeIter iter;
1558
1559 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) {
1560 char *tmpword = g_utf8_casefold(gtk_entry_get_text(GTK_ENTRY(bad_entry)), -1);
1561
1562 do {
1563 GValue val0 = {0, };
1564 char *bad;
1565
1566 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, 0, &val0);
1567 bad = g_utf8_casefold(g_value_get_string(&val0), -1);
1568
1569 if (!strcmp(bad, tmpword)) {
1570 g_value_unset(&val0);
1571 g_free(bad);
1572 g_free(tmpword);
1573
1574 gaim_notify_error(NULL, _("Duplicate Correction"),
1575 _("The specified word already exists in the correction list."),
1576 gtk_entry_get_text(GTK_ENTRY(bad_entry)));
1577 return;
1578 }
1579
1580 g_value_unset(&val0);
1581 g_free(bad);
1582
1583 } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter));
1584
1585 g_free(tmpword);
1586 }
1587
261 1588
262 gtk_list_store_append(model, &iter); 1589 gtk_list_store_append(model, &iter);
263 gtk_list_store_set(model, &iter, 1590 gtk_list_store_set(model, &iter,
264 0, gtk_entry_get_text(GTK_ENTRY(bad_entry)), 1591 0, gtk_entry_get_text(GTK_ENTRY(bad_entry)),
265 1, gtk_entry_get_text(GTK_ENTRY(good_entry)), 1592 1, gtk_entry_get_text(GTK_ENTRY(good_entry)),
276 { 1603 {
277 GSList **list = (GSList **)data; 1604 GSList **list = (GSList **)data;
278 *list = g_slist_append(*list, gtk_tree_path_copy(path) ); 1605 *list = g_slist_append(*list, gtk_tree_path_copy(path) );
279 } 1606 }
280 1607
281
282 static void remove_row(void *data1, gpointer data2) 1608 static void remove_row(void *data1, gpointer data2)
283 { 1609 {
284 GtkTreePath *path = (GtkTreePath*)data1; 1610 GtkTreePath *path = (GtkTreePath*)data1;
285 GtkTreeIter iter; 1611 GtkTreeIter iter;
286 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path); 1612 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path);
312 1638
313 name = g_build_filename(gaim_user_dir(), "dict", NULL); 1639 name = g_build_filename(gaim_user_dir(), "dict", NULL);
314 strcpy(tempfilename, name); 1640 strcpy(tempfilename, name);
315 strcat(tempfilename,".XXXXXX"); 1641 strcat(tempfilename,".XXXXXX");
316 fd = g_mkstemp(tempfilename); 1642 fd = g_mkstemp(tempfilename);
317 if(fd<0) { 1643 if (fd < 0) {
318 perror(tempfilename); 1644 perror(tempfilename);
319 g_free(name); 1645 g_free(name);
320 return; 1646 return;
321 } 1647 }
322 if (!(f = fdopen(fd, "w"))) { 1648 if (!(f = fdopen(fd, "w"))) {
326 return; 1652 return;
327 } 1653 }
328 1654
329 fchmod(fd, S_IRUSR | S_IWUSR); 1655 fchmod(fd, S_IRUSR | S_IWUSR);
330 1656
331 if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) { 1657 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) {
332 do { 1658 do {
333 GValue val0, val1; 1659 GValue val0 = {0, };
334 memset(&val0, 0, sizeof(val0)); 1660 GValue val1 = {0, };
335 memset(&val1, 0, sizeof(val1)); 1661
336 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, 0, &val0); 1662 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, 0, &val0);
337 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, 1, &val1); 1663 gtk_tree_model_get_value(GTK_TREE_MODEL(model), &iter, 1, &val1);
1664
338 fprintf(f, "BAD %s\nGOOD %s\n\n", g_value_get_string(&val0), g_value_get_string(&val1)); 1665 fprintf(f, "BAD %s\nGOOD %s\n\n", g_value_get_string(&val0), g_value_get_string(&val1));
1666
339 g_value_unset(&val0); 1667 g_value_unset(&val0);
340 g_value_unset(&val1); 1668 g_value_unset(&val1);
341 } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter)); 1669
342 } 1670 } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter));
343 if(fclose(f)) { 1671 }
1672
1673 if (fclose(f)) {
344 gaim_debug(GAIM_DEBUG_ERROR, "spellchk", 1674 gaim_debug(GAIM_DEBUG_ERROR, "spellchk",
345 "Error writing to %s: %m\n", tempfilename); 1675 "Error writing to %s: %m\n", tempfilename);
346 g_unlink(tempfilename); 1676 g_unlink(tempfilename);
347 g_free(name); 1677 g_free(name);
348 return; 1678 return;
366 gtk_widget_set_sensitive((GtkWidget*)data, is); 1696 gtk_widget_set_sensitive((GtkWidget*)data, is);
367 } 1697 }
368 1698
369 static gboolean non_empty(const char *s) 1699 static gboolean non_empty(const char *s)
370 { 1700 {
371 while(*s && g_ascii_isspace(*s)) 1701 while (*s && g_ascii_isspace(*s))
372 s++; 1702 s++;
373 return *s; 1703 return *s;
374 } 1704 }
375 1705
376 static void on_entry_changed(GtkEditable *editable, gpointer data) 1706 static void on_entry_changed(GtkEditable *editable, gpointer data)
389 { 1719 {
390 void *conv_handle = gaim_conversations_get_handle(); 1720 void *conv_handle = gaim_conversations_get_handle();
391 1721
392 load_conf(); 1722 load_conf();
393 1723
394 gaim_signal_connect(conv_handle, "writing-im-msg", 1724 gaim_signal_connect(conv_handle, "conversation-created",
395 plugin, GAIM_CALLBACK(substitute_words), NULL); 1725 plugin, GAIM_CALLBACK(spellchk_new_attach), NULL);
396 gaim_signal_connect(conv_handle, "writing-chat-msg",
397 plugin, GAIM_CALLBACK(substitute_words), NULL);
398 1726
399 return TRUE; 1727 return TRUE;
400 } 1728 }
401 1729
402 static GtkWidget * 1730 static GtkWidget *
410 GtkTreeViewColumn *column; 1738 GtkTreeViewColumn *column;
411 1739
412 sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); 1740 sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
413 1741
414 ret = gtk_vbox_new(FALSE, 18); 1742 ret = gtk_vbox_new(FALSE, 18);
415 gtk_container_set_border_width (GTK_CONTAINER (ret), 12); 1743 gtk_container_set_border_width (GTK_CONTAINER(ret), 12);
416 1744
417 vbox = gaim_gtk_make_frame(ret, _("Text Replacements")); 1745 vbox = gaim_gtk_make_frame(ret, _("Text Replacements"));
418 gtk_container_set_border_width(GTK_CONTAINER(vbox), 4); 1746 gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
419 gtk_widget_set_size_request(vbox, 300, -1); 1747 gtk_widget_set_size_request(vbox, 300, -1);
420 gtk_widget_show (vbox); 1748 gtk_widget_show(vbox);
421 1749
422 win = gtk_scrolled_window_new(0, 0); 1750 win = gtk_scrolled_window_new(0, 0);
423 gtk_container_add(GTK_CONTAINER(vbox), win); 1751 gtk_container_add(GTK_CONTAINER(vbox), win);
424 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(win), 1752 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(win),
425 GTK_SHADOW_IN); 1753 GTK_SHADOW_IN);
426 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (win), 1754 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(win),
427 GTK_POLICY_AUTOMATIC, 1755 GTK_POLICY_AUTOMATIC,
428 GTK_POLICY_AUTOMATIC); 1756 GTK_POLICY_AUTOMATIC);
429 gtk_widget_show(win); 1757 gtk_widget_show(win);
430 1758
431 tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model)); 1759 tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
432 /* gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree), TRUE); */ 1760 /* gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree), TRUE); */
433 gtk_widget_set_size_request(tree, 260,200); 1761 gtk_widget_set_size_request(tree, 260,200);
434 1762
435 renderer = gtk_cell_renderer_text_new (); 1763 renderer = gtk_cell_renderer_text_new();
436 g_object_set (G_OBJECT (renderer), 1764 g_object_set(G_OBJECT(renderer),
437 "editable", TRUE, 1765 "editable", TRUE,
438 NULL); 1766 NULL);
439 g_signal_connect(G_OBJECT(renderer), "edited", 1767 g_signal_connect(G_OBJECT(renderer), "edited",
440 G_CALLBACK(on_edited), GINT_TO_POINTER(0)); 1768 G_CALLBACK(on_edited), GINT_TO_POINTER(0));
441 column = gtk_tree_view_column_new_with_attributes (_("You type"), 1769 column = gtk_tree_view_column_new_with_attributes(_("You type"),
442 renderer, "text", BAD_COLUMN, NULL); 1770 renderer, "text", BAD_COLUMN, NULL);
443 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); 1771 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
444 gtk_tree_view_column_set_fixed_width(column, 130); 1772 gtk_tree_view_column_set_fixed_width(column, 130);
445 /* gtk_tree_view_column_set_resizable(column, TRUE); */ 1773 /* gtk_tree_view_column_set_resizable(column, TRUE); */
446 gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column); 1774 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
447 renderer = gtk_cell_renderer_text_new (); 1775 renderer = gtk_cell_renderer_text_new();
448 g_object_set (G_OBJECT (renderer), 1776 g_object_set(G_OBJECT(renderer),
449 "editable", TRUE, 1777 "editable", TRUE,
450 NULL); 1778 NULL);
451 g_signal_connect(G_OBJECT(renderer), "edited", 1779 g_signal_connect(G_OBJECT(renderer), "edited",
452 G_CALLBACK(on_edited), GINT_TO_POINTER(1)); 1780 G_CALLBACK(on_edited), GINT_TO_POINTER(1));
453 column = gtk_tree_view_column_new_with_attributes (_("You send"), 1781 column = gtk_tree_view_column_new_with_attributes(_("You send"),
454 renderer, "text", GOOD_COLUMN, NULL); 1782 renderer, "text", GOOD_COLUMN, NULL);
455 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); 1783 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
456 gtk_tree_view_column_set_fixed_width(column, 130); 1784 gtk_tree_view_column_set_fixed_width(column, 130);
457 /* gtk_tree_view_column_set_resizable(column, TRUE); */ 1785 /* gtk_tree_view_column_set_resizable(column, TRUE); */
458 gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column); 1786 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
459 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)), 1787 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)),
460 GTK_SELECTION_MULTIPLE); 1788 GTK_SELECTION_MULTIPLE);
461 gtk_container_add(GTK_CONTAINER(win), tree); 1789 gtk_container_add(GTK_CONTAINER(win), tree);
462 gtk_widget_show(tree); 1790 gtk_widget_show(tree);
463 1791