~ubuntu-branches/ubuntu/jaunty/geany/jaunty

« back to all changes in this revision

Viewing changes to src/msgwindow.c

  • Committer: Bazaar Package Importer
  • Author(s): Gauvain Pocentek
  • Date: 2008-05-09 20:40:06 UTC
  • mfrom: (1.1.7 upstream) (3.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080509204006-9fu737rfvapfj7pn
Tags: 0.14-1ubuntu1
* Merge from debian unstable, remaining changes:
  - patches/20_add_debdiff_as_diff_type.dpatch:
    Also recognize .dpatch files as diff's
  - debian/geany.xpm:
    Replace icon with a .xpm of the new one
  - Modify Maintainer value to match the DebianMaintainerField
    specification.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 *      along with this program; if not, write to the Free Software
19
19
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
20
 *
21
 
 * $Id: msgwindow.c 2153 2008-01-09 13:36:22Z eht16 $
 
21
 * $Id: msgwindow.c 2434 2008-04-01 13:12:29Z ntrel $
22
22
 */
23
23
 
24
24
/*
41
41
#include "build.h"
42
42
#include "main.h"
43
43
#include "vte.h"
 
44
#include "navqueue.h"
44
45
 
45
46
#include <string.h>
46
47
#include <stdlib.h>
47
48
 
48
49
 
49
50
 
50
 
// used for parse_file_line
 
51
/* used for parse_file_line */
51
52
typedef struct
52
53
{
53
 
        const gchar *string;    // line data
54
 
        const gchar *dir;               // working directory when string was generated
55
 
        const gchar *pattern;   // pattern to split the error message into some fields
56
 
        guint min_fields;               // used to detect errors after parsing
57
 
        guint line_idx;                 // idx of the field where the line is
58
 
        gint file_idx;                  // idx of the field where the filename is or -1
 
54
        const gchar *string;    /* line data */
 
55
        const gchar *dir;               /* working directory when string was generated */
 
56
        const gchar *pattern;   /* pattern to split the error message into some fields */
 
57
        guint min_fields;               /* used to detect errors after parsing */
 
58
        guint line_idx;                 /* idx of the field where the line is */
 
59
        gint file_idx;                  /* idx of the field where the filename is or -1 */
59
60
} ParseData;
60
61
 
61
62
MessageWindow msgwindow;
133
134
        GtkTreeSelection *selection;
134
135
        PangoFontDescription *pfd;
135
136
 
136
 
        // doc idx, line, fg, str
 
137
        /* doc idx, line, fg, str */
137
138
        msgwindow.store_msg = gtk_list_store_new(4, G_TYPE_INT, G_TYPE_INT,
138
139
                GDK_TYPE_COLOR, G_TYPE_STRING);
139
140
        gtk_tree_view_set_model(GTK_TREE_VIEW(msgwindow.tree_msg), GTK_TREE_MODEL(msgwindow.store_msg));
149
150
        gtk_widget_modify_font(msgwindow.tree_msg, pfd);
150
151
        pango_font_description_free(pfd);
151
152
 
152
 
        // use button-release-event so the selection has changed (connect_after button-press-event doesn't work)
 
153
        /* use button-release-event so the selection has changed
 
154
         * (connect_after button-press-event doesn't work) */
153
155
        g_signal_connect(G_OBJECT(msgwindow.tree_msg), "button-release-event",
154
156
                                        G_CALLBACK(on_msgwin_button_press_event), GINT_TO_POINTER(MSG_MESSAGE));
155
157
 
156
 
        // selection handling
 
158
        /* selection handling */
157
159
        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(msgwindow.tree_msg));
158
160
        gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
159
 
        //g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(on_msg_tree_selection_changed), NULL);
 
161
        /*g_signal_connect(G_OBJECT(selection), "changed",G_CALLBACK(on_msg_tree_selection_changed), NULL);*/
160
162
}
161
163
 
162
164
 
181
183
        gtk_widget_modify_font(msgwindow.tree_compiler, pfd);
182
184
        pango_font_description_free(pfd);
183
185
 
184
 
        // use button-release-event so the selection has changed (connect_after button-press-event doesn't work)
 
186
        /* use button-release-event so the selection has changed
 
187
         * (connect_after button-press-event doesn't work) */
185
188
        g_signal_connect(G_OBJECT(msgwindow.tree_compiler), "button-release-event",
186
189
                                        G_CALLBACK(on_msgwin_button_press_event), GINT_TO_POINTER(MSG_COMPILER));
187
190
 
188
 
        // selection handling
 
191
        /* selection handling */
189
192
        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(msgwindow.tree_compiler));
190
193
        gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
191
 
        //g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(on_msg_tree_selection_changed), NULL);
 
194
        /*g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(on_msg_tree_selection_changed), NULL);*/
192
195
}
193
196
 
194
197
 
197
200
static const GdkColor *get_color(gint msg_color)
198
201
{
199
202
        static const GdkColor dark_red = {0, 65535 / 2, 0, 0};
200
 
        static const GdkColor blue = {0, 0, 0, 0xD000}; // not too bright ;-)
 
203
        static const GdkColor blue = {0, 0, 0, 0xD000}; /* not too bright ;-) */
201
204
        static const GdkColor black = {0, 0, 0, 0};
202
205
 
203
206
        switch (msg_color)
222
225
}
223
226
 
224
227
 
225
 
// adds string to the compiler textview
 
228
/* adds string to the compiler textview */
226
229
void msgwin_compiler_add(gint msg_color, const gchar *msg)
227
230
{
228
231
        GtkTreeIter iter;
240
243
                gtk_tree_path_free(path);
241
244
        }
242
245
 
243
 
        // calling build_menu_update for every build message would be overkill
 
246
        /* calling build_menu_update for every build message would be overkill */
244
247
        gtk_widget_set_sensitive(build_get_menu_items(-1)->item_next_error, TRUE);
245
248
}
246
249
 
270
273
}
271
274
 
272
275
 
273
 
// adds string to the msg treeview
 
276
/* adds string to the msg treeview */
274
277
void msgwin_msg_add(gint msg_color, gint line, gint idx, const gchar *string)
275
278
{
276
279
        GtkTreeIter iter;
279
282
 
280
283
        if (! ui_prefs.msgwindow_visible) msgwin_show_hide(TRUE);
281
284
 
282
 
        // work around a strange problem when adding very long lines(greater than 4000 bytes)
283
 
        // cut the string to a maximum of 1024 bytes and discard the rest
284
 
        /// TODO find the real cause for the display problem / if it is GtkTreeView file a bug report
 
285
        /* work around a strange problem when adding very long lines(greater than 4000 bytes)
 
286
         * cut the string to a maximum of 1024 bytes and discard the rest */
 
287
        /** TODO find the real cause for the display problem / if it is GtkTreeView file a bug report */
285
288
        if (strlen(string) > 1024)
286
289
                tmp = g_strndup(string, 1024);
287
290
        else
309
312
        g_vsnprintf(string, 512, format, args);
310
313
        va_end(args);
311
314
 
312
 
        // add a timestamp to status messages
 
315
        /* add a timestamp to status messages */
313
316
        time_str = utils_get_current_time_string();
314
317
        if (time_str == NULL)
315
318
                statusmsg = g_strdup(string);
317
320
                statusmsg = g_strconcat(time_str, ": ", string, NULL);
318
321
        g_free(time_str);
319
322
 
320
 
        // add message to Status window
 
323
        /* add message to Status window */
321
324
        gtk_list_store_append(msgwindow.store_status, &iter);
322
325
        gtk_list_store_set(msgwindow.store_status, &iter, 0, statusmsg, -1);
323
326
        g_free(statusmsg);
475
478
        gchar *string;
476
479
        gboolean ret = FALSE;
477
480
        GdkColor *color;
 
481
        gint old_idx = document_get_cur_idx();
478
482
 
479
483
        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(msgwindow.tree_compiler));
480
484
        if (gtk_tree_selection_get_selected(selection, &model, &iter))
481
485
        {
482
 
                // if the item is not coloured red, it's not an error line
 
486
                /* if the item is not coloured red, it's not an error line */
483
487
                gtk_tree_model_get(model, &iter, 0, &color, -1);
484
488
                if (! gdk_color_equal(color, &color_error))
485
489
                {
510
514
                                idx = document_find_by_filename(utf8_filename, FALSE);
511
515
                                g_free(utf8_filename);
512
516
 
513
 
                                if (idx < 0)    // file not already open
 
517
                                if (idx < 0)    /* file not already open */
514
518
                                        idx = document_open_file(filename, FALSE, NULL, NULL);
515
519
 
516
 
                                if (idx >= 0 && doc_list[idx].is_valid)
 
520
                                if (DOC_IDX_VALID(idx))
517
521
                                {
518
 
                                        if (! doc_list[idx].changed)    // if modified, line may be wrong
 
522
                                        if (! doc_list[idx].changed)    /* if modified, line may be wrong */
519
523
                                                document_set_indicator(idx, line - 1);
520
 
                                        ret = utils_goto_line(idx, line);
 
524
 
 
525
                                        ret = navqueue_goto_line(old_idx, idx, line);
521
526
                                }
522
527
                        }
523
528
                        g_free(filename);
537
542
{
538
543
        gchar *end = NULL;
539
544
        gchar **fields;
540
 
        guint skip_dot_slash = 0;       // number of characters to skip at the beginning of the filename
 
545
        guint skip_dot_slash = 0;       /* number of characters to skip at the beginning of the filename */
541
546
 
542
547
        *filename = NULL;
543
548
        *line = -1;
546
551
 
547
552
        fields = g_strsplit_set(data->string, data->pattern, data->min_fields);
548
553
 
549
 
        // parse the line
 
554
        /* parse the line */
550
555
        if (g_strv_length(fields) < data->min_fields)
551
556
        {
552
557
                g_strfreev(fields);
555
560
 
556
561
        *line = strtol(fields[data->line_idx], &end, 10);
557
562
 
558
 
        // if the line could not be read, line is 0 and an error occurred, so we leave
 
563
        /* if the line could not be read, line is 0 and an error occurred, so we leave */
559
564
        if (fields[data->line_idx] == end)
560
565
        {
561
566
                g_strfreev(fields);
562
567
                return;
563
568
        }
564
569
 
565
 
        // let's stop here if there is no filename in the error message
 
570
        /* let's stop here if there is no filename in the error message */
566
571
        if (data->file_idx == -1)
567
572
        {
568
 
                // we have no filename in the error message, so take the current one and hope it's correct
 
573
                /* we have no filename in the error message, so take the current one and hope it's correct */
569
574
                document *doc = document_get_current();
570
575
                if (doc != NULL)
571
576
                        *filename = g_strdup(doc->file_name);
573
578
                return;
574
579
        }
575
580
 
576
 
        // skip some characters at the beginning of the filename, at the moment only "./"
577
 
        // can be extended if other "trash" is known
 
581
        /* skip some characters at the beginning of the filename, at the moment only "./"
 
582
         * can be extended if other "trash" is known */
578
583
        if (strncmp(fields[data->file_idx], "./", 2) == 0) skip_dot_slash = 2;
579
584
 
580
 
        // get the build directory to get the path to look for other files
 
585
        /* get the build directory to get the path to look for other files */
581
586
        if (! utils_is_absolute_path(fields[data->file_idx]))
582
587
                *filename = g_strconcat(data->dir, G_DIR_SEPARATOR_S,
583
588
                        fields[data->file_idx] + skip_dot_slash, NULL);
595
600
 * *filename must be freed unless it is NULL. */
596
601
void msgwin_parse_compiler_error_line(const gchar *string, const gchar *dir, gchar **filename, gint *line)
597
602
{
598
 
        ParseData data = {string, build_info.dir, NULL, 0, 0, 0};
 
603
        ParseData data = {NULL, NULL, NULL, 0, 0, 0};
 
604
 
 
605
        data.string = string;
 
606
        data.dir = build_info.dir;
599
607
 
600
608
        *filename = NULL;
601
609
        *line = -1;
610
618
        {
611
619
                case GEANY_FILETYPES_PHP:
612
620
                {
613
 
                        // Parse error: parse error, unexpected T_CASE in brace_bug.php on line 3
614
 
                        // Parse error: syntax error, unexpected T_LNUMBER, expecting T_FUNCTION in bob.php on line 16
 
621
                        /* Parse error: parse error, unexpected T_CASE in brace_bug.php on line 3
 
622
                         * Parse error: syntax error, unexpected T_LNUMBER, expecting T_FUNCTION in bob.php on line 16 */
615
623
                        gchar *tmp = strstr(string, " in ");
616
624
 
617
625
                        if(tmp != NULL)
633
641
                }
634
642
                case GEANY_FILETYPES_PERL:
635
643
                {
636
 
                        // syntax error at test.pl line 7, near "{
 
644
                        /* syntax error at test.pl line 7, near "{ */
637
645
                        data.pattern = " ";
638
646
                        data.min_fields = 6;
639
647
                        data.line_idx = 5;
640
648
                        data.file_idx = 3;
641
649
                        break;
642
650
                }
643
 
                // the error output of python and tcl equals
 
651
                /* the error output of python and tcl equals */
644
652
                case GEANY_FILETYPES_TCL:
645
653
                case GEANY_FILETYPES_PYTHON:
646
654
                {
647
 
                        // File "HyperArch.py", line 37, in ?
648
 
                        // (file "clrdial.tcl" line 12)
 
655
                        /* File "HyperArch.py", line 37, in ?
 
656
                         * (file "clrdial.tcl" line 12) */
649
657
                        data.pattern = " \"";
650
658
                        data.min_fields = 6;
651
659
                        data.line_idx = 5;
655
663
                case GEANY_FILETYPES_BASIC:
656
664
                case GEANY_FILETYPES_PASCAL:
657
665
                {
658
 
                        // getdrive.bas(52) error 18: Syntax error in '? GetAllDrives'
659
 
                        // bandit.pas(149,3) Fatal: Syntax error, ";" expected but "ELSE" found
 
666
                        /* getdrive.bas(52) error 18: Syntax error in '? GetAllDrives'
 
667
                         * bandit.pas(149,3) Fatal: Syntax error, ";" expected but "ELSE" found */
660
668
                        data.pattern = "(";
661
669
                        data.min_fields = 2;
662
670
                        data.line_idx = 1;
665
673
                }
666
674
                case GEANY_FILETYPES_D:
667
675
                {
668
 
                        // GNU D compiler front-end, gdc
669
 
                        // gantry.d:18: variable gantry.main.c reference to auto class must be auto
670
 
                        // warning - gantry.d:20: statement is not reachable
671
 
                        // Digital Mars dmd compiler
672
 
                        // warning - pi.d(118): implicit conversion of expression (digit) of type int ...
673
 
                        // gantry.d(18): variable gantry.main.c reference to auto class must be auto
 
676
                        /* GNU D compiler front-end, gdc
 
677
                         * gantry.d:18: variable gantry.main.c reference to auto class must be auto
 
678
                         * warning - gantry.d:20: statement is not reachable
 
679
                         * Digital Mars dmd compiler
 
680
                         * warning - pi.d(118): implicit conversion of expression (digit) of type int ...
 
681
                         * gantry.d(18): variable gantry.main.c reference to auto class must be auto */
674
682
                        if (strncmp(string, "warning - ", 10) == 0)
675
683
                        {
676
684
                                data.pattern = " (:";
689
697
                }
690
698
                case GEANY_FILETYPES_FERITE:
691
699
                {
692
 
                        // Error: Parse Error: on line 5 in "/tmp/hello.fe"
693
 
                        // Error: Compile Error: on line 24, in /test/class.fe
 
700
                        /* Error: Parse Error: on line 5 in "/tmp/hello.fe"
 
701
                         * Error: Compile Error: on line 24, in /test/class.fe */
694
702
                        if (strncmp(string, "Error: Compile Error", 20) == 0)
695
703
                        {
696
704
                                data.pattern = " ";
709
717
                }
710
718
                case GEANY_FILETYPES_HTML:
711
719
                {
712
 
                        // line 78 column 7 - Warning: <table> missing '>' for end of tag
 
720
                        /* line 78 column 7 - Warning: <table> missing '>' for end of tag */
713
721
                        data.pattern = " ";
714
722
                        data.min_fields = 4;
715
723
                        data.line_idx = 1;
721
729
                case GEANY_FILETYPES_CPP:
722
730
                case GEANY_FILETYPES_RUBY:
723
731
                case GEANY_FILETYPES_JAVA:
724
 
                        // only gcc is supported, I don't know any other C(++) compilers and their error messages
725
 
                        // empty.h:4: Warnung: type defaults to `int' in declaration of `foo'
726
 
                        // empty.c:21: error: conflicting types for `foo'
727
 
                        // Only parse file and line, so that linker errors will also work (with -g)
 
732
                        /* only gcc is supported, I don't know any other C(++) compilers and their error messages
 
733
                         * empty.h:4: Warnung: type defaults to `int' in declaration of `foo'
 
734
                         * empty.c:21: error: conflicting types for `foo'
 
735
                         * Only parse file and line, so that linker errors will also work (with -g) */
728
736
                case GEANY_FILETYPES_FORTRAN:
729
737
                case GEANY_FILETYPES_LATEX:
730
 
                        // ./kommtechnik_2b.tex:18: Emergency stop.
731
 
                case GEANY_FILETYPES_MAKE:      // Assume makefile is building with gcc
 
738
                        /* ./kommtechnik_2b.tex:18: Emergency stop. */
 
739
                case GEANY_FILETYPES_MAKE:      /* Assume makefile is building with gcc */
732
740
                case GEANY_FILETYPES_ALL:
733
 
                default:        // The default is a GNU gcc type error
 
741
                default:        /* The default is a GNU gcc type error */
734
742
                {
735
743
                        if (build_info.file_type_id == GEANY_FILETYPES_JAVA &&
736
744
                                strncmp(string, "[javac]", 7) == 0)
743
751
                                data.file_idx = 1;
744
752
                                break;
745
753
                        }
746
 
                        // don't accidently find libtool versions x:y:x and think it is a file name
 
754
                        /* don't accidently find libtool versions x:y:x and think it is a file name */
747
755
                        if (strstr(string, "libtool --mode=link") == NULL)
748
756
                        {
749
757
                                data.pattern = ":";
770
778
        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(msgwindow.tree_msg));
771
779
        if (gtk_tree_selection_get_selected(selection, &model, &iter))
772
780
        {
773
 
                gint idx, line;
 
781
                gint idx, line, old_idx = document_get_cur_idx();
774
782
                gchar *string;
775
783
 
776
784
                gtk_tree_model_get(model, &iter, 0, &line, 1, &idx, 3, &string, -1);
777
785
                if (line >= 0 && idx >= 0)
778
786
                {
779
 
                        ret = utils_goto_line(idx, line);       // checks valid idx
 
787
                        if (DOC_IDX_VALID(idx))
 
788
                                ret = navqueue_goto_line(old_idx, idx, line);
780
789
                }
781
790
                else if (line < 0 && string != NULL)
782
791
                {
784
793
                        msgwin_parse_grep_line(string, &filename, &line);
785
794
                        if (filename != NULL && line > -1)
786
795
                        {
787
 
                                // use document_open_file to find an already open file, or open it in place
 
796
                                /* use document_open_file to find an already open file, or open it in place */
788
797
                                idx = document_open_file(filename, FALSE, NULL, NULL);
789
 
                                // utils_goto_file_line will check valid filename.
790
 
                                ret = utils_goto_file_line(filename, FALSE, line);
 
798
                                if (DOC_IDX_VALID(idx))
 
799
                                        ret = navqueue_goto_line(old_idx, idx, line);
791
800
                        }
792
801
                        g_free(filename);
793
802
                }
811
820
 
812
821
        if (string == NULL || msgwindow.find_in_files_dir == NULL) return;
813
822
 
814
 
        // conflict:3:conflicting types for `foo'
 
823
        /* conflict:3:conflicting types for `foo' */
815
824
        data.string = string;
816
825
        data.dir = msgwindow.find_in_files_dir;
817
826
        data.pattern = ":";
826
835
static gboolean on_msgwin_button_press_event(GtkWidget *widget, GdkEventButton *event,
827
836
                                                                                                                                                        gpointer user_data)
828
837
{
829
 
        // user_data might be NULL, GPOINTER_TO_INT returns 0 if called with NULL
 
838
        /* user_data might be NULL, GPOINTER_TO_INT returns 0 if called with NULL */
830
839
 
831
840
        if (event->button == 1)
832
841
        {
833
842
                switch (GPOINTER_TO_INT(user_data))
834
843
                {
835
844
                        case MSG_COMPILER:
836
 
                        {       // single click in the compiler treeview
 
845
                        {       /* single click in the compiler treeview */
837
846
                                msgwin_goto_compiler_file_line();
838
847
                                break;
839
848
                        }
840
849
                        case MSG_MESSAGE:
841
 
                        {       // single click in the message treeview (results of 'Find usage')
 
850
                        {       /* single click in the message treeview (results of 'Find usage') */
842
851
                                msgwin_goto_messages_file_line();
843
852
                                break;
844
853
                        }
846
855
        }
847
856
 
848
857
        if (event->button == 3)
849
 
        {       // popupmenu to hide or clear the active treeview
 
858
        {       /* popupmenu to hide or clear the active treeview */
850
859
                switch (GPOINTER_TO_INT(user_data))
851
860
                {
852
861
                        case MSG_STATUS:
875
884
 
876
885
void msgwin_switch_tab(MessageWindowTabNum tabnum, gboolean show)
877
886
{
878
 
        GtkWidget *widget = NULL;       // widget to focus
 
887
        GtkWidget *widget = NULL;       /* widget to focus */
879
888
 
880
889
        switch (tabnum)
881
890
        {