Forum: Ruby Win32API, clipboard, unicode issue

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Berger, Daniel (Guest)
on 2006-02-14 18:16
(Received via mailing list)
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
This topic is locked and can not be replied to.