2002-11-16 Chris Toshok <toshok@ximian.com> * gal/e-text/e-completion-test.c: Lots of GObject work. * gal/e-text/e-completion-view.[ch]: same. * gal/e-text/e-completion.[ch]: same. * gal/e-text/e-entry.[ch]: same. * gal/e-text/e-table-text-model.[ch]: same. * gal/e-text/e-text-model-uri.[ch]: same. * gal/e-text/e-text-model.[ch]: same. * gal/e-text/e-text-test.c: same. * gal/e-text/e-text.[ch]: same. svn path=/trunk/; revision=18800
221 lines
4.9 KiB
C
221 lines
4.9 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
|
/*
|
|
* e-completion-test.c
|
|
* Copyright 2000, 2001, Ximian, Inc.
|
|
*
|
|
* Authors:
|
|
* Jon Trowbridge <trow@ximian.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License, version 2, as published by the Free Software Foundation.
|
|
*
|
|
* This library 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
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
* 02111-1307, USA.
|
|
*/
|
|
|
|
#include <gnome.h>
|
|
#include "e-completion.h"
|
|
#include "e-entry.h"
|
|
|
|
#define TIMEOUT 10
|
|
|
|
/* Dictionary Lookup test */
|
|
|
|
static gint word_count = 0;
|
|
static gchar **word_array = NULL;
|
|
|
|
static void
|
|
read_dict (void)
|
|
{
|
|
FILE *in = fopen ("/usr/share/dict/words", "r");
|
|
gchar buffer[128];
|
|
GList *word_list = NULL, *iter;
|
|
gint i;
|
|
|
|
while (fgets (buffer, 128, in)) {
|
|
gint len = strlen (buffer);
|
|
if (len > 0 && buffer[len-1] == '\n')
|
|
buffer[len-1] = '\0';
|
|
word_list = g_list_prepend (word_list, g_strdup (buffer));
|
|
++word_count;
|
|
}
|
|
fclose (in);
|
|
|
|
word_array = g_new (gchar *, word_count);
|
|
i = word_count-1;
|
|
for (iter = word_list; iter != NULL; iter = g_list_next (iter)) {
|
|
word_array[i] = (gchar *)iter->data;
|
|
--i;
|
|
}
|
|
}
|
|
|
|
static gint
|
|
find_word (const gchar *str)
|
|
{
|
|
gint a, b;
|
|
|
|
if (word_array == NULL)
|
|
read_dict ();
|
|
|
|
a = 0;
|
|
b = word_count-1;
|
|
|
|
while (b-a > 1) {
|
|
gint m = (a+b)/2;
|
|
gint cmp = g_strcasecmp (str, word_array[m]);
|
|
|
|
if (cmp < 0)
|
|
b = m;
|
|
else if (cmp > 0)
|
|
a = m;
|
|
else
|
|
return m;
|
|
}
|
|
|
|
return b;
|
|
}
|
|
|
|
struct {
|
|
ECompletion *complete;
|
|
const gchar *txt;
|
|
gint start;
|
|
gint current;
|
|
gint len;
|
|
gint limit;
|
|
gint count;
|
|
} dict_info;
|
|
static guint dict_tag = 0;
|
|
|
|
static gboolean
|
|
dict_check (gpointer ptr)
|
|
{
|
|
gint limit = dict_info.limit;
|
|
gint i;
|
|
|
|
/* If this is the first iteration, do the binary search in our word list to figure out
|
|
where to start. We do less work on the first iteration, to give more of a sense of
|
|
immediate feedback. */
|
|
if (dict_info.start < 0) {
|
|
dict_info.start = dict_info.current = find_word (dict_info.txt);
|
|
}
|
|
|
|
i = dict_info.current;
|
|
while (limit > 0
|
|
&& i < word_count
|
|
&& dict_info.count < 50
|
|
&& g_strncasecmp (dict_info.txt, word_array[i], dict_info.len) == 0) {
|
|
|
|
ECompletionMatch *match = g_new (ECompletionMatch, 1);
|
|
e_completion_match_construct (match);
|
|
e_completion_match_set_text (match, word_array[i], NULL);
|
|
match->score = dict_info.len / (double)strlen (word_array[i]);
|
|
e_completion_found_match (dict_info.complete, match);
|
|
|
|
++i;
|
|
--limit;
|
|
++dict_info.count;
|
|
}
|
|
dict_info.current = i;
|
|
dict_info.limit = MIN (dict_info.limit*2, 400);
|
|
|
|
if (limit != 0) {
|
|
dict_tag = 0;
|
|
e_completion_end_search (dict_info.complete);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
request_dict_search (ECompletion *complete, const gchar *txt, gint pos, gint limit, gpointer user_data)
|
|
{
|
|
gint len = strlen (txt);
|
|
|
|
if (dict_tag != 0) {
|
|
gtk_timeout_remove (dict_tag);
|
|
dict_tag = 0;
|
|
}
|
|
|
|
if (len > 0) {
|
|
dict_info.complete = complete;
|
|
dict_info.txt = txt;
|
|
dict_info.start = -1;
|
|
dict_info.current = -1;
|
|
dict_info.len = len;
|
|
dict_info.limit = 100;
|
|
dict_info.count = 0;
|
|
dict_tag = gtk_timeout_add (TIMEOUT, dict_check, NULL);
|
|
} else {
|
|
e_completion_end_search (complete);
|
|
}
|
|
}
|
|
|
|
static void
|
|
end_dict_search (ECompletion *complete, gpointer user_data)
|
|
{
|
|
if (dict_tag != 0) {
|
|
gtk_timeout_remove (dict_tag);
|
|
dict_tag = 0;
|
|
}
|
|
}
|
|
|
|
static void
|
|
popup_cb (EEntry *popup, GdkEventButton *ev, gint pos, gpointer user_data)
|
|
{
|
|
g_print ("popup at pos %d\n", pos);
|
|
}
|
|
|
|
int
|
|
main (int argc, gchar **argv)
|
|
{
|
|
ECompletion* complete;
|
|
GtkWidget *entry;
|
|
GtkWidget *win;
|
|
|
|
gnome_init ("ETextModelTest", "0.0", argc, argv);
|
|
|
|
read_dict ();
|
|
|
|
complete = e_completion_new ();
|
|
g_signal_connect (complete,
|
|
"request_completion",
|
|
G_CALLBACK (request_dict_search),
|
|
NULL);
|
|
g_signal_connect (complete,
|
|
"end_completion",
|
|
G_CALLBACK (end_dict_search),
|
|
NULL);
|
|
g_signal_connect (complete,
|
|
"cancel_completion",
|
|
G_CALLBACK (end_dict_search),
|
|
NULL);
|
|
|
|
win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
|
entry = e_entry_new ();
|
|
e_entry_enable_completion_full (E_ENTRY (entry), complete, 0, NULL);
|
|
e_entry_set_editable (E_ENTRY (entry), TRUE);
|
|
|
|
g_signal_connect (entry,
|
|
"popup",
|
|
G_CALLBACK (popup_cb),
|
|
NULL);
|
|
|
|
gtk_container_add (GTK_CONTAINER (win), entry);
|
|
gtk_widget_show_all (win);
|
|
|
|
gtk_main ();
|
|
|
|
return 0;
|
|
}
|