Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sun-barr!lll-winken!elroy.jpl.nasa.gov!usc!jarthur!jwinterm From: jwinterm@jarthur.Claremont.EDU (Jim Wintermyre) Newsgroups: comp.sys.mac.programmer Subject: Re: CDEF Woes... Message-ID: <10990@jarthur.Claremont.EDU> Date: 27 Feb 91 01:16:16 GMT References: <1435@gertie.osc.edu> Distribution: na Organization: Harvey Mudd College, Claremont, CA 91711 Lines: 147 In article <1435@gertie.osc.edu> spencer@cgrg.ohio-state.edu (Stephen N. Spencer) writes: >I've been experimenting with writing CDEF (Control Definitions) for a few >custom-type controls (an ICON button, a floating-point slider), and have >run into a problem. > >First, the setup: Since I want debugging messages from the CDEF, I'm not >compiling it as a CODE resource and linking it into my tester application. >(I have two windows in my tester app: a drawing window, and a TextEdit window. >I have an 'AddMessage()' function which takes a character string and appends >it to the TextEdit window -- instant scrolling debugging message window!) > >I'm doing the following to associate my control with the control handle: >First, I make the window, set the port, and call my setup function: > > gDrawWindow = NewWindow(....blah blah....); > SetPort(gDrawWindow); > SetupCDEF(gDrawWindow); > >Here's the setup function: > >SetupCDEF(win) > WindowPtr win; >{ > Rect r; > Handle h; > > h = NewHandle(h); > *h = (Ptr)MyControl; /* MyControl() is my CDEF 'main' function. */ > SetRect(&r, 160, 30, 400, 60); > myCH = NewControl(win, &r, "\p", TRUE, 0, 50, 100, scrollBarProc, 0L); > > HLock(myCH); > (*myCH)->contrlDefProc = myH; > HUnlock(myCH); >} > >This works, to a point. 'MyControl' intercepts all 'drawCntl' and 'testCntl' >messages passed through the control handle 'myCH', I'm glad to report, but >where it messes up is that I don't get any 'initCntl' message(s) at all. > >I could, of course, compile this CDEF into a stand-alone CODE resource and >use ResEdit to paste it into the test application, making the requisite changes >to the 'NewControl' statement, (I know how to do that). > >I don't want to, however. I want to see debugging messages. Is there SOME >way to link a CDEF function to a control handle so that it can be compiled in >together with the testing application? > >Thanks in advance for any help anyone out there can provide. When these CDEFs >are finished, I will post them to the 'net: I'm sure they would be useful. > >Stephen N. Spencer |"Now you must dance the dance that you imply! >ACCAD (614) 292-3416 | Your actions will follow you full circle round, >The Ohio State Univ. | The higher the leap, I said, >1224 Kinnear Road | The harder the ground!" >Columbus, OH 43212-1163| - Amy Ray, "Center Stage" >spencer@cgrg.ohio-state.edu||71160.3141@compuserve.com||stephen_spencer@osu.edu Hope you don't mind a Pascal example! This example is straight out of one of the example programs in the THINK Pascal package. It's a little different from what you were doing - you still have to put a little stub CDEF resource in the resource file, but this procedure modifies it so that it will jump to the code which is actually in your program. I've used this for doing the exact thing that you want to do, so I know it works. One thing - if you are having problems with the CDEF doing what it's supposed to do, make sure that you turn the debugging options off for the actual CDEF code type JmpRecord = record jmpInstr: Integer; jmpAddr: Ptr; end; JmpPtr = ^JmpRecord; JmpHandle = ^JmpPtr; Here is the documentation in the sample program (written by Rich Siegel of Symantec Corp.): InstallDefProc works by looking for a resource of the desired resource type and ID in the resource file specified by "dpPath"; if you're installing definition routines at program startup, you can pass CurResFile() as the first argument. The defproc resource is then patched to point to the procedure address given in "dpAddr". If the resource is not found in the resource file, a debugger trap is executed. To avoid this, you should create a 6-byte resource (it can be all zeros) of the defproc's type and ID, and place it in your program's resource file. Caveats: You probably don't want to install stub defprocs in the system resource file. Also remember that there are reserved resource ID's from 0 to 127; you should use resource ID's 128 or higher for your defprocs. Procedures that are installed should be in the main segment, and InstallDefProc only need be called once. HOW IT WORKS: In the normal case, the system loads a procedure resource (a CDEF, for example), and jumps to its beginning. InstallDefProc provides this functionality for procedures in your program by providing a 6-byte stub resource, which contains $4EF9, followed by a long word. The $4EF9 is a 68000 long jump instruction, and the long word is the address to which to jump. So the system calls this dummy defproc,which in turn jumps to the address passed. procedure InstallDefProc (dpPath: Integer; dpType: ResType; dpID: Integer; dpAddr: Ptr); var jH: JmpHandle; savePath: Integer; begin savePath := CurResFile; UseResFile(dpPath); jH := JmpHandle(GetResource(dpType, dpID)); UseResFile(savePath); if jH = nil then {Is there no defproc resource?} DebugStr('Stub Defproc Not Found!'); with jH^^ do begin jmpAddr := dpAddr; jmpInstr := $4EF9; end; HUnlock(Handle(jH)); MoveHHi(Handle(jH)); HNoPurge(Handle(jH)); {make this resource nonpurgeable} end; So you would call it like: InstallDefProc(CurResFile,'CDEF',200,@MyCDEFMain); Then, you would simply create a new control in the normal fashion (using NewControl), making sure that its procID field is set equal to 16 * resource ID of the CDEF stub in the resource file. So if the CDEF stub had resID 200, you'd pass 3200 in the procID parameter to NewControl. I hope this helps some. - Jim Wintermyre