Cygwin 版 vim で Windows のクリップボードを使うハック

vim でヤンクすると同じテキストが Windowsクリップボードに入り、
"*p すると Windows クリップボードのテキストがプットされるハック。
ヤンクはともかく、プットは全ての場合に対応していないし、実際には
レジスタ* を使っていないのでかなり問題がある。
しかしこのあたりは複雑であまり手がつけられない。
vim は基本的な編集機能の部分ほど入り組んでいて変更が難しい気がする。
ops.c(Vim7.1)へのパッチ

--- ../src.orig/ops.c	2007-05-28 11:46:13.674622700 +0900
+++ ops.c	2007-06-06 17:17:57.831039800 +0900
@@ -826,7 +826,8 @@
 	    || regname == '"'
 	    || regname == '-'
 	    || regname == '_'
-#ifdef FEAT_CLIPBOARD
+//#ifdef FEAT_CLIPBOARD
+#if 1
 	    || regname == '*'
 	    || regname == '+'
 #endif
@@ -1351,7 +1352,29 @@
     }
     else				/* name or number register */
     {
-	get_yank_register(regname, FALSE);
+	if (regname == '*') {
+	    FILE* clip;
+	    char buf[10240] = {0};
+
+	    clip = fopen("/dev/clipboard", "r");
+	    if ( clip ) { 
+		int len;
+
+		len = fread(buf, 1, sizeof(buf)-1, clip);
+		buf[len] = 0;
+
+		get_yank_register('x', TRUE);
+		free_yank_all();
+		if (strchr(buf, '\n'))
+		    str_to_reg(y_current, MLINE, buf, strlen(buf), 0);
+		else
+		    str_to_reg(y_current, MCHAR, buf, strlen(buf), 0);
+
+		fclose(clip); 
+
+		regname = 'x';
+	    } 
+	}
+	else
+	    get_yank_register(regname, FALSE);
+
 	if (y_current->y_array == NULL)
 	    retval = FAIL;
 	else
@@ -3027,6 +3050,48 @@
 	curbuf->b_op_end.col = MAXCOL;
     }
 
+
+    {
+       FILE* clip;
+        int i;
+        char* buf = NULL;
+        int bufsize;
+
+        if (y_current->y_type == MCHAR) {
+            bufsize = strlen(y_current->y_array[0]) + 1;
+        }
+        else {
+            bufsize = 0;
+            for (i=0; i<y_current->y_size; i++) {
+                bufsize += strlen(y_current->y_array[i]) + 1;
+            }
+            bufsize += 1;
+        } 
+
+        buf = malloc(bufsize);
+
+        if (buf) {
+            if (y_current->y_type == MCHAR) {
+                strcpy(buf, y_current->y_array[0]);
+            }
+            else { 
+                buf[0] = 0;
+                for (i=0; i<y_current->y_size; i++) {
+                    strcat(buf, y_current->y_array[i]);
+                    strcat(buf, "\n");
+                }
+            } 
+
+            clip = fopen("/dev/clipboard", "w");
+            if ( clip ) { 
+                fwrite(buf, strlen(buf), 1, clip);
+                fclose(clip); 
+            }
+            free(buf);
+        }
+    }
+
+
 #ifdef FEAT_CLIPBOARD
     /*
      * If we were yanking to the '*' register, send result to clipboard.
@@ -3169,6 +3234,32 @@
     int		allocated = FALSE;
     long	cnt;
 
+#if 1
+    if (regname == '*')
+    {
+        FILE* clip;
+        char buf[10240] = {0};
+
+        clip = fopen("/dev/clipboard", "r");
+        if ( clip ) { 
+	    int len;
+
+	    len = fread(buf, 1, sizeof(buf)-1, clip);
+            buf[len] = 0;
+
+            get_yank_register('x', TRUE);
+            free_yank_all();
+            str_to_reg(y_current, MLINE, buf, strlen(buf), 0);
+
+            fclose(clip); 
+
+	    regname = 'x';
+        } 
+
+	goto DO_PASTE;
+    }
+#endif 
+
 #ifdef FEAT_CLIPBOARD
     /* Adjust register name for "unnamed" in 'clipboard'. */
     adjust_clip_reg(&regname);
@@ -3206,6 +3297,7 @@
 	    return;
     }
 
+DO_PASTE:
     if (insert_string != NULL)
     {
 	y_type = MCHAR;

追記:"*p が機能しないことを発見。直し方はまだ不明。
→2007/05/28: valid_yank_reg() を直せばいいよう。

[追記:2006-08-18]
コピーのとき、バッファ長を可変に変更した。
" 選択範囲の単語を置換

[追記:2007-06-06]
i_CTRL-R に対応。