[futurebasic] Re: [FB] Detecting clicks in edit fields

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

From: Dan Baeckström <dan.baeckstrom@...>
Date: Thu, 30 Jun 2011 22:22:04 +0200
Well, what can I say except quote the Group Information paragraph of  
this very list:

"This list is available by subscription to anyone interested in Staz  
Software's FutureBASIC programming languages for the Macintosh. List  
members include "raw beginners" through published "commercial"  
software authors; we are all here to ask and answer questions, so  
don't be afraid to ask the one that's bothering you!"

I am usually not unaware of the transient nature of local variables.  
In this particular case, I apparently believed that the system  
function InstallEventHandler() had some magic capacity to preserve  
their values. Of course, it's just pointers. It would have been very  
tidy if it worked though.

include "Util_CE.incl"
_bouton1=1
_bouton2=2
_message=3


'
begin record controlhandlrec
dim as long ctrlno
dim as pointer fnaddress
end record
'

local fn MyControlHitHandler( nextHandler as EventHandlerCallRef,  
theEvent as EventRef, userrec as .controlhandlrec  )
dim as OSStatus      result : result = _eventNotHandledErr
select fn GetEventClass( theEvent )
case _kEventClassControl
select fn GetEventKind( theEvent )
case _kEventControlHitTest
long if fn button
def fn trapfn(butno as long) using userrec.fnaddress
fn trapfn(userrec.ctrlno)
end if
end select
end select
end fn = result
'
local fn buttontrap(butno as long)
stop "event trapped for control #"+str$(butno)
end fn
'
dim as rect rct
dim as long tempno
dim as controlhandlrec chrec(2)
dim as pointer temppoint

window 1

setrect(rct,10,10,200,30)
appearance BUTTON _bouton1,_activeBtn,,,,, @rct, _kControlStaticTextProc
temppoint = @fn buttontrap
tempno = _bouton1
gosub "makeeventhandler"
fn SETBUTTONTEXTSTRING(_bouton1,"texte statique 1")
offsetrect(rct,0,40)
appearance BUTTON _bouton2,_activeBtn,,,,, @rct, _kControlStaticTextProc
tempno=_bouton2
gosub "makeeventhandler"
fn SETBUTTONTEXTSTRING(_bouton2,"texte statique 2")

do
handleevents
until gFBQuit

end


"makeeventhandler"
chrec.ctrlno(tempno)=tempno
chrec.fnaddress(tempno)=temppoint
fn CEAddEvent(_kEventClassControl,_kEventControlHitTest)
fn CEInstallControlEventHandler( button&(tempno), @fn  
MyControlHitHandler,@chrec(tempno),0 )
return





On 30 Jun 2011, at 07:15, Robert Purves wrote:

>
> Dan Baeckström wrote:
>
>> When I find some really useful code, like Alain's, I want to  
>> rearrange it into one (or a set of) local fns that can be called by  
>> many different programs, and then put them into  
>> MyReallyUsefulFns.incl which is then included in any code that  
>> wants to use the fns. Ideally, it would look like this in the case  
>> of Alains code (note that the fns probably would have to change  
>> places in some cases to avoid errors):
>
>> local fn makectrleventhandler(butno as long,userfn as pointer)
>> dim as controlhandlrec chrec  //this record is used as user data
>> chrec.ctrlno=butno
>> chrec.fnaddress=userfn
>> fn CEAddEvent(_kEventClassControl,_kEventControlHitTest)
>> fn CEInstallControlEventHandler( button&(butno), @fn  
>> MyControlHitHandler,@chrec,0 )
>> end fn
>
>
> Unfortunately, makectrleventhandler() should be in a file  
> "ReallyBadIdeas.incl". You have fallen foul of a notorious gotcha.
> <http://en.wikipedia.org/wiki/Dangling_pointer>
>
> After setting the fields of chrec, you stash its address @chrec for  
> use later, after makectrleventhandler() has returned. For this to  
> work, obviously the content of that memory must not change before  
> you access it.
>
> Local variables such as chrec have only temporary existence. They  
> reside on the stack, an area of memory shared by all functions. Only  
> one function at a time claims a particular range of the stack. On  
> returning, a function gives up its claim so as to make the memory  
> available to subsequently called functions. Those function are free  
> to overwrite the memory in any way they choose (which may be  
> different from one compiler to another).
>
> When makectrleventhandler() returns, the values of chrec.ctrlno and  
> chrec.fnaddress become undefined; that is they could be any value.
>
>
> The demo below gives wrong results with most choices of compiler and  
> optimization level.
>
> Robert P.
>
> '------------------
> include "ConsoleWindow"
>
> begin record Thing
> dim as long a, b, c, d
> end record
>
> begin globals
> dim as ^Thing  gThingP
> end globals
>
>
> local fn PrintThing
> '~'1
> print gThingP.a, gThingP.b, gThingP.c, gThingP.d
> end fn
>
>
> local fn SetThingAndSaveAddress
> '~'1
> dim as Thing  t // local var on stack
> t.a = 1
> t.b = 2
> t.c = 3
> t.d = 4
> gThingP = @t // address of local var
> end fn
>
> print "Dangling pointer demo"
> fn SetThingAndSaveAddress
> // gThingP now points to 'stale' stack memory
> fn PrintThing
> '------------------
>
>
>
>
>
>
> --
> To unsubscribe, send ANY message to: futurebasic-unsubscribe@...
> To access the list archives, go to:  http://freegroups.net/groups/futurebasic/
>