From 5356c4549ace052b2e3be5451c9c6410ab3d9e41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Sat, 27 Dec 2014 14:40:57 +0100 Subject: [PATCH 01/14] Fix infinite loop on OS X when using find in files The GIOCondition is always set to G_IO_IN even when input end is reached (and no other flags are set) so the read_fif_io() function never returns FALSE which causes an infinite loop. It is necessary to check also the return value of g_io_channel_read_line() and return FALSE on EOF or error. --- src/search.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/search.c b/src/search.c index dfc9763c..2bdbe544 100644 --- a/src/search.c +++ b/src/search.c @@ -1841,8 +1841,10 @@ static gboolean read_fif_io(GIOChannel *source, GIOCondition condition, gchar *e if (condition & (G_IO_IN | G_IO_PRI)) { gchar *msg, *utf8_msg; + GIOStatus st; - while (g_io_channel_read_line(source, &msg, NULL, NULL, NULL) && msg) + while ((st = g_io_channel_read_line(source, &msg, NULL, NULL, NULL)) != G_IO_STATUS_ERROR && + st != G_IO_STATUS_EOF && msg) { utf8_msg = NULL; @@ -1866,6 +1868,8 @@ static gboolean read_fif_io(GIOChannel *source, GIOCondition condition, gchar *e g_free(utf8_msg); g_free(msg); } + if (st == G_IO_STATUS_ERROR || st == G_IO_STATUS_EOF) + return FALSE; } if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) return FALSE; From 3c01fae8d95f51340e16247f51d0e654500d43f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Sat, 27 Dec 2014 15:24:41 +0100 Subject: [PATCH 02/14] Disable scintilla buffer draw on OS X (with Quartz backend) This delagates font rendering to Quartz so it can be rendered in 2x resolution on "retina" displays. --- src/editor.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/editor.c b/src/editor.c index 73b85cda..b7c646cc 100644 --- a/src/editor.c +++ b/src/editor.c @@ -4779,6 +4779,11 @@ static ScintillaObject *create_new_sci(GeanyEditor *editor) /* virtual space */ SSM(sci, SCI_SETVIRTUALSPACEOPTIONS, editor_prefs.show_virtual_space, 0); + +#ifdef GDK_WINDOWING_QUARTZ + /* "retina" (HiDPI) display support on OS X - requires disabling buffered draw */ + SSM(sci, SCI_SETBUFFEREDDRAW, 0, 0); +#endif /* only connect signals if this is for the document notebook, not split window */ if (editor->sci == NULL) From 9767f79e50408911508577cb68906658872afe3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Mon, 29 Dec 2014 17:14:36 +0100 Subject: [PATCH 03/14] Improve ui_get_mime_icon() It may happen that even though we get GIcon, the actual icon dosen't exist (typically on Windows and OS X). Check if we can find the actual icon. In addition, use "icon name" instead of "stock id" - the latter doesn't work on OS X / Windows for some reason. --- src/ui_utils.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/ui_utils.c b/src/ui_utils.c index 643aadd8..8266565c 100644 --- a/src/ui_utils.c +++ b/src/ui_utils.c @@ -2893,18 +2893,32 @@ GIcon *ui_get_mime_icon(const gchar *mime_type) if (ctype) { icon = g_content_type_get_icon(ctype); + if (icon) + { + GtkIconInfo *icon_info; + + icon_info = gtk_icon_theme_lookup_by_gicon(gtk_icon_theme_get_default(), icon, 16, 0); + if (!icon_info) + { + g_object_unref(icon); + icon = NULL; + } + else + gtk_icon_info_free(icon_info); + } + g_free(ctype); } /* fallback if icon lookup failed, like it might happen on Windows (?) */ if (! icon) { - const gchar *stock_id = GTK_STOCK_FILE; + const gchar *icon_name = "text-x-generic"; if (strstr(mime_type, "directory")) - stock_id = GTK_STOCK_DIRECTORY; + icon_name = "folder"; - icon = g_themed_icon_new(stock_id); + icon = g_themed_icon_new(icon_name); } return icon; } From 558d21f2f29bf6f70655afebf8e10b55f523c864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Mon, 29 Dec 2014 17:43:12 +0100 Subject: [PATCH 04/14] Fix clang warning regarding mismatching types The Option initialization didn't match the struct - there was an extra initialization of -e parameter and missing initialization of --etags-include a bit later. This means the initializations of the fields were shifted by one between these two. --- tagmanager/ctags/options.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tagmanager/ctags/options.c b/tagmanager/ctags/options.c index 070265d0..529d4fb3 100644 --- a/tagmanager/ctags/options.c +++ b/tagmanager/ctags/options.c @@ -77,7 +77,6 @@ optionValues Option = { NULL, /* -I */ FALSE, /* -a */ FALSE, /* -B */ - FALSE, /* -e */ #ifdef MACROS_USE_PATTERNS EX_PATTERN, /* -n, --excmd */ #else @@ -90,6 +89,7 @@ optionValues Option = { NULL, /* -L */ NULL, /* -o */ NULL, /* -h */ + NULL, /* --etags-include */ DEFAULT_FILE_FORMAT,/* --format */ FALSE, /* --if0 */ FALSE, /* --kind-long */ @@ -101,7 +101,7 @@ optionValues Option = { FALSE, /* --tag-relative */ FALSE, /* --totals */ FALSE, /* --line-directives */ - FALSE, + FALSE, /* --nest */ }; From ac76c84fdcf0f9bc2551ec4453df316531c81a9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Tue, 30 Dec 2014 12:15:54 +0100 Subject: [PATCH 05/14] Use Safari as the default browser on OS X Since Safari isn't on PATH, the open command has to be used --- src/keyfile.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/keyfile.c b/src/keyfile.c index e8573800..157ea324 100644 --- a/src/keyfile.c +++ b/src/keyfile.c @@ -77,7 +77,11 @@ #else #define GEANY_DEFAULT_TOOLS_TERMINAL "xterm -e \"/bin/sh %c\"" #endif +#ifdef __APPLE__ +#define GEANY_DEFAULT_TOOLS_BROWSER "open -a safari" +#else #define GEANY_DEFAULT_TOOLS_BROWSER "firefox" +#endif #define GEANY_DEFAULT_TOOLS_PRINTCMD "lpr" #define GEANY_DEFAULT_TOOLS_GREP "grep" #define GEANY_DEFAULT_MRU_LENGTH 10 From 82b413e5062b46b3237ede6b764f40aa8bb22ab2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jir=CC=8Ci=CC=81=20Techet?= Date: Fri, 2 Jan 2015 19:51:44 +0100 Subject: [PATCH 06/14] Fix keybindings on OS X On OS X the Command key is used for common keybindings instead of Ctrl. Introduce a new macro, GEANY_PRIMARY_MOD_MASK that represents the Command key on OS X and Ctrl on other platforms. For some events, such as mouse key press, GDK_MOD2_MASK is returned for the Command key by GTK instead of GDK_META_MASK (which is returned when Command is pressed together with some other key). To hide this behavior from users, introduce keybindings_get_modifiers() which can be used instead of gtk_accelerator_get_default_mod_mask() and which inserts GDK_META_MASK when GDK_MOD2_MASK is found in the mask on OS X. --- src/callbacks.c | 2 +- src/editor.c | 4 +- src/keybindings.c | 138 +++++++++++++++++++++++++--------------------- src/keybindings.h | 7 +++ src/notebook.c | 4 +- src/prefs.c | 2 +- src/sidebar.c | 4 +- src/vte.c | 9 +-- 8 files changed, 95 insertions(+), 75 deletions(-) diff --git a/src/callbacks.c b/src/callbacks.c index 734ea2a7..cadc1cf7 100644 --- a/src/callbacks.c +++ b/src/callbacks.c @@ -1697,7 +1697,7 @@ G_MODULE_EXPORT void on_page_setup1_activate(GtkMenuItem *menuitem, gpointer use G_MODULE_EXPORT gboolean on_escape_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { - guint state = event->state & gtk_accelerator_get_default_mod_mask(); + guint state = keybindings_get_modifiers(event->state); /* make pressing escape in the sidebar and toolbar focus the editor */ if (event->keyval == GDK_Escape && state == 0) diff --git a/src/editor.c b/src/editor.c index b7c646cc..fc04ac6b 100644 --- a/src/editor.c +++ b/src/editor.c @@ -313,14 +313,14 @@ static gboolean on_editor_button_press_event(GtkWidget *widget, GdkEventButton * if (event->button == 1) { - guint state = event->state & gtk_accelerator_get_default_mod_mask(); + guint state = keybindings_get_modifiers(event->state); if (event->type == GDK_BUTTON_PRESS && editor_prefs.disable_dnd) { gint ss = sci_get_selection_start(editor->sci); sci_set_selection_end(editor->sci, ss); } - if (event->type == GDK_BUTTON_PRESS && state == GDK_CONTROL_MASK) + if (event->type == GDK_BUTTON_PRESS && state == GEANY_PRIMARY_MOD_MASK) { sci_set_current_position(editor->sci, editor_info.click_pos, FALSE); diff --git a/src/keybindings.c b/src/keybindings.c index 903848e6..508c0d91 100644 --- a/src/keybindings.c +++ b/src/keybindings.c @@ -110,6 +110,16 @@ static void cb_func_move_tab(guint key_id); static void add_popup_menu_accels(void); +GdkModifierType keybindings_get_modifiers(GdkModifierType mods) +{ +#ifdef __APPLE__ + if (mods & GDK_MOD2_MASK) + mods |= GEANY_PRIMARY_MOD_MASK; +#endif + return mods & gtk_accelerator_get_default_mod_mask(); +} + + /** Looks up a keybinding item. * @param group Group. * @param key_id Keybinding index for the group. @@ -247,32 +257,32 @@ static void init_default_kb(void) group = keybindings_get_core_group(GEANY_KEY_GROUP_FILE); add_kb(group, GEANY_KEYS_FILE_NEW, NULL, - GDK_n, GDK_CONTROL_MASK, "menu_new", _("New"), "menu_new1"); + GDK_n, GEANY_PRIMARY_MOD_MASK, "menu_new", _("New"), "menu_new1"); add_kb(group, GEANY_KEYS_FILE_OPEN, NULL, - GDK_o, GDK_CONTROL_MASK, "menu_open", _("Open"), "menu_open1"); + GDK_o, GEANY_PRIMARY_MOD_MASK, "menu_open", _("Open"), "menu_open1"); add_kb(group, GEANY_KEYS_FILE_OPENSELECTED, NULL, - GDK_o, GDK_SHIFT_MASK | GDK_CONTROL_MASK, "menu_open_selected", + GDK_o, GDK_SHIFT_MASK | GEANY_PRIMARY_MOD_MASK, "menu_open_selected", _("Open selected file"), "menu_open_selected_file1"); add_kb(group, GEANY_KEYS_FILE_SAVE, NULL, - GDK_s, GDK_CONTROL_MASK, "menu_save", _("Save"), "menu_save1"); + GDK_s, GEANY_PRIMARY_MOD_MASK, "menu_save", _("Save"), "menu_save1"); add_kb(group, GEANY_KEYS_FILE_SAVEAS, NULL, 0, 0, "menu_saveas", _("Save as"), "menu_save_as1"); add_kb(group, GEANY_KEYS_FILE_SAVEALL, NULL, - GDK_s, GDK_SHIFT_MASK | GDK_CONTROL_MASK, "menu_saveall", _("Save all"), + GDK_s, GDK_SHIFT_MASK | GEANY_PRIMARY_MOD_MASK, "menu_saveall", _("Save all"), "menu_save_all1"); add_kb(group, GEANY_KEYS_FILE_PRINT, NULL, - GDK_p, GDK_CONTROL_MASK, "menu_print", _("Print"), "print1"); + GDK_p, GEANY_PRIMARY_MOD_MASK, "menu_print", _("Print"), "print1"); add_kb(group, GEANY_KEYS_FILE_CLOSE, NULL, - GDK_w, GDK_CONTROL_MASK, "menu_close", _("Close"), "menu_close1"); + GDK_w, GEANY_PRIMARY_MOD_MASK, "menu_close", _("Close"), "menu_close1"); add_kb(group, GEANY_KEYS_FILE_CLOSEALL, NULL, - GDK_w, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "menu_closeall", _("Close all"), + GDK_w, GEANY_PRIMARY_MOD_MASK | GDK_SHIFT_MASK, "menu_closeall", _("Close all"), "menu_close_all1"); add_kb(group, GEANY_KEYS_FILE_RELOAD, NULL, - GDK_r, GDK_CONTROL_MASK, "menu_reloadfile", _("Reload file"), "menu_reload1"); + GDK_r, GEANY_PRIMARY_MOD_MASK, "menu_reloadfile", _("Reload file"), "menu_reload1"); add_kb(group, GEANY_KEYS_FILE_OPENLASTTAB, NULL, 0, 0, "file_openlasttab", _("Re-open last closed tab"), NULL); add_kb(group, GEANY_KEYS_FILE_QUIT, NULL, - GDK_q, GDK_CONTROL_MASK, "menu_quit", _("Quit"), "menu_quit1"); + GDK_q, GEANY_PRIMARY_MOD_MASK, "menu_quit", _("Quit"), "menu_quit1"); group = keybindings_get_core_group(GEANY_KEY_GROUP_PROJECT); @@ -289,23 +299,23 @@ static void init_default_kb(void) group = keybindings_get_core_group(GEANY_KEY_GROUP_EDITOR); add_kb(group, GEANY_KEYS_EDITOR_UNDO, NULL, - GDK_z, GDK_CONTROL_MASK, "menu_undo", _("Undo"), "menu_undo2"); + GDK_z, GEANY_PRIMARY_MOD_MASK, "menu_undo", _("Undo"), "menu_undo2"); add_kb(group, GEANY_KEYS_EDITOR_REDO, NULL, - GDK_y, GDK_CONTROL_MASK, "menu_redo", _("Redo"), "menu_redo2"); + GDK_y, GEANY_PRIMARY_MOD_MASK, "menu_redo", _("Redo"), "menu_redo2"); add_kb(group, GEANY_KEYS_EDITOR_DUPLICATELINE, NULL, - GDK_d, GDK_CONTROL_MASK, "edit_duplicateline", _("D_uplicate Line or Selection"), + GDK_d, GEANY_PRIMARY_MOD_MASK, "edit_duplicateline", _("D_uplicate Line or Selection"), "duplicate_line_or_selection1"); add_kb(group, GEANY_KEYS_EDITOR_DELETELINE, NULL, - GDK_k, GDK_CONTROL_MASK, "edit_deleteline", _("_Delete Current Line(s)"), + GDK_k, GEANY_PRIMARY_MOD_MASK, "edit_deleteline", _("_Delete Current Line(s)"), "delete_current_lines1"); add_kb(group, GEANY_KEYS_EDITOR_DELETELINETOEND, NULL, - GDK_Delete, GDK_SHIFT_MASK | GDK_CONTROL_MASK, "edit_deletelinetoend", + GDK_Delete, GDK_SHIFT_MASK | GEANY_PRIMARY_MOD_MASK, "edit_deletelinetoend", _("Delete to line end"), NULL); /* Note: transpose may fit better in format group, but that would break the API */ add_kb(group, GEANY_KEYS_EDITOR_TRANSPOSELINE, NULL, 0, 0, "edit_transposeline", _("_Transpose Current Line"), NULL); add_kb(group, GEANY_KEYS_EDITOR_SCROLLTOLINE, NULL, - GDK_l, GDK_SHIFT_MASK | GDK_CONTROL_MASK, "edit_scrolltoline", _("Scroll to current line"), NULL); + GDK_l, GDK_SHIFT_MASK | GEANY_PRIMARY_MOD_MASK, "edit_scrolltoline", _("Scroll to current line"), NULL); add_kb(group, GEANY_KEYS_EDITOR_SCROLLLINEUP, NULL, GDK_Up, GDK_MOD1_MASK, "edit_scrolllineup", _("Scroll up the view by one line"), NULL); add_kb(group, GEANY_KEYS_EDITOR_SCROLLLINEDOWN, NULL, @@ -319,9 +329,9 @@ static void init_default_kb(void) add_kb(group, GEANY_KEYS_EDITOR_CONTEXTACTION, NULL, 0, 0, "popup_contextaction", _("Context Action"), NULL); add_kb(group, GEANY_KEYS_EDITOR_AUTOCOMPLETE, NULL, - GDK_space, GDK_CONTROL_MASK, "edit_autocomplete", _("Complete word"), NULL); + GDK_space, GEANY_PRIMARY_MOD_MASK, "edit_autocomplete", _("Complete word"), NULL); add_kb(group, GEANY_KEYS_EDITOR_CALLTIP, NULL, - GDK_space, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "edit_calltip", _("Show calltip"), NULL); + GDK_space, GEANY_PRIMARY_MOD_MASK | GDK_SHIFT_MASK, "edit_calltip", _("Show calltip"), NULL); add_kb(group, GEANY_KEYS_EDITOR_WORDPARTCOMPLETION, NULL, GDK_Tab, 0, "edit_wordpartcompletion", _("Word part completion"), NULL); add_kb(group, GEANY_KEYS_EDITOR_MOVELINEUP, NULL, @@ -334,22 +344,22 @@ static void init_default_kb(void) group = keybindings_get_core_group(GEANY_KEY_GROUP_CLIPBOARD); add_kb(group, GEANY_KEYS_CLIPBOARD_CUT, NULL, - GDK_x, GDK_CONTROL_MASK, "menu_cut", _("Cut"), "menu_cut1"); + GDK_x, GEANY_PRIMARY_MOD_MASK, "menu_cut", _("Cut"), "menu_cut1"); add_kb(group, GEANY_KEYS_CLIPBOARD_COPY, NULL, - GDK_c, GDK_CONTROL_MASK, "menu_copy", _("Copy"), "menu_copy1"); + GDK_c, GEANY_PRIMARY_MOD_MASK, "menu_copy", _("Copy"), "menu_copy1"); add_kb(group, GEANY_KEYS_CLIPBOARD_PASTE, NULL, - GDK_v, GDK_CONTROL_MASK, "menu_paste", _("Paste"), "menu_paste1"); + GDK_v, GEANY_PRIMARY_MOD_MASK, "menu_paste", _("Paste"), "menu_paste1"); add_kb(group, GEANY_KEYS_CLIPBOARD_COPYLINE, NULL, - GDK_c, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "edit_copyline", _("_Copy Current Line(s)"), + GDK_c, GEANY_PRIMARY_MOD_MASK | GDK_SHIFT_MASK, "edit_copyline", _("_Copy Current Line(s)"), "copy_current_lines1"); add_kb(group, GEANY_KEYS_CLIPBOARD_CUTLINE, NULL, - GDK_x, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "edit_cutline", _("Cu_t Current Line(s)"), + GDK_x, GEANY_PRIMARY_MOD_MASK | GDK_SHIFT_MASK, "edit_cutline", _("Cu_t Current Line(s)"), "cut_current_lines1"); group = keybindings_get_core_group(GEANY_KEY_GROUP_SELECT); add_kb(group, GEANY_KEYS_SELECT_ALL, NULL, - GDK_a, GDK_CONTROL_MASK, "menu_selectall", _("Select All"), "menu_select_all1"); + GDK_a, GEANY_PRIMARY_MOD_MASK, "menu_selectall", _("Select All"), "menu_select_all1"); add_kb(group, GEANY_KEYS_SELECT_WORD, NULL, GDK_w, GDK_SHIFT_MASK | GDK_MOD1_MASK, "edit_selectword", _("Select current word"), NULL); add_kb(group, GEANY_KEYS_SELECT_LINE, NULL, @@ -366,20 +376,20 @@ static void init_default_kb(void) group = keybindings_get_core_group(GEANY_KEY_GROUP_FORMAT); add_kb(group, GEANY_KEYS_FORMAT_TOGGLECASE, NULL, - GDK_u, GDK_CONTROL_MASK | GDK_MOD1_MASK, "edit_togglecase", + GDK_u, GEANY_PRIMARY_MOD_MASK | GDK_MOD1_MASK, "edit_togglecase", _("T_oggle Case of Selection"), "menu_toggle_case2"); add_kb(group, GEANY_KEYS_FORMAT_COMMENTLINETOGGLE, NULL, - GDK_e, GDK_CONTROL_MASK, "edit_commentlinetoggle", _("Toggle line commentation"), + GDK_e, GEANY_PRIMARY_MOD_MASK, "edit_commentlinetoggle", _("Toggle line commentation"), "menu_toggle_line_commentation1"); add_kb(group, GEANY_KEYS_FORMAT_COMMENTLINE, NULL, 0, 0, "edit_commentline", _("Comment line(s)"), "menu_comment_line1"); add_kb(group, GEANY_KEYS_FORMAT_UNCOMMENTLINE, NULL, 0, 0, "edit_uncommentline", _("Uncomment line(s)"), "menu_uncomment_line1"); add_kb(group, GEANY_KEYS_FORMAT_INCREASEINDENT, NULL, - GDK_i, GDK_CONTROL_MASK, "edit_increaseindent", _("Increase indent"), + GDK_i, GEANY_PRIMARY_MOD_MASK, "edit_increaseindent", _("Increase indent"), "menu_increase_indent1"); add_kb(group, GEANY_KEYS_FORMAT_DECREASEINDENT, NULL, - GDK_u, GDK_CONTROL_MASK, "edit_decreaseindent", _("Decrease indent"), + GDK_u, GEANY_PRIMARY_MOD_MASK, "edit_decreaseindent", _("Decrease indent"), "menu_decrease_indent1"); add_kb(group, GEANY_KEYS_FORMAT_INCREASEINDENTBYSPACE, NULL, 0, 0, "edit_increaseindentbyspace", _("Increase indent by one space"), NULL); @@ -388,16 +398,16 @@ static void init_default_kb(void) add_kb(group, GEANY_KEYS_FORMAT_AUTOINDENT, NULL, 0, 0, "edit_autoindent", _("S_mart Line Indent"), "smart_line_indent1"); add_kb(group, GEANY_KEYS_FORMAT_SENDTOCMD1, NULL, - GDK_1, GDK_CONTROL_MASK, "edit_sendtocmd1", _("Send to Custom Command 1"), NULL); + GDK_1, GEANY_PRIMARY_MOD_MASK, "edit_sendtocmd1", _("Send to Custom Command 1"), NULL); add_kb(group, GEANY_KEYS_FORMAT_SENDTOCMD2, NULL, - GDK_2, GDK_CONTROL_MASK, "edit_sendtocmd2", _("Send to Custom Command 2"), NULL); + GDK_2, GEANY_PRIMARY_MOD_MASK, "edit_sendtocmd2", _("Send to Custom Command 2"), NULL); add_kb(group, GEANY_KEYS_FORMAT_SENDTOCMD3, NULL, - GDK_3, GDK_CONTROL_MASK, "edit_sendtocmd3", _("Send to Custom Command 3"), NULL); + GDK_3, GEANY_PRIMARY_MOD_MASK, "edit_sendtocmd3", _("Send to Custom Command 3"), NULL); /* may fit better in editor group */ add_kb(group, GEANY_KEYS_FORMAT_SENDTOVTE, NULL, 0, 0, "edit_sendtovte", _("_Send Selection to Terminal"), "send_selection_to_vte1"); add_kb(group, GEANY_KEYS_FORMAT_REFLOWPARAGRAPH, NULL, - GDK_j, GDK_CONTROL_MASK, "format_reflowparagraph", _("_Reflow Lines/Block"), + GDK_j, GEANY_PRIMARY_MOD_MASK, "format_reflowparagraph", _("_Reflow Lines/Block"), "reflow_lines_block1"); keybindings_set_item(group, GEANY_KEYS_FORMAT_JOINLINES, NULL, 0, 0, "edit_joinlines", _("Join lines"), NULL); @@ -418,7 +428,7 @@ static void init_default_kb(void) group = keybindings_get_core_group(GEANY_KEY_GROUP_SETTINGS); add_kb(group, GEANY_KEYS_SETTINGS_PREFERENCES, cb_func_menu_preferences, - GDK_p, GDK_CONTROL_MASK | GDK_MOD1_MASK, "menu_preferences", _("Preferences"), + GDK_p, GEANY_PRIMARY_MOD_MASK | GDK_MOD1_MASK, "menu_preferences", _("Preferences"), "preferences1"); add_kb(group, GEANY_KEYS_SETTINGS_PLUGINPREFERENCES, cb_func_menu_preferences, 0, 0, "menu_pluginpreferences", _("P_lugin Preferences"), "plugin_preferences1"); @@ -426,33 +436,33 @@ static void init_default_kb(void) group = keybindings_get_core_group(GEANY_KEY_GROUP_SEARCH); add_kb(group, GEANY_KEYS_SEARCH_FIND, NULL, - GDK_f, GDK_CONTROL_MASK, "menu_find", _("Find"), "find1"); + GDK_f, GEANY_PRIMARY_MOD_MASK, "menu_find", _("Find"), "find1"); add_kb(group, GEANY_KEYS_SEARCH_FINDNEXT, NULL, - GDK_g, GDK_CONTROL_MASK, "menu_findnext", _("Find Next"), "find_next1"); + GDK_g, GEANY_PRIMARY_MOD_MASK, "menu_findnext", _("Find Next"), "find_next1"); add_kb(group, GEANY_KEYS_SEARCH_FINDPREVIOUS, NULL, - GDK_g, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "menu_findprevious", _("Find Previous"), + GDK_g, GEANY_PRIMARY_MOD_MASK | GDK_SHIFT_MASK, "menu_findprevious", _("Find Previous"), "find_previous1"); add_kb(group, GEANY_KEYS_SEARCH_FINDNEXTSEL, NULL, 0, 0, "menu_findnextsel", _("Find Next _Selection"), "find_nextsel1"); add_kb(group, GEANY_KEYS_SEARCH_FINDPREVSEL, NULL, 0, 0, "menu_findprevsel", _("Find Pre_vious Selection"), "find_prevsel1"); add_kb(group, GEANY_KEYS_SEARCH_REPLACE, NULL, - GDK_h, GDK_CONTROL_MASK, "menu_replace", _("Replace"), "replace1"); + GDK_h, GEANY_PRIMARY_MOD_MASK, "menu_replace", _("Replace"), "replace1"); add_kb(group, GEANY_KEYS_SEARCH_FINDINFILES, NULL, GDK_f, - GDK_CONTROL_MASK | GDK_SHIFT_MASK, "menu_findinfiles", _("Find in Files"), + GEANY_PRIMARY_MOD_MASK | GDK_SHIFT_MASK, "menu_findinfiles", _("Find in Files"), "find_in_files1"); add_kb(group, GEANY_KEYS_SEARCH_NEXTMESSAGE, NULL, 0, 0, "menu_nextmessage", _("Next Message"), "next_message1"); add_kb(group, GEANY_KEYS_SEARCH_PREVIOUSMESSAGE, NULL, 0, 0, "menu_previousmessage", _("Previous Message"), "previous_message1"); add_kb(group, GEANY_KEYS_SEARCH_FINDUSAGE, NULL, - GDK_e, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "popup_findusage", + GDK_e, GEANY_PRIMARY_MOD_MASK | GDK_SHIFT_MASK, "popup_findusage", _("Find Usage"), "find_usage1"); add_kb(group, GEANY_KEYS_SEARCH_FINDDOCUMENTUSAGE, NULL, - GDK_d, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "popup_finddocumentusage", + GDK_d, GEANY_PRIMARY_MOD_MASK | GDK_SHIFT_MASK, "popup_finddocumentusage", _("Find Document Usage"), "find_document_usage1"); add_kb(group, GEANY_KEYS_SEARCH_MARKALL, NULL, - GDK_m, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "find_markall", _("_Mark All"), "mark_all1"); + GDK_m, GEANY_PRIMARY_MOD_MASK | GDK_SHIFT_MASK, "find_markall", _("_Mark All"), "mark_all1"); group = keybindings_get_core_group(GEANY_KEY_GROUP_GOTO); @@ -461,24 +471,24 @@ static void init_default_kb(void) add_kb(group, GEANY_KEYS_GOTO_FORWARD, NULL, GDK_Right, GDK_MOD1_MASK, "nav_forward", _("Navigate forward a location"), NULL); add_kb(group, GEANY_KEYS_GOTO_LINE, NULL, - GDK_l, GDK_CONTROL_MASK, "menu_gotoline", _("Go to Line"), "go_to_line1"); + GDK_l, GEANY_PRIMARY_MOD_MASK, "menu_gotoline", _("Go to Line"), "go_to_line1"); add_kb(group, GEANY_KEYS_GOTO_MATCHINGBRACE, NULL, - GDK_b, GDK_CONTROL_MASK, "edit_gotomatchingbrace", + GDK_b, GEANY_PRIMARY_MOD_MASK, "edit_gotomatchingbrace", _("Go to matching brace"), NULL); add_kb(group, GEANY_KEYS_GOTO_TOGGLEMARKER, NULL, - GDK_m, GDK_CONTROL_MASK, "edit_togglemarker", + GDK_m, GEANY_PRIMARY_MOD_MASK, "edit_togglemarker", _("Toggle marker"), NULL); add_kb(group, GEANY_KEYS_GOTO_NEXTMARKER, NULL, - GDK_period, GDK_CONTROL_MASK, "edit_gotonextmarker", + GDK_period, GEANY_PRIMARY_MOD_MASK, "edit_gotonextmarker", _("Go to Ne_xt Marker"), "go_to_next_marker1"); add_kb(group, GEANY_KEYS_GOTO_PREVIOUSMARKER, NULL, - GDK_comma, GDK_CONTROL_MASK, "edit_gotopreviousmarker", + GDK_comma, GEANY_PRIMARY_MOD_MASK, "edit_gotopreviousmarker", _("Go to Pre_vious Marker"), "go_to_previous_marker1"); add_kb(group, GEANY_KEYS_GOTO_TAGDEFINITION, NULL, - GDK_t, GDK_CONTROL_MASK, "popup_gototagdefinition", + GDK_t, GEANY_PRIMARY_MOD_MASK, "popup_gototagdefinition", _("Go to Tag Definition"), "goto_tag_definition1"); add_kb(group, GEANY_KEYS_GOTO_TAGDECLARATION, NULL, - GDK_t, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "popup_gototagdeclaration", + GDK_t, GEANY_PRIMARY_MOD_MASK | GDK_SHIFT_MASK, "popup_gototagdeclaration", _("Go to Tag Declaration"), "goto_tag_declaration1"); add_kb(group, GEANY_KEYS_GOTO_LINESTART, NULL, GDK_Home, 0, "edit_gotolinestart", _("Go to Start of Line"), NULL); @@ -489,9 +499,9 @@ static void init_default_kb(void) add_kb(group, GEANY_KEYS_GOTO_LINEENDVISUAL, NULL, GDK_End, GDK_MOD1_MASK, "edit_gotolineendvisual", _("Go to End of Display Line"), NULL); add_kb(group, GEANY_KEYS_GOTO_PREVWORDPART, NULL, - GDK_slash, GDK_CONTROL_MASK, "edit_prevwordstart", _("Go to Previous Word Part"), NULL); + GDK_slash, GEANY_PRIMARY_MOD_MASK, "edit_prevwordstart", _("Go to Previous Word Part"), NULL); add_kb(group, GEANY_KEYS_GOTO_NEXTWORDPART, NULL, - GDK_backslash, GDK_CONTROL_MASK, "edit_nextwordstart", _("Go to Next Word Part"), NULL); + GDK_backslash, GEANY_PRIMARY_MOD_MASK, "edit_nextwordstart", _("Go to Next Word Part"), NULL); group = keybindings_get_core_group(GEANY_KEY_GROUP_VIEW); @@ -506,11 +516,11 @@ static void init_default_kb(void) add_kb(group, GEANY_KEYS_VIEW_SIDEBAR, NULL, 0, 0, "toggle_sidebar", _("Toggle Sidebar"), "menu_show_sidebar1"); add_kb(group, GEANY_KEYS_VIEW_ZOOMIN, NULL, - GDK_plus, GDK_CONTROL_MASK, "menu_zoomin", _("Zoom In"), "menu_zoom_in1"); + GDK_plus, GEANY_PRIMARY_MOD_MASK, "menu_zoomin", _("Zoom In"), "menu_zoom_in1"); add_kb(group, GEANY_KEYS_VIEW_ZOOMOUT, NULL, - GDK_minus, GDK_CONTROL_MASK, "menu_zoomout", _("Zoom Out"), "menu_zoom_out1"); + GDK_minus, GEANY_PRIMARY_MOD_MASK, "menu_zoomout", _("Zoom Out"), "menu_zoom_out1"); add_kb(group, GEANY_KEYS_VIEW_ZOOMRESET, NULL, - GDK_0, GDK_CONTROL_MASK, "normal_size", _("Zoom Reset"), "normal_size1"); + GDK_0, GEANY_PRIMARY_MOD_MASK, "normal_size", _("Zoom Reset"), "normal_size1"); group = keybindings_get_core_group(GEANY_KEY_GROUP_FOCUS); @@ -538,16 +548,16 @@ static void init_default_kb(void) group = keybindings_get_core_group(GEANY_KEY_GROUP_NOTEBOOK); add_kb(group, GEANY_KEYS_NOTEBOOK_SWITCHTABLEFT, cb_func_switch_tableft, - GDK_Page_Up, GDK_CONTROL_MASK, "switch_tableft", _("Switch to left document"), NULL); + GDK_Page_Up, GEANY_PRIMARY_MOD_MASK, "switch_tableft", _("Switch to left document"), NULL); add_kb(group, GEANY_KEYS_NOTEBOOK_SWITCHTABRIGHT, cb_func_switch_tabright, - GDK_Page_Down, GDK_CONTROL_MASK, "switch_tabright", _("Switch to right document"), NULL); + GDK_Page_Down, GEANY_PRIMARY_MOD_MASK, "switch_tabright", _("Switch to right document"), NULL); add_kb(group, GEANY_KEYS_NOTEBOOK_SWITCHTABLASTUSED, cb_func_switch_tablastused, - GDK_Tab, GDK_CONTROL_MASK, "switch_tablastused", _("Switch to last used document"), NULL); + GDK_Tab, GEANY_PRIMARY_MOD_MASK, "switch_tablastused", _("Switch to last used document"), NULL); add_kb(group, GEANY_KEYS_NOTEBOOK_MOVETABLEFT, cb_func_move_tab, - GDK_Page_Up, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "move_tableft", + GDK_Page_Up, GEANY_PRIMARY_MOD_MASK | GDK_SHIFT_MASK, "move_tableft", _("Move document left"), NULL); add_kb(group, GEANY_KEYS_NOTEBOOK_MOVETABRIGHT, cb_func_move_tab, - GDK_Page_Down, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "move_tabright", + GDK_Page_Down, GEANY_PRIMARY_MOD_MASK | GDK_SHIFT_MASK, "move_tabright", _("Move document right"), NULL); add_kb(group, GEANY_KEYS_NOTEBOOK_MOVETABFIRST, cb_func_move_tab, 0, 0, "move_tabfirst", _("Move document first"), NULL); @@ -573,7 +583,7 @@ static void init_default_kb(void) add_kb(group, GEANY_KEYS_DOCUMENT_UNFOLDALL, NULL, 0, 0, "menu_unfoldall", _("Unfold all"), "menu_unfold_all1"); add_kb(group, GEANY_KEYS_DOCUMENT_RELOADTAGLIST, NULL, - GDK_r, GDK_SHIFT_MASK | GDK_CONTROL_MASK, "reloadtaglist", _("Reload symbol list"), NULL); + GDK_r, GDK_SHIFT_MASK | GEANY_PRIMARY_MOD_MASK, "reloadtaglist", _("Reload symbol list"), NULL); add_kb(group, GEANY_KEYS_DOCUMENT_REMOVE_MARKERS, NULL, 0, 0, "remove_markers", _("Remove Markers"), "remove_markers1"); add_kb(group, GEANY_KEYS_DOCUMENT_REMOVE_ERROR_INDICATORS, NULL, @@ -590,7 +600,7 @@ static void init_default_kb(void) add_kb(group, GEANY_KEYS_BUILD_MAKE, NULL, GDK_F9, GDK_SHIFT_MASK, "build_make", _("Make all"), NULL); add_kb(group, GEANY_KEYS_BUILD_MAKEOWNTARGET, NULL, - GDK_F9, GDK_SHIFT_MASK | GDK_CONTROL_MASK, "build_makeowntarget", + GDK_F9, GDK_SHIFT_MASK | GEANY_PRIMARY_MOD_MASK, "build_makeowntarget", _("Make custom target"), NULL); add_kb(group, GEANY_KEYS_BUILD_MAKEOBJECT, NULL, GDK_F8, GDK_SHIFT_MASK, "build_makeobject", _("Make object"), NULL); @@ -975,7 +985,7 @@ static gboolean check_fixed_kb(guint keyval, guint state) if (keyval == GDK_Page_Up || keyval == GDK_Page_Down) { /* switch to first or last document */ - if (state == (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) + if (state == (GEANY_PRIMARY_MOD_MASK | GDK_SHIFT_MASK)) { if (keyval == GDK_Page_Up) gtk_notebook_set_current_page(GTK_NOTEBOOK(main_widgets.notebook), 0); @@ -1116,7 +1126,7 @@ static gboolean check_vte(GdkModifierType state, guint keyval) if (gtk_window_get_focus(GTK_WINDOW(main_widgets.window)) != vc->vte) return FALSE; /* let VTE copy/paste override any user keybinding */ - if (state == (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && (keyval == GDK_c || keyval == GDK_v)) + if (state == (GEANY_PRIMARY_MOD_MASK | GDK_SHIFT_MASK) && (keyval == GDK_c || keyval == GDK_v)) return TRUE; if (! vc->enable_bash_keys) return FALSE; @@ -1198,7 +1208,7 @@ gboolean keybindings_check_event(GdkEventKey *ev, GeanyKeyBinding *kb) return FALSE; keyval = ev->keyval; - state = ev->state & gtk_accelerator_get_default_mod_mask(); + state = keybindings_get_modifiers(ev->state); /* hack to get around that CTRL+Shift+r results in GDK_R not GDK_r */ if ((ev->state & GDK_SHIFT_MASK) || (ev->state & GDK_LOCK_MASK)) if (keyval >= GDK_A && keyval <= GDK_Z) @@ -1228,7 +1238,7 @@ static gboolean on_key_press_event(GtkWidget *widget, GdkEventKey *ev, gpointer document_check_disk_status(doc, FALSE); keyval = ev->keyval; - state = ev->state & gtk_accelerator_get_default_mod_mask(); + state = keybindings_get_modifiers(ev->state); /* hack to get around that CTRL+Shift+r results in GDK_R not GDK_r */ if ((ev->state & GDK_SHIFT_MASK) || (ev->state & GDK_LOCK_MASK)) if (keyval >= GDK_A && keyval <= GDK_Z) diff --git a/src/keybindings.h b/src/keybindings.h index 86c84bb5..90c6a596 100644 --- a/src/keybindings.h +++ b/src/keybindings.h @@ -26,6 +26,12 @@ G_BEGIN_DECLS +#ifdef __APPLE__ +#define GEANY_PRIMARY_MOD_MASK GDK_META_MASK +#else +#define GEANY_PRIMARY_MOD_MASK GDK_CONTROL_MASK +#endif + /** Function pointer type used for keybinding callbacks. */ typedef void (*GeanyKeyCallback) (guint key_id); @@ -246,6 +252,7 @@ GeanyKeyBinding *keybindings_set_item(GeanyKeyGroup *group, gsize key_id, GeanyKeyBinding *keybindings_get_item(GeanyKeyGroup *group, gsize key_id); +GdkModifierType keybindings_get_modifiers(GdkModifierType mods); #ifdef GEANY_PRIVATE diff --git a/src/notebook.c b/src/notebook.c index 2016715f..e537a368 100644 --- a/src/notebook.c +++ b/src/notebook.c @@ -617,8 +617,8 @@ static gboolean notebook_tab_click(GtkWidget *widget, GdkEventButton *event, gpo return TRUE; /* stop other handlers like notebook_tab_bar_click_cb() */ } /* switch last used tab on ctrl-click */ - state = event->state & gtk_accelerator_get_default_mod_mask(); - if (event->button == 1 && state == GDK_CONTROL_MASK) + state = keybindings_get_modifiers(event->state); + if (event->button == 1 && state == GEANY_PRIMARY_MOD_MASK) { keybindings_send_command(GEANY_KEY_GROUP_NOTEBOOK, GEANY_KEYS_NOTEBOOK_SWITCHTABLASTUSED); diff --git a/src/prefs.c b/src/prefs.c index ed2a3e10..bdf83ec5 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -1414,7 +1414,7 @@ static gboolean kb_grab_key_dialog_key_press_cb(GtkWidget *dialog, GdkEventKey * g_return_val_if_fail(GTK_IS_LABEL(label), FALSE); - state = event->state & gtk_accelerator_get_default_mod_mask(); + state = keybindings_get_modifiers(event->state); if (event->keyval == GDK_Escape) return FALSE; /* close the dialog, don't allow escape when detecting keybindings. */ diff --git a/src/sidebar.c b/src/sidebar.c index 412fac31..e8f0aa6f 100644 --- a/src/sidebar.c +++ b/src/sidebar.c @@ -41,6 +41,7 @@ #include "symbols.h" #include "ui_utils.h" #include "utils.h" +#include "keybindings.h" #include @@ -912,7 +913,8 @@ static gboolean taglist_go_to_selection(GtkTreeSelection *selection, guint keyva if (doc != NULL) { navqueue_goto_line(doc, doc, line); - if (keyval != GDK_space && ! (state & GDK_CONTROL_MASK)) + state = keybindings_get_modifiers(state); + if (keyval != GDK_space && ! (state & GEANY_PRIMARY_MOD_MASK)) change_focus_to_editor(doc, NULL); else handled = FALSE; diff --git a/src/vte.c b/src/vte.c index e1ebc2a4..0207f784 100644 --- a/src/vte.c +++ b/src/vte.c @@ -39,6 +39,7 @@ #include "support.h" #include "ui_utils.h" #include "utils.h" +#include "keybindings.h" #include "gtkcompat.h" @@ -328,7 +329,7 @@ void vte_close(void) static gboolean vte_keyrelease_cb(GtkWidget *widget, GdkEventKey *event, gpointer data) { if (ui_is_keyval_enter_or_return(event->keyval) || - ((event->keyval == GDK_c) && (event->state & GDK_CONTROL_MASK))) + ((event->keyval == GDK_c) && (event->state & GEANY_PRIMARY_MOD_MASK))) { /* assume any text on the prompt has been executed when pressing Enter/Return */ clean = TRUE; @@ -349,7 +350,7 @@ static gboolean vte_keypress_cb(GtkWidget *widget, GdkEventKey *event, gpointer event->keyval == GDK_d || event->keyval == GDK_C || event->keyval == GDK_D) && - event->state & GDK_CONTROL_MASK && + event->state & GEANY_PRIMARY_MOD_MASK && ! (event->state & GDK_SHIFT_MASK) && ! (event->state & GDK_MOD1_MASK)) { vte_restart(widget); @@ -560,14 +561,14 @@ static GtkWidget *vte_create_popup_menu(void) item = gtk_image_menu_item_new_from_stock(GTK_STOCK_COPY, NULL); gtk_widget_add_accelerator(item, "activate", accel_group, - GDK_c, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); + GDK_c, GEANY_PRIMARY_MOD_MASK | GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(menu), item); g_signal_connect(item, "activate", G_CALLBACK(vte_popup_menu_clicked), GINT_TO_POINTER(POPUP_COPY)); item = gtk_image_menu_item_new_from_stock(GTK_STOCK_PASTE, NULL); gtk_widget_add_accelerator(item, "activate", accel_group, - GDK_v, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); + GDK_v, GEANY_PRIMARY_MOD_MASK | GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(menu), item); g_signal_connect(item, "activate", G_CALLBACK(vte_popup_menu_clicked), GINT_TO_POINTER(POPUP_PASTE)); From 98ae34f1dcc671bc691c40fa9896ab5624818e7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jir=CC=8Ci=CC=81=20Techet?= Date: Thu, 8 Jan 2015 22:32:17 +0100 Subject: [PATCH 07/14] Perform execute using the default terminal application on OS X In order to execute the runner script using the terminal application, the script has to be executable, otherwise it's not executed. In addition, when the terminal application starts, it sets $HOME as the working directory. For this reason the working directory has to be set in the runner script (to avoid additional ifdefs, this part is shared with other unix systems where the additional "cd" shouldn't matter). --- src/build.c | 22 +++++++++++++++++----- src/keyfile.c | 2 ++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/build.c b/src/build.c index 65f75ca8..0645d604 100644 --- a/src/build.c +++ b/src/build.c @@ -128,7 +128,7 @@ static guint build_items_count = 9; static void build_exit_cb(GPid child_pid, gint status, gpointer user_data); static gboolean build_iofunc(GIOChannel *ioc, GIOCondition cond, gpointer data); #endif -static gboolean build_create_shellscript(const gchar *fname, const gchar *cmd, gboolean autoclose, GError **error); +static gboolean build_create_shellscript(const gchar *fname, const gchar *working_dir, const gchar *cmd, gboolean autoclose, GError **error); static GPid build_spawn_cmd(GeanyDocument *doc, const gchar *cmd, const gchar *dir); static void set_stop_button(gboolean stop); static void run_exit_cb(GPid child_pid, gint status, gpointer user_data); @@ -937,7 +937,7 @@ static gchar *prepare_run_script(GeanyDocument *doc, gchar **vte_cmd_nonscript, /* RUN_SCRIPT_CMD should be ok in UTF8 without converting in locale because it * contains no umlauts */ tmp = g_build_filename(working_dir, RUN_SCRIPT_CMD, NULL); - result = build_create_shellscript(tmp, cmd_string, autoclose, &error); + result = build_create_shellscript(tmp, working_dir, cmd_string, autoclose, &error); if (! result) { ui_set_statusbar(TRUE, _("Failed to execute \"%s\" (start-script could not be created: %s)"), @@ -1279,13 +1279,15 @@ static void set_file_error_from_errno(GError **error, gint err, const gchar *pre /* write a little shellscript to call the executable (similar to anjuta_launcher but "internal") * fname is the full file name (including path) for the script to create */ -static gboolean build_create_shellscript(const gchar *fname, const gchar *cmd, gboolean autoclose, GError **error) +static gboolean build_create_shellscript(const gchar *fname, const gchar *working_dir, const gchar *cmd, gboolean autoclose, GError **error) { FILE *fp; gchar *str; gboolean success = TRUE; #ifdef G_OS_WIN32 gchar *expanded_cmd; +#else + gchar *escaped_dir; #endif fp = g_fopen(fname, "w"); @@ -1300,11 +1302,13 @@ static gboolean build_create_shellscript(const gchar *fname, const gchar *cmd, g str = g_strdup_printf("%s\n\n%s\ndel \"%%0\"\n\npause\n", expanded_cmd, (autoclose) ? "" : "pause"); g_free(expanded_cmd); #else + escaped_dir = g_strescape(working_dir, NULL); str = g_strdup_printf( - "#!/bin/sh\n\nrm $0\n\n%s\n\necho \"\n\n------------------\n(program exited with code: $?)\" \ - \n\n%s\n", cmd, (autoclose) ? "" : + "#!/bin/sh\n\nrm $0\n\ncd \'%s\'\n\n%s\n\necho \"\n\n------------------\n(program exited with code: $?)\" \ + \n\n%s\n", escaped_dir, cmd, (autoclose) ? "" : "\necho \"Press return to continue\"\n#to be more compatible with shells like " "dash\ndummy_var=\"\"\nread dummy_var"); + g_free(escaped_dir); #endif if (fputs(str, fp) < 0) @@ -1320,6 +1324,14 @@ static gboolean build_create_shellscript(const gchar *fname, const gchar *cmd, g set_file_error_from_errno(error, errno, "Failed to close file"); success = FALSE; } +#ifdef __APPLE__ + if (g_chmod(fname, 0777) != 0) + { + if (error && ! *error) /* don't set error twice */ + set_file_error_from_errno(error, errno, "Failed to make file executable"); + success = FALSE; + } +#endif return success; } diff --git a/src/keyfile.c b/src/keyfile.c index 157ea324..84a93e19 100644 --- a/src/keyfile.c +++ b/src/keyfile.c @@ -74,6 +74,8 @@ #define GEANY_DEFAULT_TOOLS_MAKE "make" #ifdef G_OS_WIN32 #define GEANY_DEFAULT_TOOLS_TERMINAL "cmd.exe /Q /C %c" +#elif defined(__APPLE__) +#define GEANY_DEFAULT_TOOLS_TERMINAL "open -a terminal %c" #else #define GEANY_DEFAULT_TOOLS_TERMINAL "xterm -e \"/bin/sh %c\"" #endif From 508216b7b47fba88c35c3b4af25a4a1e245f222d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jir=CC=8Ci=CC=81=20Techet?= Date: Thu, 8 Jan 2015 22:34:14 +0100 Subject: [PATCH 08/14] Use the open command to open a directory in Finder on OS X --- plugins/filebrowser.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/filebrowser.c b/plugins/filebrowser.c index 38ce5169..4aea7b8c 100644 --- a/plugins/filebrowser.c +++ b/plugins/filebrowser.c @@ -35,6 +35,8 @@ # include # define OPEN_CMD "explorer \"%d\"" +#elif defined(__APPLE__) +# define OPEN_CMD "open \"%d\"" #else # define OPEN_CMD "nautilus \"%d\"" #endif From daecf69c9cd29891c661d3c52dd0fa7ba451d972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jir=CC=8Ci=CC=81=20Techet?= Date: Thu, 8 Jan 2015 12:01:30 +0100 Subject: [PATCH 09/14] Make keybindings_get_modifiers() part of plugin API --- plugins/geanyfunctions.h | 2 ++ src/keybindings.c | 9 +++++++++ src/keybindings.h | 5 +++++ src/plugindata.h | 2 +- src/plugins.c | 3 ++- 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/plugins/geanyfunctions.h b/plugins/geanyfunctions.h index 615d70ee..3fc3f90c 100644 --- a/plugins/geanyfunctions.h +++ b/plugins/geanyfunctions.h @@ -342,6 +342,8 @@ geany_functions->p_keybindings->keybindings_set_item #define keybindings_get_item \ geany_functions->p_keybindings->keybindings_get_item +#define keybindings_get_modifiers \ + geany_functions->p_keybindings->keybindings_get_modifiers #define tm_get_real_path \ geany_functions->p_tm->tm_get_real_path #define tm_source_file_new \ diff --git a/src/keybindings.c b/src/keybindings.c index 508c0d91..84adec45 100644 --- a/src/keybindings.c +++ b/src/keybindings.c @@ -110,6 +110,15 @@ static void cb_func_move_tab(guint key_id); static void add_popup_menu_accels(void); +/** Gets significant modifiers from a GdkModifierType mask. The set of + * significant modifiers corresponds to the default modifier mask as returned + * by @c gtk_accelerator_get_default_mod_mask(). In addition, it improves + * the Command key handling on OS X by adding @c GEANY_PRIMARY_MOD_MASK + * when needed. For this reason it is preferred to use this function + * instead of @c gtk_accelerator_set_default_mod_mask(). + * @param mods GdkModifierType mask. + * @return Significant modifiers from the mask. + * @since 1.25. */ GdkModifierType keybindings_get_modifiers(GdkModifierType mods) { #ifdef __APPLE__ diff --git a/src/keybindings.h b/src/keybindings.h index 90c6a596..06480100 100644 --- a/src/keybindings.h +++ b/src/keybindings.h @@ -26,6 +26,11 @@ G_BEGIN_DECLS +/** Defines the primary modifier mask which is the Ctrl key mask on + * UNIX/Windows and Command key mask on OS X. When testing for the mask + * presence, use together with keybindings_get_modifiers() which adds + * @c GEANY_PRIMARY_MOD_MASK when needed. + * @since 1.25. */ #ifdef __APPLE__ #define GEANY_PRIMARY_MOD_MASK GDK_META_MASK #else diff --git a/src/plugindata.h b/src/plugindata.h index 3b0f3af0..e4a6a069 100644 --- a/src/plugindata.h +++ b/src/plugindata.h @@ -565,7 +565,7 @@ typedef struct KeybindingFuncs _GeanyKeyCallback callback, guint key, GdkModifierType mod, const gchar *name, const gchar *label, GtkWidget *menu_item); struct GeanyKeyBinding* (*keybindings_get_item)(struct GeanyKeyGroup *group, gsize key_id); - + GdkModifierType (*keybindings_get_modifiers)(GdkModifierType mods); } KeybindingFuncs; diff --git a/src/plugins.c b/src/plugins.c index aeeca293..e9c59721 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -284,7 +284,8 @@ static EncodingFuncs encoding_funcs = { static KeybindingFuncs keybindings_funcs = { &keybindings_send_command, &keybindings_set_item, - &keybindings_get_item + &keybindings_get_item, + &keybindings_get_modifiers }; static TagManagerFuncs tagmanager_funcs = { From 47a5b9fc5fdbd5060671413565f354247f678f75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jir=CC=8Ci=CC=81=20Techet?= Date: Thu, 8 Jan 2015 12:49:03 +0100 Subject: [PATCH 10/14] Use better default fonts on OS X Fonts are rendered much smaller on OS X so use bigger sizes by default. Also, by default they use the Light style which is extremely thin - use Medium instead. Finally, use better monospace font than the default Courier (Menlo is derived from Dejavu Sans Mono and is used by XCode and other editors). --- src/keyfile.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/keyfile.c b/src/keyfile.c index 84a93e19..a5904877 100644 --- a/src/keyfile.c +++ b/src/keyfile.c @@ -81,15 +81,18 @@ #endif #ifdef __APPLE__ #define GEANY_DEFAULT_TOOLS_BROWSER "open -a safari" +#define GEANY_DEFAULT_FONT_SYMBOL_LIST "Helvetica Medium 12" +#define GEANY_DEFAULT_FONT_MSG_WINDOW "Helvetica Medium 12" +#define GEANY_DEFAULT_FONT_EDITOR "Menlo Medium 12" #else #define GEANY_DEFAULT_TOOLS_BROWSER "firefox" +#define GEANY_DEFAULT_FONT_SYMBOL_LIST "Sans 9" +#define GEANY_DEFAULT_FONT_MSG_WINDOW "Sans 9" +#define GEANY_DEFAULT_FONT_EDITOR "Monospace 10" #endif #define GEANY_DEFAULT_TOOLS_PRINTCMD "lpr" #define GEANY_DEFAULT_TOOLS_GREP "grep" #define GEANY_DEFAULT_MRU_LENGTH 10 -#define GEANY_DEFAULT_FONT_SYMBOL_LIST "Sans 9" -#define GEANY_DEFAULT_FONT_MSG_WINDOW "Sans 9" -#define GEANY_DEFAULT_FONT_EDITOR "Monospace 10" #define GEANY_TOGGLE_MARK "~ " #define GEANY_MAX_AUTOCOMPLETE_WORDS 30 #define GEANY_MAX_SYMBOLS_UPDATE_FREQ 250 From 7229aa9cff84b6d42f75edba5b26babd2f6b8b64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrico=20Tr=C3=B6ger?= Date: Sat, 31 Jan 2015 16:11:48 +0100 Subject: [PATCH 11/14] SaveActions: Set file permissions of backup copies to 0600 As discussed in SF bug #125, it might be dangerous to store backup copies in a publicly accessable directory like /tmp with default permissions, especially on multi-user systems. So set the file permissions on non-Windows systems to 0600 by default. Also improve the documentation of the save Actions plugin to reflect this change. --- doc/geany.txt | 17 ++++++++++++++++- plugins/saveactions.c | 14 ++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/doc/geany.txt b/doc/geany.txt index c29372e2..85748e0f 100644 --- a/doc/geany.txt +++ b/doc/geany.txt @@ -5176,8 +5176,23 @@ you can configure the automatically added extension in the configure dialog in Geany's plugin manager. After the plugin was loaded in Geany's plugin manager, every file is -copied into the configured backup directory when the file is saved in Geany. +copied into the configured backup directory *after* the file has been saved +in Geany. +The created backup copy file permissions are set to read-write only for +the user. This should help to not create world-readable files on possibly +unsecure destination directories like /tmp (especially useful +on multi-user systems). +This applies only to non-Windows systems. On Windows, no explicit file +permissions are set. + + +Additionally, you can define how many levels of the original file's +directory structure should be replicated in the backup copy path. +For example, setting the option +*Directory levels to include in the backup destination* to *2* +cause the plugin to create the last two components of the original +file's path in the backup copy path and place the new file there. Contributing to this document diff --git a/plugins/saveactions.c b/plugins/saveactions.c index a97bf199..35b4f20c 100644 --- a/plugins/saveactions.c +++ b/plugins/saveactions.c @@ -27,6 +27,8 @@ #include "geanyplugin.h" #include "gtkcompat.h" +#include +#include #include #include #include @@ -195,6 +197,7 @@ static void backupcopy_document_save_cb(GObject *obj, GeanyDocument *doc, gpoint gchar *dir_parts_src; gchar *stamp; gchar buf[512]; + gint fd_dst = -1; if (! enable_backupcopy) return; @@ -220,7 +223,14 @@ static void backupcopy_document_save_cb(GObject *obj, GeanyDocument *doc, gpoint g_free(basename_src); g_free(dir_parts_src); +#ifdef G_OS_WIN32 if ((dst = g_fopen(locale_filename_dst, "wb")) == NULL) +#else + /* Use g_open() on non-Windows to set file permissions to 600 atomically. + * On Windows, seting file permissions would require specific Windows API. */ + fd_dst = g_open(locale_filename_dst, O_CREAT | O_WRONLY, S_IWUSR | S_IRUSR); + if (fd_dst == -1 || (dst = fdopen(fd_dst, "w")) == NULL) +#endif { ui_set_statusbar(FALSE, _("Backup Copy: File could not be saved (%s)."), g_strerror(errno)); @@ -228,6 +238,8 @@ static void backupcopy_document_save_cb(GObject *obj, GeanyDocument *doc, gpoint g_free(locale_filename_dst); g_free(stamp); fclose(src); + if (fd_dst != -1) + close(fd_dst); return; } @@ -238,6 +250,8 @@ static void backupcopy_document_save_cb(GObject *obj, GeanyDocument *doc, gpoint fclose(src); fclose(dst); + if (fd_dst != -1) + close(fd_dst); g_free(locale_filename_src); g_free(locale_filename_dst); g_free(stamp); From ca21a8759aada71a8f083ef8fc528bfb8988bc89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jir=CC=8Ci=CC=81=20Techet?= Date: Fri, 6 Feb 2015 00:32:10 +0100 Subject: [PATCH 12/14] Don't use "echo -n" in shell scripts The standard says: If the first operand is -n, or if any of the operands contain a backslash ( '\' ) character, the results are implementation-defined. On OS X it simply prints the "-n" string and everything which follows, including the newline. Use printf instead. --- m4/geany-status.m4 | 2 +- po/intl_stats.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/m4/geany-status.m4 b/m4/geany-status.m4 index c98bb78c..c52b7afa 100644 --- a/m4/geany-status.m4 +++ b/m4/geany-status.m4 @@ -27,7 +27,7 @@ EOF # Print a nice top bar # description + ' : ' + value total=`expr $dlen + 3 + $vlen` - for i in `seq 1 $total`; do echo -n '-'; done + for i in `seq 1 $total`; do printf '-'; done echo # And print the actual content diff --git a/po/intl_stats.sh b/po/intl_stats.sh index bfb3505a..f6ea0058 100755 --- a/po/intl_stats.sh +++ b/po/intl_stats.sh @@ -92,7 +92,7 @@ else do # maybe the regexp can be optimized, regexps are not my best friends creationdate=`grep "PO-Revision-Date:" po/$lang.po | sed 's/.*: \([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\} [0-9]\{2\}:[0-9]\{2\}[+|-][0-9]\{4\}\).*/\1/'` - echo -n $eswitch $lang"\t("$creationdate"):\t" + printf "%s %s\t(%s):\t" "$eswitch" "$lang" "$creationdate" msgfmt --check --statistics po/$lang.po; done fi From 6a132ef3fa4a01f7e05a0b8d673407429e3e6c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jir=CC=8Ci=CC=81=20Techet?= Date: Fri, 6 Feb 2015 11:23:10 +0100 Subject: [PATCH 13/14] CR line endings are used on old Mac OS systems only - make it more explicit in labels Also don't default to CR if OS is neither Windows nor Unix (including OS X). There's no other GTK backend right now so it doesn't matter much but still if something else appears, it will most probably not have CR line endings. --- data/geany.glade | 2 +- src/document.h | 4 +--- src/utils.c | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/data/geany.glade b/data/geany.glade index e74ff34c..32fbdfbd 100644 --- a/data/geany.glade +++ b/data/geany.glade @@ -7726,7 +7726,7 @@ True False - Convert and Set to CR (_Mac) + Convert and Set to CR (Classic _Mac) True crlf diff --git a/src/document.h b/src/document.h index ece1b6de..4560d4cf 100644 --- a/src/document.h +++ b/src/document.h @@ -222,10 +222,8 @@ GeanyDocument *document_find_by_id(guint id); #if defined(G_OS_WIN32) # define GEANY_DEFAULT_EOL_CHARACTER SC_EOL_CRLF -#elif defined(G_OS_UNIX) -# define GEANY_DEFAULT_EOL_CHARACTER SC_EOL_LF #else -# define GEANY_DEFAULT_EOL_CHARACTER SC_EOL_CR +# define GEANY_DEFAULT_EOL_CHARACTER SC_EOL_LF #endif extern GeanyFilePrefs file_prefs; diff --git a/src/utils.c b/src/utils.c index 7869a52e..a1f60ca6 100644 --- a/src/utils.c +++ b/src/utils.c @@ -374,7 +374,7 @@ const gchar *utils_get_eol_name(gint eol_mode) switch (eol_mode) { case SC_EOL_CRLF: return _("Win (CRLF)"); break; - case SC_EOL_CR: return _("Mac (CR)"); break; + case SC_EOL_CR: return _("Classic Mac (CR)"); break; default: return _("Unix (LF)"); break; } } From 1ab9eac7047d60e89345694134626fcd1f3a67ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jir=CC=8Ci=CC=81=20Techet?= Date: Tue, 10 Feb 2015 11:56:04 +0100 Subject: [PATCH 14/14] Use the .dylib extension when loading VTE on OS X --- src/vte.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vte.c b/src/vte.c index 0207f784..3875a4ea 100644 --- a/src/vte.c +++ b/src/vte.c @@ -206,9 +206,9 @@ void vte_init(void) gint i; const gchar *sonames[] = { #if GTK_CHECK_VERSION(3, 0, 0) - "libvte2_90.so", "libvte2_90.so.9", + "libvte2_90.so", "libvte2_90.so.9", "libvte2_90.dylib", #else - "libvte.so", "libvte.so.4", "libvte.so.8", "libvte.so.9", + "libvte.so", "libvte.so.4", "libvte.so.8", "libvte.so.9", "libvte.dylib", #endif NULL };