# Win32API, clipboard, unicode issue

**URL:** <https://www.ruby-forum.com/t/win32api-clipboard-unicode-issue/53794>\
**Category:** Ruby\
**Created:** [February 14, 2006, 5:16pm UTC](https://www.ruby-forum.com/t/win32api-clipboard-unicode-issue/53794 "2006-02-14T17:16:28Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![BergerS\_Daniel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bc8723/32.png) [@BergerS\_Daniel](https://www.ruby-forum.com/u/BergerS_Daniel)\
**Post date:** [February 14, 2006, 5:16pm UTC](https://www.ruby-forum.com/t/win32api-clipboard-unicode-issue/53794/1 "2006-02-14T17:16:28Z")

</div>

Hi all,

I’m trying to resolve a unicode issue that I’m having some trouble  
dealing with. The problem, in short, is that some unicode values  
contain embedded nulls (e.g. the Tibetan 0x0F00), and that’s causing  
data truncation in the call to GetClipboardData(), even when UNICODETEXT  
is used as a format specifier. Note that _setting_ data works fine.  
It’s _getting_ data that’s failing.

Below is the relevant code, along with a sample program at the end. If  
you run the program and paste the results (via Ctrl-V) into a modern  
text editor (MS Word, OOO, whatever), you should see 3 characters.  
However, if you try to pull that data back out via Clipboard.get\_data,  
you’ll end up with a length two string.

Any ideas?

Regards,

Dan

require “Win32API”

module Win32  
class ClipboardError \< StandardError; end  
class Clipboard  
# Clipboard data types  
TEXT = 1  
OEMTEXT = 7  
UNICODETEXT = 13

```
  # Alloc constants
  GMEM_MOVEABLE = 0x0002
  GMEM_ZEROINIT = 0x0040
  GHND = GMEM_MOVEABLE | GMEM_ZEROINIT

  # Clipboard specific functions
  @@OpenClipboard = Win32API.new(
     'user32', 'OpenClipboard', ['L'], 'I'
  )

  @@CloseClipboard = Win32API.new(
     'user32', 'CloseClipboard', [], 'I'
  )

  @@GetClipboardData = Win32API.new(
     'user32', 'GetClipboardData', ['I'], 'P'
  )

  @@SetClipboardData = Win32API.new(
     'user32', 'SetClipboardData', ['I', 'I'], 'I'
  )

  @@EmptyClipboard = Win32API.new(
     'user32', 'EmptyClipboard', [], 'I'
  )

  # Generic Win32 functions
  @@GlobalAlloc =

```

Win32API.new(‘kernel32’,‘GlobalAlloc’,[‘I’,‘I’],‘I’)  
@@GlobalLock = Win32API.new(‘kernel32’,‘GlobalLock’,[‘I’],‘I’)  
@@GlobalFree = Win32API.new(‘kernel32’,‘GlobalFree’,[‘I’],‘I’)  
@@memcpy = Win32API.new(‘msvcrt’, ‘memcpy’, [‘I’, ‘P’, ‘I’],  
‘I’)

```
  def self.open
     if 0 == @@OpenClipboard.call(0)
        raise ClipboardError, "OpenClipboard() failed"
     end
  end

  def self.close
     @@CloseClipboard.call
  end

  # Sets the clipboard contents to the data that you specify. You

```

may  
# optionally specify a clipboard format. The default is  
Clipboard::TEXT.  
def self.set\_data(clip\_data, format = TEXT)  
self.open  
@@EmptyClipboard.call

```
     # NULL terminate text
     case format
        when TEXT, OEMTEXT, UNICODETEXT
           clip_data << "\0"
     end

     # Global Allocate a movable piece of memory.
     hmem = @@GlobalAlloc.call(GHND, clip_data.length + 4)
     mem = @@GlobalLock.call(hmem)
     @@memcpy.call(mem, clip_data, clip_data.length)

     # Set the new data
     if @@SetClipboardData.call(format, hmem) == 0
        @@GlobalFree.call(hmem)
        self.close
        raise ClipboardError, "SetClipboardData() failed"
     end

     @@GlobalFree.call(hmem)
     self.close
     self
  end

  # Returns the data currently in the clipboard. If 'format' is
  # specified, it will attempt to retrieve the data in that format.

```

The  
# default is Clipboard::TEXT.  
def self.data(format = TEXT)  
clipdata = “”  
self.open  
begin  
clipdata = @@GetClipboardData.call(format)  
rescue ArgumentError  
# Assume failure is caused by no data in clipboard  
end  
self.close  
clipdata  
end

```
  # An alias for Clipboard.data.
  def self.get_data(format = TEXT)
     self.data(format)
  end

  # Empties the contents of the clipboard.
  def self.empty
     self.open
     @@EmptyClipboard.call
     self.close
     self
  end

```

end  
end

require ‘win32/clipboard’  
include Win32

def unicopy(hex\_name\_array)

Clipboard.set\_data(win32unicode(hex\_name\_array),Clipboard::UNICODETEXT)  
true  
end

def extract\_flipped\_bytes(unicode\_char\_string)  
unicode\_char\_string[0,2].to\_i(16)  
end

def win32unicode(unicode\_char\_strings)  
flipped\_bytes = unicode\_char\_strings.collect do |str|  
extract\_flipped\_bytes(str)  
end  
flipped\_bytes.flatten.pack(‘C\*’)  
end

puts unicopy(%w{ 0401 0400 0402 })

p Clipboard.get\_data
