From: pottier@clipper.ens.fr (Francois Pottier) Subject: csmp-digest-v3-046 Date: Wed, 20 Jul 1994 14:41:25 +0200 (MET DST) C.S.M.P. Digest Wed, 20 Jul 94 Volume 3 : Issue 46 Today's Topics: 3D Rotational examples - Help wanted CASE Tools for Macintosh Debugging an applet properly (AppleScript) GWorlds vs. Offscreens GWorlds: When to lock pixels? How do you write TIFFs? How to tell Energy Saver to turn the monitor on or off Newbie Gworld questions. Patching Trap ExitToShell using UniversalProcPtr's Porting from Unix to Mac - Summary Problems with Metrowerks vs. MPW 68k C calling conventions Special #define for Univ. Hdrs? Why does THINK C use a jump table? The Comp.Sys.Mac.Programmer Digest is moderated by Francois Pottier (pottier@clipper.ens.fr). The digest is a collection of article threads from the internet newsgroup comp.sys.mac.programmer. It is designed for people who read c.s.m.p. semi- regularly and want an archive of the discussions. If you don't know what a newsgroup is, you probably don't have access to it. Ask your systems administrator(s) for details. If you don't have access to news, you may still be able to post messages to the group by using a mail server like anon.penet.fi (mail help@anon.penet.fi for more information). Each issue of the digest contains one or more sets of articles (called threads), with each set corresponding to a 'discussion' of a particular subject. The articles are not edited; all articles included in this digest are in their original posted form (as received by our news server at nef.ens.fr). Article threads are not added to the digest until the last article added to the thread is at least two weeks old (this is to ensure that the thread is dead before adding it to the digest). Article threads that consist of only one message are generally not included in the digest. The digest is officially distributed by two means, by email and ftp. If you want to receive the digest by mail, send email to listserv@ens.fr with no subject and one of the following commands as body: help Sends you a summary of commands subscribe csmp-digest Your Name Adds you to the mailing list signoff csmp-digest Removes you from the list Once you have subscribed, you will automatically receive each new issue as it is created. The official ftp info is //ftp.dartmouth.edu/pub/csmp-digest. Questions related to the ftp site should be directed to scott.silver@dartmouth.edu. Currently no previous volumes of the CSMP digest are available there. Also, the digests are available to WAIS users. To search back issues with WAIS, use comp.sys.mac.programmer.src. With Mosaic, use http://www.wais.com/wais-dbs/comp.sys.mac.programmer.html. ------------------------------------------------------- >From Malicious_Monarch@nile.com (Malicious Monarch) Subject: 3D Rotational examples - Help wanted Date: Tue, 5 Jul 94 14:39:38 MDT Organization: The Nile BBS I'm looking for some examples in creating simple three dimensional objects in C. I've just started reading Michael Chen's article in issue 14 of develop, but I imagine there are some references to explain the use of the Graf3D library and perhaps even some more simplistic code to give a basic understanding of creating and drawing three dimensional objects. Please understand that I'm not concerned with a user interface at this point, just simple rendering code (ie making a cube and rotating it to give the illusion that it is a three dimensional object). If someone could point toward some source code, or any literature (books, magazines, etc.) I would really really appreciate it. Thanks... -Eric A. Drumbor- Opinions posted are of the user, not the administration. +++++++++++++++++++++++++++ >From nick@pitt.edu ( nick.c ) Date: Tue, 5 Jul 94 17:58:41 GMT Organization: University of Pittsburgh In Article <0007E5C6.fc@nile.com>, Malicious_Monarch@nile.com (Malicious Monarch) wrote: > Please understand that I'm not concerned with a user interface at this >point, just simple rendering code (ie making a cube and rotating it to give the >illusion that it is a three dimensional object). If someone could point toward >some source code, or any literature (books, magazines, etc.) I would really >really appreciate it. Thanks... There is some code called "wireframeorama" (or something like that) that's at both sumex and umich. A couple of good books are: _Computer_Graphics_ 2nd ed by Hearn & Baker ISBN 0-13-161530-0 _3D_Computer_Graphics_ 2nd ed by Alan Watt ISBN 0-201-63186-5 One general procedure is to imagine your "object" in 3D space (say with x,y,z co-ords centered around 0,0,0 to start), then imagine an "observer" in the same space (say at x,y,z=0,0,100) and a perpandicular plane between them (say at z= 70). Rotate, translate or do whatever to the object (working in cartesian it's pretty easy - it's also handy to add a fourth parameter as a scaler for xy&z - say t) then imagine vectors from the observer to each point of your object (say the vertices of the cube). The points where your vectors intersect the plane are the points you want to map to your graphics port. Then just connect the dots in your graphics port. With wire frame, you don't have to worry 'bout which point is closer to the observer. Hmmm... not the best explanation, but I'm kind of new to this too. Check out those books (or anything around T385 in your library), it's a lot easier than it seems at first. Luck, -- nick _/ _/ _/ _/_/_/ _/ _/ Sea Shells to C shells, Waikiki to _/_/ _/ _/ _/ _/ _/_/_/ the Internet, a wave, is a wave... _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/_/_/ _/ _/ CompSrv: 71232,766 I-Net: Nick@pitt.edu +++++++++++++++++++++++++++ >From cconstan@epdiv1.env.gov.bc.ca (Carl B. Constantine) Date: Wed, 06 Jul 1994 07:40:20 -0700 Organization: Ministry of Environment, Lands & Parks In article , nick@pitt.edu ( nick.c ) wrote: > In Article <0007E5C6.fc@nile.com>, Malicious_Monarch@nile.com (Malicious > Monarch) wrote: > > > Please understand that I'm not concerned with a user interface at this > >point, just simple rendering code (ie making a cube and rotating it to give the > >illusion that it is a three dimensional object). If someone could point toward > >some source code, or any literature (books, magazines, etc.) I would really > >really appreciate it. Thanks... > > There is some code called "wireframeorama" (or something like that) > that's at both sumex and umich. A couple of good books are: > [ snip ] I have a good file (better than wireframeorama) that uses the Graph3D library and rotates and scales (I think) an object in 3D space. e-mail me if you're interested. I may post it (it's small) -- ======================================================================== Carl B. Constantinedata^.die becomes true, give up. If you get a potential error, set data^.error to it, and then wait: procedure GotAnError(err:OSErr); data^.error:=err; while data^.error<>1 and not die do Yield end-while When we return from that, if die is true, then give up, otherwise continue, ignoring or handling the error as appropriate. Init: threads.qHead:=nil; threads.qTail:=nil; In the Main loop: for each data in threads queue do if data^.error=noErr then begin Signal Success Remove from queue end else if data^.error<>1 then begin Signal failure If the user wants it to abort set the die field to true otherwise set data^.error to 1 again so the thread will continue end-if end; end-for You'll have to be careful about exactly who removes the entry from the queue and disposes it, but it's not too tricky. Just be thankful we dont have preemptive multitasking. Ughh. It makes this much more horrible. Peter. -- Peter N Lewis - Macintosh TCP fingerpainter FTP my programs from redback.cs.uwa.edu.au:Others/PeterLewis/ or amug.org:pub/peterlewis/ or nic.switch.ch:software/mac/peterlewis/ --------------------------- >From fba@cs.brown.edu (Farah B. Abbas) Subject: Shared Memory on Mac Date: Thu, 8 Sep 1994 16:46:20 GMT Organization: Brown University Department of Computer Science Hi, Does anyone know how to implement shared memory on the Mac? I have an application that sets a variable that I want another app to read later. I guess one way would be to use a code resource so that one application sets the variable in the resource and the other app can load the resource and thereby look up the variable. Is there a "Apple Suggested" way that is better or do I have to do this hack ? Please email any suggestions to fba@cs.brown.edu. Thanx in advance. Farah +++++++++++++++++++++++++++ >From rmah@panix.com (Robert Mah) Date: Fri, 09 Sep 1994 03:24:53 -0500 Organization: One Step Beyond fba@cs.brown.edu (Farah B. Abbas) wrote: ) Does anyone know how to implement shared memory on the Mac? I have an ) application that sets a variable that I want another app to read later. ) I guess one way would be to use a code resource so that one application ) sets the variable in the resource and the other app can load the resource ) and thereby look up the variable. Is there a "Apple Suggested" way that ) is better or do I have to do this hack ? I've been working on something to do just this. It uses Gestalt to provide tagged, shared memory between apps (and any other code for that matter). I've thought about using a trap, but decided against it as Apple sort of has a hammerlock on the A-trap market :-). In any case, to use it, one simply registers a block of memory with the Shared Memory Manager (tm) and then can request it again later by using the tag. It is all very simple. Would you like to test/work on it with it with me? Cheers, Rob _____________________________________________________________________ Robert S. Mah Software Development +1.212.947.6507 One Step Beyond and Network Consulting rmah@panix.com +++++++++++++++++++++++++++ >From lambert_l@measurex.com (Leon Lambert) Date: Tue, 13 Sep 1994 20:04:31 GMT Organization: measurex In article <1994Sep8.164620.21157@cs.brown.edu> fba@cs.brown.edu (Farah B. Abbas) writes: > Hi, > > Does anyone know how to implement shared memory on the Mac? I have an > application that sets a variable that I want another app to read later. I guess > one way would be to use a code resource so that one application sets the > variable in the resource and the other app can load the resource and > thereby look up the variable. Is there a "Apple Suggested" way that is > better or do I have to do this hack ? Please email any suggestions to > fba@cs.brown.edu. Thanx in advance. > > Farah I did this by making an INIT that created a trap. But I now think a better way to do this is to use the gestalt manager. It has the ability to store and retrieve a 32 bit value. I haven't tried it yet but maybe someone else has. lambert_l@measurex.com (Leon Lambert) lambertlb@aol.com +++++++++++++++++++++++++++ >From Jaeger@fquest.com (Brian Stern) Date: 14 Sep 1994 15:54:21 GMT Organization: The University of Texas at Austin, Austin, Texas In article <1994Sep8.164620.21157@cs.brown.edu>, fba@cs.brown.edu (Farah B. Abbas) wrote: < Hi, < < Does anyone know how to implement shared memory on the Mac? I have an < application that sets a variable that I want another app to read later. I guess < one way would be to use a code resource so that one application sets the < variable in the resource and the other app can load the resource and < thereby look up the variable. Is there a "Apple Suggested" way that is < better or do I have to do this hack ? Please email any suggestions to < fba@cs.brown.edu. Thanx in advance. < < Farah Hi, This can be done by putting the information in a preferences file that both apps can open. You can install a gestalt selector that returns the address of this shared memory. Both the gestalt selector and the shared memory should exist in the system heap if you do this, in case of crashes. This can also be implemented by creating a driver that returns the address of the shared mem or that returns the actual values in the shared mem. Good Luck, -- Brian Stern :-{)} Jaeger@fquest.com +++++++++++++++++++++++++++ >From peter.lewis@info.curtin.edu.au (Peter N Lewis) Date: Mon, 19 Sep 1994 09:33:04 +0800 Organization: NCRPDA, Curtin University In article <1994Sep8.164620.21157@cs.brown.edu>, fba@cs.brown.edu (Farah B. Abbas) wrote: >Does anyone know how to implement shared memory on the Mac? I have an >application that sets a variable that I want another app to read later. I guess >one way would be to use a code resource so that one application sets the >variable in the resource and the other app can load the resource and >thereby look up the variable. Is there a "Apple Suggested" way that is >better or do I have to do this hack ? Please email any suggestions to >fba@cs.brown.edu. Thanx in advance. Use Gestalt. Have either or both applications install a gestalt handler that returns the variable or the address of the variable. WARNING: Do not assume you will be able to write (or perhaps even read) another app's memory directly. We desperately want Apple to give us memory protection, at least between the various app's partitions, right?! If you want to share memory directly, then at least allocate the memory in the System Heap, and use a Gestalt call to get the address of the memory. Both apps could do something like: If the gestalt call is already installed use the value returned as a ptr/handle to the data. otherwise create the memory in the system heap load the gestalt code (probably also in the system heap) install the gestalt initialize the memory end After that, you can assume the gestalt call is installed and the memory is available. Enjoy, Peter. -- Peter N Lewis - Macintosh TCP fingerpainter FTP my programs from redback.cs.uwa.edu.au:Others/PeterLewis/ or amug.org:pub/peterlewis/ or nic.switch.ch:software/mac/peterlewis/ +++++++++++++++++++++++++++ >From chrism@col.hp.com (Chris Magnuson) Date: 20 Sep 1994 17:05:56 GMT Organization: HP Colorado Springs Division It *seems* like the PPC Toolbox might be okay for this. There is an example of this on one of the developer CDs, where an INIT allocates some memory for shared globals and an application reads them. Chris Magnuson chrism@col.hp.com --------------------------- >From dbradley@Netaxs.com (Dan Bradley) Subject: Window Lists Date: 10 Sep 1994 19:10:49 GMT Organization: Netaxs Internet BBS and Shell Accounts Can anyone describe the process used to get a list of all open windows within an application? I simply want to make an on the fly menu with all the windows in my application in it. I thought of just updating the list within my open, close, and save handlers, but it seems like it would be a lot easier to just cycle through a list, which I'm sure must exist, but I simply can't find, being a newbie who just doesn't know where to look. I've been looking through IM, Think Ref, and Dave Mark's books, but haven't found anything. I'm using Think C 6 and no TCL. Thanks in advance, Dan Bradley dbradley@netaxs.com +++++++++++++++++++++++++++ >From tnleeuw@cs.vu.nl (Leeuw van der TN) Date: Mon, 12 Sep 1994 14:23:31 GMT Organization: Fac. Wiskunde & Informatica, VU, Amsterdam dbradley@Netaxs.com (Dan Bradley) writes: : Can anyone describe the process used to get a list of all open windows : within an application? I simply want to make an on the fly menu with : all the windows in my application in it. I thought of just updating the list : within my open, close, and save handlers, but it seems like it would be : a lot easier to just cycle through a list, which I'm sure must exist, but : I simply can't find, being a newbie who just doesn't know where to look. : I've been looking through IM, Think Ref, and Dave Mark's books, but : haven't found anything. I'm using Think C 6 and no TCL. : : Thanks in advance, : : Dan Bradley : dbradley@netaxs.com : Once I had a similar problem, when I wanted to get a list of my windows so I could dispose of them when quitting. I came up with the AUXWinRec, which you can call with a valid window record as a parameter, and gives you the AuxWinRecord (sp?) for the Window *if* it is a color window. *If* it is a color window, the owner field points to your window. Big Trick: it also has a field pointing to the next AuxWinRec in the list, which has of course an owner... So if you now what your first window is (like, your about-box) you might be able to get the list. I must admit that after I typed that code, I found the solution too scary to really try it. I rewrote it using Frontwindow(). I've not seen it documented anywhere what window is really next in the list. It might not be yours. I'm really curious how to do it. --Tim van der Leeuw tnleeuw@cs.vu.nl +++++++++++++++++++++++++++ >From kurisuto@babel.ling.upenn.edu (Sean Crist) Date: 12 Sep 1994 18:59:18 GMT Organization: University of Pennsylvania, Linguistics Department Unless I'm mistaken, it's still kosher to write your program as if all its windows are in one linked list. There's so many applications that step through their own windows this way that Apple really can't change this without breaking an awful lot of applications. If I remember right, though, FrontWindow returns the first _visible_ window, and you might want to start with invisible ones, so you've got to look in some low-memory pointer to really start at the front of the window list. I'm talking off the top of my head; I've got some Pascal code at home that illustrates this but I might be wrong in a few of the details. --Sean +++++++++++++++++++++++++++ >From cswan@actrix.gen.nz (Chris Swan) Date: Wed, 14 Sep 1994 00:58:40 GMT Organization: Actrix Information Exchange > : Can anyone describe the process used to get a list of all open windows > : within an application? I simply want to make an on the fly menu with > Once I had a similar problem, when I wanted to get a list of my windows > so I [deleted - really complex answer] tting. theWindow := FrontWindow; while theWindow <> nil do begin Do_Some_thing(with, theWindow); theWindow:= windowPtr(windowPeek(theWindow)^.nextWindow); end; Ref. Inside Macintosh Volume I -- Chris Swan cswan@actrix.gen.nz PO Box 11567, Wellington, New Zealand -- +++++++++++++++++++++++++++ >From Tim_Craycroft@PowerTalk.apple.com (Tim Craycroft) Date: Wed, 14 Sep 1994 00:40:00 GMT Organization: Apple Computer In article , tnleeuw@cs.vu.nl (Leeuw van der TN) wrote: > > dbradley@Netaxs.com (Dan Bradley) writes: > : Can anyone describe the process used to get a list of all open windows > : within an application? I simply want to make an on the fly menu with > : all the windows in my application in it. I thought of just updating the list > : within my open, close, and save handlers, but it seems like it would be > : a lot easier to just cycle through a list, which I'm sure must exist, but > : I simply can't find, being a newbie who just doesn't know where to look. > : I've been looking through IM, Think Ref, and Dave Mark's books, but > : haven't found anything. I'm using Think C 6 and no TCL. > : > : Thanks in advance, > : > : Dan Bradley > : dbradley@netaxs.com > : > Once I had a similar problem, when I wanted to get a list of my windows > so I could dispose of them when quitting. I came up with the AUXWinRec, > which you can call with a valid window record as a parameter, and gives > you the AuxWinRecord (sp?) for the Window *if* it is a color window. > *If* it is a color window, the owner field points to your window. Big Trick: > it also has a field pointing to the next AuxWinRec in the list, > which has of course an owner... So if you now what your first window > is (like, your about-box) you might be able to get the list. > > I must admit that after I typed that code, I found the solution too scary > to really try it. I rewrote it using Frontwindow(). I've not seen it > documented anywhere what window is really next in the list. It might not > be yours. > I'm really curious how to do it. > > --Tim van der Leeuw > tnleeuw@cs.vu.nl You want to iterate over your window list. Get the first window by calling LMGetWindowList(). The link field in the window record is ->nextWindow. If you are just interested in visible windows, you can use FrontWindow() instead of LMGetWindowList() and then check the ->visible field of all subsequent windows in the list. Do NOT use the aux record list. There is no guarantee that the link field in the aux record is an aux record of a window you own. // // Accessor macros that will someday be replace by real window mgr APIs // #define GetNextWindow(w) (((WindowPeek) w)->nextWindow) #define IsWindowVisible(w) (((WindowPeek) w)->visible) DoSomethingWithMyWindows(Boolean onlyVisible) { WindowRef currentWindow; currentWindow = LMGetWindowList(); while (currentWindow != 0) { if (!onlyVisible || ( IsWindowVisible(currentWindow) ) { // do something with this window... DoSomethingToOneWindow(currentWindow); } currentWindow = GetNextWindow(currentWindow); } } +++++++++++++++++++++++++++ >From h+@nada.kth.se (Jon W{tte) Date: Wed, 14 Sep 1994 18:36:53 +0200 Organization: Royal Institute of Something or other In article , cswan@actrix.gen.nz (Chris Swan) wrote: >theWindow := FrontWindow; >while theWindow <> nil do > begin > Do_Some_thing(with, theWindow); > theWindow:= windowPtr(windowPeek(theWindow)^.nextWindow); > end; Close, but no cigar. FrontWindow() returns the first visible window, but the nextWindow pointer can return an invisible window. WindowPtr window = FrontWindow ( ) ; while ( window ) { DoSomeThing ( window ) ; do { window = ( WindowPtr ) ( ( WindowPeek ) window ) -> nextWindow ; } while ( window && ! ( ( WindowPeek ) window ) -> visible ) ; } The Window Manager is desperately in need of a lot of accessor functions, by the way. Cheers, / h+ -- Jon Wätte (h+@nada.kth.se), Hagagatan 1, 113 48 Stockholm, Sweden ~r ~/.signature +++++++++++++++++++++++++++ >From larson@oahu.cs.ucla.edu (Christopher Larson) Date: Wed, 14 Sep 94 16:26:12 GMT Organization: UCLA, Computer Science Department In article cswan@actrix.gen.nz (Chris Swan) writes: >> : Can anyone describe the process used to get a list of all open windows >> : within an application? I simply want to make an on the fly menu with > >> Once I had a similar problem, when I wanted to get a list of my windows >> so I [deleted - really complex answer] tting. > >theWindow := FrontWindow; ^^^^^^^^^^^ >while theWindow <> nil do > begin > Do_Some_thing(with, theWindow); > theWindow:= windowPtr(windowPeek(theWindow)^.nextWindow); > end; > >Ref. Inside Macintosh Volume I If memory serves, FrontWindow() returns the frontmost _visible_ window. You may miss hidden windows this way. Try starting with the LM global WindowList. --Chris _______________________________________________________________________________ Chris Larson -- Amateur Macintosh Geek, CoBase Research Assistant L.A. Institute of Slowly and Painfully Working Out the Surprisingly Obvious Death to the Trojans! Go Bruins! (Insert disclaimer here) Internet: larson@kingston.cs.ucla.edu +++++++++++++++++++++++++++ >From tnleeuw@cs.vu.nl (Leeuw van der TN) Date: Thu, 15 Sep 1994 11:36:45 GMT Organization: Fac. Wiskunde & Informatica, VU, Amsterdam cswan@actrix.gen.nz (Chris Swan) writes: : > : Can anyone describe the process used to get a list of all open windows : > : within an application? I simply want to make an on the fly menu with : : > Once I had a similar problem, when I wanted to get a list of my windows : > so I [deleted - really complex answer] tting. : : theWindow := FrontWindow; : while theWindow <> nil do : begin : Do_Some_thing(with, theWindow); : theWindow:= windowPtr(windowPeek(theWindow)^.nextWindow); : end; I still don't understand how I could have overlooked that field. Really stupid, actually. Sorry. Anyway, I understand that you can get the first window by calling FrontWindow()? It's not the window that you first created? : : Ref. Inside Macintosh Volume I : : -- : Chris Swan : cswan@actrix.gen.nz : PO Box 11567, Wellington, New Zealand : -- --Tim van der Leeuw tnleeuw@cs.vu.nl +++++++++++++++++++++++++++ >From Jens Alfke Date: Mon, 19 Sep 1994 20:35:15 GMT Organization: Apple Computer In article <34t0bp$jkt@netaxs.com> Dan Bradley, dbradley@Netaxs.com writes: > Can anyone describe the process used to get a list of all open windows > within an application? Start with FrontWindow(), then follow the nextWindow fields in each windowRecord. Note that WindowPtr is just another name for GrafPtr, so you won't be able to access the extra WindowRecord fields through it. You have to cast to WindowPeek (defined as a pointer to WindowRecord). WindowPtr w; for( w=FrontWindow(); w; w=(WindowPtr)((WindowPeek)w)->nextWindow ) if( ((WindowPeek)w)->windowKind >= userKind ) /*do something with w*/; Note that this loop intentionally skips non-document windows like dialogs, DAs and other system windows. --Jens Alfke jens_alfke@powertalk.apple.com "A man, a plan, a yam, a can of Spam ... Bananama!" --------------------------- >From paitech@hntp2.hinet.net (paitech) Subject: preloaded CODE resources in fat binaries Date: 9 Sep 1994 08:28:52 GMT Organization: NCTU News Server, HiNet In the 68k world, we usually mark the resident CODE segments LOCKED and PRELOADED, to avoid memory fragmentation. But under the Power Macintosh runtime architecture, these preloaded CODE segments just waste memory. So how should I do to these CODE resources in the fat binaries? Currently I put the following piece of code at the beginning of my program, and it looks ugly. Are there any better methods? #ifdef __powerc for (short seg_idx = Count1Resources('CODE'); seg_idx > 0; --seg_idx) { SetResLoad(false); Handle seg = Get1IndResource('CODE', seg_idx); SetResLoad(true); if (seg) ReleaseResource(seg); } #endif Hao-yang Wang Pai Technology, Inc. Taipei +++++++++++++++++++++++++++ >From gurgle@dnai.com (Pete Gontier) Date: Fri, 09 Sep 1994 12:48:15 -0800 Organization: Integer Poet Software In article <34p6c4$jqo@serv.hinet.net>, paitech@hntp2.hinet.net (paitech) wrote: > In the 68k world, we usually mark the resident CODE segments LOCKED and > PRELOADED, to avoid memory fragmentation. But under the Power Macintosh > runtime architecture, these preloaded CODE segments just waste memory. > So how should I do to these CODE resources in the fat binaries? Currently > I put the following piece of code at the beginning of my program... [code to get and release code segments omitted] Interesting problem. I realized you have a problem just the opposite of the one I try to solve in my code, which is that pre-loaded segments don't work the same when your app is not an app (i.e. when it's a TPM project). See, in that case you have to go get the code segments yourself and lock them low in the heap. I think this is useful information for you because (1) it's an example of someone else doing a disgusting hack against the CODE resources and pretty much getting away with it, and (2) it provides you with code you might want to use instead of marking your segments pre-loaded. That way, for the PPC version, you can simply omit the code. ////////////////////////////////////////////////////////////////////////////// #if defined (THINK_C) || defined (applec) // Note selectivity of above compilers; under Metrowerks we // assume the linker has been set to merge the whole app into // one huge resource. Probably we should later include an // explicit check for this, but right now I am using the // CD ROM drive for music and can't look up the symbols. :-/ static OSErr MacLow_Init_LoadCODEs (void) { OSErr oe = noErr; // This code attempts to load all the code segments low in the heap and // lock them down. If we're not running under TPM, this should have been // done already for us by the fact that all the code resources should be // marked pre-load and lock in the resource map. If we are, we need to // take extra steps. // // First, we check to see if we are running under TPM. Since the TPM // opens an external, non-CODE resource file on top of the project file, // where the CODE resources live, we can search the top resource file for // CODEs to find out if the TPM has done this. And an easy way to do this // is Count1Resources. Boolean tpmRunning = false; short code = Count1Resources ('CODE'); if (!(oe = ResError ( )) && !code) { // OK, now we know we are running under TPM. // We need to get the "real" count of the CODE resources. // We can do this by searching beyond the current file, // which will catch the CODEs in the project. tpmRunning = true; code = CountResources ('CODE'); oe = ResError ( ); } if (!oe) { // Now index all of // them and get their IDs without loading them, reserve // space for them at the bottom of the heap, load them, // and lock them. Handle codeH; Size size; short id; ResType type; Str255 name; if (code) { Boolean oldResLoad = LMGetResLoad ( ); SetResLoad (false); do { if (tpmRunning) codeH = GetIndResource ('CODE', code); else codeH = Get1IndResource ('CODE', code); oe = ResError ( ); if (oe) break; GetResInfo (codeH, &id, &type, name); oe = ResError ( ); if (oe) break; // Skip the jump table and the startup code. // This should be more intelligent about how // various linkers handle their startup code. // It's presently set up for THINK, but may // work in other cases. if (id != 0 && id != 1) { size = GetResourceSizeOnDisk (codeH); oe = ResError ( ); if (oe) break; ReserveMem (size); oe = MemError ( ); if (oe) break; LoadResource (codeH); oe = ResError ( ); if (oe) break; HLock (codeH); oe = MemError ( ); if (oe) break; HNoPurge (codeH); // just for paranoia oe = MemError ( ); if (oe) break; } } while (--code); SetResLoad (oldResLoad); } } return (oe); } #endif -- Pete Gontier // CTO, Integer Poet Software // gurgle@dnai.com "The need to be (or appear to be) sophisticated pervades the very atmosphere in which we, the Magazine Reading Class, move." -- Ellis Weiner, Spy Magazine, 9/94 +++++++++++++++++++++++++++ >From paitech@hntp2.hinet.net (paitech) Date: 10 Sep 1994 18:51:43 GMT Organization: NCTU News Server, HiNet Pete Gontier (gurgle@dnai.com) wrote: : much getting away with it, and (2) it provides you with code you might : want to use instead of marking your segments pre-loaded. That way, for the : PPC version, you can simply omit the code. But you still have to preload the main segment (i.e. CODE 1), right? Hao-yang Wang Pai Technology, Inc. Taipei +++++++++++++++++++++++++++ >From gurgle@dnai.com (Pete Gontier) Date: Sat, 10 Sep 1994 18:14:54 -0800 Organization: Integer Poet Software In article <34sv7v$8hr@serv.hinet.net>, paitech@hntp2.hinet.net (paitech) wrote: > Pete Gontier (gurgle@dnai.com) wrote: > : much getting away with it, and (2) it provides you with code you might > : want to use instead of marking your segments pre-loaded. That way, for the > : PPC version, you can simply omit the code. > > But you still have to preload the main segment (i.e. CODE 1), right? I'm not terribly familiar with the PPC code model, so it's possible you might have to do this, but I think it's always a pretty safe assumption that if your code is running, CODE 1 loaded successfully. :-) -- Pete Gontier // CTO, Integer Poet Software // gurgle@dnai.com "The need to be (or appear to be) sophisticated pervades the very atmosphere in which we, the Magazine Reading Class, move." -- Ellis Weiner, Spy Magazine, 9/94 +++++++++++++++++++++++++++ >From paitech@hntp2.hinet.net (paitech) Date: 11 Sep 1994 08:50:52 GMT Organization: NCTU News Server, HiNet Pete Gontier (gurgle@dnai.com) wrote: : > But you still have to preload the main segment (i.e. CODE 1), right? : I'm not terribly familiar with the PPC code model, so it's possible you : might have to do this, but I think it's always a pretty safe assumption : that if your code is running, CODE 1 loaded successfully. :-) Let me make my question clearer: You suggested that instead of marking the resident segments PRELOADED, we can also load them manually at runtime. This is a good idea (It cannot be bad because MacApp has done it in a similar way since 1.0.), but when your code is executed (under 68k), the main segment is already loaded (into the middle of the heap?) and it is already too late to reallocate the main segment. So the main segment should still be marked as PRELOADED and we still have to release it under PPC, right? Hao-yang Wang Pai Technology, Inc. Taipei +++++++++++++++++++++++++++ >From h+@nada.kth.se (Jon W{tte) Date: Sun, 11 Sep 1994 19:47:54 +0200 Organization: Royal Institute of Something or other In article <34ugdc$pqk@serv.hinet.net>, paitech@hntp2.hinet.net (paitech) wrote: >You suggested that instead of marking the resident segments PRELOADED, we can >also load them manually at runtime. This is a good idea (It cannot be bad >because MacApp has done it in a similar way since 1.0.), but when your code is >executed (under 68k), the main segment is already loaded (into the middle of >the heap?) and it is already too late to reallocate the main segment. >So the main segment should still be marked as PRELOADED and we still have to >release it under PPC, right? No. The Segment Loader loads CODE 0 and whatever's referenced by the first jump table entry for you. At this time, the heap is really small (MaxApplZone() hasn't been called) and there's nothing else in it (what would it be? No memory allocation's been done) so that CODE resource is loaded snugly in the heap; no fragmentation. If your main() function is not in the same segment as the startup loader bootstrap (runtime library) you'll have a third CODE resource load before you get to the start of main, and still MaxApplZone() isn't called and no non-permanent memory is allocated to there's no chance of fragmentation. So, don't mark CODE 0 or CODE 1 (or ANY CODE) pres a particular video card. Issue a status call to the driver, with csCode=11, and csParam containing a pointer to a data area of 6 bytes. I don't think it matters what you place in this data area, but Apple places zeros there, so I'd do that too. If this control call does not return an error, then the Energy Saver driver is installed for that monitor. 2. To enter Energy Saving mode. Step through the graphics device list. For each device, determine if Energy Saver is installed for that device using that above test. For each that it is, do a control call with csCode=11 (that's decimal 11, not hex 11), and csParam containing a pointer to a data area of six bytes. In that six bytes, place the following: 0x01, 0x01, 'H', 'A', 'L', ' '. 3. To exit Energy Saving mode. This is similar to entering Energy Saving mode, except that those first two bytes of the six byte data area should be 0x00 and 0x00 instead of 0x01 and 0x01. After you've turned everything on, for each monitor do a status call with csCode=11, and csParam containing a pointer to six bytes of data. Fill out that data area with 0x00, 0x00, 'H', 'A', 'L', ' ' before doing the call. After the status call, check byte 1 of the six byte data area (numbered from 0). If that byte ANDed with 0x80 is non-zero, then do the following: short temp = (*g)->gdMode & 0xffff; (*g)->gdMode = 0; SetDepth(g,temp,0,0); where g is a handle to the GDevice record for the monitor. After you've set the depth on all the monitors that need it, call DrawMenuBar. 4. Some observations. I don't think it matters whether or not the 'HAL ' stuff is placed in the six byte data area in the control and status calls. I didn't notice anything that checked for this in the driver that handles these calls when I disassembled them. Energy Saving mode seems to scramble some of the VRAM. When it comes out of Energy Saving mode, there are random colored pixels scattered around. That business with SetDepth seems to be to get everyone to update the screen. If you are doing this from a screen saver, presumably you will already be making everyone redraw, so you probably don't need this. The status call seems to modify the first two bytes of the six byte data area pointed to be csParam. I do not know what the significance of byte 1 is, other than it seems to contain that flag that tells if the monitor needs to have the screen redrawn to clean up the garbage. Byte 0 seems to get written with 0x00 if the monitor is not in Energy Saving mode, and 0xFF if it is. Apple's software does not seem to make use of this, so it is not clear that it is safe to rely on it. 5. Sample code. Here is a simple program fragment that enters Energy Saving mode, waits for a mouse click, and then leaves Energy Saving mode. CntrlParam c; GDHandle g; OSErr e; short res[3]; // the six byte data area // // We'll just do the first screen // g = GetDeviceList(); c.ioCRefNum = (*g)->gdRefNum; c.csCode = 11; res[0] = 0; res[1] = 0; res[2] = 0; *(short **)(&c.csParam[0]) = &res[0]; c.ioCompletion = 0; e = PBStatus( (ParmBlkPtr)&c, 0 ); if ( e ) { cout << "Energy Saver not supported!" << endl; return; } // // Turn monitor off // c.ioCRefNum = (*g)->gdRefNum; c.csCode = 11; res[0] = 0x0101; res[1] = 'HA'; res[2] = 'L '; *(short **)(&c.csParam[0]) = &res[0]; c.ioCompletion = 0; e = PBControl( (ParmBlkPtr)&c, 0 ); // // Pause until the mouse is clicked // while ( ! Button() ) ; while ( Button() ) ; // // Turn monitor back on // c.ioCRefNum = (*g)->gdRefNum; c.csCode = 11; res[0] = 0x0000; res[1] = 'HA'; res[2] = 'L '; *(short **)(&c.csParam[0]) = &res[0]; c.ioCompletion = 0; e = PBControl( (ParmBlkPtr)&c, 0 ); // // See if we need to set the depth to clean up the garbage // c.ioCRefNum = (*g)->gdRefNum; c.csCode = 11; res[0] = 0; res[1] = 'HA'; res[2] = 'L '; *(short **)(&c.csParam[0]) = &res[0]; c.ioCompletion = 0; e = PBStatus( (ParmBlkPtr)&c, 0 ); if ( res[0] & 0x0080 ) { short temp = (*g)->gdMode & 0xffff; (*g)->gdMode = 0; SetDepth(g,temp, 0, 0 ); } --------------------------- >From altitude@umich.edu (Alex Tang) Subject: Newbie Gworld questions. Date: 3 Jul 1994 14:11:22 GMT Organization: University of Michigan Hi folks. I've got some pretty newbie'ish questions about Gworlds... First, i haven't been able to find a good explaination about what they're used for. From the various bits of info that I've picked up, they comprise of a lot of different graphics devices and tools (i.e. offscreen drawing). Is that right? Is the main purpose for them so that offscreen drawing is easier? The main reason i'm asking is that I'm trying to write a small, rudamentary graphics app. It's something to teach me how to do mac programming. Basically, it's supposed be able to open some windows, do some drawing into the wndows, and save the file as a PICT. I've hit a minor roadblock trying to figure out how where to draw the stuff and be able to do updates on it. At first, I thought I could draw directly to the window, but that didn't work. I'm trying to figure out if i need to use gworlds for this (and i guess i should learn about them anyway). Well, Thanx for any insight that is provided. ...alex... -- Alex Tang | UM-SNRE | UM-ITD/US Consultant II ALTITUDE@UMICH.EDU | Student | http://www.snre.umich.edu/~altitude PGP via finger. | Systems Admin | "Life's a game. This space for rent| Comp.Consut III | play for fun, and play with Honor." +++++++++++++++++++++++++++ >From gurgle@netcom.com (Pete Gontier) Date: Mon, 4 Jul 1994 01:06:54 GMT Organization: cellular altitude@umich.edu (Alex Tang) writes: >Is the main purpose for (GWorlds) so that offscreen drawing is easier? >The main reason i'm asking is that I'm trying to write a small, >rudamentary graphics app. ...it's supposed be able to open some >windows, do some drawing into the wndows, and save the file as a PICT. The question should be then, whether this drawing is going to require you to use CopyBits. CopyBits is the routine used to shove bit maps and pixel maps around in memory, on-screen and off-screen and in between the two. You need it only if you need to do some image processing which occurs as a side-effect of calls to CopyBits (colorizing bitmaps, dithering, blending pixel maps, etc.) *or* you're trying to do some updating which needs to be smooth or animated. If the answer to this sort of question is "no", then don't bother with GWorlds. Stick with Pictures. They're easier to deal with and they can be translated almost directly into PICT files (such files are 512 bytes of 0 followed by the contents of a PicHandle). >I've hit a minor roadblock trying to figure out how where to draw the >stuff and be able to do updates on it. At first, I thought I could draw >directly to the window, but that didn't work... Yes, and I understand the problem. Pictures will allow you to get around this quite nicely, and in general in less memory than GWorlds, too. Happy reading! -- Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com "...someone not acquainted with the Christian mythology of the Crucifixion might consider a Crucifix to be a particularly sadistic piece of erotica... We of the ACLU will continue to defend your right to worship such objects if it pleases you." -- Gregory J. Wageman +++++++++++++++++++++++++++ >From Mark Hanrek Date: Mon, 4 Jul 1994 21:03:07 GMT Organization: The Information Workshop In article <2v6gua$62j@lastactionhero.rs.itd.umich.edu> Alex Tang, altitude@umich.edu writes: > Hi folks. I've got some pretty newbie'ish questions about Gworlds... > > First, i haven't been able to find a good explaination about what they're > used for. From the various bits of info that I've picked up, they > comprise of a lot of different graphics devices and tools (i.e. offscreen > drawing). Is that right? Is the main purpose for them so that offscreen > drawing is easier? > > The main reason i'm asking is that I'm trying to write a small, > rudamentary graphics app. It's something to teach me how to do > mac programming. Basically, it's supposed be able to open some windows, > do some drawing into the wndows, and save the file as a PICT. I've hit a > minor roadblock trying to figure out how where to draw the stuff and be > able to do updates on it. At first, I thought I could draw directly to > the window, but that didn't work. I'm trying to figure out if i need to > use gworlds for this (and i guess i should learn about them anyway). > > Well, Thanx for any insight that is provided. > > ...alex... Alex, Here is the answer to all of your questions at once. It is the answer you were looking for... As an illustrative example, let's say your application has one window which contains an XY bar graph of some data you have. This graph would, of course, have the XY lines, the tick marks, the numbers for the tick marks, the titles, the data bars, etc, all made up of a series of QuickDraw calls, such as MoveTo, LineTo, FrameRect, PaintRect, DrawString, etc. - --- Setting up your application All "imaging" for this window should happen ONLY in response to the "update" event that is sent to this window. Period. Your update event handler should look something like this... void DoUpdateEvent( WindowPtr theWindow ) { BeginUpdate( theWindow ); DrawWindowContents( theWindow ); EndUpdate( theWindow ); } The routine "DrawWindowContents" should draw EVERYTHING that appears in your window whenever it is called regardless. This is the correct thing to do. A window should always start life this way. Do NOT put any calls to draw this window anywhere else in your software. No exceptions. When the window is created, an update event will automatically be sent to it. Convenient. And if there is some reason you need to update a certain area of your window (and the system didn't ask you to), you can do this by "invalidating" the desired area of your window, by calling InvalRect(). This triggers an update event to have that area of the window "cleaned up". In your update event handler, you must use the BeginUpdate and EndUpdate calls, allowing you to take advantage of the Window Manager, which keeps track of which part of your window actually needs to be re-drawn. ( The update region ). Your DrawWindowContents() routine will blindly draw everything to this window, but the OS will automatically cut short any QuickDraw calls that draw to areas of the window that do not actually need updating. Even with this automatic built-in optimization, if you have a very complex drawing, you will find that updating the window can be sluggish, and you can see all the individual elements being re-drawn, as you do can in, say, a complex MacDraw or Canvas drawing. This is where GWorlds come in handy... - --- Incremental Improvement #1 In response to the update event, create a GWorld the same size as your window, draw the whole image into the GWorld instead, and then draw the entire GWorld to the window all at once using CopyBits, then dispose of the GWorld. This makes it so the user does not see all the individual elements being redrawn. This is what happens when you do a "lock screen" then an "unlock screen" in HyperCard. This does not, however, eliminate the time it takes to draw all the individual elements. If you were to, say, move another window that overlaps the bar graph window by just one pixel, an update event would, of course, be sent to your bar graph window, and it would spend the time redrawing the scores of things that make up the image. To help optimize that, we can take the usage of our GWorld a step further... - --- Incremental Improvement #2 When you create your window for the first time, also create a GWorld the same size as your window, and have DrawWindowContents() draw its image into the GWorld instead, once only, to "prep" the GWorld. Then from that point on, in response to an update event, simply use CopyBits to transfer the ENTIRE GWorld to the entire window. The Window Manager will only allow the needed areas to actually be transferred, and you will now have the most efficient and optimal way of handling the imaging of window contents. Your window updating will now be instantaneous, and there will be no sluggishness. When you close the window, dispose of the GWorld too. - --- Important Note This explanation is a lot like putting you in a row boat and giving you a starting push in the direction of that little reef offshore you want to get to. You do not need to know all about boats, all about the ocean, and all about propulsion in order to make it to that little reef successfully. You also do not need to know at this time how to handle things differently if you were hypothetically put in an outrigger instead. Don't allow yourself or others to unnecessarily complicate things. Take this simple push and go with it, and you will quickly "get it". - --- Following Advice Mark my words. If you put drawing-to-window code anywhere else than in your update handler, you will find that a good chunk of your code, and the time it took to develop it, ends up being spent on compensating for the problems and side-effects that were created as a result of not following this sage advice. I made this mistake myself when I first started, and paid a hefty price for it, too. Hopefully you can avoid the waste of repeating this common (and undocumented) programming error. Hope this helps! Mark Hanrek The Information Workshop - ---------------------------------- P.S. The other undocumented programming error waiting to eat you is mixing the use of GetPort/SetPort and GetGWorld/SetGWorld in the same application. The minute you start working with GWorlds, eliminate all uses of GetPort/SetPort from your application, changing them all to the more modern GetGWorld/SetGWorld. Ouch! +++++++++++++++++++++++++++ >From kenlong@netcom.com (Ken Long) Date: Tue, 5 Jul 1994 17:04:15 GMT Organization: NETCOM On-line Communication Services (408 261-4700 guest) For more reading on GWorlds, get "Programming QuickDraw" by Surovell, Hall and Othmer. For an example of an application comparison WITHOUT and WITH GWorlds (GWorld added by Mark Hanrek) get NuCube and NewCube C source demos. (I believe they are on sumex, in a file called "ThreePointPlotters" or "WireFrameORama"). There are excellent, comprehenhive examples of GWorld C sources on ftp.apple.com (GWorld Drawing - not an app. source, but several routines) and "GWorlds" from devtools.symantec.com - source for a complete application. Of course, there are many more, too. cicnAnimDemo uses GWorlds. I was told, by a downloader of NuCude (which Mark contributed to), that he really gained a lot of understanding of them from the source. Well, Mark understands them - that's why. -Ken- --------------------------- >From brewster@enc.org (Dave Brewster) Subject: Patching Trap ExitToShell using UniversalProcPtr's Date: 5 Jul 1994 01:38:45 -0400 Organization: Eisenhower National Clearinghouse How does one go about doing this on the PPC. I've tried: SetToolTrapAddress(MyExitToShellUPP, _ExitToShell); where MyExitToShellUPP = NewRoutineDescriptor((ProcPtr)(MyExitToShell), kCStackBased, GetCurrentISA()); I figured this would be correct, but it dies a violent death! Is the kCStackBased parameter wrong? My routine doesn't take any parameters so I'm not or'ing this with anything. Oh yea, and it doesn't return anything either. My ExitToShell routine looks like: void MyExitToShell (void) { SetCurrentA5(); SetToolTrapAddress(gOldExitToShellTrapAddress, _ExitToShell); EndNNTP(); NetTerm(); ExitToShell(); } What's the deal, Dave +++++++++++++++++++++++++++ >From stevec@jolt.mpx.com.au (Stephen F Coy) Date: 5 Jul 1994 13:52:33 GMT Organization: Microplex Pty Ltd Dave Brewster (brewster@enc.org) wrote: : How does one go about doing this on the PPC. I've tried: : SetToolTrapAddress(MyExitToShellUPP, _ExitToShell); : where MyExitToShellUPP = : NewRoutineDescriptor((ProcPtr)(MyExitToShell), kCStackBased, : GetCurrentISA()); : I figured this would be correct, but it dies a violent death! : Is the kCStackBased parameter wrong? My routine doesn't take any : parameters so I'm not or'ing this with anything. Oh yea, and it doesn't : return anything either. : My ExitToShell routine looks like: : void MyExitToShell (void) : { : SetCurrentA5(); : SetToolTrapAddress(gOldExitToShellTrapAddress, _ExitToShell); : EndNNTP(); : NetTerm(); : ExitToShell(); : } If you use the standard C library function "atexit" instead you would not have to worry about all this stuff. In general, you should avoid patching traps. Most of the time it is not necessary. : What's the deal, : Dave Steve Coy Resolve Software (WA) P/L +++++++++++++++++++++++++++ >From wdh@netcom.com (Bill Hofmann) Date: Tue, 5 Jul 1994 16:11:42 GMT Organization: Fresh Software In article <199407050538.FAA08919@charm.magnus.acs.ohio-state.edu>, brewster@enc.org (Dave Brewster) wrote: > How does one go about doing this on the PPC. I've tried: > SetToolTrapAddress(MyExitToShellUPP, _ExitToShell); > where MyExitToShellUPP = > NewRoutineDescriptor((ProcPtr)(MyExitToShell), kCStackBased, > GetCurrentISA()); > > I figured this would be correct, but it dies a violent death! > > Is the kCStackBased parameter wrong? My routine doesn't take any > parameters so I'm not or'ing this with anything. Oh yea, and it doesn't > return anything either. > > My ExitToShell routine looks like: > > void MyExitToShell (void) > { > SetCurrentA5(); > SetToolTrapAddress(gOldExitToShellTrapAddress, _ExitToShell); > EndNNTP(); > NetTerm(); > ExitToShell(); > } Well, with few exceptions, the entire toolbox is either kPascalStackBased or kRegisterBased. So you have two (well, 1.5) problems: MyExitToShellUPP = NewRoutineDescriptor((ProcPtr)MyExitToShell, kPascalStackBased, GetCurrentISA()); ... pascal void MyExitToShell(void) { ... } I say 1.5 because a pascal void ... (void) is pretty much the same as a void ... (void), but better to be compulsive than sorry. I assume that you init gOldExitToShellTrapAddress. Does your code (minus the NewRoutineDescriptor()) work on 040 machines? -- Bill Hofmann wdh@netcom.com Fresh Software and Instructional Design voice: +1 510 524 0852 1640 San Pablo Ave #C, Berkeley CA 94702 USA fax: +1 510 524 0853 +++++++++++++++++++++++++++ >From kbell@cs.utexas.edu (Kevin Bell) Date: Tue, 05 Jul 1994 18:34:35 -0600 Organization: The University of Texas at Austin, Austin, Texas In article <199407050538.FAA08919@charm.magnus.acs.ohio-state.edu>, brewster@enc.org (Dave Brewster) wrote: > How does one go about doing this on the PPC. I've tried: > SetToolTrapAddress(MyExitToShellUPP, _ExitToShell); > where MyExitToShellUPP = > NewRoutineDescriptor((ProcPtr)(MyExitToShell), kCStackBased, > GetCurrentISA()); > > I figured this would be correct, but it dies a violent death! > > Is the kCStackBased parameter wrong? My routine doesn't take any > parameters so I'm not or'ing this with anything. Oh yea, and it doesn't > return anything either. > > My ExitToShell routine looks like: > > void MyExitToShell (void) > { > SetCurrentA5(); > SetToolTrapAddress(gOldExitToShellTrapAddress, _ExitToShell); > EndNNTP(); > NetTerm(); > ExitToShell(); > } > > What's the deal, > > Dave Here's the code I used to do the same thing // KMB: ExitToShell UPP Info static UniversalProcPtr gOldExitToShellTrapAddress; enum { exitToShellProcInfo = kPascalStackBased }; static void PatchExitToShell (void) { UniversalProcPtr MyExitToShellUPP = NewRoutineDescriptor((ProcPtr)MyExitToShell, exitToShellProcInfo, GetCurrentISA()); gOldExitToShellTrapAddress = GetToolTrapAddress(_ExitToShell); SetToolTrapAddress(MyExitToShellUPP, _ExitToShell); } BTW, thanks for asking this question. When I tried to open the source code with my PowerMac compiled NewsWatcher, I discovered some errors with my standard file UPP stuff. IMHO, universal procedure pointers have a serious problem in that the compiler cannot do any type checking like it could for regular function pointers. In my case, I was creating a FileFilterUPP where a ModalFilterUPP was needed. -- Kevin Bell kbell@cs.utexas.edu --------------------------- >From gtodorov@ralph.cs.haverford.edu (Gordan Todorovac) Subject: Porting from Unix to Mac - Summary Date: 1 Jul 1994 17:29:34 GMT Organization: Haverford College Computer Science Department Thanks to all who replied. Here is the content of three replies which summarize what was said: >From millsp@gov.on.ca Fri Jul 1 07:22:10 1994 I haven't used version 5 for a year or more, but I'm quite sure that malloc was available...#include and add the ANSI library to your project certainly works in v6 and its not something new I've added during the upgrade. If you're looking to move away from Unix-isms, there are Toolbox calls, NewPtr and DisposPtr, for memory management. (I've done a few small ports of things that started on Unix. My major problems have been trying to understand library calls that don't exist and don't seem to have matching concepts on the Mac...fork? yfork?...but most of them should be there.) >From gardner@osm7.cs.byu.edu Fri Jul 1 10:32:54 1994 I port code from the Unix to the Mac and from the Mac to Unix all the time (and to the PC in between). The main thing to keep in mind is *not* to use UNIXisms or MACisms (or PCisms). If you program in strictly ANSI C, you will not have a problem going either direction. Now that does eliminate taking advantage of platform specific features. But thats actually what portability is all about. As for malloc, include stdlib.h for the prototype and add ANSI to your project and you are all set. Note: THINK C gives you a set of unix-like functions in unix.h that help you compile *some* code containing some UNIXisms. However, most do not implement the semantics/behavior of the unix function (mostly because they have no MAC equivalent). I would not use them except as a last resort. >From VCHAVARR@samnet.jsc.nasa.gov Fri Jul 1 11:27:52 1994 One of the biggest differences between Mac and Unix systems is the way the operating system allocates memory. Unix uses pointers, Macs use handles, which are pointers to pointers. The malloc function tells the Unix system to allocate a certain amount of memory and returns a pointer to it. Macs use a function called NewHandle to allocate a block of memory, and a handle is returned. There is a Mac function called NewPtr (in the memory.h file, I believe), which allocates a block of memory and returns a pointer to it. Allocating memory on a Mac with pointers, however, can be a bad idea because memory segmentation can occur, especially if you are allocating a lot of memory. You could replace all of the mallocs in your code with NewPtr, if you're not worried about memory segmentation. This has the advantage of you not having to make changes to your code in the parts where pointers are referenced. If you use NewHandle to replace malloc, however, you will have to go and find all of the places where pointers are referenced and make some changes. Another area of difference between Unix and Macs are in the functions which are used to handle files. You can expect problems in this area if your Unix program reads or writes files. - ------------------------------- --Gordan --------------------------- >From rick@akbar.cc.utexas.edu (Rick Watson) Subject: Problems with Metrowerks vs. MPW 68k C calling conventions Date: 29 Jun 1994 18:43:25 GMT Organization: The University of Texas at Austin, Austin, Texas Metrowerks 68k C passes short values on the stack as 16-bit values where MPW uses 32 bits. This causes problems when trying to call MPW generated code modules, including MacTCP's domain resolver code called by DNR.c. Is there an easy workaround for this that does NOT involve prototyping the short values as longs? Rick Watson The University of Texas Computation Center, Networking Services, 512/471-8220 r.watson@utexas.edu +++++++++++++++++++++++++++ >From edandavi@well.sf.ca.us (Ed Allen and Avi Rappoport) Date: 29 Jun 1994 22:47:27 GMT Organization: The Whole Earth 'Lectronic Link, Sausalito, CA rick@akbar.cc.utexas.edu (Rick Watson) writes: >Metrowerks 68k C passes short values on the stack as 16-bit >values where MPW uses 32 bits. This causes problems when trying >to call MPW generated code modules, including MacTCP's >domain resolver code called by DNR.c. >Is there an easy workaround for this that does NOT involve prototyping >the short values as longs? Nope, there is no easy workaround. Pascal libraries are fine, but C libraries have different parameter passing conventions, as you note above. If you can get the source, compile it in MW. Sorry. -- Avi Rappoport (account also used by Ed Allen) Systems Analyst and Technical Diplomat metrowerks, Inc. Please reply to: avirr@metrowerks.ca avirr@aol.com avirr@eworld.com +++++++++++++++++++++++++++ >From mwron@aol.com (MW Ron) Date: 29 Jun 1994 17:35:04 -0400 Organization: America Online, Inc. (1-800-827-6364) In article <2usfcd$55p@geraldo.cc.utexas.edu>, rick@akbar.cc.utexas.edu (Rick Watson) writes: >>Metrowerks 68k C passes short values on the stack as 16-bit values where MPW uses 32 bits. Is there an easy workaround for this that does NOT involve prototyping the short values as longs? Did you change the structure allignment in your preferences Processor for 4 byte int and 8 byte doubles, and use the proper Libraries? I am not an MPW user so if this isn't the fix, please reply. Ron Liechty mwron@aol.com Metrowerks Inc. +++++++++++++++++++++++++++ >From johnmce@world.std.com (John McEnerney) Date: Thu, 30 Jun 1994 05:42:45 GMT Organization: The World Public Access UNIX, Brookline, MA rick@akbar.cc.utexas.edu (Rick Watson) writes: >Metrowerks 68k C passes short values on the stack as 16-bit >values where MPW uses 32 bits. This causes problems when trying >to call MPW generated code modules, including MacTCP's >domain resolver code called by DNR.c. The problem is that although you may declare an argument 'short' or 'char' in MPW C, it will pass it as 32-bits. This was common in K&R compilers but is rare in ANSI compilers (THINK C does it the same way that we do) The trick is to fool CW by declaring all integer arguments as 'long' in the prototype (including enums). Then the arguments will be properly extended to 32-bits. -- John McEnerney, Metrowerks PowerPC Product Architect +++++++++++++++++++++++++++ >From creiman@netcom.com (Charlie Reiman) Date: Fri, 1 Jul 1994 05:36:05 GMT Organization: NETCOM On-line Communication Services (408 261-4700 guest) mwron@aol.com (MW Ron) writes: >In article <2usfcd$55p@geraldo.cc.utexas.edu>, >rick@akbar.cc.utexas.edu (Rick Watson) writes: >>>Metrowerks 68k C passes short values on the stack as 16-bit >values where MPW uses 32 bits. >Is there an easy workaround for this that does NOT involve >prototyping >the short values as longs? >Did you change the structure allignment in your preferences Processor >for 4 byte int and 8 byte doubles, and use the proper Libraries? I >am not an MPW user so if this isn't the fix, please reply. >Ron Liechty >mwron@aol.com >Metrowerks Inc. Think C has the exact same feature, even with 4 byte ints turned on. I did call up Symantec tech support and argue about this. I can no longer quote the K&R ANSI page number, but the behavior you are seeing is not incorrect. It's stupid, but not incorrect. You need prototypes under Think, MW may have another solution. -- "You can't cancel the project! We already made the T-shirts!" Charlie Reiman creiman@netcom.com +++++++++++++++++++++++++++ >From StevenEllis@microapl.demon.co.uk (Steven Ellis) Date: Thu, 30 Jun 1994 10:50:06 GMT Organization: MicroAPL In article <2usfcd$55p@geraldo.cc.utexas.edu> rick@akbar.cc.utexas.edu (Rick Watson) writes: >Metrowerks 68k C passes short values on the stack as 16-bit >values where MPW uses 32 bits. This causes problems when trying >to call MPW generated code modules, including MacTCP's >domain resolver code called by DNR.c. > >Is there an easy workaround for this that does NOT involve prototyping >the short values as longs? If you look in the compiler preferences there is an option to use 4byte short values. > >Rick Watson >The University of Texas Computation Center, Networking Services, 512/471-8220 > r.watson@utexas.edu > Steven Ellis +++++++++++++++++++++++++++ >From johnmce@world.std.com (John McEnerney) Date: Fri, 1 Jul 1994 15:23:53 GMT Organization: The World Public Access UNIX, Brookline, MA creiman@netcom.com (Charlie Reiman) writes: >>>>Metrowerks 68k C passes short values on the stack as 16-bit >>values where MPW uses 32 bits. >>Is there an easy workaround for this that does NOT involve >>prototyping >>the short values as longs? >Think C has the exact same feature, even with 4 byte ints turned on. I >did call up Symantec tech support and argue about this. I can no longer >quote the K&R ANSI page number, but the behavior you are seeing is not >incorrect. >It's stupid, but not incorrect. Everybody thinks that they're a compiler designer... The ANSI standard clarified that when an argument is declared 'float', 'char' or 'short' it does not have to be widened to 'double' or 'int' when passed as an argument. (The only exception is when there is no prototype or for arguments matching the "...") It also clarified that a compiler is not required to pass arguments in reverse order when the number of arguments in known. This permits ANSI compilers to generate much better code, in this case avoiding an EXT.W for each argument passed. Some compilers (including Symantec C++ I think) will pass arguments in the order that they are declared and will have the calleee strip the arguments, again contrary to K&R practice, but also usually more efficient. I don't see why every compiler for the Mac has to be saddled with the calling conventions of a compiler that Apple hasn't done any work on in 5 years. -- John McEnerney, Metrowerks PowerPC Product Architect +++++++++++++++++++++++++++ >From Jens Alfke Date: Fri, 1 Jul 1994 18:36:29 GMT Organization: Apple Computer Steven Ellis, StevenEllis@microapl.demon.co.uk writes: > If you look in the compiler preferences there is an option to use 4byte short > values. No, there is an option to use 4byte ints. shorts are always two bytes on every Mac compiler (and on just about every other C compiler in the world, with a few exceptions.) And shorts will always be pushed as 2 bytes by every Mac compiler except MPW C. I understand that Apple, Symantec and Metrowerks are hammering out a standard C calling convention to be used by all their compilers, at least optionally via pragmas. This becomes important with CFM and SOM on 68k, where C calling conventions are used. (On PPC of course there is already one standard set of calling conventions.) --Jens Alfke jens_alfke@powertalk Rebel girl, rebel girl, .apple.com Rebel girl you are the queen of my world +++++++++++++++++++++++++++ >From creiman@netcom.com (Charlie Reiman) Date: Sat, 2 Jul 1994 00:43:50 GMT Organization: NETCOM On-line Communication Services (408 261-4700 guest) johnmce@world.std.com (John McEnerney) writes: >creiman@netcom.com (Charlie Reiman) writes: >>>>>Metrowerks 68k C passes short values on the stack as 16-bit >>>values where MPW uses 32 bits. >>>Is there an easy workaround for this that does NOT involve >>>prototyping >>>the short values as longs? >>Think C has the exact same feature, even with 4 byte ints turned on. I >>did call up Symantec tech support and argue about this. I can no longer >>quote the K&R ANSI page number, but the behavior you are seeing is not >>incorrect. >>It's stupid, but not incorrect. >Everybody thinks that they're a compiler designer... >The ANSI standard clarified that when an argument is declared 'float', >'char' or 'short' it does not have to be widened to 'double' or 'int' >when passed as an argument. (The only exception is when there is no >prototype or for arguments matching the "...") It also clarified that a >compiler is not required to pass arguments in reverse order when the >number of arguments in known. >This permits ANSI compilers to generate much better code, in this case >avoiding an EXT.W for each argument passed. Some compilers (including >Symantec C++ I think) will pass arguments in the order that they are >declared and will have the calleee strip the arguments, again contrary to >K&R practice, but also usually more efficient. >I don't see why every compiler for the Mac has to be saddled with the >calling conventions of a compiler that Apple hasn't done any work on in 5 >years. Don't get me wrong. I understand what you are trying to do. I just think the anguish it causes developers isn't worth the win in compiler speed. Calling it 'stupid' may have been harsh but you weren't here when I had to debug the problem it caused. Nor were you here when I had to wedgie protoypes on top of 300,000+ lines of complex cross-platform code to avoid future problems. I may not be a compiler designer, but I sure do beat the crap out of them. I know what breaks and I simply have to disagree with you. -- "You can't cancel the project! We already made the T-shirts!" Charlie Reiman creiman@netcom.com +++++++++++++++++++++++++++ >From Lars.Farm@nts.mh.se (Lars Farm) Date: Sat, 02 Jul 1994 11:56:40 +0100 Organization: Mid Sweden University In article <1994Jul1.183629.27436@gallant.apple.com>, Jens Alfke wrote: > I understand that Apple, Symantec and Metrowerks are hammering out a standard > C calling convention to be used by all their compilers, at least optionally > via pragmas. This becomes important with CFM and SOM on 68k, where C calling > conventions are used. (On PPC of course there is already one standard set of > calling conventions.) Isn't this a place for extern "OtherCallingConvention" void foo(int); as in extern "C", or extern "MPW", or extern "ASLM", or extern "SOM", or extern "CFM", or extern "Pascal", ... leaving internal calling conventions as an implementation detail to the specific compiler vendor? Instead of #pragmas or worse - project wide preferences. Lars -- Lars.Farm@nts.mh.se --------------------------- >From dnebing@bgsu.edu ( Mr. Neb) Subject: Special #define for Univ. Hdrs? Date: 3 Jul 1994 04:16:21 GMT Organization: Bowling Green State University Here's a quicky: I just got done adding Univ. Hdrs. to TC7.0.3 (headers from develop 18 CD) and started to recompile some existing code to see if it would fly without any serious modifications. Everything was going fine until I recompiled a project that was using IconFamilies.h (for those of you who don't remember, IconFamilies.h was the file defined in TechNote #306, "Drawing Icons the System 7 Way"). Everything from IconFamilies.h has been shuffled into Icons.h. Hey, that's fine with me. But I would like to modify my source to include IconFamilies.h if the univ. hdrs. are not available. Easiest way to do this, I says to myself, is to surround the #include with an #ifndef. The only problem is that I don't know if there is a constant defined so that I can distinguish between the old headers and the universal headers. So to wrap up, is there a constant defined somewhere within the universal headers? ============================================================ Dave Nebinger dnebing@andy.bgsu.edu Network Manager, Biology Dept. dnebing@opie.bgsu.edu Bowling Green State University dnebing@bgsuopie (bitnet) Bowling Green, OH 43403 #include *THE* alt.sources.mac supporter! +++++++++++++++++++++++++++ >From al@crucible.powertools.com (Al Evans) Date: 4 Jul 94 14:31:12 GMT Organization: PowerTools, Austin, Texas In article <2v5e2l$rm@falcon.bgsu.edu> dnebing@bgsu.edu ( Mr. Neb) writes: > So to wrap up, is there a constant defined somewhere within the >universal headers? I've been using #ifdef __CONDITIONALMACROS__. As far as I can tell, gets included any time you're using the universal headers, but doesn't exist if you're not. --Al Evans-- -- Al Evans | Graphic Elements: A new standard for | high-performance interactive Macintosh graphics. al@crucible.powertools.com | Available from mac.archive.umich.edu | /mac/misc/demo/graphicelementsdemo.sit.hqx +++++++++++++++++++++++++++ >From peter.lewis@info.curtin.edu.au (Peter N Lewis) Date: Mon, 04 Jul 1994 10:32:51 +0800 Organization: NCRPDA, Curtin University In article <2v5e2l$rm@falcon.bgsu.edu>, dnebing@bgsu.edu ( Mr. Neb) wrote: > Hey, that's fine with me. But I would like to modify my source to >include IconFamilies.h if the univ. hdrs. are not available. Easiest >way to do this, I says to myself, is to surround the #include with >an #ifndef. The only problem is that I don't know if there is a >constant defined so that I can distinguish between the old headers >and the universal headers. Wow, another few years and this will be almost as much fun as trying to get a unix program compiled. I just love the C #define, #include method of seperate compilation. Brilian piece of design :-) Peter. _______________________________________________________________________ Peter N Lewis Ph: +61 9 368 2055 --------------------------- >From mdtaylor@apple.com (Mark D. Taylor) Subject: Why does THINK C use a jump table? Date: 17 Jun 1994 10:08:53 -0700 Organization: Apple Computer Inc, Cupertino, CA Or more specifically, why does a call of a function in the same source file and segment of the caller go through a jump table? I'm having a problem with this because the call occurs at interrupt time when A5 is not guaranteed and sometimes the jump table is not where the code thinks it should be. So what controls whether the jump table is used? How can I disable it? Thanks, Mark +++++++++++++++++++++++++++ >From doc@miracle.farallon.com (eric doc kampman) Date: Fri, 17 Jun 1994 18:17:52 -0800 Organization: farallon In article <2tslb5$d6c@apple.com>, mdtaylor@apple.com (Mark D. Taylor) wrote: > Or more specifically, why does a call of a function in the same source file > and segment of the caller go through a jump table? > > I'm having a problem with this because the call occurs at interrupt time > when A5 is not guaranteed and sometimes the jump table is not where the code > thinks it should be. > > So what controls whether the jump table is used? How can I disable it? Short answer -- as far as I can tell, when one routine calls another it *always* goes through the jump table -- even if the routine you're calling is defined in the same source file and is 2 bytes away from the PC. This "feature" has caused me to retreat back to MPW when I'm not doing OOP stuff. You're going to have to save your A5 somewhere you can retrieve it when you're not the front app. There are many different situations where this occurs and many ways of handling it. For a generic solution -- check out (in THINK #includes) for a *very* interesting way of saving register values where you can get to them. It takes a little while to see why what they're doing works (or at least it did for me). -- doc@miracle.farallon.com Farallon didn't write this, Farallon isn't responsible for its con- tents -- Farallon is an abstract class and cannot be held responsible for the quality of instantiations of derived classes. ******************************************************************** Look for the thing you can't find/Seeing with eyes makes you blind You know you're out of your mind +++++++++++++++++++++++++++ >From siegel@netcom.com (Rich Siegel) Date: Sat, 18 Jun 1994 01:20:21 GMT Organization: Bare Bones Software In article <2tslb5$d6c@apple.com> mdtaylor@apple.com (Mark D. Taylor) writes: >Or more specifically, why does a call of a function in the same source file >and segment of the caller go through a jump table? (one of) Two reasons: it's not declared 'static', and/or you take its address at some point in the code. If it's not declared static, it needs to be accessible through the jump table so that other functions can call it. If you take its address, it has to be indirected thruogh the jump table to ensure position independence. R. -- Rich Siegel % siegel@netcom.com % Principal, Bare Bones Software --> For information about BBEdit, finger bbedit@world.std.com <-- "...yeah, I inhaled, and then I drank the bong water. So what're you gonna do about it?" - Dennis Miller, on Bill Clinton +++++++++++++++++++++++++++ >From gurgle@netcom.com (Pete Gontier) Date: Sat, 18 Jun 1994 05:00:40 GMT Organization: cellular mdtaylor@apple.com (Mark D. Taylor) writes: >Or more specifically, why does a call of a function in the same source >file and segment of the caller go through a jump table? I'm having a >problem with this because the call occurs at interrupt time when A5 >is not guaranteed and sometimes the jump table is not where the code >thinks it should be. So what controls whether the jump table is used? >How can I disable it? You can't disable it without using another compiler, but you can make sure your interrupt code works. First make sure the segment in question is loaded by doing some work at non-interrupt time. Make a call into the segment, perhaps to a dummy routine which exists solely to force the segment to load. Make sure you don't subsequently call UnloadSeg for that segment. Then, in your interrupt code, make sure A5 is set up properly before you make the interrupt-time call into the segment. I believe you will find relevant documentation in the usual places under 'SetCurrentA5'. None of this stuff is relevant under PowerPC, of course. -- Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com 'It seems the firm contracted by Intel to produce the famed "flying Pentium" ads could not complete the 3-D modeling on a PC before deadline. So in the best know-your-enemy tradition, they chose the next best thing -- a Quadra 840AV.' -- Mac The Knife 4/18/94 +++++++++++++++++++++++++++ >From gurgle@netcom.com (Pete Gontier) Date: Sat, 18 Jun 1994 17:26:11 GMT Organization: cellular mdtaylor@apple.com (Mark D. Taylor) writes: >Or more specifically, why does a call of a function in the same source >file and segment of the caller go through a jump table? Rich posted the reasons why, and I posted a way for you to make your interrupt code work. But I don't think anybody yet has specifically talked about the general case of how to make jump table entries go away. If your routine is declared 'static' and you don't take its address, *that* will guarantee it will not generate a jump table entry. (If your routine is only referenced from its own segment, it will not generate a jump table entry when building a stand-alone app, but it's more common for programmers to want to run their app from TPM.) This gives me an opportunity to be even a little more pedantic. THINK C supports a language extension "require prototypes". Most people should have it turned on (in the project settings dialog), because it only helps you build safer and stronger software at the expense of some extra typing sometimes. But most people don't know how to take advantage of it. They turn it on, and the compiler encounters a function like 'foo': void foo (void) { } void main (void) { foo ( ); } ...and of course the compiler complains because there is no prototype for 'foo' in scope. People's response is generally to give the compiler a prototype, even for routines which will never be called from another module: void foo (void); void foo (void) { } void main (void) { foo ( ); } ...and this makes the compiler shut up. But there is a much better way: static void foo (void) { } void main (void) { foo ( ); } ...this not only makes the compiler shut up, but it prevents 'foo' from requiring a jump table entry, as long as you don't also take its address. This not only keeps your jump-table less crowded, but it also relieves you of having to deal with the possibility that A5 (or A4 in some cases) is not valid when 'foo' is called. (If 'foo' is going to call other routines which rely on A5 (or A4), 'foo' still needs to make sure A5 (or A4) is valied before calling those other routines.) Now, some people will say that relying on this behavior is a bad idea, because the ANSI standard doesn't specify that 'static' should have this effect. However, neither does the ANSI standard specify that a feature like "require prototypes" be supported. When you hit the "ANSI settings" button in the prefs dialog, notice that "infer prototypes" gets selected, not "require prototypes". So since "require prototypes" isn't ANSI in the first place, you might as well rely on the 'static' keyword to help you use "require prototypes". I know CodeWarrior supports it, by the way, and I suspect MPW C supports it in some similar fashion, as well. The reason I really like to use the 'static' keyword in this way is the way THINK C segmentation works. You can only control segmentation at the module level, so by definition 'static' routines cannot be called from another segment. The linker simply won't cooperate. Using the 'static' keyword in this way can prevent a whole layer of mistakes before they require debugging time. -- Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com You thought Obfuscated C was confusing? Wait for Obfuscated C++! +++++++++++++++++++++++++++ >From ari@world.std.com (Ari I Halberstadt) Date: Mon, 20 Jun 1994 04:47:12 GMT Organization: The World Public Access UNIX, Brookline, MA In article , Pete Gontier wrote: >... >The reason I really like to use the 'static' keyword in this way is the >way THINK C segmentation works. You can only control segmentation at the >module level, so by definition 'static' routines cannot be called from >another segment. The linker simply won't cooperate. Using the 'static' >keyword in this way can prevent a whole layer of mistakes before they >require debugging time. There's another good reason to use this feature. It saves you from having to put prototypes into the file, which means a bit less work for the programmer/maintainer. It also helps give some logical structure to your source files, since static functions need to be defined before you can use them. If you really need to use a function before it's defined, you can place a prototype for that function near the head of the source file. -- Ari Halberstadt ari@world.std.com One generation passes away, and another generation comes: but the earth abides for ever. -- Ecclesiastes, 1:4. +++++++++++++++++++++++++++ >From Aaron Wohl Date: Fri, 1 Jul 1994 09:12:14 -0400 Organization: Systems Group 97, Carnegie Mellon, Pittsburgh, PA There are two ways around think c using A5 to make calls: a) have an lea instruction at the start of the routine (use asm {}) and patch it before using the address at interrupt time. (then flush the code caches) b) Compile the code in question as a code resource and load the resource. See the code samples on akutaktak.andrew.cmu.edu [128.2.35.1] in the /aw0g directory for some examples of using code resources. --------------------------- End of C.S.M.P. Digest **********************