gtranslator r3593 - in trunk: . plugins plugins/source-view src



Author: icq
Date: Mon Sep 22 09:38:11 2008
New Revision: 3593
URL: http://svn.gnome.org/viewvc/gtranslator?rev=3593&view=rev

Log:
Merge source-code-view into the master branch to implement feature Source view plugin

Added:
   trunk/plugins/source-view/
   trunk/plugins/source-view/Makefile.am
   trunk/plugins/source-view/source-view-dialog.glade
   trunk/plugins/source-view/source-view-plugin.c
   trunk/plugins/source-view/source-view-plugin.h
   trunk/plugins/source-view/source-view.gtranslator-plugin.desktop.in
   trunk/plugins/source-view/viewer.c
   trunk/plugins/source-view/viewer.glade
   trunk/plugins/source-view/viewer.h
Modified:
   trunk/ChangeLog
   trunk/configure.ac
   trunk/plugins/Makefile.am
   trunk/src/comment.c
   trunk/src/comment.h

Modified: trunk/configure.ac
==============================================================================
--- trunk/configure.ac	(original)
+++ trunk/configure.ac	Mon Sep 22 09:38:11 2008
@@ -303,6 +303,7 @@
 plugins/fullscreen/Makefile
 plugins/insert-tags/Makefile
 plugins/open-tran/Makefile
+plugins/source-view/Makefile
 src/Makefile
 src/dialogs/Makefile
 src/toolbareditor/Makefile

Modified: trunk/plugins/Makefile.am
==============================================================================
--- trunk/plugins/Makefile.am	(original)
+++ trunk/plugins/Makefile.am	Mon Sep 22 09:38:11 2008
@@ -1,7 +1,8 @@
 SUBDIRS = 					\
 	alternate-language			\
 	fullscreen				\
-	insert-tags
+	insert-tags				\
+	source-view
 
 if USE_CHARMAP
 SUBDIRS += charmap

Added: trunk/plugins/source-view/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/plugins/source-view/Makefile.am	Mon Sep 22 09:38:11 2008
@@ -0,0 +1,45 @@
+# source-view plugin
+plugindir = $(libdir)/gtranslator/plugins
+
+INCLUDES = \
+	-I$(top_srcdir) 				\
+	-I$(top_srcdir)/src				\
+	-I$(top_srcdir)/src/plugin-system		\
+	$(GTRANSLATOR_CFLAGS) 				\
+	$(WARN_CFLAGS)					\
+	$(DISABLE_DEPRECATED_CFLAGS)			\
+	-DDATADIR=\""$(pkgdatadir)"\"                   \
+	-DGTR_LOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\"
+
+plugin_LTLIBRARIES = \
+	libsourceview.la
+
+libsourceview_la_SOURCES = \
+	source-view-plugin.c \
+	source-view-plugin.h \
+	viewer.c \
+	viewer.h
+
+libsourceview_la_LDFLAGS = \
+	$(PLUGIN_LIBTOOL_FLAGS)				\
+	$(GTRANSLATOR_LIBS)
+
+gladedir = $(pkgdatadir)
+
+glade_DATA =  \
+        viewer.glade \
+	source-view-dialog.glade
+
+# Plugin Info
+
+plugin_in_files = source-view.gtranslator-plugin.desktop.in
+
+%.gtranslator.plugin: %.gtranslator-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
+
+plugin_DATA = $(plugin_in_files:.gtranslator-plugin.desktop.in=.gtranslator.plugin)
+
+EXTRA_DIST = $(plugin_in_files)
+
+CLEANFILES = $(plugin_DATA)
+DISTCLEANFILES = $(plugin_DATA)
+

Added: trunk/plugins/source-view/source-view-dialog.glade
==============================================================================
--- (empty file)
+++ trunk/plugins/source-view/source-view-dialog.glade	Mon Sep 22 09:38:11 2008
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--Generated with glade3 3.4.5 on Mon Jun 30 12:37:34 2008 -->
+<glade-interface>
+  <widget class="GtkDialog" id="dialog">
+    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Source View Settings</property>
+    <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
+    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+    <property name="has_separator">False</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox1">
+        <property name="visible">True</property>
+        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+        <property name="spacing">2</property>
+        <child>
+          <widget class="GtkVBox" id="main_box">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="border_width">12</property>
+            <property name="spacing">6</property>
+            <child>
+              <widget class="GtkCheckButton" id="use_editor">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="label" translatable="yes">Use external editor</property>
+                <property name="response_id">0</property>
+                <property name="draw_indicator">True</property>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkVBox" id="program_box">
+                <property name="visible">True</property>
+                <child>
+                  <widget class="GtkLabel" id="label1">
+                    <property name="visible">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">&lt;b&gt;Program command:&lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkHBox" id="hbox1">
+                    <property name="visible">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="spacing">6</property>
+                    <child>
+                      <widget class="GtkLabel" id="label2">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="label" translatable="yes">    </property>
+                      </widget>
+                      <packing>
+                        <property name="expand">False</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkEntry" id="program_cmd">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="tooltip_text">E.g.: gedit</property>
+                      </widget>
+                      <packing>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="label3">
+                    <property name="visible">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">&lt;b&gt;Line command:&lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkHBox" id="hbox2">
+                    <property name="visible">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <child>
+                      <widget class="GtkLabel" id="label4">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="label" translatable="yes">     </property>
+                      </widget>
+                      <packing>
+                        <property name="expand">False</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkEntry" id="line_cmd">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="tooltip_text">E.g.: +</property>
+                      </widget>
+                      <packing>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">3</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area1">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="layout_style">GTK_BUTTONBOX_END</property>
+            <child>
+              <widget class="GtkButton" id="cancel_button">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">gtk-cancel</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">-6</property>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkButton" id="ok_button">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">gtk-ok</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">-5</property>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">GTK_PACK_END</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+</glade-interface>

Added: trunk/plugins/source-view/source-view-plugin.c
==============================================================================
--- (empty file)
+++ trunk/plugins/source-view/source-view-plugin.c	Mon Sep 22 09:38:11 2008
@@ -0,0 +1,696 @@
+/*
+ * Copyright (C) 2008  Ignacio Casal Quinteiro <nacho resa gmail com>
+ * 
+ *     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 3 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
+ *     MERCHANPOILITY 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "source-view-plugin.h"
+#include "comment.h"
+#include "utils.h"
+#include "viewer.h"
+#include "window.h"
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+#include <string.h>
+#include <gio/gio.h>
+#include <gconf/gconf-client.h>
+
+/* Gconf keys */
+#define SOURCE_VIEW_BASE_KEY "/apps/gtranslator/plugins/source-view"
+#define USE_EDITOR_KEY SOURCE_VIEW_BASE_KEY "/use_editor"
+#define PROGRAM_CMD_KEY SOURCE_VIEW_BASE_KEY "/program_cmd"
+#define LINE_CMD_KEY SOURCE_VIEW_BASE_KEY "/line_cmd"
+
+/* Glade */
+#define GLADE_FILE DATADIR"/source-view-dialog.glade"
+
+#define GTR_SOURCE_VIEW_PLUGIN_GET_PRIVATE(object) \
+				(G_TYPE_INSTANCE_GET_PRIVATE ((object),	\
+				GTR_TYPE_SOURCE_VIEW_PLUGIN,		\
+				GtranslatorSourceViewPluginPrivate))
+
+struct _GtranslatorSourceViewPluginPrivate
+{
+	GConfClient *gconf_client;
+	
+	/* Dialog stuff */
+	GtkWidget *dialog;
+	
+	GtkWidget *main_box;
+	GtkWidget *use_editor_checkbutton;
+	GtkWidget *program_box;
+	GtkWidget *program_cmd_entry;
+	GtkWidget *line_cmd_entry;
+	
+	GtranslatorWindow *window;
+
+	gint inserted_lines;
+};
+
+GTR_PLUGIN_REGISTER_TYPE(GtranslatorSourceViewPlugin, gtranslator_source_view_plugin)
+
+static void 
+insert_link (GtkTextBuffer *buffer, 
+	     GtkTextIter *iter,
+	     const gchar *path,
+	     gint *line)
+{
+	GtkTextTag *tag;
+	gchar *text;
+
+	tag = gtk_text_buffer_create_tag (buffer, NULL, 
+					  "foreground", "blue", 
+					  "underline", PANGO_UNDERLINE_SINGLE, 
+					  NULL);
+	g_object_set_data (G_OBJECT (tag), "path", g_strdup (path));
+	g_object_set_data (G_OBJECT (tag), "line", line);
+
+	text = g_strconcat (path, "\n", NULL);
+	gtk_text_buffer_insert_with_tags (buffer, iter, text, -1, tag, NULL);
+	g_free (text);
+}
+
+static void
+show_in_editor (const gchar *program_name,
+		const gchar *line_cmd,
+		const gchar *path,
+		gint line)
+{
+	gchar *open[4];
+
+	if (g_find_program_in_path (program_name))
+	{
+		open[0] = g_strdup (program_name);
+	}
+	else
+	{
+		GtkWidget *dialog;
+		
+		dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL,
+						 GTK_DIALOG_MODAL,
+						 GTK_BUTTONS_CLOSE,
+						 _("Please, install %s to be able to show the file"),
+						 program_name);
+		gtk_dialog_run (GTK_DIALOG (dialog));
+		gtk_widget_destroy (dialog);
+	}
+	
+	open[1] = g_strdup (path);
+	open[2] = g_strdup_printf ("%s%d",line_cmd, line);
+	open[3] = NULL;
+					
+	gdk_spawn_on_screen (gdk_screen_get_default (),
+			     NULL,
+			     open,
+			     NULL,
+			     G_SPAWN_SEARCH_PATH,
+			     NULL,
+			     NULL, NULL, NULL);
+	g_free (open[0]);
+	g_free (open[1]);
+	g_free (open[2]);
+}
+
+static void
+show_source (GtranslatorSourceViewPlugin *plugin,
+	     const gchar *path,
+	     gint line)
+{
+	gboolean use_editor;
+	
+	use_editor = gconf_client_get_bool (plugin->priv->gconf_client,
+					    USE_EDITOR_KEY,
+					    NULL);
+
+	if (use_editor)
+	{
+		gchar *program_cmd;
+		gchar *line_cmd;
+		
+		//Program cmd
+		program_cmd = gconf_client_get_string (plugin->priv->gconf_client,
+						       PROGRAM_CMD_KEY,
+						       NULL);
+	
+		//Line cmd
+		line_cmd = gconf_client_get_string (plugin->priv->gconf_client,
+						    LINE_CMD_KEY,
+						    NULL);
+		
+		show_in_editor (program_cmd,
+				line_cmd,
+				path, line);
+		
+		g_free (program_cmd);
+		g_free (line_cmd);
+	}
+	else gtranslator_show_viewer (plugin->priv->window,
+				      path, line);
+}
+
+static void
+follow_if_link (GtranslatorSourceViewPlugin *plugin,
+		GtkWidget   *text_view, 
+		GtkTextIter *iter)
+{
+	GSList *tags = NULL, *tagp = NULL;
+	GtranslatorTab *tab;
+	GtranslatorPo *po;
+	const gchar *po_path;
+	gchar *fullpath;
+	gchar *dirname;
+	
+	tab = gtranslator_window_get_active_tab (plugin->priv->window);
+
+	if (!tab)
+		return;
+	po = gtranslator_tab_get_po (tab);
+
+	po_path = gtranslator_po_get_filename (po);
+	dirname = g_path_get_dirname (po_path);
+	
+	tags = gtk_text_iter_get_tags (iter);
+	for (tagp = tags;  tagp != NULL;  tagp = tagp->next)
+	{
+		GtkTextTag *tag = tagp->data;
+		gchar *path = g_object_get_data (G_OBJECT (tag), "path");
+		gint line = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tag), "line"));
+
+		fullpath = g_build_filename (dirname, path, NULL);
+		show_source (plugin, fullpath, line);
+		
+		g_free (fullpath);
+	}
+
+	if (tags)
+		g_slist_free (tags);
+	
+	g_free (dirname);
+}
+
+static gboolean
+event_after (GtkWidget *text_view,
+	     GdkEvent  *ev,
+	     GtranslatorSourceViewPlugin *plugin)
+{
+	GtkTextIter start, end, iter;
+	GtkTextBuffer *buffer;
+	GdkEventButton *event;
+	gint x, y;
+
+	if (ev->type != GDK_BUTTON_RELEASE)
+		return FALSE;
+
+	event = (GdkEventButton *)ev;
+
+	if (event->button != 1)
+		return FALSE;
+
+	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
+
+	/* we shouldn't follow a link if the user has selected something */
+	gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
+	if (gtk_text_iter_get_offset (&start) != gtk_text_iter_get_offset (&end))
+		return FALSE;
+
+	gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view), 
+					       GTK_TEXT_WINDOW_WIDGET,
+					       event->x, event->y, &x, &y);
+	
+	gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (text_view), &iter, x, y);
+
+	follow_if_link (plugin, text_view, &iter);
+
+	return FALSE;
+}
+
+static gboolean hovering_over_link = FALSE;
+static GdkCursor *hand_cursor = NULL;
+static GdkCursor *regular_cursor = NULL;
+
+/* Looks at all tags covering the position (x, y) in the text view, 
+ * and if one of them is a link, change the cursor to the "hands" cursor
+ * typically used by web browsers.
+ */
+static void
+set_cursor_if_appropriate (GtkTextView    *text_view,
+                           gint            x,
+                           gint            y)
+{
+	GSList *tags = NULL, *tagp = NULL;
+	GtkTextIter iter;
+	gboolean hovering = FALSE;
+
+	gtk_text_view_get_iter_at_location (text_view, &iter, x, y);
+  
+	tags = gtk_text_iter_get_tags (&iter);
+	for (tagp = tags;  tagp != NULL;  tagp = tagp->next)
+	{
+		GtkTextTag *tag = tagp->data;
+		gchar *path = g_object_get_data (G_OBJECT (tag), "path");
+
+		if (path) 
+		{
+			hovering = TRUE;
+			break;
+		}
+	}
+
+	if (hovering != hovering_over_link)
+	{
+		hovering_over_link = hovering;
+
+		if (hovering_over_link)
+			gdk_window_set_cursor (gtk_text_view_get_window (text_view,
+									 GTK_TEXT_WINDOW_TEXT),
+					       hand_cursor);
+		else
+			gdk_window_set_cursor (gtk_text_view_get_window (text_view,
+									 GTK_TEXT_WINDOW_TEXT),
+					       regular_cursor);
+	}
+	
+	if (tags) 
+		g_slist_free (tags);
+}
+
+/*
+ * Update the cursor image if the pointer moved. 
+ */
+static gboolean
+motion_notify_event (GtkWidget      *text_view,
+		     GdkEventMotion *event)
+{
+	gint x, y;
+
+	gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view), 
+					       GTK_TEXT_WINDOW_WIDGET,
+					       event->x, event->y, &x, &y);
+
+	set_cursor_if_appropriate (GTK_TEXT_VIEW (text_view), x, y);
+
+	gdk_window_get_pointer (text_view->window, NULL, NULL, NULL);
+	return FALSE;
+}
+
+/* Also update the cursor image if the window becomes visible
+ * (e.g. when a window covering it got iconified).
+ */
+static gboolean
+visibility_notify_event (GtkWidget          *text_view,
+			 GdkEventVisibility *event)
+{
+	gint wx, wy, bx, by;
+  
+	gdk_window_get_pointer (text_view->window, &wx, &wy, NULL);
+  
+	gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view), 
+					       GTK_TEXT_WINDOW_WIDGET,
+					       wx, wy, &bx, &by);
+
+	set_cursor_if_appropriate (GTK_TEXT_VIEW (text_view), bx, by);
+
+	return FALSE;
+}
+
+static void
+gtranslator_source_view_plugin_init (GtranslatorSourceViewPlugin *plugin)
+{
+	plugin->priv = GTR_SOURCE_VIEW_PLUGIN_GET_PRIVATE (plugin);
+
+	plugin->priv->gconf_client = gconf_client_get_default ();
+
+	gconf_client_add_dir (plugin->priv->gconf_client,
+			      SOURCE_VIEW_BASE_KEY,
+			      GCONF_CLIENT_PRELOAD_ONELEVEL,
+			      NULL);
+}
+
+static void
+gtranslator_source_view_plugin_finalize (GObject *object)
+{
+	GtranslatorSourceViewPlugin *plugin = GTR_SOURCE_VIEW_PLUGIN (object);
+	
+	gconf_client_suggest_sync (plugin->priv->gconf_client, NULL);
+
+	g_object_unref (G_OBJECT (plugin->priv->gconf_client));
+	
+	G_OBJECT_CLASS (gtranslator_source_view_plugin_parent_class)->finalize (object);
+}
+
+static void
+showed_message_cb (GtranslatorTab *tab,
+		   GtranslatorMsg *msg,
+		   GtranslatorSourceViewPlugin *plugin)
+{
+	const gchar *filename = NULL;
+	gint i = 0;
+	gint *line = NULL;
+	GtkTextIter iter;
+	GtkTextBuffer *buffer;
+	GtkTextView *view;
+	GtranslatorCommentPanel *panel;
+
+	panel = gtranslator_tab_get_comment_panel (tab);
+	view = gtranslator_comment_panel_get_extracted_text_view (panel);
+	
+	buffer = gtk_text_view_get_buffer (view);
+	
+	gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
+	
+	gtk_text_buffer_insert (buffer, &iter, _("Paths:\n"), -1);
+	
+	filename = gtranslator_msg_get_filename (msg, i);
+	while (filename)
+	{
+		line = gtranslator_msg_get_file_line (msg, i);
+		insert_link (buffer, &iter, filename, line);
+		i++;
+		filename = gtranslator_msg_get_filename (msg, i);
+	}
+
+	plugin->priv->inserted_lines = i;
+}
+
+static void
+message_edition_finished_cb (GtranslatorTab *tab,
+			     GtranslatorMsg *msg,
+			     GtranslatorSourceViewPlugin *plugin)
+{
+	GSList *tags = NULL, *tagp = NULL;
+	GtkTextIter iter;
+	GtkTextBuffer *buffer;
+	gint i = 0;
+	GtranslatorCommentPanel *panel;
+	GtkTextView *view;
+
+	panel = gtranslator_tab_get_comment_panel (tab);
+	view = gtranslator_comment_panel_get_extracted_text_view (panel);
+
+	buffer = gtk_text_view_get_buffer (view);
+	
+	gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
+
+	while (i < plugin->priv->inserted_lines)
+	{	
+		/*
+		 * Let's free the path
+		 */
+		tags = gtk_text_iter_get_tags (&iter);
+		for (tagp = tags;  tagp != NULL;  tagp = tagp->next)
+		{
+			GtkTextTag *tag = tagp->data;
+			gchar *path = g_object_get_data (G_OBJECT (tag), "path");
+
+			if (path) 
+			{
+				g_free (path);
+			}
+		}
+		g_slist_free (tags);
+		gtk_text_iter_forward_line (&iter);
+		i++;
+	}
+}
+
+static void
+page_added_cb (GtkNotebook *notebook,
+	       GtkWidget *child,
+	       guint page_num,
+	       GtranslatorSourceViewPlugin *plugin)
+{	
+	GtranslatorCommentPanel *panel;
+	GtkTextView *view;
+
+	panel = gtranslator_tab_get_comment_panel (GTR_TAB (child));
+	view = gtranslator_comment_panel_get_extracted_text_view (panel);
+
+	g_signal_connect_after (child, "showed-message",
+				G_CALLBACK (showed_message_cb), plugin);
+	/*g_signal_connect (child, "message-edition-finished,
+			  G_CALLBACK (message_edition_finished_cb), plugin);*/
+	
+	g_signal_connect (view, "event-after", 
+			  G_CALLBACK (event_after), plugin);
+	g_signal_connect (view, "motion-notify-event", 
+			  G_CALLBACK (motion_notify_event), NULL);
+	g_signal_connect (view, "visibility-notify-event", 
+			  G_CALLBACK (visibility_notify_event), NULL);
+}
+
+static void
+use_editor_toggled (GtkToggleButton *button,
+		    GtranslatorSourceViewPlugin *plugin)
+{
+	gtk_widget_set_sensitive (plugin->priv->program_box,
+				  gtk_toggle_button_get_active (button));
+}
+
+static GtkWidget *
+get_configuration_dialog (GtranslatorSourceViewPlugin *plugin)
+{
+
+	gboolean ret;
+	GtkWidget *error_widget;
+	gchar *value;
+	gboolean use_editor;
+	
+	ret = gtranslator_utils_get_glade_widgets (GLADE_FILE,
+						  "dialog",
+						  &error_widget,
+						  "dialog", &plugin->priv->dialog,
+						  "main_box", &plugin->priv->main_box,
+						  "use_editor", &plugin->priv->use_editor_checkbutton,
+						  "program_box", &plugin->priv->program_box,
+						  "program_cmd", &plugin->priv->program_cmd_entry,
+						  "line_cmd", &plugin->priv->line_cmd_entry,
+						  NULL);
+
+	if(!ret)
+	{
+		//FIXME: We have to show a dialog
+	}
+
+	/* Set default values */
+	
+	//Use editor
+	use_editor = gconf_client_get_bool (plugin->priv->gconf_client,
+					    USE_EDITOR_KEY,
+					    NULL);
+	
+	g_signal_connect (plugin->priv->use_editor_checkbutton, "toggled",
+			  G_CALLBACK (use_editor_toggled), plugin);
+	
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (plugin->priv->use_editor_checkbutton),
+				      use_editor);
+	
+	use_editor_toggled (GTK_TOGGLE_BUTTON (plugin->priv->use_editor_checkbutton),
+			    plugin);
+	
+	//Program cmd
+	value = gconf_client_get_string (plugin->priv->gconf_client,
+					 PROGRAM_CMD_KEY,
+					 NULL);
+
+	gtk_entry_set_text (GTK_ENTRY (plugin->priv->program_cmd_entry),
+			    value);
+	
+	g_free (value);
+	
+	//Line cmd
+	value = gconf_client_get_string (plugin->priv->gconf_client,
+					 LINE_CMD_KEY,
+					 NULL);
+	
+	gtk_entry_set_text (GTK_ENTRY (plugin->priv->line_cmd_entry),
+			    value);
+
+	g_free (value);
+	
+	return plugin->priv->dialog;
+}
+
+static void
+impl_activate (GtranslatorPlugin *plugin,
+	       GtranslatorWindow *window)
+{	
+	GtkWidget *notebook;
+	GtranslatorSourceViewPlugin *source_view = GTR_SOURCE_VIEW_PLUGIN (plugin);
+	GList *tabs, *l;
+
+	/*
+	 * Cursors
+	 */
+	hand_cursor = gdk_cursor_new (GDK_HAND2);
+	regular_cursor = gdk_cursor_new (GDK_XTERM);
+	
+	notebook = GTK_WIDGET (gtranslator_window_get_notebook (window));
+	
+	source_view->priv->window = window;
+	
+	g_signal_connect (notebook, "page-added",
+			  G_CALLBACK (page_added_cb), plugin);
+
+	/*
+	 * If we already have tabs opened we have to add them
+	 */
+	tabs = gtranslator_window_get_all_tabs (window);
+	for (l = tabs; l != NULL; l = g_list_next (l))
+	{
+		page_added_cb (GTK_NOTEBOOK (notebook),
+			       l->data, 0, GTR_SOURCE_VIEW_PLUGIN (plugin));
+	}
+}
+
+static void
+impl_deactivate(GtranslatorPlugin *plugin,
+	        GtranslatorWindow *window)
+{
+	GList *tabs, *l;
+	GtkTextView *view;
+	GtranslatorCommentPanel *panel;
+	GtkWidget *notebook;
+	
+	tabs = gtranslator_window_get_all_tabs (window);
+	notebook = GTK_WIDGET (gtranslator_window_get_notebook (window));
+	
+	for (l = tabs; l != NULL; l = g_list_next (l))
+	{
+		panel = gtranslator_tab_get_comment_panel (GTR_TAB (l->data));
+		view = gtranslator_comment_panel_get_extracted_text_view (panel);
+		
+		g_signal_handlers_disconnect_by_func (l->data,
+						      showed_message_cb,
+						      plugin);
+
+		g_signal_handlers_disconnect_by_func (view,
+						      event_after,
+						      window);
+		g_signal_handlers_disconnect_by_func (view,
+						      motion_notify_event,
+						      NULL);
+		g_signal_handlers_disconnect_by_func (view,
+						      visibility_notify_event,
+						      NULL);
+	}
+	
+	g_signal_handlers_disconnect_by_func (notebook, 
+					      page_added_cb,
+					      plugin);
+}
+
+static void
+ok_button_pressed (GtranslatorSourceViewPlugin *plugin)
+{
+	const gchar *program_cmd;
+	const gchar *line_cmd;
+	gboolean use_editor;
+	
+	/* We have to get the text from the entries */
+	use_editor = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (plugin->priv->use_editor_checkbutton));
+	program_cmd = gtk_entry_get_text (GTK_ENTRY (plugin->priv->program_cmd_entry));
+	line_cmd = gtk_entry_get_text (GTK_ENTRY (plugin->priv->line_cmd_entry));
+	
+	/* Now we store the data in gconf */
+	if (!gconf_client_key_is_writable (plugin->priv->gconf_client,
+					   USE_EDITOR_KEY,
+					   NULL))
+		return;
+
+	gconf_client_set_bool (plugin->priv->gconf_client,
+			       USE_EDITOR_KEY,
+			       use_editor,
+			       NULL);
+	
+	if (!gconf_client_key_is_writable (plugin->priv->gconf_client,
+					   PROGRAM_CMD_KEY,
+					   NULL))
+		return;
+
+	gconf_client_set_string (plugin->priv->gconf_client,
+				 PROGRAM_CMD_KEY,
+		       		 program_cmd,
+		       		 NULL);
+	
+	if (!gconf_client_key_is_writable (plugin->priv->gconf_client,
+					   LINE_CMD_KEY,
+					   NULL))
+		return;
+
+	gconf_client_set_string (plugin->priv->gconf_client,
+				 LINE_CMD_KEY,
+		       		 line_cmd,
+		       		 NULL);
+}
+
+static void
+configure_dialog_response_cb (GtkWidget           *widget,
+			      gint                 response,
+			      GtranslatorSourceViewPlugin *plugin)
+{
+	switch (response)
+	{
+		case GTK_RESPONSE_OK:
+		{
+			ok_button_pressed (plugin);
+
+			gtk_widget_destroy (plugin->priv->dialog);
+			break;
+		}
+		case GTK_RESPONSE_CANCEL:
+		{
+			gtk_widget_destroy (plugin->priv->dialog);
+		}
+	}
+}
+
+static GtkWidget *
+impl_create_configure_dialog (GtranslatorPlugin *plugin)
+{
+	GtkWidget *dialog;
+	
+	dialog = get_configuration_dialog (GTR_SOURCE_VIEW_PLUGIN (plugin));
+	
+	g_signal_connect (dialog,
+			  "response",
+			  G_CALLBACK (configure_dialog_response_cb),
+			  GTR_SOURCE_VIEW_PLUGIN (plugin));
+	g_signal_connect (dialog,
+			  "destroy",
+			  G_CALLBACK (gtk_widget_destroy),
+			  &dialog);
+	
+	return dialog;
+}
+
+static void
+gtranslator_source_view_plugin_class_init (GtranslatorSourceViewPluginClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	GtranslatorPluginClass *plugin_class = GTR_PLUGIN_CLASS (klass);
+
+	object_class->finalize = gtranslator_source_view_plugin_finalize;
+
+	plugin_class->activate = impl_activate;
+	plugin_class->deactivate = impl_deactivate;
+	plugin_class->create_configure_dialog = impl_create_configure_dialog;
+	
+	g_type_class_add_private (object_class, sizeof (GtranslatorSourceViewPluginPrivate));
+}

Added: trunk/plugins/source-view/source-view-plugin.h
==============================================================================
--- (empty file)
+++ trunk/plugins/source-view/source-view-plugin.h	Mon Sep 22 09:38:11 2008
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008  Ignacio Casal Quinteiro <nacho resa gmail com>
+ * 
+ *     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 3 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
+ *     MERCHANPOILITY 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __GTR_SOURCE_VIEW_PLUGIN_H__
+#define __GTR_SOURCE_VIEW_PLUGIN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "plugin.h"
+
+G_BEGIN_DECLS
+
+/*
+ * Type checking and casting macros
+ */
+#define GTR_TYPE_SOURCE_VIEW_PLUGIN		(gtranslator_source_view_plugin_get_type ())
+#define GTR_SOURCE_VIEW_PLUGIN(o)			(G_TYPE_CHECK_INSTANCE_CAST ((o), GTR_TYPE_SOURCE_VIEW_PLUGIN, GtranslatorSourceViewPlugin))
+#define GTR_SOURCE_VIEW_PLUGIN_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), GTR_TYPE_SOURCE_VIEW_PLUGIN, GtranslatorSourceViewPluginClass))
+#define GTR_IS_SOURCE_VIEW_PLUGIN(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), GTR_TYPE_SOURCE_VIEW_PLUGIN))
+#define GTR_IS_SOURCE_VIEW_PLUGIN_CLASS(k)		(G_TYPE_CHECK_CLASS_TYPE ((k), GTR_TYPE_SOURCE_VIEW_PLUGIN))
+#define GTR_SOURCE_VIEW_PLUGIN_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), GTR_TYPE_SOURCE_VIEW_PLUGIN_PLUGIN, GtranslatorSourceViewPluginClass))
+
+/* Private structure type */
+typedef struct _GtranslatorSourceViewPluginPrivate	GtranslatorSourceViewPluginPrivate;
+
+/*
+ * Main object structure
+ */
+typedef struct _GtranslatorSourceViewPlugin		GtranslatorSourceViewPlugin;
+
+struct _GtranslatorSourceViewPlugin
+{
+	GtranslatorPlugin parent_instance;
+	
+	/* private */
+	GtranslatorSourceViewPluginPrivate *priv;
+};
+
+/*
+ * Class definition
+ */
+typedef struct _GtranslatorSourceViewPluginClass	GtranslatorSourceViewPluginClass;
+
+struct _GtranslatorSourceViewPluginClass
+{
+	GtranslatorPluginClass parent_class;
+};
+
+/*
+ * Public methods
+ */
+GType	gtranslator_source_view_plugin_get_type	(void) G_GNUC_CONST;
+
+/* All the plugins must implement this function */
+G_MODULE_EXPORT GType register_gtranslator_plugin (GTypeModule *module);
+
+G_END_DECLS
+
+#endif /* __GTR_SOURCE_VIEW_PLUGIN_H__ */

Added: trunk/plugins/source-view/source-view.gtranslator-plugin.desktop.in
==============================================================================
--- (empty file)
+++ trunk/plugins/source-view/source-view.gtranslator-plugin.desktop.in	Mon Sep 22 09:38:11 2008
@@ -0,0 +1,8 @@
+[Gtranslator Plugin]
+Module=sourceview
+IAge=2
+_Name=Source View
+_Description=Show the message in the source code.
+Authors=Ignacio Casal Quinteiro  <nacho resa gmail com>
+Copyright=Copyright @ 2008 Ignacio Casal Quinteiro
+Website=http://gtranslator.sf.net

Added: trunk/plugins/source-view/viewer.c
==============================================================================
--- (empty file)
+++ trunk/plugins/source-view/viewer.c	Mon Sep 22 09:38:11 2008
@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2008  Ignacio Casal Quinteiro <nacho resa gmail com>
+ * 
+ *     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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "utils.h"
+#include "viewer.h"
+#include "window.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+#include <string.h>
+#include <gtksourceview/gtksourcelanguagemanager.h>
+
+#define GTR_VIEWER_GET_PRIVATE(object)	(G_TYPE_INSTANCE_GET_PRIVATE ( \
+						 	(object),	\
+						 	GTR_TYPE_VIEWER,     \
+						 	GtranslatorViewerPrivate))
+
+
+G_DEFINE_TYPE(GtranslatorViewer, gtranslator_viewer, GTK_TYPE_DIALOG)
+
+struct _GtranslatorViewerPrivate
+{
+	GtkWidget *main_box;
+	GtkWidget *view;
+};		    
+
+static void
+dialog_response_handler (GtkDialog *dlg, 
+			 gint       res_id)
+{
+	switch (res_id)
+	{
+		default:
+			gtk_widget_destroy (GTK_WIDGET(dlg));
+	}
+}
+
+static void
+gtranslator_viewer_init (GtranslatorViewer *dlg)
+{
+	gboolean ret;
+	GtkWidget *error_widget;
+	GtkWidget *sw;
+	
+	dlg->priv = GTR_VIEWER_GET_PRIVATE (dlg);
+	
+	gtk_dialog_add_buttons (GTK_DIALOG (dlg),
+				GTK_STOCK_CLOSE,
+				GTK_RESPONSE_CLOSE,
+				NULL);
+	
+	gtk_window_set_title (GTK_WINDOW (dlg), _("Source Viewer"));
+	gtk_window_set_default_size(GTK_WINDOW(dlg), 800, 600);
+	gtk_window_set_resizable (GTK_WINDOW (dlg), TRUE);
+	gtk_dialog_set_has_separator (GTK_DIALOG (dlg), FALSE);
+	gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg), TRUE);
+	
+	/* HIG defaults */
+	gtk_container_set_border_width (GTK_CONTAINER (dlg), 5);
+	gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dlg)->vbox), 2); /* 2 * 5 + 2 = 12 */
+	gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dlg)->action_area), 5);
+	gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dlg)->action_area), 4);
+	
+	g_signal_connect (dlg,
+			  "response",
+			  G_CALLBACK (dialog_response_handler),
+			  NULL);
+	
+	/*Glade*/
+	ret = gtranslator_utils_get_glade_widgets(DATADIR "/viewer.glade",
+		"main_box",
+		&error_widget,
+		
+		"main_box", &dlg->priv->main_box,
+		"scrolledwindow", &sw,
+		NULL);
+	
+	if(!ret)
+	{
+		gtk_widget_show(error_widget);
+		gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG (dlg)->vbox),
+					     error_widget);
+		
+		return;
+	}
+	
+	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox),
+			    dlg->priv->main_box, TRUE, TRUE, 0);
+	
+	gtk_container_set_border_width (GTK_CONTAINER (dlg->priv->main_box), 5);
+	
+	/* Source view */
+	dlg->priv->view = gtk_source_view_new ();
+	gtk_text_view_set_editable (GTK_TEXT_VIEW (dlg->priv->view), FALSE);
+	gtk_widget_show (dlg->priv->view);
+	gtk_container_add (GTK_CONTAINER (sw), dlg->priv->view);
+	
+	gtk_source_view_set_highlight_current_line (GTK_SOURCE_VIEW (dlg->priv->view),
+						    TRUE);
+	
+	gtk_source_view_set_show_line_numbers (GTK_SOURCE_VIEW (dlg->priv->view),
+					       TRUE);
+	
+	gtk_source_view_set_show_right_margin (GTK_SOURCE_VIEW (dlg->priv->view),
+					       TRUE);
+}
+
+static void
+gtranslator_viewer_finalize (GObject *object)
+{
+	G_OBJECT_CLASS (gtranslator_viewer_parent_class)->finalize (object);
+}
+
+static void
+gtranslator_viewer_class_init (GtranslatorViewerClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (GtranslatorViewerPrivate));
+
+	object_class->finalize = gtranslator_viewer_finalize;
+}
+
+/***************** File loading *****************/
+
+static void
+error_dialog (GtkWindow *parent, const gchar *msg, ...)
+{
+	va_list ap;
+	gchar *tmp;
+	GtkWidget *dialog;
+
+	va_start (ap, msg);
+	tmp = g_strdup_vprintf (msg, ap);
+	va_end (ap);
+
+	dialog = gtk_message_dialog_new (parent,
+					 GTK_DIALOG_DESTROY_WITH_PARENT,
+					 GTK_MESSAGE_ERROR,
+					 GTK_BUTTONS_OK,
+					 tmp);
+	g_free (tmp);
+
+	gtk_dialog_run (GTK_DIALOG (dialog));
+	gtk_widget_destroy (dialog);
+}
+
+static gboolean
+gtk_source_buffer_load_file (GtkSourceBuffer *source_buffer,
+			     const gchar     *filename,
+			     GError         **error)
+{
+	GtkTextIter iter;
+	gchar *buffer;
+	GError *error_here = NULL;
+
+	g_return_val_if_fail (GTK_IS_SOURCE_BUFFER (source_buffer), FALSE);
+	g_return_val_if_fail (filename != NULL, FALSE);
+
+	if (!g_file_get_contents (filename, &buffer, NULL, &error_here))
+	{
+		error_dialog (NULL, "%s\nFile %s", error_here->message, filename);
+		g_propagate_error (error, error_here);
+		return FALSE;
+	}
+
+	gtk_source_buffer_begin_not_undoable_action (source_buffer);
+	gtk_text_buffer_set_text (GTK_TEXT_BUFFER (source_buffer), buffer, -1);
+	gtk_source_buffer_end_not_undoable_action (source_buffer);
+	gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (source_buffer), FALSE);
+
+	/* move cursor to the beginning */
+	gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (source_buffer), &iter);
+	gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (source_buffer), &iter);
+
+	{
+		GtkTextIter start, end;
+		char *text;
+		gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (source_buffer), &start, &end);
+		text = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (source_buffer), &start, &end, TRUE);
+		g_assert (!strcmp (text, buffer));
+		g_free (text);
+	}
+
+	g_free (buffer);
+	return TRUE;
+}
+
+static void
+remove_all_marks (GtkSourceBuffer *buffer)
+{
+	GtkTextIter s, e;
+
+	gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (buffer), &s, &e);
+
+	gtk_source_buffer_remove_source_marks (buffer, &s, &e, NULL);
+}
+
+/* Note this is wrong for several reasons, e.g. g_pattern_match is broken
+ * for glob matching. */
+static GtkSourceLanguage *
+get_language_for_filename (const gchar *filename)
+{
+	const gchar * const *languages;
+	gchar *filename_utf8;
+	GtkSourceLanguageManager *manager;
+
+	filename_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
+	g_return_val_if_fail (filename_utf8 != NULL, NULL);
+
+	manager = gtk_source_language_manager_get_default ();
+	languages = gtk_source_language_manager_get_language_ids (manager);
+
+	while (*languages != NULL)
+	{
+		GtkSourceLanguage *lang;
+		gchar **globs, **p;
+
+		lang = gtk_source_language_manager_get_language (manager,
+								 *languages);
+		g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE (lang), NULL);
+		++languages;
+
+		globs = gtk_source_language_get_globs (lang);
+		if (globs == NULL)
+			continue;
+
+		for (p = globs; *p != NULL; p++)
+		{
+			if (g_pattern_match_simple (*p, filename_utf8))
+			{
+				g_strfreev (globs);
+				g_free (filename_utf8);
+
+				return lang;
+			}
+		}
+
+		g_strfreev (globs);
+	}
+
+	g_free (filename_utf8);
+	return NULL;
+}
+
+static GtkSourceLanguage *
+get_language_for_file (const gchar *filename)
+{
+	GtkSourceLanguage *language = NULL;
+
+	if (!language)
+		language = get_language_for_filename (filename);
+
+	return language;
+}
+
+static GtkSourceLanguage *
+get_language_by_id (const gchar *id)
+{
+	GtkSourceLanguageManager *manager;
+	manager = gtk_source_language_manager_get_default ();
+	return gtk_source_language_manager_get_language (manager, id);
+}
+
+static GtkSourceLanguage *
+get_language (GtkTextBuffer *buffer, const gchar *filename)
+{
+	GtkSourceLanguage *language = NULL;
+	GtkTextIter start, end;
+	gchar *text;
+	gchar *lang_string;
+
+	gtk_text_buffer_get_start_iter (buffer, &start);
+	end = start;
+	gtk_text_iter_forward_line (&end);
+
+#define LANG_STRING "gtk-source-lang:"
+	text = gtk_text_iter_get_slice (&start, &end);
+	lang_string = strstr (text, LANG_STRING);
+	if (lang_string != NULL)
+	{
+		gchar **tokens;
+
+		lang_string += strlen (LANG_STRING);
+		g_strchug (lang_string);
+
+		tokens = g_strsplit_set (lang_string, " \t\n", 2);
+
+		if (tokens != NULL && tokens[0] != NULL)
+			language = get_language_by_id (tokens[0]);
+
+		g_strfreev (tokens);
+	}
+
+	if (!language)
+		language = get_language_for_file (filename);
+
+	g_free (text);
+	return language;
+}
+
+static gboolean
+open_file (GtkSourceBuffer *buffer, const gchar *filename)
+{
+	GtkSourceLanguage *language = NULL;
+	gchar *freeme = NULL;
+	gboolean success = FALSE;
+	GFile *file;
+	gchar *path;
+	
+	file = g_file_new_for_path (filename);
+	path = g_file_get_path (file);
+	g_object_unref (file);
+	
+	remove_all_marks (buffer);
+
+	success = gtk_source_buffer_load_file (buffer, path, NULL);
+
+	if (!success)
+		goto out;
+
+	language = get_language (GTK_TEXT_BUFFER (buffer), filename);
+
+	if (language == NULL)
+		g_print ("No language found for file `%s'\n", filename);
+
+	gtk_source_buffer_set_language (buffer, language);
+	g_object_set_data_full (G_OBJECT (buffer),
+				"filename", g_strdup (filename),
+				(GDestroyNotify) g_free);
+
+	if (language != NULL)
+	{
+		gchar **styles;
+
+		styles = gtk_source_language_get_style_ids (language);
+
+		if (styles == NULL)
+			g_print ("No styles in language '%s'\n", gtk_source_language_get_name (language));
+		else
+		{
+			gchar **ids;
+			g_print ("Styles in in language '%s':\n", gtk_source_language_get_name (language));
+
+			ids = styles;
+
+			while (*ids != NULL)
+			{
+				const gchar *name;
+
+				name = gtk_source_language_get_style_name (language, *ids);
+
+				g_print ("- %s (name: '%s')\n", *ids, name);
+
+				++ids;
+			}
+
+			g_strfreev (styles);
+		}
+
+		g_print("\n");
+	}
+out:
+	g_free (freeme);
+	return success;
+}
+
+static void
+jump_to_line (GtkTextView *view,
+	      gint line)
+{
+	GtkTextBuffer *buffer;
+	GtkTextIter iter;
+	gint line_count;
+	
+	buffer = gtk_text_view_get_buffer (view);
+	
+	line_count = gtk_text_buffer_get_line_count (buffer);
+
+	if (line >= line_count)
+		gtk_text_buffer_get_end_iter (buffer,
+					      &iter);
+	else
+		gtk_text_buffer_get_iter_at_line (buffer,
+						  &iter,
+						  line-1);
+
+	gtk_text_buffer_place_cursor (buffer, &iter);
+	
+	gtk_text_view_scroll_to_mark (view,
+				      gtk_text_buffer_get_insert (buffer),
+				      0.25,
+				      FALSE,
+				      0.0,
+				      0.0);
+}
+
+void
+gtranslator_show_viewer (GtranslatorWindow *window,
+			 const gchar *path,
+			 gint line)
+{
+	static GtranslatorViewer *dlg = NULL;
+	
+	g_return_if_fail (GTR_IS_WINDOW (window));
+	
+	if (dlg == NULL)
+	{
+		GtkSourceBuffer *buffer;
+		
+		dlg = g_object_new (GTR_TYPE_VIEWER, NULL);
+
+		buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (dlg->priv->view)));
+		
+		open_file (buffer, path);
+		jump_to_line (GTK_TEXT_VIEW (dlg->priv->view), line);
+		
+		g_signal_connect (dlg,
+				  "destroy",
+				  G_CALLBACK (gtk_widget_destroyed),
+				  &dlg);
+		gtk_widget_show (GTK_WIDGET (dlg));
+	}
+	
+	if (GTK_WINDOW (window) != gtk_window_get_transient_for (GTK_WINDOW (dlg)))
+	{
+		gtk_window_set_transient_for (GTK_WINDOW (dlg),
+					      GTK_WINDOW (window));
+	}
+
+	gtk_window_present (GTK_WINDOW (dlg));
+}

Added: trunk/plugins/source-view/viewer.glade
==============================================================================
--- (empty file)
+++ trunk/plugins/source-view/viewer.glade	Mon Sep 22 09:38:11 2008
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--Generated with glade3 3.4.5 on Fri Jun 27 10:41:35 2008 -->
+<glade-interface>
+  <widget class="GtkDialog" id="dialog1">
+    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+    <property name="border_width">5</property>
+    <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
+    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+    <property name="has_separator">False</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox1">
+        <property name="visible">True</property>
+        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+        <property name="spacing">2</property>
+        <child>
+          <widget class="GtkVBox" id="main_box">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="spacing">6</property>
+            <child>
+              <widget class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">&lt;b&gt;Source code&lt;/b&gt;</property>
+                <property name="use_markup">True</property>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkScrolledWindow" id="scrolledwindow">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                <property name="shadow_type">GTK_SHADOW_IN</property>
+                <child>
+                  <placeholder/>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area1">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="layout_style">GTK_BUTTONBOX_END</property>
+            <child>
+              <widget class="GtkButton" id="button1">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="label" translatable="yes">gtk-close</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">0</property>
+              </widget>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">GTK_PACK_END</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+</glade-interface>

Added: trunk/plugins/source-view/viewer.h
==============================================================================
--- (empty file)
+++ trunk/plugins/source-view/viewer.h	Mon Sep 22 09:38:11 2008
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2008  Ignacio Casal Quinteiro <nacho resa gmail com>
+ * 
+ *     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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __VIEWER_H__
+#define __VIEWER_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include "window.h"
+#include "msg.h"
+
+G_BEGIN_DECLS
+
+/*
+ * Type checking and casting macros
+ */
+#define GTR_TYPE_VIEWER		(gtranslator_viewer_get_type ())
+#define GTR_VIEWER(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), GTR_TYPE_VIEWER, GtranslatorViewer))
+#define GTR_VIEWER_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), GTR_TYPE_VIEWER, GtranslatorViewerClass))
+#define GTR_IS_VIEWER(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), GTR_TYPE_VIEWER))
+#define GTR_IS_VIEWER_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), GTR_TYPE_VIEWER))
+#define GTR_VIEWER_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), GTR_TYPE_VIEWER, GtranslatorViewerClass))
+
+/* Private structure type */
+typedef struct _GtranslatorViewerPrivate	GtranslatorViewerPrivate;
+
+/*
+ * Main object structure
+ */
+typedef struct _GtranslatorViewer		GtranslatorViewer;
+
+struct _GtranslatorViewer
+{
+	GtkDialog parent_instance;
+	
+	/*< private > */
+	GtranslatorViewerPrivate *priv;
+};
+
+/*
+ * Class definition
+ */
+typedef struct _GtranslatorViewerClass	GtranslatorViewerClass;
+
+struct _GtranslatorViewerClass
+{
+	GtkDialogClass parent_class;
+};
+
+/*
+ * Public methods
+ */
+GType		 gtranslator_viewer_get_type               (void) G_GNUC_CONST;
+
+GType		 gtranslator_viewer_register_type          (GTypeModule * module);
+
+void	         gtranslator_show_viewer                   (GtranslatorWindow *window,
+							    const gchar *path,
+							    gint line);
+
+G_END_DECLS
+
+#endif /* __VIEWER_H__ */

Modified: trunk/src/comment.c
==============================================================================
--- trunk/src/comment.c	(original)
+++ trunk/src/comment.c	Mon Sep 22 09:38:11 2008
@@ -26,7 +26,6 @@
 #include <glib/gi18n.h>
 #include <glib-object.h>
 #include <gtk/gtk.h>
-#include <gio/gio.h>
 
 #define GTR_COMMENT_PANEL_GET_PRIVATE(object)	(G_TYPE_INSTANCE_GET_PRIVATE ( \
 						 (object),		       \
@@ -44,210 +43,6 @@
 	GtranslatorTab *tab;
 };
 
-static void 
-insert_link (GtkTextBuffer *buffer, 
-	     GtkTextIter *iter,
-	     const gchar *path,
-	     gint *line)
-{
-	GtkTextTag *tag;
-	gchar *text;
-	GFile  *file;
-	gchar *uri;
-
-	file = g_file_new_for_commandline_arg (path);
-	uri = g_file_get_uri (file);
-	g_object_unref (file);
-
-	tag = gtk_text_buffer_create_tag (buffer, NULL, 
-					  "foreground", "blue", 
-					  "underline", PANGO_UNDERLINE_SINGLE, 
-					  NULL);
-	g_object_set_data (G_OBJECT (tag), "path", uri);
-	g_object_set_data (G_OBJECT (tag), "line", line);
-
-	text = g_strconcat (path, "\n", NULL);
-	gtk_text_buffer_insert_with_tags (buffer, iter, text, -1, tag, NULL);
-	g_free (text);
-}
-
-static void
-show_in_editor (const gchar *path,
-		gint line)
-{
-	gchar *open[4];
-
-	if (g_find_program_in_path ("gedit"))
-	{
-		open[0] = "gedit";
-	}
-	else
-	{
-		GtkWidget *dialog;
-		
-		dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL,
-						 GTK_DIALOG_MODAL,
-						 GTK_BUTTONS_CLOSE,
-						 _("Please, install gedit to be able to show the file"));
-		gtk_dialog_run (GTK_DIALOG (dialog));
-		gtk_widget_destroy (dialog);
-	}
-	
-	open[1] = g_strdup (path);
-	open[2] = g_strdup_printf ("+%d", line);
-	open[3] = NULL;
-					
-	gdk_spawn_on_screen (gdk_screen_get_default (),
-			     NULL,
-			     open,
-			     NULL,
-			     G_SPAWN_SEARCH_PATH,
-			     NULL,
-			     NULL, NULL, NULL);
-	g_free (open[1]);
-	g_free (open[2]);
-}
-
-static void
-follow_if_link (GtkWidget   *text_view, 
-		GtkTextIter *iter)
-{
-	GSList *tags = NULL, *tagp = NULL;
-
-	tags = gtk_text_iter_get_tags (iter);
-	for (tagp = tags;  tagp != NULL;  tagp = tagp->next)
-	{
-		GtkTextTag *tag = tagp->data;
-		gchar *path = g_object_get_data (G_OBJECT (tag), "path");
-		gint line = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tag), "line"));
-		
-		show_in_editor (path, line);
-	}
-
-	if (tags)
-		g_slist_free (tags);
-}
-
-static gboolean
-event_after (GtkWidget *text_view,
-	     GdkEvent  *ev)
-{
-	GtkTextIter start, end, iter;
-	GtkTextBuffer *buffer;
-	GdkEventButton *event;
-	gint x, y;
-
-	if (ev->type != GDK_BUTTON_RELEASE)
-		return FALSE;
-
-	event = (GdkEventButton *)ev;
-
-	if (event->button != 1)
-		return FALSE;
-
-	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
-
-	/* we shouldn't follow a link if the user has selected something */
-	gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
-	if (gtk_text_iter_get_offset (&start) != gtk_text_iter_get_offset (&end))
-		return FALSE;
-
-	gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view), 
-					       GTK_TEXT_WINDOW_WIDGET,
-					       event->x, event->y, &x, &y);
-	
-	gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (text_view), &iter, x, y);
-
-	follow_if_link (text_view, &iter);
-
-	return FALSE;
-}
-
-static gboolean hovering_over_link = FALSE;
-static GdkCursor *hand_cursor = NULL;
-static GdkCursor *regular_cursor = NULL;
-
-/* Looks at all tags covering the position (x, y) in the text view, 
- * and if one of them is a link, change the cursor to the "hands" cursor
- * typically used by web browsers.
- */
-static void
-set_cursor_if_appropriate (GtkTextView    *text_view,
-                           gint            x,
-                           gint            y)
-{
-	GSList *tags = NULL, *tagp = NULL;
-	GtkTextIter iter;
-	gboolean hovering = FALSE;
-
-	gtk_text_view_get_iter_at_location (text_view, &iter, x, y);
-  
-	tags = gtk_text_iter_get_tags (&iter);
-	for (tagp = tags;  tagp != NULL;  tagp = tagp->next)
-	{
-		GtkTextTag *tag = tagp->data;
-		gchar *path = g_object_get_data (G_OBJECT (tag), "path");
-
-		if (path) 
-		{
-			hovering = TRUE;
-			break;
-		}
-	}
-
-	if (hovering != hovering_over_link)
-	{
-		hovering_over_link = hovering;
-
-		if (hovering_over_link)
-			gdk_window_set_cursor (gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_TEXT), hand_cursor);
-		else
-			gdk_window_set_cursor (gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_TEXT), regular_cursor);
-	}
-	
-	if (tags) 
-		g_slist_free (tags);
-}
-
-/*
- * Update the cursor image if the pointer moved. 
- */
-static gboolean
-motion_notify_event (GtkWidget      *text_view,
-		     GdkEventMotion *event)
-{
-	gint x, y;
-
-	gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view), 
-					       GTK_TEXT_WINDOW_WIDGET,
-					       event->x, event->y, &x, &y);
-
-	set_cursor_if_appropriate (GTK_TEXT_VIEW (text_view), x, y);
-
-	gdk_window_get_pointer (text_view->window, NULL, NULL, NULL);
-	return FALSE;
-}
-
-/* Also update the cursor image if the window becomes visible
- * (e.g. when a window covering it got iconified).
- */
-static gboolean
-visibility_notify_event (GtkWidget          *text_view,
-			 GdkEventVisibility *event)
-{
-	gint wx, wy, bx, by;
-  
-	gdk_window_get_pointer (text_view->window, &wx, &wy, NULL);
-  
-	gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view), 
-					       GTK_TEXT_WINDOW_WIDGET,
-					       wx, wy, &bx, &by);
-
-	set_cursor_if_appropriate (GTK_TEXT_VIEW (text_view), bx, by);
-
-	return FALSE;
-}
-
 static void
 showed_message_cb (GtranslatorTab *tab,
 		   GtranslatorMsg *msg,
@@ -259,46 +54,14 @@
 	gchar *context;
 	gchar *format;
     	gchar *toset;
-	const gchar *filename = NULL;
-	gint i = 0;
-	gint *index = NULL;
-	gchar *path = NULL;
-	GSList *tags = NULL, *tagp = NULL;
 
 	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (panel->priv->extracted_comments));
 	gtk_text_buffer_set_text (buffer, "", 0);
 	gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
-	
-	/*
-	 * Let's free the path
-	 */
-	tags = gtk_text_iter_get_tags (&iter);
-	for (tagp = tags;  tagp != NULL;  tagp = tagp->next)
-	{
-		GtkTextTag *tag = tagp->data;
-		gchar *path = g_object_get_data (G_OBJECT (tag), "path");
-
-		if (path) 
-		{
-			g_free (path);
-		}
-	}
-	g_slist_free (tags);
-	
-	gtk_text_buffer_insert (buffer, &iter, _("Paths:\n"), -1);
-	
-	filename = gtranslator_msg_get_filename (msg, i);
-	while (filename)
-	{
-		index = gtranslator_msg_get_file_line (msg, i);
-		insert_link (buffer, &iter, filename, index);
-		i++;
-		filename = gtranslator_msg_get_filename (msg, i);
-	}
 
 	format = g_strconcat (_("Format: "), gtranslator_msg_get_format (msg), NULL);
-    	context = g_strconcat (_("Context:\n"), gtranslator_msg_get_msgctxt (msg), NULL);
-    	extracted = g_strconcat (_("Extracted comments:\n"),
+    	context = g_strconcat (_("Context:"), gtranslator_msg_get_msgctxt (msg), NULL);
+    	extracted = g_strconcat (_("Extracted comments:"),
 				 gtranslator_msg_get_extracted_comments(msg), NULL);
     
    	toset = g_strdup_printf("%s\n%s\n%s", format, context, extracted);
@@ -322,12 +85,6 @@
 	GtkWidget *comments_scrolled_window;
 	
 	/*
-	 * Cursors
-	 */
-	hand_cursor = gdk_cursor_new (GDK_HAND2);
-	regular_cursor = gdk_cursor_new (GDK_XTERM);
-	
-	/*
 	 * Set up the scrolling window for the extracted comments display
 	 */	
 	comments_scrolled_window = gtk_scrolled_window_new(NULL, NULL);
@@ -343,12 +100,6 @@
 	 * Extracted comments
 	 */	
 	priv->extracted_comments = gtk_text_view_new();
-	g_signal_connect (priv->extracted_comments, "event-after", 
-			  G_CALLBACK (event_after), NULL);
-	g_signal_connect (priv->extracted_comments, "motion-notify-event", 
-			  G_CALLBACK (motion_notify_event), NULL);
-	g_signal_connect (priv->extracted_comments, "visibility-notify-event", 
-			  G_CALLBACK (visibility_notify_event), NULL);
 	
 	gtk_text_view_set_editable(GTK_TEXT_VIEW(priv->extracted_comments), FALSE);
 	gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->extracted_comments),
@@ -430,3 +181,12 @@
 	
 	gtk_text_buffer_set_text(buf, comments, -1);
 }
+
+GtkTextView *
+gtranslator_comment_panel_get_extracted_text_view (GtranslatorCommentPanel *panel)
+{
+	g_return_if_fail (GTR_IS_COMMENT_PANEL (panel));
+	
+	return GTK_TEXT_VIEW (panel->priv->extracted_comments);
+}
+							    

Modified: trunk/src/comment.h
==============================================================================
--- trunk/src/comment.h	(original)
+++ trunk/src/comment.h	Mon Sep 22 09:38:11 2008
@@ -71,6 +71,8 @@
 
 void             gtranslator_comment_panel_set_comments    (GtranslatorCommentPanel *panel,
 							    const gchar *comments);
+							    
+GtkTextView     *gtranslator_comment_panel_get_extracted_text_view (GtranslatorCommentPanel *panel);
 
 G_END_DECLS
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]