~ubuntu-branches/ubuntu/wily/geany/wily

« back to all changes in this revision

Viewing changes to src/document.c

  • Committer: Package Import Robot
  • Author(s): Chow Loong Jin
  • Date: 2011-12-10 07:43:26 UTC
  • mfrom: (3.3.7 sid)
  • Revision ID: package-import@ubuntu.com-20111210074326-s8yqbew5i20h33tf
Tags: 0.21-1ubuntu1
* Merge from Debian Unstable, remaining changes:
  - debian/patches/20_use_evince_viewer.patch:
     + use evince as viewer for pdf and dvi files
  - debian/patches/20_use_x_terminal_emulator.patch:
     + use x-terminal-emulator as terminal
  - debian/control
     + Add breaks on geany-plugins-common << 0.20
* Also fixes bugs:
  - Filter for MATLAB/Octave files filters everythign (LP: 885505)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 *      document.c - this file is part of Geany, a fast and lightweight IDE
3
3
 *
4
 
 *      Copyright 2005-2010 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
5
 
 *      Copyright 2006-2010 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
 
4
 *      Copyright 2005-2011 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
 
5
 *      Copyright 2006-2011 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
6
6
 *
7
7
 *      This program is free software; you can redistribute it and/or modify
8
8
 *      it under the terms of the GNU General Public License as published by
18
18
 *      along with this program; if not, write to the Free Software
19
19
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
20
 *
21
 
 * $Id: document.c 5466 2010-12-06 18:04:42Z ntrel $
 
21
 * $Id: document.c 5904 2011-08-25 20:15:02Z colombanw $
22
22
 */
23
23
 
24
24
/*
48
48
 
49
49
/* uncomment to use GIO based file monitoring, though it is not completely stable yet */
50
50
/*#define USE_GIO_FILEMON 1*/
51
 
#ifdef HAVE_GIO
52
 
# include <gio/gio.h>
53
 
#else
54
 
# if USE_GIO_FILEMON
55
 
#  undef USE_GIO_FILEMON
56
 
# endif
57
 
#endif
 
51
#include <gio/gio.h>
58
52
 
59
53
#include "document.h"
60
54
#include "documentprivate.h"
143
137
        {
144
138
                GeanyDocument *doc = documents[i];
145
139
 
146
 
                if (! doc->is_valid || G_UNLIKELY(! doc->real_path))
 
140
                if (! doc->is_valid || ! doc->real_path)
147
141
                        continue;
148
142
 
149
143
                if (filenamecmp(realname, doc->real_path) == 0)
191
185
        {
192
186
                doc = documents[i];
193
187
 
194
 
                if (! doc->is_valid || G_UNLIKELY(doc->file_name == NULL))
 
188
                if (! doc->is_valid || doc->file_name == NULL)
195
189
                        continue;
196
190
 
197
191
                if (filenamecmp(utf8_filename, doc->file_name) == 0)
313
307
                length = 30;
314
308
 
315
309
        base_name = g_path_get_basename(DOC_FILENAME(doc));
316
 
        short_name = utils_str_middle_truncate(base_name, length);
 
310
        short_name = utils_str_middle_truncate(base_name, (guint)length);
317
311
 
318
312
        g_free(base_name);
319
313
 
336
330
 
337
331
        gtk_label_set_text(GTK_LABEL(doc->priv->tab_label), short_name);
338
332
 
339
 
        ui_widget_set_tooltip_text(parent, DOC_FILENAME(doc));
 
333
        gtk_widget_set_tooltip_text(parent, DOC_FILENAME(doc));
340
334
 
341
335
        g_free(short_name);
342
336
}
395
389
        priv->undo_actions = NULL;
396
390
        priv->redo_actions = NULL;
397
391
        priv->line_count = 0;
398
 
#if ! defined(USE_GIO_FILEMON)
 
392
        priv->tag_list_update_source = 0;
 
393
#ifndef USE_GIO_FILEMON
399
394
        priv->last_check = time(NULL);
400
395
#endif
401
396
}
431
426
}
432
427
 
433
428
 
434
 
#if USE_GIO_FILEMON
 
429
#ifdef USE_GIO_FILEMON
435
430
static void monitor_file_changed_cb(G_GNUC_UNUSED GFileMonitor *monitor, G_GNUC_UNUSED GFile *file,
436
431
                                                                        G_GNUC_UNUSED GFile *other_file, GFileMonitorEvent event,
437
432
                                                                        GeanyDocument *doc)
490
485
         * doesn't work at all for remote files and legacy polling is too slow. */
491
486
        if (! doc->priv->is_remote)
492
487
        {
493
 
#if USE_GIO_FILEMON
 
488
#ifdef USE_GIO_FILEMON
494
489
                gchar *locale_filename;
495
490
 
496
491
                /* stop any previous monitoring */
780
775
        editor_goto_pos(doc->editor, 0, FALSE);
781
776
        document_try_focus(doc, NULL);
782
777
 
783
 
#if USE_GIO_FILEMON
 
778
#ifdef USE_GIO_FILEMON
784
779
        monitor_file_setup(doc);
785
780
#else
786
781
        doc->priv->mtime = time(NULL);
819
814
typedef struct
820
815
{
821
816
        gchar           *data;  /* null-terminated file data */
822
 
        gsize            size;  /* actual file size on disk */
823
817
        gsize            len;   /* string length of data */
824
818
        gchar           *enc;
825
819
        gboolean         bom;
828
822
} FileData;
829
823
 
830
824
 
831
 
/* reload file with specified encoding */
832
 
static gboolean
833
 
handle_forced_encoding(FileData *filedata, const gchar *forced_enc)
834
 
{
835
 
        GeanyEncodingIndex enc_idx;
836
 
 
837
 
        if (utils_str_equal(forced_enc, "UTF-8"))
838
 
        {
839
 
                if (! g_utf8_validate(filedata->data, filedata->len, NULL))
840
 
                {
841
 
                        return FALSE;
842
 
                }
843
 
        }
844
 
        else
845
 
        {
846
 
                gchar *converted_text = encodings_convert_to_utf8_from_charset(
847
 
                                                                                filedata->data, filedata->size, forced_enc, FALSE);
848
 
                if (converted_text == NULL)
849
 
                {
850
 
                        return FALSE;
851
 
                }
852
 
                else
853
 
                {
854
 
                        g_free(filedata->data);
855
 
                        filedata->data = converted_text;
856
 
                        filedata->len = strlen(converted_text);
857
 
                }
858
 
        }
859
 
        enc_idx = encodings_scan_unicode_bom(filedata->data, filedata->size, NULL);
860
 
        filedata->bom = (enc_idx == GEANY_ENCODING_UTF_8);
861
 
        filedata->enc = g_strdup(forced_enc);
862
 
        return TRUE;
863
 
}
864
 
 
865
 
 
866
 
/* detect encoding and convert to UTF-8 if necessary */
867
 
static gboolean
868
 
handle_encoding(FileData *filedata, GeanyEncodingIndex enc_idx)
869
 
{
870
 
        g_return_val_if_fail(filedata->enc == NULL, FALSE);
871
 
        g_return_val_if_fail(filedata->bom == FALSE, FALSE);
872
 
 
873
 
        if (filedata->size == 0)
874
 
        {
875
 
                /* we have no data so assume UTF-8, filedata->len can be 0 even we have an empty
876
 
                 * e.g. UTF32 file with a BOM(so size is 4, len is 0) */
877
 
                filedata->enc = g_strdup("UTF-8");
878
 
        }
879
 
        else
880
 
        {
881
 
                /* first check for a BOM */
882
 
                if (enc_idx != GEANY_ENCODING_NONE)
883
 
                {
884
 
                        filedata->enc = g_strdup(encodings[enc_idx].charset);
885
 
                        filedata->bom = TRUE;
886
 
 
887
 
                        if (enc_idx != GEANY_ENCODING_UTF_8) /* the BOM indicated something else than UTF-8 */
888
 
                        {
889
 
                                gchar *converted_text = encodings_convert_to_utf8_from_charset(
890
 
                                                                                filedata->data, filedata->size, filedata->enc, FALSE);
891
 
                                if (converted_text != NULL)
892
 
                                {
893
 
                                        g_free(filedata->data);
894
 
                                        filedata->data = converted_text;
895
 
                                        filedata->len = strlen(converted_text);
896
 
                                }
897
 
                                else
898
 
                                {
899
 
                                        /* there was a problem converting data from BOM encoding type */
900
 
                                        g_free(filedata->enc);
901
 
                                        filedata->enc = NULL;
902
 
                                        filedata->bom = FALSE;
903
 
                                }
904
 
                        }
905
 
                }
906
 
 
907
 
                if (filedata->enc == NULL)      /* either there was no BOM or the BOM encoding failed */
908
 
                {
909
 
                        /* try UTF-8 first */
910
 
                        if ((filedata->size == filedata->len) &&
911
 
                                g_utf8_validate(filedata->data, filedata->len, NULL))
912
 
                        {
913
 
                                filedata->enc = g_strdup("UTF-8");
914
 
                        }
915
 
                        else
916
 
                        {
917
 
                                /* detect the encoding */
918
 
                                gchar *converted_text = encodings_convert_to_utf8(filedata->data,
919
 
                                        filedata->size, &filedata->enc);
920
 
 
921
 
                                if (converted_text == NULL)
922
 
                                {
923
 
                                        return FALSE;
924
 
                                }
925
 
                                g_free(filedata->data);
926
 
                                filedata->data = converted_text;
927
 
                                filedata->len = strlen(converted_text);
928
 
                        }
929
 
                }
930
 
        }
931
 
        return TRUE;
932
 
}
933
 
 
934
 
 
935
 
static void
936
 
handle_bom(FileData *filedata)
937
 
{
938
 
        guint bom_len;
939
 
 
940
 
        encodings_scan_unicode_bom(filedata->data, filedata->size, &bom_len);
941
 
        g_return_if_fail(bom_len != 0);
942
 
 
943
 
        /* use filedata->len here because the contents are already converted into UTF-8 */
944
 
        filedata->len -= bom_len;
945
 
        /* overwrite the BOM with the remainder of the file contents, plus the NULL terminator. */
946
 
        g_memmove(filedata->data, filedata->data + bom_len, filedata->len + 1);
947
 
        filedata->data = g_realloc(filedata->data, filedata->len + 1);
948
 
}
949
 
 
950
 
 
951
825
/* loads textfile data, verifies and converts to forced_enc or UTF-8. Also handles BOM. */
952
826
static gboolean load_text_file(const gchar *locale_filename, const gchar *display_filename,
953
827
        FileData *filedata, const gchar *forced_enc)
954
828
{
955
829
        GError *err = NULL;
956
830
        struct stat st;
957
 
        GeanyEncodingIndex tmp_enc_idx;
958
831
 
959
832
        filedata->data = NULL;
960
833
        filedata->len = 0;
978
851
                return FALSE;
979
852
        }
980
853
 
981
 
        /* use strlen to check for null chars */
982
 
        filedata->size = (gsize) st.st_size;
983
 
        filedata->len = strlen(filedata->data);
984
 
 
985
 
        /* temporarily retrieve the encoding idx based on the BOM to suppress the following warning
986
 
         * if we have a BOM */
987
 
        tmp_enc_idx = encodings_scan_unicode_bom(filedata->data, filedata->size, NULL);
988
 
 
989
 
        /* check whether the size of the loaded data is equal to the size of the file in the
990
 
         * filesystem file size may be 0 to allow opening files in /proc/ which have typically a
991
 
         * file size of 0 bytes */
992
 
        if (filedata->len != filedata->size && filedata->size != 0 && (
993
 
                tmp_enc_idx == GEANY_ENCODING_UTF_8 || /* tmp_enc_idx can be UTF-7/8/16/32, UCS and None */
994
 
                tmp_enc_idx == GEANY_ENCODING_UTF_7))  /* filter UTF-7/8 where no NULL bytes are allowed */
 
854
        filedata->len = (gsize) st.st_size;
 
855
        if (! encodings_convert_to_utf8_auto(&filedata->data, &filedata->len, forced_enc,
 
856
                                &filedata->enc, &filedata->bom, &filedata->readonly))
 
857
        {
 
858
                if (forced_enc)
 
859
                {
 
860
                        ui_set_statusbar(TRUE, _("The file \"%s\" is not valid %s."),
 
861
                                display_filename, forced_enc);
 
862
                }
 
863
                else
 
864
                {
 
865
                        ui_set_statusbar(TRUE,
 
866
        _("The file \"%s\" does not look like a text file or the file encoding is not supported."),
 
867
                        display_filename);
 
868
                }
 
869
                g_free(filedata->data);
 
870
                return FALSE;
 
871
        }
 
872
 
 
873
        if (filedata->readonly)
995
874
        {
996
875
                const gchar *warn_msg = _(
997
876
                        "The file \"%s\" could not be opened properly and has been truncated. " \
1002
881
                        dialogs_show_msgbox(GTK_MESSAGE_WARNING, warn_msg, display_filename);
1003
882
 
1004
883
                ui_set_statusbar(TRUE, warn_msg, display_filename);
1005
 
 
1006
 
                /* set the file to read-only mode because saving it is probably dangerous */
1007
 
                filedata->readonly = TRUE;
1008
 
        }
1009
 
 
1010
 
        /* Determine character encoding and convert to UTF-8 */
1011
 
        if (forced_enc != NULL)
1012
 
        {
1013
 
                /* the encoding should be ignored(requested by user), so open the file "as it is" */
1014
 
                if (utils_str_equal(forced_enc, encodings[GEANY_ENCODING_NONE].charset))
1015
 
                {
1016
 
                        filedata->bom = FALSE;
1017
 
                        filedata->enc = g_strdup(encodings[GEANY_ENCODING_NONE].charset);
1018
 
                }
1019
 
                else if (! handle_forced_encoding(filedata, forced_enc))
1020
 
                {
1021
 
                        /* For translators: the second wildcard is an encoding name, e.g.
1022
 
                         * The file \"test.txt\" is not valid UTF-8. */
1023
 
                        ui_set_statusbar(TRUE, _("The file \"%s\" is not valid %s."),
1024
 
                                display_filename, forced_enc);
1025
 
                        utils_beep();
1026
 
                        g_free(filedata->data);
1027
 
                        return FALSE;
1028
 
                }
1029
 
        }
1030
 
        else if (! handle_encoding(filedata, tmp_enc_idx))
1031
 
        {
1032
 
                ui_set_statusbar(TRUE,
1033
 
        _("The file \"%s\" does not look like a text file or the file encoding is not supported."),
1034
 
                        display_filename);
1035
 
                utils_beep();
1036
 
                g_free(filedata->data);
1037
 
                return FALSE;
1038
 
        }
1039
 
 
1040
 
        if (filedata->bom)
1041
 
                handle_bom(filedata);
 
884
        }
 
885
 
1042
886
        return TRUE;
1043
887
}
1044
888
 
1082
926
        ScintillaObject *sci = editor->sci;
1083
927
        gsize count = 0;
1084
928
        struct Sci_TextToFind ttf;
1085
 
        gchar *soft_tab = g_strnfill(iprefs->width, ' ');
 
929
        gchar *soft_tab = g_strnfill((gsize)iprefs->width, ' ');
1086
930
        gchar *regex = g_strconcat("^\t+", soft_tab, "[^ ]", NULL);
1087
931
 
1088
932
        g_free(soft_tab);
1106
950
}
1107
951
 
1108
952
 
1109
 
/* Detect the indent type based on counting the leading indent characters for each line. */
1110
 
static GeanyIndentType detect_indent_type(GeanyEditor *editor)
 
953
/* Detect the indent type based on counting the leading indent characters for each line.
 
954
 * Returns whether detection succeeded, and the detected type in *type_ upon success */
 
955
gboolean document_detect_indent_type(GeanyDocument *doc, GeanyIndentType *type_)
1111
956
{
1112
 
        const GeanyIndentPrefs *iprefs = editor_get_indent_prefs(editor);
 
957
        GeanyEditor *editor = doc->editor;
1113
958
        ScintillaObject *sci = editor->sci;
1114
 
        guint line, line_count;
 
959
        gint line, line_count;
1115
960
        gsize tabs = 0, spaces = 0;
1116
961
 
1117
962
        if (detect_tabs_and_spaces(editor))
1118
 
                return GEANY_INDENT_TYPE_BOTH;
 
963
        {
 
964
                *type_ = GEANY_INDENT_TYPE_BOTH;
 
965
                return TRUE;
 
966
        }
1119
967
 
1120
968
        line_count = sci_get_line_count(sci);
1121
969
        for (line = 0; line < line_count; line++)
1131
979
                c = sci_get_char_at(sci, pos);
1132
980
                if (c == '\t')
1133
981
                        tabs++;
1134
 
                else
1135
 
                if (c == ' ')
1136
 
                {
1137
 
                        /* check for at least 2 spaces */
1138
 
                        if (sci_get_char_at(sci, pos + 1) == ' ')
1139
 
                                spaces++;
1140
 
                }
 
982
                /* check for at least 2 spaces */
 
983
                else if (c == ' ' && sci_get_char_at(sci, pos + 1) == ' ')
 
984
                        spaces++;
1141
985
        }
1142
986
        if (spaces == 0 && tabs == 0)
1143
 
                return iprefs->type;
 
987
                return FALSE;
1144
988
 
1145
989
        /* the factors may need to be tweaked */
1146
990
        if (spaces > tabs * 4)
1147
 
                return GEANY_INDENT_TYPE_SPACES;
 
991
                *type_ = GEANY_INDENT_TYPE_SPACES;
1148
992
        else if (tabs > spaces * 4)
1149
 
                return GEANY_INDENT_TYPE_TABS;
 
993
                *type_ = GEANY_INDENT_TYPE_TABS;
1150
994
        else
1151
 
                return GEANY_INDENT_TYPE_BOTH;
 
995
                *type_ = GEANY_INDENT_TYPE_BOTH;
 
996
 
 
997
        return TRUE;
 
998
}
 
999
 
 
1000
 
 
1001
/* Detect the indent width based on counting the leading indent characters for each line.
 
1002
 * Returns whether detection succeeded, and the detected width in *width_ upon success */
 
1003
static gboolean detect_indent_width(GeanyEditor *editor, GeanyIndentType type, gint *width_)
 
1004
{
 
1005
        const GeanyIndentPrefs *iprefs = editor_get_indent_prefs(editor);
 
1006
        ScintillaObject *sci = editor->sci;
 
1007
        gint line, line_count;
 
1008
        gint widths[7] = { 0 }; /* width can be from 2 to 8 */
 
1009
        gint count, width, i;
 
1010
 
 
1011
        /* can't easily detect the supposed width of a tab, guess the default is OK */
 
1012
        if (type == GEANY_INDENT_TYPE_TABS)
 
1013
                return FALSE;
 
1014
 
 
1015
        /* force 8 at detection time for tab & spaces -- anyway we don't use tabs at this point */
 
1016
        sci_set_tab_width(sci, 8);
 
1017
 
 
1018
        line_count = sci_get_line_count(sci);
 
1019
        for (line = 0; line < line_count; line++)
 
1020
        {
 
1021
                width = sci_get_line_indentation(sci, line);
 
1022
                /* most code will have indent total <= 24, otherwise it's more likely to be
 
1023
                 * alignment than indentation */
 
1024
                if (width > 24)
 
1025
                        continue;
 
1026
                /* < 2 is no indentation */
 
1027
                if (width < 2)
 
1028
                        continue;
 
1029
 
 
1030
                for (i = G_N_ELEMENTS(widths) - 1; i >= 0; i--)
 
1031
                {
 
1032
                        if ((width % (i + 2)) == 0)
 
1033
                                widths[i]++;
 
1034
                }
 
1035
        }
 
1036
        count = 0;
 
1037
        width = iprefs->width;
 
1038
        for (i = G_N_ELEMENTS(widths) - 1; i >= 0; i--)
 
1039
        {
 
1040
                /* give large indents higher weight not to be fooled by spurious indents */
 
1041
                if (widths[i] >= count * 1.5)
 
1042
                {
 
1043
                        width = i + 2;
 
1044
                        count = widths[i];
 
1045
                }
 
1046
        }
 
1047
 
 
1048
        if (count == 0)
 
1049
                return FALSE;
 
1050
 
 
1051
        *width_ = width;
 
1052
        return TRUE;
 
1053
}
 
1054
 
 
1055
 
 
1056
/* same as detect_indent_width() but uses editor's indent type */
 
1057
gboolean document_detect_indent_width(GeanyDocument *doc, gint *width_)
 
1058
{
 
1059
        return detect_indent_width(doc->editor, doc->editor->indent_type, width_);
1152
1060
}
1153
1061
 
1154
1062
 
1156
1064
{
1157
1065
        const GeanyIndentPrefs *iprefs = editor_get_indent_prefs(NULL);
1158
1066
        GeanyIndentType type = iprefs->type;
1159
 
 
1160
 
        switch (doc->file_type->id)
1161
 
        {
1162
 
                case GEANY_FILETYPES_MAKE:
1163
 
                        /* force using tabs for indentation for Makefiles */
1164
 
                        editor_set_indent(doc->editor, GEANY_INDENT_TYPE_TABS, iprefs->width);
1165
 
                        return;
1166
 
                case GEANY_FILETYPES_F77:
1167
 
                        /* force using spaces for indentation for Fortran 77 */
1168
 
                        editor_set_indent(doc->editor, GEANY_INDENT_TYPE_SPACES, iprefs->width);
1169
 
                        return;
1170
 
                default:
1171
 
                        break;
1172
 
        }
1173
 
        if (iprefs->detect_type)
1174
 
        {
1175
 
                type = detect_indent_type(doc->editor);
1176
 
 
 
1067
        gint width = iprefs->width;
 
1068
 
 
1069
        if (iprefs->detect_type && document_detect_indent_type(doc, &type))
 
1070
        {
1177
1071
                if (type != iprefs->type)
1178
1072
                {
1179
1073
                        const gchar *name = NULL;
1196
1090
                                DOC_FILENAME(doc));
1197
1091
                }
1198
1092
        }
1199
 
        editor_set_indent(doc->editor, type, iprefs->width);
1200
 
}
1201
 
 
1202
 
 
1203
 
#if 0
1204
 
static gboolean auto_update_tag_list(gpointer data)
1205
 
{
1206
 
        GeanyDocument *doc = data;
1207
 
 
1208
 
        if (! doc || ! doc->is_valid || doc->tm_file == NULL)
1209
 
                return FALSE;
1210
 
 
1211
 
        if (gtk_window_get_focus(GTK_WINDOW(main_widgets.window)) != GTK_WIDGET(doc->editor->sci))
1212
 
                return TRUE;
1213
 
 
1214
 
        if (update_tags_from_buffer(doc))
1215
 
                sidebar_update_tag_list(doc, TRUE);
1216
 
 
1217
 
        return TRUE;
1218
 
}
1219
 
#endif
 
1093
        else if (doc->file_type->indent_type > -1)
 
1094
                type = doc->file_type->indent_type;
 
1095
 
 
1096
        if (iprefs->detect_width && detect_indent_width(doc->editor, type, &width))
 
1097
        {
 
1098
                if (width != iprefs->width)
 
1099
                {
 
1100
                        ui_set_statusbar(TRUE, _("Setting indentation width to %d for %s."), width,
 
1101
                                DOC_FILENAME(doc));
 
1102
                }
 
1103
        }
 
1104
        else if (doc->file_type->indent_width > -1)
 
1105
                width = doc->file_type->indent_width;
 
1106
 
 
1107
        editor_set_indent(doc->editor, type, width);
 
1108
}
1220
1109
 
1221
1110
 
1222
1111
/* To open a new file, set doc to NULL; filename should be locale encoded.
1356
1245
                if (! main_status.opening_session_files)
1357
1246
                        ui_add_recent_file(utf8_filename);
1358
1247
 
1359
 
                if (! reload)
 
1248
                if (reload)
 
1249
                {
 
1250
                        g_signal_emit_by_name(geany_object, "document-reload", doc);
 
1251
                        ui_set_statusbar(TRUE, _("File %s reloaded."), display_filename);
 
1252
                }
 
1253
                else
 
1254
                {
1360
1255
                        g_signal_emit_by_name(geany_object, "document-open", doc);
1361
 
 
1362
 
                if (reload)
1363
 
                        ui_set_statusbar(TRUE, _("File %s reloaded."), display_filename);
1364
 
                else
1365
1256
                        /* For translators: this is the status window message for opening a file. %d is the number
1366
1257
                         * of the newly opened file, %s indicates whether the file is opened read-only
1367
1258
                         * (it is replaced with the string ", read-only"). */
1368
1259
                        msgwin_status_add(_("File %s opened(%d%s)."),
1369
1260
                                display_filename, gtk_notebook_get_n_pages(GTK_NOTEBOOK(main_widgets.notebook)),
1370
1261
                                (readonly) ? _(", read-only") : "");
 
1262
                }
1371
1263
        }
1372
1264
 
1373
1265
        g_free(display_filename);
1374
1266
        g_free(utf8_filename);
1375
1267
        g_free(locale_filename);
1376
1268
 
1377
 
        /* TODO This could be used to automatically update the symbol list,
1378
 
         * based on a configurable interval */
1379
 
        /*g_timeout_add(10000, auto_update_tag_list, doc);*/
1380
 
 
1381
1269
        /* set the cursor position according to pos, cl_options.goto_line and cl_options.goto_column */
1382
1270
        pos = set_cursor_position(doc->editor, pos);
1383
1271
        /* now bring the file in front */
1391
1279
 
1392
1280
 
1393
1281
/* Takes a new line separated list of filename URIs and opens each file.
1394
 
 * length is the length of the string or -1 if it should be detected */
1395
 
void document_open_file_list(const gchar *data, gssize length)
 
1282
 * length is the length of the string */
 
1283
void document_open_file_list(const gchar *data, gsize length)
1396
1284
{
1397
 
        gint i;
 
1285
        guint i;
1398
1286
        gchar *filename;
1399
1287
        gchar **list;
1400
1288
 
1401
1289
        g_return_if_fail(data != NULL);
1402
1290
 
1403
 
        if (length < 0)
1404
 
                length = strlen(data);
1405
 
 
1406
 
        switch (utils_get_line_endings(data, length))
1407
 
        {
1408
 
                case SC_EOL_CR: list = g_strsplit(data, "\r", 0); break;
1409
 
                case SC_EOL_CRLF: list = g_strsplit(data, "\r\n", 0); break;
1410
 
                case SC_EOL_LF: list = g_strsplit(data, "\n", 0); break;
1411
 
                default: list = g_strsplit(data, "\n", 0);
1412
 
        }
1413
 
 
1414
 
        for (i = 0; ; i++)
1415
 
        {
1416
 
                if (list[i] == NULL)
1417
 
                        break;
 
1291
        list = g_strsplit(data, utils_get_eol_char(utils_get_line_endings(data, length)), 0);
 
1292
 
 
1293
        for (i = 0; list[i] != NULL; i++)
 
1294
        {
1418
1295
                filename = g_filename_from_uri(list[i], NULL, NULL);
1419
1296
                if (G_UNLIKELY(filename == NULL))
1420
1297
                        continue;
1473
1350
 
1474
1351
static gboolean document_update_timestamp(GeanyDocument *doc, const gchar *locale_filename)
1475
1352
{
1476
 
#if ! USE_GIO_FILEMON
 
1353
#ifndef USE_GIO_FILEMON
1477
1354
        struct stat st;
1478
1355
 
1479
1356
        g_return_val_if_fail(doc != NULL, FALSE);
1714
1591
{
1715
1592
        GError *error = NULL;
1716
1593
 
1717
 
        if (! file_prefs.use_safe_file_saving)
1718
 
        {
1719
 
#ifdef HAVE_GIO
 
1594
        if (file_prefs.use_safe_file_saving)
 
1595
        {
 
1596
                /* Use old GLib API for safe saving (GVFS-safe, but alters ownership and permissons).
 
1597
                 * This is the only option that handles disk space exhaustion. */
 
1598
                if (g_file_set_contents(locale_filename, data, len, &error))
 
1599
                        geany_debug("Wrote %s with g_file_set_contents().", locale_filename);
 
1600
        }
 
1601
        else if (file_prefs.use_gio_unsafe_file_saving)
 
1602
        {
1720
1603
                GFile *fp;
1721
1604
 
1722
 
                /* Use GIO API to save file (GVFS-safe) */
 
1605
                /* Use GIO API to save file (GVFS-safe)
 
1606
                 * It is best in most GVFS setups but don't seem to work correctly on some more complex
 
1607
                 * setups (saving from some VM to their host, over some SMB shares, etc.) */
1723
1608
                fp = g_file_new_for_path(locale_filename);
1724
1609
                g_file_replace_contents(fp, data, len, NULL, file_prefs.gio_unsafe_save_backup,
1725
1610
                        G_FILE_CREATE_NONE, NULL, NULL, &error);
1726
1611
                g_object_unref(fp);
1727
 
#else
 
1612
        }
 
1613
        else
 
1614
        {
1728
1615
                FILE *fp;
1729
1616
                int save_errno;
1730
1617
                gchar *display_name = g_filename_display_name(locale_filename);
1779
1666
                }
1780
1667
 
1781
1668
                g_free(display_name);
1782
 
#endif
1783
 
        }
1784
 
        else
1785
 
        {
1786
 
                /* Use old GLib API for safe saving (GVFS-safe, but alters ownership and permissons).
1787
 
                 * This is the only option that handles disk space exhaustion. */
1788
 
                if (g_file_set_contents(locale_filename, data, len, &error))
1789
 
                        geany_debug("Wrote %s with g_file_set_contents().", locale_filename);
1790
1669
        }
1791
1670
        if (error != NULL)
1792
1671
        {
1968
1847
/* special search function, used from the find entry in the toolbar
1969
1848
 * return TRUE if text was found otherwise FALSE
1970
1849
 * return also TRUE if text is empty  */
1971
 
gboolean document_search_bar_find(GeanyDocument *doc, const gchar *text, gint flags, gboolean inc)
 
1850
gboolean document_search_bar_find(GeanyDocument *doc, const gchar *text, gint flags, gboolean inc,
 
1851
                gboolean backwards)
1972
1852
{
1973
1853
        gint start_pos, search_pos;
1974
1854
        struct Sci_TextToFind ttf;
1978
1858
        if (! *text)
1979
1859
                return TRUE;
1980
1860
 
1981
 
        start_pos = (inc) ? sci_get_selection_start(doc->editor->sci) :
 
1861
        start_pos = (inc || backwards) ? sci_get_selection_start(doc->editor->sci) :
1982
1862
                sci_get_selection_end(doc->editor->sci);        /* equal if no selection */
1983
1863
 
1984
 
        /* search cursor to end */
 
1864
        /* search cursor to end or start */
1985
1865
        ttf.chrg.cpMin = start_pos;
1986
 
        ttf.chrg.cpMax = sci_get_length(doc->editor->sci);
 
1866
        ttf.chrg.cpMax = backwards ? 0 : sci_get_length(doc->editor->sci);
1987
1867
        ttf.lpstrText = (gchar *)text;
1988
1868
        search_pos = sci_find_text(doc->editor->sci, flags, &ttf);
1989
1869
 
1990
 
        /* if no match, search start to cursor */
 
1870
        /* if no match, search start (or end) to cursor */
1991
1871
        if (search_pos == -1)
1992
1872
        {
1993
 
                ttf.chrg.cpMin = 0;
1994
 
                ttf.chrg.cpMax = start_pos + strlen(text);
 
1873
                if (backwards)
 
1874
                {
 
1875
                        ttf.chrg.cpMin = sci_get_length(doc->editor->sci);
 
1876
                        ttf.chrg.cpMax = start_pos;
 
1877
                }
 
1878
                else
 
1879
                {
 
1880
                        ttf.chrg.cpMin = 0;
 
1881
                        ttf.chrg.cpMax = start_pos + strlen(text);
 
1882
                }
1995
1883
                search_pos = sci_find_text(doc->editor->sci, flags, &ttf);
1996
1884
        }
1997
1885
 
2030
1918
 
2031
1919
/* General search function, used from the find dialog.
2032
1920
 * Returns -1 on failure or the start position of the matching text.
2033
 
 * Will skip past any selection, ignoring it. */
2034
 
gint document_find_text(GeanyDocument *doc, const gchar *text, gint flags, gboolean search_backwards,
2035
 
                gboolean scroll, GtkWidget *parent)
 
1921
 * Will skip past any selection, ignoring it.
 
1922
 *
 
1923
 * @param text Text to find.
 
1924
 * @param original_text Text as it was entered by user, or @c NULL to use @c text
 
1925
 */
 
1926
gint document_find_text(GeanyDocument *doc, const gchar *text, const gchar *original_text,
 
1927
                gint flags, gboolean search_backwards, gboolean scroll, GtkWidget *parent)
2036
1928
{
2037
1929
        gint selection_end, selection_start, search_pos;
2038
1930
 
2044
1936
        if (flags & SCFIND_REGEXP)
2045
1937
                search_backwards = FALSE;
2046
1938
 
 
1939
        if (!original_text)
 
1940
                original_text = text;
 
1941
 
2047
1942
        selection_start = sci_get_selection_start(doc->editor->sci);
2048
1943
        selection_end = sci_get_selection_end(doc->editor->sci);
2049
1944
        if ((selection_end - selection_start) > 0)
2076
1971
                if ((selection_end == 0 && ! search_backwards) ||
2077
1972
                        (selection_end == sci_len && search_backwards))
2078
1973
                {
2079
 
                        ui_set_statusbar(FALSE, _("\"%s\" was not found."), text);
 
1974
                        ui_set_statusbar(FALSE, _("\"%s\" was not found."), original_text);
2080
1975
                        utils_beep();
2081
1976
                        return -1;
2082
1977
                }
2084
1979
                /* we searched only part of the document, so ask whether to wraparound. */
2085
1980
                if (search_prefs.suppress_dialogs ||
2086
1981
                        dialogs_show_question_full(parent, GTK_STOCK_FIND, GTK_STOCK_CANCEL,
2087
 
                                _("Wrap search and find again?"), _("\"%s\" was not found."), text))
 
1982
                                _("Wrap search and find again?"), _("\"%s\" was not found."), original_text))
2088
1983
                {
2089
1984
                        gint ret;
2090
1985
 
2091
1986
                        sci_set_current_position(doc->editor->sci, (search_backwards) ? sci_len : 0, FALSE);
2092
 
                        ret = document_find_text(doc, text, flags, search_backwards, scroll, parent);
 
1987
                        ret = document_find_text(doc, text, original_text, flags, search_backwards, scroll, parent);
2093
1988
                        if (ret == -1)
2094
1989
                        {       /* return to original cursor position if not found */
2095
1990
                                sci_set_current_position(doc->editor->sci, selection_start, FALSE);
2102
1997
 
2103
1998
 
2104
1999
/* Replaces the selection if it matches, otherwise just finds the next match.
2105
 
 * Returns: start of replaced text, or -1 if no replacement was made */
2106
 
gint document_replace_text(GeanyDocument *doc, const gchar *find_text, const gchar *replace_text,
2107
 
                gint flags, gboolean search_backwards)
 
2000
 * Returns: start of replaced text, or -1 if no replacement was made
 
2001
 *
 
2002
 * @param find_text Text to find.
 
2003
 * @param original_find_text Text to find as it was entered by user, or @c NULL to use @c find_text
 
2004
 */
 
2005
gint document_replace_text(GeanyDocument *doc, const gchar *find_text, const gchar *original_find_text,
 
2006
                const gchar *replace_text, gint flags, gboolean search_backwards)
2108
2007
{
2109
2008
        gint selection_end, selection_start, search_pos;
2110
2009
 
2117
2016
        if (flags & SCFIND_REGEXP)
2118
2017
                search_backwards = FALSE;
2119
2018
 
 
2019
        if (!original_find_text)
 
2020
                original_find_text = find_text;
 
2021
 
2120
2022
        selection_start = sci_get_selection_start(doc->editor->sci);
2121
2023
        selection_end = sci_get_selection_end(doc->editor->sci);
2122
2024
        if (selection_end == selection_start)
2123
2025
        {
2124
2026
                /* no selection so just find the next match */
2125
 
                document_find_text(doc, find_text, flags, search_backwards, TRUE, NULL);
 
2027
                document_find_text(doc, find_text, original_find_text, flags, search_backwards, TRUE, NULL);
2126
2028
                return -1;
2127
2029
        }
2128
2030
        /* there's a selection so go to the start before finding to search through it
2132
2034
        else
2133
2035
                sci_goto_pos(doc->editor->sci, selection_start, TRUE);
2134
2036
 
2135
 
        search_pos = document_find_text(doc, find_text, flags, search_backwards, TRUE, NULL);
 
2037
        search_pos = document_find_text(doc, find_text, original_find_text, flags, search_backwards, TRUE, NULL);
2136
2038
        /* return if the original selected text did not match (at the start of the selection) */
2137
2039
        if (search_pos != selection_start)
2138
2040
                return -1;
2156
2058
}
2157
2059
 
2158
2060
 
2159
 
static void show_replace_summary(GeanyDocument *doc, gint count, const gchar *find_text,
2160
 
                const gchar *replace_text, gboolean escaped_chars)
 
2061
static void show_replace_summary(GeanyDocument *doc, gint count, const gchar *original_find_text,
 
2062
        const gchar *original_replace_text)
2161
2063
{
2162
 
        gchar *escaped_find_text, *escaped_replace_text, *filename;
 
2064
        gchar *filename;
2163
2065
 
2164
2066
        if (count == 0)
2165
2067
        {
2166
 
                ui_set_statusbar(FALSE, _("No matches found for \"%s\"."), find_text);
 
2068
                ui_set_statusbar(FALSE, _("No matches found for \"%s\"."), original_find_text);
2167
2069
                return;
2168
2070
        }
2169
2071
 
2170
2072
        filename = g_path_get_basename(DOC_FILENAME(doc));
2171
 
 
2172
 
        if (escaped_chars)
2173
 
        {       /* escape special characters for showing */
2174
 
                escaped_find_text = g_strescape(find_text, NULL);
2175
 
                escaped_replace_text = g_strescape(replace_text, NULL);
2176
 
                ui_set_statusbar(TRUE, ngettext(
2177
 
                        "%s: replaced %d occurrence of \"%s\" with \"%s\".",
2178
 
                        "%s: replaced %d occurrences of \"%s\" with \"%s\".",
2179
 
                        count), filename, count, escaped_find_text, escaped_replace_text);
2180
 
                g_free(escaped_find_text);
2181
 
                g_free(escaped_replace_text);
2182
 
        }
2183
 
        else
2184
 
        {
2185
 
                ui_set_statusbar(TRUE, ngettext(
2186
 
                        "%s: replaced %d occurrence of \"%s\" with \"%s\".",
2187
 
                        "%s: replaced %d occurrences of \"%s\" with \"%s\".",
2188
 
                        count), filename, count, find_text, replace_text);
2189
 
        }
 
2073
        ui_set_statusbar(TRUE, ngettext(
 
2074
                "%s: replaced %d occurrence of \"%s\" with \"%s\".",
 
2075
                "%s: replaced %d occurrences of \"%s\" with \"%s\".",
 
2076
                count), filename, count, original_find_text, original_replace_text);
2190
2077
        g_free(filename);
2191
2078
}
2192
2079
 
2236
2123
 
2237
2124
 
2238
2125
void document_replace_sel(GeanyDocument *doc, const gchar *find_text, const gchar *replace_text,
2239
 
                                                  gint flags, gboolean escaped_chars)
 
2126
                                                  const gchar *original_find_text, const gchar *original_replace_text, gint flags)
2240
2127
{
2241
2128
        gint selection_end, selection_start, selection_mode, selected_lines, last_line = 0;
2242
2129
        gint max_column = 0, count = 0;
2333
2220
        else /* no replacements */
2334
2221
                utils_beep();
2335
2222
 
2336
 
        show_replace_summary(doc, count, find_text, replace_text, escaped_chars);
 
2223
        show_replace_summary(doc, count, original_find_text, original_replace_text);
2337
2224
}
2338
2225
 
2339
2226
 
2340
2227
/* returns number of replacements made. */
2341
2228
gint document_replace_all(GeanyDocument *doc, const gchar *find_text, const gchar *replace_text,
2342
 
                gint flags, gboolean escaped_chars)
 
2229
                const gchar *original_find_text, const gchar *original_replace_text, gint flags)
2343
2230
{
2344
2231
        gint len, count;
2345
2232
        g_return_val_if_fail(doc != NULL && find_text != NULL && replace_text != NULL, FALSE);
2351
2238
        count = document_replace_range(
2352
2239
                        doc, find_text, replace_text, flags, 0, len, TRUE, NULL);
2353
2240
 
2354
 
        show_replace_summary(doc, count, find_text, replace_text, escaped_chars);
 
2241
        show_replace_summary(doc, count, original_find_text, original_replace_text);
2355
2242
        return count;
2356
2243
}
2357
2244
 
2359
2246
static gboolean update_tags_from_buffer(GeanyDocument *doc)
2360
2247
{
2361
2248
        gboolean result;
2362
 
#if 1
 
2249
#if 0
2363
2250
                /* old code */
2364
2251
                result = tm_source_file_update(doc->tm_file, TRUE, FALSE, TRUE);
2365
2252
#else
2427
2314
}
2428
2315
 
2429
2316
 
 
2317
static gboolean on_document_update_tag_list_idle(gpointer data)
 
2318
{
 
2319
        GeanyDocument *doc = data;
 
2320
 
 
2321
        if (! DOC_VALID(doc))
 
2322
                return FALSE;
 
2323
 
 
2324
        if (! main_status.quitting)
 
2325
                document_update_tag_list(doc, TRUE);
 
2326
 
 
2327
        doc->priv->tag_list_update_source = 0;
 
2328
        return FALSE;
 
2329
}
 
2330
 
 
2331
 
 
2332
void document_update_tag_list_in_idle(GeanyDocument *doc)
 
2333
{
 
2334
        if (editor_prefs.autocompletion_update_freq <= 0 || ! filetype_has_tags(doc->file_type))
 
2335
                return;
 
2336
 
 
2337
        if (doc->priv->tag_list_update_source != 0)
 
2338
                g_source_remove(doc->priv->tag_list_update_source);
 
2339
        doc->priv->tag_list_update_source = g_timeout_add_full(G_PRIORITY_LOW,
 
2340
                editor_prefs.autocompletion_update_freq, on_document_update_tag_list_idle, doc, NULL);
 
2341
}
 
2342
 
 
2343
 
2430
2344
/* Caches the list of project typenames, as a space separated GString.
2431
2345
 * Returns: TRUE if typenames have changed.
2432
2346
 * (*types) is set to the list of typenames, or NULL if there are none. */
2585
2499
 
2586
2500
        if (ft_changed)
2587
2501
        {
 
2502
                const GeanyIndentPrefs *iprefs = editor_get_indent_prefs(NULL);
 
2503
 
 
2504
                /* assume that if previous filetype was none and the settings are the default ones, this
 
2505
                 * is the first time the filetype is carefully set, so we should apply indent settings */
 
2506
                if (old_ft && old_ft->id == GEANY_FILETYPES_NONE &&
 
2507
                        doc->editor->indent_type == iprefs->type &&
 
2508
                        doc->editor->indent_width == iprefs->width)
 
2509
                {
 
2510
                        document_apply_indent_settings(doc);
 
2511
                        ui_document_show_hide(doc);
 
2512
                }
 
2513
 
2588
2514
                sidebar_openfiles_update(doc); /* to update the icon */
2589
2515
                g_signal_emit_by_name(geany_object, "document-filetype-set", doc, old_ft);
2590
2516
        }
2861
2787
{
2862
2788
        static GdkColor red = {0, 0xFFFF, 0, 0};
2863
2789
        static GdkColor green = {0, 0, 0x7FFF, 0};
2864
 
#if USE_GIO_FILEMON
 
2790
#ifdef USE_GIO_FILEMON
2865
2791
        static GdkColor orange = {0, 0xFFFF, 0x7FFF, 0};
2866
2792
#endif
2867
2793
        GdkColor *color = NULL;
2870
2796
 
2871
2797
        if (doc->changed)
2872
2798
                color = &red;
2873
 
#if USE_GIO_FILEMON
 
2799
#ifdef USE_GIO_FILEMON
2874
2800
        else if (doc->priv->file_disk_status == FILE_CHANGED)
2875
2801
                color = &orange;
2876
2802
#endif
3084
3010
                /* doc may be closed now */
3085
3011
                ret = TRUE;
3086
3012
        }
3087
 
        else if (! use_gio_filemon && /* ignore these checks when using GIO */
3088
 
                         (G_UNLIKELY(doc->priv->mtime > cur_time) || G_UNLIKELY(st.st_mtime > cur_time)))
 
3013
        else if (G_UNLIKELY(! use_gio_filemon && /* ignore these checks when using GIO */
 
3014
                         (doc->priv->mtime > cur_time || st.st_mtime > cur_time)))
3089
3015
        {
3090
3016
                g_warning("%s: Something is wrong with the time stamps.", G_STRFUNC);
3091
3017
        }
3109
3035
}
3110
3036
 
3111
3037
 
 
3038
/** Compares documents by their display names.
 
3039
 * This matches @c GCompareFunc for use with e.g. @c g_ptr_array_sort().
 
3040
 * @note 'Display name' means the base name of the document's filename.
 
3041
 *
 
3042
 * @param a @c GeanyDocument**.
 
3043
 * @param b @c GeanyDocument**.
 
3044
 * @warning The arguments take the address of each document pointer.
 
3045
 * @return Negative value if a < b; zero if a = b; positive value if a > b.
 
3046
 *
 
3047
 * @since 0.21
 
3048
 */
 
3049
gint document_compare_by_display_name(gconstpointer a, gconstpointer b)
 
3050
{
 
3051
        GeanyDocument *doc_a = *((GeanyDocument**) a);
 
3052
        GeanyDocument *doc_b = *((GeanyDocument**) b);
 
3053
        gchar *base_name_a, *base_name_b;
 
3054
        gint result;
 
3055
 
 
3056
        base_name_a = g_path_get_basename(DOC_FILENAME(doc_a));
 
3057
        base_name_b = g_path_get_basename(DOC_FILENAME(doc_b));
 
3058
 
 
3059
        result = strcmp(base_name_a, base_name_b);
 
3060
 
 
3061
        g_free(base_name_a);
 
3062
        g_free(base_name_b);
 
3063
 
 
3064
        return result;
 
3065
}
 
3066
 
 
3067
 
 
3068
/** Compares documents by their tab order.
 
3069
 * This matches @c GCompareFunc for use with e.g. @c g_ptr_array_sort().
 
3070
 *
 
3071
 * @param a @c GeanyDocument**.
 
3072
 * @param b @c GeanyDocument**.
 
3073
 * @warning The arguments take the address of each document pointer.
 
3074
 * @return Negative value if a < b; zero if a = b; positive value if a > b.
 
3075
 *
 
3076
 * @since 0.21 (GEANY_API_VERSION 209)
 
3077
 */
 
3078
gint document_compare_by_tab_order(gconstpointer a, gconstpointer b)
 
3079
{
 
3080
        GeanyDocument *doc_a = *((GeanyDocument**) a);
 
3081
        GeanyDocument *doc_b = *((GeanyDocument**) b);
 
3082
        gint notebook_position_doc_a;
 
3083
        gint notebook_position_doc_b;
 
3084
 
 
3085
        notebook_position_doc_a = document_get_notebook_page(doc_a);
 
3086
        notebook_position_doc_b = document_get_notebook_page(doc_b);
 
3087
 
 
3088
        if (notebook_position_doc_a < notebook_position_doc_b)
 
3089
                return -1;
 
3090
        if (notebook_position_doc_a > notebook_position_doc_b)
 
3091
                return 1;
 
3092
        /* equality */
 
3093
        return 0;
 
3094
}
 
3095
 
 
3096
 
 
3097
/** Compares documents by their tab order, in reverse order.
 
3098
 * This matches @c GCompareFunc for use with e.g. @c g_ptr_array_sort().
 
3099
 *
 
3100
 * @param a @c GeanyDocument**.
 
3101
 * @param b @c GeanyDocument**.
 
3102
 * @warning The arguments take the address of each document pointer.
 
3103
 * @return Negative value if a < b; zero if a = b; positive value if a > b.
 
3104
 *
 
3105
 * @since 0.21 (GEANY_API_VERSION 209)
 
3106
 */
 
3107
gint document_compare_by_tab_order_reverse(gconstpointer a, gconstpointer b)
 
3108
{
 
3109
        GeanyDocument *doc_a = *((GeanyDocument**) a);
 
3110
        GeanyDocument *doc_b = *((GeanyDocument**) b);
 
3111
        gint notebook_position_doc_a;
 
3112
        gint notebook_position_doc_b;
 
3113
 
 
3114
        notebook_position_doc_a = document_get_notebook_page(doc_a);
 
3115
        notebook_position_doc_b = document_get_notebook_page(doc_b);
 
3116
 
 
3117
        if (notebook_position_doc_a < notebook_position_doc_b)
 
3118
                return 1;
 
3119
        if (notebook_position_doc_a > notebook_position_doc_b)
 
3120
                return -1;
 
3121
        /* equality */
 
3122
        return 0;
 
3123
}
 
3124
 
 
3125
 
 
3126
void document_grab_focus(GeanyDocument *doc)
 
3127
{
 
3128
        g_return_if_fail(doc != NULL);
 
3129
 
 
3130
        gtk_widget_grab_focus(GTK_WIDGET(doc->editor->sci));
 
3131
}