1. Copying text to the clipboard in HTML format

All,

I've been working on a routine to copy text from a list view to the clipboard in
HTML format and would like to share my results.  Why, you may ask, would I want
to use HTML format?  Because with most word processors, spreadsheet and email
clients you can paste HTML data (specifically row oriented data) right into the
text.  In Word it shows up as a table.

Here's the routine:

--------------------------------------------------------------------------------
procedure CopyToClipPI_onClick(integer self, integer event, sequence
params)--params is ()
    sequence lv_select, lv_data, wrk_text, columns, hdr_seq, clip_text
    atom rtn_code, wrk_text_p, html_fmt_p, CF_HTML, startHTML, endHTML,
            startFrag, endFrag

    -- Open the clipboard
    rtn_code = w32Func(xOpenClipboard, {getHandle(MainWin)})
    if rtn_code then
        -- Get the CSV clipboard format
        html_fmt_p = allocate_string("HTML Format")
        CF_HTML = w32Func(xRegisterClipboardFormat,{html_fmt_p})
        free(html_fmt_p)
        -- Clean out the clipboard
        rtn_code = w32Func(xEmptyClipboard,{})
        -- Set up the header sequences
        hdr_seq = {}
        hdr_seq = append(hdr_seq, "Version:0.9\r\n")
        hdr_seq = append(hdr_seq, sprintf("StartHTML:%08d\r\n",0))
        hdr_seq = append(hdr_seq, sprintf("EndHTML:%08d\r\n",0))
        hdr_seq = append(hdr_seq, sprintf("StartFragment:%08d\r\n",0))
        hdr_seq = append(hdr_seq, sprintf("EndFragment:%08d\r\n",0))
        startHTML = 0
        for i = 1 to length(hdr_seq) do
            startHTML += length(hdr_seq[i])
        end for
        -- First load the column names
        wrk_text = "<HTML>\r\n<BODY>\r\n"
        startFrag = (startHTML-1) + length(wrk_text) + 1
wrk_text &= "<!--StartFragment-->\r\n<TABLE BORDER>\r\n<TR>"
        columns = getColumnHeadings(ResultsLV)
        for i = 1 to length(columns) do
            wrk_text &= "\r\n\t<TH>"
            wrk_text &= columns[i][2]
            wrk_text &= "</TH>"
        end for
        wrk_text &= "</TR>"
        -- Now get the selected rows
        lv_select = getLVSelected(ResultsLV)
        for i = 1 to length(lv_select) do
            -- Get the data for the selected row
            lv_data = getLVAllText(ResultsLV, lv_select[i])
            wrk_text &= "\r\n<TR>"
            -- Add on the data columns
            for x = 1 to length(lv_data) do
                wrk_text &= "\r\n\t<TD>"
                wrk_text &= lv_data[x]
                wrk_text &= "</TD>"
            end for
            wrk_text &= "</TR>"
        end for
        wrk_text &= "\r\n</TABLE>\r\n<!--EndFragment-->"
        endFrag = (startHTML-1) + length(wrk_text)
        wrk_text &= "\r\n</BODY>\r\n</HTML>"
        -- Set the offsets in the clip header
        hdr_seq[2] = sprintf("StartHTML:%08d\r\n",startHTML)
        hdr_seq[3] = sprintf("EndHTML:%08d\r\n",(startHTML-1)+length(wrk_text))
        hdr_seq[4] = sprintf("StartFragment:%08d\r\n",startFrag)
        hdr_seq[5] = sprintf("EndFragment:%08d\r\n",endFrag)
        -- Now form the entire text string
        clip_text = ""
        for i = 1 to length(hdr_seq) do
            clip_text &= hdr_seq[i]
        end for
        clip_text &= wrk_text
        -- Put to the clipboard
        wrk_text_p = allocate_string(clip_text)
        rtn_code = w32Func(xSetClipboardData,{CF_HTML, wrk_text_p})
        -- Close the clipboard
        w32Proc(xCloseClipboard,{})
        -- free the memory
        free(wrk_text_p)
    end if
end procedure
setHandler( CopyToClipPI, w32HClick, routine_id("CopyToClipPI_onClick"))


The above routine works but every now and then when I close the app exw crashes
with a memory exception.  Maybe someone with a keener eye than myself can spot
the problem.

I know there's redundant code but it helps when having to set the bizarre
offsets required my MS.  I also read on other language forums that the start/end
information is not required if your whole HTML is inside the fragment but I
didn't have any luck with that.

Jonas Temple
http://www.yhti.net/~jktemple

new topic     » topic index » view message » categorize

2. Re: Copying text to the clipboard in HTML format

Hi,
Concerning Clipboard operations, I read the following at 
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/dataexchange/clipboard/clipboardformats.asp

I point your attention to the following sentences:
A memory object that is to be placed on the clipboard should be allocated by
using the GlobalAlloc function with the GMEM_MOVEABLE flag.
After a memory object is placed on the clipboard, ownership of that memory
handle is transferred to the system.

My guess is:
You use allocate_string() Instead of GlobalAlloc().
As the system take ownership of the memory allocated, when you want to  free()
it there is an access denied error.

regards,
Jacques DeschĂȘnes

new topic     » goto parent     » topic index » view message » categorize

3. Re: Copying text to the clipboard in HTML format

> Hi,
> 
> I point your attention to the following sentences:
> A memory object that is to be placed on the clipboard should be allocated by
> using the GlobalAlloc function with the GMEM_MOVEABLE flag.
> After a memory object is placed on the clipboard, ownership of that memory
> handle
> is transferred to the system. 
> 
> My guess is:
> You use allocate_string() Instead of GlobalAlloc().
> As the system take ownership of the memory allocated, when you want to  free()
> it there is an access denied error.
> 
I believe you hit the nail on the head!  That's what I missed.

Thanks a bunch!

Jonas Temple
http://www.yhti.net/~jktemple

new topic     » goto parent     » topic index » view message » categorize

4. Re: Copying text to the clipboard in HTML format

Jonas Temple wrote:
> 
> > Hi,
> > 
> > I point your attention to the following sentences:
> > A memory object that is to be placed on the clipboard should be allocated by
> > using the GlobalAlloc function with the GMEM_MOVEABLE flag.
> > After a memory object is placed on the clipboard, ownership of that memory
> > handle
> > is transferred to the system. 
> > 
> > My guess is:
> > You use allocate_string() Instead of GlobalAlloc().
> > As the system take ownership of the memory allocated, when you want to 
> > free()
> > it there is an access denied error.
> > 
> I believe you hit the nail on the head!  That's what I missed.
> 
> Thanks a bunch!
> 
> Jonas Temple
> <a href="http://www.yhti.net/~jktemple">http://www.yhti.net/~jktemple</a>

Hi there,

Yes, that's right.  I posted a message here mentioning that a few years
back and someone had said that WinLib already does it the correct way.
I was using 'allocate_string' too for a while, which worked, but when
i went to XP it no longer worked (put garbage on the clipboard) so i
was forced to look for the correct way to do it :)
There are a few other tricks to it also so if you have any other
problems just yell :)


Take care,
Al

And, good luck with your Euphoria programming!

My bumper sticker: "I brake for LED's"

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu