1 #ifdef COPYRIGHT_INFORMATION
2 #include "gplv3.h"
3 #endif
4 /* this file is included by rodent_popup.c */
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 typedef struct keybind_t {
24     guint key;
25     guint mask;
26     gpointer callback;
27 } keybind_t;
28 
29 static gchar *auto_C_name[] = {AUTO_C_NAME};
30 
31 static int
32 set_auto_command (int j,
33                   const gchar * name,
34                   const gchar * alt_label,
35                   const gchar * app,
36                   const gchar * path
37                   );
38 
39 
40 //static void gui_add_to_keylist (guint in_key, guint mask, gpointer callback);
41 
42 
43 ////////////////////////////////////////////////////////////////////////////////////////
44 //           rodent_do_popup   guts (callback function)
45 ////////////////////////////////////////////////////////////////////////////////////////
46 
47 static void
popup_autostuff(record_entry_t * en)48 popup_autostuff (record_entry_t * en) {
49     if (!en) return;
50     gint j = 0;
51 
52     NOOP(stderr, "...popup_autostuff\n");
53 
54 
55     // Special "open in new window" item for partition types
56     // FIXME
57     // XXX: This should probably be done by the fstab module, not here.
58     if(FSTAB_is_partition_type (en)) {
59         NOOP(stderr, "test FSTAB_is_partition_type (en)...\n");
60         // only first item (open in new window...)
61         gchar *mount_point = FSTAB_get_mnt_dir (en->path);
62         if(mount_point) {
63             j = set_auto_command ( j, auto_C_name[j],
64             _("Open in New Window"), "rodent-fm", mount_point);
65             g_free (mount_point);
66         }
67     }
68     // Special run command for dot desktop files.
69     // XXX: as above, this should probably be done by the module...
70     else if(IS_LOCAL_TYPE(en->type) &&
71 	    en->mimetype && strcmp(en->mimetype, "application/x-desktop")==0  ) {
72 	if (rfm_void(PLUGIN_DIR, "dotdesktop", "module_active")){
73 	    // get the Icon
74 	    const gchar *Icon=rfm_natural(PLUGIN_DIR, "dotdesktop", (void *)en, "item_icon_id");
75 	    // get the Name
76 	    gchar *Name=rfm_natural(PLUGIN_DIR, "dotdesktop", en->path, "item_name");
77 	    GtkWidget *a =
78 		rfm_get_widget ("autotype_Prun");
79 	    if (Name) {
80 
81 		GtkWidget *a;
82 		a =	rfm_get_widget ("autotype_Prun");
83 		gchar *q = rfm_utf_string (Name);
84                 rfm_replace_menu_label(a, q);
85 		/*label = gtk_bin_get_child (GTK_BIN (a));
86 		gtk_label_set_text ((GtkLabel *) label, q);*/
87 		g_free (q);
88 		g_object_set_data(G_OBJECT(a), "record_entry", (void *)en);
89 	    }
90 	    if (Icon) {
91                 rfm_replace_menu_image(a, Icon);
92 	    }
93 	    if (Icon && Name){
94 		SHOW_IT ( "autotype_Prun");
95 	    }
96 	    g_free (Name);
97 	}
98     }
99     // Executable files get the special "run in terminal" menu item:
100     else if(IS_EXE_TYPE(en->type)) {
101 	if (IS_SDIR(en->type)) {
102 	    // ignore
103 	} else {
104 	    gchar *cmd;
105 
106 	    GtkWidget  *a = rfm_get_widget ("autotype_Prun");
107 	    g_object_set_data(G_OBJECT(a), "record_entry", (void *)en);
108 	    cmd = g_strdup_printf ("%s (%s)", _("Run in terminal window"), _("Is executable"));
109 	    gchar *q = rfm_utf_string (cmd);
110             rfm_replace_menu_label(a, q);
111 	    g_free (cmd);
112 	    g_free (q);
113 
114             rfm_replace_menu_image(a, "xffm/emblem_terminal");
115 	    SHOW_IT ( "autotype_Prun");
116 	}
117     }
118 
119 
120     // Mimetype associations.
121     // These mimetype associations are defined in the file
122     // "applications-module.xml" and harvested from
123     // installed dot desktop files by the dotdesktop module.
124     //
125     // Associations should be done to the basic mimetype
126     // (not any alias) for sanity sake.
127     //
128     // This is the nitty gritty.
129     // Suggest an application based on the file's mimetype.
130     //
131     NOOP(stderr, "AUTO: menu nitty-gritty now\n");
132     gchar *magic_type = NULL;
133     gchar *mime_type = NULL;
134     if (IS_LOCAL_TYPE(en->type) && 1) {
135 	magic_type = rfm_rational(RFM_MODULE_DIR, "mime", (void *)en, "mime_magic", "mime_function");
136 	if (!en->mimemagic) magic_type = g_strdup(_("unknown"));
137     }
138     else magic_type = g_strdup(_("unknown"));
139     // G_FILE_TEST_EXISTS is a downer on remote connections
140     if (g_path_is_absolute(en->path)) {
141 	mime_type = MIME_type (en->path, en->st);
142     }
143 
144     // These are the menu items set from dotdesktop files
145     // and "applications-module.xml"
146 
147     if(g_path_is_absolute(en->path)) {
148         int k;
149         NOOP(stderr, "AUTO: menu nitty-gritty mime-type=%s magic-type=%s\n", mime_type, magic_type);
150 
151         // here we use the freedesktop and magic
152         // mimetype to get the run program.
153         // We loop to get commands based on simple mimetype and magic mimetype,
154         // in that order.
155         for(k = 0; k < 2; k++) {
156             gchar **apps = NULL;
157             int i = 0;
158             if(k == 0) {
159                 apps = MIME_apps (mime_type);
160                 NOOP(stderr, "AUTO: menu nitty-gritty (%s) apps=0x%lx\n", mime_type, (long)apps);
161             } else {
162                 apps = MIME_apps (magic_type);
163                 NOOP(stderr, "AUTO: menu nitty-gritty (%s) apps=0x%lx\n", magic_type, (long)apps);
164             }
165 
166             if(apps && apps[i])
167                 for(; apps && apps[i]; i++) {
168                     NOOP ("AUTO: j=%d, i=%d %s -> %s\n", j, i, auto_C_name[j], apps[i]);fflush(NULL);
169 
170                     if(!auto_C_name[j]) {
171                         // no menuitem spaces left.
172                         continue;
173                     }
174 		    if (!strlen(apps[i])) {
175                         // bug trap, just in case an empty string slips past.
176                         continue;
177                     }
178                     j = set_auto_command ( j, auto_C_name[j], NULL,
179                                           // the command:
180                                           apps[i], en->path);
181                 }
182             g_strfreev (apps);
183         }
184 
185     }
186 
187     NOOP(stderr, "AUTO: editor test...\n");
188     gboolean has_editor=FALSE;
189     gint k;
190     gchar **apps = MIME_apps (mime_type);
191     for (k=0; k<j && apps && apps[k]; k++){
192         const gchar **editors = rfm_get_editors();
193 	for (; editors && *editors; editors++){
194 	    if (strstr(apps[k], *editors)) {
195 		has_editor=TRUE;
196 		break;
197 	    }
198 	    if (has_editor) break;
199 	}
200     }
201     g_strfreev (apps);
202     if (!has_editor){
203 	// Default editor command.
204 	gchar *text_editor = rodent_get_text_editor(en);
205 	TRACE( "Got text editor: %s\n", text_editor);
206 	if (text_editor){
207 	    j = set_auto_command ( j,
208 		    auto_C_name[j], NULL,
209 		    // the command:
210 		     text_editor, en->path);
211 		g_free(text_editor);
212 	}
213     }
214 
215 
216     if(g_path_is_absolute(en->path)) {
217         SHOW_IT ( "open_with_menuitem");
218         SHOW_IT ( "open_with_separator");
219     }
220     NOOP(stderr, "AUTO: done!\n");
221 
222     g_free (magic_type);
223     g_free (mime_type);
224     return;
225 }
226 
227 
228 ////////////////////////////////////////////////////////////////////////////////////////
229 
230 /**************************************************************************/
231 /**************************  pasteboard stuff  ****************************/
232 /**************************************************************************/
233 
234 /*  */
235 
236 /**************************************************************************/
237 
238 ///// popup callbacks....
239 
240 /* this file is included by rodent_popup.c */
241 
242 
243 static void
setup_bookmark_menuitem(record_entry_t * en,const gchar * menuitem,gboolean on)244 setup_bookmark_menuitem(record_entry_t *en,
245     const gchar *menuitem,
246     gboolean on){
247     GtkWidget *w=rfm_get_widget( menuitem);
248     if (!w) {
249 	DBG("no %s widget!\n", menuitem);
250 	return;
251     }
252 
253     gchar *basename=g_path_get_basename(en->path);
254     gchar *baseutf=rfm_utf_string (basename);
255     g_free(basename);
256     gchar *text=g_strdup_printf("%s: <b><i>%s</i></b>",
257 	   (on)?_("Add bookmark"):_("Remove bookmark"),
258 	   baseutf);
259     g_free(baseutf);
260     NOOP(stderr, "...setup_bookmark_menuitem\n");
261     gchar *q = rfm_utf_string (text);
262     g_free (text);
263     rfm_replace_menu_label(w, q);
264 
265     /*GtkWidget *label = gtk_bin_get_child (GTK_BIN (w));
266     gtk_label_set_markup ((GtkLabel *) label, q);*/
267     g_free (q);
268 
269     SHOW_IT (menuitem);
270     gchar *path = g_object_get_data(G_OBJECT(w), "path");
271     g_free(path);
272     g_object_set_data(G_OBJECT(w), "path",   g_strdup(en->path));
273     NOOP("setting path to %s\n", en->path);
274     //FIXME:
275 #if 0
276     // I don't like this way of determine expose region.
277     // Should do this in the callback, finding the appropriate
278     // population_p from path information.
279     if (population_p) {
280 	GdkRectangle *rect=g_object_get_data(G_OBJECT(w), "rect");
281 	if (!rect) rect=(GdkRectangle *)malloc(sizeof(GdkRectangle));
282 	if (rfm_get_population_icon_rect(view_p, population_p, rect)) {
283 	    g_object_set_data(G_OBJECT(w), "rect",   rect);
284 	} else {
285 	    g_object_set_data(G_OBJECT(w), "rect",   NULL);
286 	}
287     } else {
288 	g_object_set_data(G_OBJECT(w), "rect",   NULL);
289     }
290 #endif
291 
292 }
293 
294 
295 
296 /////////////////////////////////////////////77
297 //////  rodent_menu
298 
299 /*************************** specific commands to menu ***************/
300 
301 /****************** gtk functions for callbacks *********************/
302 // show_mount: shows the menu mount item if fstab module available
303 static void
show_mount_item(view_t * view_p)304 show_mount_item (view_t *view_p) {
305     if(rfm_void (PLUGIN_DIR, "fstab", "is_root_module") == NULL) return;
306     if(g_slist_length (view_p->selection_list) != 1) return;
307     record_entry_t *en = view_p->selection_list->data;
308     if (!en || !en->path) return;
309 
310     gint mounted = FALSE;
311     gboolean in_fstab = FALSE;
312     gboolean partition = FSTAB_is_partition_type (en);
313     if(partition || IS_SDIR(en->type)) {
314         mounted = FSTAB_entry_is_mounted (en);
315         in_fstab = FSTAB_is_in_fstab (en->path);
316     }
317     gboolean isofs =
318 	(en->mimetype &&
319 	 strstr(en->mimetype, "application/x-cd-image")) ||
320 	(en->mimemagic &&
321 	 strstr(en->mimemagic, "application/x-cd-image"));
322     // This does not good. Mount volume will be /dev/loopX
323     if (isofs) {
324         mounted = FSTAB_entry_is_mounted (en);
325     }
326 
327 
328     NOOP ("POPUPx  %s is mounted=%d\n", en->path, mounted);
329     gboolean do_mount_item = mounted || in_fstab || partition || isofs;
330     if(do_mount_item) {
331         if(mounted>0){ SHOW_IT ( "unmountP");}
332 	else if (mounted < 0){ SHOW_IT ( "mount_broken");}
333 	else { SHOW_IT ( "mountP");}
334     }
335 }
336 
337 static void
show_remove_item(view_t * view_p)338 show_remove_item (view_t *view_p) {
339     record_entry_t *en = view_p->selection_list->data;
340     if(!en || !en->path) return;
341     if(IS_UP_TYPE(en->type))return;
342     /* for local remove: */
343     if(g_path_is_absolute(en->path)) SHOW_IT ( "remove_menuitem");
344 }
345 
346 static void
show_properties_item(view_t * view_p)347 show_properties_item (view_t *view_p) {
348     if (!rfm_void(RFM_MODULE_DIR, "properties", "module_active")) return;
349     record_entry_t *en = view_p->selection_list->data;
350     if(!en || !en->path) return;
351     if (!g_path_is_absolute (en->path)) return;
352     SHOW_IT ( "properties_menuitem");
353     return;
354 }
355 
356 
357 static void
recursive_dirname(widgets_t * widgets_p,char * path,int level)358 recursive_dirname (widgets_t * widgets_p, char *path, int level) {
359     if(!path || strcmp (path, "/") == 0)
360         return;
361     if(level >= DEEPEST_DIR_MENU_LEVELS)
362         return;
363     gchar *b = g_path_get_dirname (path);
364     gchar *name = g_strdup_printf ("level-%d", level);
365 
366     GtkWidget *a = rfm_get_widget (name);
367     NOOP(stderr, "...recursive_dirname\n");
368     gchar *q = rfm_utf_string (b);
369     rfm_replace_menu_label(a, q);
370     /*GtkWidget *label = gtk_bin_get_child (GTK_BIN (a));
371     gtk_label_set_text ((GtkLabel *) label, q);*/
372     g_free (q);
373     gchar *old_b;
374     if((old_b = g_object_get_data (G_OBJECT (a), "path")) != NULL) {
375         g_object_set_data (G_OBJECT (a), "path", NULL);
376         g_free (old_b);
377     }
378     g_object_set_data (G_OBJECT (a), "path", (gpointer) b);
379     SHOW_IT ( name);
380 
381     recursive_dirname (widgets_p, b, level + 1);
382     g_free (name);
383     return;
384 }
385 
386 #define MENU_IN_MODULE(x) (view_p->module && rfm_void(PLUGIN_DIR,view_p->module,(x)))
387 
388 static void
show_open_items(view_t * view_p)389 show_open_items (view_t *view_p) {
390     record_entry_t *en = view_p->selection_list->data;
391     if(IS_UP_TYPE(en->type))return;
392 
393     // file_menu is already shown by here...
394     SHOW_IT("select_menu");
395     SHOW_IT("open_with_menuitem");
396     SHOW_IT("copy_menuitem");
397     SHOW_IT("cut_menuitem");
398     HIDE_IT ("newfile_menuitem");
399     HIDE_IT ("newdirectory_menuitem");
400 
401     if (en->mimetype &&
402 	    rfm_void(PLUGIN_DIR, "dotdesktop", "module_active") &&
403 	    strcmp(en->mimetype, "application/x-desktop")==0 )
404     {
405 	NOOP ("showing autotype_Prun\n");
406         SHOW_IT ( "autotype_Prun");
407     }
408 
409 
410     return;
411 }
412 
413 
414 ////////////////////////////////////////////////
415 ////   menu.i
416 
417 
418 static void
clean_object_data(GtkWidget * a,const gchar * data_id)419 clean_object_data(GtkWidget *a, const gchar *data_id)
420 {
421     gchar *old_text = g_object_get_data (G_OBJECT (a), data_id);
422     if((old_text = g_object_get_data (G_OBJECT (a), data_id)) != NULL) {
423         g_object_set_data (G_OBJECT (a), data_id, NULL);
424         g_free (old_text);
425     }
426 }
427 
428 static int
set_auto_command(int j,const gchar * name,const gchar * alt_label,const gchar * app,const gchar * path)429 set_auto_command (int j,
430                   const gchar * name,
431                   const gchar * alt_label,
432                   const gchar * app,
433                   const gchar * path
434                   ) {
435     widgets_t *widgets_p = rfm_get_widget ("widgets_p");
436     int jj;
437 
438     gchar *dirname = g_path_get_dirname (path);
439     gchar *basename = g_path_get_basename (path);
440 
441     GtkWidget *a = rfm_get_widget (name);
442 
443     const gchar * output_ext=MIME_command_output_ext(app);
444     view_t *view_p=widgets_p->view_p;
445     if(!MIME_is_valid_command (app)) {
446         if (strcmp(app, "rodent-newtab")==0 && view_p->tab_constructor) {
447             NOOP (">> set_auto_command: %s name=%s\n", app, name);
448         }
449         else if (strcmp(app, "rodent-newwin")==0) {
450             NOOP (">> set_auto_command: %s name=%s\n", app, name);
451         }
452         else if (strcmp(app, "rodent-bcrypt")==0) {
453             NOOP (">> set_auto_command: %s name=%s\n", app, name);
454         }
455         else {
456             return j;
457         }
458     }
459 
460     gchar *command;
461     if(strncmp (app, "sudo -A ", strlen ("sudo -A ")) == 0) {
462         if(getuid () == 0)
463             return j;           /* don't sudoize root */
464         if(!strlen (app + strlen ("sudo -A "))
465            || !MIME_is_valid_command (app + strlen ("sudo -A ")))
466             return j;
467     }
468 
469     TRACE( "looking for command icon \"%s\"\n",app);
470     gchar *app_no_args = g_strdup(app);
471     if (strchr(app_no_args, ' ')) *strchr(app_no_args, ' ')=0;
472     const gchar *icon_id=(const gchar *)
473 	rfm_natural(PLUGIN_DIR, "dotdesktop", (void *)app_no_args, "get_exec_icon");
474 
475     // try custom mime icon
476     if (!icon_id){
477 	icon_id=MIME_command_icon (app_no_args);
478 	NOOP("icon id= %s, %s\n", icon_id, app_no_args);
479     }
480 
481     // try named icon
482     gchar *icon=NULL;
483     if (!icon_id) {
484 	NOOP(stderr, "try named icon for %s\n", app_no_args);
485 	GdkPixbuf *pix = rfm_get_pixbuf (app_no_args, SMALL_ICON_SIZE); //refs
486 
487 	// This should always be local and absolute.
488 	if (pix){
489 	    icon_id = icon;
490             g_object_unref(pix);
491 	}
492     }
493     g_free(app_no_args);
494 
495     if (!icon_id) {
496         NOOP("2. command icon \"%s\" not found!\n",app);
497         icon_id="xffm/stock_execute";
498     }
499 
500     if (icon_id) {
501         rfm_replace_menu_image(a, icon_id);
502     }
503     g_free(icon);
504 
505 
506     gchar *effective_app = NULL;
507 
508     NOOP(stderr, "...set_auto_command\n");
509     //label = gtk_bin_get_child (GTK_BIN (a));
510     if(alt_label) {
511         gchar *new_label = rfm_utf_string (alt_label);
512         rfm_replace_menu_label(a, new_label);
513         g_free(new_label);
514     } else {
515         /* allow mixed utf8-eucjp  paths */
516         gchar *new_label;
517         {
518             const gchar *text = MIME_command_text (app);
519             if (!text && !strstr(app, " %s")){
520                 // If app does not end with a %s, try with %s
521                 effective_app = g_strdup_printf("%s %%s", app);
522                 text = MIME_command_text (effective_app);
523                 if (text) app = effective_app;
524             } else if (!text && *(strstr(app, " %s")+strlen(" %s"))==0){
525                 // If app does end with a %s, try without it.
526                 effective_app = g_strdup(app);
527                 if (strstr(effective_app, " %s")) *strstr(effective_app, " %s") = 0;
528                 text = MIME_command_text (effective_app);
529                 if (text) app = effective_app;
530             }
531 	    const gchar *text2 = MIME_command_text2 (app);
532             TRACE( "set_auto_command(): looking for %s in hash: %s %s\n",app, text, text2);
533             gchar *q;
534             if (text) {
535 		gchar *texto;
536 		if (text2){
537 		    texto=g_strconcat(_(text), _(text2), NULL);
538 		} else {
539 		    texto=g_strdup(_(text));
540 		}
541                 NOOP("MIME: found\n");
542                 if (strstr(texto,"%s")!=NULL) {
543                     q = MIME_mk_command_line (texto, basename);
544                 } else {
545                     if (output_ext)
546                         q = g_strdup_printf("%s (%s)", texto, output_ext);
547                     else
548                         q = g_strdup(texto);
549                 }
550 		g_free(texto);
551             }
552             else {
553                 NOOP("MIME: not found\n");
554                 q = MIME_mk_command_line (app, basename);
555             }
556             new_label = rfm_utf_string (q);
557             g_free (q);
558         }
559         rfm_replace_menu_label(a, new_label);
560         //gtk_label_set_text ((GtkLabel *) label, new_label);
561         g_free (new_label);
562     }
563 
564     if(output_ext) {
565         NOOP ("command is:  %s output_ext is; %s\n", app, output_ext);
566         command = g_strdup (app);
567     } else {
568         /* this is to use relative paths for arguments for all
569          * commands except those where the output directory (or
570          * widgets_p->workdir) is requested from the user.
571          * */
572         NOOP ("making command from (%s, %s)\n", app, path);
573         command = MIME_mk_command_line (app, path);
574     }
575 
576     /* check for duplicates */
577     {
578         gint argcp1;
579         gchar **argvp1;
580         GError *error = NULL;
581         if(!g_shell_parse_argv ((const gchar *)command, &argcp1, &argvp1, &error)) {
582             g_free (command);
583             g_error_free (error);
584             g_strfreev (argvp1);
585             NOOP ("!g_shell_parse_argv at popup_autostuff\n");
586             return j;
587         }
588         for(jj = 0; jj < j; jj++) {
589             gboolean is_duplicate = TRUE;
590             gint ac,
591               argcp2;
592             gchar **argvp2;
593             gchar *set_command = g_object_get_data (G_OBJECT (rfm_get_widget (auto_C_name[jj])),
594                                                     "command");
595             NOOP ("AUTO: j=%d: %s == %s\n", jj, set_command, command);
596             if(!g_shell_parse_argv ((const gchar *)set_command, &argcp2, &argvp2, &error)) {
597                 g_free (basename);
598                 g_free (command);
599                 g_error_free (error);
600                 g_strfreev (argvp2);
601                 NOOP ("!g_shell_parse_argv at popup_autostuff\n");
602                 return j;
603             }
604             if(argcp2 != argcp1) {
605                 is_duplicate = FALSE;
606             } else
607                 for(ac = 0; ac < argcp2; ac++) {
608                     if(strcmp (argvp2[ac], argvp1[ac])) {
609                         is_duplicate = FALSE;
610                         break;
611                     }
612                 }
613             NOOP ("0x%lx, 0x%lx\n", (unsigned long)argvp1, (unsigned long)argvp2);
614 
615             g_strfreev (argvp2);
616             argvp2 = NULL;
617             /*if (strcmp(set_command,command)==0) */
618             if(is_duplicate) {
619                 g_free (basename);
620                 g_free (command);
621                 NOOP ("AUTO: is_duplicate at popup_autostuff\n");
622                 return j;
623             }
624         }                       /* end for */
625         g_strfreev (argvp1);
626         argvp1 = NULL;
627     }
628     /* OK, by now we know the command is not duplicated... */
629     // But is it a valid command??
630 
631 
632     /* now let's free up any left over data from previous
633      * generated menus... */
634     clean_object_data(a, "command");
635     clean_object_data(a, "workdir");
636     g_object_set_data (G_OBJECT (a), "command", (gpointer) command);
637     g_object_set_data (G_OBJECT (a), "workdir", (gpointer) dirname);
638     if(MIME_command_output (app)) {
639         g_object_set_data (G_OBJECT (a), "querypath", (gpointer)_("Specify Output Directory..."));
640     } else {
641         g_object_set_data (G_OBJECT (a), "querypath", NULL);
642     }
643 
644     if(output_ext) {
645         g_object_set_data (G_OBJECT (a), "output_arg", g_strdup (path));
646     } else {
647         clean_object_data(a, "output_arg");
648         g_object_set_data (G_OBJECT (a), "output_arg", NULL);
649     }
650     NOOP(stderr, "AUTO:command=%s, output_arg=%s\n", command, path);
651     g_object_set_data (G_OBJECT (a), "output_ext", (gpointer) output_ext);
652     NOOP ("AUTO:now showing %s, active widget=0x%lx\n", name, (unsigned long)widgets_p->paper);
653     SHOW_IT ( name);
654     j++;
655     g_free (basename);
656     g_free (effective_app);
657     return j;
658 }
659 
660 
661 
662 
663