add shared clipboard support

Signed-off-by: Ilia Maslakov <il.smind@google.com>

    Fixed memory leaks. Type accuracy. Optimization.

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>

    * 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 <il.smind@gmail.com>
This commit is contained in:
Ilia Maslakov 2009-10-07 15:43:19 +00:00 committed by Ilia Maslakov
parent 359c9406d1
commit 478328812f
7 changed files with 151 additions and 16 deletions

View File

@ -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 =

View File

@ -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 =

View File

@ -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

View File

@ -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 },

View File

@ -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:

View File

@ -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 */

View File

@ -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 */