~ubuntu-branches/ubuntu/precise/geany/precise-201203210702

« back to all changes in this revision

Viewing changes to src/ui_utils.c

  • Committer: Bazaar Package Importer
  • Author(s): Chow Loong Jin
  • Date: 2011-01-08 17:29:46 UTC
  • mfrom: (1.1.15 upstream)
  • Revision ID: james.westby@ubuntu.com-20110108172946-mm7j881jlozn0vt8
Tags: 0.20-0ubuntu1
* New upstream release
* Refresh 20_add_debian_specific_filetypes.dpatch
* Bump Breaks version for geany-plugins-common

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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
20
 *
21
 
 * $Id: ui_utils.c 5149 2010-08-12 12:51:51Z ntrel $
 
21
 * $Id: ui_utils.c 5383 2010-11-08 13:13:33Z ntrel $
22
22
 */
23
23
 
24
24
/** @file ui_utils.h
51
51
#include "symbols.h"
52
52
#include "toolbar.h"
53
53
#include "geanymenubuttonaction.h"
 
54
#include "main.h"
 
55
#include "stash.h"
 
56
#include "keyfile.h"
54
57
 
55
58
 
56
59
GeanyInterfacePrefs     interface_prefs;
72
75
        GtkWidget       *undo_items[3];
73
76
        GtkWidget       *save_buttons[4];
74
77
        GtkWidget       *config_files_menu;
75
 
        GtkWidget       *commands_menu;
76
 
        GtkWidget       *format_menu;
77
78
}
78
79
widgets;
79
80
 
158
159
}
159
160
 
160
161
 
 
162
static gchar *statusbar_template = NULL;
 
163
 
 
164
/* note: some comments below are for translators */
 
165
static void add_statusbar_statistics(GString *stats_str,
 
166
                GeanyDocument *doc, guint line, guint col)
 
167
{
 
168
        const gchar *cur_tag;
 
169
        const gchar *fmt;
 
170
        const gchar *expos;     /* % expansion position */
 
171
        const gchar sp[] = "      ";
 
172
 
 
173
        fmt = NZV(statusbar_template) ? statusbar_template :
 
174
                /* Status bar statistics: col = column, sel = selection. */
 
175
                _("line: %l / %L\t col: %c\t sel: %s\t %w      %t      %m"
 
176
                "mode: %M      encoding: %e      filetype: %f      scope: %S");
 
177
 
 
178
        g_string_assign(stats_str, "");
 
179
        while ((expos = strchr(fmt, '%')) != NULL)
 
180
        {
 
181
                /* append leading text before % char */
 
182
                g_string_append_len(stats_str, fmt, expos - fmt);
 
183
 
 
184
                switch (*++expos)
 
185
                {
 
186
                        case 'l':
 
187
                                g_string_append_printf(stats_str, "%d", line + 1);
 
188
                                break;
 
189
                        case 'L':
 
190
                                g_string_append_printf(stats_str, "%d",
 
191
                                        sci_get_line_count(doc->editor->sci));
 
192
                                break;
 
193
                        case 'c':
 
194
                                g_string_append_printf(stats_str, "%d", col);
 
195
                                break;
 
196
                        case 'C':
 
197
                                g_string_append_printf(stats_str, "%d", col + 1);
 
198
                                break;
 
199
                        case 's':
 
200
                                g_string_append_printf(stats_str, "%d",
 
201
                                        sci_get_selected_text_length(doc->editor->sci) - 1);
 
202
                                break;
 
203
                        case 'w':
 
204
                                /* RO = read-only */
 
205
                                g_string_append(stats_str, (doc->readonly) ? _("RO ") :
 
206
                                        /* OVR = overwrite/overtype, INS = insert */
 
207
                                        (sci_get_overtype(doc->editor->sci) ? _("OVR") : _("INS")));
 
208
                                break;
 
209
                        case 'r':
 
210
                                if (doc->readonly)
 
211
                                {
 
212
                                        g_string_append(stats_str, _("RO "));   /* RO = read-only */
 
213
                                        g_string_append(stats_str, sp + 1);
 
214
                                }
 
215
                                break;
 
216
                        case 't':
 
217
                        {
 
218
                                switch (editor_get_indent_prefs(doc->editor)->type)
 
219
                                {
 
220
                                        case GEANY_INDENT_TYPE_TABS:
 
221
                                                g_string_append(stats_str, _("TAB"));
 
222
                                                break;
 
223
                                        case GEANY_INDENT_TYPE_SPACES:  /* SP = space */
 
224
                                                g_string_append(stats_str, _("SP"));
 
225
                                                break;
 
226
                                        case GEANY_INDENT_TYPE_BOTH:    /* T/S = tabs and spaces */
 
227
                                                g_string_append(stats_str, _("T/S"));
 
228
                                                break;
 
229
                                }
 
230
                                break;
 
231
                        }
 
232
                        case 'm':
 
233
                                if (doc->changed)
 
234
                                {
 
235
                                        g_string_append(stats_str, _("MOD"));   /* MOD = modified */
 
236
                                        g_string_append(stats_str, sp);
 
237
                                }
 
238
                                break;
 
239
                        case 'M':
 
240
                                g_string_append(stats_str, editor_get_eol_char_name(doc->editor));
 
241
                                break;
 
242
                        case 'e':
 
243
                                g_string_append(stats_str,
 
244
                                        doc->encoding ? doc->encoding : _("unknown"));
 
245
                                if (encodings_is_unicode_charset(doc->encoding) && (doc->has_bom))
 
246
                                {
 
247
                                        g_string_append_c(stats_str, ' ');
 
248
                                        g_string_append(stats_str, _("(with BOM)"));    /* BOM = byte order mark */
 
249
                                }
 
250
                                break;
 
251
                        case 'f':
 
252
                                g_string_append(stats_str, filetypes_get_display_name(doc->file_type));
 
253
                                break;
 
254
                        case 'S':
 
255
                                symbols_get_current_function(doc, &cur_tag);
 
256
                                g_string_append(stats_str, cur_tag);
 
257
                                break;
 
258
                        default:
 
259
                                g_string_append_len(stats_str, expos, 1);
 
260
                }
 
261
 
 
262
                /* skip past %c chars */
 
263
                if (*expos)
 
264
                        fmt = expos + 1;
 
265
                else
 
266
                        break;
 
267
        }
 
268
        /* add any remaining text */
 
269
        g_string_append(stats_str, fmt);
 
270
}
 
271
 
 
272
 
161
273
/* updates the status bar document statistics */
162
274
void ui_update_statusbar(GeanyDocument *doc, gint pos)
163
275
{
170
282
        if (doc != NULL)
171
283
        {
172
284
                static GString *stats_str = NULL;
173
 
                const gchar sp[] = "      ";
174
285
                guint line, col;
175
 
                const gchar *cur_tag;
176
 
                gchar *filetype_name = doc->file_type->name;
177
286
 
178
287
                if (G_UNLIKELY(stats_str == NULL))
179
288
                        stats_str = g_string_sized_new(120);
190
299
                else
191
300
                        col = 0;
192
301
 
193
 
                /* Status bar statistics: col = column, sel = selection. */
194
 
                g_string_printf(stats_str, _("line: %d / %d\t col: %d\t sel: %d\t "),
195
 
                        (line + 1), sci_get_line_count(doc->editor->sci), col,
196
 
                        sci_get_selected_text_length(doc->editor->sci) - 1);
197
 
 
198
 
                g_string_append(stats_str,
199
 
                        /* RO = read-only */
200
 
                        (doc->readonly) ? _("RO ") :
201
 
                                /* OVR = overwrite/overtype, INS = insert */
202
 
                                (sci_get_overtype(doc->editor->sci) ? _("OVR") : _("INS")));
203
 
                g_string_append(stats_str, sp);
204
 
 
205
 
                switch (editor_get_indent_prefs(doc->editor)->type)
206
 
                {
207
 
                        case GEANY_INDENT_TYPE_TABS:
208
 
                                g_string_append(stats_str, _("TAB"));
209
 
                                break;
210
 
                        case GEANY_INDENT_TYPE_SPACES:
211
 
                                g_string_append(stats_str, _("SP"));    /* SP = space */
212
 
                                break;
213
 
                        case GEANY_INDENT_TYPE_BOTH:
214
 
                                g_string_append(stats_str, _("T/S"));   /* T/S = tabs and spaces */
215
 
                                break;
216
 
                }
217
 
                g_string_append(stats_str, sp);
218
 
                g_string_append_printf(stats_str, _("mode: %s"),
219
 
                        editor_get_eol_char_name(doc->editor));
220
 
                g_string_append(stats_str, sp);
221
 
                g_string_append_printf(stats_str, _("encoding: %s %s"),
222
 
                        (doc->encoding) ? doc->encoding : _("unknown"),
223
 
                        (encodings_is_unicode_charset(doc->encoding)) ?
224
 
                                /* BOM = byte order mark */
225
 
                                ((doc->has_bom) ? _("(with BOM)") : "") : "");
226
 
                g_string_append(stats_str, sp);
227
 
                g_string_append_printf(stats_str, _("filetype: %s"), filetype_name);
228
 
                g_string_append(stats_str, sp);
229
 
                if (doc->changed)
230
 
                {
231
 
                        g_string_append(stats_str, _("MOD"));   /* MOD = modified */
232
 
                        g_string_append(stats_str, sp);
233
 
                }
234
 
 
235
 
                symbols_get_current_function(doc, &cur_tag);
236
 
                g_string_append_printf(stats_str, _("scope: %s"),
237
 
                        cur_tag);
 
302
                add_statusbar_statistics(stats_str, doc, line, col);
238
303
 
239
304
#ifdef GEANY_DEBUG
 
305
        {
 
306
                const gchar sp[] = "      ";
240
307
                g_string_append(stats_str, sp);
241
308
                g_string_append_printf(stats_str, "pos: %d", pos);
242
309
                g_string_append(stats_str, sp);
243
310
                g_string_append_printf(stats_str, "style: %d", sci_get_style_at(doc->editor->sci, pos));
 
311
        }
244
312
#endif
245
 
 
246
313
                /* can be overridden by status messages */
247
314
                set_statusbar(stats_str->str, TRUE);
248
315
        }
290
357
                g_string_append(str, "] - ");
291
358
        }
292
359
        g_string_append(str, "Geany");
 
360
        if (cl_options.new_instance)
 
361
        {
 
362
                g_string_append(str, _(" (new instance)"));
 
363
        }
293
364
        gtk_window_set_title(GTK_WINDOW(main_widgets.window), str->str);
294
365
        g_string_free(str, TRUE);
295
366
}
572
643
        gtk_container_add(GTK_CONTAINER(menu_edit), item);
573
644
        gtk_widget_show(item);
574
645
        g_signal_connect(item, "activate", G_CALLBACK(on_menu_insert_date_activate), str);
575
 
        g_object_set_data_full(G_OBJECT(main_widgets.window),
576
 
                "insert_date_custom1", g_object_ref(item), (GDestroyNotify)g_object_unref);
 
646
        ui_hookup_widget(main_widgets.window, item, "insert_date_custom1");
577
647
 
578
648
        item = gtk_menu_item_new_with_mnemonic(str);
579
649
        gtk_container_add(GTK_CONTAINER(menu_popup), item);
580
650
        gtk_widget_show(item);
581
651
        g_signal_connect(item, "activate", G_CALLBACK(on_insert_date_activate), str);
582
 
        g_object_set_data_full(G_OBJECT(main_widgets.editor_menu),
583
 
                "insert_date_custom2", g_object_ref(item), (GDestroyNotify)g_object_unref);
 
652
        ui_hookup_widget(main_widgets.editor_menu, item, "insert_date_custom2");
584
653
 
585
654
        insert_date_items(menu_edit, menu_popup, _("_Set Custom Date Format"));
586
655
}
661
730
        add_doc_widget("replace1");
662
731
        add_doc_widget("find_nextsel1");
663
732
        add_doc_widget("find_prevsel1");
 
733
        add_doc_widget("find_usage1");
 
734
        add_doc_widget("find_document_usage1");
664
735
        add_doc_widget("go_to_line1");
 
736
        add_doc_widget("goto_tag_definition1");
 
737
        add_doc_widget("goto_tag_declaration1");
665
738
        add_doc_toolitem("Close");
666
739
        add_doc_toolitem("CloseAll");
667
740
        add_doc_toolitem("Search");
811
884
        item = ui_lookup_widget(main_widgets.window, widget_name);
812
885
        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE);
813
886
 
 
887
        if (iprefs->width >= 1 && iprefs->width <= 8)
 
888
        {
 
889
                gchar *name;
 
890
 
 
891
                name = g_strdup_printf("indent_width_%d", iprefs->width);
 
892
                item = ui_lookup_widget(main_widgets.window, name);
 
893
                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE);
 
894
                g_free(name);
 
895
        }
 
896
 
814
897
        gtk_check_menu_item_set_active(
815
898
                        GTK_CHECK_MENU_ITEM(ui_lookup_widget(main_widgets.window, "set_file_readonly1")),
816
899
                        doc->readonly);
1379
1462
}
1380
1463
 
1381
1464
 
1382
 
/* Prepends the active text to the drop down list, unless the first element in
1383
 
 * the list is identical, ensuring there are <= history_len elements. */
1384
 
void ui_combo_box_add_to_history(GtkComboBox *combo, const gchar *text)
1385
 
{
1386
 
        const gint history_len = 30;
 
1465
static gboolean tree_model_find_text(GtkTreeModel *model,
 
1466
                GtkTreeIter *iter, gint column, const gchar *text)
 
1467
{
 
1468
        gchar *combo_text;
 
1469
        gboolean found = FALSE;
 
1470
 
 
1471
        if (gtk_tree_model_get_iter_first(model, iter))
 
1472
        {
 
1473
                do
 
1474
                {
 
1475
                        gtk_tree_model_get(model, iter, 0, &combo_text, -1);
 
1476
                        found = utils_str_equal(combo_text, text);
 
1477
                        g_free(combo_text);
 
1478
 
 
1479
                        if (found)
 
1480
                                return TRUE;
 
1481
                }
 
1482
                while (gtk_tree_model_iter_next(model, iter));
 
1483
        }
 
1484
        return FALSE;
 
1485
}
 
1486
 
 
1487
 
 
1488
/** Prepends @a text to the drop down list, removing a duplicate element in
 
1489
 * the list if found. Also ensures there are <= @a history_len elements.
 
1490
 * @param combo_entry .
 
1491
 * @param text Text to add, or @c NULL for current entry text.
 
1492
 * @param history_len Max number of items, or @c 0 for default. */
 
1493
void ui_combo_box_add_to_history(GtkComboBoxEntry *combo_entry,
 
1494
                const gchar *text, gint history_len)
 
1495
{
 
1496
        GtkComboBox *combo = GTK_COMBO_BOX(combo_entry);
1387
1497
        GtkTreeModel *model;
1388
1498
        GtkTreeIter iter;
1389
 
        gchar *combo_text;
1390
 
        gboolean equal = FALSE;
1391
1499
        GtkTreePath *path;
1392
1500
 
 
1501
        if (history_len <= 0)
 
1502
                history_len = 10;
 
1503
        if (!text)
 
1504
                text = gtk_entry_get_text(GTK_ENTRY(GTK_BIN(combo)->child));
 
1505
 
1393
1506
        model = gtk_combo_box_get_model(combo);
1394
 
        if (gtk_tree_model_get_iter_first(model, &iter))
 
1507
 
 
1508
        if (tree_model_find_text(model, &iter, 0, text))
1395
1509
        {
1396
 
                gtk_tree_model_get(model, &iter, 0, &combo_text, -1);
1397
 
                equal = utils_str_equal(combo_text, text);
1398
 
                g_free(combo_text);
 
1510
                gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
1399
1511
        }
1400
 
        if (equal) return;      /* don't prepend duplicate */
1401
 
 
1402
1512
        gtk_combo_box_prepend_text(combo, text);
1403
1513
 
1404
1514
        /* limit history */
1417
1527
{
1418
1528
        GtkTreeModel *model;
1419
1529
        GtkTreeIter iter;
1420
 
        gchar *combo_text;
1421
 
        gboolean found = FALSE;
1422
1530
 
1423
1531
        model = gtk_combo_box_get_model(combo);
1424
 
        if (gtk_tree_model_get_iter_first(model, &iter))
1425
 
        {
1426
 
                do
1427
 
                {
1428
 
                        gtk_tree_model_get(model, &iter, 0, &combo_text, -1);
1429
 
                        found = utils_str_equal(combo_text, text);
1430
 
                        g_free(combo_text);
1431
 
                }
1432
 
                while (!found && gtk_tree_model_iter_next(model, &iter));
1433
 
        }
1434
 
        if (found)
 
1532
        if (tree_model_find_text(model, &iter, 0, text))
1435
1533
                return; /* don't prepend duplicate */
1436
1534
 
1437
1535
        gtk_combo_box_prepend_text(combo, text);
1595
1693
                g_object_set_data_full(G_OBJECT(open_btn), "title", g_strdup(title),
1596
1694
                                (GDestroyNotify) g_free);
1597
1695
        g_object_set_data(G_OBJECT(open_btn), "action", (gpointer) action);
1598
 
        g_object_set_data_full(G_OBJECT(open_btn), "entry",
1599
 
                g_object_ref(path_entry), (GDestroyNotify) g_object_unref);
 
1696
        ui_hookup_widget(open_btn, path_entry, "entry");
1600
1697
        g_signal_connect(open_btn, "clicked", G_CALLBACK(ui_path_box_open_clicked), open_btn);
1601
1698
}
1602
1699
 
1886
1983
}
1887
1984
 
1888
1985
 
1889
 
static void on_editor_menu_show(GtkWidget *item)
1890
 
{
1891
 
        GtkWidget *popup = ui_lookup_widget(main_widgets.editor_menu, "commands1");
1892
 
        GtkWidget *bar = ui_lookup_widget(main_widgets.window, "commands2");
1893
 
 
1894
 
        ui_menu_move(widgets.commands_menu, bar, popup);
1895
 
 
1896
 
        popup = ui_lookup_widget(main_widgets.editor_menu, "menu_format2");
1897
 
        bar = ui_lookup_widget(main_widgets.window, "menu_format1");
1898
 
        ui_menu_move(widgets.format_menu, bar, popup);
1899
 
}
1900
 
 
1901
 
 
1902
 
static void on_editor_menu_hide(GtkWidget *item)
1903
 
{
1904
 
        GtkWidget *popup = ui_lookup_widget(main_widgets.editor_menu, "commands1");
1905
 
        GtkWidget *bar = ui_lookup_widget(main_widgets.window, "commands2");
1906
 
 
1907
 
        ui_menu_move(widgets.commands_menu, popup, bar);
1908
 
 
1909
 
        popup = ui_lookup_widget(main_widgets.editor_menu, "menu_format2");
1910
 
        bar = ui_lookup_widget(main_widgets.window, "menu_format1");
1911
 
        ui_menu_move(widgets.format_menu, popup, bar);
 
1986
typedef struct GeanySharedMenu
 
1987
{
 
1988
        gchar *menu;
 
1989
        gchar *menubar_item;
 
1990
        gchar *popup_item;
 
1991
}
 
1992
GeanySharedMenu;
 
1993
 
 
1994
#define foreach_menu(item, array) \
 
1995
        for (item = array; item->menu; item++)
 
1996
 
 
1997
static void on_editor_menu_show(GtkWidget *widget, GeanySharedMenu *items)
 
1998
{
 
1999
        GeanySharedMenu *item;
 
2000
 
 
2001
        foreach_menu(item, items)
 
2002
        {
 
2003
                GtkWidget *popup = ui_lookup_widget(main_widgets.editor_menu, item->popup_item);
 
2004
                GtkWidget *bar = ui_lookup_widget(main_widgets.window, item->menubar_item);
 
2005
                GtkWidget *menu = ui_lookup_widget(main_widgets.window, item->menu);
 
2006
 
 
2007
                ui_menu_move(menu, bar, popup);
 
2008
        }
 
2009
}
 
2010
 
 
2011
 
 
2012
static void on_editor_menu_hide(GtkWidget *widget, GeanySharedMenu *items)
 
2013
{
 
2014
        GeanySharedMenu *item;
 
2015
 
 
2016
        foreach_menu(item, items)
 
2017
        {
 
2018
                GtkWidget *popup = ui_lookup_widget(main_widgets.editor_menu, item->popup_item);
 
2019
                GtkWidget *bar = ui_lookup_widget(main_widgets.window, item->menubar_item);
 
2020
                GtkWidget *menu = ui_lookup_widget(main_widgets.window, item->menu);
 
2021
 
 
2022
                ui_menu_move(menu, popup, bar);
 
2023
        }
 
2024
}
 
2025
 
 
2026
 
 
2027
/* Currently ui_init() is called before keyfile.c stash group code is initialized,
 
2028
 * so this is called after that's done. */
 
2029
void ui_init_prefs(void)
 
2030
{
 
2031
        StashGroup *group = stash_group_new(PACKAGE);
 
2032
 
 
2033
        /* hidden prefs (don't overwrite them so users can edit them manually) */
 
2034
        configuration_add_pref_group(group, FALSE);
 
2035
        stash_group_set_write_once(group, TRUE);
 
2036
 
 
2037
        stash_group_add_boolean(group, &interface_prefs.show_symbol_list_expanders,
 
2038
                "show_symbol_list_expanders", TRUE);
 
2039
        stash_group_add_boolean(group, &interface_prefs.compiler_tab_autoscroll,
 
2040
                "compiler_tab_autoscroll", TRUE);
 
2041
        stash_group_add_boolean(group, &ui_prefs.allow_always_save,
 
2042
                "allow_always_save", FALSE);
 
2043
        stash_group_add_string(group, &statusbar_template,
 
2044
                "statusbar_template", "");
 
2045
        stash_group_add_boolean(group, &ui_prefs.new_document_after_close,
 
2046
                "new_document_after_close", FALSE);
1912
2047
}
1913
2048
 
1914
2049
 
1915
2050
void ui_init(void)
1916
2051
{
1917
 
        GtkWidget *item;
1918
 
 
1919
2052
        init_recent_files();
1920
2053
 
1921
2054
        ui_widgets.statusbar = ui_lookup_widget(main_widgets.window, "statusbar");
1923
2056
 
1924
2057
        main_widgets.progressbar = progress_bar_create();
1925
2058
 
 
2059
        /* current word sensitive items */
1926
2060
        widgets.popup_goto_items[0] = ui_lookup_widget(main_widgets.editor_menu, "goto_tag_definition1");
1927
 
        widgets.popup_goto_items[1] = ui_lookup_widget(main_widgets.editor_menu, "goto_tag_declaration1");
 
2061
        widgets.popup_goto_items[1] = ui_lookup_widget(main_widgets.editor_menu, "context_action1");
1928
2062
        widgets.popup_goto_items[2] = ui_lookup_widget(main_widgets.editor_menu, "find_usage1");
1929
2063
        widgets.popup_goto_items[3] = ui_lookup_widget(main_widgets.editor_menu, "find_document_usage1");
 
2064
 
1930
2065
        widgets.popup_copy_items[0] = ui_lookup_widget(main_widgets.editor_menu, "cut1");
1931
2066
        widgets.popup_copy_items[1] = ui_lookup_widget(main_widgets.editor_menu, "copy1");
1932
2067
        widgets.popup_copy_items[2] = ui_lookup_widget(main_widgets.editor_menu, "delete1");
1942
2077
        widgets.undo_items[0] = ui_lookup_widget(main_widgets.editor_menu, "undo1");
1943
2078
        widgets.undo_items[1] = ui_lookup_widget(main_widgets.window, "menu_undo2");
1944
2079
 
1945
 
        item = ui_lookup_widget(main_widgets.window, "menu_format1");
1946
 
        widgets.format_menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(item));
1947
 
        item = ui_lookup_widget(main_widgets.window, "commands2");
1948
 
        widgets.commands_menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(item));
 
2080
        /* reparent context submenus as needed */
 
2081
        {
 
2082
                GeanySharedMenu arr[] = {
 
2083
                        {"commands2_menu", "commands2", "commands1"},
 
2084
                        {"menu_format1_menu", "menu_format1", "menu_format2"},
 
2085
                        {"more1_menu", "more1", "search2"},
 
2086
                        {NULL, NULL, NULL}
 
2087
                };
 
2088
                static GeanySharedMenu items[G_N_ELEMENTS(arr)];
1949
2089
 
1950
 
        /* reparent edit submenus as needed */
1951
 
        item = main_widgets.editor_menu;
1952
 
        g_signal_connect(item, "show", G_CALLBACK(on_editor_menu_show), NULL);
1953
 
        g_signal_connect(item, "hide", G_CALLBACK(on_editor_menu_hide), NULL);
 
2090
                memcpy(items, arr, sizeof(arr));
 
2091
                g_signal_connect(main_widgets.editor_menu, "show", G_CALLBACK(on_editor_menu_show), items);
 
2092
                g_signal_connect(main_widgets.editor_menu, "hide", G_CALLBACK(on_editor_menu_hide), items);
 
2093
        }
1954
2094
 
1955
2095
        ui_init_toolbar_widgets();
1956
2096
        init_document_widgets();
1958
2098
}
1959
2099
 
1960
2100
 
 
2101
void ui_finalize(void)
 
2102
{
 
2103
        g_free(statusbar_template);
 
2104
}
 
2105
 
 
2106
 
1961
2107
static void auto_separator_update(GeanyAutoSeparator *autosep)
1962
2108
{
1963
2109
        g_return_if_fail(autosep->ref_count >= 0);
2181
2327
}
2182
2328
 
2183
2329
 
2184
 
/* return value is for macros */
2185
 
GtkWidget *ui_label_set_markup(GtkLabel *label, const gchar *format, ...)
 
2330
void ui_label_set_markup(GtkLabel *label, const gchar *format, ...)
2186
2331
{
2187
2332
        va_list a;
2188
2333
        gchar *text;
2194
2339
        gtk_label_set_text(label, text);
2195
2340
        gtk_label_set_use_markup(label, TRUE);
2196
2341
        g_free(text);
2197
 
        return GTK_WIDGET(label);
2198
2342
}
2199
2343
 
2200
2344
 
2204
2348
        gchar *label_text;
2205
2349
 
2206
2350
        label_text = g_markup_escape_text(text, -1);
2207
 
        label = ui_label_set_markup(GTK_LABEL(gtk_label_new(NULL)), "<b>%s</b>", label_text);
 
2351
        label = gtk_label_new(NULL);
 
2352
        ui_label_set_markup(GTK_LABEL(label), "<b>%s</b>", label_text);
2208
2353
        g_free(label_text);
2209
2354
        return label;
2210
2355
}
2219
2364
 * @since 0.19 */
2220
2365
void ui_menu_add_document_items(GtkMenu *menu, GeanyDocument *active, GCallback callback)
2221
2366
{
2222
 
        GtkWidget *menu_item, *menu_item_label;
 
2367
        GtkWidget *menu_item, *menu_item_label, *image;
2223
2368
        const GdkColor *color;
2224
2369
        GeanyDocument *doc;
2225
2370
        guint i, len;
2233
2378
                        continue;
2234
2379
 
2235
2380
                base_name = g_path_get_basename(DOC_FILENAME(doc));
2236
 
                menu_item = gtk_menu_item_new_with_label(base_name);
 
2381
                menu_item = gtk_image_menu_item_new_with_label(base_name);
 
2382
                image = gtk_image_new_from_pixbuf(doc->file_type->icon);
 
2383
                gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item), image);
 
2384
 
2237
2385
                gtk_widget_show(menu_item);
2238
2386
                gtk_container_add(GTK_CONTAINER(menu), menu_item);
2239
2387
                g_signal_connect(menu_item, "activate", callback, doc);
2291
2439
void ui_editable_insert_text_callback(GtkEditable *editable, gchar *new_text,
2292
2440
                                                                          gint new_text_len, gint *position, gpointer data)
2293
2441
{
2294
 
        gboolean stop_signal = FALSE;
2295
 
        const gchar c = *new_text;
2296
 
 
2297
 
        /* allow inserting '+' and '-' as the first character */
2298
 
        if (position != NULL && *position == 0)
2299
 
        {
2300
 
                if (c != '+' && c != '-' && ! isdigit(c))
2301
 
                        stop_signal = TRUE;
2302
 
        }
2303
 
        /* don't insert any text when it is not a digit */
2304
 
        else if (! isdigit(c))
2305
 
                stop_signal = TRUE;
2306
 
 
2307
 
        if (stop_signal)
2308
 
                g_signal_stop_emission_by_name(editable, "insert-text");
 
2442
        gboolean first = position != NULL && *position == 0;
 
2443
        gint i;
 
2444
 
 
2445
        if (new_text_len == -1)
 
2446
                new_text_len = strlen(new_text);
 
2447
 
 
2448
        for (i = 0; i < new_text_len; i++, new_text++)
 
2449
        {
 
2450
                if ((!first || !strchr("+-", *new_text)) && !isdigit(*new_text))
 
2451
                {
 
2452
                        g_signal_stop_emission_by_name(editable, "insert-text");
 
2453
                        break;
 
2454
                }
 
2455
                first = FALSE;
 
2456
        }
 
2457
}
 
2458
 
 
2459
 
 
2460
/* gets the icon that applies to a particular MIME type */
 
2461
GdkPixbuf *ui_get_mime_icon(const gchar *mime_type, GtkIconSize size)
 
2462
{
 
2463
        GdkPixbuf *icon = NULL;
 
2464
#if defined(HAVE_GIO) && GLIB_CHECK_VERSION(2, 18, 0)
 
2465
        gchar *ctype;
 
2466
        GIcon *gicon;
 
2467
        GtkIconInfo *info;
 
2468
        GtkIconTheme *theme;
 
2469
        gint real_size;
 
2470
 
 
2471
        if (!gtk_icon_size_lookup(size, &real_size, NULL))
 
2472
        {
 
2473
                g_return_val_if_reached(NULL);
 
2474
        }
 
2475
        ctype = g_content_type_from_mime_type(mime_type);
 
2476
        if (ctype != NULL)
 
2477
        {
 
2478
                gicon = g_content_type_get_icon(ctype);
 
2479
                theme = gtk_icon_theme_get_default();
 
2480
                info = gtk_icon_theme_lookup_by_gicon(theme, gicon, real_size, 0);
 
2481
                g_object_unref(gicon);
 
2482
                g_free(ctype);
 
2483
 
 
2484
                if (info != NULL)
 
2485
                {
 
2486
                        icon = gtk_icon_info_load_icon(info, NULL);
 
2487
                        gtk_icon_info_free(info);
 
2488
                }
 
2489
        }
 
2490
#endif
 
2491
        /* fallback for builds without GIO or if icon lookup failed, like it might happen on Windows */
 
2492
        if (icon == NULL)
 
2493
        {
 
2494
                const gchar *stock_id = GTK_STOCK_FILE;
 
2495
                GtkIconSet *icon_set;
 
2496
 
 
2497
                if (strstr(mime_type, "directory"))
 
2498
                        stock_id = GTK_STOCK_DIRECTORY;
 
2499
 
 
2500
                icon_set = gtk_icon_factory_lookup_default(stock_id);
 
2501
                if (icon_set)
 
2502
                {
 
2503
                        icon = gtk_icon_set_render_icon(icon_set, gtk_widget_get_default_style(),
 
2504
                                gtk_widget_get_default_direction(),
 
2505
                                GTK_STATE_NORMAL, size, NULL, NULL);
 
2506
                }
 
2507
        }
 
2508
        return icon;
2309
2509
}
2310
2510