/* Source: http://www.bravegnu.org/gtktext/index.html */ #include <gtk/gtk.h> #include <string.h> #include <glib.h> /* List of functions and their corresponding tool tips. */ static char *tips[][2] = { {"printf" , "(const char *format, ...)"}, {"fprintf" , "(FILE *stream, const char *format, ...)"}, {"sprintf" , "(char *str, const char *format, ...)"}, {"snprintf", "(char *str, size_t size, const char *format, ...)"}, {"fputc" , "(int c, FILE *stream)"}, {"fputs" , "(const char *s, FILE *stream)"}, {"putc" , "(int c, FILE *stream)"}, {"putchar" , "(int c)"}, {"puts" , "(const char *s)"} }; #define NUM_TIPS (sizeof (tips) / sizeof (tips[0])) gchar *get_tip(gchar *text) { gint i; gboolean found; found = FALSE; for (i = 0; i < NUM_TIPS; i++) { if (strcmp (text, tips[i][0]) == 0) { found = TRUE; break; } } if (!found) return NULL; return g_strdup (tips[i][1]); } GtkWidget *tip_window_new (gchar *tip) { GtkWidget *win; GtkWidget *label; GtkWidget *eb; GdkColormap *cmap; GdkColor color; PangoFontDescription *pfd; win = gtk_window_new (GTK_WINDOW_POPUP); gtk_container_set_border_width (GTK_CONTAINER (win), 0); eb = gtk_event_box_new (); gtk_container_set_border_width (GTK_CONTAINER (eb), 1); gtk_container_add (GTK_CONTAINER (win), eb); label = gtk_label_new (tip); gtk_container_add (GTK_CONTAINER (eb), label); pfd = pango_font_description_from_string ("mono"); gtk_widget_modify_font (label, pfd); cmap = gtk_widget_get_colormap (win); color.red = 0; color.green = 0; color.blue = 0; if (gdk_colormap_alloc_color (cmap, &color, FALSE, TRUE)) gtk_widget_modify_bg (win, GTK_STATE_NORMAL, &color); else g_warning ("Color allocation failed!\n"); cmap = gtk_widget_get_colormap (eb); color.red = 65535; color.green = 65535; color.blue = 45535; if (gdk_colormap_alloc_color (cmap, &color, FALSE, TRUE)) gtk_widget_modify_bg (eb, GTK_STATE_NORMAL, &color); else g_warning ("Color allocation failed!\n"); return win; } /* Called when main window is destroyed. */ void win_destroy (void) { gtk_main_quit(); } void insert_open_brace(GtkWidget **tip_win, GtkWidget *text_view, GtkTextIter *arg1) { GdkWindow *win; GtkTextIter start; GdkRectangle buf_loc; gint x, y; gint win_x, win_y; gchar *text; gchar *tip_text; /* Get the word at cursor. */ start = *arg1; if (!gtk_text_iter_backward_word_start (&start)) return; text = gtk_text_iter_get_text (&start, arg1); g_strstrip (text); /* Get the corresponding tooltip. */ tip_text = get_tip(text); if (tip_text == NULL) return; /* Calculate the tool tip window location. */ gtk_text_view_get_iter_location (GTK_TEXT_VIEW (text_view), arg1, &buf_loc); g_print ("Buffer: %d, %d\n", buf_loc.x, buf_loc.y); gtk_text_view_buffer_to_window_coords (GTK_TEXT_VIEW (text_view), GTK_TEXT_WINDOW_WIDGET, buf_loc.x, buf_loc.y, &win_x, &win_y); g_print ("Window: %d, %d\n", win_x, win_y); win = gtk_text_view_get_window (GTK_TEXT_VIEW (text_view), GTK_TEXT_WINDOW_WIDGET); gdk_window_get_origin (win, &x, &y); /* Destroy any previous tool tip window. */ if (*tip_win != NULL) gtk_widget_destroy (GTK_WIDGET (*tip_win)); /* Create a new tool tip window and place it at the caculated location. */ *tip_win = tip_window_new (tip_text); g_free(tip_text); gtk_window_move (GTK_WINDOW (*tip_win), win_x + x, win_y + y + buf_loc.height); gtk_widget_show_all (*tip_win); } void insert_close_brace (GtkWidget **tip_win) { if (*tip_win != NULL) { gtk_widget_destroy (GTK_WIDGET (*tip_win)); *tip_win = NULL; } } void buffer_insert_text (GtkTextBuffer *textbuffer, GtkTextIter *arg1, gchar *arg2, gint arg3, gpointer user_data) { static GtkWidget *tip_win = NULL; if (strcmp (arg2, "(") == 0) insert_open_brace(&tip_win, GTK_WIDGET (user_data), arg1); if (strcmp (arg2, ")") == 0) insert_close_brace(&tip_win); } int main (int argc, char *argv[]) { GtkWidget *win; GtkWidget *scroll; GtkWidget *text_view; GtkTextBuffer *buffer; PangoFontDescription *pfd; gtk_init (&argc, &argv); /* Create the window. */ win = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect (G_OBJECT (win), "destroy", win_destroy, NULL); /* Create the text widget inside a scrolled window. */ scroll = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add (GTK_CONTAINER (win), scroll); text_view = gtk_text_view_new (); buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view)); g_signal_connect (G_OBJECT (buffer), "insert_text", G_CALLBACK (buffer_insert_text), text_view); gtk_container_add (GTK_CONTAINER (scroll), text_view); pfd = pango_font_description_from_string ("mono"); gtk_widget_modify_font (text_view, pfd); gtk_widget_show_all (win); gtk_main(); return 0; }