/* Util for external clipboard. Copyright (C) 2009-2023 Free Software Foundation, Inc. Written by: Ilia Maslakov , 2010. Andrew Borodin , 2014. This file is part of the Midnight Commander. The Midnight Commander is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The Midnight Commander is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include "lib/global.h" #include "lib/fileloc.h" #include "lib/mcconfig.h" #include "lib/util.h" #include "lib/event.h" #include "lib/vfs/vfs.h" #include "src/execute.h" #include "clipboard.h" /*** global variables ****************************************************************************/ /* path to X clipboard utility */ char *clipboard_store_path = NULL; char *clipboard_paste_path = NULL; /*** file scope macro definitions ****************************************************************/ /*** file scope type declarations ****************************************************************/ /*** forward declarations (file scope functions) *************************************************/ /*** file scope variables ************************************************************************/ static const int clip_open_flags = O_CREAT | O_WRONLY | O_TRUNC | O_BINARY; static const mode_t clip_open_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; /* --------------------------------------------------------------------------------------------- */ /*** file scope functions ************************************************************************/ /* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */ /*** public functions ****************************************************************************/ /* --------------------------------------------------------------------------------------------- */ /* event callback */ gboolean clipboard_file_to_ext_clip (const gchar * event_group_name, const gchar * event_name, gpointer init_data, gpointer data) { char *tmp, *cmd; (void) event_group_name; (void) event_name; (void) init_data; (void) data; if (clipboard_store_path == NULL || clipboard_store_path[0] == '\0') return TRUE; tmp = mc_config_get_full_path (EDIT_HOME_CLIP_FILE); cmd = g_strconcat (clipboard_store_path, " ", tmp, " 2>/dev/null", (char *) NULL); if (cmd != NULL) my_system (EXECUTE_AS_SHELL, mc_global.shell->path, cmd); g_free (cmd); g_free (tmp); return TRUE; } /* --------------------------------------------------------------------------------------------- */ /* event callback */ gboolean clipboard_file_from_ext_clip (const gchar * event_group_name, const gchar * event_name, gpointer init_data, gpointer data) { mc_pipe_t *p; int file = -1; (void) event_group_name; (void) event_name; (void) init_data; (void) data; if (clipboard_paste_path == NULL || clipboard_paste_path[0] == '\0') return TRUE; p = mc_popen (clipboard_paste_path, TRUE, TRUE, NULL); if (p == NULL) return TRUE; /* don't show error message */ p->out.null_term = FALSE; p->err.null_term = TRUE; while (TRUE) { GError *error = NULL; p->out.len = MC_PIPE_BUFSIZE; p->err.len = MC_PIPE_BUFSIZE; mc_pread (p, &error); if (error != NULL) { /* don't show error message */ g_error_free (error); break; } /* ignore stderr and get stdout */ if (p->out.len == MC_PIPE_STREAM_EOF || p->out.len == MC_PIPE_ERROR_READ) break; if (p->out.len > 0) { ssize_t nwrite; if (file < 0) { vfs_path_t *fname_vpath; fname_vpath = mc_config_get_full_vpath (EDIT_HOME_CLIP_FILE); file = mc_open (fname_vpath, clip_open_flags, clip_open_mode); vfs_path_free (fname_vpath, TRUE); if (file < 0) break; } nwrite = mc_write (file, p->out.buf, p->out.len); (void) nwrite; } } if (file >= 0) mc_close (file); mc_pclose (p, NULL); return TRUE; } /* --------------------------------------------------------------------------------------------- */ /* event callback */ gboolean clipboard_text_to_file (const gchar * event_group_name, const gchar * event_name, gpointer init_data, gpointer data) { int file; vfs_path_t *fname_vpath = NULL; size_t str_len; const char *text = (const char *) data; (void) event_group_name; (void) event_name; (void) init_data; if (text == NULL) return FALSE; fname_vpath = mc_config_get_full_vpath (EDIT_HOME_CLIP_FILE); file = mc_open (fname_vpath, clip_open_flags, clip_open_mode); vfs_path_free (fname_vpath, TRUE); if (file == -1) return TRUE; str_len = strlen (text); { ssize_t ret; ret = mc_write (file, text, str_len); (void) ret; } mc_close (file); return TRUE; } /* --------------------------------------------------------------------------------------------- */ /* event callback */ gboolean clipboard_text_from_file (const gchar * event_group_name, const gchar * event_name, gpointer init_data, gpointer data) { char buf[BUF_LARGE]; FILE *f; char *fname = NULL; gboolean first = TRUE; ev_clipboard_text_from_file_t *event_data = (ev_clipboard_text_from_file_t *) data; (void) event_group_name; (void) event_name; (void) init_data; fname = mc_config_get_full_path (EDIT_HOME_CLIP_FILE); f = fopen (fname, "r"); g_free (fname); if (f == NULL) { event_data->ret = FALSE; return TRUE; } *(event_data->text) = NULL; while (fgets (buf, sizeof (buf), f)) { size_t len; len = strlen (buf); if (len > 0) { if (buf[len - 1] == '\n') buf[len - 1] = '\0'; if (first) { first = FALSE; *(event_data->text) = g_strdup (buf); } else { /* remove \n on EOL */ char *tmp; tmp = g_strconcat (*(event_data->text), " ", buf, (char *) NULL); g_free (*(event_data->text)); *(event_data->text) = tmp; } } } fclose (f); event_data->ret = (*(event_data->text) != NULL); return TRUE; } /* --------------------------------------------------------------------------------------------- */