# frozen_string_literal: true require_relative "utils" module Clipboard module Windows extend self CF_TEXT = 1 CF_UNICODETEXT = 13 GMEM_MOVEABLE = 2 # get ffi function handlers begin require 'ffi' rescue LoadError raise LoadError, 'Could not load the required ffi gem, install it with: gem install ffi' end module User32 extend FFI::Library ffi_lib "user32" ffi_convention :stdcall attach_function :open, :OpenClipboard, [ :long ], :long attach_function :close, :CloseClipboard, [ ], :long attach_function :empty, :EmptyClipboard, [ ], :long attach_function :get, :GetClipboardData, [ :long ], :long attach_function :set, :SetClipboardData, [ :long, :long ], :long end module Kernel32 extend FFI::Library ffi_lib 'kernel32' ffi_convention :stdcall attach_function :lock, :GlobalLock, [ :long ], :pointer attach_function :unlock, :GlobalUnlock, [ :long ], :long attach_function :size, :GlobalSize, [ :long ], :long attach_function :alloc, :GlobalAlloc, [ :long, :long ], :long end # see http://www.codeproject.com/KB/clipboard/archerclipboard1.aspx def paste(_ = nil) data = "".dup if 0 != User32.open( 0 ) hclip = User32.get( CF_UNICODETEXT ) if hclip && 0 != hclip pointer_to_data = Kernel32.lock( hclip ) # Windows Unicode is ended by two null bytes, so get the whole string size = Kernel32.size( hclip ) data << pointer_to_data.get_bytes( 0, size - 2 ) data.force_encoding("UTF-16LE") Kernel32.unlock( hclip ) end User32.close( ) end data end def clear if 0 != User32.open( 0 ) User32.empty( ) User32.close( ) end paste end def copy(data_to_copy) if 0 != User32.open( 0 ) User32.empty( ) data = data_to_copy.encode("UTF-16LE") # TODO: catch bad encodings data << 0 handler = Kernel32.alloc( GMEM_MOVEABLE, data.bytesize ) pointer_to_data = Kernel32.lock( handler ) pointer_to_data.put_bytes( 0, data, 0, data.bytesize ) Kernel32.unlock( handler ) User32.set( CF_UNICODETEXT, handler ) User32.close( ) else # don't touch anything Utils.popen "clip", data_to_copy # depends on clip (available by default since Vista) end paste end end end