2
* This file is part of LaTeXila.
4
* Copyright Ā© 2010 SĆ©bastien Wilmet
6
* LaTeXila is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation, either version 3 of the License, or
9
* (at your option) any later version.
11
* LaTeXila is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with LaTeXila. If not, see <http://www.gnu.org/licenses/>.
27
#include "callbacks.h"
30
static void cb_action_history_changed (GtkTreeSelection *selection,
32
static GtkListStore * get_new_output_list_store (void);
33
static void go_to_message (gboolean next, gint message_type);
34
static void scroll_to_iter (GtkTreeIter *iter, gboolean force);
35
static gboolean output_row_selection_func (GtkTreeSelection *selection,
36
GtkTreeModel *model, GtkTreePath *path,
37
gboolean path_currently_selected, gpointer data);
38
static void select_row (GtkTreeModel *model, GtkTreeIter *iter);
39
static void jump_to_file (void);
40
static void index_messages_by_type (GtkTreeModel *model);
41
static void set_previous_next_actions_sensitivity (void);
42
static void path_free (gpointer data);
43
static void index_free (gpointer data);
45
static GtkTreeView *history_view;
46
static GtkTreeView *output_view;
48
// used to scroll to the end and to flush not everytime (because it is slow)
49
static gint nb_lines = 0;
52
init_log_zone (GtkPaned *log_hpaned, GtkWidget *log_toolbar)
56
GtkListStore *history_list_store = gtk_list_store_new (N_COLS_ACTION,
57
G_TYPE_STRING, G_TYPE_POINTER);
59
history_view = GTK_TREE_VIEW (gtk_tree_view_new_with_model (
60
GTK_TREE_MODEL (history_list_store)));
61
GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
62
GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (
63
_("Action history"), renderer, "text", COL_ACTION_TITLE, NULL);
64
gtk_tree_view_append_column (history_view, column);
66
GtkTreeSelection *select = gtk_tree_view_get_selection (history_view);
67
gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
68
g_signal_connect (G_OBJECT (select), "changed",
69
G_CALLBACK (cb_action_history_changed), NULL);
72
GtkWidget *scrollbar = gtk_scrolled_window_new (NULL, NULL);
73
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollbar),
74
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
75
gtk_container_add (GTK_CONTAINER (scrollbar), GTK_WIDGET (history_view));
76
gtk_paned_add1 (log_hpaned, scrollbar);
81
GtkListStore *output_list_store = get_new_output_list_store ();
83
output_view = GTK_TREE_VIEW (gtk_tree_view_new_with_model (
84
GTK_TREE_MODEL (output_list_store)));
85
g_object_unref (output_list_store);
86
set_previous_next_actions_sensitivity ();
88
// we can now show some text (output_view must be initialized)
89
print_output_normal (_("Welcome to LaTeXila!"));
91
gtk_tree_view_set_headers_visible (output_view, FALSE);
92
gtk_tree_view_set_tooltip_column (output_view, COL_OUTPUT_FILENAME);
94
// one column with 3 cell renderers (basename, line number, and message)
95
GtkTreeViewColumn *column = gtk_tree_view_column_new ();
96
gtk_tree_view_append_column (output_view, column);
99
GtkCellRenderer *renderer1 = gtk_cell_renderer_text_new ();
100
g_object_set (renderer1, "weight-set", TRUE, NULL);
101
gtk_tree_view_column_pack_start (column, renderer1, FALSE);
102
gtk_tree_view_column_set_attributes (column, renderer1,
103
"text", COL_OUTPUT_BASENAME,
104
"foreground", COL_OUTPUT_COLOR,
105
"background", COL_OUTPUT_BG_COLOR,
106
"weight", COL_OUTPUT_WEIGHT,
110
GtkCellRenderer *renderer2 = gtk_cell_renderer_text_new ();
111
g_object_set (renderer2, "weight-set", TRUE, NULL);
112
gtk_tree_view_column_pack_start (column, renderer2, FALSE);
113
gtk_tree_view_column_set_attributes (column, renderer2,
114
"text", COL_OUTPUT_LINE_NUMBER,
115
"foreground", COL_OUTPUT_COLOR,
116
"background", COL_OUTPUT_BG_COLOR,
117
"weight", COL_OUTPUT_WEIGHT,
121
GtkCellRenderer *renderer3 = gtk_cell_renderer_text_new ();
122
g_object_set (renderer3, "weight-set", TRUE, NULL);
123
gtk_tree_view_column_pack_start (column, renderer3, FALSE);
124
gtk_tree_view_column_set_attributes (column, renderer3,
125
"text", COL_OUTPUT_MESSAGE,
126
"foreground", COL_OUTPUT_COLOR,
127
"background", COL_OUTPUT_BG_COLOR,
128
"weight", COL_OUTPUT_WEIGHT,
132
GtkTreeSelection *select = gtk_tree_view_get_selection (output_view);
133
gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
135
// If the user click on a row, output_row_selection_func() will be
136
// called, but no row will be selected (the function return FALSE
137
// everytime). Instead, if the row can be "selected" (if the message
138
// type is an error, a warning or a badbox, and if the filename is not
139
// empty), the background and foreground colors are inverted.
140
// The GtkTreePath of the row selected is stored as a data in the
141
// GtkTreeModel (with g_object_set_data()).
142
gtk_tree_selection_set_select_function (select,
143
(GtkTreeSelectionFunc) output_row_selection_func, NULL, NULL);
146
GtkWidget *scrollbar = gtk_scrolled_window_new (NULL, NULL);
147
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollbar),
148
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
149
gtk_container_add (GTK_CONTAINER (scrollbar), GTK_WIDGET (output_view));
152
* right: log toolbar (vertical)
154
GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
155
gtk_box_pack_start (GTK_BOX (hbox), scrollbar, TRUE, TRUE, 0);
156
gtk_box_pack_start (GTK_BOX (hbox), log_toolbar, FALSE, FALSE, 0);
157
gtk_paned_add2 (log_hpaned, hbox);
162
cb_action_history_changed (GtkTreeSelection *selection, gpointer user_data)
165
GtkTreeModel *history_model;
166
if (gtk_tree_selection_get_selected (selection, &history_model, &iter))
168
GtkTreeModel *output_model;
169
gtk_tree_model_get (history_model, &iter,
170
COL_ACTION_OUTPUT_STORE, &output_model,
172
gtk_tree_view_set_model (output_view, output_model);
174
output_view_columns_autosize ();
176
// scroll to the selected line
177
GtkTreePath *path = g_object_get_data (G_OBJECT (output_model),
181
GtkTreeIter output_iter;
182
gtk_tree_model_get_iter (output_model, &output_iter, path);
183
scroll_to_iter (&output_iter, TRUE);
186
set_previous_next_actions_sensitivity ();
190
static GtkListStore *
191
get_new_output_list_store (void)
193
GtkListStore *output_list_store = gtk_list_store_new (N_COLS_OUTPUT,
194
G_TYPE_STRING, // basename
195
G_TYPE_STRING, // filename
196
G_TYPE_STRING, // line number
197
G_TYPE_STRING, // message
198
G_TYPE_INT, // message type
199
G_TYPE_STRING, // color
200
G_TYPE_STRING, // background color
203
return output_list_store;
207
add_action (const gchar *title, const gchar *command)
211
GtkListStore *output_list_store = get_new_output_list_store ();
212
gtk_tree_view_set_model (output_view, GTK_TREE_MODEL (output_list_store));
213
set_previous_next_actions_sensitivity ();
215
// print title and command to the new list store
216
gchar *title_with_num = g_strdup_printf ("%d. %s", num, title);
217
print_output_title (title_with_num);
219
gchar *command_with_dolar = g_strdup_printf ("$ %s", command);
220
print_output_info (command_with_dolar);
221
g_free (command_with_dolar);
223
// append a new entry to the history action list
224
GtkTreeModel *history_tree_model = gtk_tree_view_get_model (history_view);
226
gtk_list_store_append (GTK_LIST_STORE (history_tree_model), &iter);
227
gtk_list_store_set (GTK_LIST_STORE (history_tree_model), &iter,
228
COL_ACTION_TITLE, title_with_num,
229
COL_ACTION_OUTPUT_STORE, output_list_store,
232
// select the new entry
233
GtkTreeSelection *selection = gtk_tree_view_get_selection (history_view);
234
gtk_tree_selection_select_iter (selection, &iter);
237
GtkTreePath *path = gtk_tree_model_get_path (history_tree_model, &iter);
238
gtk_tree_view_scroll_to_cell (history_view, path, NULL, FALSE, 0, 0);
239
gtk_tree_path_free (path);
241
// delete the first entry
245
gtk_tree_model_get_iter_first (history_tree_model, &first);
247
// free the output model
248
GtkTreeModel *first_output_store;
249
gtk_tree_model_get (history_tree_model, &first,
250
COL_ACTION_OUTPUT_STORE, &first_output_store,
252
g_object_unref (first_output_store);
254
gtk_list_store_remove (GTK_LIST_STORE (history_tree_model), &first);
258
g_free (title_with_num);
262
go_to_message (gboolean next, gint message_type)
264
GtkTreeModel *model = gtk_tree_view_get_model (output_view);
265
messages_index_t *index = g_object_get_data (G_OBJECT (model), "index");
269
// set nb_messages and messages with the data from index for the right
273
switch (message_type)
275
case MESSAGE_TYPE_ERROR:
276
nb_messages = index->nb_errors;
277
messages = index->errors;
280
case MESSAGE_TYPE_WARNING:
281
nb_messages = index->nb_warnings;
282
messages = index->warnings;
285
case MESSAGE_TYPE_BADBOX:
286
nb_messages = index->nb_badboxes;
287
messages = index->badboxes;
294
if (nb_messages == 0)
298
// find the row number to select
299
gint row_to_select = -1;
301
GtkTreePath *path = g_object_get_data (G_OBJECT (model), "row-selected");
304
gint *indices = gtk_tree_path_get_indices (path);
305
gint indice = indices[0];
306
for (gint i = 0 ; i < nb_messages ; i++)
308
if (next && messages[i] > indice)
310
row_to_select = messages[i];
313
else if (! next && messages[i] >= indice)
317
row_to_select = messages[i-1];
320
// the row selected is after the last row of the type message_type
321
else if (! next && i == nb_messages - 1)
323
row_to_select = messages[i];
329
if (row_to_select == -1)
333
// no row is selected, take the first
334
else if (path == NULL && next)
335
row_to_select = messages[0];
339
GtkTreePath *new_path = gtk_tree_path_new_from_indices (row_to_select, -1);
341
if (! gtk_tree_model_get_iter (model, &iter, new_path))
344
select_row (model, &iter);
345
scroll_to_iter (&iter, TRUE);
349
cb_go_previous_latex_error (void)
351
go_to_message (FALSE, MESSAGE_TYPE_ERROR);
355
cb_go_previous_latex_warning (void)
357
go_to_message (FALSE, MESSAGE_TYPE_WARNING);
361
cb_go_previous_latex_badbox (void)
363
go_to_message (FALSE, MESSAGE_TYPE_BADBOX);
367
cb_go_next_latex_error (void)
369
go_to_message (TRUE, MESSAGE_TYPE_ERROR);
373
cb_go_next_latex_warning (void)
375
go_to_message (TRUE, MESSAGE_TYPE_WARNING);
379
cb_go_next_latex_badbox (void)
381
go_to_message (TRUE, MESSAGE_TYPE_BADBOX);
385
set_history_sensitivity (gboolean sensitive)
387
gtk_widget_set_sensitive (GTK_WIDGET (history_view), sensitive);
391
output_view_columns_autosize (void)
393
gtk_tree_view_columns_autosize (output_view);
397
print_output_title (const gchar *title)
399
// generally, the title is the first line in a new output, and is used only
400
// once, so we reset the counter...
403
GtkListStore *list_store =
404
GTK_LIST_STORE (gtk_tree_view_get_model (output_view));
406
gtk_list_store_append (list_store, &iter);
407
gtk_list_store_set (list_store, &iter,
408
COL_OUTPUT_BASENAME, INFO_MESSAGE,
409
COL_OUTPUT_LINE_NUMBER, "",
410
COL_OUTPUT_MESSAGE, title,
411
COL_OUTPUT_MESSAGE_TYPE, MESSAGE_TYPE_OTHER,
412
COL_OUTPUT_WEIGHT, WEIGHT_BOLD,
417
print_output_info (const gchar *info)
421
GtkListStore *list_store =
422
GTK_LIST_STORE (gtk_tree_view_get_model (output_view));
424
gtk_list_store_append (list_store, &iter);
425
gtk_list_store_set (list_store, &iter,
426
COL_OUTPUT_BASENAME, INFO_MESSAGE,
427
COL_OUTPUT_LINE_NUMBER, "",
428
COL_OUTPUT_MESSAGE, info,
429
COL_OUTPUT_MESSAGE_TYPE, MESSAGE_TYPE_OTHER,
430
COL_OUTPUT_WEIGHT, WEIGHT_NORMAL,
432
scroll_to_iter (&iter, FALSE);
436
print_output_stats (gint nb_errors, gint nb_warnings, gint nb_badboxes)
438
gchar *str = g_strdup_printf ("%d %s, %d %s, %d %s",
439
nb_errors, nb_errors > 1 ? "errors" : "error",
440
nb_warnings, nb_warnings > 1 ? "warnings" : "warning",
441
nb_badboxes, nb_badboxes > 1 ? "badboxes" : "badbox");
443
print_output_info (str);
447
// we wait the exit code to fill it
448
messages_index_t *index = g_malloc (sizeof (messages_index_t));
449
index->nb_errors = nb_errors;
450
index->nb_warnings = nb_warnings;
451
index->nb_badboxes = nb_badboxes;
452
index->errors = g_malloc (nb_errors * sizeof (gint));
453
index->warnings = g_malloc (nb_warnings * sizeof (gint));
454
index->badboxes = g_malloc (nb_badboxes * sizeof (gint));
456
GtkTreeModel *model = gtk_tree_view_get_model (output_view);
457
g_object_set_data_full (G_OBJECT (model), "index", index,
458
(GDestroyNotify) index_free);
461
// if message != NULL the exit_code is not taken into account
463
print_output_exit (const gint exit_code, const gchar *message)
467
GtkListStore *list_store =
468
GTK_LIST_STORE (gtk_tree_view_get_model (output_view));
470
gtk_list_store_append (list_store, &iter);
471
gtk_list_store_set (list_store, &iter,
472
COL_OUTPUT_BASENAME, INFO_MESSAGE,
473
COL_OUTPUT_LINE_NUMBER, "",
474
COL_OUTPUT_MESSAGE_TYPE, MESSAGE_TYPE_OTHER,
475
COL_OUTPUT_WEIGHT, WEIGHT_NORMAL,
480
gtk_list_store_set (list_store, &iter,
481
COL_OUTPUT_MESSAGE, message,
482
COL_OUTPUT_COLOR, COLOR_RED,
485
else if (exit_code == 0)
487
gtk_list_store_set (list_store, &iter,
488
COL_OUTPUT_MESSAGE, _("Done!"),
489
COL_OUTPUT_COLOR, COLOR_GREEN,
494
gchar *tmp = g_strdup_printf (_("Finished with exit code %d"), exit_code);
495
gtk_list_store_set (list_store, &iter,
496
COL_OUTPUT_MESSAGE, tmp,
497
COL_OUTPUT_COLOR, COLOR_RED,
502
// force the scrolling and the flush
503
scroll_to_iter (&iter, TRUE);
505
// it's normally the last line, so we can index the messages by type
506
index_messages_by_type (GTK_TREE_MODEL (list_store));
510
print_output_message (const gchar *filename, const gint line_number,
511
const gchar *message, gint message_type)
513
// this function is used only in the filter, so there are less lines
514
// but we want to flush more often
517
GtkListStore *list_store =
518
GTK_LIST_STORE (gtk_tree_view_get_model (output_view));
521
if (filename != NULL)
522
basename = g_path_get_basename (filename);
524
basename = g_strdup ("");
526
gchar *line_number_str;
527
if (line_number != NO_LINE)
528
line_number_str = g_strdup_printf ("%d", line_number);
530
line_number_str = g_strdup ("");
533
switch (message_type)
535
case MESSAGE_TYPE_ERROR:
538
case MESSAGE_TYPE_WARNING:
539
color = COLOR_ORANGE;
541
case MESSAGE_TYPE_BADBOX:
550
gtk_list_store_append (list_store, &iter);
551
gtk_list_store_set (list_store, &iter,
552
COL_OUTPUT_BASENAME, basename,
553
COL_OUTPUT_FILENAME, filename != NULL ? filename : "",
554
COL_OUTPUT_LINE_NUMBER, line_number_str,
555
COL_OUTPUT_MESSAGE, message,
556
COL_OUTPUT_MESSAGE_TYPE, message_type,
557
COL_OUTPUT_COLOR, color,
558
COL_OUTPUT_WEIGHT, WEIGHT_NORMAL,
560
scroll_to_iter (&iter, FALSE);
563
g_free (line_number_str);
567
print_output_normal (const gchar *message)
571
GtkListStore *list_store =
572
GTK_LIST_STORE (gtk_tree_view_get_model (output_view));
574
gtk_list_store_append (list_store, &iter);
575
gtk_list_store_set (list_store, &iter,
576
COL_OUTPUT_BASENAME, "",
577
COL_OUTPUT_LINE_NUMBER, "",
578
COL_OUTPUT_MESSAGE, message,
579
COL_OUTPUT_MESSAGE_TYPE, MESSAGE_TYPE_OTHER,
580
COL_OUTPUT_WEIGHT, WEIGHT_NORMAL,
582
scroll_to_iter (&iter, FALSE);
586
scroll_to_iter (GtkTreeIter *iter, gboolean force)
588
/* Flush the queue for the 50 first lines and then every 40 lines.
589
* This is for the fluidity of the output, without that the lines do not
590
* appear directly and it's ugly. But it is very slow, for a command that
591
* execute for example in 10 seconds, it could take 250 seconds (!) if we
592
* flush the queue at each line... But with commands that take 1
593
* second or so there is not a big difference.
595
if (force || nb_lines < 50 || nb_lines % 40 == 0)
597
GtkTreeModel *tree_model = gtk_tree_view_get_model (output_view);
598
GtkTreePath *path = gtk_tree_model_get_path (tree_model, iter);
599
gtk_tree_view_scroll_to_cell (output_view, path, NULL, FALSE, 0, 0);
600
gtk_tree_path_free (path);
606
output_row_selection_func (GtkTreeSelection *selection, GtkTreeModel *model,
607
GtkTreePath *path, gboolean path_currently_selected, gpointer data)
610
if (gtk_tree_model_get_iter (model, &iter, path))
614
gtk_tree_model_get (model, &iter,
615
COL_OUTPUT_FILENAME, &filename,
616
COL_OUTPUT_MESSAGE_TYPE, &message_type,
619
if (message_type != MESSAGE_TYPE_OTHER && filename != NULL
620
&& strlen (filename) > 0)
621
select_row (model, &iter);
626
// rows will never be selected
631
select_row (GtkTreeModel *model, GtkTreeIter *iter)
633
GtkTreePath *current_path_selected = g_object_get_data (G_OBJECT (model),
636
GtkTreePath *path = gtk_tree_model_get_path (model, iter);
638
if (current_path_selected != NULL)
640
// if the row to select is not the same as the row already selected,
641
// we must deselect this row
642
if (gtk_tree_path_compare (current_path_selected, path) != 0)
644
GtkTreeIter current_iter_selected;
645
gtk_tree_model_get_iter (model, ¤t_iter_selected,
646
current_path_selected);
650
gtk_tree_model_get (model, ¤t_iter_selected,
651
COL_OUTPUT_BG_COLOR, &bg_color,
653
gtk_list_store_set (GTK_LIST_STORE (model), ¤t_iter_selected,
654
COL_OUTPUT_COLOR, bg_color,
655
COL_OUTPUT_BG_COLOR, NULL,
660
// the row is already selected
663
gtk_tree_path_free (path);
671
gtk_tree_model_get (model, iter,
672
COL_OUTPUT_COLOR, &color,
674
gtk_list_store_set (GTK_LIST_STORE (model), iter,
675
COL_OUTPUT_COLOR, "white",
676
COL_OUTPUT_BG_COLOR, color,
680
g_object_set_data_full (G_OBJECT (model), "row-selected", path,
681
(GDestroyNotify) path_free);
683
set_previous_next_actions_sensitivity ();
689
GtkTreeModel *model = gtk_tree_view_get_model (output_view);
690
GtkTreePath *path_selected = g_object_get_data (G_OBJECT (model),
692
if (path_selected == NULL)
696
gtk_tree_model_get_iter (model, &iter, path_selected);
698
gchar *filename = NULL;
699
gchar *line_number = NULL;
702
gtk_tree_model_get (model, &iter,
703
COL_OUTPUT_FILENAME, &filename,
704
COL_OUTPUT_LINE_NUMBER, &line_number,
705
COL_OUTPUT_MESSAGE_TYPE, &message_type,
708
if (message_type != MESSAGE_TYPE_OTHER && filename != NULL
709
&& strlen (filename) > 0)
711
// open the file (if the file is already opened, go to it)
712
open_new_document_without_uri (filename);
714
// we flush the queue here because without that, there is a bug when the
715
// file is not already opened, scroll_to_cursor() doesn't work as
720
if (line_number != NULL && strlen (line_number) != 0
721
&& latexila.active_doc != NULL)
723
gint num = strtol (line_number, NULL, 10);
724
GtkTextIter iter_file;
725
GtkTextBuffer *buffer = GTK_TEXT_BUFFER (
726
latexila.active_doc->source_buffer);
727
gtk_text_buffer_get_iter_at_line (buffer, &iter_file, --num);
728
gtk_text_buffer_place_cursor (buffer, &iter_file);
732
gtk_widget_grab_focus (latexila.active_doc->source_view);
736
g_free (line_number);
740
index_messages_by_type (GtkTreeModel *model)
742
messages_index_t *index = g_object_get_data (G_OBJECT (model), "index");
746
if (index->nb_errors == 0 && index->nb_warnings == 0
747
&& index->nb_badboxes == 0)
753
// positions in the tables
759
gboolean valid = gtk_tree_model_get_iter_first (model, &iter);
764
gtk_tree_model_get (model, &iter,
765
COL_OUTPUT_MESSAGE_TYPE, &message_type,
768
switch (message_type)
770
case MESSAGE_TYPE_ERROR:
771
index->errors[i_error] = i;
775
case MESSAGE_TYPE_WARNING:
776
index->warnings[i_warning] = i;
780
case MESSAGE_TYPE_BADBOX:
781
index->badboxes[i_badbox] = i;
789
valid = gtk_tree_model_iter_next (model, &iter);
793
set_previous_next_actions_sensitivity ();
797
set_previous_next_actions_sensitivity (void)
799
GtkTreeModel *model = gtk_tree_view_get_model (output_view);
800
messages_index_t *index = g_object_get_data (G_OBJECT (model), "index");
804
gtk_action_set_sensitive (latexila.actions.go_previous_error, FALSE);
805
gtk_action_set_sensitive (latexila.actions.go_previous_warning, FALSE);
806
gtk_action_set_sensitive (latexila.actions.go_previous_badbox, FALSE);
807
gtk_action_set_sensitive (latexila.actions.go_next_error, FALSE);
808
gtk_action_set_sensitive (latexila.actions.go_next_warning, FALSE);
809
gtk_action_set_sensitive (latexila.actions.go_next_badbox, FALSE);
813
GtkTreePath *path = g_object_get_data (G_OBJECT (model), "row-selected");
817
gtk_action_set_sensitive (latexila.actions.go_previous_error, FALSE);
818
gtk_action_set_sensitive (latexila.actions.go_previous_warning, FALSE);
819
gtk_action_set_sensitive (latexila.actions.go_previous_badbox, FALSE);
821
gtk_action_set_sensitive (latexila.actions.go_next_error, index->nb_errors > 0);
822
gtk_action_set_sensitive (latexila.actions.go_next_warning, index->nb_warnings > 0);
823
gtk_action_set_sensitive (latexila.actions.go_next_badbox, index->nb_badboxes > 0);
827
gint *indices = gtk_tree_path_get_indices (path);
828
gint indice = indices[0];
831
if (index->nb_errors > 0)
833
gtk_action_set_sensitive (latexila.actions.go_previous_error,
834
index->errors[0] < indice);
835
gtk_action_set_sensitive (latexila.actions.go_next_error,
836
index->errors[index->nb_errors - 1] > indice);
840
gtk_action_set_sensitive (latexila.actions.go_previous_error, FALSE);
841
gtk_action_set_sensitive (latexila.actions.go_next_error, FALSE);
845
if (index->nb_warnings > 0)
847
gtk_action_set_sensitive (latexila.actions.go_previous_warning,
848
index->warnings[0] < indice);
849
gtk_action_set_sensitive (latexila.actions.go_next_warning,
850
index->warnings[index->nb_warnings - 1] > indice);
854
gtk_action_set_sensitive (latexila.actions.go_previous_warning, FALSE);
855
gtk_action_set_sensitive (latexila.actions.go_next_warning, FALSE);
859
if (index->nb_badboxes > 0)
861
gtk_action_set_sensitive (latexila.actions.go_previous_badbox,
862
index->badboxes[0] < indice);
863
gtk_action_set_sensitive (latexila.actions.go_next_badbox,
864
index->badboxes[index->nb_badboxes - 1] > indice);
868
gtk_action_set_sensitive (latexila.actions.go_previous_badbox, FALSE);
869
gtk_action_set_sensitive (latexila.actions.go_next_badbox, FALSE);
874
path_free (gpointer data)
876
gtk_tree_path_free ((GtkTreePath *) data);
880
index_free (gpointer data)
882
messages_index_t *index = (messages_index_t *) data;
883
g_free (index->errors);
884
g_free (index->warnings);
885
g_free (index->badboxes);