1 /*
2  *  plugme.c
3  *
4  *  Copyright 2012 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #endif
23 
24 #include <string.h>
25 
26 #include "common.h"
27 
28 #include <gp_gtkcompat.h>
29 
30 #include <geanyplugin.h>
31 
32 extern GeanyData *geany_data;
33 
34 /* This file must not depend on Scope */
35 #include "plugme.h"
36 
run_file_chooser(const gchar * title,GtkFileChooserAction action,const gchar * utf8_path)37 static gchar *run_file_chooser(const gchar *title, GtkFileChooserAction action,
38 		const gchar *utf8_path)
39 {
40 	GtkWidget *dialog = gtk_file_chooser_dialog_new(title,
41 		GTK_WINDOW(geany->main_widgets->window), action,
42 		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
43 		GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
44 	gchar *locale_path;
45 	gchar *ret_path = NULL;
46 
47 	gtk_widget_set_name(dialog, "GeanyDialog");
48 	locale_path = utils_get_locale_from_utf8(utf8_path);
49 	if (action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
50 	{
51 		if (g_path_is_absolute(locale_path) && g_file_test(locale_path, G_FILE_TEST_IS_DIR))
52 			gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), locale_path);
53 	}
54 	else if (action == GTK_FILE_CHOOSER_ACTION_OPEN)
55 	{
56 		if (g_path_is_absolute(locale_path))
57 			gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), locale_path);
58 	}
59 	g_free(locale_path);
60 
61 	if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
62 	{
63 		gchar *dir_locale;
64 
65 		dir_locale = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
66 		ret_path = utils_get_utf8_from_locale(dir_locale);
67 		g_free(dir_locale);
68 	}
69 	gtk_widget_destroy(dialog);
70 	return ret_path;
71 }
72 
ui_path_box_open_clicked(G_GNUC_UNUSED GtkButton * button,gpointer user_data)73 static void ui_path_box_open_clicked(G_GNUC_UNUSED GtkButton *button, gpointer user_data)
74 {
75 	GtkWidget *path_box = GTK_WIDGET(user_data);
76 	GtkFileChooserAction action = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(path_box), "action"));
77 	GtkEntry *entry = g_object_get_data(G_OBJECT(path_box), "entry");
78 	const gchar *title = g_object_get_data(G_OBJECT(path_box), "title");
79 	gchar *utf8_path = NULL;
80 
81 	/* TODO: extend for other actions */
82 	g_return_if_fail(action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
83 					 action == GTK_FILE_CHOOSER_ACTION_OPEN);
84 
85 	if (title == NULL)
86 		title = (action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) ?
87 			_("Select Folder") : _("Select File");
88 
89 	if (action == GTK_FILE_CHOOSER_ACTION_OPEN)
90 	{
91 		utf8_path = run_file_chooser(title, action, gtk_entry_get_text(GTK_ENTRY(entry)));
92 	}
93 	else if (action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
94 	{
95 		gchar *path = g_path_get_dirname(gtk_entry_get_text(GTK_ENTRY(entry)));
96 		utf8_path = run_file_chooser(title, action, path);
97 		g_free(path);
98 	}
99 
100 	if (utf8_path != NULL)
101 	{
102 		gtk_entry_set_text(GTK_ENTRY(entry), utf8_path);
103 		g_free(utf8_path);
104 	}
105 }
106 
107 /* Setup a GtkButton to run a GtkFileChooser, setting entry text if successful.
108  * title can be NULL.
109  * action is the file chooser mode to use. */
plugme_ui_setup_open_button_callback(GtkWidget * open_btn,const gchar * title,GtkFileChooserAction action,GtkEntry * entry)110 void plugme_ui_setup_open_button_callback(GtkWidget *open_btn, const gchar *title,
111 		GtkFileChooserAction action, GtkEntry *entry)
112 {
113 	GtkWidget *path_entry = GTK_WIDGET(entry);
114 
115 	if (title)
116 		g_object_set_data_full(G_OBJECT(open_btn), "title", g_strdup(title),
117 				(GDestroyNotify) g_free);
118 	g_object_set_data(G_OBJECT(open_btn), "action", GINT_TO_POINTER(action));
119 	ui_hookup_widget(open_btn, path_entry, "entry");
120 	g_signal_connect(open_btn, "clicked", G_CALLBACK(ui_path_box_open_clicked), open_btn);
121 }
122 
123 /* Note: this is NOT the Geany function, only similar */
plugme_editor_get_default_selection(GeanyEditor * editor,gboolean use_current_word,const gchar * wordchars)124 gchar *plugme_editor_get_default_selection(GeanyEditor *editor, gboolean use_current_word,
125 									const gchar *wordchars)
126 {
127 	ScintillaObject *sci = editor->sci;
128 	gchar *text = NULL;
129 
130 	if (sci_has_selection(sci))
131 	{
132 		if (sci_get_selected_text_length(sci) < GEANY_MAX_WORD_LENGTH)
133 		{
134 			text = sci_get_selection_contents(sci);
135 
136 			if (strchr(text, '\n') != NULL)
137 				*strchr(text, '\n') = '\0';
138 		}
139 	}
140 	else if (use_current_word)
141 		text = editor_get_word_at_pos(editor, sci_get_current_position(sci), wordchars);
142 
143 	return text;
144 }
145 
on_config_file_clicked(G_GNUC_UNUSED GtkWidget * widget,gpointer user_data)146 static void on_config_file_clicked(G_GNUC_UNUSED GtkWidget *widget, gpointer user_data)
147 {
148 	const gchar *file_name = user_data;
149 	GeanyFiletype *ft = NULL;
150 
151 	if (strstr(file_name, G_DIR_SEPARATOR_S "filetypes."))
152 		ft = filetypes_index(GEANY_FILETYPES_CONF);
153 
154 	if (g_file_test(file_name, G_FILE_TEST_EXISTS))
155 		document_open_file(file_name, FALSE, ft, NULL);
156 	else
157 	{
158 		gchar *utf8_filename = utils_get_utf8_from_locale(file_name);
159 		gchar *base_name = g_path_get_basename(file_name);
160 		gchar *global_file = g_build_filename(geany->app->datadir, base_name, NULL);
161 		gchar *global_content = NULL;
162 
163 		/* if the requested file doesn't exist in the user's config dir, try loading the file
164 		 * from the global data directory and use its contents for the newly created file */
165 		if (g_file_test(global_file, G_FILE_TEST_EXISTS))
166 			g_file_get_contents(global_file, &global_content, NULL, NULL);
167 
168 		document_new_file(utf8_filename, ft, global_content);
169 
170 		g_free(utf8_filename);
171 		g_free(base_name);
172 		g_free(global_file);
173 		g_free(global_content);
174 	}
175 }
176 
free_on_closure_notify(gpointer data,G_GNUC_UNUSED GClosure * closure)177 static void free_on_closure_notify(gpointer data, G_GNUC_UNUSED GClosure *closure)
178 {
179 	g_free(data);
180 }
181 
plugme_ui_add_config_file_menu_item(const gchar * real_path,const gchar * label,GtkContainer * parent)182 GtkWidget *plugme_ui_add_config_file_menu_item(const gchar *real_path, const gchar *label,
183 		GtkContainer *parent)
184 {
185 	GtkWidget *item;
186 
187 	if (!parent)
188 	{
189 		item = ui_lookup_widget(geany->main_widgets->window, "configuration_files1");
190 		parent = GTK_CONTAINER(gtk_menu_item_get_submenu(GTK_MENU_ITEM(item)));
191 	}
192 
193 	if (!label)
194 	{
195 		gchar *base_name;
196 
197 		base_name = g_path_get_basename(real_path);
198 		item = gtk_menu_item_new_with_label(base_name);
199 		g_free(base_name);
200 	}
201 	else
202 		item = gtk_menu_item_new_with_mnemonic(label);
203 
204 	gtk_widget_show(item);
205 	gtk_container_add(parent, item);
206 	g_signal_connect_data(item, "activate", G_CALLBACK(on_config_file_clicked),
207 			g_strdup(real_path), free_on_closure_notify, 0);
208 
209 	return item;
210 }
211