geany  1.38
About: Geany is a text editor (using GTK2) with basic features of an integrated development environment (syntax highlighting, code folding, symbol name auto-completion, ...). F: office T: editor programming GTK+ IDE
  Fossies Dox: geany-1.38.tar.bz2  ("unofficial" and yet experimental doxygen-generated source code documentation)  

msgwindow.c
Go to the documentation of this file.
1/*
2 * msgwindow.c - this file is part of Geany, a fast and lightweight IDE
3 *
4 * Copyright 2005 The Geany contributors
5 *
6 * This program 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 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program 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.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21/**
22 * @file msgwindow.h
23 * Message window functions (status, compiler, messages windows).
24 * Also compiler error message parsing and grep file and line parsing.
25 *
26 * @see GeanyMainWidgets::message_window_notebook to append a new notebook page.
27 **/
28
29#ifdef HAVE_CONFIG_H
30# include "config.h"
31#endif
32
33#include "msgwindow.h"
34
35#include "build.h"
36#include "document.h"
37#include "callbacks.h"
38#include "filetypes.h"
39#include "keybindings.h"
40#include "main.h"
41#include "navqueue.h"
42#include "prefs.h"
43#include "support.h"
44#include "ui_utils.h"
45#include "utils.h"
46#include "vte.h"
47
48#include <string.h>
49#include <stdlib.h>
50#include <time.h>
51
52#include <gdk/gdkkeysyms.h>
53
54
55/* used for parse_file_line */
56typedef struct
57{
58 const gchar *string; /* line data */
59 const gchar *pattern; /* pattern to split the error message into some fields */
60 guint min_fields; /* used to detect errors after parsing */
61 guint line_idx; /* idx of the field where the line is */
62 gint file_idx; /* idx of the field where the filename is or -1 */
63}
65
66MessageWindow msgwindow;
67
68enum
69{
75};
76
77enum
78{
82};
83
84
85static GdkColor color_error = {0, 0xFFFF, 0, 0};
86static GdkColor color_context = {0, 0x7FFF, 0, 0};
87static GdkColor color_message = {0, 0, 0, 0xD000};
88
89
90static void prepare_msg_tree_view(void);
91static void prepare_status_tree_view(void);
92static void prepare_compiler_tree_view(void);
93static GtkWidget *create_message_popup_menu(gint type);
94static gboolean on_msgwin_button_press_event(GtkWidget *widget, GdkEventButton *event,
95 gpointer user_data);
96static void on_scribble_populate(GtkTextView *textview, GtkMenu *arg1, gpointer user_data);
97
98
100{
101 ui_widget_show_hide(gtk_widget_get_parent(msgwindow.tree_status), interface_prefs.msgwin_status_visible);
102 ui_widget_show_hide(gtk_widget_get_parent(msgwindow.tree_compiler), interface_prefs.msgwin_compiler_visible);
105}
106
107
108/**
109 * Sets the Messages path for opening any parsed filenames without absolute path from message lines.
110 *
111 * @param messages_dir The directory.
112 **/
113GEANY_API_SYMBOL
114void msgwin_set_messages_dir(const gchar *messages_dir)
115{
116 g_free(msgwindow.messages_dir);
117 msgwindow.messages_dir = g_strdup(messages_dir);
118}
119
120
121static void load_color(const gchar *color_name, GdkColor *color)
122{
123 GdkRGBA rgba_color;
124 GtkWidgetPath *path = gtk_widget_path_new();
125 GtkStyleContext *ctx = gtk_style_context_new();
126
127 gtk_widget_path_append_type(path, GTK_TYPE_WINDOW);
128 gtk_widget_path_iter_set_name(path, -1, color_name);
129 gtk_style_context_set_screen(ctx, gdk_screen_get_default());
130 gtk_style_context_set_path(ctx, path);
131 gtk_style_context_get_color(ctx, gtk_style_context_get_state(ctx), &rgba_color);
132
133 color->red = 0xffff * rgba_color.red;
134 color->green = 0xffff * rgba_color.green;
135 color->blue = 0xffff * rgba_color.blue;
136
137 gtk_widget_path_unref(path);
138 g_object_unref(ctx);
139}
140
141
142void msgwin_init(void)
143{
144 msgwindow.notebook = ui_lookup_widget(main_widgets.window, "notebook_info");
145 msgwindow.tree_status = ui_lookup_widget(main_widgets.window, "treeview3");
146 msgwindow.tree_msg = ui_lookup_widget(main_widgets.window, "treeview4");
147 msgwindow.tree_compiler = ui_lookup_widget(main_widgets.window, "treeview5");
148 msgwindow.scribble = ui_lookup_widget(main_widgets.window, "textview_scribble");
149 msgwindow.messages_dir = NULL;
150
156 msgwindow.popup_compiler_menu = create_message_popup_menu(MSG_COMPILER);
157
159 g_signal_connect(msgwindow.scribble, "populate-popup", G_CALLBACK(on_scribble_populate), NULL);
160
161 load_color("geany-compiler-error", &color_error);
162 load_color("geany-compiler-context", &color_context);
163 load_color("geany-compiler-message", &color_message);
164}
165
166
168{
169 g_free(msgwindow.messages_dir);
170}
171
172
173static gboolean on_msgwin_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
174{
175 gboolean enter_or_return = ui_is_keyval_enter_or_return(event->keyval);
176
177 if (enter_or_return || event->keyval == GDK_KEY_space)
178 {
179 switch (GPOINTER_TO_INT(data))
180 {
181 case MSG_COMPILER:
182 { /* key press in the compiler treeview */
183 msgwin_goto_compiler_file_line(enter_or_return);
184 break;
185 }
186 case MSG_MESSAGE:
187 { /* key press in the message treeview (results of 'Find usage') */
188 msgwin_goto_messages_file_line(enter_or_return);
189 break;
190 }
191 }
192 }
193 return FALSE;
194}
195
196
197/* does some preparing things to the status message list widget */
199{
200 GtkCellRenderer *renderer;
201 GtkTreeViewColumn *column;
202
203 msgwindow.store_status = gtk_list_store_new(1, G_TYPE_STRING);
204 gtk_tree_view_set_model(GTK_TREE_VIEW(msgwindow.tree_status), GTK_TREE_MODEL(msgwindow.store_status));
205 g_object_unref(msgwindow.store_status);
206
207 renderer = gtk_cell_renderer_text_new();
208 column = gtk_tree_view_column_new_with_attributes(_("Status messages"), renderer, "text", 0, NULL);
209 gtk_tree_view_append_column(GTK_TREE_VIEW(msgwindow.tree_status), column);
210
211 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(msgwindow.tree_status), FALSE);
212
214
215 g_signal_connect(msgwindow.tree_status, "button-press-event",
216 G_CALLBACK(on_msgwin_button_press_event), GINT_TO_POINTER(MSG_STATUS));
217}
218
219
220/* does some preparing things to the message list widget
221 * (currently used for showing results of 'Find usage') */
222static void prepare_msg_tree_view(void)
223{
224 GtkCellRenderer *renderer;
225 GtkTreeViewColumn *column;
226 GtkTreeSelection *selection;
227
228 /* line, doc id, fg, str */
229 msgwindow.store_msg = gtk_list_store_new(MSG_COL_COUNT, G_TYPE_INT, G_TYPE_UINT,
230 GDK_TYPE_COLOR, G_TYPE_STRING);
231 gtk_tree_view_set_model(GTK_TREE_VIEW(msgwindow.tree_msg), GTK_TREE_MODEL(msgwindow.store_msg));
232 g_object_unref(msgwindow.store_msg);
233
234 renderer = gtk_cell_renderer_text_new();
235 column = gtk_tree_view_column_new_with_attributes(NULL, renderer,
236 "foreground-gdk", MSG_COL_COLOR, "text", MSG_COL_STRING, NULL);
237 gtk_tree_view_append_column(GTK_TREE_VIEW(msgwindow.tree_msg), column);
238
239 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(msgwindow.tree_msg), FALSE);
240
242
243 /* use button-release-event so the selection has changed
244 * (connect_after button-press-event doesn't work) */
245 g_signal_connect(msgwindow.tree_msg, "button-release-event",
246 G_CALLBACK(on_msgwin_button_press_event), GINT_TO_POINTER(MSG_MESSAGE));
247 /* for double-clicking only, after the first release */
248 g_signal_connect(msgwindow.tree_msg, "button-press-event",
249 G_CALLBACK(on_msgwin_button_press_event), GINT_TO_POINTER(MSG_MESSAGE));
250 g_signal_connect(msgwindow.tree_msg, "key-press-event",
251 G_CALLBACK(on_msgwin_key_press_event), GINT_TO_POINTER(MSG_MESSAGE));
252
253 /* selection handling */
254 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(msgwindow.tree_msg));
255 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
256 /*g_signal_connect(selection, "changed",G_CALLBACK(on_msg_tree_selection_changed), NULL);*/
257}
258
259
260/* does some preparing things to the compiler list widget */
262{
263 GtkCellRenderer *renderer;
264 GtkTreeViewColumn *column;
265 GtkTreeSelection *selection;
266
267 msgwindow.store_compiler = gtk_list_store_new(COMPILER_COL_COUNT, GDK_TYPE_COLOR, G_TYPE_STRING);
268 gtk_tree_view_set_model(GTK_TREE_VIEW(msgwindow.tree_compiler), GTK_TREE_MODEL(msgwindow.store_compiler));
269 g_object_unref(msgwindow.store_compiler);
270
271 renderer = gtk_cell_renderer_text_new();
272 column = gtk_tree_view_column_new_with_attributes(NULL, renderer,
273 "foreground-gdk", COMPILER_COL_COLOR, "text", COMPILER_COL_STRING, NULL);
274 gtk_tree_view_append_column(GTK_TREE_VIEW(msgwindow.tree_compiler), column);
275
276 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(msgwindow.tree_compiler), FALSE);
277
279
280 /* use button-release-event so the selection has changed
281 * (connect_after button-press-event doesn't work) */
282 g_signal_connect(msgwindow.tree_compiler, "button-release-event",
283 G_CALLBACK(on_msgwin_button_press_event), GINT_TO_POINTER(MSG_COMPILER));
284 /* for double-clicking only, after the first release */
285 g_signal_connect(msgwindow.tree_compiler, "button-press-event",
286 G_CALLBACK(on_msgwin_button_press_event), GINT_TO_POINTER(MSG_COMPILER));
287 g_signal_connect(msgwindow.tree_compiler, "key-press-event",
288 G_CALLBACK(on_msgwin_key_press_event), GINT_TO_POINTER(MSG_COMPILER));
289
290 /* selection handling */
291 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(msgwindow.tree_compiler));
292 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
293 /*g_signal_connect(selection, "changed", G_CALLBACK(on_msg_tree_selection_changed), NULL);*/
294}
295
296static const GdkColor *get_color(gint msg_color)
297{
298 switch (msg_color)
299 {
300 case COLOR_RED: return &color_error;
301 case COLOR_DARK_RED: return &color_context;
302 case COLOR_BLUE: return &color_message;
303 default: return NULL;
304 }
305}
306
307
308/**
309 * Adds a formatted message in the compiler tab treeview in the messages window.
310 *
311 * @param msg_color A color to be used for the text. It must be an element of #MsgColors.
312 * @param format @c printf()-style format string.
313 * @param ... Arguments for the @c format string.
314 *
315 * @see msgwin_compiler_add_string()
316 *
317 * @since 0.16
318 **/
319GEANY_API_SYMBOL
320void msgwin_compiler_add(gint msg_color, const gchar *format, ...)
321{
322 gchar *string;
323 va_list args;
324
325 va_start(args, format);
326 string = g_strdup_vprintf(format, args);
327 va_end(args);
328 msgwin_compiler_add_string(msg_color, string);
329 g_free(string);
330}
331
332/**
333 * Adds a new message in the compiler tab treeview in the messages window.
334 *
335 * @param msg_color A color to be used for the text. It must be an element of #MsgColors.
336 * @param msg Compiler message to be added.
337 *
338 * @see msgwin_compiler_add()
339 *
340 * @since 1.34 (API 236)
341 **/
342GEANY_API_SYMBOL
343void msgwin_compiler_add_string(gint msg_color, const gchar *msg)
344{
345 GtkTreeIter iter;
346 const GdkColor *color = get_color(msg_color);
347 gchar *utf8_msg;
348
349 if (! g_utf8_validate(msg, -1, NULL))
350 utf8_msg = utils_get_utf8_from_locale(msg);
351 else
352 utf8_msg = (gchar *) msg;
353
354 gtk_list_store_append(msgwindow.store_compiler, &iter);
355 gtk_list_store_set(msgwindow.store_compiler, &iter,
357
358 if (ui_prefs.msgwindow_visible && interface_prefs.compiler_tab_autoscroll)
359 {
360 GtkTreePath *path = gtk_tree_model_get_path(
361 gtk_tree_view_get_model(GTK_TREE_VIEW(msgwindow.tree_compiler)), &iter);
362
363 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(msgwindow.tree_compiler), path, NULL, TRUE, 0.5, 0.5);
364 gtk_tree_path_free(path);
365 }
366
367 if (utf8_msg != msg)
368 g_free(utf8_msg);
369}
370
371
372void msgwin_show_hide(gboolean show)
373{
374 ui_prefs.msgwindow_visible = show;
375 ignore_callback = TRUE;
376 gtk_check_menu_item_set_active(
377 GTK_CHECK_MENU_ITEM(ui_lookup_widget(main_widgets.window, "menu_show_messages_window1")),
378 show);
379 ignore_callback = FALSE;
381 /* set the input focus back to the editor */
383}
384
385
386/**
387 * Adds a formatted message in the messages tab treeview in the messages window.
388 *
389 * If @a line and @a doc are set, clicking on this line jumps into the file
390 * which is specified by @a doc into the line specified with @a line.
391 *
392 * @param msg_color A color to be used for the text. It must be an element of #MsgColors.
393 * @param line The document's line where the message belongs to. Set to @c -1 to ignore.
394 * @param doc @nullable The document. Set to @c NULL to ignore.
395 * @param format @c printf()-style format string.
396 * @param ... Arguments for the @c format string.
397 *
398 * @see msgwin_msg_add_string()
399 *
400 * @since 0.16
401 **/
402GEANY_API_SYMBOL
403void msgwin_msg_add(gint msg_color, gint line, GeanyDocument *doc, const gchar *format, ...)
404{
405 gchar *string;
406 va_list args;
407
408 va_start(args, format);
409 string = g_strdup_vprintf(format, args);
410 va_end(args);
411
412 msgwin_msg_add_string(msg_color, line, doc, string);
413 g_free(string);
414}
415
416
417/**
418 * Adds a new message in the messages tab treeview in the messages window.
419 *
420 * If @a line and @a doc are set, clicking on this line jumps into the
421 * file which is specified by @a doc into the line specified with @a line.
422 *
423 * @param msg_color A color to be used for the text. It must be an element of #MsgColors.
424 * @param line The document's line where the message belongs to. Set to @c -1 to ignore.
425 * @param doc @nullable The document. Set to @c NULL to ignore.
426 * @param string Message to be added.
427 *
428 * @see msgwin_msg_add()
429 *
430 * @since 1.34 (API 236)
431 **/
432GEANY_API_SYMBOL
433void msgwin_msg_add_string(gint msg_color, gint line, GeanyDocument *doc, const gchar *string)
434{
435 GtkTreeIter iter;
436 const GdkColor *color = get_color(msg_color);
437 gchar *tmp;
438 gsize len;
439 gchar *utf8_msg;
440
441 if (! ui_prefs.msgwindow_visible)
442 msgwin_show_hide(TRUE);
443
444 /* work around a strange problem when adding very long lines(greater than 4000 bytes)
445 * cut the string to a maximum of 1024 bytes and discard the rest */
446 /* TODO: find the real cause for the display problem / if it is GtkTreeView file a bug report */
447 len = strlen(string);
448 if (len > 1024)
449 tmp = g_strndup(string, 1024);
450 else
451 tmp = g_strdup(string);
452
453 if (! g_utf8_validate(tmp, -1, NULL))
454 utf8_msg = utils_get_utf8_from_locale(tmp);
455 else
456 utf8_msg = tmp;
457
458 gtk_list_store_append(msgwindow.store_msg, &iter);
459 gtk_list_store_set(msgwindow.store_msg, &iter,
461 color, MSG_COL_STRING, utf8_msg, -1);
462
463 g_free(tmp);
464 if (utf8_msg != tmp)
465 g_free(utf8_msg);
466}
467
468
469/**
470 * Logs a new status message *without* setting the status bar.
471 *
472 * Use @ref ui_set_statusbar() to display text on the statusbar.
473 *
474 * @param string Status message to be logged.
475 *
476 * @see msgwin_status_add()
477 *
478 * @since 1.34 (API 236)
479 **/
480GEANY_API_SYMBOL
481void msgwin_status_add_string(const gchar *string)
482{
483 GtkTreeIter iter;
484 gchar *statusmsg, *time_str;
485
486 /* add a timestamp to status messages */
487 time_str = utils_get_current_time_string(FALSE);
488 statusmsg = g_strconcat(time_str, ": ", string, NULL);
489 g_free(time_str);
490
491 /* add message to Status window */
492 gtk_list_store_append(msgwindow.store_status, &iter);
493 gtk_list_store_set(msgwindow.store_status, &iter, 0, statusmsg, -1);
494 g_free(statusmsg);
495
496 if (G_LIKELY(main_status.main_window_realized))
497 {
498 GtkTreePath *path = gtk_tree_model_get_path(gtk_tree_view_get_model(GTK_TREE_VIEW(msgwindow.tree_status)), &iter);
499
500 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(msgwindow.tree_status), path, NULL, FALSE, 0.0, 0.0);
502 gtk_notebook_set_current_page(GTK_NOTEBOOK(msgwindow.notebook), MSG_STATUS);
503 gtk_tree_path_free(path);
504 }
505}
506
507/**
508 * Logs a formatted status message *without* setting the status bar.
509 *
510 * Use @ref ui_set_statusbar() to display text on the statusbar.
511 *
512 * @param format @c printf()-style format string.
513 * @param ... Arguments for the @c format string.
514 *
515 * @see msgwin_status_add_string()
516 *
517 * @since 0.12
518 **/
519GEANY_API_SYMBOL
520void msgwin_status_add(const gchar *format, ...)
521{
522 gchar *string;
523 va_list args;
524
525 va_start(args, format);
526 string = g_strdup_vprintf(format, args);
527 va_end(args);
528
530 g_free(string);
531}
532
533
534static void
535on_message_treeview_clear_activate(GtkMenuItem *menuitem, gpointer user_data)
536{
537 gint tabnum = GPOINTER_TO_INT(user_data);
538
539 msgwin_clear_tab(tabnum);
540}
541
542
543static void
544on_compiler_treeview_copy_activate(GtkMenuItem *menuitem, gpointer user_data)
545{
546 GtkWidget *tv = NULL;
547 GtkTreeSelection *selection;
548 GtkTreeModel *model;
549 GtkTreeIter iter;
550 gint str_idx = COMPILER_COL_STRING;
551
552 switch (GPOINTER_TO_INT(user_data))
553 {
554 case MSG_STATUS:
555 tv = msgwindow.tree_status;
556 str_idx = 0;
557 break;
558
559 case MSG_COMPILER:
560 tv = msgwindow.tree_compiler;
561 break;
562
563 case MSG_MESSAGE:
564 tv = msgwindow.tree_msg;
565 str_idx = MSG_COL_STRING;
566 break;
567 }
568 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv));
569
570 if (gtk_tree_selection_get_selected(selection, &model, &iter))
571 {
572 gchar *string;
573
574 gtk_tree_model_get(model, &iter, str_idx, &string, -1);
575 if (!EMPTY(string))
576 {
577 gtk_clipboard_set_text(gtk_clipboard_get(gdk_atom_intern("CLIPBOARD", FALSE)),
578 string, -1);
579 }
580 g_free(string);
581 }
582}
583
584
585static void on_compiler_treeview_copy_all_activate(GtkMenuItem *menuitem, gpointer user_data)
586{
587 GtkListStore *store = msgwindow.store_compiler;
588 GtkTreeIter iter;
589 GString *str = g_string_new("");
590 gint str_idx = COMPILER_COL_STRING;
591 gboolean valid;
592
593 switch (GPOINTER_TO_INT(user_data))
594 {
595 case MSG_STATUS:
596 store = msgwindow.store_status;
597 str_idx = 0;
598 break;
599
600 case MSG_COMPILER:
601 /* default values */
602 break;
603
604 case MSG_MESSAGE:
605 store = msgwindow.store_msg;
606 str_idx = MSG_COL_STRING;
607 break;
608 }
609
610 /* walk through the list and copy every line into a string */
611 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
612 while (valid)
613 {
614 gchar *line;
615
616 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, str_idx, &line, -1);
617 if (!EMPTY(line))
618 {
619 g_string_append(str, line);
620 g_string_append_c(str, '\n');
621 }
622 g_free(line);
623
624 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
625 }
626
627 /* copy the string into the clipboard */
628 if (str->len > 0)
629 {
630 gtk_clipboard_set_text(
631 gtk_clipboard_get(gdk_atom_intern("CLIPBOARD", FALSE)),
632 str->str,
633 str->len);
634 }
635 g_string_free(str, TRUE);
636}
637
638
639static void
640on_hide_message_window(GtkMenuItem *menuitem, gpointer user_data)
641{
642 msgwin_show_hide(FALSE);
643}
644
645
646static GtkWidget *create_message_popup_menu(gint type)
647{
648 GtkWidget *message_popup_menu, *clear, *copy, *copy_all, *image;
649
650 message_popup_menu = gtk_menu_new();
651
652 clear = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLEAR, NULL);
653 gtk_widget_show(clear);
654 gtk_container_add(GTK_CONTAINER(message_popup_menu), clear);
655 g_signal_connect(clear, "activate",
656 G_CALLBACK(on_message_treeview_clear_activate), GINT_TO_POINTER(type));
657
658 copy = gtk_image_menu_item_new_with_mnemonic(_("C_opy"));
659 gtk_widget_show(copy);
660 gtk_container_add(GTK_CONTAINER(message_popup_menu), copy);
661 image = gtk_image_new_from_stock(GTK_STOCK_COPY, GTK_ICON_SIZE_MENU);
662 gtk_widget_show(image);
663 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(copy), image);
664 g_signal_connect(copy, "activate",
665 G_CALLBACK(on_compiler_treeview_copy_activate), GINT_TO_POINTER(type));
666
667 copy_all = gtk_image_menu_item_new_with_mnemonic(_("Copy _All"));
668 gtk_widget_show(copy_all);
669 gtk_container_add(GTK_CONTAINER(message_popup_menu), copy_all);
670 image = gtk_image_new_from_stock(GTK_STOCK_COPY, GTK_ICON_SIZE_MENU);
671 gtk_widget_show(image);
672 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(copy_all), image);
673 g_signal_connect(copy_all, "activate",
674 G_CALLBACK(on_compiler_treeview_copy_all_activate), GINT_TO_POINTER(type));
675
676 msgwin_menu_add_common_items(GTK_MENU(message_popup_menu));
677
678 return message_popup_menu;
679}
680
681
682static void on_scribble_populate(GtkTextView *textview, GtkMenu *arg1, gpointer user_data)
683{
685}
686
687
688/* Menu items that should be on all message window popup menus */
690{
691 GtkWidget *item;
692
693 item = gtk_separator_menu_item_new();
694 gtk_widget_show(item);
695 gtk_container_add(GTK_CONTAINER(menu), item);
696
697 item = gtk_menu_item_new_with_mnemonic(_("_Hide Message Window"));
698 gtk_widget_show(item);
699 gtk_container_add(GTK_CONTAINER(menu), item);
700 g_signal_connect(item, "activate", G_CALLBACK(on_hide_message_window), NULL);
701}
702
703
704/* look back up from the current path and find the directory we came from */
705static gboolean
706find_prev_build_dir(GtkTreePath *cur, GtkTreeModel *model, gchar **prefix)
707{
708 GtkTreeIter iter;
709 *prefix = NULL;
710
711 while (gtk_tree_path_prev(cur))
712 {
713 if (gtk_tree_model_get_iter(model, &iter, cur))
714 {
715 gchar *string;
716 gtk_tree_model_get(model, &iter, COMPILER_COL_STRING, &string, -1);
717 if (string != NULL && build_parse_make_dir(string, prefix))
718 {
719 g_free(string);
720 return TRUE;
721 }
722 g_free(string);
723 }
724 }
725
726 return FALSE;
727}
728
729
730static gboolean goto_compiler_file_line(const gchar *fname, gint line, gboolean focus_editor)
731{
732 gboolean ret = FALSE;
733 gchar *filename;
734
735 if (!fname || line <= -1)
736 return FALSE;
737
739
740 /* If the path doesn't exist, try the current document.
741 * This happens when we receive build messages in the wrong order - after the
742 * 'Leaving directory' messages */
743 if (!g_file_test(filename, G_FILE_TEST_EXISTS))
744 {
745 gchar *cur_dir = utils_get_current_file_dir_utf8();
746 gchar *name;
747
748 if (cur_dir)
749 {
750 /* we let the user know we couldn't find the parsed filename from the message window */
751 SETPTR(cur_dir, utils_get_locale_from_utf8(cur_dir));
752 name = g_path_get_basename(filename);
753 SETPTR(name, g_build_path(G_DIR_SEPARATOR_S, cur_dir, name, NULL));
754 g_free(cur_dir);
755
756 if (g_file_test(name, G_FILE_TEST_EXISTS))
757 {
758 ui_set_statusbar(FALSE, _("Could not find file '%s' - trying the current document path."),
759 fname);
761 }
762 else
763 g_free(name);
764 }
765 }
766
767 {
768 gchar *utf8_filename = utils_get_utf8_from_locale(filename);
769 GeanyDocument *doc = document_find_by_filename(utf8_filename);
771
772 g_free(utf8_filename);
773
774 if (doc == NULL) /* file not already open */
775 doc = document_open_file(filename, FALSE, NULL, NULL);
776
777 if (doc != NULL)
778 {
779 if (! doc->changed && editor_prefs.use_indicators) /* if modified, line may be wrong */
781
782 ret = navqueue_goto_line(old_doc, doc, line);
783 if (ret && focus_editor)
784 gtk_widget_grab_focus(GTK_WIDGET(doc->editor->sci));
785
786 ret = TRUE;
787 }
788 }
789
790 g_free(filename);
791
792 return ret;
793}
794
795
796gboolean msgwin_goto_compiler_file_line(gboolean focus_editor)
797{
798 GtkTreeIter iter;
799 GtkTreeModel *model;
800 GtkTreeSelection *selection;
801 gchar *string;
802 GdkColor *color;
803
804 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(msgwindow.tree_compiler));
805 if (gtk_tree_selection_get_selected(selection, &model, &iter))
806 {
807 /* if the item is not coloured red, it's not an error line */
808 gtk_tree_model_get(model, &iter, COMPILER_COL_COLOR, &color, -1);
809 if (color == NULL || ! gdk_color_equal(color, &color_error))
810 {
811 if (color != NULL)
812 gdk_color_free(color);
813 return FALSE;
814 }
815 gdk_color_free(color);
816
817 gtk_tree_model_get(model, &iter, COMPILER_COL_STRING, &string, -1);
818 if (string != NULL)
819 {
820 gint line;
821 gchar *filename, *dir;
822 GtkTreePath *path;
823 gboolean ret;
824
825 path = gtk_tree_model_get_path(model, &iter);
826 find_prev_build_dir(path, model, &dir);
827 gtk_tree_path_free(path);
829 g_free(string);
830 g_free(dir);
831
832 ret = goto_compiler_file_line(filename, line, focus_editor);
833 g_free(filename);
834 return ret;
835 }
836 }
837 return FALSE;
838}
839
840
841static void make_absolute(gchar **filename, const gchar *dir)
842{
843 guint skip_dot_slash = 0; /* number of characters to skip at the beginning of the filename */
844
845 if (*filename == NULL)
846 return;
847
848 /* skip some characters at the beginning of the filename, at the moment only "./"
849 * can be extended if other "trash" is known */
850 if (strncmp(*filename, "./", 2) == 0)
851 skip_dot_slash = 2;
852
853 /* add directory */
855 SETPTR(*filename, g_build_filename(dir, *filename + skip_dot_slash, NULL));
856}
857
858
859/* try to parse the file and line number where the error occurred described in line
860 * and when something useful is found, it stores the line number in *line and the
861 * relevant file with the error in *filename.
862 * *line will be -1 if no error was found in string.
863 * *filename must be freed unless it is NULL. */
864static void parse_file_line(ParseData *data, gchar **filename, gint *line)
865{
866 gchar *end = NULL;
867 gchar **fields;
868
869 *filename = NULL;
870 *line = -1;
871
872 g_return_if_fail(data->string != NULL);
873
874 fields = g_strsplit_set(data->string, data->pattern, data->min_fields);
875
876 /* parse the line */
877 if (g_strv_length(fields) < data->min_fields)
878 {
879 g_strfreev(fields);
880 return;
881 }
882
883 *line = strtol(fields[data->line_idx], &end, 10);
884
885 /* if the line could not be read, line is 0 and an error occurred, so we leave */
886 if (fields[data->line_idx] == end)
887 {
888 g_strfreev(fields);
889 return;
890 }
891
892 /* let's stop here if there is no filename in the error message */
893 if (data->file_idx == -1)
894 {
895 /* we have no filename in the error message, so take the current one and hope it's correct */
897 if (doc != NULL)
898 *filename = g_strdup(doc->file_name);
899 g_strfreev(fields);
900 return;
901 }
902
903 *filename = g_strdup(fields[data->file_idx]);
904 g_strfreev(fields);
905}
906
907
908static void parse_compiler_error_line(const gchar *string,
909 gchar **filename, gint *line)
910{
911 ParseData data = {NULL, NULL, 0, 0, 0};
912
913 data.string = string;
914
915 switch (build_info.file_type_id)
916 {
918 {
919 /* Parse error: parse error, unexpected T_CASE in brace_bug.php on line 3
920 * Parse error: syntax error, unexpected T_LNUMBER, expecting T_FUNCTION in bob.php on line 16 */
921 gchar *tmp = strstr(string, " in ");
922
923 if (tmp != NULL)
924 {
925 data.string = tmp;
926 data.pattern = " ";
927 data.min_fields = 6;
928 data.line_idx = 5;
929 data.file_idx = 2;
930 }
931 else
932 {
933 data.pattern = " ";
934 data.min_fields = 11;
935 data.line_idx = 10;
936 data.file_idx = 7;
937 }
938 break;
939 }
941 {
942 /* syntax error at test.pl line 7, near "{ */
943 data.pattern = " ";
944 data.min_fields = 6;
945 data.line_idx = 5;
946 data.file_idx = 3;
947 break;
948 }
949 /* the error output of python and tcl equals */
952 {
953 /* File "HyperArch.py", line 37, in ?
954 * (file "clrdial.tcl" line 12)
955 * */
956 if (strstr(string, " line ") != NULL)
957 {
958 /* Tcl and old Python format (<= Python 2.5) */
959 data.pattern = " \"";
960 data.min_fields = 6;
961 data.line_idx = 5;
962 data.file_idx = 2;
963 }
964 else
965 {
966 /* SyntaxError: ('invalid syntax', ('sender.py', 149, 20, ' ...'))
967 * (used since Python 2.6) */
968 data.pattern = ",'";
969 data.min_fields = 8;
970 data.line_idx = 6;
971 data.file_idx = 4;
972 }
973 break;
974 }
978 {
979 /* getdrive.bas(52) error 18: Syntax error in '? GetAllDrives'
980 * bandit.pas(149,3) Fatal: Syntax error, ";" expected but "ELSE" found */
981 data.pattern = "(";
982 data.min_fields = 2;
983 data.line_idx = 1;
984 data.file_idx = 0;
985 break;
986 }
988 {
989 /* GNU D compiler front-end, gdc
990 * gantry.d:18: variable gantry.main.c reference to auto class must be auto
991 * warning - gantry.d:20: statement is not reachable
992 * Digital Mars dmd compiler
993 * warning - pi.d(118): implicit conversion of expression (digit) of type int ...
994 * gantry.d(18): variable gantry.main.c reference to auto class must be auto */
995 if (strncmp(string, "warning - ", 10) == 0)
996 {
997 data.pattern = " (:";
998 data.min_fields = 4;
999 data.line_idx = 3;
1000 data.file_idx = 2;
1001 }
1002 else
1003 {
1004 data.pattern = "(:";
1005 data.min_fields = 2;
1006 data.line_idx = 1;
1007 data.file_idx = 0;
1008 }
1009 break;
1010 }
1012 {
1013 /* Error: Parse Error: on line 5 in "/tmp/hello.fe"
1014 * Error: Compile Error: on line 24, in /test/class.fe */
1015 if (strncmp(string, "Error: Compile Error", 20) == 0)
1016 {
1017 data.pattern = " ";
1018 data.min_fields = 8;
1019 data.line_idx = 5;
1020 data.file_idx = 7;
1021 }
1022 else
1023 {
1024 data.pattern = " \"";
1025 data.min_fields = 10;
1026 data.line_idx = 5;
1027 data.file_idx = 8;
1028 }
1029 break;
1030 }
1032 {
1033 /* line 78 column 7 - Warning: <table> missing '>' for end of tag */
1034 data.pattern = " ";
1035 data.min_fields = 4;
1036 data.line_idx = 1;
1037 data.file_idx = -1;
1038 break;
1039 }
1040 /* All GNU gcc-like error messages */
1041 case GEANY_FILETYPES_C:
1045 /* only gcc is supported, I don't know any other C(++) compilers and their error messages
1046 * empty.h:4: Warnung: type defaults to `int' in declaration of `foo'
1047 * empty.c:21: error: conflicting types for `foo'
1048 * Only parse file and line, so that linker errors will also work (with -g) */
1052 /* ./kommtechnik_2b.tex:18: Emergency stop. */
1053 case GEANY_FILETYPES_MAKE: /* Assume makefile is building with gcc */
1055 default: /* The default is a GNU gcc type error */
1056 {
1057 if (build_info.file_type_id == GEANY_FILETYPES_JAVA &&
1058 strncmp(string, "[javac]", 7) == 0)
1059 {
1060 /* Java Apache Ant.
1061 * [javac] <Full Path to File + extension>:<line n°>: <error> */
1062 data.pattern = " :";
1063 data.min_fields = 4;
1064 data.line_idx = 2;
1065 data.file_idx = 1;
1066 break;
1067 }
1068 /* don't accidentally find libtool versions x:y:x and think it is a file name */
1069 if (strstr(string, "libtool --mode=link") == NULL)
1070 {
1071 data.pattern = ":";
1072 data.min_fields = 3;
1073 data.line_idx = 1;
1074 data.file_idx = 0;
1075 break;
1076 }
1077 }
1078 }
1079
1080 if (data.pattern != NULL)
1081 parse_file_line(&data, filename, line);
1082}
1083
1084
1085/* try to parse the file and line number where the error occurred described in string
1086 * and when something useful is found, it stores the line number in *line and the
1087 * relevant file with the error in *filename.
1088 * *line will be -1 if no error was found in string.
1089 * *filename must be freed unless it is NULL. */
1090void msgwin_parse_compiler_error_line(const gchar *string, const gchar *dir,
1091 gchar **filename, gint *line)
1092{
1093 GeanyFiletype *ft;
1094 gchar *trimmed_string, *utf8_dir;
1095
1096 *filename = NULL;
1097 *line = -1;
1098
1099 if (G_UNLIKELY(string == NULL))
1100 return;
1101
1102 if (dir == NULL)
1103 utf8_dir = utils_get_utf8_from_locale(build_info.dir);
1104 else
1105 utf8_dir = g_strdup(dir);
1106 g_return_if_fail(utf8_dir != NULL);
1107
1108 trimmed_string = g_strdup(string);
1109 g_strchug(trimmed_string); /* remove possible leading whitespace */
1110
1111 ft = filetypes[build_info.file_type_id];
1112
1113 /* try parsing with a custom regex */
1114 if (!filetypes_parse_error_message(ft, trimmed_string, filename, line))
1115 {
1116 /* fallback to default old-style parsing */
1117 parse_compiler_error_line(trimmed_string, filename, line);
1118 }
1119 make_absolute(filename, utf8_dir);
1120 g_free(trimmed_string);
1121 g_free(utf8_dir);
1122}
1123
1124
1125/* Tries to parse strings of the file:line style, allowing line field to be missing
1126 * * filename is filled with the filename, should be freed
1127 * * line is filled with the line number or -1 */
1128static void msgwin_parse_generic_line(const gchar *string, gchar **filename, gint *line)
1129{
1130 gchar **fields;
1131 gboolean incertain = TRUE; /* whether we're reasonably certain of the result */
1132
1133 *filename = NULL;
1134 *line = -1;
1135
1136 fields = g_strsplit(string, ":", 2);
1137 /* extract the filename */
1138 if (fields[0] != NULL)
1139 {
1141 if (msgwindow.messages_dir != NULL)
1142 make_absolute(filename, msgwindow.messages_dir);
1143
1144 /* now the line */
1145 if (fields[1] != NULL)
1146 {
1147 gchar *end;
1148
1149 *line = strtol(fields[1], &end, 10);
1150 if (end == fields[1])
1151 *line = -1;
1152 else if (*end == ':' || g_ascii_isspace(*end))
1153 { /* if we have a blank or a separator right after the number, assume we really got a
1154 * filename (it's a grep-like syntax) */
1155 incertain = FALSE;
1156 }
1157 }
1158
1159 /* if we aren't sure we got a supposedly correct filename, check it */
1160 if (incertain && ! g_file_test(*filename, G_FILE_TEST_EXISTS))
1161 {
1162 SETPTR(*filename, NULL);
1163 *line = -1;
1164 }
1165 }
1166 g_strfreev(fields);
1167}
1168
1169
1170gboolean msgwin_goto_messages_file_line(gboolean focus_editor)
1171{
1172 GtkTreeIter iter;
1173 GtkTreeModel *model;
1174 GtkTreeSelection *selection;
1175 gboolean ret = FALSE;
1176
1177 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(msgwindow.tree_msg));
1178 if (gtk_tree_selection_get_selected(selection, &model, &iter))
1179 {
1180 gint line;
1181 guint id;
1182 gchar *string;
1183 GeanyDocument *doc;
1185
1186 gtk_tree_model_get(model, &iter,
1187 MSG_COL_LINE, &line, MSG_COL_DOC_ID, &id, MSG_COL_STRING, &string, -1);
1188 if (line >= 0 && id > 0)
1189 {
1190 /* check doc is still open */
1191 doc = document_find_by_id(id);
1192 if (!doc)
1193 {
1194 ui_set_statusbar(FALSE, _("The document has been closed."));
1195 utils_beep();
1196 }
1197 else
1198 {
1199 ret = navqueue_goto_line(old_doc, doc, line);
1200 if (ret && focus_editor)
1201 gtk_widget_grab_focus(GTK_WIDGET(doc->editor->sci));
1202 }
1203 }
1204 else if (line < 0 && string != NULL)
1205 {
1206 gchar *filename;
1207
1208 /* try with a file:line parsing */
1210 if (filename != NULL)
1211 {
1212 /* use document_open_file to find an already open file, or open it in place */
1213 doc = document_open_file(filename, FALSE, NULL, NULL);
1214 if (doc != NULL)
1215 {
1216 ret = (line < 0) ? TRUE : navqueue_goto_line(old_doc, doc, line);
1217 if (ret && focus_editor)
1218 gtk_widget_grab_focus(GTK_WIDGET(doc->editor->sci));
1219 }
1220 }
1221 g_free(filename);
1222 }
1223 g_free(string);
1224 }
1225 return ret;
1226}
1227
1228
1229static gboolean on_msgwin_button_press_event(GtkWidget *widget, GdkEventButton *event,
1230 gpointer user_data)
1231{
1232 /* user_data might be NULL, GPOINTER_TO_INT returns 0 if called with NULL */
1233 gboolean double_click = event->type == GDK_2BUTTON_PRESS;
1234
1235 if (event->button == 1 && (event->type == GDK_BUTTON_RELEASE || double_click))
1236 {
1237 switch (GPOINTER_TO_INT(user_data))
1238 {
1239 case MSG_COMPILER:
1240 { /* mouse click in the compiler treeview */
1241 msgwin_goto_compiler_file_line(double_click);
1242 break;
1243 }
1244 case MSG_MESSAGE:
1245 { /* mouse click in the message treeview (results of 'Find usage') */
1246 msgwin_goto_messages_file_line(double_click);
1247 break;
1248 }
1249 }
1250 return double_click; /* TRUE prevents message window re-focusing */
1251 }
1252
1253 if (event->button == 3)
1254 { /* popupmenu to hide or clear the active treeview */
1255 switch (GPOINTER_TO_INT(user_data))
1256 {
1257 case MSG_STATUS:
1258 {
1259 gtk_menu_popup(GTK_MENU(msgwindow.popup_status_menu), NULL, NULL, NULL, NULL,
1260 event->button, event->time);
1261 break;
1262 }
1263 case MSG_MESSAGE:
1264 {
1265 gtk_menu_popup(GTK_MENU(msgwindow.popup_msg_menu), NULL, NULL, NULL, NULL,
1266 event->button, event->time);
1267 break;
1268 }
1269 case MSG_COMPILER:
1270 {
1271 gtk_menu_popup(GTK_MENU(msgwindow.popup_compiler_menu), NULL, NULL, NULL, NULL,
1272 event->button, event->time);
1273 break;
1274 }
1275 }
1276 }
1277 return FALSE;
1278}
1279
1280
1281/**
1282 * Switches to the given notebook tab of the messages window.
1283 *
1284 * The messages window is shown if it was previously hidden and @a show is set to @c TRUE.
1285 *
1286 * @param tabnum An index of a tab in the messages window. Valid values are
1287 * all elements of #MessageWindowTabNum.
1288 * @param show Whether to show the messages window at all if it was hidden before.
1289 *
1290 * @since 0.15
1291 **/
1292GEANY_API_SYMBOL
1293void msgwin_switch_tab(gint tabnum, gboolean show)
1294{
1295 GtkWidget *widget = NULL; /* widget to focus */
1296
1297 switch (tabnum)
1298 {
1299 case MSG_SCRATCH: widget = msgwindow.scribble; break;
1300 case MSG_COMPILER: widget = msgwindow.tree_compiler; break;
1301 case MSG_STATUS: widget = msgwindow.tree_status; break;
1302 case MSG_MESSAGE: widget = msgwindow.tree_msg; break;
1303#ifdef HAVE_VTE
1304 case MSG_VTE: widget = (vte_info.have_vte) ? vc->vte : NULL; break;
1305#endif
1306 default: break;
1307 }
1308
1309 /* the msgwin must be visible before we switch to the VTE page so that
1310 * the font settings are applied on realization */
1311 if (show)
1312 msgwin_show_hide(TRUE);
1313 gtk_notebook_set_current_page(GTK_NOTEBOOK(msgwindow.notebook), tabnum);
1314 if (show && widget)
1315 gtk_widget_grab_focus(widget);
1316}
1317
1318
1319/**
1320 * Removes all messages from a tab specified by @a tabnum in the messages window.
1321 *
1322 * @param tabnum An index of a tab in the messages window which should be cleared.
1323 * Valid values are @c MSG_STATUS, @c MSG_COMPILER and @c MSG_MESSAGE.
1324 *
1325 * @since 0.15
1326 **/
1327GEANY_API_SYMBOL
1328void msgwin_clear_tab(gint tabnum)
1329{
1330 GtkListStore *store = NULL;
1331
1332 switch (tabnum)
1333 {
1334 case MSG_MESSAGE:
1335 store = msgwindow.store_msg;
1336 break;
1337
1338 case MSG_COMPILER:
1339 gtk_list_store_clear(msgwindow.store_compiler);
1340 build_menu_update(NULL); /* update next error items */
1341 return;
1342
1343 case MSG_STATUS: store = msgwindow.store_status; break;
1344 default: return;
1345 }
1346 if (store == NULL)
1347 return;
1348 gtk_list_store_clear(store);
1349}
GeanyBuildInfo build_info
Definition: build.c:67
gboolean build_parse_make_dir(const gchar *string, gchar **prefix)
Definition: build.c:1051
void build_menu_update(GeanyDocument *doc)
Definition: build.c:1457
Interface to the Build menu functionality.
gboolean ignore_callback
Definition: libmain.c:87
GeanyDocument * document_get_current(void)
Finds the current document.
Definition: document.c:371
const gchar * name
Definition: document.c:3219
GeanyDocument * document_find_by_filename(const gchar *utf8_filename)
Finds a document with the given filename.
Definition: document.c:183
GdkColor color
Definition: document.c:3220
GeanyDocument * document_open_file(const gchar *locale_filename, gboolean readonly, GeanyFiletype *ft, const gchar *forced_enc)
Opens a document specified by locale_filename.
Definition: document.c:908
GeanyDocument * document_find_by_id(guint id)
Lookup an old document by its ID.
Definition: document.c:247
Document related actions: new, save, open, etc.
void editor_indicator_set_on_line(GeanyEditor *editor, gint indic, gint line)
Sets an indicator indic on line.
Definition: editor.c:4175
GeanyEditorPrefs editor_prefs
Definition: editor.c:77
@ GEANY_INDICATOR_ERROR
Indicator to highlight errors in the document text.
Definition: editor.h:68
static void clear(void)
Definition: filebrowser.c:302
Filetype detection, file extensions and filetype menu items.
@ GEANY_FILETYPES_JAVA
Definition: filetypes.h:65
@ GEANY_FILETYPES_CS
Definition: filetypes.h:72
@ GEANY_FILETYPES_CPP
Definition: filetypes.h:80
@ GEANY_FILETYPES_PHP
Definition: filetypes.h:48
@ GEANY_FILETYPES_NONE
Definition: filetypes.h:46
@ GEANY_FILETYPES_PYTHON
Definition: filetypes.h:71
@ GEANY_FILETYPES_TCL
Definition: filetypes.h:60
@ GEANY_FILETYPES_PASCAL
Definition: filetypes.h:75
@ GEANY_FILETYPES_F77
Definition: filetypes.h:84
@ GEANY_FILETYPES_D
Definition: filetypes.h:86
@ GEANY_FILETYPES_C
Definition: filetypes.h:55
@ GEANY_FILETYPES_LATEX
Definition: filetypes.h:76
@ GEANY_FILETYPES_FERITE
Definition: filetypes.h:53
@ GEANY_FILETYPES_HTML
Definition: filetypes.h:70
@ GEANY_FILETYPES_PERL
Definition: filetypes.h:73
@ GEANY_FILETYPES_FORTRAN
Definition: filetypes.h:82
@ GEANY_FILETYPES_RUBY
Definition: filetypes.h:51
@ GEANY_FILETYPES_MAKE
Definition: filetypes.h:59
@ GEANY_FILETYPES_BASIC
Definition: filetypes.h:49
#define filetypes
Wraps GeanyData::filetypes_array so it can be used with C array syntax.
Definition: filetypes.h:178
vString * line
Definition: geany_cobol.c:133
CobolFormat format
Definition: geany_cobol.c:137
void keybindings_send_command(guint group_id, guint key_id)
Mimics a (built-in only) keybinding action.
Definition: keybindings.c:1426
Configurable keyboard shortcuts.
@ GEANY_KEY_GROUP_FOCUS
Group.
Definition: keybindings.h:113
@ GEANY_KEYS_FOCUS_EDITOR
Keybinding.
Definition: keybindings.h:194
GeanyStatus main_status
Definition: libmain.c:89
Main program-related commands.
void msgwin_switch_tab(gint tabnum, gboolean show)
Switches to the given notebook tab of the messages window.
Definition: msgwindow.c:1293
static gboolean goto_compiler_file_line(const gchar *fname, gint line, gboolean focus_editor)
Definition: msgwindow.c:730
void msgwin_status_add_string(const gchar *string)
Logs a new status message without setting the status bar.
Definition: msgwindow.c:481
static void prepare_status_tree_view(void)
Definition: msgwindow.c:198
void msgwin_clear_tab(gint tabnum)
Removes all messages from a tab specified by tabnum in the messages window.
Definition: msgwindow.c:1328
gboolean msgwin_goto_messages_file_line(gboolean focus_editor)
Definition: msgwindow.c:1170
static const GdkColor * get_color(gint msg_color)
Definition: msgwindow.c:296
static void load_color(const gchar *color_name, GdkColor *color)
Definition: msgwindow.c:121
@ COMPILER_COL_COUNT
Definition: msgwindow.c:81
@ COMPILER_COL_COLOR
Definition: msgwindow.c:79
@ COMPILER_COL_STRING
Definition: msgwindow.c:80
void msgwin_parse_compiler_error_line(const gchar *string, const gchar *dir, gchar **filename, gint *line)
Definition: msgwindow.c:1090
static void make_absolute(gchar **filename, const gchar *dir)
Definition: msgwindow.c:841
static void on_scribble_populate(GtkTextView *textview, GtkMenu *arg1, gpointer user_data)
Definition: msgwindow.c:682
void msgwin_show_hide_tabs(void)
Definition: msgwindow.c:99
void msgwin_set_messages_dir(const gchar *messages_dir)
Sets the Messages path for opening any parsed filenames without absolute path from message lines.
Definition: msgwindow.c:114
static gboolean on_msgwin_button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
Definition: msgwindow.c:1229
static gboolean on_msgwin_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
Definition: msgwindow.c:173
static void parse_compiler_error_line(const gchar *string, gchar **filename, gint *line)
Definition: msgwindow.c:908
static GdkColor color_context
Definition: msgwindow.c:86
void msgwin_show_hide(gboolean show)
Definition: msgwindow.c:372
static GdkColor color_message
Definition: msgwindow.c:87
void msgwin_compiler_add_string(gint msg_color, const gchar *msg)
Adds a new message in the compiler tab treeview in the messages window.
Definition: msgwindow.c:343
static void on_message_treeview_clear_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: msgwindow.c:535
void msgwin_finalize(void)
Definition: msgwindow.c:167
@ MSG_COL_COUNT
Definition: msgwindow.c:74
@ MSG_COL_LINE
Definition: msgwindow.c:70
@ MSG_COL_STRING
Definition: msgwindow.c:73
@ MSG_COL_COLOR
Definition: msgwindow.c:72
@ MSG_COL_DOC_ID
Definition: msgwindow.c:71
MessageWindow msgwindow
Definition: msgwindow.c:66
void msgwin_init(void)
Definition: msgwindow.c:142
void msgwin_msg_add(gint msg_color, gint line, GeanyDocument *doc, const gchar *format,...)
Adds a formatted message in the messages tab treeview in the messages window.
Definition: msgwindow.c:403
void msgwin_msg_add_string(gint msg_color, gint line, GeanyDocument *doc, const gchar *string)
Adds a new message in the messages tab treeview in the messages window.
Definition: msgwindow.c:433
static void on_hide_message_window(GtkMenuItem *menuitem, gpointer user_data)
Definition: msgwindow.c:640
void msgwin_status_add(const gchar *format,...)
Logs a formatted status message without setting the status bar.
Definition: msgwindow.c:520
static void on_compiler_treeview_copy_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: msgwindow.c:544
gboolean msgwin_goto_compiler_file_line(gboolean focus_editor)
Definition: msgwindow.c:796
static void msgwin_parse_generic_line(const gchar *string, gchar **filename, gint *line)
Definition: msgwindow.c:1128
static void prepare_msg_tree_view(void)
Definition: msgwindow.c:222
static void parse_file_line(ParseData *data, gchar **filename, gint *line)
Definition: msgwindow.c:864
void msgwin_menu_add_common_items(GtkMenu *menu)
Definition: msgwindow.c:689
static GtkWidget * create_message_popup_menu(gint type)
Definition: msgwindow.c:646
void msgwin_compiler_add(gint msg_color, const gchar *format,...)
Adds a formatted message in the compiler tab treeview in the messages window.
Definition: msgwindow.c:320
static gboolean find_prev_build_dir(GtkTreePath *cur, GtkTreeModel *model, gchar **prefix)
Definition: msgwindow.c:706
static void prepare_compiler_tree_view(void)
Definition: msgwindow.c:261
static void on_compiler_treeview_copy_all_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: msgwindow.c:585
static GdkColor color_error
Definition: msgwindow.c:85
Message window functions (status, compiler, messages windows).
@ MSG_COMPILER
Index of the compiler tab.
Definition: msgwindow.h:47
@ MSG_VTE
Index of the VTE tab.
Definition: msgwindow.h:50
@ MSG_STATUS
Index of the status message tab.
Definition: msgwindow.h:46
@ MSG_MESSAGE
Index of the messages tab.
Definition: msgwindow.h:48
@ MSG_SCRATCH
Index of the scratch tab.
Definition: msgwindow.h:49
@ COLOR_BLUE
Color blue.
Definition: msgwindow.h:39
@ COLOR_DARK_RED
Color dark red.
Definition: msgwindow.h:37
@ COLOR_RED
Color red.
Definition: msgwindow.h:36
gboolean navqueue_goto_line(GeanyDocument *old_doc, GeanyDocument *new_doc, gint line)
Adds old file position and new file position to the navqueue, then goes to the new position.
Definition: navqueue.c:151
Simple code navigation.
GeanyPrefs prefs
Definition: prefs.c:66
#define NULL
Definition: rbtree.h:150
char * strstr(const char *str, const char *substr)
Definition: routines.c:304
SidebarTreeviews tv
Definition: sidebar.c:50
gboolean filetypes_parse_error_message(GeanyFiletype *ft, const gchar *message, gchar **filename, gint *line)
Definition: filetypes.c:1272
const gchar filename[]
Definition: stash-example.c:4
gtk_container_add(GTK_CONTAINER(dialog->vbox), check_button)
Structure for representing an open tab with all its properties.
Definition: document.h:81
gchar * file_name
The UTF-8 encoded file name.
Definition: document.h:92
gboolean changed
Whether this document has been changed since it was last saved.
Definition: document.h:107
GeanyEditor * editor
The editor associated with the document.
Definition: document.h:98
guint id
A pseudo-unique ID for this document.
Definition: document.h:119
gboolean use_indicators
Definition: editor.h:113
ScintillaObject * sci
The Scintilla editor GtkWidget.
Definition: editor.h:152
Represents a filetype.
Definition: filetypes.h:144
gboolean compiler_tab_autoscroll
whether compiler messages window is automatically scrolled to show new messages
Definition: ui_utils.h:69
gboolean msgwin_status_visible
whether message window's status tab is visible
Definition: ui_utils.h:62
gchar * msgwin_font
message window font
Definition: ui_utils.h:51
gboolean msgwin_compiler_visible
whether message window's compiler tab is visible
Definition: ui_utils.h:63
gboolean msgwin_scribble_visible
whether message window's scribble tab is visible
Definition: ui_utils.h:65
gboolean msgwin_messages_visible
whether message window's messages tab is visible
Definition: ui_utils.h:64
GtkWidget * window
Main window.
Definition: ui_utils.h:80
GtkWidget * message_window_notebook
Message Window notebook.
Definition: ui_utils.h:89
gboolean switch_to_status
Definition: prefs.h:37
const gchar * pattern
Definition: msgwindow.c:59
guint min_fields
Definition: msgwindow.c:60
gint file_idx
Definition: msgwindow.c:62
const gchar * string
Definition: msgwindow.c:58
guint line_idx
Definition: msgwindow.c:61
Defines internationalization macros.
#define _(String)
Definition: support.h:42
void ui_widget_show_hide(GtkWidget *widget, gboolean show)
Definition: ui_utils.c:987
gboolean ui_is_keyval_enter_or_return(guint keyval)
Checks whether the passed keyval is the Enter or Return key.
Definition: ui_utils.c:3009
GeanyMainWidgets main_widgets
Definition: ui_utils.c:72
void ui_set_statusbar(gboolean log, const gchar *format,...)
Displays text on the statusbar.
Definition: ui_utils.c:168
UIPrefs ui_prefs
Definition: ui_utils.c:74
GtkWidget * ui_lookup_widget(GtkWidget *widget, const gchar *widget_name)
Returns a widget from a name in a component, usually created by Glade.
Definition: ui_utils.c:2743
void ui_widget_modify_font_from_string(GtkWidget *widget, const gchar *str)
Modifies the font of a widget using gtk_widget_modify_font().
Definition: ui_utils.c:1894
GeanyInterfacePrefs interface_prefs
Definition: ui_utils.c:71
User Interface general utility functions.
gchar * utils_get_utf8_from_locale(const gchar *locale_text)
Converts the given string (in locale encoding) into UTF-8 encoding.
Definition: utils.c:1272
gchar * utils_get_current_file_dir_utf8(void)
Definition: utils.c:897
void utils_beep(void)
Definition: utils.c:918
gchar * utils_get_current_time_string(gboolean include_microseconds)
Definition: utils.c:1019
gboolean utils_is_absolute_path(const gchar *path)
Definition: utils.c:432
gchar * utils_get_locale_from_utf8(const gchar *utf8_text)
Converts the given UTF-8 encoded string into locale encoding.
Definition: utils.c:1243
General utility functions, non-GTK related.
#define SETPTR(ptr, result)
Assigns result to ptr, then frees the old value.
Definition: utils.h:50
#define EMPTY(ptr)
Returns TRUE if ptr is NULL or *ptr is FALSE.
Definition: utils.h:38