? gok/gok-word-completion-changes.txt
? gok/keyboard-geometry
? gok/test-gok-wordcomplete
? gok/word-complete.c.foo
Index: gok/gok-utf8-word-complete.c
===================================================================
RCS file: /cvs/gnome/gok/gok/gok-utf8-word-complete.c,v
retrieving revision 1.1
diff -u -r1.1 gok-utf8-word-complete.c
--- gok/gok-utf8-word-complete.c	1 Oct 2003 15:35:11 -0000	1.1
+++ gok/gok-utf8-word-complete.c	1 Oct 2003 20:33:49 -0000
@@ -19,10 +19,13 @@
 *
 */
 
+#include <string.h>
 #include <gnome.h>
 #include "gok-log.h"
 #include "gok-utf8-word-complete.h"
 
+#define MAX_DICTIONARY_ENTRIES 100000
+
 /* private functions */
 
 /* implementations of GokWordCompleteClass virtual methods */
@@ -41,6 +44,10 @@
 	gint   priority;
 } WordPrediction;
 
+static WordPrediction *dict_entries = NULL;
+
+static gint word_count;
+
 /* The filename of the dictionary file */
 static gchar *dictionary_full_path;
 
@@ -51,6 +58,7 @@
 /* private intermal methods */
 static GSList *utf8_wordcomplete_find (const gchar *word);
 static gint utf8_sort_by_priority (gconstpointer a, gconstpointer b);
+static gboolean utf8_add_from_system_dict (WordPrediction **dictionary, const gchar *system_dict_filename);
 
 /* 
  * This macro initializes GokUtf8WordComplete with the GType system 
@@ -75,7 +83,10 @@
 static gboolean
 utf8_wordcomplete_open (GokWordComplete *complete, const gchar *directory)
 {
-	FILE *file;
+	gchar *contents;
+	gchar **dictionary_list = NULL;
+	gint i;
+	GError *error = NULL;
 
 	gok_log ("gok_utf8_wordcomplete_open");
 	
@@ -83,13 +94,52 @@
 
 	/* open the dictionary file */
 	dictionary_full_path = g_build_filename (directory, "dictionary.txt", NULL);
-	file = fopen (dictionary_full_path, "rt");
-	if (file == NULL)
+
+	if (!g_file_get_contents (dictionary_full_path, &contents, NULL, &error))
+	{
+		fprintf (stderr, "could not get file contents\n");
+		return FALSE;
+	}
+
+	/* split into lines */
+	dictionary_list = 
+		g_strsplit (contents, "\n", MAX_DICTIONARY_ENTRIES + 1 - word_count);
+
+	if (dictionary_list == NULL) 
 	{
-		/* can't open dictionary file! */
-		gok_log_x ("Can't open dictionary file in utf8_wordcomplete_open !\n");
 		return FALSE;
 	}
+
+	g_free (contents);
+
+	for (word_count = 0; dictionary_list[word_count]; ++word_count)	
+		; /* noop */
+
+	/* ignore first line, it's just "WPDict"; and backpedal once for end of loop */
+	word_count -= 2;
+
+	dict_entries = g_new0 (WordPrediction, word_count + 1);
+
+	for (i = 0; i < word_count; ++i)
+	{
+		gchar *string;
+		gint   priority;
+		gchar **line;
+		line = g_strsplit (dictionary_list[i+1], "\t", 3);
+		string = (line && line[0]) ? g_utf8_normalize (line[0], -1, G_NORMALIZE_ALL): NULL;
+		dict_entries[i].string = string ? g_utf8_casefold (string, -1): NULL;
+		if (string) 
+			g_free (string);
+		dict_entries[i].priority = (line && line[1]) ? g_ascii_strtod (line[1], NULL) : 0;
+		if (line) 
+			g_strfreev (line);
+	}
+	dict_entries[word_count].string = NULL;
+
+	utf8_add_from_system_dict (&dict_entries, "/usr/share/dict/words");
+
+	g_strfreev (dictionary_list);
+
 	return TRUE;
 }
 
@@ -128,21 +178,12 @@
 		WordPrediction *prediction;
 		++n;
 		prediction = g_slist_nth_data (predictions, n);
-		word_predict_list [n] = prediction ? prediction->string : NULL;
+		word_predict_list [n] = prediction ? strdup (prediction->string) : NULL;
 	} while (word_predict_list [n] && n < num_predictions);
 
-	word_predict_list [num_predictions] = NULL; /* in case predictions-len >= num_predictions */
+	word_predict_list [num_predictions] = NULL; /* in case predictions-length >= num_predictions */
 
-	/* free the extra storage; returned strings will be freed later */
-	data = g_slist_nth_data (predictions, num_predictions);
-	while (data) {
-		WordPrediction *prediction = (WordPrediction *) data;
-		m = num_predictions;
-		g_free (prediction->string);
-		g_free (prediction);
-		++m;
-		data = g_slist_nth_data (predictions, m);
-	}
+	/* free the extra storage */
 	g_slist_free (predictions);
 
 	/* were there any predictions? */
@@ -158,25 +199,21 @@
 	return word_predict_list; /* predictions made! */
 }
 
-static WordPrediction*
-prediction_new (const gchar *string, gint priority)
-{
-	WordPrediction *prediction = g_new0 (WordPrediction, 1);
-	prediction->string = strdup (string);
-	prediction->priority = priority;
-	return prediction;
-}
-
 static GSList *
 utf8_wordcomplete_find (const gchar *word)
 {
 	GSList *found = NULL;
 	WordPrediction *prediction;
-	found = g_slist_append (found, prediction_new ("foo", 1));
-	found = g_slist_append (found, prediction_new ("bar", 1));
-	found = g_slist_append (found, prediction_new ("kilroy", 2));
-	found = g_slist_append (found, prediction_new ("was", 2));
-	found = g_slist_append (found, prediction_new ("here", 2));
+	gint i;
+
+	for (i = 0; dict_entries[i].string; ++i) 
+	{
+		if (g_str_has_prefix (dict_entries[i].string, word)) 
+		{
+			found = g_slist_append (found, &dict_entries[i]);
+		}
+	}
+
 	return found;
 }
 
@@ -189,4 +226,46 @@
 		return p_b->priority - p_a->priority;
 	else
 		return (a) ? -1 : ((b) ? 1 : 0);
+}
+
+static gboolean
+utf8_add_from_system_dict (WordPrediction **dictionary, const gchar *system_dict_filename)
+{
+	gchar *contents;
+	gchar **dictionary_list = NULL;
+	GError *error = NULL;
+	gint count, i;
+
+	if (!g_file_get_contents (system_dict_filename, &contents, NULL, &error))
+		return FALSE;
+	/* */
+	/* split into lines */
+	dictionary_list = 
+		g_strsplit (contents, "\n", MAX_DICTIONARY_ENTRIES + 1);
+
+	if (dictionary_list == NULL) 
+	{
+		return FALSE;
+	}
+
+	g_free (contents);
+
+	for (count = 0; dictionary_list [count]; ++count)	
+		; /* noop */
+
+	*dictionary = g_renew (WordPrediction, *dictionary, word_count + count);
+	
+	fprintf (stderr, "Adding %d new words from system dictionary; total words = %d.\n", count, word_count + count);
+
+	for (i = 0; dictionary_list [i]; ++i, ++word_count)
+	{
+		(* dictionary) [word_count].string = dictionary_list [i] ? strdup (dictionary_list [i]) : (void *) NULL;
+		(* dictionary) [word_count].priority = 1;
+	}
+
+	(* dictionary) [word_count].string = NULL;
+
+	g_strfreev (dictionary_list);
+
+	return TRUE;
 }
Index: gok/gok-word-complete.c
===================================================================
RCS file: /cvs/gnome/gok/gok/gok-word-complete.c,v
retrieving revision 1.23
diff -u -r1.23 gok-word-complete.c
--- gok/gok-word-complete.c	1 Oct 2003 15:35:11 -0000	1.23
+++ gok/gok-word-complete.c	1 Oct 2003 20:33:50 -0000
@@ -41,6 +41,7 @@
 #include "gok-keyboard.h"
 
 #include "word-complete.h" /* TODO: remove this when we make this class abstract */
+#include "gok-utf8-word-complete.h"
 
 static void gok_wordcomplete_finalize (GObject *obj);
 static void gok_wordcomplete_real_reset (GokWordComplete *complete);
@@ -312,7 +313,7 @@
 gok_wordcomplete_get_default (void)
 {
 	if (default_wordcomplete_engine == NULL)
-		default_wordcomplete_engine = g_object_new (GOK_TYPE_TRIEWORDCOMPLETE, NULL);  
+		default_wordcomplete_engine = g_object_new (GOK_TYPE_UTF8WORDCOMPLETE, NULL);  
         /* TODO: establish default subtype and create type - making the base class abstract */
 	return default_wordcomplete_engine;
 }
Index: gok/word-complete.c
===================================================================
RCS file: /cvs/gnome/gok/gok/word-complete.c,v
retrieving revision 1.13
diff -u -r1.13 word-complete.c
--- gok/word-complete.c	1 Oct 2003 15:35:11 -0000	1.13
+++ gok/word-complete.c	1 Oct 2003 20:33:51 -0000
@@ -590,6 +590,8 @@
 		bMadePrediction = TRUE;
 	}
 
+	word_predict_list[i] = NULL;
+
 	/* were there any predictions? */
 	if (bMadePrediction == FALSE)
 	{
