clipboard.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /*
  2. Util for external clipboard.
  3. Copyright (C) 2009-2024
  4. Free Software Foundation, Inc.
  5. Written by:
  6. Ilia Maslakov <il.smind@gmail.com>, 2010.
  7. Andrew Borodin <aborodin@vmail.ru>, 2014.
  8. This file is part of the Midnight Commander.
  9. The Midnight Commander is free software: you can redistribute it
  10. and/or modify it under the terms of the GNU General Public License as
  11. published by the Free Software Foundation, either version 3 of the License,
  12. or (at your option) any later version.
  13. The Midnight Commander is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. GNU General Public License for more details.
  17. You should have received a copy of the GNU General Public License
  18. along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <config.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <sys/types.h>
  24. #include "lib/global.h"
  25. #include "lib/fileloc.h"
  26. #include "lib/mcconfig.h"
  27. #include "lib/util.h"
  28. #include "lib/event.h"
  29. #include "lib/vfs/vfs.h"
  30. #include "src/execute.h"
  31. #include "clipboard.h"
  32. /*** global variables ****************************************************************************/
  33. /* path to X clipboard utility */
  34. char *clipboard_store_path = NULL;
  35. char *clipboard_paste_path = NULL;
  36. /*** file scope macro definitions ****************************************************************/
  37. /*** file scope type declarations ****************************************************************/
  38. /*** forward declarations (file scope functions) *************************************************/
  39. /*** file scope variables ************************************************************************/
  40. static const int clip_open_flags = O_CREAT | O_WRONLY | O_TRUNC | O_BINARY;
  41. static const mode_t clip_open_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
  42. /* --------------------------------------------------------------------------------------------- */
  43. /*** file scope functions ************************************************************************/
  44. /* --------------------------------------------------------------------------------------------- */
  45. /* --------------------------------------------------------------------------------------------- */
  46. /*** public functions ****************************************************************************/
  47. /* --------------------------------------------------------------------------------------------- */
  48. /* event callback */
  49. gboolean
  50. clipboard_file_to_ext_clip (const gchar *event_group_name, const gchar *event_name,
  51. gpointer init_data, gpointer data)
  52. {
  53. char *tmp, *cmd;
  54. (void) event_group_name;
  55. (void) event_name;
  56. (void) init_data;
  57. (void) data;
  58. if (clipboard_store_path == NULL || clipboard_store_path[0] == '\0')
  59. return TRUE;
  60. tmp = mc_config_get_full_path (EDIT_HOME_CLIP_FILE);
  61. cmd = g_strconcat (clipboard_store_path, " ", tmp, " 2>/dev/null", (char *) NULL);
  62. if (cmd != NULL)
  63. my_system (EXECUTE_AS_SHELL, mc_global.shell->path, cmd);
  64. g_free (cmd);
  65. g_free (tmp);
  66. return TRUE;
  67. }
  68. /* --------------------------------------------------------------------------------------------- */
  69. /* event callback */
  70. gboolean
  71. clipboard_file_from_ext_clip (const gchar *event_group_name, const gchar *event_name,
  72. gpointer init_data, gpointer data)
  73. {
  74. mc_pipe_t *p;
  75. int file = -1;
  76. (void) event_group_name;
  77. (void) event_name;
  78. (void) init_data;
  79. (void) data;
  80. if (clipboard_paste_path == NULL || clipboard_paste_path[0] == '\0')
  81. return TRUE;
  82. p = mc_popen (clipboard_paste_path, TRUE, TRUE, NULL);
  83. if (p == NULL)
  84. return TRUE; /* don't show error message */
  85. p->out.null_term = FALSE;
  86. p->err.null_term = TRUE;
  87. while (TRUE)
  88. {
  89. GError *error = NULL;
  90. p->out.len = MC_PIPE_BUFSIZE;
  91. p->err.len = MC_PIPE_BUFSIZE;
  92. mc_pread (p, &error);
  93. if (error != NULL)
  94. {
  95. /* don't show error message */
  96. g_error_free (error);
  97. break;
  98. }
  99. /* ignore stderr and get stdout */
  100. if (p->out.len == MC_PIPE_STREAM_EOF || p->out.len == MC_PIPE_ERROR_READ)
  101. break;
  102. if (p->out.len > 0)
  103. {
  104. ssize_t nwrite;
  105. if (file < 0)
  106. {
  107. vfs_path_t *fname_vpath;
  108. fname_vpath = mc_config_get_full_vpath (EDIT_HOME_CLIP_FILE);
  109. file = mc_open (fname_vpath, clip_open_flags, clip_open_mode);
  110. vfs_path_free (fname_vpath, TRUE);
  111. if (file < 0)
  112. break;
  113. }
  114. nwrite = mc_write (file, p->out.buf, p->out.len);
  115. (void) nwrite;
  116. }
  117. }
  118. if (file >= 0)
  119. mc_close (file);
  120. mc_pclose (p, NULL);
  121. return TRUE;
  122. }
  123. /* --------------------------------------------------------------------------------------------- */
  124. /* event callback */
  125. gboolean
  126. clipboard_text_to_file (const gchar *event_group_name, const gchar *event_name,
  127. gpointer init_data, gpointer data)
  128. {
  129. int file;
  130. vfs_path_t *fname_vpath = NULL;
  131. size_t str_len;
  132. const char *text = (const char *) data;
  133. (void) event_group_name;
  134. (void) event_name;
  135. (void) init_data;
  136. if (text == NULL)
  137. return FALSE;
  138. fname_vpath = mc_config_get_full_vpath (EDIT_HOME_CLIP_FILE);
  139. file = mc_open (fname_vpath, clip_open_flags, clip_open_mode);
  140. vfs_path_free (fname_vpath, TRUE);
  141. if (file == -1)
  142. return TRUE;
  143. str_len = strlen (text);
  144. {
  145. ssize_t ret;
  146. ret = mc_write (file, text, str_len);
  147. (void) ret;
  148. }
  149. mc_close (file);
  150. return TRUE;
  151. }
  152. /* --------------------------------------------------------------------------------------------- */
  153. /* event callback */
  154. gboolean
  155. clipboard_text_from_file (const gchar *event_group_name, const gchar *event_name,
  156. gpointer init_data, gpointer data)
  157. {
  158. char buf[BUF_LARGE];
  159. FILE *f;
  160. char *fname = NULL;
  161. gboolean first = TRUE;
  162. ev_clipboard_text_from_file_t *event_data = (ev_clipboard_text_from_file_t *) data;
  163. (void) event_group_name;
  164. (void) event_name;
  165. (void) init_data;
  166. fname = mc_config_get_full_path (EDIT_HOME_CLIP_FILE);
  167. f = fopen (fname, "r");
  168. g_free (fname);
  169. if (f == NULL)
  170. {
  171. event_data->ret = FALSE;
  172. return TRUE;
  173. }
  174. *(event_data->text) = NULL;
  175. while (fgets (buf, sizeof (buf), f))
  176. {
  177. size_t len;
  178. len = strlen (buf);
  179. if (len > 0)
  180. {
  181. if (buf[len - 1] == '\n')
  182. buf[len - 1] = '\0';
  183. if (first)
  184. {
  185. first = FALSE;
  186. *(event_data->text) = g_strdup (buf);
  187. }
  188. else
  189. {
  190. /* remove \n on EOL */
  191. char *tmp;
  192. tmp = g_strconcat (*(event_data->text), " ", buf, (char *) NULL);
  193. g_free (*(event_data->text));
  194. *(event_data->text) = tmp;
  195. }
  196. }
  197. }
  198. fclose (f);
  199. event_data->ret = (*(event_data->text) != NULL);
  200. return TRUE;
  201. }
  202. /* --------------------------------------------------------------------------------------------- */