mirror of
https://github.com/MidnightCommander/mc
synced 2024-12-23 21:06:52 +03:00
0a1238fe83
* gdesktop.c, gdnd.c, gaction.c, gicon.c, gnome-file-property-dialog.c, gpopup.c, gpopup2.c, gprefs.cgmain.h, setup.c: Add option of using GNOME "magic" routines to determine file types. This makes MC intelligently look at the data in the file to see what type of file it is, rather than looking at the filename extension. This slows down MC quite a bit, so it has been made an optional preference item. Type detection is expected to improve as mime-magic matures.
352 lines
8.2 KiB
C
352 lines
8.2 KiB
C
#include <config.h>
|
|
#include <string.h>
|
|
#include "x.h"
|
|
#include "global.h"
|
|
#include "dir.h"
|
|
#include "command.h"
|
|
#include "panel.h"
|
|
#define WANT_WIDGETS /* bleah */
|
|
#include "main.h"
|
|
#include "color.h"
|
|
#include "mouse.h"
|
|
#include "layout.h" /* get_panel_widget */
|
|
#include "ext.h" /* regex_command */
|
|
#include "cmd.h" /* copy_cmd, ren_cmd, delete_cmd, ... */
|
|
#include "gscreen.h"
|
|
#include "gmain.h"
|
|
#include "dir.h"
|
|
#include "dialog.h"
|
|
#include "view.h"
|
|
#include "gcmd.h"
|
|
#include "../vfs/vfs.h"
|
|
#include "gnome-open-dialog.h"
|
|
|
|
static void
|
|
gmc_unable_to_execute_dlg (gchar *fname, const gchar *command, gchar *action, const gchar *mime)
|
|
{
|
|
GtkWidget *msg_dialog = NULL;
|
|
GtkWidget *hack_widget;
|
|
gchar *msg;
|
|
gchar *fix = NULL;
|
|
if (!strcmp (action, "x-gnome-app-info")) {
|
|
msg = g_strdup_printf (
|
|
_("Unable to execute\n\"%s\".\n\n"
|
|
"Please check it to see if it points to a valid command."),
|
|
fname);
|
|
|
|
} else {
|
|
if (mime)
|
|
fix = g_strdup_printf (
|
|
_("\".\n\nTo fix this, bring up the mime-properties editor "
|
|
"in the GNOME Control Center, and edit the default %s"
|
|
"-action for \"%s\"."),
|
|
action, mime);
|
|
else
|
|
fix = g_strdup_printf (
|
|
_("\".\n\nTo fix this error, bring up this file's properties "
|
|
"and change the default %s-action."),
|
|
action);
|
|
|
|
msg = g_strdup_printf (
|
|
_("Unable to %s\n\"%s\"\nwith the command:\n\"%s\"%s"),
|
|
action, fname, command, fix);
|
|
|
|
g_free (fix);
|
|
}
|
|
msg_dialog = gnome_message_box_new (msg,
|
|
GNOME_MESSAGE_BOX_ERROR,
|
|
GNOME_STOCK_BUTTON_OK,
|
|
NULL);
|
|
/* Kids, don't try this at home */
|
|
/* this is pretty evil... <-: */
|
|
hack_widget = GNOME_DIALOG (msg_dialog)->vbox;
|
|
hack_widget = ((GtkBoxChild *) GTK_BOX (hack_widget)->children->data)->widget;
|
|
hack_widget = ((GtkBoxChild *) GTK_BOX (hack_widget)->children->next->data)->widget;
|
|
gtk_label_set_line_wrap (GTK_LABEL (hack_widget), TRUE);
|
|
|
|
gnome_dialog_run_and_close (GNOME_DIALOG (msg_dialog));
|
|
g_free (msg);
|
|
}
|
|
|
|
static void
|
|
gmc_execute (const char *fname, const char *buf, int needs_terminal)
|
|
{
|
|
exec_extension (fname, buf, NULL, NULL, 0, needs_terminal);
|
|
}
|
|
|
|
static gboolean
|
|
gmc_check_exec_string (const char *buf)
|
|
{
|
|
gint argc;
|
|
gint retval, i;
|
|
gchar *prog;
|
|
gchar **argv;
|
|
|
|
gnome_config_make_vector (buf, &argc, &argv);
|
|
if (argc < 1)
|
|
return FALSE;
|
|
|
|
prog = gnome_is_program_in_path (argv[0]);
|
|
if (prog)
|
|
retval = TRUE;
|
|
else
|
|
retval = FALSE;
|
|
g_free (prog);
|
|
/* check to see if it's a GMC directive. */
|
|
if ((strlen (argv[0]) > 1) && (argv[0][0] == '%') && (argv[0][1] != '%'))
|
|
retval = TRUE;
|
|
for (i = 0; i < argc; i++)
|
|
g_free (argv[i]);
|
|
g_free (argv);
|
|
return retval;
|
|
}
|
|
int
|
|
gmc_open_filename (char *fname, GList *args)
|
|
{
|
|
/* fname is a full name */
|
|
|
|
const char *mime_type;
|
|
const char *cmd;
|
|
char *buf = NULL;
|
|
int size;
|
|
int needs_terminal = 0;
|
|
|
|
if (use_magic)
|
|
mime_type = gnome_mime_type_or_default_of_file (fname, NULL);
|
|
else
|
|
mime_type = gnome_mime_type_or_default (fname, NULL);
|
|
/*
|
|
* We accept needs_terminal as -1, which means our caller
|
|
* did not want to do the work
|
|
*/
|
|
if (gnome_metadata_get (fname, "flags", &size, &buf) == 0){
|
|
needs_terminal = (strstr (buf, "needsterminal") != 0);
|
|
g_free (buf);
|
|
} else if (mime_type)
|
|
needs_terminal = gnome_mime_needsterminal (mime_type, NULL);
|
|
|
|
if (gnome_metadata_get (fname, "fm-open", &size, &buf) != 0) {
|
|
gnome_metadata_get (fname, "open", &size, &buf);
|
|
}
|
|
if (buf) {
|
|
if (gmc_check_exec_string (buf))
|
|
gmc_execute (fname, buf, needs_terminal);
|
|
else
|
|
gmc_unable_to_execute_dlg (fname, buf, _("open"), NULL);
|
|
g_free (buf);
|
|
return 1;
|
|
}
|
|
if (!mime_type)
|
|
return 0;
|
|
|
|
cmd = gnome_mime_get_value (mime_type, "fm-open");
|
|
if (cmd == NULL) {
|
|
cmd = gnome_mime_get_value (mime_type, "open");
|
|
}
|
|
|
|
if (cmd){
|
|
if (gmc_check_exec_string (cmd))
|
|
gmc_execute (fname, cmd, needs_terminal);
|
|
else
|
|
gmc_unable_to_execute_dlg (fname, cmd, _("open"), mime_type);
|
|
return 1;
|
|
}
|
|
|
|
if (strcmp (mime_type, "application/x-gnome-app-info") == 0){
|
|
GnomeDesktopEntry *entry;
|
|
|
|
entry = gnome_desktop_entry_load (fname);
|
|
if (entry){
|
|
gnome_desktop_entry_launch (entry);
|
|
gnome_desktop_entry_free (entry);
|
|
return 1;
|
|
} else {
|
|
gmc_unable_to_execute_dlg (fname, NULL, "x-gnome-app-info", NULL);
|
|
return 1;
|
|
}
|
|
}
|
|
/* We just struck out. Prompt the user. */
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
gmc_edit (char *fname)
|
|
{
|
|
/* fname is a full path */
|
|
|
|
const char *mime_type;
|
|
const char *cmd;
|
|
char *buf;
|
|
int size;
|
|
char *editor, *type;
|
|
int on_terminal;
|
|
|
|
if (gnome_metadata_get (fname, "edit", &size, &buf) == 0){
|
|
if (gmc_check_exec_string (buf))
|
|
gmc_execute (fname, buf, 0);
|
|
else
|
|
gmc_unable_to_execute_dlg (fname, buf, _("edit"), NULL);
|
|
g_free (buf);
|
|
return 1;
|
|
}
|
|
|
|
if (use_magic)
|
|
mime_type = gnome_mime_type_or_default_of_file (fname, NULL);
|
|
else
|
|
mime_type = gnome_mime_type_or_default (fname, NULL);
|
|
|
|
if (mime_type){
|
|
cmd = gnome_mime_get_value (mime_type, "edit");
|
|
|
|
if (cmd){
|
|
if (gmc_check_exec_string (cmd))
|
|
gmc_execute (fname, cmd, 0);
|
|
else
|
|
gmc_unable_to_execute_dlg (fname, cmd, _("edit"), mime_type);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
gnome_config_push_prefix( "/editor/Editor/");
|
|
type = gnome_config_get_string ("EDITOR_TYPE=executable");
|
|
|
|
if (strcmp (type, "mc-internal") == 0){
|
|
g_free (type);
|
|
do_edit (fname);
|
|
return 1;
|
|
}
|
|
g_free (type);
|
|
|
|
editor = gnome_config_get_string ("EDITOR=emacs");
|
|
on_terminal = gnome_config_get_bool ("NEEDS_TERM=false");
|
|
|
|
if (on_terminal){
|
|
char *quoted = name_quote (fname, 0);
|
|
char *editor_cmd = g_strconcat (editor, " ", quoted, NULL);
|
|
|
|
gnome_open_terminal_with_cmd (editor_cmd);
|
|
g_free (quoted);
|
|
g_free (editor_cmd);
|
|
} else {
|
|
char *cmd = g_strconcat (editor, " %s", NULL);
|
|
|
|
gmc_execute (fname, cmd, 0);
|
|
g_free (cmd);
|
|
}
|
|
|
|
g_free (editor);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
gmc_open (file_entry *fe)
|
|
{
|
|
gint retval;
|
|
gchar *fullname;
|
|
fullname = g_concat_dir_and_file (cpanel->cwd, fe->fname);
|
|
retval = gmc_open_filename (fullname, NULL);
|
|
g_free (fullname);
|
|
return retval;
|
|
}
|
|
|
|
int
|
|
gmc_open_with (gchar *filename)
|
|
{
|
|
GtkWidget *dialog;
|
|
gchar *command = NULL;
|
|
gchar *real_command;
|
|
WPanel *panel = cpanel;
|
|
|
|
dialog = gnome_open_dialog_new (filename);
|
|
if (!is_a_desktop_panel (panel))
|
|
gnome_dialog_set_parent (GNOME_DIALOG (dialog), GTK_WINDOW (panel->xwindow));
|
|
|
|
switch (gnome_dialog_run (GNOME_DIALOG (dialog))) {
|
|
case 0:
|
|
command = gtk_entry_get_text (GTK_ENTRY (gnome_entry_gtk_entry (GNOME_ENTRY (
|
|
GNOME_FILE_ENTRY (GNOME_OPEN_DIALOG (dialog)->entry)->gentry))));
|
|
/* Assume COMMAND %f */
|
|
if (command) {
|
|
/* FIXME: these need the needs_terminal argument to be set correctly */
|
|
if (strchr (command, '%'))
|
|
exec_extension (filename, command, NULL, NULL, 0, FALSE);
|
|
else {
|
|
/* This prolly isn't perfect, but it will do. */
|
|
real_command = g_strconcat (command, " %f", NULL);
|
|
exec_extension (filename, real_command, NULL, NULL, 0, FALSE);
|
|
g_free (real_command);
|
|
}
|
|
}
|
|
if (command) {
|
|
gtk_widget_destroy (dialog);
|
|
return 1;
|
|
}
|
|
gtk_widget_destroy (dialog);
|
|
return 0;
|
|
case 1:
|
|
gtk_widget_destroy (dialog);
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
static void
|
|
gmc_run_view (const char *filename, const char *buf)
|
|
{
|
|
exec_extension (filename, buf, NULL, NULL, 0, 0);
|
|
}
|
|
static gchar *
|
|
gmc_view_command (gchar *filename)
|
|
{
|
|
const char *mime_type, *cmd;
|
|
char *buf;
|
|
int size;
|
|
|
|
if (gnome_metadata_get (filename, "fm-view", &size, &buf) == 0)
|
|
return buf;
|
|
|
|
if (gnome_metadata_get (filename, "view", &size, &buf) == 0)
|
|
return buf;
|
|
|
|
if (use_magic)
|
|
mime_type = gnome_mime_type_or_default_of_file (filename, NULL);
|
|
else
|
|
mime_type = gnome_mime_type_or_default (filename, NULL);
|
|
|
|
if (!mime_type)
|
|
return NULL;
|
|
|
|
|
|
cmd = gnome_mime_get_value (mime_type, "fm-view");
|
|
|
|
if (cmd)
|
|
return g_strdup (cmd);
|
|
|
|
cmd = gnome_mime_get_value (mime_type, "view");
|
|
if (cmd){
|
|
return g_strdup (cmd);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int
|
|
gmc_view (char *filename, int start_line)
|
|
{
|
|
gchar *cmd;
|
|
const gchar *mime_type;
|
|
if (use_magic)
|
|
mime_type = gnome_mime_type_or_default_of_file (filename, NULL);
|
|
else
|
|
mime_type = gnome_mime_type_or_default (filename, NULL);
|
|
cmd = gmc_view_command (filename);
|
|
if (cmd) {
|
|
if (gmc_check_exec_string (cmd))
|
|
gmc_run_view (filename, cmd);
|
|
else
|
|
gmc_unable_to_execute_dlg (filename, cmd, _("view"), mime_type);
|
|
g_free (cmd);
|
|
return 1;
|
|
} else
|
|
view (NULL, filename, 0, 0);
|
|
return 0;
|
|
}
|