[gnome-latex: 172/205] Log output: jump to lines and files



commit bb274b2df3e91d7cf7081fa5fab53ea0acfcbcad
Author: Sébastien Wilmet <sebastien wilmet gmail com>
Date:   Wed Jan 20 17:36:51 2010 +0100

    Log output: jump to lines and files
    
    We can now click on a message and go to the file and the line specified.
    Certain row can not be selected, only those with a real filename. If the
    line number is not specified, simply go to the file (but not change the
    cursor position).
    
    There are also some fixes for memory leaks, that's why a lot of files
    are modified ;)

 TODO                      |   2 +-
 src/callbacks.c           |  22 ++-----
 src/external_commands.c   |  17 ------
 src/file_browser.c        |   1 +
 src/latex_output_filter.c |  93 ++++++++++++++++--------------
 src/log.c                 | 142 ++++++++++++++++++++++++++++++++++++++++++----
 src/log.h                 |   4 +-
 src/main.c                | 110 ++++++++++++++++++++---------------
 src/prefs.c               |   8 ++-
 src/print.c               |   1 -
 src/templates.c           |   7 ++-
 src/ui.c                  |   2 +-
 src/utils.c               |  14 +++++
 src/utils.h               |   1 +
 14 files changed, 280 insertions(+), 144 deletions(-)
---
diff --git a/TODO b/TODO
index cb06795..2251e6f 100644
--- a/TODO
+++ b/TODO
@@ -8,7 +8,7 @@ TODO LaTeXila
        x extract informations: file, line, message
        x GtkTextBuffer -> GtkListStore
        x colors
-       - jump to lines and files
+       x jump to lines and files
        - buttons for going to the previous/next error/warning/badbox
 
 - Auto-completion of LaTeX commands
diff --git a/src/callbacks.c b/src/callbacks.c
index 61d01d2..c8e459a 100644
--- a/src/callbacks.c
+++ b/src/callbacks.c
@@ -38,6 +38,7 @@
 #include "prefs.h"
 #include "file_browser.h"
 #include "latex_output_filter.h"
+#include "utils.h"
 
 static void close_document (gint index);
 static void save_as_dialog (void);
@@ -46,7 +47,6 @@ static gboolean close_all (void);
 static void set_title (void);
 static void set_undo_redo_sensitivity (void);
 static void update_cursor_position_statusbar (void);
-static void scroll_to_cursor (void);
 static void find (gboolean backward);
 static gboolean find_next_match (const gchar *what, GtkSourceSearchFlags flags,
                gboolean backward, GtkTextIter *match_start, GtkTextIter *match_end);
@@ -1159,14 +1159,15 @@ open_new_document (const gchar *filename, const gchar *uri)
                // convert the text to UTF-8
                gchar *text_utf8 = g_locale_to_utf8 (contents, -1, NULL, NULL, NULL);
 
-               create_document_in_new_tab (filename, text_utf8,
-                               g_path_get_basename (filename));
+               gchar *basename = g_path_get_basename (filename);
+               create_document_in_new_tab (filename, text_utf8, basename);
 
                GtkRecentManager *manager = gtk_recent_manager_get_default ();
                gtk_recent_manager_add_item (manager, uri);
 
                g_free (contents);
                g_free (text_utf8);
+               g_free (basename);
        }
 
        else
@@ -1213,6 +1214,7 @@ create_document_in_new_tab (const gchar *path, const gchar *text,
        new_doc->saved = TRUE;
        new_doc->source_buffer = gtk_source_buffer_new (NULL);
        new_doc->source_view = gtk_source_view_new_with_buffer (new_doc->source_buffer);
+       g_object_unref (new_doc->source_buffer);
 
        latexila.all_docs = g_list_append (latexila.all_docs, new_doc);
        latexila.active_doc = new_doc;
@@ -1222,6 +1224,7 @@ create_document_in_new_tab (const gchar *path, const gchar *text,
        // set the language for the syntaxic color
        if (path != NULL)
        {
+               // TODO check memory leaks here
                GtkSourceLanguage *lang = gtk_source_language_manager_guess_language (
                                lm, path, NULL);
                if (lang != NULL)
@@ -1616,19 +1619,6 @@ update_cursor_position_statusbar (void)
        g_free (text);
 }
 
-static void
-scroll_to_cursor (void)
-{
-       if (latexila.active_doc == NULL)
-               return;
-
-       gtk_text_view_scroll_to_mark (
-                       GTK_TEXT_VIEW (latexila.active_doc->source_view),
-                       gtk_text_buffer_get_insert (
-                               GTK_TEXT_BUFFER (latexila.active_doc->source_buffer)),
-                       0.25, FALSE, 0, 0);
-}
-
 static void
 find (gboolean backward)
 {
diff --git a/src/external_commands.c b/src/external_commands.c
index a85edb4..8d0d1ff 100644
--- a/src/external_commands.c
+++ b/src/external_commands.c
@@ -328,8 +328,6 @@ cb_watch_output_command (GIOChannel *channel, GIOCondition condition,
 
        if (condition & G_IO_IN)
        {
-               int nb_lines = 0;
-
                GError *error = NULL;
                gchar *line = NULL;
                GIOStatus gio_status = g_io_channel_read_line (channel, &line, NULL, NULL, &error); 
@@ -351,21 +349,7 @@ cb_watch_output_command (GIOChannel *channel, GIOCondition condition,
                                line_utf8[strlen (line_utf8) - 1] = '\0';
 
                                if (show_all_output)
-                               {
                                        print_output_normal (line_utf8);
-
-                                       /* Flush the queue for the 200 first lines and then every 50 lines.
-                                        * This is for the fluidity of the output, without that the lines do 
not
-                                        * appear directly and it's ugly. But it is very slow, for a command 
that
-                                        * execute for example in 10 seconds, it could take 250 seconds (!) 
if we
-                                        * flush the queue at each line... But with commands that take 1
-                                        * second or so there is not a big difference.
-                                        */
-                                       if (nb_lines < 200 || nb_lines % 50 == 0)
-                                               flush_queue ();
-                                       nb_lines++;
-                               }
-
                                else
                                        latex_output_filter (line_utf8);
 
@@ -433,7 +417,6 @@ finish_execute (void)
                print_output_exit (42, _("The child process exited abnormally"));
 
        output_view_columns_autosize ();
-       flush_queue ();
 
        // unlock the action list and all the build actions
        set_action_sensitivity (TRUE);
diff --git a/src/file_browser.c b/src/file_browser.c
index b773f84..6154095 100644
--- a/src/file_browser.c
+++ b/src/file_browser.c
@@ -147,6 +147,7 @@ fill_list_store_with_current_dir (void)
                return;
        }
 
+       //TODO check memomy leaks
        gtk_list_store_clear (latexila.file_browser.list_store);
 
        /* append all the files contained in the directory */
diff --git a/src/latex_output_filter.c b/src/latex_output_filter.c
index c3f9696..e49344c 100644
--- a/src/latex_output_filter.c
+++ b/src/latex_output_filter.c
@@ -25,7 +25,6 @@
 
 #include "main.h"
 #include "print.h"
-#include "utils.h"
 #include "latex_output_filter.h"
 #include "log.h"
 
@@ -44,6 +43,7 @@ static void update_stack_file (const gchar *line);
 static void update_stack_file_heuristic (const gchar *line);
 
 static gboolean file_exists (const gchar *filename);
+static gchar * get_path_if_file_exists (const gchar *filename);
 static gchar * get_current_filename (void);
 static void push_file_on_stack (gchar *filename, gboolean reliable);
 static void pop_file_from_stack (void);
@@ -183,38 +183,12 @@ latex_output_filter_set_path (const gchar *dir)
 void
 latex_output_filter_print_stats (void)
 {
-       gchar *str;
-       if (nb_errors > 1)
-               str = g_strdup_printf (_("%d errors, "), nb_errors);
-       else
-               str = g_strdup_printf (_("%d error, "), nb_errors);
-       if (nb_warnings > 1)
-       {
-               gchar *tmp = g_strdup_printf (_("%s%d warnings, "), str, nb_warnings);
-               g_free (str);
-               str = tmp;
-       }
-       else
-       {
-               gchar *tmp = g_strdup_printf (_("%s%d warning, "), str, nb_warnings);
-               g_free (str);
-               str = tmp;
-       }
-       if (nb_badboxes > 1)
-       {
-               gchar *tmp = g_strdup_printf (_("%s%d badboxes"), str, nb_badboxes);
-               g_free (str);
-               str = tmp;
-       }
-       else
-       {
-               gchar *tmp = g_strdup_printf (_("%s%d badbox"), str, nb_badboxes);
-               g_free (str);
-               str = tmp;
-       }
+       gchar *str = g_strdup_printf ("%d %s, %d %s, %d %s",
+                       nb_errors, nb_errors > 1 ? "errors" : "error",
+                       nb_warnings, nb_warnings > 1 ? "warnings" : "warning",
+                       nb_badboxes, nb_badboxes > 1 ? "badboxes" : "badbox");
 
        print_output_info (str);
-       flush_queue ();
        g_free (str);
 
        // it's finish, we reset the counters
@@ -222,12 +196,15 @@ latex_output_filter_print_stats (void)
        nb_warnings = 0;
        nb_errors = 0;
 
-       // if the file stack is not empty
+       // empty the stack file
        gint nb_files_in_stack = g_slist_length (stack_file);
        if (nb_files_in_stack > 0)
                print_warning ("the file stack was not empty!");
        for (int i = 0 ; i < nb_files_in_stack ; i++)
+       {
+               print_info ("%s", get_current_filename ());
                pop_file_from_stack ();
+       }
 }
 
 static gboolean
@@ -731,15 +708,36 @@ update_stack_file_heuristic (const gchar *line)
 static gboolean
 file_exists (const gchar *filename)
 {
-       if (g_path_is_absolute (filename))
-               return g_file_test (filename, G_FILE_TEST_IS_REGULAR);
-
-       gchar *full_path = g_build_filename (path, filename, NULL);
-       if (g_file_test (full_path, G_FILE_TEST_IS_REGULAR))
+       gchar *full_path = get_path_if_file_exists (filename);
+       if (full_path != NULL)
        {
                g_free (full_path);
                return TRUE;
        }
+       return FALSE;
+}
+
+// return NULL if the filename does not exist
+// return the path of the filename if it exists (must be freed)
+static gchar *
+get_path_if_file_exists (const gchar *filename)
+{
+       if (g_path_is_absolute (filename))
+       {
+               if (g_file_test (filename, G_FILE_TEST_IS_REGULAR))
+                       return g_strdup (filename);
+               else
+                       return NULL;
+       }
+
+       gchar *full_path;
+       if (g_str_has_prefix (filename, "./"))
+               full_path = g_build_filename (path, filename + 2, NULL);
+       else
+               full_path = g_build_filename (path, filename, NULL);
+
+       if (g_file_test (full_path, G_FILE_TEST_IS_REGULAR))
+               return full_path;
 
        // try to add various extensions on the filename to see if the file exists
        gchar *extensions[] = {".tex", ".ltx", ".latex", ".dtx", ".ins"};
@@ -749,14 +747,14 @@ file_exists (const gchar *filename)
                gchar *tmp = g_strdup_printf ("%s%s", full_path, extensions[i]);
                if (g_file_test (tmp, G_FILE_TEST_IS_REGULAR))
                {
-                       g_free (tmp);
                        g_free (full_path);
-                       return TRUE;
+                       return tmp;
                }
                g_free (tmp);
        }
 
-       return FALSE;
+       g_free (full_path);
+       return NULL;
 }
 
 static gchar *
@@ -776,7 +774,13 @@ push_file_on_stack (gchar *filename, gboolean reliable)
 {
        //print_info ("***\tpush\t\"%s\" (%s)", filename, reliable ? "reliable" : "not reliable");
        file_in_stack_t *file = g_malloc (sizeof (file_in_stack_t));
-       file->filename = g_strdup (filename);
+
+       gchar *path = get_path_if_file_exists (filename);
+       if (path != NULL)
+               file->filename = path;
+       else
+               file->filename = g_strdup (filename);
+
        file->reliable = reliable;
        stack_file = g_slist_prepend (stack_file, file);
 }
@@ -784,7 +788,7 @@ push_file_on_stack (gchar *filename, gboolean reliable)
 static void
 pop_file_from_stack (void)
 {
-       file_in_stack_t *file = g_slist_nth_data (stack_file, 0);
+       file_in_stack_t *file = stack_file->data;
        //print_info ("***\tpop\t\"%s\" (%s)", file->filename, file->reliable ? "reliable" : "not reliable");
        stack_file = g_slist_remove (stack_file, file);
        g_free (file->filename);
@@ -795,7 +799,9 @@ static gboolean
 top_file_on_stack_reliable (void)
 {
        // stack_file must contain at least one file
-       file_in_stack_t *file = g_slist_nth_data (stack_file, 0);
+       g_assert (stack_file != NULL);
+
+       file_in_stack_t *file = stack_file->data;
        return file->reliable;
 }
 
@@ -804,7 +810,6 @@ print_msg (void)
 {
        gchar *filename = get_current_filename ();
        print_output_message (filename, msg.line, msg.message, msg.message_type);
-       flush_queue ();
        
        msg.line = NO_LINE;
        msg.message_type = MESSAGE_TYPE_OTHER;
diff --git a/src/log.c b/src/log.c
index 37ad211..f706eff 100644
--- a/src/log.c
+++ b/src/log.c
@@ -17,19 +17,30 @@
  * along with LaTeXila.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <stdlib.h>
+#include <string.h>
 #include <gtk/gtk.h>
 
 #include "main.h"
 #include "log.h"
+#include "utils.h"
+#include "callbacks.h"
 
 static void cb_action_history_changed (GtkTreeSelection *selection,
                gpointer user_data);
+static void cb_output_row_changed (GtkTreeSelection *selection, gpointer data);
+static gboolean output_row_selection_func (GtkTreeSelection *selection,
+               GtkTreeModel *model, GtkTreePath *path,
+               gboolean path_currently_selected, gpointer data);
 static GtkListStore * get_new_output_list_store (void);
-static void scroll_to_end (GtkTreeIter *iter);
+static void scroll_to_end (GtkTreeIter *iter, gboolean force);
 
 static GtkTreeView *history_view;
 static GtkTreeView *output_view;
 
+// used to scroll to the end and to flush not everytime (because it is slow)
+static gint nb_lines = 0;
+
 void
 init_log_zone (GtkPaned *log_hpaned)
 {
@@ -106,6 +117,16 @@ init_log_zone (GtkPaned *log_hpaned)
                                NULL);
                gtk_tree_view_append_column (output_view, column);
 
+               // selection
+               GtkTreeSelection *select = gtk_tree_view_get_selection (output_view);
+               gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
+               g_signal_connect (G_OBJECT (select), "changed",
+                               G_CALLBACK (cb_output_row_changed), NULL);
+
+               // certain rows can not be selected
+               gtk_tree_selection_set_select_function (select,
+                               (GtkTreeSelectionFunc) output_row_selection_func, NULL, NULL);
+
                // with a scrollbar
                GtkWidget *scrollbar = gtk_scrolled_window_new (NULL, NULL);
                gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollbar),
@@ -131,6 +152,71 @@ cb_action_history_changed (GtkTreeSelection *selection, gpointer user_data)
        }
 }
 
+static void
+cb_output_row_changed (GtkTreeSelection *selection, gpointer data)
+{
+       GtkTreeIter iter;
+       GtkTreeModel *model;
+       if (gtk_tree_selection_get_selected (selection, &model, &iter))
+       {
+               gchar *filename;
+               gchar *line_number;
+               gint message_type;
+
+               gtk_tree_model_get (model, &iter,
+                               COL_OUTPUT_FILENAME, &filename,
+                               COL_OUTPUT_LINE_NUMBER, &line_number,
+                               COL_OUTPUT_MESSAGE_TYPE, &message_type,
+                               -1);
+
+               if (message_type != MESSAGE_TYPE_OTHER && filename != NULL
+                               && strlen (filename) != 0)
+               {
+                       // open the file (if the file is already opened, go to it)
+                       open_new_document_without_uri (filename);
+
+                       // go to line
+                       if (line_number != NULL && strlen (line_number) != 0
+                                       && latexila.active_doc != NULL)
+                       {
+                               gint num = strtol (line_number, NULL, 10);
+                               GtkTextIter iter_file;
+                               GtkTextBuffer *buffer = GTK_TEXT_BUFFER (
+                                               latexila.active_doc->source_buffer);
+                               gtk_text_buffer_get_iter_at_line (buffer, &iter_file, --num);
+                               gtk_text_buffer_place_cursor (buffer, &iter_file);
+                               scroll_to_cursor ();
+                       }
+
+                       gtk_widget_grab_focus (latexila.active_doc->source_view);
+               }
+       }
+}
+
+static gboolean
+output_row_selection_func (GtkTreeSelection *selection, GtkTreeModel *model,
+               GtkTreePath *path, gboolean path_currently_selected, gpointer data)
+{
+       GtkTreeIter iter;
+       if (gtk_tree_model_get_iter (model, &iter, path))
+       {
+               gint message_type;
+               gchar *filename;
+               gtk_tree_model_get (model, &iter,
+                               COL_OUTPUT_FILENAME, &filename,
+                               COL_OUTPUT_MESSAGE_TYPE, &message_type,
+                               -1);
+
+               if (message_type == MESSAGE_TYPE_OTHER || filename == NULL
+                               || strlen (filename) == 0)
+                       return FALSE;
+               else
+                       return TRUE;
+       }
+
+       return FALSE; // not allow the selection state to change
+}
+
 static GtkListStore *
 get_new_output_list_store (void)
 {
@@ -154,7 +240,6 @@ add_action (const gchar *title, const gchar *command)
 
        GtkListStore *output_list_store = get_new_output_list_store ();
        gtk_tree_view_set_model (output_view, GTK_TREE_MODEL (output_list_store));
-       g_object_unref (output_list_store);
 
        // print title and command to the new list store
        gchar *title_with_num = g_strdup_printf ("%d. %s", num, title);
@@ -180,12 +265,20 @@ add_action (const gchar *title, const gchar *command)
        // scroll to the end
        GtkTreePath *path = gtk_tree_model_get_path (history_tree_model, &iter);
        gtk_tree_view_scroll_to_cell (history_view, path, NULL, FALSE, 0, 0);
+       gtk_tree_path_free (path);
 
        // delete the first entry
        if (num > 5)
        {
                GtkTreeIter first;
                gtk_tree_model_get_iter_first (history_tree_model, &first);
+
+               // free the output model
+               GtkTreeModel *first_output_store;
+               gtk_tree_model_get (history_tree_model, &first,
+                               COL_ACTION_OUTPUT_STORE, &first_output_store, -1);
+               g_object_unref (first_output_store);
+
                gtk_list_store_remove (GTK_LIST_STORE (history_tree_model), &first);
        }
 
@@ -208,6 +301,10 @@ output_view_columns_autosize (void)
 void
 print_output_title (const gchar *title)
 {
+       // generally, the title is the first line in a new output, and is used only
+       // once, so we reset the counter...
+       nb_lines = 0;
+
        GtkListStore *list_store =
                GTK_LIST_STORE (gtk_tree_view_get_model (output_view));
        GtkTreeIter iter;
@@ -220,12 +317,13 @@ print_output_title (const gchar *title)
                        COL_OUTPUT_COLOR_SET, FALSE,
                        COL_OUTPUT_WEIGHT, WEIGHT_BOLD,
                        -1);
-       scroll_to_end (&iter);
 }
 
 void
 print_output_info (const gchar *info)
 {
+       nb_lines++;
+
        GtkListStore *list_store =
                GTK_LIST_STORE (gtk_tree_view_get_model (output_view));
        GtkTreeIter iter;
@@ -238,13 +336,15 @@ print_output_info (const gchar *info)
                        COL_OUTPUT_COLOR_SET, FALSE,
                        COL_OUTPUT_WEIGHT, WEIGHT_NORMAL,
                        -1);
-       scroll_to_end (&iter);
+       scroll_to_end (&iter, FALSE);
 }
 
 // if message != NULL the exit_code is not taken into account
 void
 print_output_exit (const gint exit_code, const gchar *message)
 {
+       nb_lines++;
+
        GtkListStore *list_store =
                GTK_LIST_STORE (gtk_tree_view_get_model (output_view));
        GtkTreeIter iter;
@@ -280,13 +380,19 @@ print_output_exit (const gint exit_code, const gchar *message)
                                -1);
                g_free (tmp);
        }
-       scroll_to_end (&iter);
+
+       // force the scrolling and the flush
+       scroll_to_end (&iter, TRUE);
 }
 
 void
 print_output_message (const gchar *filename, const gint line_number,
                const gchar *message, gint message_type)
 {
+       // this function is used only in the filter, so there are less lines
+       // but we want to flush more often
+       nb_lines += 2;
+
        GtkListStore *list_store =
                GTK_LIST_STORE (gtk_tree_view_get_model (output_view));
 
@@ -331,7 +437,7 @@ print_output_message (const gchar *filename, const gint line_number,
                        COL_OUTPUT_COLOR_SET, TRUE,
                        COL_OUTPUT_WEIGHT, WEIGHT_NORMAL,
                        -1);
-       scroll_to_end (&iter);
+       scroll_to_end (&iter, FALSE);
 
        g_free (basename);
        g_free (line_number_str);
@@ -340,6 +446,8 @@ print_output_message (const gchar *filename, const gint line_number,
 void
 print_output_normal (const gchar *message)
 {
+       nb_lines++;
+
        GtkListStore *list_store =
                GTK_LIST_STORE (gtk_tree_view_get_model (output_view));
        GtkTreeIter iter;
@@ -352,13 +460,25 @@ print_output_normal (const gchar *message)
                        COL_OUTPUT_COLOR_SET, FALSE,
                        COL_OUTPUT_WEIGHT, WEIGHT_NORMAL,
                        -1);
-       scroll_to_end (&iter);
+       scroll_to_end (&iter, FALSE);
 }
 
 static void
-scroll_to_end (GtkTreeIter *iter)
+scroll_to_end (GtkTreeIter *iter, gboolean force)
 {
-       GtkTreeModel *tree_model = gtk_tree_view_get_model (output_view);
-       GtkTreePath *path = gtk_tree_model_get_path (tree_model, iter);
-       gtk_tree_view_scroll_to_cell (output_view, path, NULL, FALSE, 0, 0);
+       /* Flush the queue for the 50 first lines and then every 40 lines.
+        * This is for the fluidity of the output, without that the lines do not
+        * appear directly and it's ugly. But it is very slow, for a command that
+        * execute for example in 10 seconds, it could take 250 seconds (!) if we
+        * flush the queue at each line... But with commands that take 1
+        * second or so there is not a big difference.
+        */
+       if (force || nb_lines < 50 || nb_lines % 40 == 0)
+       {
+               GtkTreeModel *tree_model = gtk_tree_view_get_model (output_view);
+               GtkTreePath *path = gtk_tree_model_get_path (tree_model, iter);
+               gtk_tree_view_scroll_to_cell (output_view, path, NULL, FALSE, 0, 0);
+               gtk_tree_path_free (path);
+               flush_queue ();
+       }
 }
diff --git a/src/log.h b/src/log.h
index 3c2e872..386c2cb 100644
--- a/src/log.h
+++ b/src/log.h
@@ -51,9 +51,9 @@ enum history_action
 enum output_message_type
 {
        MESSAGE_TYPE_OTHER,
-       MESSAGE_TYPE_ERROR,
+       MESSAGE_TYPE_BADBOX,
        MESSAGE_TYPE_WARNING,
-       MESSAGE_TYPE_BADBOX
+       MESSAGE_TYPE_ERROR
 };
 
 enum output_line
diff --git a/src/main.c b/src/main.c
index 109102b..5b11c83 100644
--- a/src/main.c
+++ b/src/main.c
@@ -101,6 +101,7 @@ init_main_window (void)
 
        for (int i = 0 ; i < nb_icons ; i++)
        {
+               // TODO check memory leaks here
                GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (filenames[i], &error);
                if (error != NULL)
                {
@@ -115,6 +116,10 @@ init_main_window (void)
 
        gtk_window_set_default_icon_list (list_icons);
 
+       // Gtk have a copy of the GList and adds a ref to every icon
+       g_list_foreach (list_icons, (GFunc) g_object_unref, NULL);
+       g_list_free (list_icons);
+
        if (latexila.prefs.window_maximised)
                gtk_window_maximize (GTK_WINDOW (window));
 }
@@ -128,35 +133,39 @@ init_side_pane (void)
        gtk_paned_add1 (latexila.main_hpaned, side_pane_notebook);
 
        // symbol tables
-       GtkWidget *vbox_symbols = gtk_vbox_new (FALSE, 0);
-       latexila.symbols.vbox = vbox_symbols;
-
-       GtkWidget *tab_label = gtk_hbox_new (FALSE, 3);
-       GtkWidget *label = gtk_label_new (_("Symbols"));
-       GtkWidget *image = gtk_image_new_from_file (DATA_DIR "/images/greek/01.png");
-       gtk_box_pack_start (GTK_BOX (tab_label), image, FALSE, FALSE, 0);
-       gtk_box_pack_start (GTK_BOX (tab_label), label, TRUE, TRUE, 0);
-       gtk_widget_show_all (tab_label);
-
-       gtk_notebook_append_page (GTK_NOTEBOOK (side_pane_notebook), vbox_symbols,
-                       tab_label);
-       init_symbols ();
+       {
+               GtkWidget *vbox_symbols = gtk_vbox_new (FALSE, 0);
+               latexila.symbols.vbox = vbox_symbols;
+
+               GtkWidget *tab_label = gtk_hbox_new (FALSE, 3);
+               GtkWidget *label = gtk_label_new (_("Symbols"));
+               GtkWidget *image = gtk_image_new_from_file (DATA_DIR "/images/greek/01.png");
+               gtk_box_pack_start (GTK_BOX (tab_label), image, FALSE, FALSE, 0);
+               gtk_box_pack_start (GTK_BOX (tab_label), label, TRUE, TRUE, 0);
+               gtk_widget_show_all (tab_label);
+
+               gtk_notebook_append_page (GTK_NOTEBOOK (side_pane_notebook), vbox_symbols,
+                               tab_label);
+               init_symbols ();
+       }
 
        // file browser
-       GtkWidget *vbox_file_browser = gtk_vbox_new (FALSE, 0);
-       latexila.file_browser.vbox = vbox_file_browser;
-
-       tab_label = gtk_hbox_new (FALSE, 3);
-       label = gtk_label_new (_("File Browser"));
-       image = gtk_image_new_from_stock (GTK_STOCK_OPEN,
-                       GTK_ICON_SIZE_MENU);
-       gtk_box_pack_start (GTK_BOX (tab_label), image, FALSE, FALSE, 0);
-       gtk_box_pack_start (GTK_BOX (tab_label), label, TRUE, TRUE, 0);
-       gtk_widget_show_all (tab_label);
-
-       gtk_notebook_append_page (GTK_NOTEBOOK (side_pane_notebook),
-                       vbox_file_browser, tab_label);
-       init_file_browser ();
+       {
+               GtkWidget *vbox_file_browser = gtk_vbox_new (FALSE, 0);
+               latexila.file_browser.vbox = vbox_file_browser;
+
+               GtkWidget *tab_label = gtk_hbox_new (FALSE, 3);
+               GtkWidget *label = gtk_label_new (_("File Browser"));
+               GtkWidget *image = gtk_image_new_from_stock (GTK_STOCK_OPEN,
+                               GTK_ICON_SIZE_MENU);
+               gtk_box_pack_start (GTK_BOX (tab_label), image, FALSE, FALSE, 0);
+               gtk_box_pack_start (GTK_BOX (tab_label), label, TRUE, TRUE, 0);
+               gtk_widget_show_all (tab_label);
+
+               gtk_notebook_append_page (GTK_NOTEBOOK (side_pane_notebook),
+                               vbox_file_browser, tab_label);
+               init_file_browser ();
+       }
 }
 
 static void
@@ -339,14 +348,20 @@ main (int argc, char *argv[])
 {
        GError *error = NULL;
 
-       /* command line options */
-       gboolean option_new_document = FALSE;
-
+       /* localisation */
        gchar *latexila_nls_package = NULL;
+
 #ifdef LATEXILA_NLS_ENABLED
+       setlocale (LC_ALL, "");
+       bindtextdomain (LATEXILA_NLS_PACKAGE, LATEXILA_NLS_LOCALEDIR);
+       bind_textdomain_codeset (LATEXILA_NLS_PACKAGE, "UTF-8");
+       textdomain (LATEXILA_NLS_PACKAGE);
        latexila_nls_package = LATEXILA_NLS_PACKAGE;
 #endif
 
+       /* command line options */
+       gboolean option_new_document = FALSE;
+
        GOptionEntry options[] = {
                { "version", 'v', G_OPTION_FLAG_IN_MAIN | G_OPTION_FLAG_NO_ARG,
                        G_OPTION_ARG_CALLBACK, (gpointer) option_version,
@@ -357,29 +372,29 @@ main (int argc, char *argv[])
                {NULL}
        };
 
-       GOptionContext *context = g_option_context_new ("[FILES]");
-       g_option_context_add_main_entries (context, options, latexila_nls_package);
+       GOptionContext *context = g_option_context_new (NULL);
        g_option_context_add_group (context, gtk_get_option_group (TRUE));
+       g_option_context_add_main_entries (context, options, latexila_nls_package);
 
        // TODO with valgrind there are a lot of memory leaks with this, can we do
        // something?
-       if (! g_option_context_parse (context, &argc, &argv, &error))
+       gboolean tmp = g_option_context_parse (context, &argc, &argv, &error);
+       g_option_context_free (context);
+       if (! tmp)
+       {
                print_error ("option parsing failed: %s\n", error->message);
+               g_error_free (error);
+               exit (EXIT_FAILURE);
+       }
 
        gtk_init_with_args (&argc, &argv, NULL, options, latexila_nls_package,
                        &error);
        if (error != NULL)
+       {
                print_error ("%s", error->message);
-
-       g_option_context_free (context);
-
-       /* localisation */
-#ifdef LATEXILA_NLS_ENABLED
-       setlocale (LC_ALL, "");
-       bindtextdomain (LATEXILA_NLS_PACKAGE, LATEXILA_NLS_LOCALEDIR);
-       bind_textdomain_codeset (LATEXILA_NLS_PACKAGE, "UTF-8");
-       textdomain (LATEXILA_NLS_PACKAGE);
-#endif
+               g_error_free (error);
+               exit (EXIT_FAILURE);
+       }
 
        /* preferences */
        load_preferences (&latexila.prefs);
@@ -470,10 +485,13 @@ main (int argc, char *argv[])
 
        /* reopen files on startup */
        gchar ** list_opened_docs = (gchar **) latexila.prefs.list_opened_docs->pdata;
-       for (int i = 0 ; i < latexila.prefs.list_opened_docs->len
-                       && latexila.prefs.reopen_files_on_startup ; i++)
+       for (int i = 0 ; i < latexila.prefs.list_opened_docs->len ; i++)
        {
-               open_new_document_without_uri (list_opened_docs[i]);
+               if (latexila.prefs.reopen_files_on_startup)
+                       open_new_document_without_uri (list_opened_docs[i]);
+
+               // in all cases we must free the string
+               g_free (list_opened_docs[i]);
        }
        g_ptr_array_free (latexila.prefs.list_opened_docs, TRUE);
        latexila.prefs.list_opened_docs = g_ptr_array_new ();
diff --git a/src/prefs.c b/src/prefs.c
index 171f777..ea946e9 100644
--- a/src/prefs.c
+++ b/src/prefs.c
@@ -373,6 +373,7 @@ load_preferences (preferences_t *prefs)
                gchar **current = list_opened_docs;
                while (*current != NULL)
                {
+                       // the string must be freed later
                        g_ptr_array_add (prefs->list_opened_docs,
                                        (gpointer) g_strdup (*current));
                        current++;
@@ -882,6 +883,7 @@ cb_style_scheme_changed (GtkTreeSelection *selection, gpointer user_data)
        {
                gchar *id;
                gtk_tree_model_get (model, &iter, COLUMN_STYLE_SCHEME_ID, &id, -1);
+               g_free (latexila.prefs.style_scheme_id);
                latexila.prefs.style_scheme_id = id;
 
                GtkSourceStyleSchemeManager *style_scheme_manager =
@@ -890,12 +892,11 @@ cb_style_scheme_changed (GtkTreeSelection *selection, gpointer user_data)
                        gtk_source_style_scheme_manager_get_scheme (style_scheme_manager, id);
 
                // set the style scheme for all opened documents
-               GList *current = latexila.all_docs;
-               while (current != NULL)
+               for (GList *current = latexila.all_docs ; current != NULL ;
+                               current = g_list_next (current))
                {
                        document_t *doc = g_list_nth_data (current, 0);
                        gtk_source_buffer_set_style_scheme (doc->source_buffer, style_scheme);
-                       current = g_list_next (current);
                }
        }
 }
@@ -1102,6 +1103,7 @@ create_preferences (void)
        {
                GtkWidget *hbox = gtk_hbox_new (FALSE, 5);
                GtkWidget *label = gtk_label_new (_("Font:"));
+               // TODO check memory leaks here
                GtkWidget *font_button = gtk_font_button_new_with_font (
                                latexila.prefs.font_str);
                g_signal_connect (G_OBJECT (font_button), "font-set",
diff --git a/src/print.c b/src/print.c
index 77c2750..bc2bf9f 100644
--- a/src/print.c
+++ b/src/print.c
@@ -50,5 +50,4 @@ print_error (const char *format, ...)
        fprintf (stderr, "Error: ");
        vfprintf (stderr, format, va);
        fprintf (stderr, "\n");
-       exit (EXIT_FAILURE);
 }
diff --git a/src/templates.c b/src/templates.c
index 6060fe1..68df9ba 100644
--- a/src/templates.c
+++ b/src/templates.c
@@ -348,12 +348,15 @@ init_templates (void)
        for (gint i = 0 ; i < length ; i++)
        {
                gchar *file = g_strdup_printf ("%s/%d.tex", rc_dir, i);
-
                if (! g_file_test (file, G_FILE_TEST_EXISTS))
+               {
+                       g_free (file);
                        continue;
-               
+               }
+
                add_template_from_file (personnal_store, names[i],
                                DATA_DIR "/images/templates/article.png", file);
+               g_free (file);
        }
 
        g_strfreev (names);
diff --git a/src/ui.c b/src/ui.c
index 1c3c221..d7ceccd 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -816,7 +816,7 @@ init_ui (GtkWidget *box)
        {
                print_error ("building menubar and toolbar failed: %s", error->message);
                g_error_free (error);
-               error = NULL;
+               exit (EXIT_FAILURE);
        }
 
        // get and put the menubar and the toolbars to the main vbox
diff --git a/src/utils.c b/src/utils.c
index ac29f2f..92d4e99 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -21,6 +21,7 @@
 #include <stdio.h>
 #include <gtk/gtk.h>
 
+#include "main.h"
 #include "utils.h"
 
 void
@@ -29,3 +30,16 @@ flush_queue (void)
        while (g_main_context_pending (NULL))
                g_main_context_iteration (NULL, TRUE);
 }
+
+void
+scroll_to_cursor (void)
+{
+       if (latexila.active_doc == NULL)
+               return;
+
+       gtk_text_view_scroll_to_mark (
+                       GTK_TEXT_VIEW (latexila.active_doc->source_view),
+                       gtk_text_buffer_get_insert (
+                               GTK_TEXT_BUFFER (latexila.active_doc->source_buffer)),
+                       0.25, FALSE, 0, 0);
+}
diff --git a/src/utils.h b/src/utils.h
index dbab2fd..17841be 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -21,5 +21,6 @@
 #define UTILS_H
 
 void flush_queue (void);
+void scroll_to_cursor (void);
 
 #endif /* UTILS_H */


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