home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 2 / MacMania 2.toast / Demo's / Tools&Utilities / Programming / MPS disk 1.0.1 / Chapter 09 / DEF's / Generic LDEF.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-19  |  3.6 KB  |  75 lines  |  [TEXT/KAHL]

  1.  
  2. /*******************************************************************************
  3.  
  4.     Generic LDEF
  5.  
  6.     This short code segment is the front end for an LDEF. Normally, LDEFs are
  7.     standalone pieces of code developed separately from the rest of the
  8.     application. While this is not really a bad idea, there are several
  9.     disadvantages with it:
  10.  
  11.     - You don’t have access to your application’s global variables. Your
  12.       compiled code can only access a common set of global variables if all
  13.       the parts are linked at the same time. Since the LDEF is linked
  14.       separately from the application, your won’t be able to access the
  15.       application’s globals. On the other hand, some would say that a module
  16.       such as an LDEF should be independent of an application’s
  17.       implementation. If so, then an LDEF shouldn’t need to access the
  18.       application’s variables.
  19.  
  20.     - If you program in a THINK development system and are developing your
  21.       LDEF and application in parallel, you will have to continually jump back
  22.       and forth between projects. You will also have to continually make sure
  23.       your LDEF is incorporated into the right resource file.
  24.  
  25.     - Source level debugging is more difficult under MPW, and impossible
  26.       under THINK.
  27.  
  28.     To solve these problems, we use a front end for the code used to display
  29.     the list. All this LDEF does is call the _real_ code back in the
  30.     application. When the list record is created, the application will be
  31.     expected to store the address of the real code in the list record’s refCon
  32.     field. Our front end will fetch that address and jump to it.
  33.  
  34.     The disadvantage of this approach is that the application is not able to
  35.     set the refCon before the List Manager calls the LDEF with the LInitMsg.
  36.     This means that any initialization normally be done at that time will have
  37.     to be done later. In our sample application, we show how to do that.
  38.  
  39.     Note that when we call the real code in the application, we duplicate the
  40.     parameters passed in to us. This isn’t wrong or bad or anything. But it
  41.     _is_ inefficient. Ideally, we would like to just jump to the real routine,
  42.     letting it use the same parameters passed to us. If we were writing in
  43.     assembly, this would be simple to do. However, when writing in C, we have
  44.     to deal with some of the little “extras” a high level language gives us.
  45.     Although THINK C has an inline assembly and we could generate the
  46.     instructions to jump to the application code, we have to contend with any
  47.     LINK statements or register saving instructions the compiler generates for
  48.     our routine. These alter the stack pointer and would have to be
  49.     compensated for before jumping back into the application. By examining the
  50.     output of the compiler, we could do this. In fact, early versions of this
  51.     LDEF _did_ do this. However, this approach is highly dependent on the
  52.     compiler you are using. Since, in the Galactic Order of Things, we don’t
  53.     really gain a whole lot by doing a JMP back into the application, we opted
  54.     for compatibility and easy maintenance instead. The result is that we end
  55.     up with a 64 bytes routine instead of a 30 byte routine. Big deal.
  56.  
  57. *******************************************************************************/
  58.  
  59. typedef pascal void (*LDEFProc)(short lMessage, Boolean lSelect, Rect* lRect,
  60.                                 Cell lCell, short lDataOffset, short lDataLen,
  61.                                 ListHandle lHandle);
  62.  
  63. pascal void main(short lMessage, Boolean lSelect, Rect* lRect, Cell lCell,
  64.                  short lDataOffset, short lDataLen, ListHandle lHandle)
  65. {
  66.     long    refCon;
  67.  
  68.     refCon = (**lHandle).refCon;
  69.     if (refCon != 0L) {
  70.         ((LDEFProc) refCon) (lMessage, lSelect, lRect, lCell,
  71.                                 lDataOffset, lDataLen, lHandle);
  72.     }
  73. }
  74.  
  75.