1 #ifdef COPYRIGHT_INFORMATION
2 #include "gplv3.h"
3 #endif
4 #include "primary-internal.h"
5 /*
6 * Copyright (C) 2002-2012 Edscott Wilson Garcia
7 * EMail: edscott@users.sf.net
8 *
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program;
22 */
23
24 // All these functions are thread called. GDK mutex must be
25 // locked if instruction set requires this mutex.
26
27
28 // XXX duplicate and symlink could be multiple selection
29
30
31
32 // These callbacks will be processed by keybindings and showed in the
33 // keybindings listing. If a menu option is not listed here, then it will
34 // not be subject to a keybinding, nor a keybinding modification.
35 static
36 RodentCallback menu_callback_v[]={
37 // F keys
38 HELP_CALLBACK,
39 SETTINGS_CALLBACK,
40 MENU_CALLBACK,
41 TERMINAL_CALLBACK,
42 RELOAD_CALLBACK,
43 RUN_CALLBACK,
44 SEARCH_CALLBACK,
45 DIFFERENCES_CALLBACK,
46 // ADD_BOOKMARK_CALLBACK,
47 // REMOVE_BOOKMARK_CALLBACK,
48 CASE_SORT_CALLBACK,
49 TOGGLE_BOOKMARK_CALLBACK,
50 // ctrl F keys
51 SORT_ASCENDING_CALLBACK,
52 SORT_DESCENDING_CALLBACK,
53 NAME_SORT_CALLBACK,
54 TYPE_SORT_CALLBACK,
55 DATE_SORT_CALLBACK,
56 SIZE_SORT_CALLBACK,
57 OWNER_SORT_CALLBACK,
58 GROUP_SORT_CALLBACK,
59 MODE_SORT_CALLBACK,
60 KEYBINDINGS_CALLBACK,
61 //
62 NEW_FILE_CALLBACK,
63 NEWDIR_CALLBACK,
64 BCRYPT_CALLBACK,
65 RENAME_CALLBACK,
66 DUPLICATE_CALLBACK,
67 SYMLINK_CALLBACK,
68 TOUCH_CALLBACK,
69 PROPERTIES_CALLBACK,
70 SELECT_ALL_CALLBACK,
71 SELECT_INVERT_CALLBACK,
72 SELECT_BYFILTER_CALLBACK,
73 UNSELECT_BYFILTER_CALLBACK,
74 UNSELECT_ALL_CALLBACK,
75 NEW_TAB_CALLBACK,
76 NEW_WINDOW_CALLBACK,
77 SHOW_HIDDEN_CALLBACK,
78 SHOW_BACKUP_CALLBACK,
79 PREVIEW_IMAGES_CALLBACK,
80 COMPACT_ICONSIZE_CALLBACK,
81 TINY_ICONSIZE_CALLBACK,
82 NORMAL_ICONSIZE_CALLBACK,
83 BIG_ICONSIZE_CALLBACK,
84 HUGE_ICONSIZE_CALLBACK,
85 PLUS_ICONSIZE_CALLBACK,
86 MINUS_ICONSIZE_CALLBACK,
87 ABOUT_CALLBACK,
88 JUMP_TO_CALLBACK,
89 GOTO_HOST_CALLBACK,
90 GOTO_HOME_CALLBACK,
91 GO_UP_CALLBACK,
92 GO_BACK_CALLBACK,
93 GO_FORWARD_CALLBACK,
94 CUT_CALLBACK,
95 COPY_CALLBACK,
96 PASTE_CALLBACK,
97 REMOVE_CALLBACK,
98 // AUTOTYPE_CALLBACK,
99 // AUTOTYPE_R_CALLBACK,
100 OPEN_WITH_CALLBACK,
101 FIND_CALLBACK,
102 MOUNT_CALLBACK,
103 UNMOUNT_CALLBACK,
104 CLOSE_CALLBACK,
105 LS_CALLBACK,
106 NULL_CALLBACK
107 };
108
109 static RodentCallback*
get_menu_callback_p(gint menu_enum)110 get_menu_callback_p(gint menu_enum){
111 gint i;
112 // Check if menu_enum is defined in menu_callback_v
113 for (i=0; menu_callback_v[i].function_id >= 0; i++){
114 if (menu_enum==menu_callback_v[i].function_id) {
115 // Now check whether function_id is valid
116 if (menu_callback_v[i].function_id >= ENUM_CALLBACKS) return NULL;
117 return &(menu_callback_v[i]);
118 }
119 }
120 return NULL;
121 }
122
123 static gboolean
is_valid_view_entry(widgets_t * widgets_p,gint menu_enum)124 is_valid_view_entry(widgets_t *widgets_p, gint menu_enum){
125 view_t *view_p = widgets_p->view_p;
126 if (!rfm_entry_available(widgets_p, view_p->en)) {
127 RodentCallback *menu_callback_p = get_menu_callback_p(menu_enum);
128 rfm_show_text(widgets_p);
129 rfm_threaded_diagnostics(widgets_p, "xffm/stock_dialog-warning", NULL);
130 rfm_threaded_diagnostics(widgets_p, "xffm_tag/blue",
131 g_strconcat(
132 (menu_callback_p->string)?_(menu_callback_p->string):".",
133 ": ", _( "Could not validate the transaction"), "\n",NULL));
134 NOOP("callback_enter(): view entry is no longer valid\n");
135 return FALSE;
136 }
137 return TRUE;
138 }
139
140 static gboolean
is_single_selection(widgets_t * widgets_p,gint menu_enum)141 is_single_selection(widgets_t *widgets_p, gint menu_enum){
142 view_t *view_p = widgets_p->view_p;
143 if (g_slist_length(view_p->selection_list) != 1){
144 RodentCallback *menu_callback_p = get_menu_callback_p(menu_enum);
145 rfm_threaded_show_text(widgets_p);
146 rfm_threaded_diagnostics(widgets_p, "xffm/stock_dialog-warning",NULL);
147 rfm_threaded_diagnostics(widgets_p, "xffm_tag/blue",
148 g_strconcat((menu_callback_p->string)?_(menu_callback_p->string):".",
149 ": ", _( "No selection available"), "\n",NULL));
150 return FALSE;
151 }
152 return TRUE;
153 }
154
155
156 static gboolean
is_multiple_selection(widgets_t * widgets_p,gint menu_enum)157 is_multiple_selection(widgets_t *widgets_p, gint menu_enum){
158 view_t *view_p = widgets_p->view_p;
159 if (g_slist_length(view_p->selection_list) == 0){
160 RodentCallback *menu_callback_p = get_menu_callback_p(menu_enum);
161 rfm_threaded_show_text(widgets_p);
162 rfm_threaded_diagnostics(widgets_p, "xffm/stock_dialog-warning",NULL);
163 rfm_threaded_diagnostics(widgets_p, "xffm_tag/blue",
164 g_strconcat(
165 (menu_callback_p->string)?_(menu_callback_p->string):".",
166 ": ", _( "No group selected"), "\n",NULL));
167 return FALSE;
168 }
169 return TRUE;
170 }
171 static void
time_out_message(widgets_t * widgets_p,const gchar * path)172 time_out_message(widgets_t *widgets_p, const gchar *path){
173 rfm_threaded_show_text(widgets_p);
174 rfm_threaded_diagnostics(widgets_p, "xffm/stock_dialog-error", g_strconcat(path, ": ", NULL));
175 rfm_threaded_diagnostics(widgets_p, "xffm_tag/stderr", g_strconcat(_(strerror(ETIMEDOUT)), "\n", NULL));
176 rfm_global_t *rfm_global_p = rfm_global();
177 rfm_threaded_cursor_reset(rfm_global_p->window);
178 return;
179 }
180 ///////////////////////////////////////////////////////////////////////////////////
181 ///******************************************************************************/
182 //////////////////////////////////////////////////////////////////////////////////
183 static void jump_to (widgets_t *widgets_p);
184 static void open_x(widgets_t *widgets_p);
185 static void
open_with(widgets_t * widgets_p,record_entry_t * en)186 open_with (widgets_t *widgets_p, record_entry_t * en) {
187 /* open with */
188 gchar *command=NULL;
189 gchar *command_fmt=NULL;
190 NOOP ("open_with()... \n");
191
192 if(!en || !en->path) {
193 NOOP ("OPEN: open_with !en || !en->path\n");
194 return;
195 }
196
197 gchar *wd = g_path_get_dirname (en->path);
198 if (!rfm_g_file_test_with_wait (wd, G_FILE_TEST_EXISTS)){
199 time_out_message(widgets_p, wd);
200 g_free(wd);
201 wd = g_strdup(g_get_home_dir());
202 }
203
204 g_free (widgets_p->workdir);
205 widgets_p->workdir = wd;
206
207 // Here we take special consideration for shell scripts.
208 // Shell scripts will be editable files, therefore will
209 // have an associated mime_command to open the editor.
210 // tests
211
212 if (!en->mimetype) en->mimetype=MIME_type (en->path, en->st);
213 if(!en->mimemagic){
214 if (IS_LOCAL_TYPE(en->type) && !en->mimemagic) {
215 en->mimemagic = rfm_rational(RFM_MODULE_DIR, "mime", en, "mime_magic", "mime_function");
216 if (!en->mimemagic) en->mimemagic = g_strdup(_("unknown"));
217 }
218 else en->mimemagic = g_strdup(_("unknown"));
219 }
220
221 if(!en->filetype) {
222 if (IS_LOCAL_TYPE(en->type)) {
223 en->filetype = rfm_rational(RFM_MODULE_DIR, "mime", en, "mime_file", "mime_function");
224 if (!en->filetype) en->filetype = g_strdup(_("unknown"));
225 }
226 else en->filetype = g_strdup(_("unknown"));
227 }
228
229 command_fmt = MIME_command (en->mimetype);
230 NOOP ("OPEN: command_fmt(%s) = %s\n", en->mimetype, command_fmt);
231 if(!command_fmt) {
232 command_fmt = MIME_command (en->mimemagic);
233 }
234
235 gboolean is_script= ((en->mimetype && strstr (en->mimetype, "/x-sh")) ||
236 (en->mimemagic && strstr (en->mimemagic, "/x-sh")) ||
237 (en->mimetype && strstr (en->mimetype, "/x-shellscript")) ||
238 (en->mimemagic && strstr (en->mimemagic, "/x-shellscript")) ||
239 (en->mimetype && strstr (en->mimetype, "/x-csh")) ||
240 (en->mimemagic && strstr (en->mimemagic, "/x-csh")) ||
241 (en->mimetype && strstr (en->mimetype, "/x-perl")) ||
242 (en->mimemagic && strstr (en->mimemagic, "/x-perl")) );
243 if (is_script && !IS_EXE_TYPE(en->type)){
244 g_free(command_fmt);
245 command_fmt = NULL;
246 }
247
248 // for default editor...
249 gchar *text_editor = NULL;
250 if(!command_fmt) {
251 text_editor = rodent_get_text_editor(en);
252 NOOP ("OPEN: text_editor = %s\n", text_editor);
253 if(text_editor) {
254 /* OK to apply an editor */
255 command_fmt = g_strconcat(text_editor, " ", NULL);
256 }
257 }
258
259 //command_fmt=get_command_fmt(en);
260 if (is_script) {
261 rfm_threaded_show_text(widgets_p);
262 if (!IS_EXE_TYPE(en->type)){
263 rfm_threaded_diagnostics(widgets_p, "xffm/stock_dialog-warning",
264 g_strconcat(en->path, "\n", NULL));
265 rfm_threaded_diagnostics(widgets_p, "xffm_tag/stderr",
266 g_strconcat(_("The program exists, but is not executable.\nPlease check your installation and/or install the binary properly."),
267 "\n", NULL));
268 rfm_threaded_diagnostics(widgets_p, "xffm/stock_dialog-info", NULL);
269 gchar *text=g_strdup_printf (_("Open with %s"), _("Text Editor"));
270 gchar *base=g_path_get_basename(en->path);
271 rfm_threaded_diagnostics(widgets_p, "xffm_tag/green", g_strconcat(text, ": ", base, "\n", NULL));
272 g_free(base);
273 g_free(text);
274 }
275 }
276
277 NOOP ("open_with(): magic=%s, mime=%s, command_fmt=%s, editor=%s\n",
278 en->mimemagic, en->mimetype, command_fmt, text_editor);
279 g_free(text_editor);
280
281 if(command_fmt) {
282 command = MIME_mk_command_line (command_fmt, en->path);
283 TRACE( "OPEN: command = %s\n", command);
284
285 RFM_THREAD_RUN2ARGV (widgets_p, command, FALSE);
286 g_free (command);
287 g_free (command_fmt);
288 } else {
289 open_x(widgets_p);
290 //rodent_open_with_activate (NULL, (gpointer) widgets_p);
291 }
292 return;
293 }
294
295
296 // This is used by the go back callback
297 static void
pop_view_go_history(view_t * view_p)298 pop_view_go_history (view_t * view_p) {
299 GList *last;
300 if(!view_p->go_list)
301 return;
302 last = g_list_last (view_p->go_list);
303 if(!last) {
304 g_list_free (view_p->go_list);
305 view_p->go_list = NULL;
306 return;
307 }
308 view_p->go_list = g_list_remove (view_p->go_list, last->data);
309 if(!g_list_length (view_p->go_list)) {
310 g_list_free (view_p->go_list);
311 view_p->go_list = NULL;
312 return;
313 }
314 return;
315 }
316
317 // This is used by the goto callback
get_jumpto_dir(widgets_t * widgets_p)318 static gchar *get_jumpto_dir(widgets_t *widgets_p){
319 if (g_thread_self() == rfm_get_gtk_thread()){
320 g_error("get_jumpto_dir() is a thread function\n");
321 }
322 view_t *view_p = widgets_p->view_p;
323 gchar *f = g_build_filename (GOTO_DBH_FILE, NULL);
324 gchar *response = get_response_history ( _("Go To"), _("Path"),
325 NULL, // extra_text
326 f,
327 NULL, NULL, NULL, NULL,
328 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
329 g_get_home_dir (),
330 MATCH_FILE);
331 g_free (f);
332
333 NOOP("dialog returned with %s\n", response);
334 if (!response) return NULL;
335 gchar *choice = response;
336
337 g_strstrip(choice);
338 if (strlen(choice)==0) {
339 g_free(choice);
340 return NULL;
341 }
342 if (g_path_is_absolute(choice)){
343 if (!rfm_g_file_test_with_wait (choice, G_FILE_TEST_EXISTS)){
344 time_out_message(widgets_p, choice);
345 g_free(choice);
346 return NULL;
347 }
348 } else {
349 // make path absolute
350 const gchar *dirname;
351 if (view_p->en && view_p->en->path) dirname = view_p->en->path;
352 else dirname = g_get_home_dir();
353 gchar *fullpath = g_build_filename(dirname, choice, NULL);
354 if (!rfm_g_file_test_with_wait (fullpath, G_FILE_TEST_EXISTS)){
355 time_out_message(widgets_p, fullpath);
356 g_free(fullpath);
357 g_free(choice);
358 return NULL;
359 }
360 g_free(fullpath);
361 }
362
363
364 if(!rfm_g_file_test_with_wait (choice, G_FILE_TEST_IS_DIR)) {
365 gchar *text=g_strdup_printf(_("%s does not exist."), choice);
366 rfm_confirm (widgets_p,GTK_MESSAGE_ERROR, text, NULL, NULL);
367 g_free(choice);
368 g_free(text);
369 return NULL;
370 }
371 else if(chdir (choice) < 0) {
372 rfm_threaded_show_text(widgets_p);
373 rfm_threaded_diagnostics (widgets_p, "xffm/stock_dialog-error", NULL);
374 rfm_threaded_diagnostics (widgets_p, "xffm_tag/stderr", g_strconcat(choice, ": ", strerror (errno), "\n", NULL));
375 g_free(choice);
376 return NULL;
377 }
378 g_free(choice);
379 gchar *g = g_get_current_dir ();
380 SETWD();
381 return g;
382 }
383
384 /*****************************************************************************/
385
386 // Used by execute()
387 static gchar *
get_command_fmt(record_entry_t * en)388 get_command_fmt(record_entry_t *en) {
389 gchar *command_fmt = MIME_command (en->mimetype);
390 if(!command_fmt) {
391 command_fmt = MIME_command (en->mimemagic);
392 }
393 gboolean is_text = ((en->mimetype && strstr (en->mimetype, "text/")) ||
394 (en->mimemagic && strstr (en->mimemagic, "text/")) ||
395 (en->filetype && strstr (en->filetype, "text")));
396 if(!command_fmt && is_text && getenv ("EDITOR_CMD") && strlen (getenv ("EDITOR_CMD"))) {
397 command_fmt = g_strdup (getenv ("EDITOR_CMD"));
398 }
399 return command_fmt;
400 }
401
402 // Used by execute()
403 static gchar *
strip_path(gchar * command_fmt,const gchar * path)404 strip_path(gchar *command_fmt, const gchar *path){
405 if (!path) return command_fmt;
406 NOOP("stipping %s\n", command_fmt);
407 if (strstr(command_fmt, path)){
408 gchar *end = strstr(command_fmt,path) + strlen(path);
409 *strstr(command_fmt, path) = 0;
410 gchar *g = g_strconcat(command_fmt, "%","s",end, NULL);
411 g_free(command_fmt);
412 command_fmt=g;
413 NOOP("stipped %s\n", command_fmt);
414 return command_fmt;
415 }
416 // What if the path is quoted or escaped or both
417 gchar *esc_path = rfm_esc_string (path);
418 if (strstr(command_fmt, esc_path)){
419 command_fmt = strip_path(command_fmt, esc_path);
420 }
421 g_free(esc_path);
422 return command_fmt;
423 }
424
425 typedef struct execute_t{
426 widgets_t *widgets_p;
427 GSList *list;
428 } execute_t;
429
430 // Used by run and open-with callbacks
431 // This opens the confirmation or user input dialog.
432 static void *
execute(widgets_t * widgets_p,GSList * selection_list)433 execute (widgets_t *widgets_p, GSList *selection_list) {
434 if (g_thread_self() == rfm_get_gtk_thread()){
435 g_error("execute() is a thread function\n");
436 }
437
438 view_t *view_p = widgets_p->view_p;
439 //GSList *selection_list = execute_p->list;
440 gpointer retval=GINT_TO_POINTER(1);
441
442 gchar *command_fmt=NULL;
443 /* set the working directory */
444 g_free (widgets_p->workdir);
445 if(view_p->en && IS_LOCAL_TYPE(view_p->en->type) && view_p->en->path)
446 widgets_p->workdir = g_strdup (view_p->en->path);
447 else
448 widgets_p->workdir = g_strdup (g_get_home_dir ());
449
450 TRACE ("execute()...\n");
451 gchar *files = NULL;
452 gchar *files_txt;
453
454 gchar *first_path=NULL;
455 if(selection_list) {
456 files_txt = g_strdup_printf (_("Open with %s"),": \n\n");
457 if(g_slist_length (selection_list)) {
458 gchar *tt,
459 *ttt;
460 files = g_strdup (" ");
461 GSList *tmp = selection_list;
462 for(; tmp; tmp = tmp->next) {
463 record_entry_t *en = (record_entry_t *) tmp->data;
464 char *b = g_path_get_basename (en->path);
465 gchar *q = rfm_utf_string (rfm_chop_excess (b));
466 tt = g_strconcat (files_txt, q, "\n", NULL);
467 gchar *esc_path = rfm_esc_string (en->path);
468 if (!first_path){
469 first_path=g_strdup(esc_path);
470 command_fmt=get_command_fmt(en);
471 }
472 ttt = g_strconcat (files, esc_path, " ", NULL);
473 g_free (esc_path);
474 g_free (files_txt);
475 g_free (q);
476 g_free (b);
477 g_free (files);
478 files_txt = tt;
479 files = ttt;
480 }
481 }
482 } else {
483 // no selection
484 files_txt = g_strdup_printf ("%s \n\n", _("Command:"));
485 }
486 NOOP ("OPEN: files=%s\n", files);
487 NOOP ("OPEN: first_path=%s\n", first_path);
488 gboolean interm = FALSE;
489 gchar *g=NULL;
490 {
491 gchar *f = g_build_filename (RUN_DBH_FILE, NULL);
492 gchar *ff = g_build_filename (RUN_FLAG_FILE, NULL);
493 NOOP (stderr, "RUN_DBH_FILE=%s RUN_FLAG_FILE=%s\n", f, ff);
494
495 gchar *title;
496 if (selection_list) {
497 title=g_strdup_printf(_("Open with %s"),"");
498 } else {
499 title=g_strdup(_("Execute Shell Command"));
500 }
501 g = get_response_history (title,
502 files_txt,
503 _("Console: quickly run single commands -- write a command here and press enter."),
504 f,
505 first_path,
506 command_fmt, //NULL, // entry text
507 ff,
508 _("Run in Terminal"),
509 GTK_FILE_CHOOSER_ACTION_OPEN,
510 "/usr/bin",
511 MATCH_COMMAND);
512 g_free (f);
513 g_free (ff);
514 NOOP(stderr, "got: \"%s\"\n", g);
515 }
516 g_free (first_path);
517 g_free (command_fmt);
518
519 g_free (files_txt);
520 if(!g) {
521 NOOP ("on_open_with_activate... !g\n");
522 retval=NULL;
523 goto cleanup;
524 }
525 if(g[strlen (g) + 1])
526 interm = TRUE;
527
528 if(selection_list) {
529 /* if only one file selected, associate to mimetype...
530 * but not default unless no other command available
531 * (i.e., append, not prepend)*/
532 if(g_slist_length (selection_list) == 1) {
533 record_entry_t *en = selection_list->data;
534 if(!en->mimetype || strcmp(en->mimetype, _("unknown"))==0) {
535 if (IS_LOCAL_TYPE(en->type) && !en->mimemagic) {
536 en->mimemagic = rfm_rational(RFM_MODULE_DIR, "mime", en, "mime_magic", "mime_function");
537 if (!en->mimemagic) en->mimemagic = g_strdup(_("unknown"));
538 }
539 }
540 const gchar *type = en->mimetype;
541 if (!type || strcmp(type, _("unknown"))==0) type = en->mimemagic;
542 if(type) {
543 gchar *command_fmt = g_strdup (g);
544 if(interm) {
545 gchar *term_command = MIME_mk_terminal_line (command_fmt);
546 g_free (command_fmt);
547 command_fmt = term_command;
548 }
549 command_fmt = strip_path(command_fmt,en->path);
550 NOOP(stderr, "OPEN: adding %s --> %s (from %s)\n", type, command_fmt, g);
551 rfm_rational(RFM_MODULE_DIR,"mime",
552 (void *)(en->mimetype),
553 (void *)command_fmt, "mime_append");
554 // MIME_add would prepend, which is now deprecated:
555 // MIME_add (view_p->mouse_event.selected_p->en->mimetype, command_fmt);
556 g_free(command_fmt);
557 }
558 }
559 }
560 gchar *command;
561 if(strstr (g, "%s")) {
562 command = g_strdup_printf (g, (files)?files:"");
563 } else {
564 command = g_strdup_printf ("%s %s", g, (files)?files:"");
565 }
566 g_strstrip(command);
567 g_free(g);
568 NOOP (stderr,"OPEN: command = \"%s\"\n", command);
569 g_free (files);
570
571 if(widgets_p->diagnostics_window){
572 if (!rfm_threaded_get_visible(widgets_p->diagnostics_window)){
573 rfm_threaded_show_text(widgets_p);
574 }
575 } else {
576 rfm_threaded_show_text(widgets_p);
577 }
578
579 // do the call with argv so that command not saved in lpterm history
580 // (but this is broken when we have pipes or redirection)
581 gboolean shell_it = FALSE;
582 gchar *tokens="|><;&";
583 gchar *c=tokens;
584 for (c=tokens; *c; c++){
585 if (strchr(command, *c)){
586 shell_it=TRUE;
587 break;
588 }
589 }
590 NOOP(stderr, "command = %s (shell=%d)\n", command, shell_it);
591 if (shell_it){
592 RFM_THREAD_RUN (widgets_p, command, interm);
593 } else {
594 RFM_THREAD_RUN2ARGV (widgets_p, command, interm);
595 }
596
597 g_free (command);
598 // Cleanup
599 cleanup:;
600 GSList *list = selection_list;
601 for (; list && list->data; list = list->next){
602 record_entry_t *en = list->data;
603 rfm_destroy_entry(en);
604 }
605 if (selection_list) g_slist_free(selection_list);
606 TRACE("execute done...\n");
607 return retval;
608 }
609
610
611 static void
rodent_save_workdir_history(char * p)612 rodent_save_workdir_history (char *p) {
613 gchar *f = g_build_filename (WORKDIR_DBH_FILE, NULL);
614 COMBOBOX_save_to_history (f, p);
615 g_free (f);
616 }
617 // Determines the work directory of the command to be executed
618 // to do things like extract a tar file to a selected diretory
619 static gchar *
autofunction_workdir(widgets_t * widgets_p,const gchar * querypath)620 autofunction_workdir (widgets_t *widgets_p, const gchar * querypath) {
621 if (g_thread_self() == rfm_get_gtk_thread()){
622 g_error("autofunction_workdir() is a thread function\n");
623 }
624 view_t *view_p = widgets_p->view_p;
625 static gchar *last_dir = NULL;
626 gchar *g=NULL;
627
628 if (!view_p->en) return NULL;
629 if(querypath) {
630 gchar *f = g_build_filename (WORKDIR_DBH_FILE, NULL);
631 const gchar *folder;
632 if(view_p->en && view_p->en->path && IS_SDIR(view_p->en->type)) {
633 folder = view_p->en->path;
634 } else {
635 folder = g_get_home_dir ();
636 }
637 NOOP ("COMBO: last_dir is %s\n", last_dir);
638 //const gchar *default_dir=last_dir;
639 const gchar *default_dir=NULL;
640 if (!default_dir) default_dir=view_p->en->path;
641 if (!rfm_entry_available(widgets_p, view_p->en)) {
642 default_dir=g_get_home_dir();
643 }
644 g = get_response_history ( _(querypath),
645 _("Path"), _("Select directory"),
646 f, NULL,
647 default_dir,
648 NULL, NULL,
649 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
650 folder,
651 MATCH_FILE);
652 g_free (f);
653
654 if(!g) return NULL;
655
656 gboolean exists = g_file_test (g, G_FILE_TEST_EXISTS);
657 gboolean isdir = g_file_test (g, G_FILE_TEST_IS_DIR);
658
659
660 if(exists && !isdir) {
661 rfm_threaded_status (widgets_p, "xffm/stock_dialog-warning", g_strdup(strerror (ENOTDIR)));
662 g_free(g);
663 return NULL;
664 }
665 if(!exists) {
666 gchar *b = g_strdup_printf ("%s: %s\n%s...", g,
667 strerror (ENOENT),_("Create New Folder"));
668 if(!rfm_confirm (widgets_p, GTK_MESSAGE_QUESTION, b, _("Cancel"), NULL)) {
669 g_free(g);
670 g_free (b);
671 return NULL;
672 }
673 g_free (b);
674 if(g_mkdir_with_parents (g, 0750) < 0) {
675 rfm_threaded_show_text(widgets_p);
676 rfm_threaded_diagnostics (widgets_p, "xffm/stock_dialog-error", NULL);
677 rfm_threaded_status (widgets_p, "xffm_tag/stderr", g_strconcat(g, ": ", strerror (errno), "\n", NULL));
678 g_free(g);
679 return NULL;
680 }
681 }
682
683
684 g_free (last_dir);
685 last_dir = g_strdup (g);
686 NOOP ("COMBO: setting last_dir to %s\n", last_dir);
687 if(isdir)
688 rodent_save_workdir_history (widgets_p->workdir);
689 else {
690 rfm_threaded_show_text(widgets_p);
691 rfm_threaded_diagnostics (widgets_p, "xffm/stock_dialog-error", NULL);
692 rfm_threaded_status (widgets_p, "xffm_tag/stderr", g_strconcat(g, ": ", strerror (errno), "\n", NULL));
693 g_free(g);
694 return NULL;
695 }
696 return g;
697 }
698
699 g_free(g);
700 return NULL;
701 }
702
703 static int
select_all_view(view_t * view_p,gboolean invert)704 select_all_view (view_t * view_p, gboolean invert) {
705 rfm_global_t *rfm_global_p = rfm_global();
706 population_t **population_pp;
707 int items = 0;
708 if(!view_p || !view_p->en)
709 return items;
710 rfm_cursor_wait (rfm_global_p->window);
711 population_pp = view_p->population_pp;
712 for(; population_pp && *population_pp; population_pp++) {
713 if((*population_pp)->en == NULL)
714 continue;
715 if(IS_DUMMY_TYPE ((*population_pp)->en->type))
716 continue;
717 items++;
718 NOOP ("selected item %d", items);
719 //
720
721 if (invert) {
722 if ((*population_pp)->flags & POPULATION_SELECTED) {
723 //no gtk in this function:
724 rfm_unselect_pixbuf (view_p, *population_pp);
725 } else {
726 //no gtk in this function:
727 rfm_select_pixbuf (view_p, *population_pp);
728 }
729 rfm_expose_item (view_p, *population_pp);
730 } else {
731 if (!((*population_pp)->flags & POPULATION_SELECTED)){
732 //no gtk in this function:
733 rfm_select_pixbuf (view_p, *population_pp);
734 //all expose issues are invoked in main context:
735 rfm_expose_item (view_p, *population_pp);
736 }
737 }
738
739 }
740 rfm_threaded_cursor_reset (rfm_global_p->window);
741 return items;
742 }
743
744 enum {
745 END_MATCH,
746 START_MATCH,
747 TOMATO_IN_SANDWICH_MATCH,
748 BREAD_ON_SANDWICH_MATCH,
749 EXACT_MATCH
750 };
751
752 static gint
select_byfilter_view(widgets_t * widgets_p,const gchar * select_filter,gboolean select_it)753 select_byfilter_view (widgets_t *widgets_p, const gchar * select_filter, gboolean select_it) {
754 rfm_global_t *rfm_global_p = rfm_global();
755
756 view_t *view_p = widgets_p->view_p;
757 population_t **population_pp;
758 gint items = 0;
759 if(!view_p || !view_p->en) return items;
760 if(!select_filter || !strlen (select_filter)) return items;
761 if(strcmp (select_filter, "*") == 0) return select_all_view (view_p, FALSE);
762 rfm_threaded_cursor_wait (rfm_global_p->window);
763
764 gchar *filter = g_strdup (select_filter);
765 memset (filter, 0, strlen (select_filter));
766 int j = 0,
767 i = 0,
768 caso;
769 for(; i < strlen (select_filter); i++) {
770 if(select_filter[i] != '*')
771 filter[j++] = select_filter[i];
772 }
773
774 if(select_filter[0] == '*' && select_filter[strlen (select_filter) - 1] == '*') {
775 caso = TOMATO_IN_SANDWICH_MATCH;
776 } else if(select_filter[0] == '*') {
777 caso = END_MATCH;
778 } else if(select_filter[strlen (select_filter) - 1] == '*') {
779 caso = START_MATCH;
780 } else if(strchr (select_filter, (int)'*')) {
781 caso = BREAD_ON_SANDWICH_MATCH;
782 } else {
783 caso = EXACT_MATCH;
784 }
785
786 //rodent_unselect_all_pixbuf (view_p);
787 population_pp = view_p->population_pp;
788 for(; population_pp && *population_pp; population_pp++) {
789 gchar *f;
790 gboolean match = FALSE;
791 if((*population_pp)->en == NULL)
792 continue;
793 if((*population_pp)->en->path == NULL)
794 continue;
795 if(IS_DUMMY_TYPE ((*population_pp)->en->type))
796 continue;
797 f = g_path_get_basename ((*population_pp)->en->path);
798 gchar *p = strcasestr (f, filter);
799
800 if(p && caso == END_MATCH) {
801 gchar *pp;
802 do {
803 pp = p;
804 p = strcasestr (p + 1, filter);
805 }
806 while(p);
807 p = pp;
808 }
809
810 if(p) {
811 NOOP ("p=%s, filter=%s\n", p, filter);
812 switch (caso) {
813 case TOMATO_IN_SANDWICH_MATCH:
814 match = TRUE;
815 break;
816 case END_MATCH:
817 if(p[strlen (filter)] == 0)
818 match = TRUE;
819 break;
820 case START_MATCH:
821 if(p == f)
822 match = TRUE;
823 break;
824 case EXACT_MATCH:
825 if(strlen (p) == strlen (filter))
826 match = TRUE;
827 break;
828 case BREAD_ON_SANDWICH_MATCH:
829 //not implemented. Need to do 2 matches.
830 //break;
831 default: //START_END_MATCH
832 match = TRUE;
833 break;
834
835 }
836 }
837 if(match) {
838 items++;
839 if (select_it) rfm_select_pixbuf (view_p, *population_pp);
840 else rfm_unselect_pixbuf (view_p, *population_pp);
841 rfm_expose_item (view_p, *population_pp);
842 }
843 g_free (f);
844 }
845 rfm_threaded_cursor_reset (rfm_global_p->window);
846 gchar *plural_text=g_strdup_printf (ngettext ("%'u item", "%'u items",
847 items),items);
848 gchar *g = g_strdup_printf ("%s: %s", _("Selection"), plural_text);
849 g_free(plural_text);
850
851 rfm_threaded_status (&(view_p->widgets), "xffm/stock_dialog-info", g );
852 g_free (filter);
853
854 return items;
855 }
856
857 static void
unselect_all(widgets_t * widgets_p)858 unselect_all (widgets_t *widgets_p) {
859 view_t *view_p = widgets_p->view_p;
860 rodent_unselect_all_pixbuf (view_p);
861 }
862
863
864 static void
private_mount(widgets_t * widgets_p,gint mounted)865 private_mount (widgets_t *widgets_p, gint mounted) {
866 rfm_global_t *rfm_global_p = rfm_global();
867 view_t *view_p = widgets_p->view_p;
868 record_entry_t *en = view_p->selection_list->data;
869 NOOP ("MOUNT: private_mount %d (0x%x)\n", mounted, GPOINTER_TO_INT(view_p));
870 if(!en || !en->path) {
871 DBG ("no entry to mount\n");
872 return;
873 }
874 if(mounted){
875 SET_MOUNTED_TYPE (en->type);
876 } else{
877 UNSET_MOUNTED_TYPE (en->type);
878 }
879 rfm_threaded_show_text(widgets_p);
880 gchar *text;
881 const gchar *icon;
882 if (mounted){
883 icon = "xffm/emblem_redball/compositeC/stock_go-up";
884 text = g_strdup_printf(_("Unmounting %s"), en->path);
885 } else {
886 icon = "xffm/emblem_greenball/compositeC/stock_go-up";
887 text = g_strdup_printf(_("Mounting %s"), en->path);
888 }
889 rfm_threaded_diagnostics(widgets_p, icon, g_strconcat(text, "\n", NULL));
890 FSTAB_fstab_mount (widgets_p, en);
891 g_free(text);
892
893
894 unselect_all(widgets_p);
895 rfm_threaded_cursor_reset (rfm_global_p->window);
896
897 NOOP ("MOUNT: private_mount done\n");
898 return;
899 }
900
901
902 static gint
gui_pasteboard_list(GList ** list_p)903 gui_pasteboard_list (GList ** list_p) {
904
905 // client side pasteboard, via MIT-shm
906 gchar *b=rfm_get_paste_buffer();
907 if((!b) || (!strlen (b))) {
908 no_pasteboard:
909 g_free(b);
910 return 0;
911 }
912 gboolean cut;
913 gchar *word;
914 if((word = strtok (b, ":")) == NULL)
915 goto no_pasteboard;
916 if(!strstr (word, "#xfvalid_buffer"))
917 goto no_pasteboard;
918 if((word = strtok (NULL, ":")) == NULL)
919 goto no_pasteboard;
920 if(strstr (word, "cut"))
921 cut = TRUE;
922 else
923 cut = FALSE;
924 if((word = strtok (NULL, ":")) == NULL)
925 goto no_pasteboard;
926 //src_host = g_strdup(word);
927
928 word = word + strlen (word) + 1;
929 if(word[0] == '\n') {
930 word++;
931 if(word[0] == 0)
932 goto no_pasteboard;
933 } else {
934 if((word = strtok (NULL, "\n")) == NULL)
935 goto no_pasteboard;
936 word = word + strlen (word) + 1;
937 }
938
939 /* create list to send to CreateTmpList */
940 gint retval = rfm_uri_parse_list (word, list_p);
941
942 g_free (b);
943 if (retval) {
944 if(cut) retval=1;
945 else retval= 2;
946 }
947 return retval;
948 }
949
950 static gint
gui_pasteboard_transfer(widgets_t * widgets_p,record_entry_t * t_en,GList * list,gboolean cut,gboolean symlink)951 gui_pasteboard_transfer (widgets_t * widgets_p,
952 record_entry_t * t_en,
953 GList * list,
954 gboolean cut,
955 gboolean symlink) {
956 if (!list){
957 g_warning("gui_pasteboard_transfer() list is null\n");
958 return 0;
959 }
960 gchar *url = (gchar *) list->data;
961 if(!url){
962 DBG("gui_pasteboard_transfer: !url\n");
963 return 0;
964 }
965
966 if(t_en->module) {
967 NOOP ("PASTE: en->module=%s\n", t_en->module);
968 if(rfm_natural (PLUGIN_DIR, t_en->module, t_en, "valid_drop_site")) {
969 NOOP ("module: valid_drop_site for %s\n", t_en->module);
970 rfm_natural (PLUGIN_DIR, t_en->module, t_en, "set_drop_entry");
971 if(rfm_rational (PLUGIN_DIR, t_en->module, list, widgets_p, "process_drop")) {
972 NOOP ("module: process_drop ok\n");
973 /*result=TRUE; */
974 }
975 rfm_void (PLUGIN_DIR, t_en->module, "clear_drop_entry");
976 return 1;
977 }
978 }
979 NOOP ("PASTE: must be local then\n");
980 int mode;
981 if(cut) {
982 mode = TR_MOVE;
983 } else {
984 mode = TR_COPY;
985 }
986 if(symlink) {
987 mode = TR_LINK;
988 }
989
990 // Only the uploading notice works here...
991 gchar *text=NULL;
992 const gchar *icon=NULL;
993 //gint type=0;
994 gboolean local_target = TRUE;
995 //gboolean local_source = TRUE;
996 //if (!IS_LOCAL_TYPE(type))local_source = FALSE;
997 if (!IS_LOCAL_TYPE(t_en->type))local_target = FALSE;
998 if (!local_target){
999 switch (mode){
1000 case TR_COPY:
1001 case TR_MOVE:
1002 case TR_COPY_REMOTE:
1003 case TR_MOVE_REMOTE:
1004 icon = "xffm/emblem_network/compositeSE/stock_go-forward";
1005 text = g_strdup_printf(_("Uploading file %s"), "...");
1006 break;
1007 default:
1008 break;
1009 }
1010 } else {
1011 // Local target. Test first item of list for remote host.
1012 const gchar *path = list->data;
1013 record_entry_t *en = rfm_stat_entry(path, 0);
1014 if (!IS_LOCAL_TYPE(en->type)) {
1015 icon = "xffm/emblem_network/compositeSE/stock_go-back";
1016 text = g_strdup_printf(_("Downloading file %s..."), "");
1017 }
1018 rfm_destroy_entry(en);
1019 }
1020
1021
1022
1023 if (text) {
1024 rfm_threaded_diagnostics(widgets_p, "xffm/emblem_network/compositeSE/stock_go-forward", NULL);
1025 rfm_threaded_diagnostics(widgets_p, icon, NULL);
1026 rfm_threaded_diagnostics(widgets_p, "xffm_tag/red", g_strconcat(text, "\n", NULL));
1027 g_free(text);
1028 }
1029 // Here we are already in a threaded environment, so plain cp
1030 // would create an unnecessary extra thread.
1031 // cp (mode, list, t_en->path);
1032 plain_cp(widgets_p, mode, list, t_en->path, FALSE);
1033
1034 return 1;
1035 }
1036
1037
1038 static void
private_paste(widgets_t * widgets_p,view_t * view_p,gboolean symlink)1039 private_paste (widgets_t * widgets_p, view_t * view_p, gboolean symlink) {
1040 gboolean cut;
1041 GList *list = NULL;
1042 record_entry_t *t_en = NULL;
1043 int i;
1044
1045
1046
1047 if((t_en = view_p->en) == NULL){
1048 DBG("(t_en = view_p->en) == NULL\n");
1049 return;
1050 }
1051
1052
1053 if((i = gui_pasteboard_list (&list)) == 0){
1054 DBG("(i = gui_pasteboard_list (&list)) == 0\n");
1055 return;
1056 }
1057 if(i == 1)
1058 cut = TRUE;
1059 else
1060 cut = FALSE;
1061 i = gui_pasteboard_transfer (widgets_p, t_en, list, cut, symlink);
1062
1063 list = rfm_uri_free_list (list);
1064
1065 if(i) {
1066 if(cut){
1067 rfm_clear_paste_buffer();
1068 }
1069 }
1070 return;
1071 }
1072
1073 static void
gui_pasteboard_copy_cut(widgets_t * widgets_p,gboolean cut,GSList ** paste_list)1074 gui_pasteboard_copy_cut (widgets_t * widgets_p, gboolean cut, GSList ** paste_list) {
1075 gint len;
1076 gchar *buffer;
1077 //gchar *files;
1078 view_t *view_p = widgets_p->view_p;
1079 // clear any previous icon emblems
1080 rodent_clear_cut_icons (view_p);
1081
1082 if(*paste_list == NULL){
1083 DBG("*paste_list == NULL\n");
1084 return;
1085 }
1086
1087 if(cut)
1088 rfm_threaded_status (widgets_p, "xffm/stock_dialog-info", g_strdup(_("Cut")));
1089 else
1090 rfm_threaded_status (widgets_p, "xffm/stock_dialog-info", g_strdup(_("Copy")));
1091
1092 rfm_clear_paste_buffer();
1093
1094 len = 1 + strlen ("#xfvalid_buffer:copy:%%:\n");
1095 len += strlen (g_get_host_name ());
1096 GSList *tmp = *paste_list;
1097 for(; tmp; tmp = tmp->next) {
1098 gint addlen;
1099 record_entry_t *en = (record_entry_t *) tmp->data;
1100 addlen = 0;
1101 len += (1 + strlen (en->path) + addlen);
1102 }
1103 buffer = (gchar *)malloc (len * sizeof (char) + 1);
1104 if(!buffer) {
1105 DBG ("rfm: unable to allocate paste buffer\n");
1106 return;
1107 }
1108 sprintf (buffer, "#xfvalid_buffer:%s:%s:\n", (cut) ? "cut" : "copy", g_get_host_name ());
1109 //files = buffer + strlen (buffer);
1110
1111 for(tmp = *paste_list; tmp; tmp = tmp->next) {
1112 record_entry_t *en = (record_entry_t *) tmp->data;
1113 {
1114 strcat (buffer, en->path);
1115 strcat (buffer, "\n");
1116 }
1117 }
1118 NOOP("dbg:len=%d,strlen=%d,data=%s\n",len,strlen(buffer),buffer);
1119 rfm_store_paste_buffer(buffer, len);
1120 g_free (buffer);
1121 buffer = NULL;
1122
1123 if(cut)
1124 rfm_threaded_status (widgets_p, "xffm/stock_dialog-info", g_strconcat(_("Cut"), NULL));
1125 else
1126 rfm_threaded_status (widgets_p, "xffm/stock_dialog-info", g_strconcat(_("Copy"), NULL));
1127 //view_p->flags.pasteboard_serial++;
1128 NOOP ("PASTE: view_p->flags.pasteboard_serial=%d\n", view_p->flags.pasteboard_serial);
1129 gchar *value = g_strdup_printf ("%d", view_p->flags.pasteboard_serial + 1);
1130 if (rfm_rational (RFM_MODULE_DIR, "settings", (void *)"RFM_PASTEBOARD_SERIAL", (void *)value, "mcs_set_var") == NULL){
1131 rfm_setenv ("RFM_PASTEBOARD_SERIAL", value, TRUE);
1132 NOOP("cannot set RFM_PASTEBOARD_SERIAL");
1133 }
1134 g_free (value);
1135 rodent_update_cut_icons(view_p);
1136 TRACE("copy-cut calling rodent_expose_all()\n");
1137 //rodent_expose_all (view_p);
1138 rodent_redraw_items (view_p);
1139 }
1140
1141 static void
copy_cut_callback(widgets_t * widgets_p,gboolean cut)1142 copy_cut_callback (widgets_t *widgets_p, gboolean cut) {
1143
1144 view_t *view_p = widgets_p->view_p;
1145 if (!rfm_entry_available(widgets_p, view_p->en)) return;
1146 if(!view_p->selection_list) return;
1147
1148 gui_pasteboard_copy_cut (widgets_p, cut, &(view_p->selection_list));
1149 // unselect stuff if it is cut or copied.
1150 GSList *tmp=view_p->selection_list;
1151 for (;tmp && tmp->data; tmp=tmp->next){
1152 record_entry_t *en=tmp->data;
1153 rfm_destroy_entry(en);
1154 }
1155 g_slist_free (view_p->selection_list);
1156 view_p->selection_list = NULL;
1157
1158 // Mark all population items as unselected.
1159 if(rfm_population_read_lock (view_p, "copy_cut_callback")) {
1160 population_t **pp;
1161 for(pp = view_p->population_pp; pp && *pp; pp++) {
1162 population_t *population_p = *pp;
1163 population_p->flags &= (POPULATION_SELECTED ^ 0xffffffff);
1164 }
1165 rfm_population_read_unlock (view_p, "copy_cut_callback");
1166 }
1167
1168 }
1169 static void
paste_callback(widgets_t * widgets_p,gboolean symlink)1170 paste_callback (widgets_t *widgets_p, gboolean symlink) {
1171 view_t *view_p = widgets_p->view_p;
1172 if(!view_p->en)
1173 return;
1174 if (!rfm_entry_available(widgets_p, view_p->en)) return;
1175 //rfm_details->pastepath = view_p->en->path;
1176 private_paste (widgets_p, view_p, symlink);
1177 }
1178
1179
1180 ///////////////////////////////////////////////////////////////////////////
1181 ///******************************************************************///
1182 //////////////////////////////////////////////////////////////////////////
1183
1184 static void
glob_x(widgets_t * widgets_p)1185 glob_x (widgets_t *widgets_p){
1186 NOOP( "glob_x...\n");
1187 gchar *fgr = g_find_program_in_path("rodent-fgr");
1188 if (!fgr) {
1189 DBG("fgr not found.\n");
1190 return;
1191 }
1192
1193 view_t *view_p = widgets_p->view_p;
1194 gchar *path = NULL;
1195
1196 // on keybind call, mouse_event is ignored, selection_p is
1197 // set to NULL in keybind.
1198 if(view_p->mouse_event.selected_p && view_p->mouse_event.selected_p->en
1199 && IS_SDIR(view_p->mouse_event.selected_p->en->type)
1200 && g_slist_length (view_p->selection_list) == 1) {
1201 path = g_strdup(view_p->mouse_event.selected_p->en->path);
1202 } else if(view_p->en) {
1203 path = g_strdup(view_p->en->path);
1204 }
1205 gchar *argv[]={fgr, path, NULL};
1206 rfm_threaded_show_text(widgets_p);
1207 rfm_thread_run_argv(widgets_p, argv, FALSE);
1208 g_free(fgr);
1209 g_free(path);
1210 }
1211
1212 static void
help(widgets_t * widgets_p)1213 help (widgets_t *widgets_p){
1214 //view_t *view_p = widgets_p->view_p;
1215 // XXX: should define PDF_DIR and use ./configure --pdfdir=xxx
1216 gchar *help_file=g_strdup_printf("%s/doc/rfm/RTFM.pdf",
1217 PACKAGE_DATA_DIR);
1218 // This is a local and absolute path.
1219 if (!g_file_test(help_file, G_FILE_TEST_EXISTS)){
1220 DBG("%s: %s\n", help_file, strerror(ENOENT));
1221 } else {
1222 record_entry_t *en=rfm_stat_entry(help_file, 0);
1223 en->mimetype=MIME_type(en->path, NULL);
1224 open_with (widgets_p, en);
1225 rfm_destroy_entry(en);
1226 }
1227 g_free(help_file);
1228 }
1229 static void
remove_x(widgets_t * widgets_p)1230 remove_x (widgets_t *widgets_p){
1231 view_t *view_p = widgets_p->view_p;
1232 if (view_p && g_slist_length(view_p->selection_list) >= 1){
1233 GSList *list = NULL;
1234 GSList *tmp=view_p->selection_list;
1235 for (;tmp && tmp->data; tmp=tmp->next) {
1236 record_entry_t *en=tmp->data;
1237 list = g_slist_prepend(list, g_strdup (en->path));
1238 list = g_slist_reverse(list);
1239 }
1240 rm(widgets_p, list);
1241 // unselect all items now so they won't remain in selection
1242 // list when the thread is done.
1243 TRACE("** rm call has returned\n");
1244 rodent_unselect_all_pixbuf (view_p);
1245 }
1246 }
1247
1248 static void
refresh(widgets_t * widgets_p)1249 refresh (widgets_t *widgets_p){
1250 NOOP(stderr, "refresh...\n");
1251 view_t *view_p = widgets_p->view_p;
1252 if(view_p->en){
1253 if (view_p->en->path) {
1254 gchar *path = g_strdup( view_p->en->path);
1255 rfm_cleanup_thumbnails(path);
1256 }
1257 if (view_p->en->module &&
1258 rfm_natural(PLUGIN_DIR, view_p->en->module, view_p, "reload")) {
1259 return;
1260 }
1261 }
1262 record_entry_t *en = rfm_copy_entry (view_p->en);
1263 if (!rodent_refresh (widgets_p, en)){ rfm_destroy_entry(en); }
1264 }
1265
1266 static void
host(widgets_t * widgets_p)1267 host (widgets_t *widgets_p) {
1268 view_t *view_p = widgets_p->view_p;
1269 if(view_p->child_constructor) {
1270 (*view_p->child_constructor) (widgets_p, NULL);
1271 } else {
1272 rodent_push_view_go_history ();
1273 if (!rodent_refresh (widgets_p, NULL)){
1274 g_warning("!rodent_refresh (widgets_p, NULL)\n");
1275 }
1276 }
1277 }
1278
1279 static void
goup(widgets_t * widgets_p)1280 goup (widgets_t *widgets_p) {
1281 view_t *view_p = widgets_p->view_p;
1282 record_entry_t *en = NULL;
1283 if (view_p->population_pp && view_p->population_pp[0]){
1284 if (view_p->population_pp[0]->en &&
1285 view_p->population_pp[0]->en->module) {
1286 en =rfm_copy_entry(view_p->population_pp[0]->en);
1287 } else if (view_p->population_pp[0]->en) {
1288 gchar *path=g_strdup(view_p->population_pp[0]->en->path);
1289 if (g_path_is_absolute(path)){
1290 while (!rfm_g_file_test_with_wait(path, G_FILE_TEST_IS_DIR)){
1291 gchar *d = g_path_get_dirname(path);
1292 g_free(path);
1293 path = d;
1294 }
1295 } else {
1296 g_error("goup_activate(): this should not happen\n");
1297 }
1298 en =rfm_stat_entry(path, 0);
1299 g_free(path);
1300 }
1301 }
1302 if (!en) {
1303 host (widgets_p);
1304 return;
1305 }
1306 if (IS_SDIR(en->type)){
1307 rodent_push_view_go_history ();
1308 }
1309 if(view_p->child_constructor) {
1310 if (en->module) {
1311 gchar *m=g_strdup_printf("rodent-plug %s", en->module);
1312 (*view_p->child_constructor) (widgets_p, (char *)m);
1313 g_free(m);
1314 } else {
1315 (*view_p->child_constructor) (widgets_p, en->path);
1316 }
1317 rfm_destroy_entry(en);
1318 } else {
1319 if (IS_SDIR(en->type)){
1320 rodent_push_view_go_history ();
1321 }
1322 if (!rodent_refresh (widgets_p, en)){
1323 rfm_destroy_entry(en);
1324 }
1325 }
1326 }
1327
1328
1329 static void
forward(widgets_t * widgets_p)1330 forward (widgets_t *widgets_p){
1331 view_t *view_p = widgets_p->view_p;
1332 if (!view_p->f_list) {
1333 rfm_threaded_show_text(widgets_p);
1334 rfm_threaded_diagnostics(widgets_p, "xffm/stock_dialog-info", NULL);
1335 rfm_threaded_diagnostics(widgets_p, "xffm_tag/blue",
1336 g_strconcat(_("Empty history"), "\n", NULL));
1337 jump_to(widgets_p);
1338 return;
1339 }
1340 record_entry_t *en = view_p->f_list->data;
1341 view_p->f_list = g_slist_remove(view_p->f_list, en);
1342 // if we reach the end, push history (hack)
1343 rodent_push_view_go_history();
1344 if(en) view_p->module = en->module;
1345 else view_p->module = NULL;
1346 TRACE( "forward() calling rodent_full_reload_view\n");
1347 rodent_full_reload_view ((gpointer) view_p, en);
1348 }
1349
1350 static void
back(widgets_t * widgets_p)1351 back (widgets_t *widgets_p){
1352 view_t *view_p = widgets_p->view_p;
1353 GList *last = g_list_last (view_p->go_list);
1354 if(!last) {
1355 // This will only occur on keybinding callback.
1356 rfm_threaded_show_text(widgets_p);
1357 rfm_threaded_diagnostics(widgets_p, "xffm/stock_dialog-info", NULL);
1358 rfm_threaded_diagnostics(widgets_p, "xffm_tag/blue",
1359 g_strconcat(_("Initial Point"),
1360 ": ", (view_p->en)?view_p->en->path:_("Plugins"), "\n", NULL));
1361 return;
1362 }
1363 record_entry_t *en = last->data;
1364 // Failure warning instead of going to previous back.
1365 if (!rfm_entry_available(widgets_p, en)) {
1366 pop_view_go_history (view_p);
1367 return;
1368 }
1369 view_p->f_list = g_slist_prepend(view_p->f_list, rfm_copy_entry(view_p->en));
1370 if(en) view_p->module = en->module;
1371 else view_p->module = NULL;
1372 pop_view_go_history (view_p);
1373 TRACE( "back() calling rodent_full_reload_view\n");
1374 rodent_full_reload_view ((gpointer) view_p, en);
1375 }
1376
1377 static void
home(widgets_t * widgets_p)1378 home (widgets_t *widgets_p){
1379 view_t *view_p = widgets_p->view_p;
1380 if (!rfm_g_file_test_with_wait (g_get_home_dir(), G_FILE_TEST_IS_DIR)){
1381 time_out_message(widgets_p, g_get_home_dir());
1382 return;
1383 }
1384 if(view_p->child_constructor) {
1385 (*view_p->child_constructor) (widgets_p, (char *)g_get_home_dir ());
1386 } else {
1387 rodent_push_view_go_history ();
1388 record_entry_t *en = rfm_stat_entry ((gchar *) g_get_home_dir (), 0);
1389 if (!rodent_refresh (widgets_p, en)){ rfm_destroy_entry(en); }
1390 }
1391 }
1392
1393 static void
jump_to(widgets_t * widgets_p)1394 jump_to (widgets_t *widgets_p){
1395 view_t *view_p = widgets_p->view_p;
1396 gchar *g = get_jumpto_dir(widgets_p);
1397 if (!g) return;
1398 if(view_p->child_constructor) {
1399 (*view_p->child_constructor) (widgets_p, g);
1400 } else {
1401 rodent_push_view_go_history ();
1402 rfm_save_to_go_history (g);
1403 record_entry_t *en = rfm_stat_entry (g, 0);
1404 if (!rodent_refresh (widgets_p, en)){ rfm_destroy_entry(en); }
1405 }
1406 g_free (g);
1407 }
1408
1409 static void
plugin_goto(widgets_t * widgets_p,gpointer data)1410 plugin_goto (widgets_t *widgets_p, gpointer data) {
1411 view_t *view_p = widgets_p->view_p;
1412 GtkWidget *menu_item = data;
1413 const gchar *module_name = g_object_get_data(G_OBJECT(menu_item), "module_name");
1414 if(module_name) {
1415 if (view_p->child_constructor) {
1416 gchar *m = g_strconcat("rodent-plug"," ", module_name, NULL);
1417 (*view_p->child_constructor) (widgets_p, (char *)m);
1418 g_free(m);
1419 } else {
1420 rodent_push_view_go_history ();
1421 record_entry_t *new_en = rfm_mk_entry (0);
1422 SET_ROOT_TYPE (new_en->type);
1423 new_en->module = module_name;
1424 new_en->path = rfm_void (PLUGIN_DIR, module_name, "module_label");
1425 if (!rodent_refresh (widgets_p, new_en)){ rfm_destroy_entry(new_en); }
1426 }
1427 } else {
1428 DBG ("cannot get module_name from module-goto menu\n");
1429 }
1430 return;
1431 }
1432
1433 // This function uses menuitem and does not accept keybinding...
1434 static void
level_goto(widgets_t * widgets_p,gpointer data)1435 level_goto (widgets_t *widgets_p, gpointer data) {
1436 view_t *view_p = widgets_p->view_p;
1437 GtkWidget *menu_item = data;
1438 const gchar *path = g_object_get_data(G_OBJECT(menu_item), "path");
1439 NOOP("path is %s\n", path);
1440 if(path) {
1441 if(view_p->child_constructor) {
1442 (*view_p->child_constructor) (widgets_p, (char *)path);
1443 } else {
1444 rodent_push_view_go_history ();
1445 record_entry_t *new_en;
1446 if (rfm_g_file_test_with_wait(path, G_FILE_TEST_EXISTS)){
1447 new_en = rfm_stat_entry (path, 0);
1448 } else {
1449 rfm_confirm (widgets_p, GTK_MESSAGE_ERROR, strerror (EEXIST), NULL, NULL);
1450 return;
1451 }
1452 if (new_en && !new_en->module) {
1453 rfm_save_to_go_history ((gchar *) path);
1454 }
1455 if (!rodent_refresh (widgets_p, new_en)){
1456 rfm_destroy_entry(new_en);
1457 }
1458
1459 }
1460 } else {
1461 DBG ("cannot get path from level-goto menu\n");
1462 }
1463 return;
1464 }
1465
1466
1467 static void
ascending_descending(widgets_t * widgets_p,enum menu_enum_t menu_enum)1468 ascending_descending (widgets_t *widgets_p, enum menu_enum_t menu_enum){
1469 view_t *view_p = widgets_p->view_p;
1470
1471 if (view_p->flags.preferences & SORT_ASCENDING) {
1472 view_p->flags.preferences &= (SORT_ASCENDING ^ 0xffffffff);
1473 } else {
1474 view_p->flags.preferences |= SORT_ASCENDING;
1475 }
1476 #if 0
1477 if (menu_enum == ASCENDING_ACTIVATE) {
1478 if (view_p->flags.preferences & SORT_ASCENDING) return;
1479 view_p->flags.preferences |= SORT_ASCENDING;
1480 } else {
1481 if ((view_p->flags.preferences & SORT_ASCENDING) == 0) return;
1482 view_p->flags.preferences &= (SORT_ASCENDING ^ 0xffffffff);
1483 }
1484 #endif
1485 rfm_save_view_preferences (view_p, view_p->en);
1486 record_entry_t *en = rfm_copy_entry (view_p->en);
1487 if (!rodent_refresh (widgets_p, en)){ rfm_destroy_entry(en); }
1488 }
1489
1490 static void
about(widgets_t * widgets_p)1491 about(widgets_t *widgets_p){
1492 gchar *argv[3];
1493 argv[0] = "rodent";
1494 argv[1] = "--version";
1495 argv[2] = NULL;
1496
1497
1498 rfm_threaded_show_text (widgets_p);
1499 rfm_thread_run_argv (widgets_p, argv, FALSE);
1500 // pipe output of current app...
1501 gchar *app = g_strdup("rodent-app");
1502 rfm_global_t *rfm_global_p = rfm_global();
1503 if (rfm_global_p){
1504 gchar *c = g_strdup_printf("%s --version", rfm_global_p->argv[0]);
1505 FILE *p = popen(c, "r");
1506 gchar buffer[256];
1507 memset(buffer, 0, 256);
1508 if (p && fgets(buffer, 255, p)){
1509 g_free(app);
1510 if (strchr(buffer,'\n')) *strchr(buffer,'\n') = 0;
1511 app = g_strdup(buffer);
1512 }
1513 if (p) pclose(p);
1514 }
1515
1516 void *arg[]={widgets_p, app};
1517 rfm_context_function(about_dialog_f, arg);
1518 g_free(app);
1519 }
1520
1521 static void
newdir(widgets_t * widgets_p)1522 newdir (widgets_t *widgets_p) {
1523 view_t *view_p = widgets_p->view_p;
1524 record_entry_t *en = view_p->en;
1525 gchar *label = g_strdup_printf ("%s/", en->path);
1526 gchar *q = rfm_utf_string (rfm_chop_excess (label));
1527 gchar *g = get_response (_("Create New Folder"), q,
1528 _("Name"));
1529 g_free (label);
1530 g_free (q);
1531
1532 if(g && strlen (g)) {
1533 gchar *p = g_build_filename (en->path, g, NULL);
1534 //
1535 if(!rfm_locate_path(view_p, p))
1536 {
1537 gchar *argv[4];
1538 int j=0;
1539 argv[j++]="mkdir";
1540 argv[j++]=p;
1541 argv[j++]=NULL;
1542
1543 if (en->st->st_mode == 0) {
1544 DBG("This should not happen: en->st->st_mode == 0\n");
1545 g_free(g);
1546 return;
1547 }
1548
1549 if (rfm_write_ok_path(en->path)){
1550 rfm_thread_run_argv (widgets_p, argv, FALSE);
1551 } else {
1552 gchar *base=g_path_get_basename(p);
1553 gchar *operation=g_strconcat("mkdir ", base, NULL);
1554 g_free(base);
1555 if (confirm_sudo(widgets_p, en->path,
1556 _("write failed"), operation)){
1557 RFM_TRY_SUDO (widgets_p, argv, FALSE);
1558 rfm_threaded_show_text(widgets_p);
1559 rfm_threaded_diagnostics(widgets_p, "xffm/stock_properties",NULL);
1560 rfm_threaded_diagnostics(widgets_p, "xffm_tag/green",
1561 g_strconcat(_("Don't forget"), " ", NULL));
1562 rfm_threaded_diagnostics(widgets_p, "xffm_tag/magenta",
1563 g_strconcat("chown pid:gid", " ", p, "\n", NULL));
1564 }
1565 g_free(operation);
1566 }
1567 }
1568 else {
1569 rfm_confirm (widgets_p, GTK_MESSAGE_ERROR, strerror (EEXIST), NULL, NULL);
1570 }
1571 g_free(p);
1572 }
1573 g_free(g);
1574 }
1575
1576 static void
newfile(widgets_t * widgets_p)1577 newfile (widgets_t *widgets_p) {
1578 view_t *view_p = widgets_p->view_p;
1579 record_entry_t *en = view_p->en;
1580 gchar *label = g_strdup_printf ("%s/", en->path);
1581 gchar *q = rfm_utf_string (rfm_chop_excess (label));
1582 gchar *g = get_response ( _("New file"), q, _("Name"));
1583 g_free (q);
1584 g_free (label);
1585 if(g && strlen (g)) {
1586 gchar *p = g_build_filename (en->path, g, NULL);
1587 if(!rfm_locate_path(view_p, p)) {
1588 gchar *argv[3];
1589 int j=0;
1590 argv[j++]="touch";
1591 argv[j++]=p;
1592 argv[j++]=NULL;
1593
1594
1595 if (rfm_write_ok_path(en->path)){
1596 rfm_thread_run_argv (widgets_p, argv, FALSE);
1597 } else {
1598 gchar *base=g_path_get_basename(p);
1599 gchar *operation=g_strconcat("touch ", base, NULL);
1600 g_free(base);
1601 if (confirm_sudo(widgets_p, en->path,
1602 _("write failed"), operation)){
1603 RFM_TRY_SUDO (widgets_p, argv, FALSE);
1604 rfm_threaded_show_text(widgets_p);
1605 rfm_threaded_diagnostics(widgets_p, "xffm/stock_properties",NULL);
1606 rfm_threaded_diagnostics(widgets_p, "xffm_tag/green",
1607 g_strconcat(_("Don't forget"), " ", NULL));
1608 rfm_threaded_diagnostics(widgets_p, "xffm_tag/magenta",
1609 g_strconcat("chown pid:gid", " ", p, "\n", NULL));
1610 }
1611 g_free(operation);
1612 }
1613 } else {
1614 rfm_confirm (widgets_p, GTK_MESSAGE_ERROR, strerror (EEXIST), NULL, NULL);
1615 }
1616 g_free (p);
1617 }
1618 g_free(g);
1619 }
1620
1621 static void
run(widgets_t * widgets_p)1622 run(widgets_t *widgets_p){
1623 gboolean visible=rfm_threaded_diagnostics_is_visible(widgets_p);
1624 if (!visible) rfm_threaded_show_text(widgets_p);
1625 if (!execute (widgets_p, NULL)){
1626 if (!visible && widgets_p->diagnostics_window==NULL){
1627 rfm_threaded_hide_text(widgets_p);
1628 }
1629 }
1630 }
1631
1632 static void
bcrypt(widgets_t * widgets_p)1633 bcrypt(widgets_t *widgets_p){
1634 // this will be an internal function call, rodent-bcrypt
1635 view_t *view_p = widgets_p->view_p;
1636 GSList *list=NULL;
1637 GSList *s_list = view_p->selection_list;
1638 if (g_slist_length(s_list) > MAX_COMMAND_ARGS - 5){
1639 DBG("Argument list too long (%d > %d)\n",
1640 g_slist_length(s_list), MAX_COMMAND_ARGS - 5);
1641 return;
1642 }
1643 for (; s_list && s_list->data; s_list = s_list->next){
1644 record_entry_t *en = s_list->data;
1645 if (en && g_path_is_absolute(en->path))
1646 list = g_slist_append(list, g_strdup(en->path));
1647 }
1648 if (!rfm_natural(RFM_MODULE_DIR, "bcrypt", list, "bcrypt_dialog")){
1649 DBG("cannot load bcrypt plugin\n");
1650 }
1651 for (s_list = list; s_list && s_list->data; s_list = s_list->next){
1652 g_free(s_list->data);
1653 }
1654 g_slist_free(list);
1655 }
1656
1657 static void
open_x(widgets_t * widgets_p)1658 open_x(widgets_t *widgets_p){
1659 view_t *view_p = widgets_p->view_p;
1660 GSList *list=NULL;
1661 GSList *s_list = view_p->selection_list;
1662 for (; s_list && s_list->data; s_list = s_list->next){
1663 record_entry_t *in_en = s_list->data;
1664 record_entry_t *out_en = rfm_copy_entry(in_en);
1665 list = g_slist_append(list, out_en);
1666 }
1667 execute(widgets_p, list);
1668 }
1669
1670 static void
new_window(widgets_t * widgets_p)1671 new_window(widgets_t *widgets_p){
1672 view_t *view_p = widgets_p->view_p;
1673 gchar *new_path=NULL;
1674 if (view_p->module) {
1675 new_path=g_strconcat("rodent-plug", " ", view_p->module, NULL);
1676 } else if (view_p->en) {
1677 if (!rfm_g_file_test_with_wait(view_p->en->path, G_FILE_TEST_IS_DIR)){
1678 time_out_message(widgets_p, view_p->en->path);
1679 return;
1680 }
1681 new_path=g_strdup(view_p->en->path);
1682 }
1683 rodent_new_gridview(widgets_p, new_path);
1684 g_free(new_path);
1685 }
1686 static void
open_in_terminal(widgets_t * widgets_p)1687 open_in_terminal(widgets_t *widgets_p){
1688 view_t *view_p = widgets_p->view_p;
1689 gchar *shell = rfm_xterm_shell();
1690 if (!shell) return;
1691 if(!view_p->en
1692 || !view_p->en->path
1693 || !g_path_is_absolute(view_p->en->path)){
1694 g_free (widgets_p->workdir);
1695 widgets_p->workdir = g_strdup (g_get_home_dir ());
1696 } else {
1697 g_free (widgets_p->workdir);
1698 widgets_p->workdir = g_strdup (view_p->en->path);
1699 }
1700
1701 gchar *argv[] = { shell, NULL };
1702 // use argv version so that it won't go into history file...
1703 rfm_thread_run_argv (widgets_p, argv, TRUE);
1704 g_free(shell);
1705 }
1706 static void
differences(widgets_t * widgets_p)1707 differences(widgets_t *widgets_p){
1708 view_t *view_p = widgets_p->view_p;
1709 gchar *file1 = NULL;
1710 gchar *file2 = NULL;
1711 if(view_p->selection_list) {
1712 file1 = ((record_entry_t *) (view_p->selection_list->data))->path;
1713 if(g_slist_length (view_p->selection_list) > 1){
1714 file2 = ((record_entry_t *) (view_p->selection_list->next->data))->path;
1715 }
1716 }
1717 if (file1 && !rfm_g_file_test_with_wait(file1, G_FILE_TEST_EXISTS)) {
1718 time_out_message(widgets_p, file1);
1719 return;
1720 }
1721 if (file2 && !rfm_g_file_test_with_wait(file2, G_FILE_TEST_EXISTS)) {
1722 time_out_message(widgets_p, file2);
1723 return;
1724 }
1725 g_free (widgets_p->workdir);
1726 widgets_p->workdir = g_strdup (g_get_home_dir ());
1727
1728 gchar *argv[4];
1729 int i = 0;
1730 argv[i++] = "rodent-diff";
1731 if(file1)
1732 argv[i++] = file1;
1733 if(file2)
1734 argv[i++] = file2;
1735 argv[i] = NULL;
1736
1737 rfm_thread_run_argv (widgets_p, argv, FALSE);
1738 }
1739 static void
settings(widgets_t * widgets_p)1740 settings(widgets_t *widgets_p){
1741 if(rfm_void (RFM_MODULE_DIR, "settings", "module_active")) {
1742 rfm_void (RFM_MODULE_DIR, "settings", "run_rfm_settings_dialog");
1743 } else {
1744 DBG ("rodent_settings_activate(): cannot load libsettings\n");
1745 }
1746 }
1747
1748 static void *
new_tab(gpointer data)1749 new_tab(gpointer data){
1750 void **arg = data;
1751 view_t *view_p = arg[0];
1752 gchar *argv = arg[1];
1753 g_free(arg);
1754 widgets_t *widgets_p = &(view_p->widgets);
1755 if (view_p->tab_constructor) (*(view_p->tab_constructor))(widgets_p, argv);
1756 g_free(argv);
1757 return NULL;
1758 }
1759
1760 static void *
new_tab_f(void * data)1761 new_tab_f(void *data){
1762 if (rfm_get_gtk_thread() != g_thread_self()){
1763 rfm_context_function(new_tab_f, data);
1764 return NULL;
1765 }
1766 widgets_t *widgets_p = data;
1767 view_t *view_p = widgets_p->view_p;
1768 if (!view_p->tab_constructor) return NULL;
1769 gchar *path = NULL;
1770 if (view_p->en && !view_p->en->module) path = view_p->en->path;
1771 (*(view_p->tab_constructor))(widgets_p, path);
1772 return NULL;
1773 }
1774
1775
1776
1777
1778
1779 // This function uses menuitem and does not accept keybinding...
1780 // autotype C is "open with" operator which is determined by
1781 // means of the command associated data item of the widget
1782 static void
autotype(widgets_t * widgets_p,gpointer menuitem)1783 autotype (widgets_t *widgets_p, gpointer menuitem) {
1784 if (!menuitem) return;
1785 view_t *view_p = widgets_p->view_p;
1786 gchar *new_command=NULL;
1787 record_entry_t *en = view_p->selection_list->data;
1788 if (!en->path || !strlen(en->path))return;
1789
1790 const gchar *output_arg = g_object_get_data (G_OBJECT (menuitem), "output_arg");
1791 const gchar *command = g_object_get_data (G_OBJECT (menuitem), "command");
1792 const gchar *dirname = g_object_get_data (G_OBJECT (menuitem), "workdir");
1793 const gchar *querypath = g_object_get_data (G_OBJECT (menuitem), "querypath");
1794 const gchar *output_ext = g_object_get_data (G_OBJECT (menuitem), "output_ext");
1795
1796 // Assign command as default command here, if applicable.
1797 if (g_object_get_data(G_OBJECT(menuitem), "CTL_SET")) {
1798 NOOP("CTL is set\n");
1799 // must substitute path in command line for %s
1800 gchar *command_fmt=g_strdup(command);
1801 command_fmt=strip_path(command_fmt,en->path);
1802
1803 if(!en->mimetype || strcmp(en->mimetype, _("unknown"))==0) {
1804 if (IS_LOCAL_TYPE(en->type) && !en->mimemagic) {
1805 en->mimemagic = rfm_rational(RFM_MODULE_DIR, "mime", en, "mime_magic", "mime_function");
1806 if (!en->mimemagic) en->mimemagic = g_strdup(_("unknown"));
1807 } else {
1808 en->mimemagic = g_strdup(_("unknown"));
1809 }
1810 }
1811 if(en->mimetype && strcmp(en->mimetype, _("unknown"))!= 0) {
1812 NOOP (stderr, "OPEN: adding %s --> %s \n", view_p->mouse_event.selected_p->en->mimetype, command_fmt);
1813 // This sets it as default command for the specified mimetype
1814 MIME_add (en->mimetype, command_fmt);
1815 }
1816 g_free(command_fmt);
1817 }
1818
1819
1820
1821
1822 gint argc;
1823 gchar **argv;
1824 GError *error=NULL;
1825
1826 if(!g_shell_parse_argv (command, &argc, &argv, &error)) {
1827 DBG("autotype_activate(%s): %s\n", command, error->message);
1828 g_error_free (error);
1829 g_strfreev (argv);
1830 NOOP ("!g_shell_parse_argv at popup_autostuff\n");
1831 return;
1832 }
1833
1834 // internal commands:
1835 if (strcmp(argv[0], "rodent-newtab")==0){
1836 if(view_p->tab_constructor) {
1837 void **arg = (void **)malloc(2*sizeof(void*));
1838 if (!arg) g_error("malloc: %s\n", strerror(errno));
1839 arg[0] = view_p;
1840 arg[1] = g_strdup(argv[1]);
1841 // Wait for this:
1842 rfm_context_function(new_tab, arg);
1843 }
1844 return;
1845 }
1846 if (strcmp(argv[0], "rodent-bcrypt")==0){
1847 bcrypt(widgets_p);
1848 return;
1849 }
1850 if (strcmp(argv[0], "rodent-newwin")==0){
1851 rodent_new_gridview(widgets_p, argv[1]);
1852 return;
1853 }
1854 // We don't use this any more:
1855 g_strfreev (argv);
1856
1857 gchar *workdir=NULL;
1858 if(querypath) {
1859 workdir=autofunction_workdir (widgets_p, querypath);
1860 if (!workdir) return;
1861 }
1862
1863 if (dirname) {// XXX I wonder what this is for?
1864 g_free (widgets_p->workdir);
1865 widgets_p->workdir = g_strdup (dirname);
1866 }
1867 if(output_ext) {
1868 gchar *basename = g_path_get_basename (output_arg);
1869 gchar *output_path=g_strconcat("\"",workdir, G_DIR_SEPARATOR_S, basename, output_ext,"\"",NULL);
1870 gchar *esc_path = g_strconcat("\"",basename,"\"",NULL);
1871 g_free(basename);
1872 basename=esc_path;
1873
1874 gchar *s=strstr(command,"%s");
1875 if (s) {
1876 // XXX this should have at least two %s tokens...
1877 new_command = g_strdup_printf(command, output_path, basename);
1878 } else {
1879 NOOP("no %%s in command");
1880 new_command = g_strconcat (command, " ", output_path, " ", basename, NULL);
1881 }
1882 command = (const gchar *)new_command;
1883 g_free (output_path);
1884 g_free (basename);
1885 } else if (workdir) {
1886 g_free (widgets_p->workdir);
1887 widgets_p->workdir = g_strdup (workdir);
1888 }
1889 NOOP ("output_arg=%s, command=%s, querypath(string)=%s, output_ext=%s, dirname=%s workdir=%s\n", output_arg, command, querypath,
1890 output_ext, dirname, widgets_p->workdir);
1891
1892 rfm_threaded_show_text(widgets_p);
1893 RFM_THREAD_RUN2ARGV (widgets_p, (void *)command, FALSE);
1894
1895 g_free (new_command);
1896 g_free (workdir);
1897
1898
1899 }
1900
1901 // This function is for executables and dotdesktop types.
1902 static void
autotype_r(widgets_t * widgets_p,gpointer menuitem)1903 autotype_r (widgets_t *widgets_p, gpointer menuitem) {
1904 if (!menuitem) return;
1905 record_entry_t *en = g_object_get_data(G_OBJECT(menuitem), "record_entry");
1906 if (en) {
1907 if (en->mimetype &&
1908 strcmp(en->mimetype, "application/x-desktop")==0 &&
1909 rfm_rational(PLUGIN_DIR, "dotdesktop", widgets_p, en, "double_click"))
1910 {
1911 return;
1912 }
1913
1914 if (en->path && IS_EXE_TYPE(en->type))
1915 {
1916 NOOP("executing %s\n", en->path);
1917 g_free(widgets_p->workdir);
1918 widgets_p->workdir=g_path_get_dirname(en->path);
1919 if (!rfm_g_file_test_with_wait(widgets_p->workdir, G_FILE_TEST_EXISTS)){
1920 time_out_message(widgets_p, widgets_p->workdir);
1921 g_free(widgets_p->workdir);
1922 widgets_p->workdir = g_strdup(g_get_home_dir());
1923 } else {
1924 gchar *argv[2]={en->path, NULL};
1925 rfm_thread_run_argv(widgets_p, argv, TRUE);
1926 }
1927 }
1928 }
1929 return;
1930 }
1931
1932 static void
rename_x(widgets_t * widgets_p)1933 rename_x (widgets_t *widgets_p) {
1934 view_t *view_p = widgets_p->view_p;
1935 void **arg = (void **) malloc(3*sizeof(void *));
1936 if (!arg) g_error("malloc: %s\n", strerror(errno));
1937 arg[0] = view_p;
1938 arg[1] = (void *)(view_p->mouse_event.selected_p);
1939 arg[2] = GINT_TO_POINTER(RENAME_CASO);
1940 rfm_context_function(mk_rename_entry, arg);
1941 }
1942
1943 static void
duplicate(widgets_t * widgets_p)1944 duplicate (widgets_t *widgets_p) {
1945 view_t *view_p = widgets_p->view_p;
1946 void **arg = (void **) malloc(3*sizeof(void *));
1947 if (!arg) g_error("malloc: %s\n", strerror(errno));
1948 arg[0] = view_p;
1949 arg[1] = (void *)(view_p->mouse_event.selected_p);
1950 arg[2] = GINT_TO_POINTER(DUPLICATE_CASO);
1951 rfm_context_function(mk_rename_entry, arg);
1952 }
1953
1954 static void
symlink_x(widgets_t * widgets_p)1955 symlink_x (widgets_t *widgets_p) {
1956 view_t *view_p = widgets_p->view_p;
1957 void **arg = (void **) malloc(3*sizeof(void *));
1958 if (!arg) g_error("malloc: %s\n", strerror(errno));
1959 arg[0] = view_p;
1960 arg[1] = (void *)(view_p->mouse_event.selected_p);
1961 arg[2] = GINT_TO_POINTER(SYMLINK_CASO);
1962 rfm_context_function(mk_rename_entry, arg);
1963 }
1964
1965
1966 static void
touch(widgets_t * widgets_p)1967 touch (widgets_t *widgets_p) {
1968 view_t *view_p = widgets_p->view_p;
1969 GSList *list = NULL;
1970 GSList *tmp = view_p->selection_list;
1971 for (;tmp && tmp->data; tmp=tmp->next) {
1972 record_entry_t *en=tmp->data;
1973 list = g_slist_append(list, g_strdup (en->path));
1974 }
1975 void **argv = (void **)malloc(2*sizeof(void *));
1976 argv[0] = widgets_p;
1977 argv[1] = list;
1978 rfm_context_function(touch_dialog, argv);
1979 return;
1980 }
1981
1982 static void
properties(widgets_t * widgets_p)1983 properties (widgets_t *widgets_p) {
1984 view_t *view_p = widgets_p->view_p;
1985 if(view_p->module &&
1986 rfm_rational (PLUGIN_DIR, view_p->module,
1987 widgets_p, view_p->selection_list, "do_properties")
1988 ) {
1989 // module has done the properties thing here;
1990 } else {
1991 rfm_natural(RFM_MODULE_DIR, "properties", widgets_p, "do_prop");
1992 }
1993 }
1994
1995
1996 static void
select_all(widgets_t * widgets_p,gpointer user_data)1997 select_all (widgets_t *widgets_p, gpointer user_data) {
1998 view_t *view_p = widgets_p->view_p;
1999 rfm_status (&(view_p->widgets), "xffm/stock_dialog-info", _("Select All"), "...", NULL);
2000 select_all_view (view_p, GPOINTER_TO_INT(user_data));
2001 gchar *plural_text=g_strdup_printf (
2002 ngettext ("%'u item", "%'u items", g_slist_length(view_p->selection_list)),
2003 g_slist_length(view_p->selection_list));
2004 gchar *g = g_strdup_printf ("%s: %s", _("Selection"), plural_text);
2005 g_free(plural_text);
2006 rfm_threaded_status (&(view_p->widgets), "xffm/stock_dialog-info", g);
2007 }
2008
2009 static void
select_by_filter(widgets_t * widgets_p,gpointer user_data)2010 select_by_filter (widgets_t *widgets_p, gpointer user_data) {
2011 gboolean select_it = GPOINTER_TO_INT(user_data);
2012 gchar *filter_s;
2013 view_t *view_p = widgets_p->view_p;
2014 gchar *b = g_strdup_printf ("%s/", view_p->en->path);
2015 gchar *label = rfm_utf_string (rfm_chop_excess (b));
2016 filter_s = get_response ( (select_it)?_("Select Items Matching..."):
2017 _("Unselect Items Matching..."), label, "*");
2018 g_free (label);
2019 g_free (b);
2020 if(filter_s && strlen (filter_s)) {
2021 select_byfilter_view (widgets_p, filter_s, select_it);
2022 }
2023 g_free(filter_s);
2024 }
2025
2026
2027 static void
mount(widgets_t * widgets_p)2028 mount (widgets_t *widgets_p) {
2029 private_mount (widgets_p, FALSE);
2030 }
2031
2032 static void
unmount(widgets_t * widgets_p)2033 unmount (widgets_t *widgets_p) {
2034 private_mount (widgets_p, TRUE);
2035 }
2036
2037 static void *close_x (gpointer data);
2038
2039
2040 static void *
quit(void * data)2041 quit (void *data) {
2042 //return NULL;
2043 rfm_global_t *rfm_global_p = rfm_global();
2044 g_mutex_lock(rfm_global_p->status_mutex);
2045 //g_error("wuit...\n");
2046 TRACE("quit(): setting status to STATUS_EXIT\n");
2047 rfm_global_p->status = STATUS_EXIT;
2048 g_mutex_unlock(rfm_global_p->status_mutex);
2049
2050 #ifndef VERIFY_LEAKS
2051 TRACE("ZZZ quit(): killing all controller children now...\n");
2052 rfm_killall_children();
2053 // This is quick exit, without memory leak check cleanup
2054 TRACE("ZZZ quit(): exit now.\n");
2055 exit(1);
2056 #else
2057 TRACE("VERIFY_LEAKS is set on exit...\n");
2058 // This way the janitor exits the main loop and the main program
2059 // will do a full cleanup to verify memory leaks.
2060 widgets_t *widgets_p = data;
2061 TRACE( "ZZZ quit callback... thread 0x%x\n",GPOINTER_TO_INT(g_thread_self()));
2062 if (rfm_get_gtk_thread() != g_thread_self()){
2063 rfm_context_function(quit, widgets_p);
2064 return NULL;
2065 }
2066 TRACE( "ZZZ quit callback proceed ... thread 0x%x\n",GPOINTER_TO_INT(g_thread_self()));
2067
2068 g_cond_signal(rfm_global_p->janitor_signal);
2069 gtk_widget_hide(rfm_global_p->window);
2070 gdk_flush();
2071 #endif
2072 return NULL;
2073 }
2074
2075 static void *
destructor(void * data)2076 destructor(void *data){
2077 view_t *view_p = data;
2078 (*(view_p->tab_destructor))(view_p);
2079 return NULL;
2080 }
2081
2082 static void *
close_x(gpointer data)2083 close_x (gpointer data) {
2084 TRACE("ZZZ close_x callback...\n");
2085 widgets_t *widgets_p = data;
2086 rfm_global_t *rfm_global_p = rfm_global();
2087 if (!widgets_p){
2088 DBG("close_x(): widgets_p==NULL\n");
2089 return NULL;
2090 }
2091
2092 if (strstr(rfm_global_p->argv[0], "rodent-desk")){
2093 quit(widgets_p);
2094 return NULL;
2095 }
2096
2097 GSList **list_p = rfm_view_list_lock(NULL, "close_x");
2098 gint active_views = g_slist_length(*list_p);
2099 rfm_view_list_unlock("close_x");
2100 if(active_views == 1) quit(widgets_p);
2101 // Gridview...
2102 view_t *view_p = widgets_p->view_p;
2103 if (!view_p) return FALSE;
2104 TRACE("ZZZ calling destructor...\n");
2105 if (view_p->tab_destructor) destructor(view_p);
2106 return NULL;
2107 }
2108
2109
2110 // This function uses menuitem and does not accept keybinding...
2111 static void
bookmark_add(widgets_t * widgets_p,gpointer menuitem)2112 bookmark_add (widgets_t *widgets_p, gpointer menuitem) {
2113 view_t * view_p = widgets_p->view_p;
2114 const gchar *path = NULL;
2115 if (menuitem) path = g_object_get_data(G_OBJECT(menuitem), "path");
2116 else if (view_p->en) path = view_p->en->path;
2117 if (!path) return;
2118 if (!g_path_is_absolute(path)){
2119 return;
2120 }
2121 if (rodent_bookmarks_add(path)) {
2122 unselect_all (widgets_p);
2123 if (menuitem){
2124 GdkRectangle *rect=g_object_get_data(G_OBJECT(menuitem), "rect");
2125 if (rect) rfm_expose_rect (view_p, rect);
2126 }
2127 rodent_set_view_icon (view_p); // this is sent to main context.
2128 rfm_threaded_diagnostics(widgets_p, "xffm/stock_dialog-info",NULL);
2129 rfm_threaded_diagnostics(widgets_p, "xffm_tag/blue", g_strconcat(_("Bookmark added"),"\n",NULL));
2130 } else {
2131 rfm_threaded_diagnostics(widgets_p, "xffm/stock_dialog-warning",NULL);
2132 rfm_threaded_diagnostics(widgets_p, "xffm_tag/stderr", g_strconcat(_("The operation was cancelled."),"\n",NULL));
2133 }
2134 }
2135
2136 // This function uses menuitem and does not accept keybinding...
2137 static void
bookmark_remove(widgets_t * widgets_p,gpointer menuitem)2138 bookmark_remove (widgets_t *widgets_p, gpointer menuitem) {
2139 view_t * view_p = widgets_p->view_p;
2140 const gchar *path = NULL;
2141 if (menuitem) path = g_object_get_data(G_OBJECT(menuitem), "path");
2142 else if (view_p->en) path = view_p->en->path;
2143 if (!path) return;
2144
2145 if (rodent_bookmarks_remove(path)) {
2146 unselect_all (widgets_p);
2147 if (menuitem){
2148 GdkRectangle *rect=g_object_get_data(G_OBJECT(menuitem), "rect");
2149 if (rect) rfm_expose_rect (view_p, rect);
2150 }
2151 rodent_set_view_icon (view_p); // this is sent to main context.
2152 } else {
2153 rfm_threaded_diagnostics(widgets_p, "xffm/stock_dialog-warning",NULL);
2154 rfm_threaded_diagnostics(widgets_p, "xffm_tag/stderr", g_strconcat(_("The operation was cancelled."),"\n",NULL));
2155 }
2156 }
2157
2158 static void
toggle_bookmark(widgets_t * widgets_p)2159 toggle_bookmark (widgets_t *widgets_p) {
2160 view_t * view_p = widgets_p->view_p;
2161 const gchar *path = NULL;
2162 if (view_p->en) path = view_p->en->path;
2163 if (!path) return;
2164 if (rodent_path_has_bookmark(path)) bookmark_remove(widgets_p, NULL);
2165 else bookmark_add(widgets_p, NULL);
2166 }
2167
2168 static gint
compar(const void * a_p,const void * b_p)2169 compar(const void *a_p, const void *b_p){
2170 RodentCallback *a = (RodentCallback *)a_p;
2171 RodentCallback *b = (RodentCallback *)b_p;
2172 if (!a && !b) return 0;
2173 if (!a) return -1;
2174 if (!b) return -1;
2175 if (a->key - b->key) return (a->key - b->key);
2176 return (a->mask - b->mask);
2177 }
2178
2179 static void
keybindings(widgets_t * widgets_p)2180 keybindings (widgets_t *widgets_p){
2181 RodentCallback *p = menu_callback_v;
2182 size_t nmemb = sizeof(menu_callback_v) / sizeof(RodentCallback) - 1;
2183 // quick sort
2184 qsort(p, nmemb, sizeof(RodentCallback), compar);
2185 //void (*callback)(GtkMenuItem * menuitem, gpointer user_data);
2186 rfm_threaded_show_text(widgets_p);
2187 for (; p && p->function_id > 0; p++){
2188 if (!p->key) continue;
2189 gchar *mod=g_strdup("");
2190 gchar *key=NULL;
2191 if (p->mask & GDK_SHIFT_MASK) {
2192 gchar *g = g_strconcat (mod,_("Shift"), "+", NULL);
2193 g_free(mod);
2194 mod = g;
2195 }
2196 if (p->mask & GDK_CONTROL_MASK) {
2197 gchar *g = g_strconcat (mod,_("Control"), "+", NULL);
2198 g_free(mod);
2199 mod = g;
2200 }
2201 if (p->mask & GDK_MOD1_MASK) {
2202 gchar *g = g_strconcat (mod,_("Alt"), "+", NULL);
2203 g_free(mod);
2204 mod = g;
2205 }
2206 if ((p->key > 0x40 && p->key < 0x5b) ||(p->key >0x02f && p->key < 0x03a)) {
2207 key = g_strdup_printf("%c", p->key);
2208 }
2209 else if (p->key > 0x60 && p->key < 0x7b) {
2210 key = g_strdup_printf("%c", toupper(p->key));
2211 }
2212 else if (p->key > 0xffbd && p->key < 0xffca) { // function keys f1-f12
2213 key = g_strdup_printf("F%d", p->key-0xffbd);
2214 }
2215 else { // other keys
2216 switch (p->key){
2217 case GDK_KEY_Home: key = g_strdup(_("Home")); break;
2218 case GDK_KEY_Left: key = g_strdup(_("Left")); break;
2219 case GDK_KEY_Up: key = g_strdup(_("Up")); break;
2220 case GDK_KEY_Right: key = g_strdup(_("Right")); break;
2221 case GDK_KEY_Down: key = g_strdup(_("Down")); break;
2222 case GDK_KEY_Page_Up: key = g_strdup(_("Page up")); break;
2223 case GDK_KEY_Page_Down: key = g_strdup(_("Page down")); break;
2224 case GDK_KEY_End: key = g_strdup(_("End")); break;
2225 case GDK_KEY_Begin: key = g_strdup(_("Begin")); break;
2226 case GDK_KEY_Delete: key = g_strdup(_("Delete")); break;
2227 case GDK_KEY_Insert: key = g_strdup(_("Insert")); break;
2228 case GDK_KEY_equal: key = g_strdup(_("Equal")); break;
2229 case GDK_KEY_plus: key = g_strdup(_("Plus")); break;
2230 case GDK_KEY_minus: key = g_strdup(_("Minus")); break;
2231 case GDK_KEY_KP_Add: key = g_strdup(_("Add")); break;
2232 case GDK_KEY_KP_Subtract: key = g_strdup(_("Subtract")); break;
2233 }
2234 }
2235 if (!key) key = g_strdup_printf("0x%x", p->key);
2236 const gchar *icon = p->icon;
2237 if (!icon && p->type == CHECKITEM_TYPE)icon = "xffm/emblem_synchronized";
2238 else if (!icon && p->type == RADIOITEM_TYPE)icon = "xffm/emblem_favorite";
2239 rfm_threaded_diagnostics(widgets_p, icon, NULL);
2240 rfm_threaded_diagnostics(widgets_p, "xffm_tag/red", g_strconcat(mod, key, " ",NULL));
2241 rfm_threaded_diagnostics(widgets_p, "xffm_tag/green", g_strconcat(_(p->string), "\n",NULL));
2242 g_free(key);
2243 g_free(mod);
2244 }
2245 }
2246
2247 static gboolean
do_item_click(widgets_t * widgets_p,record_entry_t * en)2248 do_item_click(widgets_t *widgets_p, record_entry_t *en){
2249 TRACE ("do_item_click: %s\n", en->path);
2250 if (en && !IS_LOCAL_TYPE(en->type) &&
2251 !rfm_entry_available(widgets_p, en)) return TRUE;
2252 if ((!en->mimetype || strcmp(en->mimetype, _("unknown"))==0) && !en->mimemagic){
2253 if (IS_LOCAL_TYPE(en->type) && !en->mimemagic) {
2254 // avoid magic on remote fs...
2255 en->mimemagic = rfm_rational(RFM_MODULE_DIR, "mime", en, "mime_magic", "mime_function");
2256 if (!en->mimemagic) en->mimemagic = g_strdup(_("unknown"));
2257 }
2258 if (!en->mimemagic) en->mimemagic = g_strdup(_("unknown"));
2259 }
2260 const gchar *mimetype = en->mimetype;
2261 if (!mimetype || strcmp(mimetype, _("unknown"))==0){
2262 mimetype = en->mimemagic;
2263 }
2264
2265 if (strstr(mimetype, "application/x-desktop") &&
2266 rfm_void(PLUGIN_DIR, "dotdesktop", "module_active")) {
2267 rfm_rational(PLUGIN_DIR, "dotdesktop", widgets_p, en, "double_click");
2268 return TRUE;
2269 }
2270 gchar *prg = MIME_command (mimetype);
2271 NOOP("prg=%s, mimetype=%s\n", prg, mimetype);
2272 if (prg) {
2273 // This open_with, since prg != NULL, will
2274 // open the associated application.
2275 NOOP (stderr, "OPEN: calling rodent_open_with()\n");
2276 open_with (widgets_p, en);
2277 g_free (prg);
2278 return TRUE;
2279
2280 } else if (IS_EXE_TYPE (en->type)) {
2281 // Since there is no associated application, then try
2282 // to execute the program if it has the exec bit on.
2283 NOOP("rodent_mouse: using RFM_THREAD_RUN2ARGV\n");
2284 view_t *view_p = widgets_p->view_p;
2285 if (view_p->en && IS_LOCAL_TYPE(view_p->en->type)){
2286 g_free(widgets_p->workdir);
2287 widgets_p->workdir=g_strdup(view_p->en->path);
2288 }
2289 /* assume in_term to be safe */
2290 RFM_THREAD_RUN2ARGV (widgets_p, en->path, TRUE);
2291 return TRUE;
2292
2293 } else {
2294 // this open_with, when prg==NULL will open the dialog, or
2295 // default to default editor if file is editable.
2296 open_with (widgets_p, en);
2297 return TRUE;
2298
2299 }
2300 DBG("do_item_click(): nothing programed here with double click: %s\n", en->path);
2301 return FALSE;
2302 }
2303 #define MODULE_EN(x) ((view_p->module)?view_p->module:(x)->module)
2304
2305 static gboolean
do_folder_click(widgets_t * widgets_p,record_entry_t * en)2306 do_folder_click(widgets_t *widgets_p, record_entry_t *en){
2307 TRACE( " do_folder_click...\n");
2308
2309 if (en && !IS_LOCAL_TYPE(en->type) &&
2310 !rfm_entry_available(widgets_p, en)) {
2311 return TRUE;
2312 }
2313
2314 view_t *view_p = widgets_p->view_p;
2315 view_t *view_target = view_p;
2316
2317 // Action will proceed. Clear out selection list.
2318 // XXX not working....
2319 {
2320 // XXX Mutex protection is missing here.
2321 GSList *list = view_p->selection_list;
2322 for (;list && list->data; list=list->next){
2323 rfm_destroy_entry((record_entry_t *)list->data);
2324 }
2325 g_slist_free(view_p->selection_list);
2326 view_p->selection_list = NULL;
2327 }
2328
2329 // Special treatment when item vanishes from system
2330 // (only local types to avoid blockage on network error).
2331 if (en && !en->module &&
2332 IS_SDIR(en->type) &&
2333 IS_LOCAL_TYPE(en->type) &&
2334 !g_file_test(en->path, G_FILE_TEST_IS_DIR)) {
2335 NOOP("Element is not a directory (may no longer exist)\n");
2336 // if go up icon selected, then go up...
2337 if(IS_UP_TYPE(en->type))
2338 {
2339 gchar *path=g_strdup(en->path);
2340 while (!rfm_g_file_test(path, G_FILE_TEST_IS_DIR)){
2341 gchar *d = g_path_get_dirname(path);
2342 g_free(path);
2343 path = d;
2344 }
2345 record_entry_t *new_en =rfm_stat_entry(path, 0);
2346 if (!rodent_refresh (&(view_target->widgets), new_en)) rfm_destroy_entry(new_en);
2347 g_free(path);
2348 } else {
2349 rfm_confirm(widgets_p, GTK_MESSAGE_WARNING, _("The location does not exist."), NULL, _("Accept"));
2350 }
2351 return TRUE;
2352
2353
2354 }
2355
2356 // Default folder click action: jump to.
2357 if(en) UNSET_DUMMY_TYPE(en->type);
2358 if(en && IS_SDIR(en->type)){
2359 // en != NULL implies that path is directory
2360 rfm_save_to_go_history (en->path);
2361 }
2362
2363 if(view_p->flags.type == DESKVIEW_TYPE &&
2364 (!getenv("RFM_NAVIGATE_DESKTOP") ||
2365 strlen(getenv("RFM_NAVIGATE_DESKTOP"))==0)){
2366 // This will open in a new window.
2367 // Basically for deskview type.
2368 gchar *path=NULL;
2369 if (en && MODULE_EN(en)) {
2370 path=g_strdup_printf("rodent-plug %s", MODULE_EN(en));
2371 } else if (en){
2372 path=g_strdup(en->path);
2373 }
2374
2375 NOOP ("DOUBLE_CLICK: en && view_p->child_constructor: %s (%s)\n", path, MODULE_EN(en));
2376 rodent_new_gridview(widgets_p, path);
2377 g_free(path);
2378 return TRUE;
2379
2380 }
2381 NOOP(stderr, "folder click... doing refresh...\n");
2382 // This is for the navigation history
2383 rodent_push_view_go_history ();
2384 // Quick visual response to the user:
2385 rodent_threaded_clean_paper(&(view_target->widgets));
2386 record_entry_t *new_en = rfm_copy_entry(en);
2387 // Deskview and iconview navigation:
2388 if(rodent_refresh (&(view_target->widgets), new_en)) {
2389 if(en && en->path &&
2390 IS_SDIR (en->type)){
2391 // This is for the combobox history
2392 rfm_save_to_go_history (en->path);
2393 }
2394 } else {
2395 rfm_destroy_entry(new_en);
2396 rodent_expose_all (view_target);
2397 }
2398 return TRUE;
2399 }
2400
2401 static void *
double_click(widgets_t * widgets_p)2402 double_click(widgets_t *widgets_p){
2403 rfm_global_t *rfm_global_p = rfm_global();
2404 view_t *view_p = widgets_p->view_p;
2405 record_entry_t *en = NULL;
2406 g_mutex_lock(view_p->mutexes.status_mutex);
2407 gboolean status = view_p->flags.status;
2408 g_mutex_unlock(view_p->mutexes.status_mutex);
2409 if(status == STATUS_EXIT) return NULL;
2410
2411 if (view_p->selection_list)
2412 en = rfm_copy_entry((record_entry_t *)view_p->selection_list->data);
2413
2414 NOOP( "**** double_click\n");
2415 //hide_tip (view_p);
2416
2417
2418 if(en && !en->module && IS_NOACCESS_TYPE (en->type) && !IS_PARTITION_TYPE(en->type)) {
2419 rfm_threaded_show_text(widgets_p);
2420 rfm_threaded_diagnostics (widgets_p, "xffm/stock_dialog-error", NULL);
2421 rfm_threaded_diagnostics (widgets_p, "xffm_tag/stderr",
2422 g_strconcat(strerror(EACCES), ": '", en->path, "'\n", NULL));
2423 rfm_threaded_cursor_reset(rfm_global_p->window);
2424 rfm_destroy_entry(en);
2425 return NULL;
2426 }
2427
2428 /* does the POPULATION_MODULE have something else in mind for the
2429 double click on the particular entry ? */
2430
2431 gboolean item_click=FALSE;
2432 gboolean folder_click=FALSE;
2433 gboolean module_click=FALSE;
2434 if (en){
2435 if (en && MODULE_EN(en)) {
2436 module_click = TRUE;
2437 }
2438 if (IS_SDIR (en->type)){
2439 folder_click = TRUE;
2440 } else if (g_path_is_absolute (en->path)){
2441 item_click = TRUE;
2442 } else if (module_click) {
2443 folder_click = TRUE;
2444 }
2445 } else {
2446 folder_click = TRUE;
2447 }
2448 TRACE( "Mouse: module_click=%d, item_click=%d, folder_click=%d\n",
2449 module_click,item_click, folder_click);
2450 // if the POPULATION_MODULE's double_click function does not exist or
2451 // returns NULL, callback proceeds with either item or folder behaviour.
2452 if (module_click &&
2453 rfm_rational(PLUGIN_DIR, MODULE_EN(en), widgets_p, en, "double_click"));
2454 else if (item_click) do_item_click(widgets_p, en);
2455 else if (folder_click) do_folder_click(widgets_p, en);
2456 else DBG("double_click(): should not reach this point (harmless though)\n");
2457
2458 rfm_threaded_cursor_reset(rfm_global_p->window);
2459 rfm_destroy_entry(en);
2460 return NULL;
2461 }
2462
2463 /////////////////////////////////////
2464 // Thread pool refactoring ready...//
2465 /////////////////////////////////////
2466
2467 static void
apply_new_icon_size(view_t * view_p)2468 apply_new_icon_size (view_t *view_p){
2469 static gboolean running = FALSE;
2470 if (running){
2471 DBG("Quietely ignoring apply_new_icon_size until current execution is done.\n");
2472 return;
2473 } else running = TRUE;
2474 TRACE("apply_new_icon_size: id=%d size=%d\n", ICON_SIZE_ID(view_p) ,ICON_SIZE(view_p));
2475 if (!rfm_population_read_lock (view_p, "apply_new_icon_size")) {
2476 running = FALSE;
2477 return ;
2478 }
2479 if (view_p->module){
2480 // Set the iconsize in the module for the view_p.
2481 gint size = ICON_SIZE_ID(view_p);
2482 if (!size) size = -1;
2483 rfm_rational(PLUGIN_DIR,view_p->module, view_p,
2484 GINT_TO_POINTER(size), "module_icon_size");
2485 }
2486 //record_entry_t *en = rfm_copy_entry (view_p->en);
2487 rfm_save_view_preferences (view_p, view_p->en);
2488
2489 view_p->flags.thumbnailer_active=TRUE;
2490 population_t **p = view_p->population_pp;
2491 gint element=0;
2492 for (;p && *p; p++, element++){
2493 population_t *population_p = *p;
2494 // FIXME: here we should resolve with the same procedure as used
2495 // when initially loaded. This here is borked (using icontheme though not selected)
2496 // but this *only* happens when monitor is disabled!
2497 // Remove iconsize changes from monitor... Everything should be here.
2498 if (population_p->layout) g_object_unref(population_p->layout);
2499 population_p->layout=NULL;
2500 if (population_p->layout2) g_object_unref(population_p->layout2);
2501 population_p->layout2=NULL;
2502 if (population_p->layout_full) g_object_unref(population_p->layout_full);
2503 population_p->layout_full=NULL;
2504
2505 if (population_p->pixbuf) g_object_unref(population_p->pixbuf);
2506 population_p->pixbuf = NULL;
2507
2508 population_p->icon_size=ICON_SIZE(view_p);
2509 population_p->icon_size_id = ICON_SIZE_ID(view_p);
2510
2511
2512 // No monitor, then get new icons here...
2513 if (10) {
2514 if (population_p->flags & POPULATION_IS_IMAGE){
2515 GdkPixbuf *pixbuf = rfm_create_preview (population_p->en->path, population_p->icon_size);//refs
2516 if (pixbuf) {
2517 population_p->thumbnail = pixbuf;
2518 population_p->flags |= POPULATION_PIXBUF_CLEAN;
2519 if (element % 5 == 0) rodent_expose_all(view_p);
2520 //rfm_expose_item(view_p, population_p);
2521 }
2522 }
2523
2524 if (population_p->pixbuf == NULL) {
2525 if (population_p->icon_id)
2526 population_p->pixbuf = rfm_get_pixbuf(population_p->icon_id, ICON_SIZE(view_p));
2527 else if (population_p->en && population_p->en->mimetype)
2528 population_p->pixbuf = rfm_get_pixbuf(population_p->en->mimetype, ICON_SIZE(view_p));
2529 else if (population_p->en && population_p->en->mimemagic)
2530 population_p->pixbuf = rfm_get_pixbuf(population_p->en->mimemagic, ICON_SIZE(view_p));
2531 else
2532 population_p->pixbuf = rfm_get_pixbuf("xffm/whatever", ICON_SIZE(view_p));
2533
2534 }
2535 } else {
2536 // monitor will take care of new icons
2537 // path absolute, en != NULL en-module ==NULL
2538 // memset(population_p->en->st, 0., sizeof(struct stat));
2539 }
2540 population_p->layout=NULL;
2541 population_p->layout2=NULL;
2542 population_p->layout_full=NULL;
2543
2544 rfm_layout_pango_layout_setup(view_p); // this gets name column width for details view
2545 rfm_layout_population_grid_row (view_p, population_p, element); // this sets correct row,col
2546 }
2547
2548 rfm_population_read_unlock (view_p, "apply_new_icon_size");
2549 rodent_expose_all(view_p);
2550 view_p->flags.thumbnailer_active=FALSE;
2551 running = FALSE;
2552
2553 }
2554
2555 static GMutex *
get_sweep_mutex(void)2556 get_sweep_mutex(void){
2557 static GMutex *mutex = NULL;
2558 static gsize initialized = 0;
2559 if (g_once_init_enter (&initialized)){
2560 rfm_mutex_init(mutex);
2561 g_once_init_leave (&initialized, 1);
2562 }
2563 return mutex;
2564 }
2565 static void
reset_saved_iconsize(DBHashTable * old)2566 reset_saved_iconsize (DBHashTable * old) {
2567 DBHashTable *new = old->sweep_data;
2568 gint record_size = DBH_RECORD_SIZE(old);
2569
2570 dbh_set_recordsize (new, record_size);
2571 memcpy(DBH_KEY(new), DBH_KEY(old), DBH_KEYLENGTH(old));
2572 memcpy(new->data, old->data, record_size);
2573 view_preferences_t *view_preferences_p = new->data;
2574 view_preferences_p->icon_size = rfm_get_default_size();
2575 NOOP("sweep now, record size=%d\n", record_size);
2576 dbh_update(new);
2577 return;
2578 }
2579
2580 static void
default_iconsize_all(widgets_t * widgets_p)2581 default_iconsize_all (widgets_t *widgets_p){
2582 // The easy way would be just to unlink the preferences file,
2583 // but that would take down sort orders and show hidden
2584 // attributes as well. So instead we just set each saved preference
2585 // item to user default size.
2586 NOOP("rodent_default_iconsize_all\n");
2587
2588 view_t *view_p = widgets_p->view_p;
2589 gint default_size = rfm_get_default_size();
2590
2591 gchar *f;
2592 if (view_p->flags.type==ICONVIEW_TYPE) {
2593 f = g_build_filename (GRID_PREFERENCES_FILE, NULL);
2594 } else {
2595 f = g_build_filename (DESK_PREFERENCES_FILE, NULL);
2596 }
2597 FILE *f_p = fopen(f,"r");
2598 if (!f_p){
2599 g_free(f);
2600 return;
2601 }
2602 fclose(f_p);
2603 TRACE("opening %s...\n",f);
2604 DBHashTable *old = dbh_new (f, NULL, DBH_PARALLEL_SAFE);
2605 TRACE("opened %s.\n",f);
2606 if(old == NULL) {
2607 g_free(f);
2608 return;
2609 }
2610 dbh_set_parallel_lock_timeout(old, 3);
2611
2612 gchar *ff=g_strconcat(f,"-new",NULL);
2613 GMutex *sweep_mutex=get_sweep_mutex() ;
2614 g_mutex_lock(sweep_mutex);
2615 unsigned char keylength=DBH_KEYLENGTH (old);
2616 gchar *directory = g_path_get_dirname(ff);
2617 if (!g_file_test(directory, G_FILE_TEST_IS_DIR)){
2618 g_mkdir_with_parents(directory, 0700);
2619 }
2620 g_free(directory);
2621 TRACE("opening %s...\n",ff);
2622 DBHashTable *new = dbh_new (ff, &keylength, DBH_PARALLEL_SAFE|DBH_CREATE);
2623 TRACE("open %s.\n",ff);
2624
2625 if(new == NULL) {
2626 dbh_close(old);
2627 DBG("cannot create file %s\n", ff);
2628 g_free(f);
2629 g_free(ff);
2630 g_mutex_unlock(sweep_mutex);
2631 return;
2632 }
2633 dbh_set_parallel_lock_timeout(new, 3);
2634 old->sweep_data = new;
2635 NOOP("sweep now\n");
2636 dbh_foreach_sweep (old, reset_saved_iconsize);
2637
2638 dbh_close(old);
2639 dbh_close(new);
2640
2641 /*if (unlink(f) < 0) {
2642 DBG("unlink(%s): %s\n", f, strerror(errno));
2643 }*/
2644 NOOP("rename(%s, %s)\n", f, ff);
2645 if (rename (ff,f) < 0) {
2646 DBG("rename(%s, %s): %s\n", f, ff, strerror(errno));
2647 }
2648
2649
2650 g_free(f);
2651 g_free(ff);
2652
2653 g_mutex_unlock(sweep_mutex);
2654
2655 if (default_size != ICON_SIZE_ID(view_p)) {
2656 rfm_layout_set_icon_size_full(view_p, default_size);
2657 apply_new_icon_size (view_p);
2658 }
2659 }
2660 static void
default_iconsize(widgets_t * widgets_p)2661 default_iconsize (widgets_t *widgets_p){
2662 view_t *view_p = widgets_p->view_p;
2663 gint default_size = rfm_get_default_size();
2664 if (default_size != ICON_SIZE_ID(view_p)) {
2665 rfm_layout_set_icon_size_full(view_p, default_size);
2666 apply_new_icon_size (view_p);
2667 }
2668 }
2669
2670 static void
increase_iconsize(widgets_t * widgets_p)2671 increase_iconsize (widgets_t *widgets_p){
2672 view_t *view_p = widgets_p->view_p;
2673 gint original_size = ICON_SIZE_ID(view_p);
2674 gint new_size = original_size + 24;
2675 //if (new_size > BIG_ICON_SIZE) new_size = LIST_ICON_SIZE;
2676 if (new_size > BIG_ICON_SIZE) new_size = BIG_ICON_SIZE;
2677 TRACE( "newsize/original %d/%d\n", new_size, original_size);
2678
2679 if (original_size != new_size) {
2680 rfm_layout_set_icon_size_full(view_p, new_size);
2681 apply_new_icon_size (view_p);
2682 }
2683 }
2684
2685 static void
decrease_iconsize(widgets_t * widgets_p)2686 decrease_iconsize (widgets_t *widgets_p){
2687 view_t *view_p = widgets_p->view_p;
2688 gint original_size = ICON_SIZE_ID(view_p);
2689 gint new_size = original_size - 24;
2690 //if (new_size < LIST_ICON_SIZE) new_size = BIG_ICON_SIZE;
2691 if (new_size < LIST_ICON_SIZE) new_size = LIST_ICON_SIZE;
2692 if (original_size != new_size) {
2693 rfm_layout_set_icon_size_full(view_p, new_size);
2694 apply_new_icon_size (view_p);
2695 }
2696 }
2697
2698
2699 static void
toggle_casesort(widgets_t * widgets_p)2700 toggle_casesort(widgets_t *widgets_p){
2701 view_t *view_p = widgets_p->view_p;
2702 // Toggle value
2703 view_p->flags.preferences ^= __CASE_INSENSITIVE;
2704
2705 rfm_save_view_preferences (view_p, view_p->en);
2706 record_entry_t *en = rfm_copy_entry (view_p->en);
2707 NOOP(stderr, "*-*-*-* toggle_casesort rodent_refresh\n");
2708 if (!rodent_refresh (widgets_p, en)){ rfm_destroy_entry(en); }
2709 }
2710
2711 static void
backup_unbackup(widgets_t * widgets_p)2712 backup_unbackup(widgets_t *widgets_p){
2713 view_t *view_p = widgets_p->view_p;
2714
2715 // Toggle value
2716 view_p->flags.preferences ^= __SHOWS_BACKUP;
2717 rfm_save_view_preferences (view_p, view_p->en);
2718 record_entry_t *en = rfm_copy_entry (view_p->en);
2719 /*if (SHOWS_BACKUP(view_p->flags.preferences)) {
2720 SET_SHOWS_BACKUP(en->type);
2721 } else {
2722 UNSET_SHOWS_BACKUP(en->type);
2723 }*/
2724 rodent_unsaturate_icon (view_p);
2725
2726 if (!rodent_refresh (widgets_p, en)){ rfm_destroy_entry(en); }
2727 }
2728
2729 static void
hide_unhide(widgets_t * widgets_p)2730 hide_unhide(widgets_t *widgets_p){
2731 view_t *view_p = widgets_p->view_p;
2732
2733 // Toggle value
2734 view_p->flags.preferences ^= __SHOW_HIDDEN;
2735 rfm_save_view_preferences (view_p, view_p->en);
2736 record_entry_t *en = rfm_copy_entry (view_p->en);
2737 /*if (SHOWS_HIDDEN(view_p->flags.preferences)) {
2738 SET_SHOWS_HIDDEN(en->type);
2739 } else {
2740 UNSET_SHOWS_HIDDEN(en->type);
2741 }*/
2742 rodent_unsaturate_icon (view_p);
2743
2744 if (!rodent_refresh (widgets_p, en)){ rfm_destroy_entry(en); }
2745 }
2746
2747 static void
preview(widgets_t * widgets_p)2748 preview (widgets_t *widgets_p) {
2749 view_t *view_p = widgets_p->view_p;
2750
2751 // Toggle value
2752 view_p->flags.preferences ^= __SHOW_IMAGES;
2753 // Save preferences
2754 rfm_save_view_preferences (view_p, view_p->en);
2755 // Now do the refresh.
2756 record_entry_t *en = rfm_copy_entry (view_p->en);
2757 if (!rodent_refresh (widgets_p, en)){ rfm_destroy_entry(en); }
2758 }
2759
2760 static void
sort(widgets_t * widgets_p,gpointer user_data)2761 sort(widgets_t *widgets_p, gpointer user_data){
2762 view_t *view_p = widgets_p->view_p;
2763 view_p->flags.sortcolumn = GPOINTER_TO_INT (user_data);
2764 switch (GPOINTER_TO_INT (user_data)){
2765 case DATE_SORT:
2766 case SIZE_SORT:
2767 case MODE_SORT:
2768 view_p->flags.preferences &= (SORT_ASCENDING ^ 0xffffffff);
2769 break;
2770 default:
2771 view_p->flags.preferences |= SORT_ASCENDING;
2772 }
2773 NOOP(stderr, "sort callback: return on apply new sort: %d\n", GPOINTER_TO_INT (user_data));
2774 rfm_save_view_preferences (view_p, view_p->en);
2775 record_entry_t *en = rfm_copy_entry (view_p->en);
2776 if (!rodent_refresh (widgets_p, en)){ rfm_destroy_entry(en); }
2777 }
2778
2779 static void
size(widgets_t * widgets_p,gpointer user_data)2780 size(widgets_t *widgets_p, gpointer user_data){
2781 NOOP(stderr, "size now...\n");
2782 view_t *view_p = widgets_p->view_p;
2783 gint new_size = GPOINTER_TO_INT (user_data);
2784 if (new_size != ICON_SIZE_ID(view_p)) {
2785 rfm_layout_set_icon_size_full(view_p, new_size);
2786 apply_new_icon_size (view_p);
2787 }
2788 }
2789
2790
2791 /*****************************************************************************/
2792
2793
2794 // New thread pool compatible method.
2795 static void *
threaded_callback(void * data)2796 threaded_callback(void *data){
2797 TRACE("threaded_callback()...\n");
2798 void **arg = data;
2799 enum menu_enum_t menu_enum = GPOINTER_TO_INT(arg[0]);
2800 GtkWidget *menuitem = arg[1];
2801 view_t *view_p = arg[2];
2802
2803 g_free(data);
2804
2805 // Put a lock on the view list to hold janitor in
2806 // case the view scheduled to be destroyed.
2807 // This will return false if view_p is no longer valid.
2808 if (!rfm_view_list_lock(view_p, "threaded_callback")) return NULL;
2809
2810 widgets_t *widgets_p = &(view_p->widgets);
2811
2812 // Do we really need to stop monitor?
2813 // Probably. I had a crash on a ctrl-f, when it tests for directory
2814 // condition. But placed in such a top level place as such, it
2815 // causes diverse callback deadlocks. Must fine tune the lock placement.
2816 //rfm_rw_lock_reader_lock (&(view_p->mutexes.monitor_lock));
2817
2818 NOOP(stderr, "threaded_callback: 0x%d\n", menu_enum);
2819
2820 gboolean valid = FALSE;
2821 switch (menu_enum){
2822 case RENAME_ACTIVATE:
2823 case DUPLICATE_ACTIVATE:
2824 case SYMLINK_ACTIVATE:
2825 case MOUNT_ACTIVATE:
2826 case UNMOUNT_ACTIVATE:
2827 case AUTOTYPE_ACTIVATE:
2828 case AUTOTYPE_R_ACTIVATE:
2829 if (!is_valid_view_entry(widgets_p, menu_enum)) break;
2830 if (!is_single_selection(widgets_p, menu_enum)) break;
2831 valid = TRUE; break;
2832
2833 case BCRYPT_ACTIVATE:
2834 case OPEN_WITH_ACTIVATE:
2835 case TOUCH_ACTIVATE:
2836 case PROPERTIES_ACTIVATE:
2837 case REMOVE_ACTIVATE:
2838 case CUT_ACTIVATE:
2839 case COPY_ACTIVATE:
2840 if (!is_valid_view_entry(widgets_p, menu_enum)) break;
2841 if (!is_multiple_selection(widgets_p, menu_enum)) break;
2842 valid = TRUE; break;
2843
2844 case PASTE_ACTIVATE:
2845 case DIFFERENCES_ACTIVATE:
2846 case RELOAD_ACTIVATE:
2847 case REFRESH_ACTIVATE:
2848 case NEW_WINDOW_ACTIVATE:
2849 case NEW_TAB_ACTIVATE:
2850 case NEWDIR_ACTIVATE:
2851 case NEWFILE_ACTIVATE:
2852 case UNSELECT_ALL_ACTIVATE:
2853 case SELECT_INVERT_ACTIVATE:
2854 case SELECT_ALL_ACTIVATE:
2855 case UNSELECT_BY_FILTER_ACTIVATE:
2856 case SELECT_BY_FILTER_ACTIVATE:
2857 case BOOKMARK_TOGGLED:
2858 case ASCENDING_ACTIVATE:
2859 case DESCENDING_ACTIVATE:
2860 case BOOKMARK_ADD_ACTIVATE:
2861 case BOOKMARK_REMOVE_ACTIVATE:
2862 case LS_ACTIVATE:
2863 if (!is_valid_view_entry(widgets_p, menu_enum)) break;
2864 valid = TRUE; break;
2865 // toggles:
2866 case HIDDEN_TOGGLED:
2867 case BACKUP_TOGGLED:
2868 case PREVIEW_TOGGLED:
2869 case CASESORT_TOGGLED:
2870
2871
2872 case NAME_SORT_ACTIVATE:
2873 case TYPE_SORT_ACTIVATE:
2874 case DATE_SORT_ACTIVATE:
2875 case SIZE_SORT_ACTIVATE:
2876 case OWNER_SORT_ACTIVATE:
2877 case GROUP_SORT_ACTIVATE:
2878 case MODE_SORT_ACTIVATE:
2879 if (!is_valid_view_entry(widgets_p, menu_enum)) break;
2880 valid = TRUE; break;
2881
2882 case COMPACT_ICONSIZE_TOGGLED:
2883 case TINY_ICONSIZE_TOGGLED:
2884 case NORMAL_ICONSIZE_TOGGLED:
2885 case BIG_ICONSIZE_TOGGLED:
2886 case HUGE_ICONSIZE_TOGGLED:
2887 case PLUS_ICONSIZE_ACTIVATE:
2888 case MINUS_ICONSIZE_ACTIVATE:
2889 case DEFAULT_ICONSIZE_ACTIVATE:
2890 case DEFAULT_ICONSIZE_ALL_ACTIVATE:
2891 default:
2892 valid = TRUE;
2893 }
2894 NOOP( "***** callback: valid=%d\n", valid);
2895 if (valid) switch (menu_enum){
2896
2897 // Size callbacks:
2898 case COMPACT_ICONSIZE_TOGGLED:
2899 size(widgets_p, GINT_TO_POINTER(LIST_ICON_SIZE)); break;
2900 case TINY_ICONSIZE_TOGGLED:
2901 size(widgets_p, GINT_TO_POINTER(TINY_ICON_SIZE)); break;
2902 case NORMAL_ICONSIZE_TOGGLED:
2903 size(widgets_p, GINT_TO_POINTER(SMALL_ICON_SIZE)); break;
2904 case BIG_ICONSIZE_TOGGLED:
2905 size(widgets_p, GINT_TO_POINTER(MEDIUM_ICON_SIZE)); break;
2906 case HUGE_ICONSIZE_TOGGLED:
2907 size(widgets_p, GINT_TO_POINTER(BIG_ICON_SIZE)); break;
2908 case PLUS_ICONSIZE_ACTIVATE:
2909 increase_iconsize(widgets_p); break;
2910 case MINUS_ICONSIZE_ACTIVATE:
2911 decrease_iconsize(widgets_p); break;
2912 case DEFAULT_ICONSIZE_ACTIVATE:
2913 default_iconsize(widgets_p); break;
2914 case DEFAULT_ICONSIZE_ALL_ACTIVATE:
2915 default_iconsize_all(widgets_p); break;
2916 // Edit callbacks:
2917 case CUT_ACTIVATE: copy_cut_callback (widgets_p, TRUE); break;
2918 case COPY_ACTIVATE: copy_cut_callback (widgets_p, FALSE); break;
2919 case PASTE_ACTIVATE: paste_callback (widgets_p, FALSE); break;
2920 case REMOVE_ACTIVATE: remove_x( widgets_p); break;
2921 case DIFFERENCES_ACTIVATE: differences( widgets_p); break;
2922 case TOUCH_ACTIVATE: touch(widgets_p); break;
2923 case PROPERTIES_ACTIVATE: properties(widgets_p); break;
2924 case ACTIVATE: double_click(widgets_p); break;
2925 case RUN_ACTIVATE: run(widgets_p); break;
2926 case OPEN_WITH_ACTIVATE: open_x(widgets_p); break;
2927 case MOUNT_ACTIVATE: mount(widgets_p); break;
2928 case UNMOUNT_ACTIVATE: unmount(widgets_p); break;
2929 case AUTOTYPE_ACTIVATE: autotype(widgets_p, menuitem); break;
2930 case AUTOTYPE_R_ACTIVATE: autotype_r(widgets_p, menuitem); break;
2931
2932 case FIND_ACTIVATE:
2933 case GLOB_ACTIVATE: glob_x(widgets_p); break;
2934
2935 case BCRYPT_ACTIVATE: bcrypt( widgets_p); break;
2936 case LS_ACTIVATE: ls(widgets_p); break;
2937 case RENAME_ACTIVATE: rename_x( widgets_p); break;
2938 case DUPLICATE_ACTIVATE: duplicate( widgets_p); break;
2939 case SYMLINK_ACTIVATE: symlink_x( widgets_p); break;
2940 case DONE_WITH_RENAME:
2941 rfm_context_function(done_with_rename, widgets_p);
2942 break;
2943 // View independent callbacks
2944 case KEYBINDINGS_ACTIVATE: keybindings(widgets_p); break;
2945 case HELP_ACTIVATE: help(widgets_p); break;
2946 case ABOUT_ACTIVATE: about(widgets_p); break;
2947
2948 case HOST_ACTIVATE: host(widgets_p); break;
2949 case OPEN_IN_TERMINAL_ACTIVATE: open_in_terminal(widgets_p); break;
2950 case SETTINGS_ACTIVATE: settings(widgets_p); break;
2951 case CLOSE_ACTIVATE: close_x(widgets_p); break;
2952 case QUIT_ACTIVATE: quit(widgets_p); break;
2953 case MENU_ACTIVATE:
2954 DBG("MENU_ACTIVATE: should not reach here.\n");
2955 break;
2956
2957 /////////////////////
2958
2959 // Go Callbacks:
2960 case PLUGIN_GOTO_ACTIVATE: plugin_goto(widgets_p, menuitem); break;
2961 case LEVEL_GOTO_ACTIVATE: level_goto(widgets_p, menuitem); break;
2962 case BOOKMARK_ADD_ACTIVATE: bookmark_add(widgets_p, menuitem); break;
2963 case BOOKMARK_REMOVE_ACTIVATE: bookmark_remove(widgets_p, menuitem); break;
2964
2965 case RELOAD_ACTIVATE:
2966 case REFRESH_ACTIVATE: refresh(widgets_p); break;
2967 case GOUP_ACTIVATE: goup(widgets_p); break;
2968 case FORWARD_ACTIVATE: forward(widgets_p); break;
2969 case BACK_ACTIVATE: back(widgets_p); break;
2970 case HOME_ACTIVATE: home(widgets_p); break;
2971 case JUMP_TO_ACTIVATE: jump_to(widgets_p); break;
2972 case HIDDEN_TOGGLED: hide_unhide(widgets_p); break;
2973 case BACKUP_TOGGLED: backup_unbackup(widgets_p); break;
2974 case PREVIEW_TOGGLED: preview(widgets_p); break;
2975 case NAME_SORT_ACTIVATE: sort(widgets_p,
2976 GINT_TO_POINTER(NAME_SORT)); break;
2977 case TYPE_SORT_ACTIVATE: sort(widgets_p,
2978 GINT_TO_POINTER(TYPE_SORT)); break;
2979 case DATE_SORT_ACTIVATE: sort(widgets_p,
2980 GINT_TO_POINTER(DATE_SORT)); break;
2981 case SIZE_SORT_ACTIVATE: sort(widgets_p,
2982 GINT_TO_POINTER(SIZE_SORT)); break;
2983 case OWNER_SORT_ACTIVATE: sort(widgets_p,
2984 GINT_TO_POINTER(OWNER_SORT)); break;
2985 case GROUP_SORT_ACTIVATE: sort(widgets_p,
2986 GINT_TO_POINTER(GROUP_SORT)); break;
2987 case MODE_SORT_ACTIVATE: sort(widgets_p,
2988 GINT_TO_POINTER(MODE_SORT)); break;
2989 case NEW_WINDOW_ACTIVATE: new_window(widgets_p); break;
2990 case NEW_TAB_ACTIVATE: new_tab_f(widgets_p); break;
2991 case NEWDIR_ACTIVATE: newdir (widgets_p); break;
2992 case NEWFILE_ACTIVATE: newfile (widgets_p); break;
2993 case UNSELECT_ALL_ACTIVATE: unselect_all(widgets_p); break;
2994 case SELECT_INVERT_ACTIVATE: select_all(widgets_p, GINT_TO_POINTER(1)); break;
2995 case SELECT_ALL_ACTIVATE: select_all(widgets_p, NULL); break;
2996 case UNSELECT_BY_FILTER_ACTIVATE: select_by_filter(widgets_p, NULL); break;
2997 case SELECT_BY_FILTER_ACTIVATE: select_by_filter(widgets_p, GINT_TO_POINTER(1)); break;
2998 case BOOKMARK_TOGGLED: toggle_bookmark(widgets_p); break;
2999 case CASESORT_TOGGLED: toggle_casesort(widgets_p); break;
3000 case ASCENDING_ACTIVATE:
3001 case DESCENDING_ACTIVATE:
3002 ascending_descending(widgets_p, menu_enum); break;
3003
3004
3005 //////////////
3006 // Dummy item:
3007 case ENUM_CALLBACKS: break;
3008
3009 } // end switch.
3010
3011 //rfm_rw_lock_reader_unlock (&(view_p->mutexes.monitor_lock));
3012
3013 rfm_view_list_unlock("threaded_callback()");
3014 TRACE("** threaded_callback is done\n");
3015 return NULL;
3016 }
3017
3018
3019