Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
--proc/system/clipboard: clipboard API
--Written by Cosmin Apreutesei. Public Domain.
setfenv(1, require'winapi')
require'winapi.memory'
-- Predefined Clipboard Formats
CF_NAMES = constants{
CF_TEXT = 1,
CF_BITMAP = 2, --only for DDBs, doesn't work with DIBs!
CF_METAFILEPICT = 3,
CF_SYLK = 4,
CF_DIF = 5,
CF_TIFF = 6,
CF_OEMTEXT = 7,
CF_DIB = 8, --DIB without alpha
CF_PALETTE = 9,
CF_PENDATA = 10,
CF_RIFF = 11,
CF_WAVE = 12,
CF_UNICODETEXT = 13,
CF_ENHMETAFILE = 14,
CF_HDROP = 15,
CF_LOCALE = 16,
CF_DIBV5 = 17, --DIB with alpha
CF_OWNERDISPLAY = 0x0080,
CF_DSPTEXT = 0x0081,
CF_DSPBITMAP = 0x0082,
CF_DSPMETAFILEPICT = 0x0083,
CF_DSPENHMETAFILE = 0x008E,
}
-- "Private" formats don't get GlobalFree()'d
CF_PRIVATEFIRST = 0x0200
CF_PRIVATELAST = 0x02FF
-- "GDIOBJ" formats do get DeleteObject()'d
CF_GDIOBJFIRST = 0x0300
CF_GDIOBJLAST = 0x03FF
ffi.cdef[[
BOOL OpenClipboard(HWND hWndNewOwner);
BOOL CloseClipboard(void);
BOOL IsClipboardFormatAvailable(UINT format);
int CountClipboardFormats(void);
HANDLE GetClipboardData(UINT uFormat);
BOOL EmptyClipboard(void);
HANDLE SetClipboardData(UINT uFormat, HANDLE hMem);
UINT EnumClipboardFormats(UINT format);
int GetClipboardFormatNameW(UINT format, LPWSTR lpszFormatName, int cchMaxCount);
UINT RegisterClipboardFormatW(LPWSTR lpszFormat);
]]
function OpenClipboard(hwnd)
return C.OpenClipboard(hwnd) ~= 0
end
function CloseClipboard(hwnd)
return checknz(C.CloseClipboard())
end
function IsClipboardFormatAvailable(format)
return C.IsClipboardFormatAvailable(flags(format)) ~= 0
end
function CountClipboardFormats()
return callnz2(C.CountClipboardFormats)
end
function GetClipboardData(uFormat)
return checkh(C.GetClipboardData(flags(uFormat)))
end
function EmptyClipboard()
checknz(C.EmptyClipboard())
end
function SetClipboardData(format, hmem)
return checkh(C.SetClipboardData(flags(format), hmem))
end
function EnumClipboardFormats(last_format)
local ret = callnz2(C.EnumClipboardFormats, last_format or 0)
return ret ~= 0 and ret or nil
end
function GetClipboardFormatName(format, buf, sz)
if not buf then buf, sz = WCS(sz) end
sz = checknz(C.GetClipboardFormatNameW(format, buf, sz))
return buf, sz
end
function RegisterClipboardFormat(name)
return checknz(C.RegisterClipboardFormatW(wcs(name)))
end
--hi-level API: get/set data from/to clipboard.
--custom functions, don't look them up in msdn.
--return a list of available clipboard formats, in original order.
function GetClipboardFormats()
local format
local t = {}
repeat
format = EnumClipboardFormats(format)
t[#t+1] = format
until not format
return t
end
--return a list of available clipboard format names, in original order.
--for built-in formats, the format number is returned instead.
function GetClipboardFormatNames()
local t = GetClipboardFormats()
local buf, sz
for i=1,#t do
local format = t[i]
local name
if CF_NAMES[format] then
name = format
else
if not buf then buf, sz = WCS() end
name = mbs(GetClipboardFormatName(format, buf, sz))
end
t[i] = name
end
return t
end
--get the data buffer of a specific format, pass it to a function,
--and return the result of that function.
function GetClipboardDataBuffer(format, copy)
if not IsClipboardFormatAvailable(format) then
return
end
return glue.fcall(function(finally)
local h = GetClipboardData(format)
local buf = GlobalLock(h)
if not buf then return end
finally(function() GlobalUnlock(h) end)
local sz = GlobalSize(h)
return copy(buf, sz)
end)
end
--set the clipboard data for a specific format from a buffer or string.
--you can pass a buffer and a size, or just the size and a copy function.
function SetClipboardDataBuffer(format, srcbuf, sz, copy)
--windows will own this memory, no need to free it.
glue.fcall(function(finally, onerror)
sz = sz or #buf
local h = GlobalAlloc(bit.bor(GMEM_MOVEABLE, GMEM_ZEROINIT, GMEM_SHARE), sz)
onerror(function() GlobalFree(h) end)
local buf = GlobalLock(h)
finally(function() GlobalUnlock(h) end)
if copy then
copy(buf, sz)
else
ffi.copy(buf, srcbuf, sz)
end
SetClipboardData(format, h)
end)
end
--get utf8 text out of the clipboard.
function GetClipboardText()
return GetClipboardDataBuffer(CF_UNICODETEXT, function(buf)
return mbs(ffi.cast('WCHAR*', buf))
end)
end
--set utf8 text into the clipboard.
function SetClipboardText(s)
local buf = wcs(s)
SetClipboardDataBuffer(CF_UNICODETEXT, buf, ffi.sizeof(buf))
end
--get a list of files from clipboard.
function GetClipboardFiles()
require'winapi.shellapi'
return GetClipboardDataBuffer(CF_HDROP, function(buf)
local hdrop = ffi.cast('HDROP', buf)
return DragQueryFiles(hdrop)
end)
end
--put a list of files in clipboard.
function SetClipboardFiles(files)
require'winapi.shellapi'
local df = DROPFILES(files)
return SetClipboardDataBuffer(CF_HDROP, df, ffi.sizeof(df))
end
--test/demo
if not ... then
if not OpenClipboard() then
error'OpenClipboard() failed'
end
print''
print'clipboard as found:'
print''
for i,format in ipairs(GetClipboardFormats()) do
local name
if CF_NAMES[format] then
name = CF_NAMES[format]
else
name = mbs(GetClipboardFormatName(format))
end
print('>' .. name)
if format == CF_UNICODETEXT then
print(GetClipboardText())
elseif format == CF_HDROP then
require'pp'(GetClipboardFiles())
else
GetClipboardDataBuffer(format, function(buf, sz)
print(buf, sz, name)
end)
end
end
print''
print'utf8 text:'
print''
local s = 'hello from the clipboard!'
EmptyClipboard()
SetClipboardText(s)
assert(#GetClipboardFormatNames() == 1)
assert(GetClipboardFormatNames()[1] == CF_UNICODETEXT)
assert(GetClipboardText() == s)
print(GetClipboardText())
print''
print'list of files:'
print''
EmptyClipboard()
SetClipboardFiles{'file1', 'file2', 'file3'}
assert(#GetClipboardFiles() == 3)
assert(GetClipboardFiles()[3] == 'file3')
require'pp'(GetClipboardFiles())
CloseClipboard()
end