screenのコピー&ペーストをWindowsのクリップボードと同期させる

Cygwinでscreenを使っているが、Windowsのクリップボードとscreenのコピペが同期したら便利かも…と思ったので少しいじってみた。

クリップボードの操作

まず、クリップボードを操作する関数を書く。
(see http://nienie.com/~masapico/api_GetClipboardData.html)

clip.h
#ifndef __CLIP_H__
#define __CLIP_H__

char *getclip(int *lenp);
void putclip(char *buf, int len);

#endif
clip.c
#include <windows.h>
#include <stdlib.h>
#include <string.h>

char *getclip(int *lenp) {
  HANDLE hText;
  char *pText, *buf;
  int len = 0;

  OpenClipboard(NULL);
  hText = GetClipboardData(CF_TEXT);

  if (hText) {
    pText = GlobalLock(hText);
    len = strlen(pText);
    buf = malloc(len + 1);
    memcpy(buf, pText, len);
    buf[len] = '\0';
    GlobalUnlock(hText);
  }

  CloseClipboard();

  if (lenp) {
    *lenp = len;
  }

  return buf;
}

void putclip(char *buf, int len) {
  HGLOBAL hText;
  char *pText;

  hText = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, len + 1);
  pText = GlobalLock(hText);
  lstrcpy(pText, buf);
  GlobalUnlock(hText);

  OpenClipboard(NULL);
  EmptyClipboard();
  SetClipboardData(CF_TEXT, hText);
  CloseClipboard();
}

コピーの同期

mark.cの1069行目あたりにコピーした文字列をクリップボードに入れる処理を追加する。

	      ExitOverlayPage();

              /* ここから */
              putclip(md_user->u_plop.buf, md_user->u_plop.len);
              /* ここまで */

	      if (append_mode)

ペーストの同期

process.cの2143行目あたりにクリップボードから文字列を取り出して、画面にペーストする処理を追加する。screen自体のペースト処理は無視。
エンコードがカラムと文字化けするような…

      /*FALLTHROUGH*/
    case RC_PASTE:
      /* ここから */
      {
        int len;
        char *buf = (char *) getclip(&len);
        MakePaster(&fore->w_paster, buf, len, 0);
        free(buf);
        break;
      }
      /* ここまで */
      {
        char *ss, *dbuf, dch;
追記

改行コードがLF…orz

追記2

力業で解決…orz
環境に依存しそうな気が。

#include <windows.h>
#include <stdlib.h>
#include <string.h>

char *getclip(int *lenp) {
  HANDLE hText;
  char *pText, *buf;
  int len = 0;

  OpenClipboard(NULL);
  hText = GetClipboardData(CF_TEXT);

  if (hText) {
    int i, j, n;
    char prev = 0;
    pText = GlobalLock(hText);
    len = n = strlen(pText);

    for (i = 0; i < len; i++)
      if (pText[i] == '\n') n++;

    buf = calloc(n + 1, sizeof(char));

    for (i = 0, j = 0; i < len; i++) {
      if (pText[i] == '\n' && prev != '\r') {
        buf[j++] = '\r';
        buf[j++] = '\n';
      } else {
        buf[j++] = pText[i];
      }

      prev = pText[i];
    }

    len = j;

    for (i = 0, j = 0; i < len; i++) {
      if (buf[i] != '\n')
        buf[j++] = buf[i];
    }

    len = j;
    buf[len] = '\0';
    GlobalUnlock(hText);
  }

  CloseClipboard();

  if (lenp) {
    *lenp = len;
  }

  return buf;
}

void putclip(char *buf, int len) {
  HGLOBAL hText;
  char *pText;
  int i;

  hText = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, len + 1);
  pText = GlobalLock(hText);
  lstrcpy(pText, buf);

  for (i = 0; i < len; i++)
    if (pText[i] == '\r')
      pText[i] = '\n';

  GlobalUnlock(hText);

  OpenClipboard(NULL);
  EmptyClipboard();
  SetClipboardData(CF_TEXT, hText);
  CloseClipboard();
}