home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 July / macformat-026.iso / mac / Shareware City / Developers / CDEF Template 1.0 / CDEF Template.c next >
Encoding:
Text File  |  1995-03-10  |  19.8 KB  |  469 lines  |  [TEXT/MPCC]

  1. /****************************************************************************************************
  2. *                                                                                                   *
  3. * CDEFTemplate.c -- Copyright Chris Larson (larson@cs.ucla.edu), 1994 - 1995  All Rights Reserved   *
  4. *                                                                                                   *
  5. * Source file for a CDEF shell.                                                                     *
  6. *                                                                                                   *
  7. * This source file and its compiled derivatives may be freely used within any freeware, shareware,  *
  8. * postcardware, beerware, etc. as long as you mention my name in your credits. Neither this source  *
  9. * nor its compiled derivatives are in the public domain and may not be use in any form in public    *
  10. * domain software. Neither this source nor its compiled derivatives may be used in any form in a    *
  11. * commercial product without the expressed, written consent of the author (me).                     *
  12. *                                                                                                   *
  13. * Version 1.0 -- March 10, 1995                                                                     *
  14. *                                                                                                   *
  15. ****************************************************************************************************/
  16.  
  17. // Include Files
  18.  
  19. #ifndef    powerc
  20. #include <A4Stuff.h>
  21. #endif
  22.  
  23. #include "CDEF Template.h"
  24.  
  25. //---------------------------------------------------------------------------------------------------
  26. // main -- CDEF entry point. Handle all messages and dispatch to appropriate subroutines.
  27. //---------------------------------------------------------------------------------------------------
  28.  
  29. pascal long main (short varCode, ControlHandle theControlHandle, short message, long param)
  30. {
  31.     long            returnValue = 0;        // Init return value to 0.
  32.     ControlPtr        theControl;
  33.     SignedByte        controlRecState;
  34.     
  35.     #ifndef    powerc
  36.  
  37.     long            oldA4 = SetCurrentA4();    // Set up the A4 register (680x0 only).
  38.  
  39.     #endif    
  40.  
  41.  
  42.     // ----------
  43.     // Lock down the ControlRecord and get a pointer to it.
  44.     // ----------
  45.     
  46.     controlRecState = HGetState((Handle)theControlHandle);
  47.     HLock((Handle)theControlHandle);
  48.     theControl = *theControlHandle;
  49.     
  50.     // ----------
  51.     // Dispatch to appropriate subroutine.
  52.     // ----------
  53.     
  54.     switch (message)
  55.         {
  56.         // ----------
  57.         // drawCntl -- Draw the control if it’s visible. The part code to draw is held in the low
  58.         //               word of param. The high word contains garbage so only the low word should
  59.         //               be used. Note that the prototype of BeginDraw has its third parameter of
  60.         //               type short. This takes care of stripping the high word.
  61.         // ----------
  62.         
  63.         case drawCntl:
  64.             if ( theControl->contrlVis )
  65.                 BeginDraw(theControlHandle,varCode,param);
  66.             break;
  67.  
  68.         // ----------
  69.         // testCntl -- Determine which part of the control contains the point held in param. The
  70.         //               funny cast on param is needed because Point is a struct and param is not,
  71.         //               even though they are the same size. Note that IM: Macintosh TB Essentials
  72.         //               does not explicitly tell us that param is a Point but the structure and size
  73.         //               are both the same when given the testCntl message (a 4-byte quantity with the
  74.         //               high word containing the vertical coordinate and the low word containing the
  75.         //               horizontal coordinate). The coordinates given are local coordinates.
  76.         // ----------
  77.  
  78.         case testCntl:
  79.             returnValue = FindControlPart(theControl,varCode,*((Point*)(¶m)));
  80.             break;
  81.         
  82.         // ----------
  83.         // calcCRgns -- Calculate control or thumb region (24-bit addressing mode only). If the
  84.         //                high bit of param is set, calculate the thumb region. Otherwise, calculate
  85.         //                the control region. In either case clear the high bit of param to get the
  86.         //                valid region handle.
  87.         // ----------
  88.         
  89.         case calcCRgns:
  90.             if ( ( param & 0x80000000 ) == 0 )
  91.                 CalculateControlRegion(theControl,varCode,(RgnHandle)(param&0x7FFFFFFF));
  92.             else
  93.                 CalculateIndicatorRegion(theControl,varCode,(RgnHandle)(param&0x7FFFFFFF));
  94.             break;
  95.         
  96.         // ----------
  97.         // initCntl -- Perform any additional initialization.
  98.         // ----------
  99.         
  100.         case initCntl:
  101.             InitControl(theControl,varCode);
  102.             break;
  103.         
  104.         // ----------
  105.         // dispCntl -- Perform any additional disposal actions.
  106.         // ----------
  107.         
  108.         case dispCntl:
  109.             DispControl(theControl,varCode);
  110.             break;
  111.         
  112.         // ----------
  113.         // posCntl -- Displace the control indicator by the offsets in param and update the
  114.         //              contrlValue field of the control record. The offsets are stored as follows:
  115.         //              vertical offset in high word of param, horizontal offset in low word of param.
  116.         //              Both are signed quantities. Once again the stange cast on param is to make
  117.         //              the compiler jump through the right hoops and push the high word of param.
  118.         // ----------
  119.         
  120.         case posCntl:
  121.             PositionIndicator(theControl,varCode,*((short*)(¶m)),param);
  122.             break;
  123.         
  124.         // ----------
  125.         // thumbCntl -- Calculate parameters for indicator dragging. The location of the mouse-
  126.         //                 down event which triggered this message is given, in local coordinates,
  127.         //                at the address pointed to by param. Further, param points to a structure
  128.         //                of type IndicatorDragConstraint (see header file Controls.h) to be filled
  129.         //                in by the CDEF. Fields within the IndicatorDragConstraint structure are
  130.         //                analogus to those for DragGrayRgn().
  131.         // ----------
  132.         
  133.         case thumbCntl:
  134.             CalcIndicatorValues(theControl,varCode,*((Point*)(param)),
  135.                                 (IndicatorDragConstraintPtr)param);
  136.             break;
  137.         
  138.         // ----------
  139.         // dragCntl -- Drag the control or its indicator. If param == 0 then the entire control is
  140.         //               to be dragged, otherwise, just the indicator is to be dragged. If you want
  141.         //               the Control Manager to drag for you (using DragControl() for controls and
  142.         //               DragGrayRgn() for indicators), just return 0. Otherwise, drag it yourself and
  143.         //               call MoveControl() when done moving entire controls or change the contrlValue
  144.         //               field of the control record and redraw the control. Note that TrackControl()
  145.         //               always returns 0 for custom indicator dragging and this can cause problems
  146.         //               if it is not expected. Refer to IM: Mac TB Essentials, pp. 5-114 and 5-115
  147.         //               for details.
  148.         // ----------
  149.         
  150.         case dragCntl:
  151.             returnValue = CustomDrag(theControl,varCode,(param != 0));
  152.             break;
  153.         
  154.         // ----------
  155.         // autoTrack -- Custom control action procedure. The part code that the user clicked
  156.         //                on is contained in the low word of param. The high word contains garbage.
  157.         //                Action procedures are described in IM: Mac TB Essentials in the Control
  158.         //                Manager chapter. Note that for this to work correctly, -1L must be stored
  159.         //                in the contrlAction field by the initCntl handler and -1L must be passed
  160.         //                to TrackControl() in the actionProc parameter.
  161.         // ----------
  162.         
  163.         case autoTrack:
  164.             ActionProcedure(theControl,varCode,param);
  165.             break;
  166.         
  167.         // ----------
  168.         // calcCntlRgn -- Calculate the control’s region (32-bit addressing mode only). Place the
  169.         //                  control’s region into the region handle given in param.
  170.         // ----------
  171.         
  172.         case calcCntlRgn:
  173.             CalculateControlRegion(theControl,varCode,(RgnHandle)param);
  174.             break;
  175.         
  176.         // ----------
  177.         // calcThumbRgn -- Calculate the control indicator’s region (32-bit addressing mode only).
  178.         //                   Put the control indicator’s region into the region handle given in param.
  179.         // ----------
  180.         
  181.         case calcThumbRgn:
  182.             CalculateIndicatorRegion(theControl,varCode,(RgnHandle)param);
  183.             break;
  184.         }
  185.     
  186.     // ----------
  187.     // Return the control record handle to its previous state, restore the A4 register and exit.
  188.     // ----------
  189.     
  190.     HSetState((Handle)theControlHandle, controlRecState);
  191.  
  192.     #ifndef    powerc
  193.  
  194.     SetA4(oldA4);
  195.  
  196.     #endif
  197.  
  198.     return (returnValue);
  199. }
  200.  
  201. //---------------------------------------------------------------------------------------------------
  202. // BeginDraw -- This is the first part of a two-layer drawing system. This function saves off and
  203. //                restores all things that are munged during drawing, it figures out whether to
  204. //                draw in color or not, and it gets pointers to the control’s color table and the
  205. //                control’s window’s color table. The actual drawing is performed by the DrawControl()
  206. //                function. (Do not confuse this with the Control Manager’s Draw1Control() call.)
  207. //              Note that not much is actually saved here -- you should save off anything additional
  208. //              which you alter in DrawControl(). This function exists to prevent the draw routine
  209. //              running out of registers for local variables because some are used as storage for
  210. //              these settings. It is, of course, not necessary to separate this code from the
  211. //              actual drawing code if that’s what you desire.
  212. //---------------------------------------------------------------------------------------------------
  213.  
  214. void BeginDraw(ControlHandle theControlHandle, short varCode, short partCode)
  215. {
  216.     ControlPtr        theControl = *theControlHandle;
  217.     GrafPtr            savePort, controlPort = theControl->contrlOwner;
  218.     Boolean            inColor;
  219.     RgnHandle        saveClip, newClip;
  220.     PenState        savePen;
  221.     SignedByte        controlCTableState, windowCTableState;
  222.     CTabHandle        windowColorTableHandle, controlColorTableHandle;
  223.     CTabPtr            windowColorTable = NULL, controlColorTable = NULL;
  224.     AuxWinHandle    theAuxHandle;
  225.     RGBColor        saveForeground, saveBackground;
  226.     
  227.     // ----------
  228.     // Should we draw in color? Yes if we are drawing into a color port.
  229.     // ----------
  230.     
  231.     inColor = ( controlPort->portBits.rowBytes & kColorPort ) == kColorPort;
  232.     
  233.     // ----------
  234.     // Save off the current port and make the control’s port current.
  235.     // ----------
  236.     
  237.     GetPort(&savePort);
  238.     SetPort(controlPort);
  239.     
  240.     // ----------
  241.     // Save off the clipping region and set the clipping region to the intersection of the control’s
  242.     // rectangle and the old clipping region.
  243.     // ----------
  244.     
  245.     saveClip = NewRgn();
  246.     GetClip(saveClip);
  247.     newClip = NewRgn();
  248.     RectRgn(newClip,&(theControl->contrlRect));
  249.     SectRgn(newClip,saveClip,newClip);
  250.     SetClip(newClip);
  251.     DisposeRgn(newClip);
  252.     
  253.     // ----------
  254.     // Save off and reset the pen state.
  255.     // ----------
  256.     
  257.     GetPenState(&savePen);
  258.     PenNormal();
  259.     
  260.     // ----------
  261.     // If we are drawing in color, save the foreground and background colors. Get pointers to the
  262.     // control’s color table and the control’s window’s color table. Note that the color tables need
  263.     // to be locked in order for the FindColorInTable() function (included here) to return stable
  264.     // addresses, so save the states of the color tables’ handles and lock them down.
  265.     // ----------
  266.     
  267.     if ( inColor ) {
  268.  
  269.         GetForeColor(&saveForeground);
  270.         GetBackColor(&saveBackground);
  271.         
  272.         GetAuxWin(controlPort,&theAuxHandle);
  273.         windowColorTableHandle = (**theAuxHandle).awCTable;
  274.         windowCTableState = HGetState((Handle)windowColorTableHandle);
  275.         HLock((Handle)windowColorTableHandle);
  276.         windowColorTable = *windowColorTableHandle;
  277.         
  278.         GetAuxCtl(theControlHandle,(AuxCtlHandle*)(&theAuxHandle));
  279.         controlColorTableHandle = (CTabHandle)(**(AuxCtlHandle)theAuxHandle).acCTable;
  280.         controlCTableState = HGetState((Handle)controlColorTableHandle);
  281.         HLock((Handle)controlColorTableHandle);
  282.         controlColorTable = *controlColorTableHandle;
  283.     }
  284.     
  285.     // ----------
  286.     // Draw the control.
  287.     // ----------
  288.     
  289.     DrawControl(theControl,varCode,partCode,windowColorTable,controlColorTable,inColor);
  290.     
  291.     // ----------
  292.     // If we are in color, restore the foreground and background colors, and return the color
  293.     // tables’ handles to thier previous states.
  294.     // ----------
  295.     
  296.     if ( inColor ) {
  297.  
  298.         HSetState((Handle)windowColorTableHandle,windowCTableState);
  299.         HSetState((Handle)controlColorTableHandle,controlCTableState);
  300.         
  301.         RGBForeColor(&saveForeground);
  302.         RGBBackColor(&saveBackground);
  303.     }
  304.     
  305.     // ----------
  306.     // Restore the pen state.
  307.     // ----------
  308.     
  309.     SetPenState(&savePen);
  310.     
  311.     // ----------
  312.     // Reset the clipping region to the original clipping region.
  313.     // ----------
  314.     
  315.     SetClip(saveClip);
  316.     DisposeRgn(saveClip);
  317.     
  318.     // ----------
  319.     // Set the port back and exit.
  320.     // ----------
  321.     
  322.     SetPort(savePort);
  323. }
  324.  
  325. //---------------------------------------------------------------------------------------------------
  326. // DrawControl -- Perform the actual control drawing. All the relevant information should be given
  327. //                  either in the control record or in the function parameters. Note that the inColor
  328. //                  parameter is true if the control’s port is a color port -- it does not indicate
  329. //                  what bit depth the current device is using, nor does it distinguish between color
  330. //                  and greyscale devices. If that information is needed by your CDEF, you will need
  331. //                  to get it from the appropriate sources.
  332. //---------------------------------------------------------------------------------------------------
  333.  
  334. void DrawControl(ControlPtr theControl, short varCode, short partCode, CTabPtr windowColorTable,
  335.                  CTabPtr controlColorTable, Boolean inColor)
  336. {
  337. }
  338.  
  339. //---------------------------------------------------------------------------------------------------
  340. // FindControlPart -- Determine and return the part code of the control part which contains hitPoint.
  341. //                      Note that hitPoint is given in coordinates local to the control’s port. Return
  342. //                      0 if hitPoint lies outside of the given control.
  343. //---------------------------------------------------------------------------------------------------
  344.  
  345. short FindControlPart(ControlPtr theControl, short varCode, Point hitPoint)
  346. {
  347.     return(0);
  348. }
  349.  
  350. //---------------------------------------------------------------------------------------------------
  351. // CalculateControlRegion -- Place in theRegion the region occupied by the entire given control. Note
  352. //                             that theRegion is already a valid RgnHandle; you do not need to call
  353. //                             NewRgn() to initialize it.
  354. //---------------------------------------------------------------------------------------------------
  355.  
  356. void CalculateControlRegion(ControlPtr theControl, short varCode, RgnHandle theRegion)
  357. {
  358.     EmptyRgn(theRegion);
  359. }
  360.  
  361. //---------------------------------------------------------------------------------------------------
  362. // CalculateIndicatorRegion -- Place in theRegion the region occupied by the control’s indicator.
  363. //                               Note that theRegion is already a valid RgnHandle; you do not need to
  364. //                               call NewRgn() to initialize it.
  365. //---------------------------------------------------------------------------------------------------
  366.  
  367. void CalculateIndicatorRegion(ControlPtr theControl, short varCode, RgnHandle theRegion)
  368. {
  369.     EmptyRgn(theRegion);
  370. }
  371.  
  372. //---------------------------------------------------------------------------------------------------
  373. // InitControl -- Perform any additional initialization needed.
  374. //---------------------------------------------------------------------------------------------------
  375.  
  376. void InitControl(ControlPtr theControl, short varCode)
  377. {
  378. }
  379.  
  380. //---------------------------------------------------------------------------------------------------
  381. // DispControl -- Perform any additional disposal actions needed.
  382. //---------------------------------------------------------------------------------------------------
  383.  
  384. void DispControl(ControlPtr theControl, short varCode)
  385. {
  386. }
  387.  
  388. //---------------------------------------------------------------------------------------------------
  389. // PositionIndicator -- Offset the position of the control’s indicator by dh in the horizontal
  390. //                        direction and dv in the vertical direction. Update the contrlValue field
  391. //                        of the ControlRecord and redraw the control to reflect the new setting.
  392. //                        See the NOTE under CustomDrag regarding updating contrlValue and redrawing.
  393. //---------------------------------------------------------------------------------------------------
  394.  
  395. void PositionIndicator(ControlPtr theControl, short varCode, short dv, short dh)
  396. {
  397. }
  398.  
  399. //---------------------------------------------------------------------------------------------------
  400. // CalcIndicatorValues -- Calculate parameters for dragging the control’s indicator. The hitPoint
  401. //                          parameter contains the point at which the mouse-down event triggering this
  402. //                          message occurred. This routine should fill in all the fields of the struct
  403. //                          pointed to by info.
  404. //---------------------------------------------------------------------------------------------------
  405.  
  406. void CalcIndicatorValues(ControlPtr theControl, short varCode, Point hitPoint,
  407.                          IndicatorDragConstraintPtr info)
  408. {
  409. }
  410.  
  411. //---------------------------------------------------------------------------------------------------
  412. // CustomDrag -- Perform custom dragging of the control or the control’s indicator. If no custom
  413. //                 dragging is desired return 0. If the entire control s custom dragged, call
  414. //                 MoveControl() to move the control to its destination after the mouse button is
  415. //                 released. If the indicator is custom dragged, the new setting must be calculated,
  416. //                 the contrlValue field updated, and the control redrawn. A nonzero value should be
  417. //                 returned if custom dragging is used. The dragIndicator parameter is true if just
  418. //                 the indicator is to be dragged, false if the whole control is to be dragged.
  419. //
  420. //                 NOTE: Updating of the contrlValue field and redrawing of the control should be
  421. //                 done directly; don’t call the Control Manager’s functions SetCtlValue() to do
  422. //                 this. The reason is that the Control Manager locks the CDEF when calling it and
  423. //                 then unlocks it upon returning. This is not reentrant: for example, assume we are
  424. //                 called with a dragCntl message. The CDEF is locked, and called. Within the CDEF, a
  425. //                 call is made to SetCtlValue(). The Control Manager knows the control should be
  426. //                 drawn to reflect it’s new setting so it locks and calls the CDEF with a drawCntl
  427. //                 message. When the CDEF returns from drawing, the Control Manager unlocks it and
  428. //                 SetCtlValue() returns, coming back to the original invocation of the CDEF. We are
  429. //                 now running in an unlocked block of code. If the Memory Manager decides to move
  430. //                 the CDEF, crash-o-rama. The moral: DON’T CALL CONTROL MANAGER ROUTINES FROM WITHIN
  431. //                 A CDEF -- DO EVERYTHING DIRECTLY.
  432. //---------------------------------------------------------------------------------------------------
  433.  
  434. Boolean CustomDrag(ControlPtr theControl, short varCode, Boolean dragIndicator)
  435. {
  436.     return(false);
  437. }
  438.  
  439. //---------------------------------------------------------------------------------------------------
  440. // ActionProcedure -- Custom action procedure. Action procedures are described in the Control Manager
  441. //                      chapter of IM: Mac TB Essentials. Note that for this action procedure to work
  442. //                      properly, -1 must be stored in the contrlAction field of the Control Record
  443. //                      (best done during the initCntl message -- in the InitControl function here) and
  444. //                      -1 must be passed to TrackControl in the actionProc parameter.
  445. //---------------------------------------------------------------------------------------------------
  446.  
  447. void ActionProcedure(ControlPtr theControl, short varCode, short partCode)
  448. {
  449. }
  450.  
  451. //---------------------------------------------------------------------------------------------------
  452. // FindColorInTable -- Returns a pointer to the RGBColor field of the ColorSpec record with the
  453. //                       corresponding value field in the given color table. Returns a pointer to the
  454. //                       first color in the table if no ColorSpec with value == id was found. (Matches
  455. //                       the way the standard CDEF’s search color tables.
  456. //---------------------------------------------------------------------------------------------------
  457.  
  458. RGBColor *FindColorInTable (CTabPtr colorTable, short id)
  459. {
  460.     short counter;
  461.     
  462.     for (counter = colorTable->ctSize; counter > 0; counter--) {
  463.  
  464.         if ( colorTable->ctTable[counter].value == id )
  465.             break;
  466.     }
  467.  
  468.     return ( &( colorTable->ctTable[counter].rgb ) );
  469. }