From 478328812f63307a166dd155504daa1b9c1596d7 Mon Sep 17 00:00:00 2001 From: Ilia Maslakov Date: Wed, 7 Oct 2009 15:43:19 +0000 Subject: [PATCH] Ticket #244 add shared clipboard support Signed-off-by: Ilia Maslakov Fixed memory leaks. Type accuracy. Optimization. Signed-off-by: Andrew Borodin * fixed ctrl-g handler * change action names from InputKillSave to InputXStore and InputPaste to InputXPaste * update mc.keymap.default mc.keymap.emacs Signed-off-by: Ilia Maslakov --- misc/mc.keymap.default | 4 +- misc/mc.keymap.emacs | 4 +- src/cmddef.h | 3 + src/keybind.c | 4 +- src/main.c | 1 - src/tty/key.h | 3 +- src/widget.c | 148 ++++++++++++++++++++++++++++++++++++++--- 7 files changed, 151 insertions(+), 16 deletions(-) diff --git a/misc/mc.keymap.default b/misc/mc.keymap.default index 6a64d5ac9..0dd68b3cc 100644 --- a/misc/mc.keymap.default +++ b/misc/mc.keymap.default @@ -298,10 +298,12 @@ InputKillWord = alt-d InputBackwardKillWord = alt-backspace InputSetMark = InputKillRegion = ctrl-w -InputKillSave = alt-w +InputXStore = alt-w +InputXPaste = InputYank = ctrl-y InputKillLine = ctrl-k InputHistoryPrev = alt-p; ctrl-down InputHistoryNext = alt-n; ctrl-up InputHistoryShow = alt-h InputComplete = alt-tab +InputClearLine = diff --git a/misc/mc.keymap.emacs b/misc/mc.keymap.emacs index 53aeb6e81..dcf6afe65 100644 --- a/misc/mc.keymap.emacs +++ b/misc/mc.keymap.emacs @@ -302,10 +302,12 @@ InputKillWord = alt-d InputBackwardKillWord = alt-backspace InputSetMark = InputKillRegion = ctrl-w -InputKillSave = alt-w +InputXStore = alt-w +InputXPaste = InputYank = ctrl-y InputKillLine = ctrl-k InputHistoryPrev = alt-p; ctrl-down InputHistoryNext = alt-n; ctrl-up InputHistoryShow = alt-h InputComplete = alt-tab +InputClearLine = diff --git a/src/cmddef.h b/src/cmddef.h index 265aed921..26441300c 100644 --- a/src/cmddef.h +++ b/src/cmddef.h @@ -226,6 +226,9 @@ #define CK_InputHistoryNext 4022 #define CK_InputHistoryShow 4023 #define CK_InputComplete 4024 +#define CK_InputPaste 4025 +#define CK_InputClearLine 4026 + /* Viewer */ #define CK_ViewSearch 5001 diff --git a/src/keybind.c b/src/keybind.c index 430c717a4..5edfdc3f9 100644 --- a/src/keybind.c +++ b/src/keybind.c @@ -382,13 +382,15 @@ static const name_keymap_t command_names[] = { { "InputBackwardKillWord", CK_InputBackwardKillWord }, { "InputSetMark", CK_InputSetMark }, { "InputKillRegion", CK_InputKillRegion }, - { "InputKillSave", CK_InputKillSave }, { "InputYank", CK_InputYank }, { "InputKillLine", CK_InputKillLine }, { "InputHistoryPrev", CK_InputHistoryPrev }, { "InputHistoryNext", CK_InputHistoryNext }, { "InputHistoryShow", CK_InputHistoryShow }, { "InputComplete", CK_InputComplete }, + { "InputXStore", CK_InputKillSave }, + { "InputXPaste", CK_InputPaste }, + { "InputClearLine", CK_InputClearLine }, /* common */ { "ExtMap1", CK_StartExtMap1 }, diff --git a/src/main.c b/src/main.c index c601d3730..511e494e1 100644 --- a/src/main.c +++ b/src/main.c @@ -1569,7 +1569,6 @@ static cb_ret_t midnight_callback (struct Dlg_head *h, dlg_msg_t msg, int parm) { int i; - switch (msg) { case DLG_IDLE: diff --git a/src/tty/key.h b/src/tty/key.h index 34193988a..812f342e4 100644 --- a/src/tty/key.h +++ b/src/tty/key.h @@ -75,8 +75,7 @@ void channels_down (void); static inline gboolean is_abort_char (int c) { - return ((c == XCTRL ('c')) || (c == XCTRL ('g')) - || (c == ESC_CHAR) || (c == KEY_F (10))); + return ((c == ESC_CHAR) || (c == KEY_F (10))); } /* To define sequences and return codes */ diff --git a/src/widget.c b/src/widget.c index c144c7758..78b49d9ca 100644 --- a/src/widget.c +++ b/src/widget.c @@ -57,6 +57,7 @@ #include "cmddef.h" /* CK_ cmd name const */ #include "keybind.h" /* global_keymap_t */ #include "fileloc.h" +#include "panel.h" /* current_panel */ const global_keymap_t *input_map; @@ -579,6 +580,104 @@ check_new (int y, int x, int state, const char *text) return c; } +static gboolean +save_text_to_clip_file (const char *text) +{ + int file; + char *fname = NULL; + + fname = g_build_filename (home_dir, EDIT_CLIP_FILE, NULL); + file = mc_open (fname, O_CREAT | O_WRONLY | O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | O_BINARY); + g_free (fname); + + if (file == -1) + return FALSE; + + mc_write (file, (char *) text, strlen (text)); + mc_close (file); + return TRUE; +} + +static gboolean +load_text_from_clip_file (char **text) +{ + char buf[BUF_LARGE]; + FILE *f; + char *fname = NULL; + gboolean first = TRUE; + + fname = g_build_filename (home_dir, EDIT_CLIP_FILE, NULL); + f = fopen (fname, "r"); + g_free (fname); + + if (f == NULL) + return FALSE; + + *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; + *text = g_strdup (buf); + } else { + /* remove \n on EOL */ + char *tmp; + + tmp = g_strconcat (*text, " ", buf, (char *) NULL); + g_free (*text); + *text = tmp; + } + } + } + + fclose (f); + + return (*text != NULL); +} + +static gboolean +panel_save_curent_file_to_clip_file (void) +{ + gboolean res; + + if (current_panel->marked == 0) + res = save_text_to_clip_file (selection (current_panel)->fname); + else { + int i; + gboolean first = TRUE; + char *flist = NULL; + + for (i = 0; i < current_panel->count; i++) + if (current_panel->dir.list[i].f.marked != 0) { /* Skip the unmarked ones */ + if (first) { + flist = g_strdup (current_panel->dir.list[i].fname); + first = FALSE; + } else { + /* Add empty lines after the file */ + char *tmp; + + tmp = g_strconcat (flist, "\n", current_panel->dir.list[i].fname, (char *) NULL); + g_free (flist); + flist = tmp; + } + } + + if (flist != NULL) { + res = save_text_to_clip_file (flist); + g_free (flist); + } + } + return res; +} + /* Label widget */ @@ -1470,8 +1569,11 @@ copy_region (WInput *in, int x_first, int x_last) int first = min (x_first, x_last); int last = max (x_first, x_last); - if (last == first) - return; + if (last == first) { + /* Copy selected files to clipboard */ + panel_save_curent_file_to_clip_file (); + return; + } g_free (kill_buffer); @@ -1479,23 +1581,24 @@ copy_region (WInput *in, int x_first, int x_last) last = str_offset_to_pos (in->buffer, last); kill_buffer = g_strndup(in->buffer + first, last - first); + save_text_to_clip_file (kill_buffer); } static void delete_region (WInput *in, int x_first, int x_last) { - int first = min (x_first, x_last); - int last = max (x_first, x_last); + int first = min (x_first, x_last); + int last = max (x_first, x_last); size_t len; - in->point = first; - in->mark = first; + in->point = first; + in->mark = first; last = str_offset_to_pos (in->buffer, last); first = str_offset_to_pos (in->buffer, first); len = strlen (&in->buffer[last]) + 1; memmove (&in->buffer[first], &in->buffer[last], len); in->charpoint = 0; - in->need_push = 1; + in->need_push = 1; } static void @@ -1549,6 +1652,12 @@ kill_region (WInput *in) delete_region (in, in->point, in->mark); } +static void +clear_region (WInput *in) +{ + delete_region (in, in->point, in->mark); +} + static void yank (WInput *in) { @@ -1572,6 +1681,21 @@ kill_line (WInput *in) in->charpoint = 0; } +static void +ins_from_clip (WInput *in) +{ + char *p = NULL; + + if (load_text_from_clip_file (&p)) { + char *pp; + + for (pp = p; *pp != '\0'; pp++) + insert_char (in, *pp); + + g_free (p); + } +} + void assign_text (WInput *in, const char *text) { @@ -1700,12 +1824,18 @@ input_execute_cmd (WInput *in, int command) case CK_InputKillRegion: kill_region (in); break; + case CK_InputClearLine: + clear_region (in); + break; case CK_InputKillSave: kill_save (in); break; case CK_InputYank: yank (in); break; + case CK_InputPaste: + ins_from_clip (in); + break; case CK_InputKillLine: kill_line (in); break; @@ -1735,7 +1865,6 @@ int is_in_input_map (WInput *in, int key) { int i; - for (i = 0; input_map[i].key; i++) { if (key == input_map[i].key) { input_execute_cmd (in, input_map[i].command); @@ -1763,7 +1892,6 @@ handle_char (WInput *in, int key) quote = 0; return v; } - for (i = 0; input_map[i].key; i++) { if (key == input_map[i].key) { if (input_map[i].command != CK_InputComplete) @@ -1830,7 +1958,7 @@ input_callback (Widget *w, widget_msg_t msg, int parm) /* Keys we want others to handle */ if (parm == KEY_UP || parm == KEY_DOWN || parm == ESC_CHAR - || parm == KEY_F (10) || parm == XCTRL ('g') || parm == '\n') + || parm == KEY_F (10) || parm == '\n') return MSG_NOT_HANDLED; /* When pasting multiline text, insert literal Enter */