pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
Use Meson summary() function.
2021-07-27, Elliott Sales de Andrade
cb640ea0f315
Use Meson summary() function.
Now that we require at least 0.52, we can use Meson's builtin summary printing to display the results of configuration.
Testing Done:
Configured with defaults, and with pixmaps disabled to trigger the warning: https://asciinema.org/a/mV2oxOoVCJNdmrPwgqqUJ3mkU?t=17
Reviewed at https://reviews.imfreedom.org/r/848/
/*
* Purple - Replace certain misspelled words with their correct form.
*
* Signification changes were made by Benjamin Kahn ("xkahn") and
* Richard Laager ("rlaager") in April 2005--you may want to contact
* them if you have questions.
*
* Pidgin is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
* source distribution.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
*/
/*
* A lot of this code (especially the config code) was taken directly
* or nearly directly from xchat, version 1.4.2 by Peter Zelezny and others.
*/
#include
<stdio.h>
#include
<string.h>
#include
<sys/types.h>
#include
<glib/gi18n-lib.h>
#include
<purple.h>
#include
<pidgin.h>
#define SPELLCHECK_PLUGIN_ID "gtk-spellcheck"
#define SPELLCHK_OBJECT_KEY "spellchk"
enum
{
BAD_COLUMN
,
GOOD_COLUMN
,
WORD_ONLY_COLUMN
,
CASE_SENSITIVE_COLUMN
,
N_COLUMNS
};
struct
_spellchk
{
GtkTextView
*
view
;
GtkTextMark
*
mark_insert_start
;
GtkTextMark
*
mark_insert_end
;
gchar
*
word
;
gboolean
inserting
;
gboolean
ignore_correction
;
gboolean
ignore_correction_on_send
;
gint
pos
;
};
typedef
struct
_spellchk
spellchk
;
static
GtkListStore
*
model
;
static
gboolean
is_word_uppercase
(
const
gchar
*
word
)
{
for
(;
word
[
0
]
!=
'\0'
;
word
=
g_utf8_find_next_char
(
word
,
NULL
))
{
gunichar
c
=
g_utf8_get_char
(
word
);
if
(
!
(
g_unichar_isupper
(
c
)
||
g_unichar_ispunct
(
c
)
||
g_unichar_isspace
(
c
)))
return
FALSE
;
}
return
TRUE
;
}
static
gboolean
is_word_lowercase
(
const
gchar
*
word
)
{
for
(;
word
[
0
]
!=
'\0'
;
word
=
g_utf8_find_next_char
(
word
,
NULL
))
{
gunichar
c
=
g_utf8_get_char
(
word
);
if
(
!
(
g_unichar_islower
(
c
)
||
g_unichar_ispunct
(
c
)
||
g_unichar_isspace
(
c
)))
return
FALSE
;
}
return
TRUE
;
}
static
gboolean
is_word_proper
(
const
gchar
*
word
)
{
if
(
word
[
0
]
==
'\0'
)
return
FALSE
;
if
(
!
g_unichar_isupper
(
g_utf8_get_char_validated
(
word
,
-1
)))
return
FALSE
;
return
is_word_lowercase
(
g_utf8_offset_to_pointer
(
word
,
1
));
}
static
gchar
*
make_word_proper
(
const
gchar
*
word
)
{
char
buf
[
7
];
gchar
*
lower
=
g_utf8_strdown
(
word
,
-1
);
gint
bytes
;
gchar
*
ret
;
bytes
=
g_unichar_to_utf8
(
g_unichar_toupper
(
g_utf8_get_char
(
word
)),
buf
);
g_assert
(
bytes
>=
0
);
buf
[
MIN
((
gsize
)
bytes
,
sizeof
(
buf
)
-
1
)]
=
'\0'
;
ret
=
g_strconcat
(
buf
,
g_utf8_offset_to_pointer
(
lower
,
1
),
NULL
);
g_free
(
lower
);
return
ret
;
}
static
gboolean
substitute_simple_buffer
(
GtkTextBuffer
*
buffer
)
{
GtkTextIter
start
;
GtkTextIter
end
;
GtkTreeIter
treeiter
;
gchar
*
text
=
NULL
;
gtk_text_buffer_get_iter_at_offset
(
buffer
,
&
start
,
0
);
gtk_text_buffer_get_iter_at_offset
(
buffer
,
&
end
,
0
);
gtk_text_iter_forward_to_end
(
&
end
);
text
=
gtk_text_buffer_get_text
(
buffer
,
&
start
,
&
end
,
FALSE
);
if
(
gtk_tree_model_get_iter_first
(
GTK_TREE_MODEL
(
model
),
&
treeiter
)
&&
text
)
{
do
{
GValue
val1
;
const
gchar
*
bad
;
gchar
*
cursor
;
glong
char_pos
;
val1
.
g_type
=
0
;
gtk_tree_model_get_value
(
GTK_TREE_MODEL
(
model
),
&
treeiter
,
WORD_ONLY_COLUMN
,
&
val1
);
if
(
g_value_get_boolean
(
&
val1
))
{
g_value_unset
(
&
val1
);
continue
;
}
g_value_unset
(
&
val1
);
gtk_tree_model_get_value
(
GTK_TREE_MODEL
(
model
),
&
treeiter
,
BAD_COLUMN
,
&
val1
);
bad
=
g_value_get_string
(
&
val1
);
/* using g_utf8_* to get /character/ offsets instead of byte offsets for buffer */
if
((
cursor
=
g_strrstr
(
text
,
bad
)))
{
GValue
val2
;
const
gchar
*
good
;
val2
.
g_type
=
0
;
gtk_tree_model_get_value
(
GTK_TREE_MODEL
(
model
),
&
treeiter
,
GOOD_COLUMN
,
&
val2
);
good
=
g_value_get_string
(
&
val2
);
char_pos
=
g_utf8_pointer_to_offset
(
text
,
cursor
);
gtk_text_buffer_get_iter_at_offset
(
buffer
,
&
start
,
char_pos
);
gtk_text_buffer_get_iter_at_offset
(
buffer
,
&
end
,
char_pos
+
g_utf8_strlen
(
bad
,
-1
));
gtk_text_buffer_delete
(
buffer
,
&
start
,
&
end
);
gtk_text_buffer_get_iter_at_offset
(
buffer
,
&
start
,
char_pos
);
gtk_text_buffer_insert
(
buffer
,
&
start
,
good
,
-1
);
g_value_unset
(
&
val2
);
g_free
(
text
);
g_value_unset
(
&
val1
);
return
TRUE
;
}
g_value_unset
(
&
val1
);
}
while
(
gtk_tree_model_iter_next
(
GTK_TREE_MODEL
(
model
),
&
treeiter
));
}
g_free
(
text
);
return
FALSE
;
}
static
gchar
*
substitute_word
(
gchar
*
word
)
{
GtkTreeIter
iter
;
gchar
*
outword
;
gchar
*
lowerword
;
gchar
*
foldedword
;
if
(
word
==
NULL
)
return
NULL
;
lowerword
=
g_utf8_strdown
(
word
,
-1
);
foldedword
=
g_utf8_casefold
(
word
,
-1
);
if
(
gtk_tree_model_get_iter_first
(
GTK_TREE_MODEL
(
model
),
&
iter
))
{
do
{
GValue
val1
;
gboolean
case_sensitive
;
const
char
*
bad
;
gchar
*
tmpbad
=
NULL
;
val1
.
g_type
=
0
;
gtk_tree_model_get_value
(
GTK_TREE_MODEL
(
model
),
&
iter
,
WORD_ONLY_COLUMN
,
&
val1
);
if
(
!
g_value_get_boolean
(
&
val1
))
{
g_value_unset
(
&
val1
);
continue
;
}
g_value_unset
(
&
val1
);
gtk_tree_model_get_value
(
GTK_TREE_MODEL
(
model
),
&
iter
,
CASE_SENSITIVE_COLUMN
,
&
val1
);
case_sensitive
=
g_value_get_boolean
(
&
val1
);
g_value_unset
(
&
val1
);
gtk_tree_model_get_value
(
GTK_TREE_MODEL
(
model
),
&
iter
,
BAD_COLUMN
,
&
val1
);
bad
=
g_value_get_string
(
&
val1
);
if
((
case_sensitive
&&
purple_strequal
(
bad
,
word
))
||
(
!
case_sensitive
&&
(
purple_strequal
(
bad
,
lowerword
)
||
(
!
is_word_lowercase
(
bad
)
&&
purple_strequal
((
tmpbad
=
g_utf8_casefold
(
bad
,
-1
)),
foldedword
)))))
{
GValue
val2
;
const
char
*
good
;
g_free
(
tmpbad
);
val2
.
g_type
=
0
;
gtk_tree_model_get_value
(
GTK_TREE_MODEL
(
model
),
&
iter
,
GOOD_COLUMN
,
&
val2
);
good
=
g_value_get_string
(
&
val2
);
if
(
!
case_sensitive
&&
is_word_lowercase
(
bad
)
&&
is_word_lowercase
(
good
))
{
if
(
is_word_uppercase
(
word
))
outword
=
g_utf8_strup
(
good
,
-1
);
else
if
(
is_word_proper
(
word
))
outword
=
make_word_proper
(
good
);
else
outword
=
g_strdup
(
good
);
}
else
outword
=
g_strdup
(
good
);
g_value_unset
(
&
val1
);
g_value_unset
(
&
val2
);
g_free
(
lowerword
);
g_free
(
foldedword
);
return
outword
;
}
g_value_unset
(
&
val1
);
g_free
(
tmpbad
);
}
while
(
gtk_tree_model_iter_next
(
GTK_TREE_MODEL
(
model
),
&
iter
));
}
g_free
(
lowerword
);
g_free
(
foldedword
);
return
NULL
;
}
static
void
spellchk_free
(
spellchk
*
spell
)
{
GtkTextBuffer
*
buffer
;
g_return_if_fail
(
spell
!=
NULL
);
buffer
=
gtk_text_view_get_buffer
(
spell
->
view
);
g_signal_handlers_disconnect_matched
(
buffer
,
G_SIGNAL_MATCH_DATA
,
0
,
0
,
NULL
,
NULL
,
spell
);
g_free
(
spell
->
word
);
g_free
(
spell
);
}
/* Pango doesn't know about the "'" character. Let's fix that. */
static
gboolean
spellchk_inside_word
(
GtkTextIter
*
iter
)
{
gunichar
ucs4_char
=
gtk_text_iter_get_char
(
iter
);
gchar
*
utf8_str
;
gchar
c
=
0
;
utf8_str
=
g_ucs4_to_utf8
(
&
ucs4_char
,
1
,
NULL
,
NULL
,
NULL
);
if
(
utf8_str
!=
NULL
)
{
c
=
utf8_str
[
0
];
g_free
(
utf8_str
);
}
/* Hack because otherwise typing things like U.S. gets difficult
* if you have 'u' -> 'you' set as a correction...
*
* Part 1 of 2: This marks . as being an inside-word character. */
if
(
c
==
'.'
)
return
TRUE
;
if
(
c
==
'+'
)
return
TRUE
;
if
(
c
==
'-'
)
return
TRUE
;
/* Avoid problems with \r, for example (SF #1289031). */
if
(
c
==
'\\'
)
return
TRUE
;
if
(
gtk_text_iter_inside_word
(
iter
)
==
TRUE
)
return
TRUE
;
if
(
c
==
'\''
)
{
gboolean
result
=
gtk_text_iter_backward_char
(
iter
);
gboolean
output
=
gtk_text_iter_inside_word
(
iter
);
if
(
result
)
{
/*
* Hack so that "u'll" will correct correctly.
*/
ucs4_char
=
gtk_text_iter_get_char
(
iter
);
utf8_str
=
g_ucs4_to_utf8
(
&
ucs4_char
,
1
,
NULL
,
NULL
,
NULL
);
if
(
utf8_str
!=
NULL
)
{
c
=
utf8_str
[
0
];
g_free
(
utf8_str
);
if
(
c
==
'u'
||
c
==
'U'
)
{
gtk_text_iter_forward_char
(
iter
);
return
FALSE
;
}
}
gtk_text_iter_forward_char
(
iter
);
}
return
output
;
}
else
if
(
c
==
'&'
)
return
TRUE
;
return
FALSE
;
}
static
gboolean
spellchk_backward_word_start
(
GtkTextIter
*
iter
)
{
int
output
;
int
result
;
output
=
gtk_text_iter_backward_word_start
(
iter
);
/* It didn't work... */
if
(
!
output
)
return
FALSE
;
while
(
spellchk_inside_word
(
iter
))
{
result
=
gtk_text_iter_backward_char
(
iter
);
/* We can't go backwards anymore? We're at the beginning of the word. */
if
(
!
result
)
return
TRUE
;
if
(
!
spellchk_inside_word
(
iter
))
{
gtk_text_iter_forward_char
(
iter
);
return
TRUE
;
}
output
=
gtk_text_iter_backward_word_start
(
iter
);
if
(
!
output
)
return
FALSE
;
}
return
TRUE
;
}
static
gboolean
check_range
(
spellchk
*
spell
,
GtkTextBuffer
*
buffer
,
GtkTextIter
start
,
GtkTextIter
end
,
gboolean
sending
)
{
gboolean
replaced
;
gboolean
result
;
gchar
*
tmp
;
int
period_count
=
0
;
gchar
*
word
;
GtkTextMark
*
mark
;
GtkTextIter
pos
;
if
((
replaced
=
substitute_simple_buffer
(
buffer
)))
{
mark
=
gtk_text_buffer_get_insert
(
buffer
);
gtk_text_buffer_get_iter_at_mark
(
buffer
,
&
pos
,
mark
);
spell
->
pos
=
gtk_text_iter_get_offset
(
&
pos
);
gtk_text_buffer_get_iter_at_mark
(
buffer
,
&
start
,
mark
);
gtk_text_buffer_get_iter_at_mark
(
buffer
,
&
end
,
mark
);
}
if
(
!
sending
)
{
/* We need to go backwords to find out if we are inside a word or not. */
gtk_text_iter_backward_char
(
&
end
);
if
(
spellchk_inside_word
(
&
end
))
{
gtk_text_iter_forward_char
(
&
end
);
return
replaced
;
/* We only pay attention to whole words. */
}
}
/* We could be in the middle of a whitespace block. Check for that. */
result
=
gtk_text_iter_backward_char
(
&
end
);
if
(
!
spellchk_inside_word
(
&
end
))
{
if
(
result
)
gtk_text_iter_forward_char
(
&
end
);
return
replaced
;
}
if
(
result
)
gtk_text_iter_forward_char
(
&
end
);
/* Move backwards to the beginning of the word. */
spellchk_backward_word_start
(
&
start
);
g_free
(
spell
->
word
);
spell
->
word
=
gtk_text_iter_get_text
(
&
start
,
&
end
);
/* Hack because otherwise typing things like U.S. gets difficult
* if you have 'u' -> 'you' set as a correction...
*
* Part 2 of 2: This chops periods off the end of the word so
* the right substitution entry is found. */
tmp
=
g_strdup
(
spell
->
word
);
if
(
tmp
!=
NULL
&&
*
tmp
!=
'\0'
)
{
gchar
*
c
;
for
(
c
=
tmp
+
strlen
(
tmp
)
-
1
;
c
!=
tmp
;
c
--
)
{
if
(
*
c
==
'.'
)
{
*
c
=
'\0'
;
period_count
++
;
}
else
break
;
}
}
if
((
word
=
substitute_word
(
tmp
)))
{
GtkTextMark
*
mark
;
GtkTextIter
pos
;
gchar
*
tmp2
;
int
i
;
for
(
i
=
1
;
i
<=
period_count
;
i
++
)
{
tmp2
=
g_strconcat
(
word
,
"."
,
NULL
);
g_free
(
word
);
word
=
tmp2
;
}
gtk_text_buffer_delete
(
buffer
,
&
start
,
&
end
);
gtk_text_buffer_insert
(
buffer
,
&
start
,
word
,
-1
);
mark
=
gtk_text_buffer_get_insert
(
buffer
);
gtk_text_buffer_get_iter_at_mark
(
buffer
,
&
pos
,
mark
);
spell
->
pos
=
gtk_text_iter_get_offset
(
&
pos
);
g_free
(
word
);
g_free
(
tmp
);
return
TRUE
;
}
g_free
(
tmp
);
g_free
(
spell
->
word
);
spell
->
word
=
NULL
;
return
replaced
;
}
/* insertion works like this:
* - before the text is inserted, we mark the position in the buffer.
* - after the text is inserted, we see where our mark is and use that and
* the current position to check the entire range of inserted text.
*
* this may be overkill for the common case (inserting one character). */
static
void
insert_text_before
(
GtkTextBuffer
*
buffer
,
GtkTextIter
*
iter
,
gchar
*
text
,
gint
len
,
spellchk
*
spell
)
{
if
(
spell
->
inserting
==
TRUE
)
return
;
spell
->
inserting
=
TRUE
;
g_free
(
spell
->
word
);
spell
->
word
=
NULL
;
gtk_text_buffer_move_mark
(
buffer
,
spell
->
mark_insert_start
,
iter
);
}
static
void
insert_text_after
(
GtkTextBuffer
*
buffer
,
GtkTextIter
*
iter
,
gchar
*
text
,
gint
len
,
spellchk
*
spell
)
{
GtkTextIter
start
,
end
;
GtkTextMark
*
mark
;
spell
->
ignore_correction_on_send
=
FALSE
;
if
(
spell
->
ignore_correction
)
{
spell
->
ignore_correction
=
FALSE
;
return
;
}
/* we need to check a range of text. */
gtk_text_buffer_get_iter_at_mark
(
buffer
,
&
start
,
spell
->
mark_insert_start
);
if
(
len
==
1
)
check_range
(
spell
,
buffer
,
start
,
*
iter
,
FALSE
);
/* if check_range modified the buffer, iter has been invalidated */
mark
=
gtk_text_buffer_get_insert
(
buffer
);
gtk_text_buffer_get_iter_at_mark
(
buffer
,
&
end
,
mark
);
gtk_text_buffer_move_mark
(
buffer
,
spell
->
mark_insert_end
,
&
end
);
spell
->
inserting
=
FALSE
;
}
static
void
delete_range_after
(
GtkTextBuffer
*
buffer
,
GtkTextIter
*
start
,
GtkTextIter
*
end
,
spellchk
*
spell
)
{
GtkTextIter
start2
,
end2
;
GtkTextMark
*
mark
;
GtkTextIter
pos
;
gint
place
;
spell
->
ignore_correction_on_send
=
FALSE
;
if
(
!
spell
->
word
)
return
;
if
(
spell
->
inserting
==
TRUE
)
return
;
spell
->
inserting
=
TRUE
;
mark
=
gtk_text_buffer_get_insert
(
buffer
);
gtk_text_buffer_get_iter_at_mark
(
buffer
,
&
pos
,
mark
);
place
=
gtk_text_iter_get_offset
(
&
pos
);
if
((
place
+
1
)
!=
spell
->
pos
)
{
g_free
(
spell
->
word
);
spell
->
word
=
NULL
;
return
;
}
gtk_text_buffer_get_iter_at_mark
(
buffer
,
&
start2
,
spell
->
mark_insert_start
);
gtk_text_buffer_get_iter_at_mark
(
buffer
,
&
end2
,
spell
->
mark_insert_end
);
gtk_text_buffer_delete
(
buffer
,
&
start2
,
&
end2
);
gtk_text_buffer_insert
(
buffer
,
&
start2
,
spell
->
word
,
-1
);
spell
->
ignore_correction
=
TRUE
;
spell
->
ignore_correction_on_send
=
TRUE
;
spell
->
inserting
=
FALSE
;
g_free
(
spell
->
word
);
spell
->
word
=
NULL
;
}
static
void
message_send_cb
(
GtkWidget
*
widget
,
spellchk
*
spell
)
{
GtkTextBuffer
*
buffer
;
GtkTextIter
start
,
end
;
GtkTextMark
*
mark
;
gboolean
replaced
;
if
(
spell
->
ignore_correction_on_send
)
{
spell
->
ignore_correction_on_send
=
FALSE
;
return
;
}
#if 0
if (!purple_prefs_get_bool("/plugins/gtk/spellchk/last_word_replace"))
return;
#endif
buffer
=
gtk_text_view_get_buffer
(
spell
->
view
);
gtk_text_buffer_get_end_iter
(
buffer
,
&
start
);
gtk_text_buffer_get_end_iter
(
buffer
,
&
end
);
spell
->
inserting
=
TRUE
;
replaced
=
check_range
(
spell
,
buffer
,
start
,
end
,
TRUE
);
spell
->
inserting
=
FALSE
;
/* if check_range modified the buffer, iter has been invalidated */
mark
=
gtk_text_buffer_get_insert
(
buffer
);
gtk_text_buffer_get_iter_at_mark
(
buffer
,
&
end
,
mark
);
gtk_text_buffer_move_mark
(
buffer
,
spell
->
mark_insert_end
,
&
end
);
if
(
replaced
)
{
g_signal_stop_emission_by_name
(
widget
,
"message_send"
);
spell
->
ignore_correction_on_send
=
TRUE
;
}
}
static
void
spellchk_new_attach
(
PurpleConversation
*
conv
)
{
spellchk
*
spell
;
GtkTextBuffer
*
buffer
;
GtkTextIter
start
,
end
;
PidginConversation
*
gtkconv
;
GtkTextView
*
view
;
gtkconv
=
PIDGIN_CONVERSATION
(
conv
);
view
=
GTK_TEXT_VIEW
(
gtkconv
->
entry
);
spell
=
g_object_get_data
(
G_OBJECT
(
view
),
SPELLCHK_OBJECT_KEY
);
if
(
spell
!=
NULL
)
return
;
/* attach to the widget */
spell
=
g_new0
(
spellchk
,
1
);
spell
->
view
=
view
;
g_object_set_data_full
(
G_OBJECT
(
view
),
SPELLCHK_OBJECT_KEY
,
spell
,
(
GDestroyNotify
)
spellchk_free
);
buffer
=
gtk_text_view_get_buffer
(
view
);
/* we create the mark here, but we don't use it until text is
* inserted, so we don't really care where iter points. */
gtk_text_buffer_get_bounds
(
buffer
,
&
start
,
&
end
);
spell
->
mark_insert_start
=
gtk_text_buffer_create_mark
(
buffer
,
"spellchk-insert-start"
,
&
start
,
TRUE
);
spell
->
mark_insert_end
=
gtk_text_buffer_create_mark
(
buffer
,
"spellchk-insert-end"
,
&
start
,
TRUE
);
g_signal_connect_after
(
G_OBJECT
(
buffer
),
"delete-range"
,
G_CALLBACK
(
delete_range_after
),
spell
);
g_signal_connect
(
G_OBJECT
(
buffer
),
"insert-text"
,
G_CALLBACK
(
insert_text_before
),
spell
);
g_signal_connect_after
(
G_OBJECT
(
buffer
),
"insert-text"
,
G_CALLBACK
(
insert_text_after
),
spell
);
g_signal_connect
(
G_OBJECT
(
gtkconv
->
entry
),
"message_send"
,
G_CALLBACK
(
message_send_cb
),
spell
);
}
static
int
buf_get_line
(
char
*
ibuf
,
char
**
buf
,
gsize
*
position
,
gsize
len
)
{
gsize
pos
=
*
position
;
gsize
spos
=
pos
;
if
(
pos
==
len
)
return
0
;
while
(
!
(
ibuf
[
pos
]
==
'\n'
||
(
ibuf
[
pos
]
==
'\r'
&&
ibuf
[
pos
+
1
]
!=
'\n'
)))
{
pos
++
;
if
(
pos
==
len
)
return
0
;
}
if
(
pos
!=
0
&&
ibuf
[
pos
]
==
'\n'
&&
ibuf
[
pos
-
1
]
==
'\r'
)
ibuf
[
pos
-
1
]
=
'\0'
;
ibuf
[
pos
]
=
'\0'
;
*
buf
=
&
ibuf
[
spos
];
pos
++
;
*
position
=
pos
;
return
1
;
}
static
void
load_conf
(
void
)
{
/* Corrections to change "...", "(c)", "(r)", and "(tm)" to their
* Unicode character equivalents were not added here even though
* they existed in the source list(s). I think these corrections
* would be more trouble than they're worth.
*/
const
char
*
const
defaultconf
=
"BAD abbout
\n
GOOD about
\n
"
"BAD abotu
\n
GOOD about
\n
"
"BAD abouta
\n
GOOD about a
\n
"
"BAD aboutit
\n
GOOD about it
\n
"
"BAD aboutthe
\n
GOOD about the
\n
"
"BAD abscence
\n
GOOD absence
\n
"
"BAD accesories
\n
GOOD accessories
\n
"
"BAD accidant
\n
GOOD accident
\n
"
"BAD accomodate
\n
GOOD accommodate
\n
"
"BAD accordingto
\n
GOOD according to
\n
"
"BAD accross
\n
GOOD across
\n
"
"BAD acheive
\n
GOOD achieve
\n
"
"BAD acheived
\n
GOOD achieved
\n
"
"BAD acheiving
\n
GOOD achieving
\n
"
"BAD acn
\n
GOOD can
\n
"
"BAD acommodate
\n
GOOD accommodate
\n
"
"BAD acomodate
\n
GOOD accommodate
\n
"
"BAD actualyl
\n
GOOD actually
\n
"
"BAD additinal
\n
GOOD additional
\n
"
"BAD addtional
\n
GOOD additional
\n
"
"BAD adequit
\n
GOOD adequate
\n
"
"BAD adequite
\n
GOOD adequate
\n
"
"BAD adn
\n
GOOD and
\n
"
"BAD advanage
\n
GOOD advantage
\n
"
"BAD affraid
\n
GOOD afraid
\n
"
"BAD afterthe
\n
GOOD after the
\n
"
"COMPLETE 0
\n
BAD againstt he
\n
GOOD against the
\n
"
"BAD aganist
\n
GOOD against
\n
"
"BAD aggresive
\n
GOOD aggressive
\n
"
"BAD agian
\n
GOOD again
\n
"
"BAD agreemeent
\n
GOOD agreement
\n
"
"BAD agreemeents
\n
GOOD agreements
\n
"
"BAD agreemnet
\n
GOOD agreement
\n
"
"BAD agreemnets
\n
GOOD agreements
\n
"
"BAD agressive
\n
GOOD aggressive
\n
"
"BAD agressiveness
\n
GOOD aggressiveness
\n
"
"BAD ahd
\n
GOOD had
\n
"
"BAD ahold
\n
GOOD a hold
\n
"
"BAD ahppen
\n
GOOD happen
\n
"
"BAD ahve
\n
GOOD have
\n
"
"BAD allready
\n
GOOD already
\n
"
"BAD allwasy
\n
GOOD always
\n
"
"BAD allwyas
\n
GOOD always
\n
"
"BAD almots
\n
GOOD almost
\n
"
"BAD almsot
\n
GOOD almost
\n
"
"BAD alomst
\n
GOOD almost
\n
"
"BAD alot
\n
GOOD a lot
\n
"
"BAD alraedy
\n
GOOD already
\n
"
"BAD alreayd
\n
GOOD already
\n
"
"BAD alreday
\n
GOOD already
\n
"
"BAD alwasy
\n
GOOD always
\n
"
"BAD alwats
\n
GOOD always
\n
"
"BAD alway
\n
GOOD always
\n
"
"BAD alwyas
\n
GOOD always
\n
"
"BAD amde
\n
GOOD made
\n
"
"BAD Ameria
\n
GOOD America
\n
"
"BAD amke
\n
GOOD make
\n
"
"BAD amkes
\n
GOOD makes
\n
"
"BAD anbd
\n
GOOD and
\n
"
"BAD andone
\n
GOOD and one
\n
"
"BAD andteh
\n
GOOD and the
\n
"
"BAD andthe
\n
GOOD and the
\n
"
"COMPLETE 0
\n
BAD andt he
\n
GOOD and the
\n
"
"BAD anothe
\n
GOOD another
\n
"
"BAD anual
\n
GOOD annual
\n
"
"BAD any1
\n
GOOD anyone
\n
"
"BAD apparant
\n
GOOD apparent
\n
"
"BAD apparrent
\n
GOOD apparent
\n
"
"BAD appearence
\n
GOOD appearance
\n
"
"BAD appeares
\n
GOOD appears
\n
"
"BAD applicaiton
\n
GOOD application
\n
"
"BAD applicaitons
\n
GOOD applications
\n
"
"BAD applyed
\n
GOOD applied
\n
"
"BAD appointiment
\n
GOOD appointment
\n
"
"BAD approrpiate
\n
GOOD appropriate
\n
"
"BAD approrpriate
\n
GOOD appropriate
\n
"
"BAD aquisition
\n
GOOD acquisition
\n
"
"BAD aquisitions
\n
GOOD acquisitions
\n
"
"BAD arent
\n
GOOD aren't
\n
"
"COMPLETE 0
\n
BAD aren;t
\n
GOOD aren't
\n
"
"BAD arguement
\n
GOOD argument
\n
"
"BAD arguements
\n
GOOD arguments
\n
"
"COMPLETE 0
\n
BAD arn't
\n
GOOD aren't
\n
"
"BAD arond
\n
GOOD around
\n
"
"BAD artical
\n
GOOD article
\n
"
"BAD articel
\n
GOOD article
\n
"
"BAD asdvertising
\n
GOOD advertising
\n
"
"COMPLETE 0
\n
BAD askt he
\n
GOOD ask the
\n
"
"BAD assistent
\n
GOOD assistant
\n
"
"BAD asthe
\n
GOOD as the
\n
"
"BAD atention
\n
GOOD attention
\n
"
"BAD atmospher
\n
GOOD atmosphere
\n
"
"BAD attentioin
\n
GOOD attention
\n
"
"BAD atthe
\n
GOOD at the
\n
"
"BAD audeince
\n
GOOD audience
\n
"
"BAD audiance
\n
GOOD audience
\n
"
"BAD authentification
\n
GOOD authentication
\n
"
"BAD availalbe
\n
GOOD available
\n
"
"BAD awya
\n
GOOD away
\n
"
"BAD aywa
\n
GOOD away
\n
"
"BAD b4
\n
GOOD before
\n
"
"BAD bakc
\n
GOOD back
\n
"
"BAD balence
\n
GOOD balance
\n
"
"BAD ballance
\n
GOOD balance
\n
"
"BAD baout
\n
GOOD about
\n
"
"BAD bcak
\n
GOOD back
\n
"
"BAD bcuz
\n
GOOD because
\n
"
"BAD beacuse
\n
GOOD because
\n
"
"BAD becasue
\n
GOOD because
\n
"
"BAD becaus
\n
GOOD because
\n
"
"BAD becausea
\n
GOOD because a
\n
"
"BAD becauseof
\n
GOOD because of
\n
"
"BAD becausethe
\n
GOOD because the
\n
"
"BAD becauseyou
\n
GOOD because you
\n
"
"COMPLETE 0
\n
BAD beckon call
\n
GOOD beck and call
\n
"
"BAD becomeing
\n
GOOD becoming
\n
"
"BAD becomming
\n
GOOD becoming
\n
"
"BAD becuase
\n
GOOD because
\n
"
"BAD becuse
\n
GOOD because
\n
"
"BAD befoer
\n
GOOD before
\n
"
"BAD beggining
\n
GOOD beginning
\n
"
"BAD begining
\n
GOOD beginning
\n
"
"BAD beginining
\n
GOOD beginning
\n
"
"BAD beleiev
\n
GOOD believe
\n
"
"BAD beleieve
\n
GOOD believe
\n
"
"BAD beleif
\n
GOOD belief
\n
"
"BAD beleive
\n
GOOD believe
\n
"
"BAD beleived
\n
GOOD believed
\n
"
"BAD beleives
\n
GOOD believes
\n
"
"BAD belive
\n
GOOD believe
\n
"
"BAD belived
\n
GOOD believed
\n
"
"BAD belives
\n
GOOD believes
\n
"
"BAD benifit
\n
GOOD benefit
\n
"
"BAD benifits
\n
GOOD benefits
\n
"
"BAD betwen
\n
GOOD between
\n
"
"BAD beutiful
\n
GOOD beautiful
\n
"
"BAD blase
\n
GOOD blas
\303\251\n
"
"BAD boxs
\n
GOOD boxes
\n
"
"BAD brodcast
\n
GOOD broadcast
\n
"
"BAD butthe
\n
GOOD but the
\n
"
"BAD bve
\n
GOOD be
\n
"
"COMPLETE 0
\n
BAD byt he
\n
GOOD by the
\n
"
"BAD cafe
\n
GOOD caf
\303\251\n
"
"BAD caharcter
\n
GOOD character
\n
"
"BAD calcullated
\n
GOOD calculated
\n
"
"BAD calulated
\n
GOOD calculated
\n
"
"BAD candidtae
\n
GOOD candidate
\n
"
"BAD candidtaes
\n
GOOD candidates
\n
"
"COMPLETE 0
\n
BAD case and point
\n
GOOD case in point
\n
"
"BAD cant
\n
GOOD can't
\n
"
"COMPLETE 0
\n
BAD can;t
\n
GOOD can't
\n
"
"COMPLETE 0
\n
BAD can't of been
\n
GOOD can't have been
\n
"
"BAD catagory
\n
GOOD category
\n
"
"BAD categiory
\n
GOOD category
\n
"
"BAD certian
\n
GOOD certain
\n
"
"BAD challange
\n
GOOD challenge
\n
"
"BAD challanges
\n
GOOD challenges
\n
"
"BAD chaneg
\n
GOOD change
\n
"
"BAD chanegs
\n
GOOD changes
\n
"
"BAD changable
\n
GOOD changeable
\n
"
"BAD changeing
\n
GOOD changing
\n
"
"BAD changng
\n
GOOD changing
\n
"
"BAD charachter
\n
GOOD character
\n
"
"BAD charachters
\n
GOOD characters
\n
"
"BAD charactor
\n
GOOD character
\n
"
"BAD charecter
\n
GOOD character
\n
"
"BAD charector
\n
GOOD character
\n
"
"BAD cheif
\n
GOOD chief
\n
"
"BAD chekc
\n
GOOD check
\n
"
"BAD chnage
\n
GOOD change
\n
"
"BAD cieling
\n
GOOD ceiling
\n
"
"BAD circut
\n
GOOD circuit
\n
"
"BAD claer
\n
GOOD clear
\n
"
"BAD claered
\n
GOOD cleared
\n
"
"BAD claerly
\n
GOOD clearly
\n
"
"BAD cliant
\n
GOOD client
\n
"
"BAD cliche
\n
GOOD clich
\303\251\n
"
"BAD cna
\n
GOOD can
\n
"
"BAD colection
\n
GOOD collection
\n
"
"BAD comanies
\n
GOOD companies
\n
"
"BAD comany
\n
GOOD company
\n
"
"BAD comapnies
\n
GOOD companies
\n
"
"BAD comapny
\n
GOOD company
\n
"
"BAD combintation
\n
GOOD combination
\n
"
"BAD comited
\n
GOOD committed
\n
"
"BAD comittee
\n
GOOD committee
\n
"
"BAD commadn
\n
GOOD command
\n
"
"BAD comming
\n
GOOD coming
\n
"
"BAD commitee
\n
GOOD committee
\n
"
"BAD committe
\n
GOOD committee
\n
"
"BAD committment
\n
GOOD commitment
\n
"
"BAD committments
\n
GOOD commitments
\n
"
"BAD committy
\n
GOOD committee
\n
"
"BAD comntain
\n
GOOD contain
\n
"
"BAD comntains
\n
GOOD contains
\n
"
"BAD compair
\n
GOOD compare
\n
"
"COMPLETE 0
\n
BAD company;s
\n
GOOD company's
\n
"
"BAD competetive
\n
GOOD competitive
\n
"
"BAD compleated
\n
GOOD completed
\n
"
"BAD compleatly
\n
GOOD completely
\n
"
"BAD compleatness
\n
GOOD completeness
\n
"
"BAD completly
\n
GOOD completely
\n
"
"BAD completness
\n
GOOD completeness
\n
"
"BAD composate
\n
GOOD composite
\n
"
"BAD comtain
\n
GOOD contain
\n
"
"BAD comtains
\n
GOOD contains
\n
"
"BAD comunicate
\n
GOOD communicate
\n
"
"BAD comunity
\n
GOOD community
\n
"
"BAD condolances
\n
GOOD condolences
\n
"
"BAD conected
\n
GOOD connected
\n
"
"BAD conferance
\n
GOOD conference
\n
"
"BAD confirmmation
\n
GOOD confirmation
\n
"
"BAD congradulations
\n
GOOD congratulations
\n
"
"BAD considerit
\n
GOOD considerate
\n
"
"BAD considerite
\n
GOOD considerate
\n
"
"BAD consonent
\n
GOOD consonant
\n
"
"BAD conspiricy
\n
GOOD conspiracy
\n
"
"BAD consultent
\n
GOOD consultant
\n
"
"BAD convertable
\n
GOOD convertible
\n
"
"BAD cooparate
\n
GOOD cooperate
\n
"
"BAD cooporate
\n
GOOD cooperate
\n
"
"BAD corproation
\n
GOOD corporation
\n
"
"BAD corproations
\n
GOOD corporations
\n
"
"BAD corruptable
\n
GOOD corruptible
\n
"
"BAD cotten
\n
GOOD cotton
\n
"
"BAD coudl
\n
GOOD could
\n
"
"COMPLETE 0
\n
BAD coudln't
\n
GOOD couldn't
\n
"
"COMPLETE 0
\n
BAD coudn't
\n
GOOD couldn't
\n
"
"BAD couldnt
\n
GOOD couldn't
\n
"
"COMPLETE 0
\n
BAD couldn;t
\n
GOOD couldn't
\n
"
"COMPLETE 0
\n
BAD could of been
\n
GOOD could have been
\n
"
"COMPLETE 0
\n
BAD could of had
\n
GOOD could have had
\n
"
"BAD couldthe
\n
GOOD could the
\n
"
"BAD couldve
\n
GOOD could've
\n
"
"BAD cpoy
\n
GOOD copy
\n
"
"BAD creme
\n
GOOD cr
\303\250
me
\n
"
"BAD ctaegory
\n
GOOD category
\n
"
"BAD cu
\n
GOOD see you
\n
"
"BAD cusotmer
\n
GOOD customer
\n
"
"BAD cusotmers
\n
GOOD customers
\n
"
"BAD cutsomer
\n
GOOD customer
\n
"
"BAD cutsomers
\n
GOOD customer
\n
"
"BAD cuz
\n
GOOD because
\n
"
"BAD cxan
\n
GOOD can
\n
"
"BAD danceing
\n
GOOD dancing
\n
"
"BAD dcument
\n
GOOD document
\n
"
"BAD deatils
\n
GOOD details
\n
"
"BAD decison
\n
GOOD decision
\n
"
"BAD decisons
\n
GOOD decisions
\n
"
"BAD decor
\n
GOOD d
\303\251
cor
\n
"
"BAD defendent
\n
GOOD defendant
\n
"
"BAD definately
\n
GOOD definitely
\n
"
"COMPLETE 0
\n
BAD deja vu
\n
GOOD d
\303\251
j
\303\240
vu
\n
"
"BAD deptartment
\n
GOOD department
\n
"
"BAD desicion
\n
GOOD decision
\n
"
"BAD desicions
\n
GOOD decisions
\n
"
"BAD desision
\n
GOOD decision
\n
"
"BAD desisions
\n
GOOD decisions
\n
"
"BAD detente
\n
GOOD d
\303\251
tente
\n
"
"BAD develeoprs
\n
GOOD developers
\n
"
"BAD devellop
\n
GOOD develop
\n
"
"BAD develloped
\n
GOOD developed
\n
"
"BAD develloper
\n
GOOD developer
\n
"
"BAD devellopers
\n
GOOD developers
\n
"
"BAD develloping
\n
GOOD developing
\n
"
"BAD devellopment
\n
GOOD development
\n
"
"BAD devellopments
\n
GOOD developments
\n
"
"BAD devellops
\n
GOOD develop
\n
"
"BAD develope
\n
GOOD develop
\n
"
"BAD developement
\n
GOOD development
\n
"
"BAD developements
\n
GOOD developments
\n
"
"BAD developor
\n
GOOD developer
\n
"
"BAD developors
\n
GOOD developers
\n
"
"BAD develpment
\n
GOOD development
\n
"
"BAD diaplay
\n
GOOD display
\n
"
"BAD didint
\n
GOOD didn't
\n
"
"BAD didnot
\n
GOOD did not
\n
"
"BAD didnt
\n
GOOD didn't
\n
"
"COMPLETE 0
\n
BAD didn;t
\n
GOOD didn't
\n
"
"BAD difefrent
\n
GOOD different
\n
"
"BAD diferences
\n
GOOD differences
\n
"
"BAD differance
\n
GOOD difference
\n
"
"BAD differances
\n
GOOD differences
\n
"
"BAD differant
\n
GOOD different
\n
"
"BAD differemt
\n
GOOD different
\n
"
"BAD differnt
\n
GOOD different
\n
"
"BAD diffrent
\n
GOOD different
\n
"
"BAD directer
\n
GOOD director
\n
"
"BAD directers
\n
GOOD directors
\n
"
"BAD directiosn
\n
GOOD direction
\n
"
"BAD disatisfied
\n
GOOD dissatisfied
\n
"
"BAD discoverd
\n
GOOD discovered
\n
"
"BAD disign
\n
GOOD design
\n
"
"BAD dispaly
\n
GOOD display
\n
"
"BAD dissonent
\n
GOOD dissonant
\n
"
"BAD distribusion
\n
GOOD distribution
\n
"
"BAD divsion
\n
GOOD division
\n
"
"BAD docuement
\n
GOOD documents
\n
"
"BAD docuemnt
\n
GOOD document
\n
"
"BAD documetn
\n
GOOD document
\n
"
"BAD documnet
\n
GOOD document
\n
"
"BAD documnets
\n
GOOD documents
\n
"
"COMPLETE 0
\n
BAD doens't
\n
GOOD doesn't
\n
"
"BAD doese
\n
GOOD does
\n
"
"COMPLETE 0
\n
BAD doe snot
\n
GOOD does not
\n
"
"BAD doesnt
\n
GOOD doesn't
\n
"
"COMPLETE 0
\n
BAD doesn;t
\n
GOOD doesn't
\n
"
"BAD doign
\n
GOOD doing
\n
"
"BAD doimg
\n
GOOD doing
\n
"
"BAD doind
\n
GOOD doing
\n
"
"BAD dollers
\n
GOOD dollars
\n
"
"BAD donig
\n
GOOD doing
\n
"
"BAD donno
\n
GOOD don't know
\n
"
"BAD dont
\n
GOOD don't
\n
"
"COMPLETE 0
\n
BAD do'nt
\n
GOOD don't
\n
"
"COMPLETE 0
\n
BAD don;t
\n
GOOD don't
\n
"
"COMPLETE 0
\n
BAD don't no
\n
GOOD don't know
\n
"
"COMPLETE 0
\n
BAD dosn't
\n
GOOD doesn't
\n
"
"BAD driveing
\n
GOOD driving
\n
"
"BAD drnik
\n
GOOD drink
\n
"
"BAD dunno
\n
GOOD don't know
\n
"
"BAD eclair
\n
GOOD
\303\251
clair
\n
"
"BAD efel
\n
GOOD feel
\n
"
"BAD effecient
\n
GOOD efficient
\n
"
"BAD efort
\n
GOOD effort
\n
"
"BAD eforts
\n
GOOD efforts
\n
"
"BAD ehr
\n
GOOD her
\n
"
"BAD eligable
\n
GOOD eligible
\n
"
"BAD embarass
\n
GOOD embarrass
\n
"
"BAD emigre
\n
GOOD
\303\251
migr
\303\251\n
"
"BAD enought
\n
GOOD enough
\n
"
"BAD entree
\n
GOOD entr
\303\251
e
\n
"
"BAD enuf
\n
GOOD enough
\n
"
"BAD equippment
\n
GOOD equipment
\n
"
"BAD equivalant
\n
GOOD equivalent
\n
"
"BAD esle
\n
GOOD else
\n
"
"BAD especally
\n
GOOD especially
\n
"
"BAD especialyl
\n
GOOD especially
\n
"
"BAD espesially
\n
GOOD especially
\n
"
"BAD essense
\n
GOOD essence
\n
"
"BAD excellance
\n
GOOD excellence
\n
"
"BAD excellant
\n
GOOD excellent
\n
"
"BAD excercise
\n
GOOD exercise
\n
"
"BAD exchagne
\n
GOOD exchange
\n
"
"BAD exchagnes
\n
GOOD exchanges
\n
"
"BAD excitment
\n
GOOD excitement
\n
"
"BAD exhcange
\n
GOOD exchange
\n
"
"BAD exhcanges
\n
GOOD exchanges
\n
"
"BAD experiance
\n
GOOD experience
\n
"
"BAD experienc
\n
GOOD experience
\n
"
"BAD exprience
\n
GOOD experience
\n
"
"BAD exprienced
\n
GOOD experienced
\n
"
"BAD eyt
\n
GOOD yet
\n
"
"BAD facade
\n
GOOD fa
\303\247
ade
\n
"
"BAD faeture
\n
GOOD feature
\n
"
"BAD faetures
\n
GOOD feature
\n
"
"BAD familair
\n
GOOD familiar
\n
"
"BAD familar
\n
GOOD familiar
\n
"
"BAD familliar
\n
GOOD familiar
\n
"
"BAD fammiliar
\n
GOOD familiar
\n
"
"BAD feild
\n
GOOD field
\n
"
"BAD feilds
\n
GOOD fields
\n
"
"BAD fianlly
\n
GOOD finally
\n
"
"BAD fidn
\n
GOOD find
\n
"
"BAD finalyl
\n
GOOD finally
\n
"
"BAD firends
\n
GOOD friends
\n
"
"BAD firts
\n
GOOD first
\n
"
"BAD follwo
\n
GOOD follow
\n
"
"BAD follwoing
\n
GOOD following
\n
"
"BAD fora
\n
GOOD for a
\n
"
"COMPLETE 0
\n
BAD for all intensive purposes
\n
for all intents and purposes
\n
"
"BAD foriegn
\n
GOOD foreign
\n
"
"BAD forthe
\n
GOOD for the
\n
"
"BAD forwrd
\n
GOOD forward
\n
"
"BAD forwrds
\n
GOOD forwards
\n
"
"BAD foudn
\n
GOOD found
\n
"
"BAD foward
\n
GOOD forward
\n
"
"BAD fowards
\n
GOOD forwards
\n
"
"BAD freind
\n
GOOD friend
\n
"
"BAD freindly
\n
GOOD friendly
\n
"
"BAD freinds
\n
GOOD friends
\n
"
"BAD friday
\n
GOOD Friday
\n
"
"BAD frmo
\n
GOOD from
\n
"
"BAD fromthe
\n
GOOD from the
\n
"
"COMPLETE 0
\n
BAD fromt he
\n
GOOD from the
\n
"
"BAD furneral
\n
GOOD funeral
\n
"
"BAD fwe
\n
GOOD few
\n
"
"BAD garantee
\n
GOOD guarantee
\n
"
"BAD gaurd
\n
GOOD guard
\n
"
"BAD gemeral
\n
GOOD general
\n
"
"BAD gerat
\n
GOOD great
\n
"
"BAD geting
\n
GOOD getting
\n
"
"BAD gettin
\n
GOOD getting
\n
"
"BAD gievn
\n
GOOD given
\n
"
"BAD giveing
\n
GOOD giving
\n
"
"BAD gloabl
\n
GOOD global
\n
"
"BAD goign
\n
GOOD going
\n
"
"BAD gonig
\n
GOOD going
\n
"
"BAD govenment
\n
GOOD government
\n
"
"BAD goverment
\n
GOOD government
\n
"
"BAD gruop
\n
GOOD group
\n
"
"BAD gruops
\n
GOOD groups
\n
"
"BAD grwo
\n
GOOD grow
\n
"
"BAD guidlines
\n
GOOD guidelines
\n
"
"BAD hadbeen
\n
GOOD had been
\n
"
"BAD hadnt
\n
GOOD hadn't
\n
"
"COMPLETE 0
\n
BAD hadn;t
\n
GOOD hadn't
\n
"
"BAD haev
\n
GOOD have
\n
"
"BAD hapen
\n
GOOD happen
\n
"
"BAD hapened
\n
GOOD happened
\n
"
"BAD hapening
\n
GOOD happening
\n
"
"BAD hapens
\n
GOOD happens
\n
"
"BAD happend
\n
GOOD happened
\n
"
"BAD hasbeen
\n
GOOD has been
\n
"
"BAD hasnt
\n
GOOD hasn't
\n
"
"COMPLETE 0
\n
BAD hasn;t
\n
GOOD hasn't
\n
"
"BAD havebeen
\n
GOOD have been
\n
"
"BAD haveing
\n
GOOD having
\n
"
"BAD havent
\n
GOOD haven't
\n
"
"COMPLETE 0
\n
BAD haven;t
\n
GOOD haven't
\n
"
"BAD hda
\n
GOOD had
\n
"
"BAD hearign
\n
GOOD hearing
\n
"
"COMPLETE 0
\n
BAD he;d
\n
GOOD he'd
\n
"
"BAD heirarchy
\n
GOOD hierarchy
\n
"
"BAD hel
\n
GOOD he'll
\n
"
"COMPLETE 0
\n
BAD he;ll
\n
GOOD he'll
\n
"
"BAD helpfull
\n
GOOD helpful
\n
"
"BAD herat
\n
GOOD heart
\n
"
"BAD heres
\n
GOOD here's
\n
"
"COMPLETE 0
\n
BAD here;s
\n
GOOD here's
\n
"
"BAD hes
\n
GOOD he's
\n
"
"COMPLETE 0
\n
BAD he;s
\n
GOOD he's
\n
"
"BAD hesaid
\n
GOOD he said
\n
"
"BAD hewas
\n
GOOD he was
\n
"
"BAD hge
\n
GOOD he
\n
"
"BAD hismelf
\n
GOOD himself
\n
"
"BAD hlep
\n
GOOD help
\n
"
"BAD hott
\n
GOOD hot
\n
"
"BAD hows
\n
GOOD how's
\n
"
"BAD hsa
\n
GOOD has
\n
"
"BAD hse
\n
GOOD she
\n
"
"BAD hsi
\n
GOOD his
\n
"
"BAD hte
\n
GOOD the
\n
"
"BAD htere
\n
GOOD there
\n
"
"BAD htese
\n
GOOD these
\n
"
"BAD htey
\n
GOOD they
\n
"
"BAD hting
\n
GOOD thing
\n
"
"BAD htink
\n
GOOD think
\n
"
"BAD htis
\n
GOOD this
\n
"
"COMPLETE 0
\n
BAD htp:
\n
GOOD http:
\n
"
"COMPLETE 0
\n
BAD http:
\\\\
nGOOD http://
\n
"
"BAD httpL
\n
GOOD http:
\n
"
"BAD hvae
\n
GOOD have
\n
"
"BAD hvaing
\n
GOOD having
\n
"
"BAD hwich
\n
GOOD which
\n
"
"BAD i
\n
GOOD I
\n
"
"COMPLETE 0
\n
BAD i c
\n
GOOD I see
\n
"
"COMPLETE 0
\n
BAD i;d
\n
GOOD I'd
\n
"
"COMPLETE 0
\n
BAD i'd
\n
GOOD I'd
\n
"
"COMPLETE 0
\n
BAD I;d
\n
GOOD I'd
\n
"
"BAD idae
\n
GOOD idea
\n
"
"BAD idaes
\n
GOOD ideas
\n
"
"BAD identofy
\n
GOOD identify
\n
"
"BAD ihs
\n
GOOD his
\n
"
"BAD iits the
\n
GOOD it's the
\n
"
"COMPLETE 0
\n
BAD i'll
\n
GOOD I'll
\n
"
"COMPLETE 0
\n
BAD I;ll
\n
GOOD I'll
\n
"
"COMPLETE 0
\n
BAD i;m
\n
GOOD I'm
\n
"
"COMPLETE 0
\n
BAD i'm
\n
GOOD I'm
\n
"
"COMPLETE 0
\n
BAD I
\"
m
\n
GOOD I'm
\n
"
"BAD imediate
\n
GOOD immediate
\n
"
"BAD imediatly
\n
GOOD immediately
\n
"
"BAD immediatly
\n
GOOD immediately
\n
"
"BAD importent
\n
GOOD important
\n
"
"BAD importnat
\n
GOOD important
\n
"
"BAD impossable
\n
GOOD impossible
\n
"
"BAD improvemnt
\n
GOOD improvement
\n
"
"BAD improvment
\n
GOOD improvement
\n
"
"BAD includ
\n
GOOD include
\n
"
"BAD indecate
\n
GOOD indicate
\n
"
"BAD indenpendence
\n
GOOD independence
\n
"
"BAD indenpendent
\n
GOOD independent
\n
"
"BAD indepedent
\n
GOOD independent
\n
"
"BAD independance
\n
GOOD independence
\n
"
"BAD independant
\n
GOOD independent
\n
"
"BAD influance
\n
GOOD influence
\n
"
"BAD infomation
\n
GOOD information
\n
"
"BAD informatoin
\n
GOOD information
\n
"
"BAD inital
\n
GOOD initial
\n
"
"BAD instaleld
\n
GOOD installed
\n
"
"BAD insted
\n
GOOD instead
\n
"
"BAD insurence
\n
GOOD insurance
\n
"
"BAD inteh
\n
GOOD in the
\n
"
"BAD interum
\n
GOOD interim
\n
"
"BAD inthe
\n
GOOD in the
\n
"
"COMPLETE 0
\n
BAD int he
\n
GOOD in the
\n
"
"BAD inturn
\n
GOOD intern
\n
"
"BAD inwhich
\n
GOOD in which
\n
"
"COMPLETE 0
\n
BAD i snot
\n
GOOD is not
\n
"
"BAD isnt
\n
GOOD isn't
\n
"
"COMPLETE 0
\n
BAD isn;t
\n
GOOD isn't
\n
"
"BAD isthe
\n
GOOD is the
\n
"
"BAD itd
\n
GOOD it'd
\n
"
"COMPLETE 0
\n
BAD it;d
\n
GOOD it'd
\n
"
"BAD itis
\n
GOOD it is
\n
"
"BAD ititial
\n
GOOD initial
\n
"
"BAD itll
\n
GOOD it'll
\n
"
"COMPLETE 0
\n
BAD it;ll
\n
GOOD it'll
\n
"
"BAD itnerest
\n
GOOD interest
\n
"
"BAD itnerested
\n
GOOD interested
\n
"
"BAD itneresting
\n
GOOD interesting
\n
"
"BAD itnerests
\n
GOOD interests
\n
"
"COMPLETE 0
\n
BAD it;s
\n
GOOD it's
\n
"
"BAD itsa
\n
GOOD it's a
\n
"
"COMPLETE 0
\n
BAD its a
\n
GOOD it's a
\n
"
"COMPLETE 0
\n
BAD it snot
\n
GOOD it's not
\n
"
"COMPLETE 0
\n
BAD it' snot
\n
GOOD it's not
\n
"
"COMPLETE 0
\n
BAD its the
\n
GOOD it's the
\n
"
"BAD itwas
\n
GOOD it was
\n
"
"BAD ive
\n
GOOD I've
\n
"
"COMPLETE 0
\n
BAD i;ve
\n
GOOD I've
\n
"
"COMPLETE 0
\n
BAD i've
\n
GOOD I've
\n
"
"BAD iwll
\n
GOOD will
\n
"
"BAD iwth
\n
GOOD with
\n
"
"BAD jsut
\n
GOOD just
\n
"
"BAD jugment
\n
GOOD judgment
\n
"
"BAD kno
\n
GOOD know
\n
"
"BAD knowldge
\n
GOOD knowledge
\n
"
"BAD knowlege
\n
GOOD knowledge
\n
"
"BAD knwo
\n
GOOD know
\n
"
"BAD knwon
\n
GOOD known
\n
"
"BAD knwos
\n
GOOD knows
\n
"
"BAD konw
\n
GOOD know
\n
"
"BAD konwn
\n
GOOD known
\n
"
"BAD konws
\n
GOOD knows
\n
"
"BAD labratory
\n
GOOD laboratory
\n
"
"BAD labtop
\n
GOOD laptop
\n
"
"BAD lastyear
\n
GOOD last year
\n
"
"BAD laterz
\n
GOOD later
\n
"
"BAD learnign
\n
GOOD learning
\n
"
"BAD lenght
\n
GOOD length
\n
"
"COMPLETE 0
\n
BAD let;s
\n
GOOD let's
\n
"
"COMPLETE 0
\n
BAD let's him
\n
GOOD lets him
\n
"
"COMPLETE 0
\n
BAD let's it
\n
GOOD lets it
\n
"
"BAD levle
\n
GOOD level
\n
"
"BAD libary
\n
GOOD library
\n
"
"BAD librarry
\n
GOOD library
\n
"
"BAD librery
\n
GOOD library
\n
"
"BAD liek
\n
GOOD like
\n
"
"BAD liekd
\n
GOOD liked
\n
"
"BAD lieutenent
\n
GOOD lieutenant
\n
"
"BAD liev
\n
GOOD live
\n
"
"BAD likly
\n
GOOD likely
\n
"
"BAD lisense
\n
GOOD license
\n
"
"BAD littel
\n
GOOD little
\n
"
"BAD litttle
\n
GOOD little
\n
"
"BAD liuke
\n
GOOD like
\n
"
"BAD liveing
\n
GOOD living
\n
"
"BAD loev
\n
GOOD love
\n
"
"BAD lonly
\n
GOOD lonely
\n
"
"BAD lookign
\n
GOOD looking
\n
"
"BAD m
\n
GOOD am
\n
"
"BAD maintainence
\n
GOOD maintenance
\n
"
"BAD maintenence
\n
GOOD maintenance
\n
"
"BAD makeing
\n
GOOD making
\n
"
"BAD managment
\n
GOOD management
\n
"
"BAD mantain
\n
GOOD maintain
\n
"
"BAD marraige
\n
GOOD marriage
\n
"
"COMPLETE 0
\n
BAD may of been
\n
GOOD may have been
\n
"
"COMPLETE 0
\n
BAD may of had
\n
GOOD may have had
\n
"
"BAD memeber
\n
GOOD member
\n
"
"BAD merchent
\n
GOOD merchant
\n
"
"BAD mesage
\n
GOOD message
\n
"
"BAD mesages
\n
GOOD messages
\n
"
"COMPLETE 0
\n
BAD might of been
\n
GOOD might have been
\n
"
"COMPLETE 0
\n
BAD might of had
\n
GOOD might have had
\n
"
"BAD mispell
\n
GOOD misspell
\n
"
"BAD mispelling
\n
GOOD misspelling
\n
"
"BAD mispellings
\n
GOOD misspellings
\n
"
"BAD mkae
\n
GOOD make
\n
"
"BAD mkaes
\n
GOOD makes
\n
"
"BAD mkaing
\n
GOOD making
\n
"
"BAD moeny
\n
GOOD money
\n
"
"BAD monday
\n
GOOD Monday
\n
"
"BAD morgage
\n
GOOD mortgage
\n
"
"BAD mroe
\n
GOOD more
\n
"
"COMPLETE 0
\n
BAD must of been
\n
GOOD must have been
\n
"
"COMPLETE 0
\n
BAD must of had
\n
GOOD must have had
\n
"
"COMPLETE 0
\n
BAD mute point
\n
GOOD moot point
\n
"
"BAD mysefl
\n
GOOD myself
\n
"
"BAD myu
\n
GOOD my
\n
"
"BAD naive
\n
GOOD naïve
\n
"
"BAD ne1
\n
GOOD anyone
\n
"
"BAD neway
\n
GOOD anyway
\n
"
"BAD neways
\n
GOOD anyways
\n
"
"BAD necassarily
\n
GOOD necessarily
\n
"
"BAD necassary
\n
GOOD necessary
\n
"
"BAD neccessarily
\n
GOOD necessarily
\n
"
"BAD neccessary
\n
GOOD necessary
\n
"
"BAD necesarily
\n
GOOD necessarily
\n
"
"BAD necesary
\n
GOOD necessary
\n
"
"BAD negotiaing
\n
GOOD negotiating
\n
"
"BAD nkow
\n
GOOD know
\n
"
"BAD nothign
\n
GOOD nothing
\n
"
"BAD nto
\n
GOOD not
\n
"
"BAD nver
\n
GOOD never
\n
"
"BAD nwe
\n
GOOD new
\n
"
"BAD nwo
\n
GOOD now
\n
"
"BAD obediant
\n
GOOD obedient
\n
"
"BAD ocasion
\n
GOOD occasion
\n
"
"BAD occassion
\n
GOOD occasion
\n
"
"BAD occurance
\n
GOOD occurrence
\n
"
"BAD occured
\n
GOOD occurred
\n
"
"BAD occurence
\n
GOOD occurrence
\n
"
"BAD occurrance
\n
GOOD occurrence
\n
"
"BAD oclock
\n
GOOD o'clock
\n
"
"BAD oculd
\n
GOOD could
\n
"
"BAD ocur
\n
GOOD occur
\n
"
"BAD oeprator
\n
GOOD operator
\n
"
"BAD ofits
\n
GOOD of its
\n
"
"BAD ofthe
\n
GOOD of the
\n
"
"BAD oft he
\n
GOOD of the
\n
"
"BAD oging
\n
GOOD going
\n
"
"BAD ohter
\n
GOOD other
\n
"
"BAD omre
\n
GOOD more
\n
"
"BAD oneof
\n
GOOD one of
\n
"
"BAD onepoint
\n
GOOD one point
\n
"
"BAD onthe
\n
GOOD on the
\n
"
"COMPLETE 0
\n
BAD ont he
\n
GOOD on the
\n
"
"BAD onyl
\n
GOOD only
\n
"
"BAD oppasite
\n
GOOD opposite
\n
"
"BAD opperation
\n
GOOD operation
\n
"
"BAD oppertunity
\n
GOOD opportunity
\n
"
"BAD opposate
\n
GOOD opposite
\n
"
"BAD opposible
\n
GOOD opposable
\n
"
"BAD opposit
\n
GOOD opposite
\n
"
"BAD oppotunities
\n
GOOD opportunities
\n
"
"BAD oppotunity
\n
GOOD opportunity
\n
"
"BAD orginization
\n
GOOD organization
\n
"
"BAD orginized
\n
GOOD organized
\n
"
"BAD otehr
\n
GOOD other
\n
"
"BAD otu
\n
GOOD out
\n
"
"BAD outof
\n
GOOD out of
\n
"
"BAD overthe
\n
GOOD over the
\n
"
"BAD owrk
\n
GOOD work
\n
"
"BAD owuld
\n
GOOD would
\n
"
"BAD oxident
\n
GOOD oxidant
\n
"
"BAD papaer
\n
GOOD paper
\n
"
"BAD passe
\n
GOOD pass
\303\251\n
"
"BAD parliment
\n
GOOD parliament
\n
"
"BAD partof
\n
GOOD part of
\n
"
"BAD paymetn
\n
GOOD payment
\n
"
"BAD paymetns
\n
GOOD payments
\n
"
"BAD pciture
\n
GOOD picture
\n
"
"BAD peice
\n
GOOD piece
\n
"
"BAD peices
\n
GOOD pieces
\n
"
"BAD peolpe
\n
GOOD people
\n
"
"BAD peopel
\n
GOOD people
\n
"
"BAD percentof
\n
GOOD percent of
\n
"
"BAD percentto
\n
GOOD percent to
\n
"
"BAD performence
\n
GOOD performance
\n
"
"BAD perhasp
\n
GOOD perhaps
\n
"
"BAD perhpas
\n
GOOD perhaps
\n
"
"BAD permanant
\n
GOOD permanent
\n
"
"BAD perminent
\n
GOOD permanent
\n
"
"BAD personalyl
\n
GOOD personally
\n
"
"BAD pleasent
\n
GOOD pleasant
\n
"
"BAD pls
\n
GOOD please
\n
"
"BAD plz
\n
GOOD please
\n
"
"BAD poeple
\n
GOOD people
\n
"
"BAD porblem
\n
GOOD problem
\n
"
"BAD porblems
\n
GOOD problems
\n
"
"BAD porvide
\n
GOOD provide
\n
"
"BAD possable
\n
GOOD possible
\n
"
"BAD postition
\n
GOOD position
\n
"
"BAD potatoe
\n
GOOD potato
\n
"
"BAD potatos
\n
GOOD potatoes
\n
"
"BAD potentialy
\n
GOOD potentially
\n
"
"BAD ppl
\n
GOOD people
\n
"
"BAD pregnent
\n
GOOD pregnant
\n
"
"BAD presance
\n
GOOD presence
\n
"
"BAD primative
\n
GOOD primitive
\n
"
"BAD probally
\n
GOOD probably
\n
"
"BAD probelm
\n
GOOD problem
\n
"
"BAD probelms
\n
GOOD problems
\n
"
"BAD probly
\n
GOOD probably
\n
"
"BAD prolly
\n
GOOD probably
\n
"
"BAD proly
\n
GOOD probably
\n
"
"BAD prominant
\n
GOOD prominent
\n
"
"BAD proposterous
\n
GOOD preposterous
\n
"
"BAD protege
\n
GOOD prot
\303\251
g
\303\251\n
"
"BAD protoge
\n
GOOD prot
\303\251
g
\303\251\n
"
"BAD psoition
\n
GOOD position
\n
"
"BAD ptogress
\n
GOOD progress
\n
"
"BAD pursuade
\n
GOOD persuade
\n
"
"BAD puting
\n
GOOD putting
\n
"
"BAD pwoer
\n
GOOD power
\n
"
"BAD quater
\n
GOOD quarter
\n
"
"BAD quaters
\n
GOOD quarters
\n
"
"BAD quesion
\n
GOOD question
\n
"
"BAD quesions
\n
GOOD questions
\n
"
"BAD questioms
\n
GOOD questions
\n
"
"BAD questiosn
\n
GOOD questions
\n
"
"BAD questoin
\n
GOOD question
\n
"
"BAD quetion
\n
GOOD question
\n
"
"BAD quetions
\n
GOOD questions
\n
"
"BAD r
\n
GOOD are
\n
"
"BAD raeson
\n
GOOD reason
\n
"
"BAD realyl
\n
GOOD really
\n
"
"BAD reccomend
\n
GOOD recommend
\n
"
"BAD reccommend
\n
GOOD recommend
\n
"
"BAD receieve
\n
GOOD receive
\n
"
"BAD recieve
\n
GOOD receive
\n
"
"BAD recieved
\n
GOOD received
\n
"
"BAD recieving
\n
GOOD receiving
\n
"
"BAD recomend
\n
GOOD recommend
\n
"
"BAD recomendation
\n
GOOD recommendation
\n
"
"BAD recomendations
\n
GOOD recommendations
\n
"
"BAD recomended
\n
GOOD recommended
\n
"
"BAD reconize
\n
GOOD recognize
\n
"
"BAD recrod
\n
GOOD record
\n
"
"BAD rediculous
\n
GOOD ridiculous
\n
"
"BAD rediculus
\n
GOOD ridiculous
\n
"
"BAD reguard
\n
GOOD regard
\n
"
"BAD religous
\n
GOOD religious
\n
"
"BAD reluctent
\n
GOOD reluctant
\n
"
"BAD remeber
\n
GOOD remember
\n
"
"BAD reommend
\n
GOOD recommend
\n
"
"BAD representativs
\n
GOOD representatives
\n
"
"BAD representives
\n
GOOD representatives
\n
"
"BAD represetned
\n
GOOD represented
\n
"
"BAD represnt
\n
GOOD represent
\n
"
"BAD reserach
\n
GOOD research
\n
"
"BAD resollution
\n
GOOD resolution
\n
"
"BAD resorces
\n
GOOD resources
\n
"
"BAD respomd
\n
GOOD respond
\n
"
"BAD respomse
\n
GOOD response
\n
"
"BAD responce
\n
GOOD response
\n
"
"BAD responsability
\n
GOOD responsibility
\n
"
"BAD responsable
\n
GOOD responsible
\n
"
"BAD responsibile
\n
GOOD responsible
\n
"
"BAD responsiblity
\n
GOOD responsibility
\n
"
"BAD restaraunt
\n
GOOD restaurant
\n
"
"BAD restuarant
\n
GOOD restaurant
\n
"
"BAD reult
\n
GOOD result
\n
"
"BAD reveiw
\n
GOOD review
\n
"
"BAD reveiwing
\n
GOOD reviewing
\n
"
"BAD rumers
\n
GOOD rumors
\n
"
"BAD rwite
\n
GOOD write
\n
"
"BAD rythm
\n
GOOD rhythm
\n
"
"BAD saidhe
\n
GOOD said he
\n
"
"BAD saidit
\n
GOOD said it
\n
"
"BAD saidthat
\n
GOOD said that
\n
"
"BAD saidthe
\n
GOOD said the
\n
"
"COMPLETE 0
\n
BAD saidt he
\n
GOOD said the
\n
"
"BAD sandwhich
\n
GOOD sandwich
\n
"
"BAD sandwitch
\n
GOOD sandwich
\n
"
"BAD saturday
\n
GOOD Saturday
\n
"
"BAD scedule
\n
GOOD schedule
\n
"
"BAD sceduled
\n
GOOD scheduled
\n
"
"BAD seance
\n
GOOD s
\303\251
ance
\n
"
"BAD secratary
\n
GOOD secretary
\n
"
"BAD sectino
\n
GOOD section
\n
"
"BAD seh
\n
GOOD she
\n
"
"BAD selectoin
\n
GOOD selection
\n
"
"BAD sence
\n
GOOD sense
\n
"
"BAD sentance
\n
GOOD sentence
\n
"
"BAD separeate
\n
GOOD separate
\n
"
"BAD seperate
\n
GOOD separate
\n
"
"BAD sercumstances
\n
GOOD circumstances
\n
"
"BAD shcool
\n
GOOD school
\n
"
"COMPLETE 0
\n
BAD she;d
\n
GOOD she'd
\n
"
"COMPLETE 0
\n
BAD she;ll
\n
GOOD she'll
\n
"
"BAD shes
\n
GOOD she's
\n
"
"COMPLETE 0
\n
BAD she;s
\n
GOOD she's
\n
"
"BAD shesaid
\n
GOOD she said
\n
"
"BAD shineing
\n
GOOD shining
\n
"
"BAD shiped
\n
GOOD shipped
\n
"
"BAD shoudl
\n
GOOD should
\n
"
"COMPLETE 0
\n
BAD shoudln't
\n
GOOD shouldn't
\n
"
"BAD shouldent
\n
GOOD shouldn't
\n
"
"BAD shouldnt
\n
GOOD shouldn't
\n
"
"COMPLETE 0
\n
BAD shouldn;t
\n
GOOD shouldn't
\n
"
"COMPLETE 0
\n
BAD should of been
\n
GOOD should have been
\n
"
"COMPLETE 0
\n
BAD should of had
\n
GOOD should have had
\n
"
"BAD shouldve
\n
GOOD should've
\n
"
"BAD showinf
\n
GOOD showing
\n
"
"BAD signifacnt
\n
GOOD significant
\n
"
"BAD simalar
\n
GOOD similar
\n
"
"BAD similiar
\n
GOOD similar
\n
"
"BAD simpyl
\n
GOOD simply
\n
"
"BAD sincerly
\n
GOOD sincerely
\n
"
"BAD sitll
\n
GOOD still
\n
"
"BAD smae
\n
GOOD same
\n
"
"BAD smoe
\n
GOOD some
\n
"
"BAD soem
\n
GOOD some
\n
"
"BAD sohw
\n
GOOD show
\n
"
"BAD soical
\n
GOOD social
\n
"
"BAD some1
\n
GOOD someone
\n
"
"BAD somethign
\n
GOOD something
\n
"
"BAD someting
\n
GOOD something
\n
"
"BAD somewaht
\n
GOOD somewhat
\n
"
"BAD somthing
\n
GOOD something
\n
"
"BAD somtimes
\n
GOOD sometimes
\n
"
"COMPLETE 0
\n
BAD sot hat
\n
GOOD so that
\n
"
"BAD soudn
\n
GOOD sound
\n
"
"BAD soudns
\n
GOOD sounds
\n
"
"BAD speach
\n
GOOD speech
\n
"
"BAD specificaly
\n
GOOD specifically
\n
"
"BAD specificalyl
\n
GOOD specifically
\n
"
"BAD spelt
\n
GOOD spelled
\n
"
"BAD sry
\n
GOOD sorry
\n
"
"COMPLETE 0
\n
BAD state of the ark
\n
GOOD state of the art
\n
"
"BAD statment
\n
GOOD statement
\n
"
"BAD statments
\n
GOOD statements
\n
"
"BAD stnad
\n
GOOD stand
\n
"
"BAD stopry
\n
GOOD story
\n
"
"BAD stoyr
\n
GOOD story
\n
"
"BAD stpo
\n
GOOD stop
\n
"
"BAD strentgh
\n
GOOD strength
\n
"
"BAD stroy
\n
GOOD story
\n
"
"BAD struggel
\n
GOOD struggle
\n
"
"BAD strugle
\n
GOOD struggle
\n
"
"BAD studnet
\n
GOOD student
\n
"
"BAD successfull
\n
GOOD successful
\n
"
"BAD successfuly
\n
GOOD successfully
\n
"
"BAD successfulyl
\n
GOOD successfully
\n
"
"BAD sucess
\n
GOOD success
\n
"
"BAD sucessfull
\n
GOOD successful
\n
"
"BAD sufficiant
\n
GOOD sufficient
\n
"
"BAD sum1
\n
GOOD someone
\n
"
"BAD sunday
\n
GOOD Sunday
\n
"
"BAD suposed
\n
GOOD supposed
\n
"
"BAD supposably
\n
GOOD supposedly
\n
"
"BAD suppossed
\n
GOOD supposed
\n
"
"BAD suprise
\n
GOOD surprise
\n
"
"BAD suprised
\n
GOOD surprised
\n
"
"BAD sux
\n
GOOD sucks
\n
"
"BAD swiming
\n
GOOD swimming
\n
"
"BAD tahn
\n
GOOD than
\n
"
"BAD taht
\n
GOOD that
\n
"
"COMPLETE 0
\n
BAD take it for granite
\n
GOOD take it for granted
\n
"
"COMPLETE 0
\n
BAD taken for granite
\n
GOOD taken for granted
\n
"
"BAD talekd
\n
GOOD talked
\n
"
"BAD talkign
\n
GOOD talking
\n
"
"BAD tath
\n
GOOD that
\n
"
"BAD tecnical
\n
GOOD technical
\n
"
"BAD teh
\n
GOOD the
\n
"
"BAD tehy
\n
GOOD they
\n
"
"COMPLETE 0
\n
BAD tellt he
\n
GOOD tell the
\n
"
"BAD termoil
\n
GOOD turmoil
\n
"
"BAD tets
\n
GOOD test
\n
"
"BAD tghe
\n
GOOD the
\n
"
"BAD tghis
\n
GOOD this
\n
"
"BAD thansk
\n
GOOD thanks
\n
"
"BAD thanx
\n
GOOD thanks
\n
"
"BAD thats
\n
GOOD that's
\n
"
"BAD thatthe
\n
GOOD that the
\n
"
"COMPLETE 0
\n
BAD thatt he
\n
GOOD that the
\n
"
"BAD thecompany
\n
GOOD the company
\n
"
"BAD thefirst
\n
GOOD the first
\n
"
"BAD thegovernment
\n
GOOD the government
\n
"
"COMPLETE 0
\n
BAD their are
\n
GOOD there are
\n
"
"COMPLETE 0
\n
BAD their aren't
\n
GOOD there aren't
\n
"
"COMPLETE 0
\n
BAD their is
\n
GOOD there is
\n
"
"BAD themself
\n
GOOD themselves
\n
"
"BAD themselfs
\n
GOOD themselves
\n
"
"BAD thenew
\n
GOOD the new
\n
"
"BAD theres
\n
GOOD there's
\n
"
"COMPLETE 0
\n
BAD there's is
\n
GOOD theirs is
\n
"
"COMPLETE 0
\n
BAD there's isn't
\n
GOOD theirs isn't
\n
"
"BAD theri
\n
GOOD their
\n
"
"BAD thesame
\n
GOOD the same
\n
"
"BAD thetwo
\n
GOOD the two
\n
"
"BAD theyd
\n
GOOD they'd
\n
"
"COMPLETE 0
\n
BAD they;d
\n
GOOD they'd
\n
"
"COMPLETE 0
\n
BAD they;l
\n
GOOD they'll
\n
"
"BAD theyll
\n
GOOD they'll
\n
"
"COMPLETE 0
\n
BAD they;ll
\n
GOOD they'll
\n
"
"COMPLETE 0
\n
BAD they;r
\n
GOOD they're
\n
"
"COMPLETE 0
\n
BAD theyre
\n
GOOD they're
\n
"
"COMPLETE 0
\n
BAD they;re
\n
GOOD they're
\n
"
"COMPLETE 0
\n
BAD they're are
\n
GOOD there are
\n
"
"COMPLETE 0
\n
BAD they're is
\n
GOOD there is
\n
"
"COMPLETE 0
\n
BAD they;v
\n
GOOD they've
\n
"
"BAD theyve
\n
GOOD they've
\n
"
"COMPLETE 0
\n
BAD they;ve
\n
GOOD they've
\n
"
"BAD thgat
\n
GOOD that
\n
"
"BAD thge
\n
GOOD the
\n
"
"BAD thier
\n
GOOD their
\n
"
"BAD thigsn
\n
GOOD things
\n
"
"BAD thisyear
\n
GOOD this year
\n
"
"BAD thme
\n
GOOD them
\n
"
"BAD thna
\n
GOOD than
\n
"
"BAD thne
\n
GOOD then
\n
"
"BAD thnig
\n
GOOD thing
\n
"
"BAD thnigs
\n
GOOD things
\n
"
"BAD tho
\n
GOOD though
\n
"
"BAD threatend
\n
GOOD threatened
\n
"
"BAD thsi
\n
GOOD this
\n
"
"BAD thsoe
\n
GOOD those
\n
"
"BAD thta
\n
GOOD that
\n
"
"BAD thursday
\n
GOOD Thursday
\n
"
"BAD thx
\n
GOOD thanks
\n
"
"BAD tihs
\n
GOOD this
\n
"
"BAD timne
\n
GOOD time
\n
"
"BAD tiogether
\n
GOOD together
\n
"
"BAD tje
\n
GOOD the
\n
"
"BAD tjhe
\n
GOOD the
\n
"
"BAD tkae
\n
GOOD take
\n
"
"BAD tkaes
\n
GOOD takes
\n
"
"BAD tkaing
\n
GOOD taking
\n
"
"BAD tlaking
\n
GOOD talking
\n
"
"BAD tnx
\n
GOOD thanks
\n
"
"BAD todya
\n
GOOD today
\n
"
"BAD togehter
\n
GOOD together
\n
"
"COMPLETE 0
\n
BAD toldt he
\n
GOOD told the
\n
"
"BAD tomorow
\n
GOOD tomorrow
\n
"
"BAD tongiht
\n
GOOD tonight
\n
"
"BAD tonihgt
\n
GOOD tonight
\n
"
"BAD tonite
\n
GOOD tonight
\n
"
"BAD totaly
\n
GOOD totally
\n
"
"BAD totalyl
\n
GOOD totally
\n
"
"BAD tothe
\n
GOOD to the
\n
"
"COMPLETE 0
\n
BAD tot he
\n
GOOD to the
\n
"
"BAD touche
\n
GOOD touch
\303\251\n
"
"BAD towrad
\n
GOOD toward
\n
"
"BAD traditionalyl
\n
GOOD traditionally
\n
"
"BAD transfered
\n
GOOD transferred
\n
"
"BAD truely
\n
GOOD truly
\n
"
"BAD truley
\n
GOOD truly
\n
"
"BAD tryed
\n
GOOD tried
\n
"
"BAD tthe
\n
GOOD the
\n
"
"BAD tuesday
\n
GOOD Tuesday
\n
"
"BAD tyhat
\n
GOOD that
\n
"
"BAD tyhe
\n
GOOD the
\n
"
"BAD u
\n
GOOD you
\n
"
"BAD udnerstand
\n
GOOD understand
\n
"
"BAD understnad
\n
GOOD understand
\n
"
"COMPLETE 0
\n
BAD undert he
\n
GOOD under the
\n
"
"BAD unforseen
\n
GOOD unforeseen
\n
"
"BAD UnitedStates
\n
GOOD United States
\n
"
"BAD unliek
\n
GOOD unlike
\n
"
"BAD unpleasently
\n
GOOD unpleasantly
\n
"
"BAD untill
\n
GOOD until
\n
"
"BAD untilll
\n
GOOD until
\n
"
"BAD ur
\n
GOOD you are
\n
"
"BAD useing
\n
GOOD using
\n
"
"BAD usualyl
\n
GOOD usually
\n
"
"BAD veyr
\n
GOOD very
\n
"
"BAD virtualyl
\n
GOOD virtually
\n
"
"BAD visavis
\n
GOOD vis-a-vis
\n
"
"COMPLETE 0
\n
BAD vis-a-vis
\n
GOOD vis-
\303\240
-vis
\n
"
"BAD vrey
\n
GOOD very
\n
"
"BAD vulnerible
\n
GOOD vulnerable
\n
"
"BAD waht
\n
GOOD what
\n
"
"BAD warrent
\n
GOOD warrant
\n
"
"COMPLETE 0
\n
BAD wa snot
\n
GOOD was not
\n
"
"COMPLETE 0
\n
BAD wasnt
\n
GOOD wasn't
\n
"
"COMPLETE 0
\n
BAD wasn;t
\n
GOOD wasn't
\n
"
"BAD wat
\n
GOOD what
\n
"
"BAD watn
\n
GOOD want
\n
"
"COMPLETE 0
\n
BAD we;d
\n
GOOD we'd
\n
"
"BAD wednesday
\n
GOOD Wednesday
\n
"
"BAD wehn
\n
GOOD when
\n
"
"COMPLETE 0
\n
BAD we'l
\n
GOOD we'll
\n
"
"COMPLETE 0
\n
BAD we;ll
\n
GOOD we'll
\n
"
"COMPLETE 0
\n
BAD we;re
\n
GOOD we're
\n
"
"BAD werent
\n
GOOD weren't
\n
"
"COMPLETE 0
\n
BAD weren;t
\n
GOOD weren't
\n
"
"COMPLETE 0
\n
BAD wern't
\n
GOOD weren't
\n
"
"BAD werre
\n
GOOD were
\n
"
"BAD weve
\n
GOOD we've
\n
"
"COMPLETE 0
\n
BAD we;ve
\n
GOOD we've
\n
"
"BAD whats
\n
GOOD what's
\n
"
"COMPLETE 0
\n
BAD what;s
\n
GOOD what's
\n
"
"BAD whcih
\n
GOOD which
\n
"
"COMPLETE 0
\n
BAD whent he
\n
GOOD when the
\n
"
"BAD wheres
\n
GOOD where's
\n
"
"COMPLETE 0
\n
BAD where;s
\n
GOOD where's
\n
"
"BAD wherre
\n
GOOD where
\n
"
"BAD whic
\n
GOOD which
\n
"
"COMPLETE 0
\n
BAD whicht he
\n
GOOD which the
\n
"
"BAD whihc
\n
GOOD which
\n
"
"BAD wholl
\n
GOOD who'll
\n
"
"BAD whos
\n
GOOD who's
\n
"
"COMPLETE 0
\n
BAD who;s
\n
GOOD who's
\n
"
"BAD whove
\n
GOOD who've
\n
"
"COMPLETE 0
\n
BAD who;ve
\n
GOOD who've
\n
"
"BAD whta
\n
GOOD what
\n
"
"BAD whys
\n
GOOD why's
\n
"
"BAD wief
\n
GOOD wife
\n
"
"BAD wierd
\n
GOOD weird
\n
"
"BAD wihch
\n
GOOD which
\n
"
"BAD wiht
\n
GOOD with
\n
"
"BAD willbe
\n
GOOD will be
\n
"
"COMPLETE 0
\n
BAD will of been
\n
GOOD will have been
\n
"
"COMPLETE 0
\n
BAD will of had
\n
GOOD will have had
\n
"
"BAD windoes
\n
GOOD windows
\n
"
"BAD witha
\n
GOOD with a
\n
"
"BAD withdrawl
\n
GOOD withdrawal
\n
"
"BAD withe
\n
GOOD with
\n
"
"COMPLETE 0
\n
BAD withthe
\n
GOOD with the
\n
"
"BAD witht he
\n
GOOD with the
\n
"
"BAD wiull
\n
GOOD will
\n
"
"BAD wnat
\n
GOOD want
\n
"
"BAD wnated
\n
GOOD wanted
\n
"
"BAD wnats
\n
GOOD wants
\n
"
"BAD woh
\n
GOOD who
\n
"
"BAD wohle
\n
GOOD whole
\n
"
"BAD wokr
\n
GOOD work
\n
"
"BAD wont
\n
GOOD won't
\n
"
"COMPLETE 0
\n
BAD wo'nt
\n
GOOD won't
\n
"
"COMPLETE 0
\n
BAD won;t
\n
GOOD won't
\n
"
"BAD woudl
\n
GOOD would
\n
"
"COMPLETE 0
\n
BAD woudln't
\n
GOOD wouldn't
\n
"
"BAD wouldbe
\n
GOOD would be
\n
"
"BAD wouldnt
\n
GOOD wouldn't
\n
"
"COMPLETE 0
\n
BAD wouldn;t
\n
GOOD wouldn't
\n
"
"COMPLETE 0
\n
BAD would of been
\n
GOOD would have been
\n
"
"COMPLETE 0
\n
BAD would of had
\n
GOOD would have had
\n
"
"BAD wouldve
\n
GOOD would've
\n
"
"BAD wriet
\n
GOOD write
\n
"
"BAD writting
\n
GOOD writing
\n
"
"BAD wrod
\n
GOOD word
\n
"
"BAD wroet
\n
GOOD wrote
\n
"
"BAD wroking
\n
GOOD working
\n
"
"BAD wtih
\n
GOOD with
\n
"
"BAD wuould
\n
GOOD would
\n
"
"BAD wud
\n
GOOD would
\n
"
"BAD wut
\n
GOOD what
\n
"
"BAD wya
\n
GOOD way
\n
"
"BAD y
\n
GOOD why
\n
"
"BAD yeh
\n
GOOD yeah
\n
"
"BAD yera
\n
GOOD year
\n
"
"BAD yeras
\n
GOOD years
\n
"
"BAD yersa
\n
GOOD years
\n
"
"BAD yoiu
\n
GOOD you
\n
"
"BAD youare
\n
GOOD you are
\n
"
"BAD youd
\n
GOOD you'd
\n
"
"COMPLETE 0
\n
BAD you;d
\n
GOOD you'd
\n
"
"BAD youll
\n
GOOD you'll
\n
"
"COMPLETE 0
\n
BAD your a
\n
GOOD you're a
\n
"
"COMPLETE 0
\n
BAD your an
\n
GOOD you're an
\n
"
"BAD youre
\n
GOOD you're
\n
"
"COMPLETE 0
\n
BAD you;re
\n
GOOD you're
\n
"
"COMPLETE 0
\n
BAD you're own
\n
GOOD your own
\n
"
"COMPLETE 0
\n
BAD your her
\n
GOOD you're her
\n
"
"COMPLETE 0
\n
BAD your here
\n
GOOD you're here
\n
"
"COMPLETE 0
\n
BAD your his
\n
GOOD you're his
\n
"
"COMPLETE 0
\n
BAD your my
\n
GOOD you're my
\n
"
"COMPLETE 0
\n
BAD your the
\n
GOOD you're the
\n
"
"COMPLETE 0
\n
BAD your their
\n
GOOD you're their
\n
"
"COMPLETE 0
\n
BAD your your
\n
GOOD you're your
\n
"
"BAD youve
\n
GOOD you've
\n
"
"COMPLETE 0
\n
BAD you;ve
\n
GOOD you've
\n
"
"BAD ytou
\n
GOOD you
\n
"
"BAD yuo
\n
GOOD you
\n
"
"BAD yuor
\n
GOOD your
\n
"
;
gchar
*
buf
;
gchar
*
ibuf
;
GHashTable
*
hashes
;
char
bad
[
82
]
=
""
;
char
good
[
256
]
=
""
;
gsize
pnt
=
0
;
gsize
size
;
gboolean
complete
=
TRUE
;
gboolean
case_sensitive
=
FALSE
;
buf
=
g_build_filename
(
purple_config_dir
(),
"dict"
,
NULL
);
if
(
!
(
g_file_get_contents
(
buf
,
&
ibuf
,
&
size
,
NULL
)
&&
ibuf
))
{
ibuf
=
g_strdup
(
defaultconf
);
size
=
strlen
(
defaultconf
);
}
g_free
(
buf
);
model
=
gtk_list_store_new
((
gint
)
N_COLUMNS
,
G_TYPE_STRING
,
G_TYPE_STRING
,
G_TYPE_BOOLEAN
,
G_TYPE_BOOLEAN
);
hashes
=
g_hash_table_new_full
(
g_str_hash
,
g_str_equal
,
g_free
,
NULL
);
while
(
ibuf
&&
buf_get_line
(
ibuf
,
&
buf
,
&
pnt
,
size
))
{
if
(
*
buf
!=
'#'
)
{
if
(
!
g_ascii_strncasecmp
(
buf
,
"BAD "
,
4
))
{
strncpy
(
bad
,
buf
+
4
,
81
);
}
else
if
(
!
g_ascii_strncasecmp
(
buf
,
"CASE "
,
5
))
{
case_sensitive
=
*
(
buf
+
5
)
==
'0'
?
FALSE
:
TRUE
;
}
else
if
(
!
g_ascii_strncasecmp
(
buf
,
"COMPLETE "
,
9
))
{
complete
=
*
(
buf
+
9
)
==
'0'
?
FALSE
:
TRUE
;
}
else
if
(
!
g_ascii_strncasecmp
(
buf
,
"GOOD "
,
5
))
{
strncpy
(
good
,
buf
+
5
,
255
);
if
(
*
bad
&&
*
good
&&
g_hash_table_lookup
(
hashes
,
bad
)
==
NULL
)
{
GtkTreeIter
iter
;
/* We don't actually need to store the good string, since this
* hash is just being used to eliminate duplicate bad strings.
* The value has to be non-NULL so the lookup above will work.
*/
g_hash_table_insert
(
hashes
,
g_strdup
(
bad
),
GINT_TO_POINTER
(
1
));
if
(
!
complete
)
case_sensitive
=
TRUE
;
gtk_list_store_append
(
model
,
&
iter
);
gtk_list_store_set
(
model
,
&
iter
,
BAD_COLUMN
,
bad
,
GOOD_COLUMN
,
good
,
WORD_ONLY_COLUMN
,
complete
,
CASE_SENSITIVE_COLUMN
,
case_sensitive
,
-1
);
}
bad
[
0
]
=
'\0'
;
complete
=
TRUE
;
case_sensitive
=
FALSE
;
}
}
}
g_free
(
ibuf
);
g_hash_table_destroy
(
hashes
);
gtk_tree_sortable_set_sort_column_id
(
GTK_TREE_SORTABLE
(
model
),
0
,
GTK_SORT_ASCENDING
);
}
static
GtkWidget
*
tree
;
static
GtkWidget
*
bad_entry
;
static
GtkWidget
*
good_entry
;
static
GtkWidget
*
complete_toggle
;
static
GtkWidget
*
case_toggle
;
static
void
save_list
(
void
);
static
void
on_edited
(
GtkCellRendererText
*
cellrenderertext
,
gchar
*
path
,
gchar
*
arg2
,
gpointer
data
)
{
GtkTreeIter
iter
;
GValue
val
;
if
(
arg2
[
0
]
==
'\0'
)
{
gdk_beep
();
return
;
}
g_return_if_fail
(
gtk_tree_model_get_iter_from_string
(
GTK_TREE_MODEL
(
model
),
&
iter
,
path
));
val
.
g_type
=
0
;
gtk_tree_model_get_value
(
GTK_TREE_MODEL
(
model
),
&
iter
,
GPOINTER_TO_INT
(
data
),
&
val
);
if
(
!
purple_strequal
(
arg2
,
g_value_get_string
(
&
val
)))
{
gtk_list_store_set
(
model
,
&
iter
,
GPOINTER_TO_INT
(
data
),
arg2
,
-1
);
save_list
();
}
g_value_unset
(
&
val
);
}
static
void
word_only_toggled
(
GtkCellRendererToggle
*
cellrenderertoggle
,
gchar
*
path
,
gpointer
data
){
GtkTreeIter
iter
;
gboolean
enabled
;
g_return_if_fail
(
gtk_tree_model_get_iter_from_string
(
GTK_TREE_MODEL
(
model
),
&
iter
,
path
));
gtk_tree_model_get
(
GTK_TREE_MODEL
(
model
),
&
iter
,
WORD_ONLY_COLUMN
,
&
enabled
,
-1
);
gtk_list_store_set
(
GTK_LIST_STORE
(
model
),
&
iter
,
WORD_ONLY_COLUMN
,
!
enabled
,
-1
);
/* I want to be sure that the above change has happened to the GtkTreeView first. */
gtk_list_store_set
(
GTK_LIST_STORE
(
model
),
&
iter
,
CASE_SENSITIVE_COLUMN
,
enabled
,
-1
);
save_list
();
}
static
void
case_sensitive_toggled
(
GtkCellRendererToggle
*
cellrenderertoggle
,
gchar
*
path
,
gpointer
data
){
GtkTreeIter
iter
;
gboolean
enabled
;
g_return_if_fail
(
gtk_tree_model_get_iter_from_string
(
GTK_TREE_MODEL
(
model
),
&
iter
,
path
));
/* Prevent the case sensitive column from changing on non-whole word replacements.
* Ideally, the column would be set insensitive in the word_only_toggled callback. */
gtk_tree_model_get
(
GTK_TREE_MODEL
(
model
),
&
iter
,
WORD_ONLY_COLUMN
,
&
enabled
,
-1
);
if
(
!
enabled
)
return
;
gtk_tree_model_get
(
GTK_TREE_MODEL
(
model
),
&
iter
,
CASE_SENSITIVE_COLUMN
,
&
enabled
,
-1
);
gtk_list_store_set
(
GTK_LIST_STORE
(
model
),
&
iter
,
CASE_SENSITIVE_COLUMN
,
!
enabled
,
-1
);
save_list
();
}
static
void
list_add_new
(
void
)
{
GtkTreeIter
iter
;
const
char
*
word
=
gtk_entry_get_text
(
GTK_ENTRY
(
bad_entry
));
gboolean
case_sensitive
=
gtk_toggle_button_get_active
(
GTK_TOGGLE_BUTTON
(
case_toggle
));
if
(
gtk_tree_model_get_iter_first
(
GTK_TREE_MODEL
(
model
),
&
iter
))
{
char
*
tmpword
=
g_utf8_casefold
(
word
,
-1
);
do
{
GValue
bad_val
;
gboolean
match
;
bad_val
.
g_type
=
0
;
gtk_tree_model_get_value
(
GTK_TREE_MODEL
(
model
),
&
iter
,
BAD_COLUMN
,
&
bad_val
);
if
(
case_sensitive
)
{
GValue
case_sensitive_val
;
case_sensitive_val
.
g_type
=
0
;
gtk_tree_model_get_value
(
GTK_TREE_MODEL
(
model
),
&
iter
,
CASE_SENSITIVE_COLUMN
,
&
case_sensitive_val
);
/* If they're both case-sensitive, then compare directly.
* Otherwise, they overlap. */
if
(
g_value_get_boolean
(
&
case_sensitive_val
))
{
match
=
purple_strequal
(
g_value_get_string
(
&
bad_val
),
word
);
}
else
{
char
*
bad
=
g_utf8_casefold
(
g_value_get_string
(
&
bad_val
),
-1
);
match
=
purple_strequal
(
bad
,
tmpword
);
g_free
(
bad
);
}
g_value_unset
(
&
case_sensitive_val
);
}
else
{
char
*
bad
=
g_utf8_casefold
(
g_value_get_string
(
&
bad_val
),
-1
);
match
=
purple_strequal
(
bad
,
tmpword
);
g_free
(
bad
);
}
if
(
match
)
{
g_value_unset
(
&
bad_val
);
g_free
(
tmpword
);
purple_notify_error
(
NULL
,
_
(
"Duplicate Correction"
),
_
(
"The specified word already exists in the correction list."
),
gtk_entry_get_text
(
GTK_ENTRY
(
bad_entry
)),
NULL
);
return
;
}
g_value_unset
(
&
bad_val
);
}
while
(
gtk_tree_model_iter_next
(
GTK_TREE_MODEL
(
model
),
&
iter
));
g_free
(
tmpword
);
}
gtk_list_store_append
(
model
,
&
iter
);
gtk_list_store_set
(
model
,
&
iter
,
BAD_COLUMN
,
word
,
GOOD_COLUMN
,
gtk_entry_get_text
(
GTK_ENTRY
(
good_entry
)),
WORD_ONLY_COLUMN
,
gtk_toggle_button_get_active
(
GTK_TOGGLE_BUTTON
(
complete_toggle
)),
CASE_SENSITIVE_COLUMN
,
case_sensitive
,
-1
);
gtk_editable_delete_text
(
GTK_EDITABLE
(
bad_entry
),
0
,
-1
);
gtk_editable_delete_text
(
GTK_EDITABLE
(
good_entry
),
0
,
-1
);
gtk_toggle_button_set_active
(
GTK_TOGGLE_BUTTON
(
complete_toggle
),
TRUE
);
gtk_toggle_button_set_active
(
GTK_TOGGLE_BUTTON
(
case_toggle
),
FALSE
);
gtk_widget_grab_focus
(
bad_entry
);
save_list
();
}
static
void
add_selected_row_to_list
(
GtkTreeModel
*
model
,
GtkTreePath
*
path
,
GtkTreeIter
*
iter
,
gpointer
data
)
{
GtkTreeRowReference
*
row_reference
;
GSList
**
list
=
(
GSList
**
)
data
;
row_reference
=
gtk_tree_row_reference_new
(
model
,
path
);
*
list
=
g_slist_prepend
(
*
list
,
row_reference
);
}
static
void
remove_row
(
gpointer
data
)
{
GtkTreeRowReference
*
row_reference
=
(
GtkTreeRowReference
*
)
data
;
GtkTreePath
*
path
;
GtkTreeIter
iter
;
path
=
gtk_tree_row_reference_get_path
(
row_reference
);
if
(
gtk_tree_model_get_iter
(
GTK_TREE_MODEL
(
model
),
&
iter
,
path
))
gtk_list_store_remove
(
model
,
&
iter
);
gtk_tree_path_free
(
path
);
gtk_tree_row_reference_free
(
row_reference
);
}
static
void
list_delete
(
void
)
{
GtkTreeSelection
*
sel
;
GSList
*
list
=
NULL
;
sel
=
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
tree
));
gtk_tree_selection_selected_foreach
(
sel
,
add_selected_row_to_list
,
&
list
);
g_slist_free_full
(
list
,
remove_row
);
save_list
();
}
static
void
save_list
()
{
GString
*
data
;
GtkTreeIter
iter
;
data
=
g_string_new
(
""
);
if
(
gtk_tree_model_get_iter_first
(
GTK_TREE_MODEL
(
model
),
&
iter
))
{
do
{
GValue
val0
;
GValue
val1
;
GValue
val2
;
GValue
val3
;
val0
.
g_type
=
0
;
val1
.
g_type
=
0
;
val2
.
g_type
=
0
;
val3
.
g_type
=
0
;
gtk_tree_model_get_value
(
GTK_TREE_MODEL
(
model
),
&
iter
,
BAD_COLUMN
,
&
val0
);
gtk_tree_model_get_value
(
GTK_TREE_MODEL
(
model
),
&
iter
,
GOOD_COLUMN
,
&
val1
);
gtk_tree_model_get_value
(
GTK_TREE_MODEL
(
model
),
&
iter
,
WORD_ONLY_COLUMN
,
&
val2
);
gtk_tree_model_get_value
(
GTK_TREE_MODEL
(
model
),
&
iter
,
CASE_SENSITIVE_COLUMN
,
&
val3
);
g_string_append_printf
(
data
,
"COMPLETE %d
\n
CASE %d
\n
BAD %s
\n
GOOD %s
\n\n
"
,
g_value_get_boolean
(
&
val2
),
g_value_get_boolean
(
&
val3
),
g_value_get_string
(
&
val0
),
g_value_get_string
(
&
val1
));
g_value_unset
(
&
val0
);
g_value_unset
(
&
val1
);
g_value_unset
(
&
val2
);
g_value_unset
(
&
val3
);
}
while
(
gtk_tree_model_iter_next
(
GTK_TREE_MODEL
(
model
),
&
iter
));
}
purple_util_write_data_to_config_file
(
"dict"
,
data
->
str
,
-1
);
g_string_free
(
data
,
TRUE
);
}
static
void
on_selection_changed
(
GtkTreeSelection
*
sel
,
gpointer
data
)
{
gint
num_selected
;
num_selected
=
gtk_tree_selection_count_selected_rows
(
sel
);
gtk_widget_set_sensitive
((
GtkWidget
*
)
data
,
(
num_selected
>
0
));
}
static
gboolean
non_empty
(
const
char
*
s
)
{
while
(
*
s
&&
g_ascii_isspace
(
*
s
))
s
++
;
return
*
s
;
}
static
void
on_entry_changed
(
GtkEditable
*
editable
,
gpointer
data
)
{
gtk_widget_set_sensitive
((
GtkWidget
*
)
data
,
non_empty
(
gtk_entry_get_text
(
GTK_ENTRY
(
bad_entry
)))
&&
non_empty
(
gtk_entry_get_text
(
GTK_ENTRY
(
good_entry
))));
}
static
void
whole_words_button_toggled
(
GtkToggleButton
*
complete_toggle
,
GtkToggleButton
*
case_toggle
)
{
gboolean
enabled
=
gtk_toggle_button_get_active
(
complete_toggle
);
gtk_toggle_button_set_active
(
case_toggle
,
!
enabled
);
gtk_widget_set_sensitive
(
GTK_WIDGET
(
case_toggle
),
enabled
);
}
static
GtkWidget
*
get_config_frame
(
PurplePlugin
*
plugin
)
{
GtkWidget
*
ret
,
*
vbox
;
GtkWidget
*
hbox
;
GtkWidget
*
button
;
GtkSizeGroup
*
sg
;
GtkSizeGroup
*
sg2
;
GtkCellRenderer
*
renderer
;
GtkTreeViewColumn
*
column
;
GtkWidget
*
vbox2
;
GtkWidget
*
vbox3
;
ret
=
gtk_box_new
(
GTK_ORIENTATION_VERTICAL
,
18
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
ret
),
12
);
vbox
=
pidgin_make_frame
(
ret
,
_
(
"Text Replacements"
));
gtk_container_set_border_width
(
GTK_CONTAINER
(
vbox
),
4
);
gtk_widget_show
(
vbox
);
tree
=
gtk_tree_view_new_with_model
(
GTK_TREE_MODEL
(
model
));
gtk_widget_set_size_request
(
tree
,
-1
,
200
);
renderer
=
gtk_cell_renderer_text_new
();
g_object_set
(
G_OBJECT
(
renderer
),
"editable"
,
TRUE
,
NULL
);
g_signal_connect
(
G_OBJECT
(
renderer
),
"edited"
,
G_CALLBACK
(
on_edited
),
GINT_TO_POINTER
(
0
));
column
=
gtk_tree_view_column_new_with_attributes
(
_
(
"You type"
),
renderer
,
"text"
,
BAD_COLUMN
,
NULL
);
gtk_tree_view_column_set_sizing
(
column
,
GTK_TREE_VIEW_COLUMN_FIXED
);
gtk_tree_view_column_set_fixed_width
(
column
,
150
);
gtk_tree_view_column_set_resizable
(
column
,
TRUE
);
gtk_tree_view_append_column
(
GTK_TREE_VIEW
(
tree
),
column
);
renderer
=
gtk_cell_renderer_text_new
();
g_object_set
(
G_OBJECT
(
renderer
),
"editable"
,
TRUE
,
NULL
);
g_signal_connect
(
G_OBJECT
(
renderer
),
"edited"
,
G_CALLBACK
(
on_edited
),
GINT_TO_POINTER
(
1
));
column
=
gtk_tree_view_column_new_with_attributes
(
_
(
"You send"
),
renderer
,
"text"
,
GOOD_COLUMN
,
NULL
);
gtk_tree_view_column_set_sizing
(
column
,
GTK_TREE_VIEW_COLUMN_FIXED
);
gtk_tree_view_column_set_fixed_width
(
column
,
150
);
gtk_tree_view_column_set_resizable
(
column
,
TRUE
);
gtk_tree_view_append_column
(
GTK_TREE_VIEW
(
tree
),
column
);
renderer
=
gtk_cell_renderer_toggle_new
();
g_object_set
(
G_OBJECT
(
renderer
),
"activatable"
,
TRUE
,
NULL
);
g_signal_connect
(
G_OBJECT
(
renderer
),
"toggled"
,
G_CALLBACK
(
word_only_toggled
),
NULL
);
column
=
gtk_tree_view_column_new_with_attributes
(
_
(
"Whole words only"
),
renderer
,
"active"
,
WORD_ONLY_COLUMN
,
NULL
);
gtk_tree_view_column_set_resizable
(
column
,
TRUE
);
gtk_tree_view_append_column
(
GTK_TREE_VIEW
(
tree
),
column
);
renderer
=
gtk_cell_renderer_toggle_new
();
g_object_set
(
G_OBJECT
(
renderer
),
"activatable"
,
TRUE
,
NULL
);
g_signal_connect
(
G_OBJECT
(
renderer
),
"toggled"
,
G_CALLBACK
(
case_sensitive_toggled
),
NULL
);
column
=
gtk_tree_view_column_new_with_attributes
(
_
(
"Case sensitive"
),
renderer
,
"active"
,
CASE_SENSITIVE_COLUMN
,
NULL
);
gtk_tree_view_column_set_resizable
(
column
,
TRUE
);
gtk_tree_view_append_column
(
GTK_TREE_VIEW
(
tree
),
column
);
gtk_tree_selection_set_mode
(
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
tree
)),
GTK_SELECTION_MULTIPLE
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
pidgin_make_scrollable
(
tree
,
GTK_POLICY_NEVER
,
GTK_POLICY_ALWAYS
,
GTK_SHADOW_IN
,
-1
,
-1
),
TRUE
,
TRUE
,
0
);
gtk_widget_show
(
tree
);
hbox
=
gtk_button_box_new
(
GTK_ORIENTATION_HORIZONTAL
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
hbox
,
FALSE
,
FALSE
,
0
);
gtk_widget_show
(
hbox
);
button
=
gtk_button_new_with_mnemonic
(
_
(
"_Delete"
));
g_signal_connect
(
G_OBJECT
(
button
),
"clicked"
,
G_CALLBACK
(
list_delete
),
NULL
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
button
,
FALSE
,
FALSE
,
0
);
gtk_widget_set_sensitive
(
button
,
FALSE
);
g_signal_connect
(
G_OBJECT
(
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
tree
))),
"changed"
,
G_CALLBACK
(
on_selection_changed
),
button
);
gtk_widget_show
(
button
);
vbox
=
pidgin_make_frame
(
ret
,
_
(
"Add a new text replacement"
));
hbox
=
gtk_box_new
(
GTK_ORIENTATION_HORIZONTAL
,
6
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
hbox
,
TRUE
,
TRUE
,
0
);
gtk_widget_show
(
hbox
);
vbox2
=
gtk_box_new
(
GTK_ORIENTATION_VERTICAL
,
6
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
vbox2
,
TRUE
,
TRUE
,
0
);
gtk_widget_show
(
vbox2
);
sg
=
gtk_size_group_new
(
GTK_SIZE_GROUP_HORIZONTAL
);
sg2
=
gtk_size_group_new
(
GTK_SIZE_GROUP_HORIZONTAL
);
bad_entry
=
gtk_entry_new
();
/* Set a minimum size. Since they're in a size group, the other entry will match up. */
gtk_widget_set_size_request
(
bad_entry
,
350
,
-1
);
gtk_size_group_add_widget
(
sg2
,
bad_entry
);
pidgin_add_widget_to_vbox
(
GTK_BOX
(
vbox2
),
_
(
"You _type:"
),
sg
,
bad_entry
,
FALSE
,
NULL
);
good_entry
=
gtk_entry_new
();
gtk_size_group_add_widget
(
sg2
,
good_entry
);
pidgin_add_widget_to_vbox
(
GTK_BOX
(
vbox2
),
_
(
"You _send:"
),
sg
,
good_entry
,
FALSE
,
NULL
);
/* Created here so it can be passed to whole_words_button_toggled. */
case_toggle
=
gtk_check_button_new_with_mnemonic
(
_
(
"_Exact case match (uncheck for automatic case handling)"
));
complete_toggle
=
gtk_check_button_new_with_mnemonic
(
_
(
"Only replace _whole words"
));
gtk_toggle_button_set_active
(
GTK_TOGGLE_BUTTON
(
complete_toggle
),
TRUE
);
g_signal_connect
(
G_OBJECT
(
complete_toggle
),
"clicked"
,
G_CALLBACK
(
whole_words_button_toggled
),
case_toggle
);
gtk_widget_show
(
complete_toggle
);
gtk_box_pack_start
(
GTK_BOX
(
vbox2
),
complete_toggle
,
FALSE
,
FALSE
,
0
);
/* The button is created above so it can be passed to whole_words_button_toggled. */
gtk_toggle_button_set_active
(
GTK_TOGGLE_BUTTON
(
case_toggle
),
FALSE
);
gtk_widget_show
(
case_toggle
);
gtk_box_pack_start
(
GTK_BOX
(
vbox2
),
case_toggle
,
FALSE
,
FALSE
,
0
);
button
=
gtk_button_new_with_mnemonic
(
_
(
"_Add"
));
g_signal_connect
(
G_OBJECT
(
button
),
"clicked"
,
G_CALLBACK
(
list_add_new
),
NULL
);
vbox3
=
gtk_box_new
(
GTK_ORIENTATION_VERTICAL
,
0
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
vbox3
,
TRUE
,
FALSE
,
0
);
gtk_widget_show
(
vbox3
);
gtk_box_pack_end
(
GTK_BOX
(
vbox3
),
button
,
FALSE
,
FALSE
,
0
);
g_signal_connect
(
G_OBJECT
(
bad_entry
),
"changed"
,
G_CALLBACK
(
on_entry_changed
),
button
);
g_signal_connect
(
G_OBJECT
(
good_entry
),
"changed"
,
G_CALLBACK
(
on_entry_changed
),
button
);
gtk_widget_set_sensitive
(
button
,
FALSE
);
gtk_widget_show
(
button
);
#if 0
vbox = pidgin_make_frame(ret, _("General Text Replacement Options"));
pidgin_prefs_checkbox(_("Enable replacement of last word on send"),
"/plugins/gtk/spellchk/last_word_replace", vbox);
#endif
gtk_widget_show_all
(
ret
);
g_object_unref
(
sg
);
g_object_unref
(
sg2
);
return
ret
;
}
/*
* EXPORTED FUNCTIONS
*/
static
GPluginPluginInfo
*
spell_check_query
(
GError
**
error
)
{
const
gchar
*
const
authors
[]
=
{
"Eric Warmenhoven <eric@warmenhoven.org>"
,
NULL
};
return
pidgin_plugin_info_new
(
"id"
,
SPELLCHECK_PLUGIN_ID
,
"name"
,
N_
(
"Text replacement"
),
"version"
,
DISPLAY_VERSION
,
"category"
,
N_
(
"Utility"
),
"summary"
,
N_
(
"Replaces text in outgoing messages according to user-defined rules."
),
"description"
,
N_
(
"Replaces text in outgoing messages according to user-defined rules."
),
"authors"
,
authors
,
"website"
,
PURPLE_WEBSITE
,
"abi-version"
,
PURPLE_ABI_VERSION
,
"gtk-config-frame-cb"
,
get_config_frame
,
NULL
);
}
static
gboolean
spell_check_load
(
GPluginPlugin
*
plugin
,
GError
**
error
)
{
void
*
conv_handle
=
purple_conversations_get_handle
();
GList
*
convs
;
#if 0
purple_prefs_add_none("/plugins");
purple_prefs_add_none("/plugins/gtk");
purple_prefs_add_none("/plugins/gtk/spellchk");
purple_prefs_add_bool("/plugins/gtk/spellchk/last_word_replace", TRUE);
#endif
load_conf
();
/* Attach to existing conversations */
for
(
convs
=
purple_conversations_get_all
();
convs
!=
NULL
;
convs
=
convs
->
next
)
{
spellchk_new_attach
((
PurpleConversation
*
)
convs
->
data
);
}
purple_signal_connect
(
conv_handle
,
"conversation-created"
,
plugin
,
PURPLE_CALLBACK
(
spellchk_new_attach
),
NULL
);
return
TRUE
;
}
static
gboolean
spell_check_unload
(
GPluginPlugin
*
plugin
,
GError
**
error
)
{
GList
*
convs
;
/* Detach from existing conversations */
for
(
convs
=
purple_conversations_get_all
();
convs
!=
NULL
;
convs
=
convs
->
next
)
{
PidginConversation
*
gtkconv
=
PIDGIN_CONVERSATION
((
PurpleConversation
*
)
convs
->
data
);
spellchk
*
spell
=
g_object_get_data
(
G_OBJECT
(
gtkconv
->
entry
),
SPELLCHK_OBJECT_KEY
);
g_signal_handlers_disconnect_by_func
(
gtkconv
->
entry
,
message_send_cb
,
spell
);
g_object_set_data
(
G_OBJECT
(
gtkconv
->
entry
),
SPELLCHK_OBJECT_KEY
,
NULL
);
}
return
TRUE
;
}
GPLUGIN_NATIVE_PLUGIN_DECLARE
(
spell_check
)