Loading ...
Sorry, an error occurred while loading the content.

47009Re: Subject: Re: vim on cygwin using win32 clipboard

Expand Messages
  • Frodak Baksik
    May 22, 2007
    • 0 Attachment
      On 5/18/07, Gary Johnson <garyjohn@...> wrote:
      > On 2007-05-17, Gary Johnson <garyjohn@...> wrote:
      > > On 2007-02-15, Frodak Baksik <frodak17@...> wrote:
      > > > On 2/15/07, Chris Sutcliffe wrote:
      > > > > > > Also, is there anything I can do to help get the original
      > > > > > > patch accepted?
      > > > > >
      > > > > > Ask a few people to try it out and report their results here.
      > > > >
      > > > > I'll give it a shot. Is there somewhere I can grab the patch from, or
      > > > > should I go through the list archives to find it?
      > >
      > > > Here are all the changes in a single patch.
      > > > I'm also posting this to the cygwin-apps mailing list, so if anyone
      > > > over there could try it out would be nice.
      > >
      > > I just applied this patch to the 7.1 source. The patch to
      > > proto/os_mswin.pro failed, but it was easy to fix manually. The
      > > problem was that the extern prefix has been removed from the 7.1
      > > declarations. Hunk #2 of the patch to os_win32.c failed, apparently
      > > because that change was already made to the 7.1 source, so I left
      > > that file with only hunk #1 applied.
      >
      > It looks like I goofed when applying the patch that way. I just
      > applied the patch to another system, but edited the patch first to
      > get rid of the failures instead of trying to edit the files
      > afterwards. All I had to do to the proto/winclip.pro section was to
      > remove "extern " from the start of all the lines. While editing the
      > os_win32.c section, I discovered that 'patch' was missing the first
      > hunk in the target and applying the first hunk of the patch to the
      > second hunk in the target, causing the application of the second
      > hunk of the patch to fail. This was cause by the reformatting of a
      > comment from 7.0 to 7.1. I changed the comment in the patch to
      > match the comment in the 7.1 source and the entire patch applied
      > successfully.
      >
      > Regards,
      > Gary
      >
      > --
      > Gary Johnson | Agilent Technologies
      > garyjohn@... | Mobile Broadband Division
      > | Spokane, Washington, USA
      >

      I've updated the patch to work with version 7.1. Specifically the
      first patch was against version 212 of
      https://svn.sourceforge.net/svnroot/vim/vim7. I checked this out,
      applied the patch, updated to revision 296, and fixed the conflicts
      you mentioned.

      Thanks,
      Frodak

      Index: term.c
      ===================================================================
      --- term.c (revision 296)
      +++ term.c (working copy)
      @@ -1921,7 +1921,9 @@
      # ifdef FEAT_GUI
      if (!gui.in_use)
      # endif
      +# ifndef FEAT_CYGWIN_WIN32_CLIPBOARD
      clip_init(FALSE);
      +# endif
      # endif
      if (term_is_xterm)
      {
      Index: Make_cyg.mak
      ===================================================================
      --- Make_cyg.mak (revision 296)
      +++ Make_cyg.mak (working copy)
      @@ -420,6 +420,7 @@
      $(OUTDIR)/option.o \
      $(OUTDIR)/os_win32.o \
      $(OUTDIR)/os_mswin.o \
      + $(OUTDIR)/winclip.o \
      $(OUTDIR)/pathdef.o \
      $(OUTDIR)/popupmnu.o \
      $(OUTDIR)/quickfix.o \
      Index: configure.in
      ===================================================================
      --- configure.in (revision 296)
      +++ configure.in (working copy)
      @@ -1969,7 +1969,22 @@
      dnl end of GUI-checking
      dnl ---------------------------------------------------------------------------

      +dnl Check for Cygwin, which needs an extra source file if not using X11
      +AC_MSG_CHECKING(for CYGWIN environment)
      +case `uname` in
      + CYGWIN*) CYGWIN=yes; AC_MSG_RESULT(yes)
      + AC_MSG_CHECKING(for CYGWIN clipboard support)
      + if test "x$with_x" = "xno" ; then
      + OS_EXTRA_SRC=winclip.c; OS_EXTRA_OBJ=objects/winclip.o
      + AC_MSG_RESULT(yes)
      + AC_DEFINE(FEAT_CYGWIN_WIN32_CLIPBOARD)
      + else
      + AC_MSG_RESULT(no - using X11)
      + fi ;;

      + *) CYGWIN=no; AC_MSG_RESULT(no);;
      +esac
      +
      dnl Only really enable hangul input when GUI and XFONTSET are available
      if test "$enable_hangulinput" = "yes"; then
      if test "x$GUITYPE" = "xNONE"; then
      Index: Make_ming.mak
      ===================================================================
      --- Make_ming.mak (revision 296)
      +++ Make_ming.mak (working copy)
      @@ -388,6 +388,7 @@
      $(OUTDIR)/option.o \
      $(OUTDIR)/os_win32.o \
      $(OUTDIR)/os_mswin.o \
      + $(OUTDIR)/winclip.o \
      $(OUTDIR)/pathdef.o \
      $(OUTDIR)/popupmnu.o \
      $(OUTDIR)/quickfix.o \
      Index: proto/winclip.pro
      ===================================================================
      --- proto/winclip.pro (revision 0)
      +++ proto/winclip.pro (revision 0)
      @@ -0,0 +1,13 @@
      +/* winclip.c */
      +int utf8_to_ucs2 __ARGS((char_u *instr, int inlen, short_u *outstr,
      int *unconvlenp));
      +int ucs2_to_utf8 __ARGS((short_u *instr, int inlen, char_u *outstr));
      +void MultiByteToWideChar_alloc __ARGS((UINT cp, DWORD flags, LPCSTR
      in, int inlen, LPWSTR *out, int *outlen));
      +void WideCharToMultiByte_alloc __ARGS((UINT cp, DWORD flags, LPCWSTR
      in, int inlen, LPSTR *out, int *outlen, LPCSTR def, LPBOOL useddef));
      +int clip_mch_own_selection __ARGS((VimClipboard *cbd));
      +void clip_mch_lose_selection __ARGS((VimClipboard *cbd));
      +short_u *enc_to_ucs2 __ARGS((char_u *str, int *lenp));
      +char_u *ucs2_to_enc __ARGS((short_u *str, int *lenp));
      +void clip_mch_request_selection __ARGS((VimClipboard *cbd));
      +void acp_to_enc __ARGS((char_u *str, int str_size, char_u **out, int *outlen));
      +void clip_mch_set_selection __ARGS((VimClipboard *cbd));
      +/* vim: set ft=c : */
      Index: proto/os_mswin.pro
      ===================================================================
      --- proto/os_mswin.pro (revision 296)
      +++ proto/os_mswin.pro (working copy)
      @@ -22,17 +22,6 @@
      int can_end_termcap_mode __ARGS((int give_msg));
      int mch_screenmode __ARGS((char_u *arg));
      int mch_libcall __ARGS((char_u *libname, char_u *funcname, char_u
      *argstring, int argint, char_u **string_result, int *number_result));
      -int utf8_to_ucs2 __ARGS((char_u *instr, int inlen, short_u *outstr,
      int *unconvlenp));
      -int ucs2_to_utf8 __ARGS((short_u *instr, int inlen, char_u *outstr));
      -void MultiByteToWideChar_alloc __ARGS((UINT cp, DWORD flags, LPCSTR
      in, int inlen, LPWSTR *out, int *outlen));
      -void WideCharToMultiByte_alloc __ARGS((UINT cp, DWORD flags, LPCWSTR
      in, int inlen, LPSTR *out, int *outlen, LPCSTR def, LPBOOL useddef));
      -int clip_mch_own_selection __ARGS((VimClipboard *cbd));
      -void clip_mch_lose_selection __ARGS((VimClipboard *cbd));
      -short_u *enc_to_ucs2 __ARGS((char_u *str, int *lenp));
      -char_u *ucs2_to_enc __ARGS((short_u *str, int *lenp));
      -void clip_mch_request_selection __ARGS((VimClipboard *cbd));
      -void acp_to_enc __ARGS((char_u *str, int str_size, char_u **out, int *outlen));
      -void clip_mch_set_selection __ARGS((VimClipboard *cbd));
      void DumpPutS __ARGS((const char *psz));
      int mch_get_winpos __ARGS((int *x, int *y));
      void mch_set_winpos __ARGS((int x, int y));
      Index: vim.h
      ===================================================================
      --- vim.h (revision 296)
      +++ vim.h (working copy)
      @@ -1739,7 +1739,7 @@
      GdkAtom gtk_sel_atom; /* PRIMARY/CLIPBOARD selection ID */
      # endif

      -# ifdef MSWIN
      +# if defined(MSWIN) || defined(FEAT_CYGWIN_WIN32_CLIPBOARD)
      int_u format; /* Vim's own special clipboard format */
      int_u format_raw; /* Vim's raw text clipboard format */
      # endif
      Index: Make_w16.mak
      ===================================================================
      --- Make_w16.mak (revision 296)
      +++ Make_w16.mak (working copy)
      @@ -107,6 +107,7 @@
      $(INTDIR)\os_win16.obj\
      $(INTDIR)\os_msdos.obj\
      $(INTDIR)\os_mswin.obj\
      + $(INTDIR)\winclip.obj\
      $(INTDIR)\popupmnu.obj\
      $(INTDIR)\quickfix.obj\
      $(INTDIR)\regexp.obj\
      Index: Make_bc5.mak
      ===================================================================
      --- Make_bc5.mak (revision 296)
      +++ Make_bc5.mak (working copy)
      @@ -638,7 +638,7 @@

      !if ($(OSTYPE)==WIN32)
      vimobj = $(vimobj) \
      - $(OBJDIR)\os_win32.obj $(OBJDIR)\os_mswin.obj
      + $(OBJDIR)\os_win32.obj $(OBJDIR)\os_mswin.obj $(OBJDIR)\winclip.obj
      !elif ($(OSTYPE)==DOS16)
      vimobj = $(vimobj) \
      $(OBJDIR)\os_msdos.obj
      Index: feature.h
      ===================================================================
      --- feature.h (revision 296)
      +++ feature.h (working copy)
      @@ -1050,6 +1050,11 @@
      * +xterm_clipboard Unix only: Include code for handling the clipboard
      * in an xterm like in the GUI.
      */
      +
      +#ifdef FEAT_CYGWIN_WIN32_CLIPBOARD
      +# define FEAT_CLIPBOARD
      +#endif
      +
      #ifdef FEAT_GUI
      # ifndef FEAT_CLIPBOARD
      # define FEAT_CLIPBOARD
      Index: proto.h
      ===================================================================
      --- proto.h (revision 296)
      +++ proto.h (working copy)
      @@ -47,10 +47,12 @@
      typedef int LPBOOL;
      # include "os_win16.pro"
      # include "os_mswin.pro"
      +# include "winclip.pro"
      # endif
      # ifdef WIN3264
      # include "os_win32.pro"
      # include "os_mswin.pro"
      +# include "winclip.pro"
      # if (defined(__GNUC__) && !defined(__MINGW32__)) \
      || (defined(__BORLANDC__) && __BORLANDC__ < 0x502)
      extern int _stricoll __ARGS((char *a, char *b));
      Index: Makefile
      ===================================================================
      --- Makefile (revision 296)
      +++ Makefile (working copy)
      @@ -1534,7 +1534,7 @@
      RSRC_DIR = os_mac_rsrc

      PRO_MANUAL = os_amiga.pro os_msdos.pro os_win16.pro os_win32.pro \
      - os_mswin.pro os_beos.pro os_vms.pro os_riscos.pro $(PERL_PRO)
      + os_mswin.pro winclip.pro os_beos.pro os_vms.pro os_riscos.pro $(PERL_PRO)

      # Default target is making the executable and tools
      all: $(VIMTARGET) $(TOOLS) languages $(GUI_BUNDLE)
      @@ -1675,6 +1675,10 @@
      cproto $(PFLAGS) -DWIN16 -DWIN32 -UHAVE_CONFIG_H $< > proto/$@
      echo "/* vim: set ft=c : */" >> proto/$@

      +winclip.pro: winclip.c
      + cproto $(PFLAGS) -DWIN16 -DWIN32 -UHAVE_CONFIG_H $< > proto/$@
      + echo "/* vim: set ft=c : */" >> proto/$@
      +
      os_beos.pro: os_beos.c
      cproto $(PFLAGS) -D__BEOS__ -UHAVE_CONFIG_H $< > proto/$@
      echo "/* vim: set ft=c : */" >> proto/$@
      @@ -2472,6 +2476,12 @@
      objects/os_unix.o: os_unix.c
      $(CCC) -o $@ os_unix.c

      +objects/os_mswin.o: os_mswin.c
      + $(CCC) -o $@ os_mswin.c
      +
      +objects/winclip.o: winclip.c
      + $(CCC) -o $@ winclip.c
      +
      objects/pathdef.o: auto/pathdef.c
      $(CCC) -o $@ auto/pathdef.c

      @@ -2795,6 +2805,10 @@
      ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
      gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \
      arabic.h version.h
      +objects/winclip.o: winclip.c vimio.h vim.h auto/config.h feature.h os_unix.h \
      + auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
      + regexp.h gui.h ex_cmds.h proto.h globals.h farsi.h arabic.h \
      + proto/winclip.pro
      objects/window.o: window.c vim.h auto/config.h feature.h os_unix.h
      auto/osdef.h \
      ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
      gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \
      Index: config.h.in
      ===================================================================
      --- config.h.in (revision 296)
      +++ config.h.in (working copy)
      @@ -372,3 +372,6 @@

      /* Define if you want XSMP interaction as well as vanilla swapfile safety */
      #undef USE_XSMP_INTERACT
      +
      +/* Define if you want Cygwin to use the WIN32 clipboard, not
      compatible with X11*/
      +#undef FEAT_CYGWIN_WIN32_CLIPBOARD
      Index: mbyte.c
      ===================================================================
      --- mbyte.c (revision 296)
      +++ mbyte.c (working copy)
      @@ -585,7 +585,7 @@
      enc_dbcs = enc_dbcs_new;
      has_mbyte = (enc_dbcs != 0 || enc_utf8);

      -#ifdef WIN3264
      +#if defined(WIN3264) || defined(FEAT_CYGWIN_WIN32_CLIPBOARD)
      enc_codepage = encname2codepage(p_enc);
      enc_latin9 = (STRCMP(p_enc, "iso-8859-15") == 0);
      #endif
      @@ -3127,7 +3127,7 @@
      return enc_canonize((char_u *)buf);
      }

      -#if defined(WIN3264) || defined(PROTO)
      +#if defined(WIN3264) || defined(PROTO) || defined(FEAT_CYGWIN_WIN32_CLIPBOARD)
      /*
      * Convert an encoding name to an MS-Windows codepage.
      * Returns zero if no codepage can be figured out.
      @@ -4414,7 +4414,7 @@
      /* If 'imdisable' is set, XIM is never active. */
      if (p_imdisable)
      active = FALSE;
      -#if !defined (FEAT_GUI_GTK)
      +#if !defined(FEAT_GUI_GTK)
      else if (input_style & XIMPreeditPosition)
      /* There is a problem in switching XIM off when preediting is used,
      * and it is not clear how this can be solved. For now, keep XIM on
      Index: os_unix.c
      ===================================================================
      --- os_unix.c (revision 296)
      +++ os_unix.c (working copy)
      @@ -1125,6 +1125,9 @@
      #ifdef MACOS_CONVERT
      mac_conv_init();
      #endif
      +#ifdef FEAT_CYGWIN_WIN32_CLIPBOARD
      + win_clip_init();
      +#endif
      }

      static void
      Index: os_mswin.c
      ===================================================================
      --- os_mswin.c (revision 296)
      +++ os_mswin.c (working copy)
      @@ -892,693 +892,8 @@
      }
      #endif

      -#if defined(FEAT_MBYTE) || defined(PROTO)
      -/*
      - * Convert an UTF-8 string to UCS-2.
      - * "instr[inlen]" is the input. "inlen" is in bytes.
      - * When "outstr" is NULL only return the number of UCS-2 words produced.
      - * Otherwise "outstr" must be a buffer of sufficient size.
      - * Returns the number of UCS-2 words produced.
      - */
      - int
      -utf8_to_ucs2(char_u *instr, int inlen, short_u *outstr, int *unconvlenp)
      -{
      - int outlen = 0;
      - char_u *p = instr;
      - int todo = inlen;
      - int l;

      - while (todo > 0)
      - {
      - /* Only convert if we have a complete sequence. */
      - l = utf_ptr2len_len(p, todo);
      - if (l > todo)
      - {
      - /* Return length of incomplete sequence. */
      - if (unconvlenp != NULL)
      - *unconvlenp = todo;
      - break;
      - }
      -
      - if (outstr != NULL)
      - *outstr++ = utf_ptr2char(p);
      - ++outlen;
      - p += l;
      - todo -= l;
      - }
      -
      - return outlen;
      -}
      -
      /*
      - * Convert an UCS-2 string to UTF-8.
      - * The input is "instr[inlen]" with "inlen" in number of ucs-2 words.
      - * When "outstr" is NULL only return the required number of bytes.
      - * Otherwise "outstr" must be a buffer of sufficient size.
      - * Return the number of bytes produced.
      - */
      - int
      -ucs2_to_utf8(short_u *instr, int inlen, char_u *outstr)
      -{
      - int outlen = 0;
      - int todo = inlen;
      - short_u *p = instr;
      - int l;
      -
      - while (todo > 0)
      - {
      - if (outstr != NULL)
      - {
      - l = utf_char2bytes(*p, outstr);
      - outstr += l;
      - }
      - else
      - l = utf_char2len(*p);
      - ++p;
      - outlen += l;
      - --todo;
      - }
      -
      - return outlen;
      -}
      -
      -/*
      - * Call MultiByteToWideChar() and allocate memory for the result.
      - * Returns the result in "*out[*outlen]" with an extra zero appended.
      - * "outlen" is in words.
      - */
      - void
      -MultiByteToWideChar_alloc(UINT cp, DWORD flags,
      - LPCSTR in, int inlen,
      - LPWSTR *out, int *outlen)
      -{
      - *outlen = MultiByteToWideChar(cp, flags, in, inlen, 0, 0);
      - /* Add one one word to avoid a zero-length alloc(). */
      - *out = (LPWSTR)alloc(sizeof(WCHAR) * (*outlen + 1));
      - if (*out != NULL)
      - {
      - MultiByteToWideChar(cp, flags, in, inlen, *out, *outlen);
      - (*out)[*outlen] = 0;
      - }
      -}
      -
      -/*
      - * Call WideCharToMultiByte() and allocate memory for the result.
      - * Returns the result in "*out[*outlen]" with an extra NUL appended.
      - */
      - void
      -WideCharToMultiByte_alloc(UINT cp, DWORD flags,
      - LPCWSTR in, int inlen,
      - LPSTR *out, int *outlen,
      - LPCSTR def, LPBOOL useddef)
      -{
      - *outlen = WideCharToMultiByte(cp, flags, in, inlen, NULL, 0, def, useddef);
      - /* Add one one byte to avoid a zero-length alloc(). */
      - *out = alloc((unsigned)*outlen + 1);
      - if (*out != NULL)
      - {
      - WideCharToMultiByte(cp, flags, in, inlen, *out, *outlen, def, useddef);
      - (*out)[*outlen] = 0;
      - }
      -}
      -
      -#endif /* FEAT_MBYTE */
      -
      -#ifdef FEAT_CLIPBOARD
      -/*
      - * Clipboard stuff, for cutting and pasting text to other windows.
      - */
      -
      -/* Type used for the clipboard type of Vim's data. */
      -typedef struct
      -{
      - int type; /* MCHAR, MBLOCK or MLINE */
      - int txtlen; /* length of CF_TEXT in bytes */
      - int ucslen; /* length of CF_UNICODETEXT in words */
      - int rawlen; /* length of clip_star.format_raw, including encoding,
      - excluding terminating NUL */
      -} VimClipType_t;
      -
      -/*
      - * Make vim the owner of the current selection. Return OK upon success.
      - */
      -/*ARGSUSED*/
      - int
      -clip_mch_own_selection(VimClipboard *cbd)
      -{
      - /*
      - * Never actually own the clipboard. If another application sets the
      - * clipboard, we don't want to think that we still own it.
      - */
      - return FAIL;
      -}
      -
      -/*
      - * Make vim NOT the owner of the current selection.
      - */
      -/*ARGSUSED*/
      - void
      -clip_mch_lose_selection(VimClipboard *cbd)
      -{
      - /* Nothing needs to be done here */
      -}
      -
      -/*
      - * Copy "str[*size]" into allocated memory, changing CR-NL to NL.
      - * Return the allocated result and the size in "*size".
      - * Returns NULL when out of memory.
      - */
      - static char_u *
      -crnl_to_nl(const char_u *str, int *size)
      -{
      - int pos = 0;
      - int str_len = *size;
      - char_u *ret;
      - char_u *retp;
      -
      - /* Avoid allocating zero bytes, it generates an error message. */
      - ret = lalloc((long_u)(str_len == 0 ? 1 : str_len), TRUE);
      - if (ret != NULL)
      - {
      - retp = ret;
      - for (pos = 0; pos < str_len; ++pos)
      - {
      - if (str[pos] == '\r' && str[pos + 1] == '\n')
      - {
      - ++pos;
      - --(*size);
      - }
      - *retp++ = str[pos];
      - }
      - }
      -
      - return ret;
      -}
      -
      -#if defined(FEAT_MBYTE) || defined(PROTO)
      -/*
      - * Note: the following two functions are only guaranteed to work when using
      - * valid MS-Windows codepages or when iconv() is available.
      - */
      -
      -/*
      - * Convert "str" from 'encoding' to UCS-2.
      - * Input in "str" with length "*lenp". When "lenp" is NULL, use strlen().
      - * Output is returned as an allocated string. "*lenp" is set to the length of
      - * the result. A trailing NUL is always added.
      - * Returns NULL when out of memory.
      - */
      - short_u *
      -enc_to_ucs2(char_u *str, int *lenp)
      -{
      - vimconv_T conv;
      - WCHAR *ret;
      - char_u *allocbuf = NULL;
      - int len_loc;
      - int length;
      -
      - if (lenp == NULL)
      - {
      - len_loc = (int)STRLEN(str) + 1;
      - lenp = &len_loc;
      - }
      -
      - if (enc_codepage > 0)
      - {
      - /* We can do any CP### -> UCS-2 in one pass, and we can do it
      - * without iconv() (convert_* may need iconv). */
      - MultiByteToWideChar_alloc(enc_codepage, 0, str, *lenp, &ret, &length);
      - }
      - else
      - {
      - /* Use "latin1" by default, we might be called before we have p_enc
      - * set up. Convert to utf-8 first, works better with iconv(). Does
      - * nothing if 'encoding' is "utf-8". */
      - conv.vc_type = CONV_NONE;
      - if (convert_setup(&conv, p_enc ? p_enc : (char_u *)"latin1",
      - (char_u *)"utf-8") == FAIL)
      - return NULL;
      - if (conv.vc_type != CONV_NONE)
      - {
      - str = allocbuf = string_convert(&conv, str, lenp);
      - if (str == NULL)
      - return NULL;
      - }
      - convert_setup(&conv, NULL, NULL);
      -
      - length = utf8_to_ucs2(str, *lenp, NULL, NULL);
      - ret = (WCHAR *)alloc((unsigned)((length + 1) * sizeof(WCHAR)));
      - if (ret != NULL)
      - {
      - utf8_to_ucs2(str, *lenp, (short_u *)ret, NULL);
      - ret[length] = 0;
      - }
      -
      - vim_free(allocbuf);
      - }
      -
      - *lenp = length;
      - return (short_u *)ret;
      -}
      -
      -/*
      - * Convert an UCS-2 string to 'encoding'.
      - * Input in "str" with length (counted in wide characters) "*lenp". When
      - * "lenp" is NULL, use wcslen().
      - * Output is returned as an allocated string. If "*lenp" is not NULL it is
      - * set to the length of the result.
      - * Returns NULL when out of memory.
      - */
      - char_u *
      -ucs2_to_enc(short_u *str, int *lenp)
      -{
      - vimconv_T conv;
      - char_u *utf8_str = NULL, *enc_str = NULL;
      - int len_loc;
      -
      - if (lenp == NULL)
      - {
      - len_loc = (int)wcslen(str) + 1;
      - lenp = &len_loc;
      - }
      -
      - if (enc_codepage > 0)
      - {
      - /* We can do any UCS-2 -> CP### in one pass. */
      - int length;
      -
      - WideCharToMultiByte_alloc(enc_codepage, 0, str, *lenp,
      - (LPSTR *)&enc_str, &length, 0, 0);
      - *lenp = length;
      - return enc_str;
      - }
      -
      - /* Avoid allocating zero bytes, it generates an error message. */
      - utf8_str = alloc(ucs2_to_utf8(str, *lenp == 0 ? 1 : *lenp, NULL));
      - if (utf8_str != NULL)
      - {
      - *lenp = ucs2_to_utf8(str, *lenp, utf8_str);
      -
      - /* We might be called before we have p_enc set up. */
      - conv.vc_type = CONV_NONE;
      - convert_setup(&conv, (char_u *)"utf-8",
      - p_enc? p_enc: (char_u *)"latin1");
      - if (conv.vc_type == CONV_NONE)
      - {
      - /* p_enc is utf-8, so we're done. */
      - enc_str = utf8_str;
      - }
      - else
      - {
      - enc_str = string_convert(&conv, utf8_str, lenp);
      - vim_free(utf8_str);
      - }
      -
      - convert_setup(&conv, NULL, NULL);
      - }
      -
      - return enc_str;
      -}
      -#endif /* FEAT_MBYTE */
      -
      -/*
      - * Get the current selection and put it in the clipboard register.
      - *
      - * NOTE: Must use GlobalLock/Unlock here to ensure Win32s compatibility.
      - * On NT/W95 the clipboard data is a fixed global memory object and
      - * so its handle = its pointer.
      - * On Win32s, however, co-operation with the Win16 system means that
      - * the clipboard data is moveable and its handle is not a pointer at all,
      - * so we can't just cast the return value of GetClipboardData to (char_u*).
      - * <VN>
      - */
      - void
      -clip_mch_request_selection(VimClipboard *cbd)
      -{
      - VimClipType_t metadata = { -1, -1, -1, -1 };
      - HGLOBAL hMem = NULL;
      - char_u *str = NULL;
      -#if defined(FEAT_MBYTE) && defined(WIN3264)
      - char_u *to_free = NULL;
      -#endif
      -#ifdef FEAT_MBYTE
      - HGLOBAL rawh = NULL;
      -#endif
      - int str_size = 0;
      - int maxlen;
      - size_t n;
      -
      - /*
      - * Don't pass GetActiveWindow() as an argument to OpenClipboard() because
      - * then we can't paste back into the same window for some reason - webb.
      - */
      - if (!OpenClipboard(NULL))
      - return;
      -
      - /* Check for vim's own clipboard format first. This only gets the type of
      - * the data, still need to use CF_UNICODETEXT or CF_TEXT for the text. */
      - if (IsClipboardFormatAvailable(cbd->format))
      - {
      - VimClipType_t *meta_p;
      - HGLOBAL meta_h;
      -
      - /* We have metadata on the clipboard; try to get it. */
      - if ((meta_h = GetClipboardData(cbd->format)) != NULL
      - && (meta_p = (VimClipType_t *)GlobalLock(meta_h)) != NULL)
      - {
      - /* The size of "VimClipType_t" changed, "rawlen" was added later.
      - * Only copy what is available for backwards compatibility. */
      - n = sizeof(VimClipType_t);
      - if (GlobalSize(meta_h) < n)
      - n = GlobalSize(meta_h);
      - memcpy(&metadata, meta_p, n);
      - GlobalUnlock(meta_h);
      - }
      - }
      -
      -#ifdef FEAT_MBYTE
      - /* Check for Vim's raw clipboard format first. This is used without
      - * conversion, but only if 'encoding' matches. */
      - if (IsClipboardFormatAvailable(cbd->format_raw)
      - && metadata.rawlen > (int)STRLEN(p_enc))
      - {
      - /* We have raw data on the clipboard; try to get it. */
      - if ((rawh = GetClipboardData(cbd->format_raw)) != NULL)
      - {
      - char_u *rawp;
      -
      - rawp = (char_u *)GlobalLock(rawh);
      - if (rawp != NULL && STRCMP(p_enc, rawp) == 0)
      - {
      - n = STRLEN(p_enc) + 1;
      - str = rawp + n;
      - str_size = (int)(metadata.rawlen - n);
      - }
      - else
      - {
      - GlobalUnlock(rawh);
      - rawh = NULL;
      - }
      - }
      - }
      - if (str == NULL)
      - {
      -#endif
      -
      -#if defined(FEAT_MBYTE) && defined(WIN3264)
      - /* Try to get the clipboard in Unicode if it's not an empty string. */
      - if (IsClipboardFormatAvailable(CF_UNICODETEXT) && metadata.ucslen != 0)
      - {
      - HGLOBAL hMemW;
      -
      - if ((hMemW = GetClipboardData(CF_UNICODETEXT)) != NULL)
      - {
      - WCHAR *hMemWstr = (WCHAR *)GlobalLock(hMemW);
      -
      - /* Use the length of our metadata if possible, but limit it to the
      - * GlobalSize() for safety. */
      - maxlen = (int)(GlobalSize(hMemW) / sizeof(WCHAR));
      - if (metadata.ucslen >= 0)
      - {
      - if (metadata.ucslen > maxlen)
      - str_size = maxlen;
      - else
      - str_size = metadata.ucslen;
      - }
      - else
      - {
      - for (str_size = 0; str_size < maxlen; ++str_size)
      - if (hMemWstr[str_size] == NUL)
      - break;
      - }
      - to_free = str = ucs2_to_enc((short_u *)hMemWstr, &str_size);
      - GlobalUnlock(hMemW);
      - }
      - }
      - else
      -#endif
      - /* Get the clipboard in the Active codepage. */
      - if (IsClipboardFormatAvailable(CF_TEXT))
      - {
      - if ((hMem = GetClipboardData(CF_TEXT)) != NULL)
      - {
      - str = (char_u *)GlobalLock(hMem);
      -
      - /* The length is either what our metadata says or the strlen().
      - * But limit it to the GlobalSize() for safety. */
      - maxlen = (int)GlobalSize(hMem);
      - if (metadata.txtlen >= 0)
      - {
      - if (metadata.txtlen > maxlen)
      - str_size = maxlen;
      - else
      - str_size = metadata.txtlen;
      - }
      - else
      - {
      - for (str_size = 0; str_size < maxlen; ++str_size)
      - if (str[str_size] == NUL)
      - break;
      - }
      -
      -# if defined(FEAT_MBYTE) && defined(WIN3264)
      - /* The text is in the active codepage. Convert to 'encoding',
      - * going through UCS-2. */
      - acp_to_enc(str, str_size, &to_free, &maxlen);
      - if (to_free != NULL)
      - {
      - str_size = maxlen;
      - str = to_free;
      - }
      -# endif
      - }
      - }
      -#ifdef FEAT_MBYTE
      - }
      -#endif
      -
      - if (str != NULL && *str != NUL)
      - {
      - char_u *temp_clipboard;
      -
      - /* If the type is not known guess it. */
      - if (metadata.type == -1)
      - metadata.type = (vim_strchr(str, '\n') == NULL) ? MCHAR : MLINE;
      -
      - /* Translate <CR><NL> into <NL>. */
      - temp_clipboard = crnl_to_nl(str, &str_size);
      - if (temp_clipboard != NULL)
      - {
      - clip_yank_selection(metadata.type, temp_clipboard, str_size, cbd);
      - vim_free(temp_clipboard);
      - }
      - }
      -
      - /* unlock the global object */
      - if (hMem != NULL)
      - GlobalUnlock(hMem);
      -#ifdef FEAT_MBYTE
      - if (rawh != NULL)
      - GlobalUnlock(rawh);
      -#endif
      - CloseClipboard();
      -#if defined(FEAT_MBYTE) && defined(WIN3264)
      - vim_free(to_free);
      -#endif
      -}
      -
      -#if (defined(FEAT_MBYTE) && defined(WIN3264)) || defined(PROTO)
      -/*
      - * Convert from the active codepage to 'encoding'.
      - * Input is "str[str_size]".
      - * The result is in allocated memory: "out[outlen]". With terminating NUL.
      - */
      - void
      -acp_to_enc(str, str_size, out, outlen)
      - char_u *str;
      - int str_size;
      - char_u **out;
      - int *outlen;
      -
      -{
      - LPWSTR widestr;
      -
      - MultiByteToWideChar_alloc(GetACP(), 0, str, str_size, &widestr, outlen);
      - if (widestr != NULL)
      - {
      - ++*outlen; /* Include the 0 after the string */
      - *out = ucs2_to_enc((short_u *)widestr, outlen);
      - vim_free(widestr);
      - }
      -}
      -#endif
      -
      -/*
      - * Send the current selection to the clipboard.
      - */
      - void
      -clip_mch_set_selection(VimClipboard *cbd)
      -{
      - char_u *str = NULL;
      - VimClipType_t metadata;
      - long_u txtlen;
      - HGLOBAL hMemRaw = NULL;
      - HGLOBAL hMem = NULL;
      - HGLOBAL hMemVim = NULL;
      -# if defined(FEAT_MBYTE) && defined(WIN3264)
      - HGLOBAL hMemW = NULL;
      -# endif
      -
      - /* If the '*' register isn't already filled in, fill it in now */
      - cbd->owned = TRUE;
      - clip_get_selection(cbd);
      - cbd->owned = FALSE;
      -
      - /* Get the text to be put on the clipboard, with CR-LF. */
      - metadata.type = clip_convert_selection(&str, &txtlen, cbd);
      - if (metadata.type < 0)
      - return;
      - metadata.txtlen = (int)txtlen;
      - metadata.ucslen = 0;
      - metadata.rawlen = 0;
      -
      -#ifdef FEAT_MBYTE
      - /* Always set the raw bytes: 'encoding', NUL and the text. This is used
      - * when copy/paste from/to Vim with the same 'encoding', so that illegal
      - * bytes can also be copied and no conversion is needed. */
      - {
      - LPSTR lpszMemRaw;
      -
      - metadata.rawlen = (int)(txtlen + STRLEN(p_enc) + 1);
      - hMemRaw = (LPSTR)GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
      - metadata.rawlen + 1);
      - lpszMemRaw = (LPSTR)GlobalLock(hMemRaw);
      - if (lpszMemRaw != NULL)
      - {
      - STRCPY(lpszMemRaw, p_enc);
      - memcpy(lpszMemRaw + STRLEN(p_enc) + 1, str, txtlen + 1);
      - GlobalUnlock(hMemRaw);
      - }
      - else
      - metadata.rawlen = 0;
      - }
      -#endif
      -
      -# if defined(FEAT_MBYTE) && defined(WIN3264)
      - {
      - WCHAR *out;
      - int len = metadata.txtlen;
      -
      - /* Convert the text to UCS-2. This is put on the clipboard as
      - * CF_UNICODETEXT. */
      - out = (WCHAR *)enc_to_ucs2(str, &len);
      - if (out != NULL)
      - {
      - WCHAR *lpszMemW;
      -
      - /* Convert the text for CF_TEXT to Active codepage. Otherwise it's
      - * p_enc, which has no relation to the Active codepage. */
      - metadata.txtlen = WideCharToMultiByte(GetACP(), 0, out, len,
      - NULL, 0, 0, 0);
      - vim_free(str);
      - str = (char_u *)alloc((unsigned)(metadata.txtlen == 0 ? 1
      - : metadata.txtlen));
      - if (str == NULL)
      - {
      - vim_free(out);
      - return; /* out of memory */
      - }
      - WideCharToMultiByte(GetACP(), 0, out, len,
      - str, metadata.txtlen, 0, 0);
      -
      - /* Allocate memory for the UCS-2 text, add one NUL word to
      - * terminate the string. */
      - hMemW = (LPSTR)GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
      - (len + 1) * sizeof(WCHAR));
      - lpszMemW = (WCHAR *)GlobalLock(hMemW);
      - if (lpszMemW != NULL)
      - {
      - memcpy(lpszMemW, out, len * sizeof(WCHAR));
      - lpszMemW[len] = NUL;
      - GlobalUnlock(hMemW);
      - }
      - vim_free(out);
      - metadata.ucslen = len;
      - }
      - }
      -# endif
      -
      - /* Allocate memory for the text, add one NUL byte to terminate the string.
      - */
      - hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, metadata.txtlen + 1);
      - {
      - LPSTR lpszMem = (LPSTR)GlobalLock(hMem);
      -
      - if (lpszMem)
      - {
      - vim_strncpy(lpszMem, str, metadata.txtlen);
      - GlobalUnlock(hMem);
      - }
      - }
      -
      - /* Set up metadata: */
      - {
      - VimClipType_t *lpszMemVim = NULL;
      -
      - hMemVim = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,
      - sizeof(VimClipType_t));
      - lpszMemVim = (VimClipType_t *)GlobalLock(hMemVim);
      - memcpy(lpszMemVim, &metadata, sizeof(metadata));
      - GlobalUnlock(hMemVim);
      - }
      -
      - /*
      - * Open the clipboard, clear it and put our text on it.
      - * Always set our Vim format. Put Unicode and plain text on it.
      - *
      - * Don't pass GetActiveWindow() as an argument to OpenClipboard()
      - * because then we can't paste back into the same window for some
      - * reason - webb.
      - */
      - if (OpenClipboard(NULL))
      - {
      - if (EmptyClipboard())
      - {
      - SetClipboardData(cbd->format, hMemVim);
      - hMemVim = 0;
      -# if defined(FEAT_MBYTE) && defined(WIN3264)
      - if (hMemW != NULL)
      - {
      - if (SetClipboardData(CF_UNICODETEXT, hMemW) != NULL)
      - hMemW = NULL;
      - }
      -# endif
      - /* Always use CF_TEXT. On Win98 Notepad won't obtain the
      - * CF_UNICODETEXT text, only CF_TEXT. */
      - SetClipboardData(CF_TEXT, hMem);
      - hMem = 0;
      - }
      - CloseClipboard();
      - }
      -
      - vim_free(str);
      - /* Free any allocations we didn't give to the clipboard: */
      - if (hMemRaw)
      - GlobalFree(hMemRaw);
      - if (hMem)
      - GlobalFree(hMem);
      -# if defined(FEAT_MBYTE) && defined(WIN3264)
      - if (hMemW)
      - GlobalFree(hMemW);
      -# endif
      - if (hMemVim)
      - GlobalFree(hMemVim);
      -}
      -
      -#endif /* FEAT_CLIPBOARD */
      -
      -
      -/*
      * Debugging helper: expose the MCH_WRITE_DUMP stuff to other modules
      */
      /*ARGSUSED*/
      Index: os_win32.c
      ===================================================================
      --- os_win32.c (revision 296)
      +++ os_win32.c (working copy)
      @@ -1677,16 +1677,7 @@
      set_option_value((char_u *)"grepprg", 0, (char_u *)"grep -n", 0);

      #ifdef FEAT_CLIPBOARD
      - clip_init(TRUE);
      -
      - /*
      - * Vim's own clipboard format recognises whether the text is char, line,
      - * or rectangular block. Only useful for copying between two Vims.
      - * "VimClipboard" was used for previous versions, using the first
      - * character to specify MCHAR, MLINE or MBLOCK.
      - */
      - clip_star.format = RegisterClipboardFormat("VimClipboard2");
      - clip_star.format_raw = RegisterClipboardFormat("VimRawBytes");
      + win_clip_init();
      #endif
      }

      @@ -2169,16 +2160,7 @@
      #endif

      #ifdef FEAT_CLIPBOARD
      - clip_init(TRUE);
      -
      - /*
      - * Vim's own clipboard format recognises whether the text is char, line, or
      - * rectangular block. Only useful for copying between two Vims.
      - * "VimClipboard" was used for previous versions, using the first
      - * character to specify MCHAR, MLINE or MBLOCK.
      - */
      - clip_star.format = RegisterClipboardFormat("VimClipboard2");
      - clip_star.format_raw = RegisterClipboardFormat("VimRawBytes");
      + win_clip_init();
      #endif

      /* This will be NULL on anything but NT 4.0 */
      Index: Make_ivc.mak
      ===================================================================
      --- Make_ivc.mak (revision 296)
      +++ Make_ivc.mak (working copy)
      @@ -240,6 +240,7 @@
      "$(INTDIR)/ops.obj" \
      "$(INTDIR)/option.obj" \
      "$(INTDIR)/os_mswin.obj" \
      + "$(INTDIR)/winclip.obj" \
      "$(INTDIR)/os_win32.obj" \
      "$(INTDIR)/popupmnu.obj" \
      "$(INTDIR)/quickfix.obj" \
      @@ -594,6 +595,10 @@
      # End Source File
      # Begin Source File

      +SOURCE=.\winclip.c
      +# End Source File
      +# Begin Source File
      +
      SOURCE=.\os_win32.c
      # End Source File
      # Begin Source File
      Index: Make_mvc.mak
      ===================================================================
      --- Make_mvc.mak (revision 296)
      +++ Make_mvc.mak (working copy)
      @@ -417,6 +417,7 @@
      $(OUTDIR)\ops.obj \
      $(OUTDIR)\option.obj \
      $(OUTDIR)\os_mswin.obj \
      + $(OUTDIR)\winclip.obj \
      $(OUTDIR)\os_win32.obj \
      $(OUTDIR)\pathdef.obj \
      $(OUTDIR)\popupmnu.obj \
      @@ -908,6 +909,8 @@

      $(OUTDIR)/os_mswin.obj: $(OUTDIR) os_mswin.c $(INCL)

      +$(OUTDIR)/winclip.obj: $(OUTDIR) winclip.c $(INCL)
      +
      $(OUTDIR)/os_win32.obj: $(OUTDIR) os_win32.c $(INCL) os_win32.h

      $(OUTDIR)/os_w32exe.obj: $(OUTDIR) os_w32exe.c $(INCL)
      @@ -1007,6 +1010,7 @@
      proto/ops.pro \
      proto/option.pro \
      proto/os_mswin.pro \
      + proto/winclip.pro \
      proto/os_win32.pro \
      proto/popupmnu.pro \
      proto/quickfix.pro \
      Index: auto/configure
      ===================================================================
      --- auto/configure (revision 296)
      +++ auto/configure (working copy)
      @@ -9265,7 +9265,30 @@



      +echo "$as_me:$LINENO: checking for CYGWIN environment" >&5
      +echo $ECHO_N "checking for CYGWIN environment... $ECHO_C" >&6
      +case `uname` in
      + CYGWIN*) CYGWIN=yes; echo "$as_me:$LINENO: result: yes" >&5
      +echo "${ECHO_T}yes" >&6
      + echo "$as_me:$LINENO: checking for CYGWIN clipboard
      support" >&5
      +echo $ECHO_N "checking for CYGWIN clipboard support... $ECHO_C" >&6
      + if test "x$with_x" = "xno" ; then
      + OS_EXTRA_SRC=winclip.c; OS_EXTRA_OBJ=objects/winclip.o
      + echo "$as_me:$LINENO: result: yes" >&5
      +echo "${ECHO_T}yes" >&6
      + cat >>confdefs.h <<\_ACEOF
      +#define FEAT_CYGWIN_WIN32_CLIPBOARD 1
      +_ACEOF

      + else
      + echo "$as_me:$LINENO: result: no - using X11" >&5
      +echo "${ECHO_T}no - using X11" >&6
      + fi ;;
      +
      + *) CYGWIN=no; echo "$as_me:$LINENO: result: no" >&5
      +echo "${ECHO_T}no" >&6;;
      +esac
      +
      if test "$enable_hangulinput" = "yes"; then
      if test "x$GUITYPE" = "xNONE"; then
      echo "$as_me:$LINENO: result: no GUI selected; hangul input has
      been disabled" >&5
      Index: winclip.c
      ===================================================================
      --- winclip.c (revision 0)
      +++ winclip.c (revision 0)
      @@ -0,0 +1,737 @@
      +/* vi:set ts=8 sts=4 sw=4:
      + *
      + * VIM - Vi IMproved by Bram Moolenaar
      + *
      + * Do ":help uganda" in Vim to read copying and usage conditions.
      + * Do ":help credits" in Vim to see a list of people who contributed.
      + * See README.txt for an overview of the Vim source code.
      + */
      +
      +/*
      + * winclip.c
      + *
      + * Routines common to both Win16 and Win32 for clipboard handling.
      + */
      +
      +#ifdef WIN16
      +# ifdef __BORLANDC__
      +# pragma warn -par
      +# pragma warn -ucp
      +# pragma warn -use
      +# pragma warn -aus
      +# endif
      +#endif
      +
      +#include "vimio.h"
      +#include "vim.h"
      +
      +/* compile only the clipboard handling features when
      + * compiling for cygwin posix environment.
      + */
      +#ifdef FEAT_CYGWIN_WIN32_CLIPBOARD
      +# define WIN3264
      +# define WIN32_LEAN_AND_MEAN
      +# include <windows.h>
      +# include "proto/winclip.pro"
      +#endif
      +
      +
      +#if defined(FEAT_MBYTE) || defined(PROTO)
      +/*
      + * Convert an UTF-8 string to UCS-2.
      + * "instr[inlen]" is the input. "inlen" is in bytes.
      + * When "outstr" is NULL only return the number of UCS-2 words produced.
      + * Otherwise "outstr" must be a buffer of sufficient size.
      + * Returns the number of UCS-2 words produced.
      + */
      + int
      +utf8_to_ucs2(char_u *instr, int inlen, short_u *outstr, int *unconvlenp)
      +{
      + int outlen = 0;
      + char_u *p = instr;
      + int todo = inlen;
      + int l;
      +
      + while (todo > 0)
      + {
      + /* Only convert if we have a complete sequence. */
      + l = utf_ptr2len_len(p, todo);
      + if (l > todo)
      + {
      + /* Return length of incomplete sequence. */
      + if (unconvlenp != NULL)
      + *unconvlenp = todo;
      + break;
      + }
      +
      + if (outstr != NULL)
      + *outstr++ = utf_ptr2char(p);
      + ++outlen;
      + p += l;
      + todo -= l;
      + }
      +
      + return outlen;
      +}
      +
      +/*
      + * Convert an UCS-2 string to UTF-8.
      + * The input is "instr[inlen]" with "inlen" in number of ucs-2 words.
      + * When "outstr" is NULL only return the required number of bytes.
      + * Otherwise "outstr" must be a buffer of sufficient size.
      + * Return the number of bytes produced.
      + */
      + int
      +ucs2_to_utf8(short_u *instr, int inlen, char_u *outstr)
      +{
      + int outlen = 0;
      + int todo = inlen;
      + short_u *p = instr;
      + int l;
      +
      + while (todo > 0)
      + {
      + if (outstr != NULL)
      + {
      + l = utf_char2bytes(*p, outstr);
      + outstr += l;
      + }
      + else
      + l = utf_char2len(*p);
      + ++p;
      + outlen += l;
      + --todo;
      + }
      +
      + return outlen;
      +}
      +
      +/*
      + * Call MultiByteToWideChar() and allocate memory for the result.
      + * Returns the result in "*out[*outlen]" with an extra zero appended.
      + * "outlen" is in words.
      + */
      + void
      +MultiByteToWideChar_alloc(UINT cp, DWORD flags,
      + LPCSTR in, int inlen,
      + LPWSTR *out, int *outlen)
      +{
      + *outlen = MultiByteToWideChar(cp, flags, in, inlen, 0, 0);
      + /* Add one one word to avoid a zero-length alloc(). */
      + *out = (LPWSTR)alloc(sizeof(WCHAR) * (*outlen + 1));
      + if (*out != NULL)
      + {
      + MultiByteToWideChar(cp, flags, in, inlen, *out, *outlen);
      + (*out)[*outlen] = 0;
      + }
      +}
      +
      +/*
      + * Call WideCharToMultiByte() and allocate memory for the result.
      + * Returns the result in "*out[*outlen]" with an extra NUL appended.
      + */
      + void
      +WideCharToMultiByte_alloc(UINT cp, DWORD flags,
      + LPCWSTR in, int inlen,
      + LPSTR *out, int *outlen,
      + LPCSTR def, LPBOOL useddef)
      +{
      + *outlen = WideCharToMultiByte(cp, flags, in, inlen, NULL, 0, def, useddef);
      + /* Add one one byte to avoid a zero-length alloc(). */
      + *out = alloc((unsigned)*outlen + 1);
      + if (*out != NULL)
      + {
      + WideCharToMultiByte(cp, flags, in, inlen, *out, *outlen, def, useddef);
      + (*out)[*outlen] = 0;
      + }
      +}
      +
      +#endif /* FEAT_MBYTE */
      +
      +#ifdef FEAT_CLIPBOARD
      +/*
      + * Clipboard stuff, for cutting and pasting text to other windows.
      + */
      +
      + void
      +win_clip_init(void)
      +{
      + clip_init(TRUE);
      +
      + /*
      + * Vim's own clipboard format recognises whether the text is char, line,
      + * or rectangular block. Only useful for copying between two Vims.
      + * "VimClipboard" was used for previous versions, using the first
      + * character to specify MCHAR, MLINE or MBLOCK.
      + */
      + clip_star.format = RegisterClipboardFormat("VimClipboard2");
      + clip_star.format_raw = RegisterClipboardFormat("VimRawBytes");
      +}
      +
      +/* Type used for the clipboard type of Vim's data. */
      +typedef struct
      +{
      + int type; /* MCHAR, MBLOCK or MLINE */
      + int txtlen; /* length of CF_TEXT in bytes */
      + int ucslen; /* length of CF_UNICODETEXT in words */
      + int rawlen; /* length of clip_star.format_raw, including encoding,
      + excluding terminating NUL */
      +} VimClipType_t;
      +
      +/*
      + * Make vim the owner of the current selection. Return OK upon success.
      + */
      +/*ARGSUSED*/
      + int
      +clip_mch_own_selection(VimClipboard *cbd)
      +{
      + /*
      + * Never actually own the clipboard. If another application sets the
      + * clipboard, we don't want to think that we still own it.
      + */
      + return FAIL;
      +}
      +
      +/*
      + * Make vim NOT the owner of the current selection.
      + */
      +/*ARGSUSED*/
      + void
      +clip_mch_lose_selection(VimClipboard *cbd)
      +{
      + /* Nothing needs to be done here */
      +}
      +
      +/*
      + * Copy "str[*size]" into allocated memory, changing CR-NL to NL.
      + * Return the allocated result and the size in "*size".
      + * Returns NULL when out of memory.
      + */
      + static char_u *
      +crnl_to_nl(const char_u *str, int *size)
      +{
      + int pos = 0;
      + int str_len = *size;
      + char_u *ret;
      + char_u *retp;
      +
      + /* Avoid allocating zero bytes, it generates an error message. */
      + ret = lalloc((long_u)(str_len == 0 ? 1 : str_len), TRUE);
      + if (ret != NULL)
      + {
      + retp = ret;
      + for (pos = 0; pos < str_len; ++pos)
      + {
      + if (str[pos] == '\r' && str[pos + 1] == '\n')
      + {
      + ++pos;
      + --(*size);
      + }
      + *retp++ = str[pos];
      + }
      + }
      +
      + return ret;
      +}
      +
      +#if defined(FEAT_MBYTE) || defined(PROTO)
      +/*
      + * Note: the following two functions are only guaranteed to work when using
      + * valid MS-Windows codepages or when iconv() is available.
      + */
      +
      +/*
      + * Convert "str" from 'encoding' to UCS-2.
      + * Input in "str" with length "*lenp". When "lenp" is NULL, use strlen().
      + * Output is returned as an allocated string. "*lenp" is set to the length of
      + * the result. A trailing NUL is always added.
      + * Returns NULL when out of memory.
      + */
      + short_u *
      +enc_to_ucs2(char_u *str, int *lenp)
      +{
      + vimconv_T conv;
      + WCHAR *ret;
      + char_u *allocbuf = NULL;
      + int len_loc;
      + int length;
      +
      + if (lenp == NULL)
      + {
      + len_loc = (int)STRLEN(str) + 1;
      + lenp = &len_loc;
      + }
      +
      + if (enc_codepage > 0)
      + {
      + /* We can do any CP### -> UCS-2 in one pass, and we can do it
      + * without iconv() (convert_* may need iconv). */
      + MultiByteToWideChar_alloc(enc_codepage, 0, str, *lenp, &ret, &length);
      + }
      + else
      + {
      + /* Use "latin1" by default, we might be called before we have p_enc
      + * set up. Convert to utf-8 first, works better with iconv(). Does
      + * nothing if 'encoding' is "utf-8". */
      + conv.vc_type = CONV_NONE;
      + if (convert_setup(&conv, p_enc ? p_enc : (char_u *)"latin1",
      + (char_u *)"utf-8") == FAIL)
      + return NULL;
      + if (conv.vc_type != CONV_NONE)
      + {
      + str = allocbuf = string_convert(&conv, str, lenp);
      + if (str == NULL)
      + return NULL;
      + }
      + convert_setup(&conv, NULL, NULL);
      +
      + length = utf8_to_ucs2(str, *lenp, NULL, NULL);
      + ret = (WCHAR *)alloc((unsigned)((length + 1) * sizeof(WCHAR)));
      + if (ret != NULL)
      + {
      + utf8_to_ucs2(str, *lenp, (short_u *)ret, NULL);
      + ret[length] = 0;
      + }
      +
      + vim_free(allocbuf);
      + }
      +
      + *lenp = length;
      + return (short_u *)ret;
      +}
      +
      +/*
      + * Convert an UCS-2 string to 'encoding'.
      + * Input in "str" with length (counted in wide characters) "*lenp". When
      + * "lenp" is NULL, use wcslen().
      + * Output is returned as an allocated string. If "*lenp" is not NULL it is
      + * set to the length of the result.
      + * Returns NULL when out of memory.
      + */
      + char_u *
      +ucs2_to_enc(short_u *str, int *lenp)
      +{
      + vimconv_T conv;
      + char_u *utf8_str = NULL, *enc_str = NULL;
      + int len_loc;
      +
      + if (lenp == NULL)
      + {
      + len_loc = (int)wcslen(str) + 1;
      + lenp = &len_loc;
      + }
      +
      + if (enc_codepage > 0)
      + {
      + /* We can do any UCS-2 -> CP### in one pass. */
      + int length;
      +
      + WideCharToMultiByte_alloc(enc_codepage, 0, str, *lenp,
      + (LPSTR *)&enc_str, &length, 0, 0);
      + *lenp = length;
      + return enc_str;
      + }
      +
      + /* Avoid allocating zero bytes, it generates an error message. */
      + utf8_str = alloc(ucs2_to_utf8(str, *lenp == 0 ? 1 : *lenp, NULL));
      + if (utf8_str != NULL)
      + {
      + *lenp = ucs2_to_utf8(str, *lenp, utf8_str);
      +
      + /* We might be called before we have p_enc set up. */
      + conv.vc_type = CONV_NONE;
      + convert_setup(&conv, (char_u *)"utf-8",
      + p_enc? p_enc: (char_u *)"latin1");
      + if (conv.vc_type == CONV_NONE)
      + {
      + /* p_enc is utf-8, so we're done. */
      + enc_str = utf8_str;
      + }
      + else
      + {
      + enc_str = string_convert(&conv, utf8_str, lenp);
      + vim_free(utf8_str);
      + }
      +
      + convert_setup(&conv, NULL, NULL);
      + }
      +
      + return enc_str;
      +}
      +#endif /* FEAT_MBYTE */
      +
      +/*
      + * Get the current selection and put it in the clipboard register.
      + *
      + * NOTE: Must use GlobalLock/Unlock here to ensure Win32s compatibility.
      + * On NT/W95 the clipboard data is a fixed global memory object and
      + * so its handle = its pointer.
      + * On Win32s, however, co-operation with the Win16 system means that
      + * the clipboard data is moveable and its handle is not a pointer at all,
      + * so we can't just cast the return value of GetClipboardData to (char_u*).
      + * <VN>
      + */
      + void
      +clip_mch_request_selection(VimClipboard *cbd)
      +{
      + VimClipType_t metadata = { -1, -1, -1, -1 };
      + HGLOBAL hMem = NULL;
      + char_u *str = NULL;
      +#if defined(FEAT_MBYTE) && defined(WIN3264)
      + char_u *to_free = NULL;
      +#endif
      +#ifdef FEAT_MBYTE
      + HGLOBAL rawh = NULL;
      +#endif
      + int str_size = 0;
      + int maxlen;
      + size_t n;
      +
      + /*
      + * Don't pass GetActiveWindow() as an argument to OpenClipboard() because
      + * then we can't paste back into the same window for some reason - webb.
      + */
      + if (!OpenClipboard(NULL))
      + return;
      +
      + /* Check for vim's own clipboard format first. This only gets the type of
      + * the data, still need to use CF_UNICODETEXT or CF_TEXT for the text. */
      + if (IsClipboardFormatAvailable(cbd->format))
      + {
      + VimClipType_t *meta_p;
      + HGLOBAL meta_h;
      +
      + /* We have metadata on the clipboard; try to get it. */
      + if ((meta_h = GetClipboardData(cbd->format)) != NULL
      + && (meta_p = (VimClipType_t *)GlobalLock(meta_h)) != NULL)
      + {
      + /* The size of "VimClipType_t" changed, "rawlen" was added later.
      + * Only copy what is available for backwards compatibility. */
      + n = sizeof(VimClipType_t);
      + if (GlobalSize(meta_h) < n)
      + n = GlobalSize(meta_h);
      + memcpy(&metadata, meta_p, n);
      + GlobalUnlock(meta_h);
      + }
      + }
      +
      +#ifdef FEAT_MBYTE
      + /* Check for Vim's raw clipboard format first. This is used without
      + * conversion, but only if 'encoding' matches. */
      + if (IsClipboardFormatAvailable(cbd->format_raw)
      + && metadata.rawlen > (int)STRLEN(p_enc))
      + {
      + /* We have raw data on the clipboard; try to get it. */
      + if ((rawh = GetClipboardData(cbd->format_raw)) != NULL)
      + {
      + char_u *rawp;
      +
      + rawp = (char_u *)GlobalLock(rawh);
      + if (rawp != NULL && STRCMP(p_enc, rawp) == 0)
      + {
      + n = STRLEN(p_enc) + 1;
      + str = rawp + n;
      + str_size = (int)(metadata.rawlen - n);
      + }
      + else
      + {
      + GlobalUnlock(rawh);
      + rawh = NULL;
      + }
      + }
      + }
      + if (str == NULL)
      + {
      +#endif
      +
      +#if defined(FEAT_MBYTE) && defined(WIN3264)
      + /* Try to get the clipboard in Unicode if it's not an empty string. */
      + if (IsClipboardFormatAvailable(CF_UNICODETEXT) && metadata.ucslen != 0)
      + {
      + HGLOBAL hMemW;
      +
      + if ((hMemW = GetClipboardData(CF_UNICODETEXT)) != NULL)
      + {
      + WCHAR *hMemWstr = (WCHAR *)GlobalLock(hMemW);
      +
      + /* Use the length of our metadata if possible, but limit it to the
      + * GlobalSize() for safety. */
      + maxlen = (int)(GlobalSize(hMemW) / sizeof(WCHAR));
      + if (metadata.ucslen >= 0)
      + {
      + if (metadata.ucslen > maxlen)
      + str_size = maxlen;
      + else
      + str_size = metadata.ucslen;
      + }
      + else
      + {
      + for (str_size = 0; str_size < maxlen; ++str_size)
      + if (hMemWstr[str_size] == NUL)
      + break;
      + }
      + to_free = str = ucs2_to_enc((short_u *)hMemWstr, &str_size);
      + GlobalUnlock(hMemW);
      + }
      + }
      + else
      +#endif
      + /* Get the clipboard in the Active codepage. */
      + if (IsClipboardFormatAvailable(CF_TEXT))
      + {
      + if ((hMem = GetClipboardData(CF_TEXT)) != NULL)
      + {
      + str = (char_u *)GlobalLock(hMem);
      +
      + /* The length is either what our metadata says or the strlen().
      + * But limit it to the GlobalSize() for safety. */
      + maxlen = (int)GlobalSize(hMem);
      + if (metadata.txtlen >= 0)
      + {
      + if (metadata.txtlen > maxlen)
      + str_size = maxlen;
      + else
      + str_size = metadata.txtlen;
      + }
      + else
      + {
      + for (str_size = 0; str_size < maxlen; ++str_size)
      + if (str[str_size] == NUL)
      + break;
      + }
      +
      +# if defined(FEAT_MBYTE) && defined(WIN3264)
      + /* The text is in the active codepage. Convert to 'encoding',
      + * going through UCS-2. */
      + acp_to_enc(str, str_size, &to_free, &maxlen);
      + if (to_free != NULL)
      + {
      + str_size = maxlen;
      + str = to_free;
      + }
      +# endif
      + }
      + }
      +#ifdef FEAT_MBYTE
      + }
      +#endif
      +
      + if (str != NULL && *str != NUL)
      + {
      + char_u *temp_clipboard;
      +
      + /* If the type is not known guess it. */
      + if (metadata.type == -1)
      + metadata.type = (vim_strchr(str, '\n') == NULL) ? MCHAR : MLINE;
      +
      + /* Translate <CR><NL> into <NL>. */
      + temp_clipboard = crnl_to_nl(str, &str_size);
      + if (temp_clipboard != NULL)
      + {
      + clip_yank_selection(metadata.type, temp_clipboard, str_size, cbd);
      + vim_free(temp_clipboard);
      + }
      + }
      +
      + /* unlock the global object */
      + if (hMem != NULL)
      + GlobalUnlock(hMem);
      +#ifdef FEAT_MBYTE
      + if (rawh != NULL)
      + GlobalUnlock(rawh);
      +#endif
      + CloseClipboard();
      +#if defined(FEAT_MBYTE) && defined(WIN3264)
      + vim_free(to_free);
      +#endif
      +}
      +
      +#if (defined(FEAT_MBYTE) && defined(WIN3264)) || defined(PROTO)
      +/*
      + * Convert from the active codepage to 'encoding'.
      + * Input is "str[str_size]".
      + * The result is in allocated memory: "out[outlen]". With terminating NUL.
      + */
      + void
      +acp_to_enc(str, str_size, out, outlen)
      + char_u *str;
      + int str_size;
      + char_u **out;
      + int *outlen;
      +
      +{
      + LPWSTR widestr;
      +
      + MultiByteToWideChar_alloc(GetACP(), 0, str, str_size, &widestr, outlen);
      + if (widestr != NULL)
      + {
      + ++*outlen; /* Include the 0 after the string */
      + *out = ucs2_to_enc((short_u *)widestr, outlen);
      + vim_free(widestr);
      + }
      +}
      +#endif
      +
      +/*
      + * Send the current selection to the clipboard.
      + */
      + void
      +clip_mch_set_selection(VimClipboard *cbd)
      +{
      + char_u *str = NULL;
      + VimClipType_t metadata;
      + long_u txtlen;
      + HGLOBAL hMemRaw = NULL;
      + HGLOBAL hMem = NULL;
      + HGLOBAL hMemVim = NULL;
      +# if defined(FEAT_MBYTE) && defined(WIN3264)
      + HGLOBAL hMemW = NULL;
      +# endif
      +
      + /* If the '*' register isn't already filled in, fill it in now */
      + cbd->owned = TRUE;
      + clip_get_selection(cbd);
      + cbd->owned = FALSE;
      +
      + /* Get the text to be put on the clipboard, with CR-LF. */
      + metadata.type = clip_convert_selection(&str, &txtlen, cbd);
      + if (metadata.type < 0)
      + return;
      + metadata.txtlen = (int)txtlen;
      + metadata.ucslen = 0;
      + metadata.rawlen = 0;
      +
      +#ifdef FEAT_MBYTE
      + /* Always set the raw bytes: 'encoding', NUL and the text. This is used
      + * when copy/paste from/to Vim with the same 'encoding', so that illegal
      + * bytes can also be copied and no conversion is needed. */
      + {
      + LPSTR lpszMemRaw;
      +
      + metadata.rawlen = (int)(txtlen + STRLEN(p_enc) + 1);
      + hMemRaw = (LPSTR)GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
      + metadata.rawlen + 1);
      + lpszMemRaw = (LPSTR)GlobalLock(hMemRaw);
      + if (lpszMemRaw != NULL)
      + {
      + STRCPY(lpszMemRaw, p_enc);
      + memcpy(lpszMemRaw + STRLEN(p_enc) + 1, str, txtlen + 1);
      + GlobalUnlock(hMemRaw);
      + }
      + else
      + metadata.rawlen = 0;
      + }
      +#endif
      +
      +# if defined(FEAT_MBYTE) && defined(WIN3264)
      + {
      + WCHAR *out;
      + int len = metadata.txtlen;
      +
      + /* Convert the text to UCS-2. This is put on the clipboard as
      + * CF_UNICODETEXT. */
      + out = (WCHAR *)enc_to_ucs2(str, &len);
      + if (out != NULL)
      + {
      + WCHAR *lpszMemW;
      +
      + /* Convert the text for CF_TEXT to Active codepage. Otherwise it's
      + * p_enc, which has no relation to the Active codepage. */
      + metadata.txtlen = WideCharToMultiByte(GetACP(), 0, out, len,
      + NULL, 0, 0, 0);
      + vim_free(str);
      + str = (char_u *)alloc((unsigned)(metadata.txtlen == 0 ? 1
      + : metadata.txtlen));
      + if (str == NULL)
      + {
      + vim_free(out);
      + return; /* out of memory */
      + }
      + WideCharToMultiByte(GetACP(), 0, out, len,
      + str, metadata.txtlen, 0, 0);
      +
      + /* Allocate memory for the UCS-2 text, add one NUL word to
      + * terminate the string. */
      + hMemW = (LPSTR)GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
      + (len + 1) * sizeof(WCHAR));
      + lpszMemW = (WCHAR *)GlobalLock(hMemW);
      + if (lpszMemW != NULL)
      + {
      + memcpy(lpszMemW, out, len * sizeof(WCHAR));
      + lpszMemW[len] = NUL;
      + GlobalUnlock(hMemW);
      + }
      + vim_free(out);
      + metadata.ucslen = len;
      + }
      + }
      +# endif
      +
      + /* Allocate memory for the text, add one NUL byte to terminate the string.
      + */
      + hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, metadata.txtlen + 1);
      + {
      + LPSTR lpszMem = (LPSTR)GlobalLock(hMem);
      +
      + if (lpszMem)
      + {
      + vim_strncpy(lpszMem, str, metadata.txtlen);
      + GlobalUnlock(hMem);
      + }
      + }
      +
      + /* Set up metadata: */
      + {
      + VimClipType_t *lpszMemVim = NULL;
      +
      + hMemVim = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,
      + sizeof(VimClipType_t));
      + lpszMemVim = (VimClipType_t *)GlobalLock(hMemVim);
      + memcpy(lpszMemVim, &metadata, sizeof(metadata));
      + GlobalUnlock(hMemVim);
      + }
      +
      + /*
      + * Open the clipboard, clear it and put our text on it.
      + * Always set our Vim format. Put Unicode and plain text on it.
      + *
      + * Don't pass GetActiveWindow() as an argument to OpenClipboard()
      + * because then we can't paste back into the same window for some
      + * reason - webb.
      + */
      + if (OpenClipboard(NULL))
      + {
      + if (EmptyClipboard())
      + {
      + SetClipboardData(cbd->format, hMemVim);
      + hMemVim = 0;
      +# if defined(FEAT_MBYTE) && defined(WIN3264)
      + if (hMemW != NULL)
      + {
      + if (SetClipboardData(CF_UNICODETEXT, hMemW) != NULL)
      + hMemW = NULL;
      + }
      +# endif
      + /* Always use CF_TEXT. On Win98 Notepad won't obtain the
      + * CF_UNICODETEXT text, only CF_TEXT. */
      + SetClipboardData(CF_TEXT, hMem);
      + hMem = 0;
      + }
      + CloseClipboard();
      + }
      +
      + vim_free(str);
      + /* Free any allocations we didn't give to the clipboard: */
      + if (hMemRaw)
      + GlobalFree(hMemRaw);
      + if (hMem)
      + GlobalFree(hMem);
      +# if defined(FEAT_MBYTE) && defined(WIN3264)
      + if (hMemW)
      + GlobalFree(hMemW);
      +# endif
      + if (hMemVim)
      + GlobalFree(hMemVim);
      +}
      +
      +#endif /* FEAT_CLIPBOARD */
      Index: globals.h
      ===================================================================
      --- globals.h (revision 296)
      +++ globals.h (working copy)
      @@ -764,7 +764,7 @@
      EXTERN int enc_unicode INIT(= 0); /* 2: UCS-2 or UTF-16, 4: UCS-4 */
      EXTERN int enc_utf8 INIT(= FALSE); /* UTF-8 encoded Unicode */
      EXTERN int enc_latin1like INIT(= TRUE); /* 'encoding' is latin1 comp. */
      -# ifdef WIN3264
      +# if defined(WIN3264) || defined(FEAT_CYGWIN_WIN32_CLIPBOARD)
      /* Codepage nr of 'encoding'. Negative means it's not been set yet, zero
      * means 'encoding' is not a valid codepage. */
      EXTERN int enc_codepage INIT(= -1);
    • Show all 29 messages in this topic