1 /*
2  * Copyright (C) 2002-2012 Edscott Wilson Garcia
3  * EMail: edscott@users.sf.net
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program;
18  */
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22 
23 #include "rodent.h"
24 #include "rfm_modules.h"
25 #include "rodent_popup.i"
26 
27 void
rodent_update_menu(GtkWidget * menu)28 rodent_update_menu(GtkWidget *menu){
29     if (!menu || !GTK_IS_CONTAINER(menu)) return;
30     // First, hide everything in menu.
31 #if GTK_MAJOR_VERSION==2 && GTK_MINOR_VERSION<24
32     // This is deprecated as of 2.24, which forces us
33     // to get children and hide each one of them... bleah!
34     gtk_widget_hide_all (menu);
35 #else
36     GList *children = gtk_container_get_children(GTK_CONTAINER(menu));
37     GList *tmp=children;
38     for (; tmp && tmp->data; tmp = tmp->next){
39 	if(GTK_IS_WIDGET(tmp->data)) gtk_widget_hide (GTK_WIDGET(tmp->data));
40     }
41     g_list_free(children);
42 #endif
43     widgets_t *widgets_p = rfm_get_widget ("widgets_p");
44     view_t *view_p = widgets_p->view_p;
45 
46     // Show the file menu
47     SHOW_IT("file_menu");
48     // hide items in file menu
49     HIDE_IT("rename_menuitem");
50     HIDE_IT("duplicate_menuitem");
51     HIDE_IT("symlink_menuitem");
52     HIDE_IT("touch_menuitem");
53     HIDE_IT("properties_menuitem");
54 
55     // Show search item if we have fgr
56     gchar *fgr = g_find_program_in_path("rodent-fgr");
57     if (fgr) SHOW_IT ( "find2");
58     g_free(fgr);
59 
60     // Next, show other items on a need to see basis.
61     //
62     // First test, do we have a valid associated population_p?
63     gint items=g_slist_length(view_p->selection_list);
64     if (items == 1){
65         // Yes, we do. So we show the cp/mv/ln items.
66 	SHOW_IT("rename_menuitem");
67 	SHOW_IT("duplicate_menuitem");
68 	SHOW_IT("symlink_menuitem");
69     }
70     if (items && view_p->selection_list->data ) {
71 	HIDE_IT ( "addbookmark_menuitem");
72 	HIDE_IT ( "removebookmark_menuitem");
73 	show_remove_item(view_p);
74 	show_open_items(view_p);
75 	show_properties_item(view_p);
76 	if (items==1) {
77             // Mimetype specific items are shown here:
78 	    popup_autostuff (view_p->selection_list->data);
79 
80             // Does the item need the mount/umount item?
81             // This will only be effective if fstab plugin is loadable.
82 	    show_mount_item(view_p);
83 
84 	    record_entry_t *en = view_p->selection_list->data;
85 	    if (IS_SDIR(en->type)){
86 		gboolean on = rodent_path_is_bookmarkable(en->path);
87 		if (on) setup_bookmark_menuitem( en, "addbookmark_menuitem", on);
88 		else setup_bookmark_menuitem( en, "removebookmark_menuitem", on);
89 	    }
90 	}
91 	if(view_p->module) {
92 	    rfm_rational (PLUGIN_DIR, view_p->module, widgets_p,
93 		    view_p->selection_list->data, "hide_local_menu_items");
94 	    rfm_rational (PLUGIN_DIR, view_p->module, widgets_p,
95 		    view_p->selection_list->data, "show_local_menu_items");
96 	}
97 	SHOW_IT ("touch_menuitem");
98     }
99     else {
100 	//rodent_reset_menu_toggles ();// this is now after popup is mapped
101         rodent_reset_menu ();
102     }
103 
104 }
105 
106 void
rodent_pop_menu(const gchar * menu_id,GdkEventButton * event)107 rodent_pop_menu (const gchar *menu_id, GdkEventButton * event) {
108     gboolean is_thread = (g_thread_self() != rfm_get_gtk_thread());
109     if (is_thread){
110 	g_error("rodent_pop_menu: fixme, this is broken when called from a thread\n");
111 	return;
112     }
113     widgets_t *widgets_p = rfm_get_widget ("widgets_p");
114     view_t *view_p = widgets_p->view_p;
115 
116     if(view_p->module && !(event->state & GDK_CONTROL_MASK)){
117 	if (rfm_rational (PLUGIN_DIR, view_p->module,
118 		    widgets_p, NULL,
119 		"private_popup")) return ;
120     }
121 
122     GtkMenu *menu = rfm_get_widget(menu_id);
123     if (!menu){
124 	DBG("Menu not ready: be patient\n");
125 	return;
126     }
127 #if 10
128     // hide/show items depending on context:
129     rodent_update_menu(GTK_WIDGET(menu));
130 #endif
131     // pop it:
132     NOOP(stderr, "gtk_menu_popup \"%s\" now...\n", menu_id);
133 #if GTK_MAJOR_VERSION<3
134     //gtk_menu_popup (menu, rfm_get_widget("main_popup_menu_menu"), NULL, NULL, NULL, 3, event->time);
135     gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 3, event->time);
136 #else
137     GdkDeviceManager *gdm =
138 	    gdk_display_get_device_manager (gdk_display_get_default());
139     gtk_menu_popup_for_device (menu,
140 	    gdk_device_manager_get_client_pointer(gdm), // GdkDevice *device,
141 	    NULL, NULL, NULL, NULL,
142 	    NULL,  //GDestroyNotify destroy,
143 	    3, event->time);
144 #endif
145 
146 #if 10
147     // Finally, set toggles to correct setting (with popup mapped).
148     if (!g_slist_length(view_p->selection_list) || !view_p->selection_list->data ) {
149         rodent_reset_menu_toggles ();
150     }
151 #endif
152 
153 
154     NOOP(stderr, "menu popped \"%s\" now...\n", menu_id);
155     return ;
156 }
157 
158 ///////////////////////////////////////////////////////////////////////////////////
159 ///////////////////////////////////////////////////////////////////////////////////
160 void
rodent_push_view_go_history(void)161 rodent_push_view_go_history (void) {
162     widgets_t *widgets_p = rfm_get_widget ("widgets_p");
163     if (!widgets_p) return;
164     view_t *view_p = widgets_p->view_p;
165 
166     record_entry_t *history_en;
167     /*if (!view_p->en || !view_p->en->path) return; */
168     if(view_p->go_list) {
169         GList *last = g_list_last (view_p->go_list);
170         record_entry_t *last_en;
171         last_en = last->data;
172         if(!last_en && !view_p->en)
173             return;             /* NULL case */
174         if(last_en && view_p->en) {
175             if(!last_en->path && !view_p->en->path)
176                 return;
177             if(last_en->path && view_p->en->path) {
178                 if(strcmp (last_en->path, view_p->en->path) == 0)
179                     return;
180             }
181         }
182     }
183     history_en = rfm_copy_entry (view_p->en);
184     view_p->go_list = g_list_append (view_p->go_list, history_en);
185     //if (view_p->f_list){}
186 
187 
188     return;
189 }
190 ////////////////////////////////////////////////////////////
191 ////////////////////////////////////////////////////////////
192 
193 /****************/
194 
195 
196 void
rodent_reset_menu(void)197 rodent_reset_menu (void) {
198     widgets_t *widgets_p = rfm_get_widget ("widgets_p");
199     view_t * view_p = widgets_p->view_p;
200     gchar *void_items[]={"goto_menu", "sort_menu", "view_menu", "help_menu", "refresh3", "run2", "navigation_separator",  "file_separator", "exec_separator", "exit2", NULL};
201 
202     gchar **p;
203 
204     static gsize initialized = 0;
205     if (g_once_init_enter(&initialized)){
206 	// dynamically constructed texts.
207 	GtkWidget *a = rfm_get_widget ("host2");
208         rfm_replace_menu_label(a, g_get_host_name ());
209 	/*GtkWidget *label = gtk_bin_get_child (GTK_BIN (a));
210 	gtk_label_set_text ((GtkLabel *) label, g_get_host_name ());*/
211 	a = rfm_get_widget ("default_iconsize");
212 	gchar *text = g_strdup_printf("%s (%s)", _("Reset default state"), _("Single Instance"));
213         rfm_replace_menu_label(a, text);
214 /*	label = gtk_bin_get_child (GTK_BIN (a));
215 	gtk_label_set_text ((GtkLabel *) label, text);*/
216 	g_free(text);
217 
218 	a = rfm_get_widget ("default_iconsize_all");
219 	text = g_strdup_printf("%s (%s)", _("Reset default state"), _("All Instances"));
220         rfm_replace_menu_label(a, text);
221 	/*label = gtk_bin_get_child (GTK_BIN (a));
222 	gtk_label_set_text ((GtkLabel *) label, text);*/
223 	g_free(text);
224 	g_once_init_leave(&initialized, 1);
225     }
226 
227     for (p=void_items; p && *p; p++) SHOW_IT(*p);
228     if (view_p->flags.type == DESKVIEW_TYPE) HIDE_IT("newtab");
229     if(!view_p->en || !view_p->en->path) HIDE_IT ( "goup_menuitem");
230     if(!view_p->go_list) HIDE_IT ("go_back_menuitem");
231     if(!view_p->f_list) HIDE_IT("go_forward_menuitem");
232 
233     rodent_bookmark_set_menuitems(&(view_p->widgets), "bookmark");
234     gint i;
235     for(i = 0; i < DEEPEST_BOOK_MENU_LEVELS; i++) {
236 	gchar *name = g_strdup_printf ("bookmark-%d", i);
237 	GtkWidget *menuitem = rfm_get_widget(name);
238 	 if (!menuitem){
239 	     DBG("rodent_reset_menu(): widget %s not found\n", name);
240 	     g_free(name);
241 	     continue;
242 	 }
243 	 gchar *path=g_object_get_data(G_OBJECT(menuitem), "path");
244 	 if (!path) {
245 	     HIDE_IT ( name);
246 	 } else {
247 	     SHOW_IT ( name);
248 	 }
249 	 g_free(name);
250     }
251 
252     for(i = 0; i < DEEPEST_DIR_MENU_LEVELS; i++) {
253 	char *name = g_strdup_printf ("level-%d", i);
254 	HIDE_IT ( name);
255 	g_free (name);
256     }
257     /* this shows valid directories to goto */
258     recursive_dirname (&(view_p->widgets), view_p->deepest_dir, 0);
259 
260     gchar **w_name,
261      *widget_name[] = { "show_hidden_menuitem", "preview_images_menuitem", "newfile_menuitem", "newdirectory_menuitem", NULL };
262     for(w_name = widget_name; w_name && *w_name; w_name++) {
263 	if(view_p->en && view_p->en->path) {
264 	    if(view_p->module) {
265 		if(rfm_void (PLUGIN_DIR, view_p->module, *w_name))
266 		    SHOW_IT ( *w_name);
267 	    } else if(IS_SDIR(view_p->en->type)) {
268 		SHOW_IT ( *w_name);
269 	    }
270 	}
271     }
272 
273     if(view_p->flags.preferences & SORT_ASCENDING){
274 	HIDE_IT ( "ascending1");
275         // False positive.
276         // coverity[copy_paste_error : FALSE]
277 	SHOW_IT ( "descending1");
278     } else {
279 	HIDE_IT ( "descending1");
280 	SHOW_IT ( "ascending1");
281     }
282 
283     // dotdesktop_menu will not exist if dotdesktop module is not present
284     gboolean have_dotdesktop =
285 	GPOINTER_TO_INT(rfm_void(PLUGIN_DIR, "dotdesktop", "is_root_module"));
286     if (have_dotdesktop) {
287 	GtkWidget *applications_menu = rfm_get_widget("applications_menu");
288 	if (applications_menu) {
289 	    GtkWidget *popup_widget=
290 		rfm_rational(PLUGIN_DIR, "dotdesktop",widgets_p,
291 			applications_menu,
292 			"dotdesktop_nondetached_menu");
293 	    if (popup_widget) {
294 		gtk_widget_show_all(applications_menu);
295 	    }
296 	}
297     }
298 
299 
300 #if 0
301     if (view_p->flags.type == DESKVIEW_TYPE) {
302 	if (ICON_SIZE(view_p) < BIG_ICON_SIZE) {
303 	    SHOW_IT ( "plus_iconsize");
304 	}
305 	if (ICON_SIZE(view_p) >= TINY_ICON_SIZE) {
306 	    SHOW_IT ( "minus_iconsize");
307 	}
308     }
309     if (rfm_get_default_size() != ICON_SIZE_ID(view_p)){
310 	SHOW_IT ( "default_iconsize");
311     }
312 #endif
313 
314 
315 
316     if(rfm_pasteboard_status (view_p) && view_p->en && view_p->en->path
317 	    &&
318 	      IS_SDIR(view_p->en->type)
319 	    )
320     {
321         SHOW_IT ( "paste_menuitem");
322     }
323 
324     if(view_p->constructor) {
325         SHOW_IT ( "newwindow");
326 
327     }
328 
329     if(getenv ("TERMINAL_CMD") && strlen (getenv ("TERMINAL_CMD"))) {
330         gchar *term = g_find_program_in_path (getenv ("TERMINAL_CMD"));
331 	if (!term){
332 	    const gchar **p=rfm_get_terminals();
333 	    for (;p && *p; p++){
334 		term = g_find_program_in_path (*p);
335 		if (term) break;
336 	    }
337 	}
338 
339 	if (term) {
340 	    SHOW_IT ( "terminal2");
341 	    g_free(term);
342 	} else {
343 #ifdef DEBUG
344 	    const gchar *t=getenv ("TERMINAL_CMD");
345 	    DBG("Terminal command \"%s\" not found\n", t);
346 #endif
347 	}
348     }
349     gchar *fgr = g_find_program_in_path("rodent-fgr");
350     if (fgr) {
351 	SHOW_IT ( "find2");
352 	g_free(fgr);
353     }
354     gchar *rodent_diff = g_find_program_in_path("rodent-diff");
355     if (rodent_diff){
356 	SHOW_IT ( "differences2");
357 	g_free(rodent_diff);
358     }
359 
360     if(view_p->en) {
361         SHOW_IT ( "select_menu");
362         SHOW_IT ( "edit_separator");
363     }
364     if (rfm_void(RFM_MODULE_DIR, "settings", "module_active")) {
365 	SHOW_IT ( "settings2");
366     }
367     HIDE_IT ( "addbookmark_menuitem");
368     HIDE_IT ( "removebookmark_menuitem");
369     if (view_p->en && view_p->en->path && g_path_is_absolute(view_p->en->path)){
370 	gboolean on = rodent_path_is_bookmarkable(view_p->en->path);
371 	if (on){
372 	    setup_bookmark_menuitem( view_p->en, "addbookmark_menuitem", on);
373 	} else {
374 	    setup_bookmark_menuitem( view_p->en, "removebookmark_menuitem", on);
375 	}
376     }
377     GtkWidget *inner_label = rfm_get_widget ("sort_menu");
378     if(view_p->flags.preferences & SORT_ASCENDING)
379         rfm_replace_menu_image(inner_label, "xffm/stock_sort-ascending");
380     else
381         rfm_replace_menu_image(inner_label, "xffm/stock_sort-descending");
382 }
383 
384 void
rodent_reset_menu_toggles(void)385 rodent_reset_menu_toggles (void) {
386     NOOP( "***** popup now at rodent_reset_menu_toggles\n");
387     widgets_t *widgets_p = rfm_get_widget ("widgets_p");
388     view_t *view_p = widgets_p->view_p;
389     GtkCheckMenuItem *check;
390     switch (GPOINTER_TO_INT (ICON_SIZE_ID(view_p))){
391 	case LIST_ICON_SIZE:
392 	    check = rfm_get_widget ("compact_iconsize"); break;
393 	    break;
394 	case TINY_ICON_SIZE:
395 	    check = rfm_get_widget ("tiny_iconsize"); break;
396 	    break;
397 	case MEDIUM_ICON_SIZE:
398 	    check = rfm_get_widget ("big_iconsize"); break;
399 	    break;
400 	case BIG_ICON_SIZE:
401 	    check = rfm_get_widget ("huge_iconsize"); break;
402 	    break;
403 	case SMALL_ICON_SIZE:
404 	default:
405 	    check = rfm_get_widget ("normal_iconsize"); break;
406 	    break;
407     }
408     gtk_check_menu_item_set_active (check, TRUE);
409     switch (view_p->flags.sortcolumn){
410 	case NAME_SORT:
411 	    check = rfm_get_widget ("namesort"); break;
412 	case SIZE_SORT:
413 	    check = rfm_get_widget ("size6"); break;
414 	case DATE_SORT:
415 	    check = rfm_get_widget ("date6"); break;
416 	case OWNER_SORT:
417 	    check = rfm_get_widget ("owner6"); break;
418 	case GROUP_SORT:
419 	    check = rfm_get_widget ("group6"); break;
420 	case MODE_SORT:
421 	    check = rfm_get_widget ("mode6"); break;
422 	case TYPE_SORT:
423 	default:
424 	    check = rfm_get_widget ("unsorted6"); break;
425 
426     }
427     gtk_check_menu_item_set_active (check, TRUE);
428     gtk_check_menu_item_set_active ((GtkCheckMenuItem *)
429 				    rfm_get_widget ("casesort_menuitem"), view_p->flags.preferences & __CASE_INSENSITIVE);
430 
431     NOOP ("before setting __SHOW_IMAGES toggle now...%s\n", (view_p->flags.preferences & __SHOW_IMAGES) ? "ON" : "Off");
432     gtk_check_menu_item_set_active ((GtkCheckMenuItem *)
433 				    rfm_get_widget ("preview_images_menuitem"), view_p->flags.preferences & __SHOW_IMAGES);
434 
435     NOOP ("after setting __SHOW_IMAGES toggle now...%s\n", (view_p->flags.preferences & __SHOW_IMAGES) ? "ON" : "Off");
436     gtk_check_menu_item_set_active ((GtkCheckMenuItem *)
437 				    rfm_get_widget ("show_hidden_menuitem"), view_p->flags.preferences & __SHOW_HIDDEN);
438     gtk_check_menu_item_set_active ((GtkCheckMenuItem *)
439 				    rfm_get_widget ("show_backup_menuitem"), view_p->flags.preferences & __SHOWS_BACKUP);
440     NOOP ("setting __SHOW_HIDDEN toggle now...%s\n", (view_p->flags.preferences & __SHOW_HIDDEN) ? "ON" : "Off");
441     return;
442 }
443 
444 static pthread_mutex_t flags_mutex=PTHREAD_MUTEX_INITIALIZER;
445 void
rodent_recover_flags(extra_key_t * extra_key_p)446 rodent_recover_flags (extra_key_t * extra_key_p) {
447     DBHashTable *runflags;
448     GString *gs;
449     gint64 *flags;
450 
451     pthread_mutex_lock(&flags_mutex);
452     TRACE("opening %s...\n",extra_key_p->flagfile);
453     runflags = dbh_new (extra_key_p->flagfile, NULL, DBH_READ_ONLY|DBH_PARALLEL_SAFE);
454     TRACE("opened %s.\n",extra_key_p->flagfile);
455 
456     if(runflags  == NULL) {
457         NOOP ("Cannot open %s\n", extra_key_p->flagfile);
458         extra_key_p->flag1 = 0;
459         extra_key_p->flag2 = 0;
460 	pthread_mutex_unlock(&flags_mutex);
461         return;
462     }
463     dbh_set_parallel_lock_timeout(runflags, 3);
464     gs = g_string_new (extra_key_p->response);
465     sprintf ((char *)DBH_KEY (runflags), "%10u", g_string_hash (gs));
466     g_string_free (gs, TRUE);
467 
468     if (dbh_load (runflags)){
469     flags = (gint64 *)runflags->data;
470         extra_key_p->flag1 = flags[0];
471         extra_key_p->flag2 = flags[1];
472     } else {
473         extra_key_p->flag1 = extra_key_p->flag2 = 0;
474     }
475     dbh_close (runflags);
476     pthread_mutex_unlock(&flags_mutex);
477 
478     NOOP ("rodent_recover_flags(): flags recovered from dbh file for %s, flag1=%d flag2=%d\n",
479          extra_key_p->response, extra_key_p->flag1, extra_key_p->flag2);
480 }
481 
482 void
rodent_save_flags(extra_key_t * extra_key_p)483 rodent_save_flags (extra_key_t * extra_key_p) {
484     DBHashTable *runflags;
485     GString *gs;
486     gint64 *flags;
487 
488     pthread_mutex_lock(&flags_mutex);
489     TRACE("opening %s...\n",extra_key_p->flagfile);
490     runflags = dbh_new (extra_key_p->flagfile, NULL, DBH_PARALLEL_SAFE);
491     TRACE("opened %s.\n",extra_key_p->flagfile);
492 
493     if(runflags == NULL) {
494         NOOP ("Creating cache file: %s", extra_key_p->flagfile);
495 	unsigned char keylength=11;
496         gchar *directory = g_path_get_dirname(extra_key_p->flagfile);
497         if (!g_file_test(directory, G_FILE_TEST_IS_DIR)){
498             g_mkdir_with_parents(directory, 0700);
499         }
500         g_free(directory);
501         TRACE("opening %s...\n",extra_key_p->flagfile);
502 	runflags = dbh_new (extra_key_p->flagfile, &keylength, DBH_CREATE|DBH_PARALLEL_SAFE);
503         TRACE("opened %s.\n",extra_key_p->flagfile);
504         if(runflags == NULL) {
505             DBG ("Cannot create %s\n", extra_key_p->flagfile);
506 	    pthread_mutex_unlock(&flags_mutex);
507 	    return;
508         }
509     }
510     dbh_set_parallel_lock_timeout(runflags, 3);
511     gs = g_string_new (extra_key_p->response);
512     sprintf ((char *)DBH_KEY (runflags), "%10u", g_string_hash (gs));
513     g_string_free (gs, TRUE);
514     flags = (gint64 *)runflags->data;
515     flags[0] = extra_key_p->flag1;
516     flags[1] = extra_key_p->flag2;
517     dbh_set_recordsize (runflags, 2 * sizeof (gint64));
518 
519     dbh_update (runflags);
520     dbh_close (runflags);
521     pthread_mutex_unlock(&flags_mutex);
522     NOOP ("flags saved in dbh file  %s flag1=%d flag2=%d\n", extra_key_p->flagfile, extra_key_p->flag1, extra_key_p->flag2);
523 
524 }
525 
526 
527 gchar *
rodent_get_text_editor(record_entry_t * en)528 rodent_get_text_editor(record_entry_t *en){
529     if(!g_path_is_absolute(en->path)) {
530 	return NULL;
531     }
532     gchar **text_editors = NULL;
533     // Default editor command.
534     // We magic the file because the freedesktop standard
535     // is borked and changes text/ for application/ on a
536     // number of files. Precisely what should not be done.
537     //
538     if (!en->mimetype) en->mimetype = MIME_type (en->path, en->st);
539     if(!en->mimetype || strcmp(en->mimetype, _("unknown"))==0) {
540 	if (IS_LOCAL_TYPE(en->type) && !en->mimemagic){
541 	    en->mimemagic = rfm_rational(RFM_MODULE_DIR, "mime", en, "mime_magic", "mime_function");
542 	    if (!en->mimemagic) en->mimemagic = g_strdup(_("unknown"));
543 	} else en->mimemagic = g_strdup(_("unknown"));
544     }
545     if(en->mimemagic && strstr (en->mimemagic, "text/")){
546 	    text_editors = MIME_apps ("text/plain");
547     } else if(en->mimetype && strstr (en->mimetype, "text/")){
548 	    text_editors = MIME_apps ("text/plain");
549     }
550 
551     // Even magic mimetype may miss the mark. Take care of that here...
552     if(!en->filetype) {
553 	if (IS_LOCAL_TYPE(en->type)) {
554 	    en->filetype = rfm_rational(RFM_MODULE_DIR, "mime", en, "mime_file", "mime_function");
555 	    if (!en->filetype) en->filetype = g_strdup(_("unknown"));
556 	}
557 	else en->filetype = g_strdup(_("unknown"));
558     }
559     if(!text_editors) {
560 	if(en->filetype && strstr (en->filetype, "text"))
561 	    text_editors = MIME_apps ("text/plain");
562     }
563 
564     if(!text_editors) {
565 	return NULL;
566     }
567     g_strfreev(text_editors);
568     /* OK to apply an editor. We will use the default editor */
569     gchar *basename=NULL;
570     if(getenv ("EDITOR") && strlen (getenv ("EDITOR"))) {
571 	basename=g_strdup(getenv ("EDITOR"));
572     }
573     return (basename);
574 }
575 
576 
577