2
* This file is a part of the Cairo-Dock project
4
* Copyright : (C) see the 'copyright' file.
5
* E-mail : see the 'copyright' file.
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; either version 3
10
* of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
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/>.
20
/******************************************************************************
22
This file is a part of the cairo-dock program,
23
released under the terms of the GNU General Public License.
25
Adapted from the Gnome-panel for Cairo-Dock by Fabrice Rey (for any bug report, please mail me to fabounet@users.berlios.de)
27
******************************************************************************/
29
#include "applet-struct.h"
30
#include "applet-run-dialog.h"
36
#include <sys/types.h>
40
#include <gdk/gdkkeysyms.h>
44
fill_files_from (const char *dirname,
45
const char *dirprefix,
47
GList *existing_items)
54
dir = opendir (dirname);
59
while ((dent = readdir (dir))) {
65
dent->d_name [0] != prefix)
68
file = g_build_filename (dirname, dent->d_name, NULL);
72
/* don't use g_file_test at first so we don't stat() */
73
dent->d_type == DT_DIR ||
74
(dent->d_type == DT_LNK &&
75
g_file_test (file, G_FILE_TEST_IS_DIR))
76
//g_file_test (file, G_FILE_TEST_IS_DIR)
82
item = g_build_filename (dirprefix, dent->d_name, suffix, NULL);
84
list = g_list_prepend (list, item);
93
fill_possible_executables (void)
101
path = g_getenv ("PATH");
103
if (!path || !path [0])
106
pathv = g_strsplit (path, ":", 0);
108
for (i = 0; pathv [i]; i++) {
113
dir = g_dir_open (pathv [i], 0, NULL);
118
while ((file = g_dir_read_name (dir))) {
119
filename = g_build_filename (pathv [i], file, NULL);
120
list = g_list_prepend (list, filename);
132
fill_executables (GList *possible_executables,
133
GList *existing_items,
141
for (l = possible_executables; l; l = l->next) {
142
const char *filename;
146
basename = g_path_get_basename (filename);
148
if (basename [0] == prefix &&
149
g_file_test (filename, G_FILE_TEST_IS_REGULAR) &&
150
g_file_test (filename, G_FILE_TEST_IS_EXECUTABLE)) {
152
if (g_list_find_custom (existing_items, basename,
153
(GCompareFunc) strcmp)) {
158
list = g_list_prepend (list, basename);
167
static void cd_menu_run_dialog_update_completion (CairoDockModuleInstance *myApplet,
178
g_assert (text != NULL && *text != '\0' && !g_ascii_isspace (*text));
183
if (!myData.completion) {
184
myData.completion = g_completion_new (NULL);
185
myData.possible_executables = fill_possible_executables ();
186
myData.dir_hash = g_hash_table_new_full (g_str_hash,
191
buf = g_path_get_basename (text);
194
if (prefix == '/' || prefix == '.')
197
if (text [0] == '/') {
198
/* complete against absolute path */
199
dirname = g_path_get_dirname (text);
200
dirprefix = g_strdup (dirname);
202
/* complete against relative path and executable name */
203
if (!strchr (text, '/')) {
204
executables = fill_executables (myData.possible_executables,
205
myData.completion_items,
207
dirprefix = g_strdup ("");
209
dirprefix = g_path_get_dirname (text);
212
dirname = g_build_filename (g_get_home_dir (), dirprefix, NULL);
215
key = g_strdup_printf ("%s%c%c", dirprefix, G_DIR_SEPARATOR, prefix);
217
if (!g_hash_table_lookup (myData.dir_hash, key)) {
218
g_hash_table_insert (myData.dir_hash, key, myApplet);
220
list = fill_files_from (dirname, dirprefix, prefix,
221
myData.completion_items);
226
list = g_list_concat (list, executables);
234
g_completion_add_items (myData.completion, list);
236
myData.completion_items = g_list_concat (myData.completion_items, list);
239
static gboolean _entry_event (GtkEditable *entry,
241
CairoDockModuleInstance *myApplet)
243
GtkTreeSelection *selection;
245
char *nospace_prefix;
250
if (event->type != GDK_KEY_PRESS)
254
if (event->keyval == GDK_Tab) {
255
gtk_editable_get_selection_bounds (entry, &pos, &tmp);
257
if (myData.completion_started &&
260
tmp == strlen (gtk_entry_get_text (GTK_ENTRY (entry)))) {
261
gtk_editable_select_region (entry, 0, 0);
262
gtk_editable_set_position (entry, -1);
266
} else if (event->length > 0) {
268
gtk_editable_get_selection_bounds (entry, &pos, &tmp);
270
if (myData.completion_started &&
273
tmp == strlen (gtk_entry_get_text (GTK_ENTRY (entry)))) {
274
temp = gtk_editable_get_chars (entry, 0, pos);
275
prefix = g_strconcat (temp, event->string, NULL);
277
} else if (pos == tmp &&
278
tmp == strlen (gtk_entry_get_text (GTK_ENTRY (entry)))) {
279
prefix = g_strconcat (gtk_entry_get_text (GTK_ENTRY (entry)),
280
event->string, NULL);
285
nospace_prefix = prefix;
286
while (g_ascii_isspace (*nospace_prefix))
288
if (*nospace_prefix == '\0')
291
cd_menu_run_dialog_update_completion (myApplet, nospace_prefix);
293
if (!myData.completion) {
298
pos = strlen (prefix);
301
g_completion_complete_utf8 (myData.completion,
309
temp = g_strndup (prefix, nospace_prefix - prefix);
312
prefix = g_strconcat (temp, nprefix, NULL);
314
gtk_editable_delete_text (entry, 0, -1);
316
gtk_editable_insert_text (entry,
317
prefix, strlen (prefix),
320
gtk_editable_set_position (entry, pos);
321
gtk_editable_select_region (entry, pos, -1);
323
myData.completion_started = TRUE;
339
static void _cd_menu_on_quick_launch (int iClickedButton, GtkWidget *pInteractiveWidget, gpointer data, CairoDialog *pDialog)
341
if (iClickedButton == 0 || iClickedButton == -1) // ok ou entree.
343
const gchar *cCommand = gtk_entry_get_text (GTK_ENTRY (pInteractiveWidget));
344
if (cCommand != NULL && *cCommand != '0')
345
cairo_dock_launch_command (cCommand);
349
gtk_entry_set_text (GTK_ENTRY (pInteractiveWidget), "");
351
cairo_dock_dialog_reference (myData.pQuickLaunchDialog);
352
cairo_dock_hide_dialog (myData.pQuickLaunchDialog);
354
CairoDialog *cd_menu_create_quick_launch_dialog (CairoDockModuleInstance *myApplet)
356
CairoDialog *pDialog = cairo_dock_show_dialog_with_entry (D_("Enter a command to launch :"),
358
MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE,
360
(CairoDockActionOnAnswerFunc) _cd_menu_on_quick_launch, NULL, NULL);
362
GtkWidget *pEntry = pDialog->pInteractiveWidget;
363
g_signal_connect (pEntry, "key-press-event",
364
G_CALLBACK (_entry_event),