From 149594f974350bb364a76c73b91b1d5ffddaa1fa Mon Sep 17 00:00:00 2001 From: axel Date: Tue, 20 Sep 2005 23:26:39 +1000 Subject: Initial revision darcs-hash:20050920132639-ac50b-fa3b476891e1f5f67207cf4cc7bf623834cc5edc.gz --- kill.c | 256 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 kill.c (limited to 'kill.c') diff --git a/kill.c b/kill.c new file mode 100644 index 00000000..86a6f34a --- /dev/null +++ b/kill.c @@ -0,0 +1,256 @@ +/** \file kill.c + The killring. + + Works like the killring in emacs and readline. The killring is cut + and paste with a memory of previous cuts. It supports integration + with the X clipboard. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "config.h" +#include "util.h" +#include "wutil.h" +#include "kill.h" +#include "proc.h" +#include "sanity.h" +#include "common.h" +#include "env.h" +#include "expand.h" +#include "exec.h" +#include "parser.h" + +/** + Maximum entries in killring +*/ +#define KILL_MAX 8192 + + +static ll_node_t /** Last kill string */*kill_last=0, /** Current kill string */*kill_current =0; +/** + Contents of the X clipboard, at last time we checked it +*/ +static wchar_t *cut_buffer=0; + +/** + Test if the xsel command is installed +*/ +static int has_xsel() +{ + wchar_t *path = get_filename( L"xsel" ); + if( path) + { + free(path); + return 1; + } + else + return 0; +} + + + +/** + Add the string to the internal killring +*/ +static void kill_add_internal( wchar_t *str ) +{ + if( wcslen( str ) == 0 ) + return; + + if( kill_last == 0 ) + { + kill_current = kill_last=malloc( sizeof( ll_node_t ) ); + kill_current->data = wcsdup(str); + kill_current->prev = kill_current; + } + else + { + kill_current = malloc( sizeof( ll_node_t ) ); + kill_current->data = kill_last->data; + kill_last->data = wcsdup(str); + kill_current->prev = kill_last->prev; + kill_last->prev = kill_current; + kill_current = kill_last; + } +} + + +void kill_add( wchar_t *str ) +{ + kill_add_internal(str); + + if( !has_xsel() ) + return; + + /* This is for sending the kill to the X copy-and-paste buffer */ + wchar_t *disp; + if( (disp = env_get( L"DISPLAY" )) ) + { + wchar_t *escaped_str = expand_escape( wcsdup(str), 1 ); + wchar_t *cmd = wcsdupcat2(L"echo ", escaped_str, L"|xsel -b",0); + exec_subshell( cmd, 0 ); + free( cut_buffer ); + free( cmd ); + + cut_buffer = escaped_str; + } +} + + +wchar_t *kill_yank_rotate() +{ + if( kill_current == 0 ) + return L""; + kill_current = kill_current->prev; + return (wchar_t *)kill_current->data; +} + +/** + Check the X clipboard. If it has been changed, add the new + clipboard contents to the fish killring. +*/ +static void kill_check_x_buffer() +{ + wchar_t *disp; + + if( !has_xsel() ) + return; + + + if( (disp = env_get( L"DISPLAY" )) ) + { + int i; + wchar_t *cmd = L"xsel -t 500 -b"; + wchar_t *new_cut_buffer=0; + array_list_t list; + al_init( &list ); + exec_subshell( cmd, &list ); + + for( i=0; idata; +} + +void kill_sanity_check() +{ + int i; + if( is_interactive ) + { + /* Test that the kill-ring is consistent */ + if( kill_current != 0 ) + { + int kill_ok = 0; + ll_node_t *tmp = kill_current->prev; + for( i=0; idata == 0 ) + break; + + if( tmp == kill_current ) + { + kill_ok = 1; + break; + } + tmp = tmp->prev; + } + if( !kill_ok ) + { + debug( 0, + L"Killring inconsistent" ); + sanity_lose(); + } + } + + } +} + +void kill_init() +{ +} + +void kill_destroy() +{ + if( cut_buffer ) + free( cut_buffer ); + + if( kill_current != 0 ) + { + kill_current = kill_last->prev; + kill_last->prev = 0; + + while( kill_current ) + { + ll_node_t *tmp = kill_current; + kill_current = kill_current->prev; + free( tmp->data ); + free( tmp ); + } + } + +} + -- cgit v1.2.3