T9exp

Gtk+ 2.0

Descrizione

Esperimento nella creazione di un inserimento di testo facilitato da suggerimenti basati su un dizionario pre impostato.


Sorgente

#include <gtk/gtk.h>
#include <string.h>
#include <ctype.h>

void change_text (GtkTextBuffer *textbuffer, gpointer user_data);

GtkTextBuffer *buffer;
GtkWidget *status_bar;
GtkWidget *textview;

int handler_buffer_id;
int handler_backspace;

int backspace_pressed = 0;

void set_backspace_pressed (void)
{
backspace_pressed = 1;
}

int main (int argc, char *argv[])
{
GtkWidget *window, *vbox, *hbox;
GtkWidget *scrolled_window;

gtk_init (&argc, &argv);

window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 320, 240);
gtk_window_set_title (GTK_WINDOW (window), "T9 Experiment");
g_signal_connect (G_OBJECT (window), "delete_event",
                   G_CALLBACK (gtk_main_quit), NULL);
gtk_widget_show (window);

vbox = gtk_vbox_new (FALSE, 0);
gtk_widget_show (vbox);
gtk_container_add (GTK_CONTAINER (window), vbox);

scrolled_window = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0);
gtk_widget_show (scrolled_window);

textview = gtk_text_view_new ();
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (textview), 3);
gtk_text_view_set_pixels_below_lines (GTK_TEXT_VIEW (textview), 2);
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (textview), GTK_WRAP_WORD);
gtk_widget_modify_font (textview, pango_font_description_from_string ("Monospace 8"));
gtk_container_add (GTK_CONTAINER (scrolled_window), textview);

buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
handler_buffer_id = g_signal_connect_object (G_OBJECT (buffer), "changed",
                          G_CALLBACK (change_text), NULL, G_CONNECT_SWAPPED);
handler_backspace = g_signal_connect_object (G_OBJECT (textview), "backspace",
                          G_CALLBACK (set_backspace_pressed), NULL, G_CONNECT_SWAPPED);

gtk_widget_show (textview);

hbox = gtk_hbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox);

status_bar = gtk_statusbar_new ();
gtk_box_pack_start (GTK_BOX (hbox), status_bar, TRUE, TRUE, 0);
gtk_widget_show (status_bar);

gtk_statusbar_pop (GTK_STATUSBAR (status_bar), 1);
gtk_statusbar_push (GTK_STATUSBAR (status_bar), 1, "Caratteri: 0 - Parole: 0");

gtk_main ();

return 0;
}

char *get_word (GtkTextIter *start, GtkTextIter *end)
{
char *str;

gtk_text_iter_backward_word_start (start);
gtk_text_iter_forward_word_end (end);

if ( gtk_text_iter_equal (start, end) )
      return NULL;

return gtk_text_buffer_get_text (buffer, start, end, FALSE);
}

gboolean is_separator (char c)
{
static const char *token = " -.,;:#+*][{}^'?!\"£$%&/\\()=|<>\n\t\r";
int lt, j;

lt = strlen (token);
for ( j = 0; j < lt; j++ )
       if ( token[j] == c )
            return TRUE;

return FALSE;
}

int gtk_text_buffer_get_word_count (GtkTextBuffer *buffer)
{
GtkTextIter start, end;
char *str;
int j, k, ls, cnt;

gtk_text_buffer_get_bounds (buffer, &start, &end);
str = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
ls = strlen (str);

for ( j = (cnt = 1) - 1; j < ls; j++ )
       if ( is_separator (str[j]) && !is_separator (j ? str[j - 1] : 'h') )
            cnt++;

if ( is_separator (str[j - 1]) )
      cnt--;

g_free (str);

return cnt;
}

char *get_suggest (char *word)
{
GIOChannel *gic;
GError *error = NULL;
GString *string;
gsize seek;
int j, k, w;
char *l_str;

gic = g_io_channel_new_file ("words.italian.txt", "r", &error);
if ( !gic ) {
      g_error ("%s", error->message);
      g_error_free (error);
      return NULL;
}

w = strlen (word);
string = g_string_new ("");
while ( G_IO_STATUS_EOF != g_io_channel_read_line_string (gic, string, &seek, &error) ) {
         k = strlen (string->str);
         if ( (k - 1) <= w )
              continue;

         for ( j = 0; j < w; j++ )
               if ( tolower (word[j]) != tolower (string->str[j]) )
                    break;

         if ( j < w )
              continue;

         g_io_channel_close (gic);
         l_str = g_strndup (string->str + w, string->len - (w + 1));
         g_string_free (string, TRUE);
         return l_str;
}

return g_strdup_printf ("");
}

void change_text (GtkTextBuffer *textbuffer, gpointer user_data)
{
GtkTextMark *mark;
GtkTextIter start, end, *select;
char *word, *statusbar, *suggest;

g_signal_handler_disconnect (buffer, handler_buffer_id);

if ( !GTK_IS_TEXT_BUFFER (buffer) )
      return;

gtk_text_buffer_delete_selection (buffer, TRUE, TRUE);
mark = gtk_text_buffer_get_insert (buffer);
gtk_text_buffer_get_iter_at_mark (buffer, &start, mark);
gtk_text_buffer_get_iter_at_mark (buffer, &end, mark);

word = get_word (&start, &end);
if ( !word )
      return;

if ( strlen (word) > 2 && !backspace_pressed) {
      suggest = get_suggest (word);
      gtk_text_buffer_insert (buffer, &end, suggest, -1);
      select = gtk_text_iter_copy (&end);
      gtk_text_iter_backward_chars (&end, strlen (suggest));
      gtk_text_buffer_select_range (buffer, &end, select);
      g_free (suggest);
}
g_free (word);

statusbar = g_strdup_printf ("Caratteri: %d - Parole: %d",
                              gtk_text_buffer_get_char_count (buffer),
                              gtk_text_buffer_get_word_count (buffer));
gtk_statusbar_pop (GTK_STATUSBAR (status_bar), 1);
gtk_statusbar_push (GTK_STATUSBAR (status_bar), 1, statusbar);
g_free (statusbar);

if ( backspace_pressed )
      backspace_pressed = 0;

handler_buffer_id = g_signal_connect_object (G_OBJECT (buffer), "changed",
                          G_CALLBACK (change_text), NULL, G_CONNECT_SWAPPED);
}