From: ··········@medialab.com
Subject: CLISP and win32 clipboard access
Date: 
Message-ID: <1143570090.190399.131340@i39g2000cwa.googlegroups.com>
I can't tell for sure, but CLISP seems to have some win32 api access
glue.  Is there enough built-in to allow clipboard access?

Ideally I'm looking for something fairly hight level, specifically
get-clipboard-string and set-clipboard-string.

I saw there was something like this for Corman lisp, but I'm working in
CLISP and would really like to stay there.

If CLISP can't do it out of the box, can it do it by calling through to
emacs in some way? (I'm using the CLISP Lisp-in-a-box.)

Any information would be greatly appreciated as my hours of googling
"clisp win32" etc have produced little except the gui widget toolkit
which seems only to have basic window and control support.

I suppose I could write a c extension to CLISP to do this, but I don't
think anyone here wants to see the tsunami of questions on this list
that could potentially generate.  :-)

Thanks!

Tom

From: Pascal Bourguignon
Subject: Re: CLISP and win32 clipboard access
Date: 
Message-ID: <87psk6e85p.fsf@thalassa.informatimago.com>
··········@medialab.com writes:

> I can't tell for sure, but CLISP seems to have some win32 api access
> glue.  Is there enough built-in to allow clipboard access?
>
> Ideally I'm looking for something fairly hight level, specifically
> get-clipboard-string and set-clipboard-string.
>
> I saw there was something like this for Corman lisp, but I'm working in
> CLISP and would really like to stay there.
>
> If CLISP can't do it out of the box, can it do it by calling through to
> emacs in some way? (I'm using the CLISP Lisp-in-a-box.)
>
> Any information would be greatly appreciated as my hours of googling
> "clisp win32" etc have produced little except the gui widget toolkit
> which seems only to have basic window and control support.
>
> I suppose I could write a c extension to CLISP to do this, but I don't
> think anyone here wants to see the tsunami of questions on this list
> that could potentially generate.  :-)

clisp has a good FFI, so you should be able to call MS-Windows
functions directly.  You'll just have to declare the external routine
with: FFI:DEF-CALL-OUT

See: http://clisp.cons.org/impnotes/dffi.html
See: http://clisp.cons.org/impnotes/

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

In a World without Walls and Fences, 
who needs Windows and Gates?
From: ··········@medialab.com
Subject: Re: CLISP and win32 clipboard access
Date: 
Message-ID: <1143573213.363977.16920@z34g2000cwc.googlegroups.com>
I just found a very promising thread from last year in the CLISP list,
but it doesn't seem to have gone anywhere.

Arseny Slobodyuk posted:
 "I"ve implemented following functions on Windows
 /* (EXT::SETCLIPBOARD str)
...
 /* (EXT::GETCLIPBOARD)"

Which is perfect.  Then there is a brief discussion about the way in
which this should be added to CLISP, but it appears to have never
happened.
From: ··········@medialab.com
Subject: Re: CLISP and win32 clipboard access
Date: 
Message-ID: <1143635720.236413.214280@i39g2000cwa.googlegroups.com>
I notice that this example works:

(use-package "FFI")
(def-call-out messagebox
              (:name "MessageBoxA") (:library "user32.dll")
              (:arguments (hwnd int) (text c-string) (capt c-string)
(type uint))
              (:return-type int)
              (:language :stdc))

Would it be possible to do something like this from within CLISP
without having to recompile?

I tried this but got only NIL as the return value:

(def-call-out clipget
              (:name "GetClipboardData") (:library "user32.dll")
	      (:arguments (type uint))
	      (:return-type int)
	      (:language :stdc))

Is this the right direction to go in at least?
From: Pascal Bourguignon
Subject: Re: CLISP and win32 clipboard access
Date: 
Message-ID: <87hd5h4cww.fsf@thalassa.informatimago.com>
··········@medialab.com writes:

> I notice that this example works:
>
> (use-package "FFI")
> (def-call-out messagebox
>               (:name "MessageBoxA") (:library "user32.dll")
>               (:arguments (hwnd int) (text c-string) (capt c-string)
> (type uint))
>               (:return-type int)
>               (:language :stdc))
>
> Would it be possible to do something like this from within CLISP
> without having to recompile?

Yes.


> I tried this but got only NIL as the return value:

That should not possible. DEF-CALL-OUT returns the name of the lisp
function defined (a symbol, CLIPGET in this case), and the function
CLIPGET should return an integer.

> (def-call-out clipget
>               (:name "GetClipboardData") (:library "user32.dll")
> 	      (:arguments (type uint))
> 	      (:return-type int)
> 	      (:language :stdc))
>
> Is this the right direction to go in at least?

Yes.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"This machine is a piece of GAGH!  I need dual Opteron 850
processors if I am to do battle with this code!"
From: ··········@medialab.com
Subject: Re: CLISP and win32 clipboard access
Date: 
Message-ID: <1143638604.039180.182750@e56g2000cwe.googlegroups.com>
(Thank you Pascal!)

Hmm, okay, that's encouraging.

So now I have three challenges:

1. Why isn't CLIPGET returning anything but NIL?  Perhaps int is the
wrong return type?
2. Assuming I can get it to return the datahandle from win32 how do I
convert it to a Lisp string?
3. If I can get 1 & 2 to work, can I coerce a Lisp string into the
right form to put ON the clipboard after I manipulate it?
From: ··········@medialab.com
Subject: Re: CLISP and win32 clipboard access
Date: 
Message-ID: <1143639086.006440.142340@g10g2000cwb.googlegroups.com>
Okay, one down two to go.  I am now getting a value from the clipboard
by prefacing it with OpenClipboard().

Any ideas how to coerce the result to a Lisp string?

Thanks!

Tom
From: Pascal Bourguignon
Subject: Re: CLISP and win32 clipboard access
Date: 
Message-ID: <87d5g548ra.fsf@thalassa.informatimago.com>
··········@medialab.com writes:

> Okay, one down two to go.  I am now getting a value from the clipboard
> by prefacing it with OpenClipboard().
>
> Any ideas how to coerce the result to a Lisp string?

I don't know anything about Microsoft Windows, but assuming this is it:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/dataexchange/clipboard/usingtheclipboard.asp

the first step is to know the signature of the function.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/dataexchange/clipboard/clipboardreference/clipboardfunctions/getclipboarddata.asp

Says that it's:    HANDLE GetCliboardData(UINT uFormat);
with:

   Return Value

    If the function succeeds, the return value is the handle to a
    clipboard object in the specified format.

    If the function fails, the return value is NULL. To get extended
    error information, call GetLastError. 

So in any case, the return value is not an int, but a pointer of some kind.

After the examples linked above, it seems you'll need to use
GlobalLock to get a pointer to the data from the returned handle.

If a function returned a string, it would be a simple matter of saying so.

;; http://clisp.cons.org/impnotes/dffi.html

(ffi:def-call-out f (:name "somefun")
    (:arguments (arg ffi:c-string))
    (:return-type ffi:c-string))

Note that the conversion of the bytes in the c-string is governed by
the ext:*foreign-encoding*, and that the actual encoding used by
MS-Windows seems to depend on the uFormat argument.


You'll have to check MS-Windows headers to see what type a HANDLE is.
Assuming it's a void*, you could declare it as:

    (ffi:def-c-type HANDLE ffi:c-pointer)

and then the correct declaration of GET-CLIPBOARD-DATA would be:

(ffi:def-call-out GET-CLIPBOARD-DATA (:name "GetClipboardData")
    (:arguments (arg ffi:uint))
    (:return-type HANDLE))




If you have to use a lot of MS-Windows functions, it might be
worthwhile to check SWIG to generate the FFI declarations from the
headers.

http://www.cliki.net/SWIG

http://www.cliki.net/Verrazano
http://www.cliki.net/CFFI

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

READ THIS BEFORE OPENING PACKAGE: According to certain suggested
versions of the Grand Unified Theory, the primary particles
constituting this product may decay to nothingness within the next
four hundred million years.
From: ··········@medialab.com
Subject: Re: CLISP and win32 clipboard access
Date: 
Message-ID: <1143644195.584925.222560@z34g2000cwc.googlegroups.com>
Okay, for posterity, here it is.  Thank you Pascal!!

(use-package "FFI")
(def-call-out clip-open
          (:name "OpenClipboard") (:library "user32.dll")
	      (:arguments (hwnd uint))
	      (:return-type int)
	      (:language :stdc))

(def-call-out clip-close
          (:name "CloseClipboard") (:library "user32.dll")
	      (:arguments (hwnd uint))
	      (:return-type int)
	      (:language :stdc))

(def-call-out clip-get
          (:name "GetClipboardData") (:library "user32.dll")
	      (:arguments (type uint))
	      (:return-type int)
	      (:language :stdc))

(def-call-out clip-set
          (:name "SetClipboardData") (:library "user32.dll")
	      (:arguments (data uint) (format uint))
	      (:return-type int)
	      (:language :stdc))

(def-call-out global-alloc
          (:name "GlobalAlloc") (:library "kernel32.dll")
	      (:arguments (flags uint) (numbytes uint))
	      (:return-type int)
	      (:language :stdc))

(def-call-out global-lock
          (:name "GlobalLock") (:library "kernel32.dll")
	      (:arguments (type uint))
	      (:return-type uint)
	      (:language :stdc))

(def-call-out global-lock-string
          (:name "GlobalLock") (:library "kernel32.dll")
	      (:arguments (type uint))
	      (:return-type ffi:c-string)
	      (:language :stdc))

(def-call-out global-unlock
          (:name "GlobalUnlock") (:library "kernel32.dll")
	      (:arguments (type uint))
	      (:return-type int)
	      (:language :stdc))

(def-call-out memcpy
          (:name "memcpy") (:library "msvcrt.dll")
	      (:arguments (dest uint) (src ffi:c-string) (count uint))
	      (:return-type int)
	      (:language :stdc))

(defun get-clip-string ()
          (clip-open 0)
		  (let* ((h (clip-get 1)) (s (global-lock-string h)))
		         (global-unlock h) (clip-close 0) s))

(defun set-clip-string (s)
          (let* ((slen (+ 1 (length s)))(newh (global-alloc 8194 slen))
(newp (global-lock newh)))
		  (memcpy newp s (+ 1 slen)) (global-unlock newh) (clip-open 0)
(clip-set 1 newh) (clip-close 0)))
From: Pascal Bourguignon
Subject: Re: CLISP and win32 clipboard access
Date: 
Message-ID: <878xqt47cd.fsf@thalassa.informatimago.com>
··········@medialab.com writes:

> Okay, for posterity, here it is.  Thank you Pascal!!

Here, I think it would be better to use unwind-protect:

> (defun get-clip-string ()
>           (clip-open 0)
> 		  (let* ((h (clip-get 1)) (s (global-lock-string h)))
> 		         (global-unlock h) (clip-close 0) s))
>
> (defun set-clip-string (s)
>           (let* ((slen (+ 1 (length s)))(newh (global-alloc 8194 slen))
> (newp (global-lock newh)))
> 		  (memcpy newp s (+ 1 slen)) (global-unlock newh) (clip-open 0)
> (clip-set 1 newh) (clip-close 0)))

(defun get-clip-string ()
  (let ((s nil))
    (unwind-protect
      (let* ((dummy (clip-open 0))
             (h (clip-get 1)))
          (unwind-protect
              (setf s (global-lock-string h))
           (global-unlock h)))
      (clip-close 0))
     s))

And similarly in set-clip-string.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

COMPONENT EQUIVALENCY NOTICE: The subatomic particles (electrons,
protons, etc.) comprising this product are exactly the same in every
measurable respect as those used in the products of other
manufacturers, and no claim to the contrary may legitimately be
expressed or implied.
From: Sacha
Subject: Re: CLISP and win32 clipboard access
Date: 
Message-ID: <IbFWf.344689$Iu2.10144877@phobos.telenet-ops.be>
> If you have to use a lot of MS-Windows functions, it might be
> worthwhile to check SWIG to generate the FFI declarations from the
> headers.
>
> http://www.cliki.net/SWIG
>
> http://www.cliki.net/Verrazano
> http://www.cliki.net/CFFI
>
> -- 
> __Pascal Bourguignon__                     http://www.informatimago.com/
>

I've been recently working a lot with .NET, and found 
http://www.pinvoke.net/ to be very usefull.
This web site is providing the .NET world equivalent to FFI for win32 calls.
Wouldn't it be very nice to have such a wiki for FFIs ?

Sacha