[futurebasic] Re: [FB] Append a String to the Clipboard in Carbon

Message: < previous - next > : Reply : Subscribe : Cleanse
Home   : June 2002 : Group Archive : Group : All Groups

From: Alain Pastor <pixmix@...>
Date: Sun, 16 Jun 2002 09:51:44 +0200
RICH LOVE wrote:
> 
> Ken,
> 
> That works great!
> Thanks very much.
> FYI, it works under OS X (which is all I need) but crashes when booted under
> OS 9 saying it is out of memory trying to dispose a handle.
> 
I don't know about your crash, but I got a memory problem related to
container with the code posted by Ken under Mac OS 9.2.2. I have not
tried to find the cause of the trouble, instead I have used the
original program to test another approach without the use of containers.

While containers may be handy, I don't like that much to be forced to
add global variables in my programs. I always try to keep them at the
minimum. Not that containers variables would eat too much memory space
but it is also slightly more difficult to reuse the functions in other
projects if they refer to containers.
I think it is a good habit to build self contained functions in local
mode. You can see the benefits as soon as you start a new project.

It is also a good habit whenever possible to free the memory allocated
in the same function you have asked for it. I saw that Ken didn't do
that. It is OK in very short demos, but in real projects you might
easily loose tracks on what is going on with memory.

Here is my hack of Ken's code (not tested under OS X):


/*

   Append text to clipboard based on Ken Shmidheiser's demo
                                                     Alain

*/


/*
     this function gets a copy of the raw text
     from the clipboard. It returns a _nil handle
     if the operation fails.
*/
local mode
local fn GetClipboardText
dim as handle     scrapTextH
dim as long     @ length
dim as ScrapRef @ theScrapRef

scrapTextH = _nil
// getting the scrap reference
long if fn GetCurrentScrap( theScrapRef ) = _noErr
// checking for text
long if fn GetScrapFlavorSize( theScrapRef,¬
            _"TEXT", length ) = _noErr
// if length is not null, we've got some
long if length
// making a new handle with an appropriate size
scrapTextH = fn NewHandleClear( length )
long if scrapTextH
// getting the text from the clipboard
HLock( scrapTextH )
Long if fn GetScrapFlavorData( theScrapRef,¬
            _"TEXT", length, #[scrapTextH] ) != _noErr
beep : beep
end if
HUnlock( scrapTextH )
Xelse
beep : beep
end if
end if
end if
end if
end fn = scrapTextH

/*
     this function puts some raw text pointed to
     by a handle into the clipboard
*/
local mode
local fn TextToClipboard( textH as handle )
dim as OSStatus      err
dim as ScrapRef @ theScrapRef

Long if textH
// clear the scrap
err = fn ClearCurrentScrap
// get the scrap reference
long if fn GetCurrentScrap( theScrapRef ) = _noErr
HLock( textH )
// put text into the scrap
err = fn PutScrapFlavor( theScrapRef, _"TEXT",¬
       _kScrapFlavorMaskNone, fn GetHandleSize( textH ), #[textH] )
HUnlock( textH )
if err then beep : beep
end if
end if

end fn

/*
     this function appends data to
     the clipboard text (if any)
*/
local mode
local fn AppendTextToClipboard( textH as handle )
dim clipTextH as handle

// getting the existing clipboard text
clipTextH = fn GetClipboardText
// if no text found create an empty handle
if clipTextH = _nil then clipTextH = fn NewHandle( 0 )
long if clipTextH
// append the data
long if fn HandAndHand( textH, clipTextH  ) = _noErr
// copy to clipboard
fn TextToClipboard( clipTextH )
xelse
beep : beep
end if
// we don't need anymore the handle
DisposeHandle( clipTextH )
end if

end fn

local fn buildMenus

apple menu "(Ken's Clipboard Demo..."

menu 1, 0, _enable, "File"
menu 1, 1, _enable, "Quit"

edit menu 2

end fn

local fn buildWindow
dim as rect r

setrect( r, 0, 0, 500, 370)
window -1,"Ken's Clipboard Tester",@r,_docNoGrow

text _applFont, 12
edit = 4
setrect( r, 20, 20, 280, 34)
edit field -1,"What would you like to do?",@r,_statNoframed,_leftJust

setrect( r, 300, 50, 462, 310)
edit field -2,"",@r,_framed,_leftJust
setrect( r, 463, 47, 480, 313)
SCROLL BUTTON -2,0,0,0,0, @r, _scrollOther

setrect( r, 24, 232, 276, 246)
edit field -3,"",@r,_statNoframed,_leftJust

setrect( r, 24, 258, 263, 332)
edit field -4,"",@r,_framed,_leftJust
setrect( r, 263, 256, 278, 334)
SCROLL BUTTON -4,0,0,0,0, @r, _scrollOther


setrect( r, 20, 50, 280, 74)
button 10,1,"View clipboard text",@r,_push

offsetrect( r, 0, 60 )
button 20,1,"Clear clipboard",@r,_push

offsetrect( r, 0, 60 )
button 30,1,"Enter text for clipboard append",@r,_push

setrect( r, 300, 330, 480, 350)
button 40,0,"Append text to clipboard",@r,_push

edit field 0

window 1

end fn

local fn ClearButtons
edit$(4) = ""
button 40,0
end fn

/*
     this function displays the text
     contained in the clipboard
*/
local fn ViewClipboardText
dim scrapTextH as handle
dim textLen    as long

fn ClearButtons
// get the clipboard text
scrapTextH = fn GetClipboardText
long if scrapTextH
/*
     OK, now we've got our handle
     comes the tricky part. I wanted to
     use the syntax : EDIT$(_efNumber) = @myHandle
     In that case myHandle must be a ZTEXT handle
     which is specific to FB. It consists of a
     leading integer specifying the text length,
     followed by the raw text optionally followed
     by style information.
*/
// get the length of the clipboard text
textLen = fn GetHandleSize( scrapTextH )
// increase the handle size to make room for the integer
SetHandleSize( scrapTextH, sizeof(int) + textLen )
long if fn MemError = _noErr
// move the data to free space at the beginning of the handle
BlockMove([scrapTextH], [scrapTextH] + sizeof(int), textLen )
// store the text length in the two first bytes
scrapTextH..nil% = textLen
// put the "ZTEXT" handle in the edit field
Edit$(2) = &scrapTextH
end if
end if
end fn

local fn ClearClipboard
long if fn ClearCurrentScrap = _noErr
fn ClearButtons
Edit$(2) = ""
end if
end fn

local fn AllowAppendText
edit$(3) = "Please enter text to append here:"
button 40,1
edit field 4
end fn

/*
     this function copies the raw text
     from an edit field and appends it to
     the existing clipboard text.
*/
local fn DoAppend
dim teH     as ..TERec
dim @ textH as handle

// get a handle to the Text Edit record
teH   = tehandle( 4 )
// make an "alias" of the text handle
textH = teH..hText
// copy the data
long if fn HandToHand( textH ) = _noErr
// append the data duplicated to the clipboard text
fn AppendTextToClipboard( textH )
// get rid of the copy handle
DisposeHandle( textH )
fn ViewClipboardText
xelse
beep : beep
end if
end fn

local fn DoDialog
dim as long evnt, id

evnt = dialog(0)
id = dialog(evnt)

select case( evnt )
case _wndClose
select( id )
case 1 : gFBQuit = _zTrue
end select

case _btnClick
select( id )
case 10 : fn ViewClipboardText
case 20 : fn ClearClipboard
case 30 : fn AllowAppendText
case 40 : fn DoAppend
end select

end select

end fn

local fn DoMenu
dim as long menuID, itemID

menuID = menu(_menuID)
itemID = menu(_itemID)

select case( menuID )
case 1 : gFBQuit = _zTrue
end select
menu

end fn

on dialog fn DoDialog
on menu   fn DoMenu

fn buildMenus
fn buildWindow

do
handleevents
until gFBQuit
end


-- 
Cheers,

Alain