home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / System / Control Panel Project 0.9.5 / MyControlPanel.c < prev    next >
Encoding:
Text File  |  1994-10-06  |  25.2 KB  |  794 lines  |  [TEXT/KAHL]

  1. /*
  2.     MyControlPanel.c
  3.  
  4.     Written by Ken Worley, 10/04/94, using Symantec Think C 7.0.
  5.     Copyright 1994. All Rights Reserved.
  6.     
  7.     Feel free to use this code in a control panel of your own.  Please don't
  8.     publish or distribute this source code without giving me proper credit.
  9.     
  10.     This control panel uses no global variables, so it's not necessary
  11.     to set up and restore A4.  All of our 'global' data is in the shared data
  12.     structure (in a handle to a block in the system heap).
  13.     
  14.     The Control Panel Manager sends messages to your control panel through
  15.     its main routine when it is opened, closed, or manipulated in any way that you
  16.     would need to respond to.
  17.     
  18.     The routines already set up here will handle ALL of the messages that
  19.     would be received.  Most of them, at the present time, don't do anything
  20.     since this is only an example.  By simply inserting code into the routines,
  21.     however, you can add functionality.
  22.     
  23.     The three most common messages received are:
  24.     
  25.         initDev        We receive this when the user opens our control panel (or
  26.                     selects it in the scrolling list of control panels in System 6).
  27.         
  28.         closeDev    We receive this when the user closes the control panel (or
  29.                     selects a different control panel in System 6).
  30.                     
  31.         hitDev        The user has manipulated a control in the control panel (i.e.
  32.                     pressed a button or clicked in a text field, etc.)
  33.                     
  34.         Other messages are received when the user selects items in the Edit menu,
  35.         when the control panel is sent to the background or brought to the foreground,
  36.         when the user types, and when the control panel needs to be updated.  Controls
  37.         in the panel's DITL (item list) are updated automatically.
  38.         
  39.     The cdevValue parameter of main is a mechanism that allows you to store data
  40.     across calls to the control panel.  Normally, when an initDev message is received,
  41.     we would allocate a new handle and return the handle as the function's
  42.     return value (unless an error occurred).  The next time main is called by the
  43.     Control Panel Manager, the same value is passed back to us in cdevValue so that
  44.     we can access the memory.  We don't need to actually allocate anything here, but
  45.     we still use the mechanism to retain the address of our shared data structure
  46.     between calls.  When a closeDev message is received, we dispose of
  47.     the memory block and return cdevUnset to indicate no handle is allocated.
  48.     
  49.     Other possible return values are:
  50.     
  51.         cdevUnset    Control Panel Manager need not keep track of any memory
  52.         cdevGenErr    generic error - no error dialog is shown but panel does not load
  53.         cdevMemErr    not enough memory to continue - error dialog shown
  54.         cdevResErr    a resource is unavailable - error dialog shown
  55.         A handle to some memory for the Control Panel Manager to keep track of
  56.             between calls.
  57.     
  58.     Instead of allocating new memory, we look up the address of our shared memory
  59.     structure in a resource created by the extension code.  We use the cdevValue
  60.     mechanism to save that as long as the control panel is open.  This memory
  61.     was initially allocated by the extension code (which stored the address
  62.     in the resource).  This resource is of type 'memA'.
  63.     
  64.     I use a resource of type 'pref' to hold the control panel's "preferences."  At
  65.     this time, the resource is a struct containing only two fields:  On and
  66.     ShowIcon.  'On' indicates whether the patch should take action when trapped to and
  67.     'ShowIcon' indicates whether the extension's icon should be shown at system
  68.     startup time.
  69.     
  70.     Because of the fact that we release our resource every time the control panel is
  71.     closed, if you need to access values manipulated by the control panel in the
  72.     patch code for example, you may want to duplicate the final values in the
  73.     shared data structure.  It would be most convenient to do this in the CloseCP
  74.     routine just before the resource is released.  I store the on/off status of
  75.     the control panel in the field 'CPon' in the shared data.  The patch code uses
  76.     this field to determine if it should take any action.  The control panel also
  77.     refers to the field 'patched' to determine if the patch was installed at
  78.     system startup.
  79.     
  80.     Any resources used by a control panel must be in the range -4064 thru -4033.
  81.     The only exception has to do with balloon help.  Of that range, -4064 thru -4049
  82.     is reserved for standard resources (and some optional resources).  You can use
  83.     -4048 thru -4033 for any resources you include for use with your control panel.
  84.     This is from the New Inside Macintosh: More Macintosh Toolbox (chapter 8).
  85.     
  86.     Coordinates in your control panel dialog:
  87.     
  88.         System 7 lets you use almost any size control panel you wish.  System 6 and
  89.         earlier (which uses the Control Panel desk accessory) requires the control
  90.         panel to be in the rectangle (-1, 87, 255, 322).  In both cases, the origin
  91.         of your control panel should be at (-1, 87).  This leaves space for the
  92.         scrolling list of icons in the Control Panel desk accessory and is left
  93.         off in System 7.
  94.     
  95.     The 'nrct' resource:
  96.     
  97.         This resource contains coordinates for rectangles within your control
  98.         panel.  The Control Panel Manager will draw a 2-pixel box around each
  99.         rectangle defined in this resource.  You may include only one rectangle
  100.         if you like (to surround the entire control panel), or you can define 
  101.         several to separate different sets of controls.  This example includes
  102.         three rectangles:  one surrounds the on and off radio buttons, another
  103.         surrounds the PICT at the top of the control panel, and another
  104.         surrounds the rest of the controls/items.  This resource should have an
  105.         ID number of -4064.  If the rectangles you define do not form a rectangle
  106.         when put together, the extra space is filled in with a gray pattern.
  107.     
  108.     The 'DITL' resource:
  109.     
  110.         This is a standard dialog item list resource that defines all the controls
  111.         and other items in your control panel.  The ID numbers you give each item
  112.         are used to identify those items in your code that responds to the hitDev
  113.         message.  This resource should have an ID number of -4064.
  114.         
  115.         NOTE:  According to the New Inside Macintosh:  More Macintosh Toolbox,
  116.         chapter 8 (Control Panels), if you use a font other than the standard 
  117.         application font (if you define an 'finf' resource), you must define
  118.         text as user items rather than static text items in order for the
  119.         control panel to run in the Control Panel Desk Accessory in System 6
  120.         and earlier.
  121.         
  122.     The 'ICN#' (and related) resources:
  123.         
  124.         This is simply the icon that represents the control panel in the finder.
  125.         The ICN# resource actually refers to other resources that define icons
  126.         for different screen depths and statuses.  It is sometimes referred to
  127.         as an 'icon family' resource.  This resource must have an ID number of
  128.         -4064 and must be purgeable.
  129.         
  130.         The Mac does NOT automatically draw your control panel's icon on the
  131.         screen during startup.  We use a routine called ShowIconFamily in our
  132.         extension code to do this.
  133.     
  134.     The 'mach' resource:
  135.     
  136.         This resource indicates to the Control Panel Manager what type of machine
  137.         this control panel runs on or if it needs to check with the control panel
  138.         for that.  It has these possible values (in hex, 4 bytes):
  139.         
  140.             0000 FFFF    Call control panel with macDev message.  The control panel
  141.                         will return true if it can run on this machine and false if
  142.                         it cannot.  This example code will simply return true if
  143.                         called with the macDev message.
  144.             
  145.             3FFF 0000    Runs on Mac II systems only.
  146.             
  147.             7FFF 0400    Runs on all Macs with an ADB (Apple Desktop Bus).
  148.             
  149.             FFFF 0000    Runs on all Macs.
  150.     
  151.     The 'finf' resource:
  152.     
  153.         This resource specifies a font other than the standard application font
  154.         to be used for drawing the text in your control panel.  This only works
  155.         in System 7.  In earlier systems, define text as user items instead of
  156.         static text items and draw the text in whatever font you wish.  This
  157.         resource should have an ID number of -4049.
  158.         
  159.         For purposes of this example, I did use static text items and an 'finf'
  160.         resource.  In system 6 and earlier, text will be drawn in the standard
  161.         application font.
  162.         
  163.     Of course, your control panel will need to include a file reference (FREF)
  164.     resource, bundle (BNDL) resource, and signature resource.  Refer to your
  165.     development system documentation or Inside Macintosh for information on
  166.     these resources.
  167.     
  168.     BUILDING THE CODE RESOURCE
  169.     
  170.         This file should be included in a project of type 'code resource' along
  171.         with MacTraps. The type should be 'cdev' and the ID should be -4064.
  172.         The file type should also be 'cdev'.
  173.         The file should have the purgeable attribute set, and the locked
  174.         attribute should NOT be set. You should create a new file when you
  175.         build this code resource, then merge the extension (INIT) and patch
  176.         code resources into the same file.
  177. */
  178.  
  179.  
  180. #define    LOCKP    HLock( (Handle)myData->CPprefsRsrc )    /* lock handle to prefs rsrc */
  181. #define    UNLOCKP    HUnlock( (Handle)myData->CPprefsRsrc )    /* unlock same */
  182.  
  183. #include "SharedData.h"            /* The definition of our shared data structure. */
  184.                                 /* Includes definitions of myDataStruct, myDataPtr, */
  185.                                 /* and myDataHandle to refer to this data */
  186.  
  187. /* used for any dialog shown by DoInfoDialog */
  188.  
  189. #define kTheOKButton        1
  190.  
  191. /* about box item defines */
  192.  
  193. #define    kAboutDialogID    -4048
  194. #define kAboutOKButton        1
  195. #define kAboutText            2
  196.  
  197. /* changes after restart dialog defines */
  198.  
  199. #define kRestartDialogID    -4047
  200. #define kRestartOKButton    1
  201. #define kRestartText        2
  202.  
  203. /* control panel unavailable dialog defines */
  204.  
  205. #define kUnavailDialogID    -4046
  206. #define kUnavailOKButton    1
  207. #define kUnavailText        2
  208.  
  209. /* control panel item defines */
  210.  
  211. #define    kCPAboutButton        1
  212. #define kCPShowIconBox        2
  213. #define kCPOnRadioButton    3
  214. #define kCPOffRadioButton    4
  215.  
  216. /* control panel preferences resource defines */
  217.  
  218. #define kCPprefsRsrcType    'pref'
  219. #define    kCPprefsRsrcID        -4048    /* careful - this number is also used in the INIT */
  220.  
  221. /* shared memory address resource defines */
  222.  
  223. #define kMemAddrType        'memA'
  224. #define kMemAddrID            -4048    /* careful - this number is also used in the INIT */
  225.  
  226. typedef struct {        /* struct used to load the memory address resource */
  227.     long    theAddr;
  228. } **memAddrHdl;
  229.  
  230. /* prototypes */
  231.  
  232. pascal long    main( short message, short item, short numItems, short cpID,
  233.     EventRecord *evt, long cdevValue, DialogPtr theCP );
  234. myDataPtr    InitCP( DialogPtr theCP, short numItems );
  235. void    CloseCP( myDataPtr myData );
  236. void    Hit( myDataPtr myData, short whichItem );
  237. void    Twiddle( myDataPtr myData );
  238. void    Update( myDataPtr myData );
  239. void    Activate( myDataPtr myData );
  240. void    Deactivate( myDataPtr myData );
  241. void    KeyPress( myDataPtr myData, EventRecord *event );
  242. void    Undo( myDataPtr myData );
  243. void    Cut( myDataPtr myData );
  244. void    Copy( myDataPtr myData );
  245. void    Paste( myDataPtr myData );
  246. void    Clear( myDataPtr myData );
  247. void    DoInfoDialog( short theDialogID );
  248.  
  249. /* Functions */
  250.  
  251. pascal long    main( short message, short item, short numItems, short cpID,
  252.     EventRecord *evt, long cdevValue, DialogPtr theCP )
  253. {
  254.     myDataPtr        myData;        /* address of my shared data (shared with patch) */
  255.     long            result;        /* result to return */
  256.     char            theChar;    /* used to handle some key presses */
  257.  
  258.     /*    This function gets called every time any action is taken in this control
  259.      *    panel (including opening & closing).  If this isn't the first call to
  260.      *    the control panel (just opening), the value we need for myData should
  261.      *    be passed to us in cdevValue.
  262.      */
  263.          if ( message == initDev )
  264.              myData = NULL;
  265.          else
  266.              myData = (myDataPtr)cdevValue;
  267.          
  268.     /*    The macDev message is sent if the Mac wants to see if we should be
  269.      *    showing in the Control Panel.  Since we want to be run on any machine,
  270.      *    we do no checking; we just return true.
  271.      */
  272.      
  273.         if ( message == macDev )
  274.             return 1L;
  275.     
  276.     /*    Here, we decide what to do based on the 'message' received from the
  277.      *    Control Panel.
  278.      */
  279.      
  280.          result = (long)myData;    /* Unless there's an error, always return myData */
  281.          
  282.         switch ( message )
  283.         {
  284.             case initDev:    /* initialize - user opened this control panel */
  285.                 myData = InitCP( theCP, numItems );
  286.                 if ( myData )
  287.                 {
  288.                     result = (long)myData;
  289.                 }
  290.                 else
  291.                 {
  292.                     DoInfoDialog( kUnavailDialogID );
  293.                     result = cdevGenErr;
  294.                 }
  295.                 break;
  296.                 
  297.             case closeDev:    /* close - last call to this device before closing */
  298.                 CloseCP( myData );
  299.                 break;
  300.                 
  301.             case hitDev:    /* user has pressed mouse button on an item */
  302.                 Hit( myData, item - numItems );
  303.                 break;
  304.                 
  305.             case nulDev:    /* nothing else to report - so twiddle */
  306.                 Twiddle( myData );
  307.                 break;
  308.                 
  309.             case updateDev:    /* update panel window (redraw controls, etc.) */
  310.                 Update( myData );
  311.                 break;
  312.                 
  313.             case activDev:    /* becoming active after being in background */
  314.                 Activate( myData );
  315.                 break;
  316.                 
  317.             case deactivDev:    /* becoming inactive after being in foreground */
  318.                 Deactivate( myData );
  319.                 break;
  320.                 
  321.             case keyEvtDev:    /* user has pressed a key */
  322.                 /* Check to see if the command key was down for menu equivalents */
  323.                     if ( ( evt->what != autoKey ) && ( evt->modifiers & cmdKey ) )
  324.                     {
  325.                         theChar = ( evt->message & charCodeMask );
  326.                         switch ( theChar )
  327.                         {
  328.                             case 'z':            /* menu command equivalents */
  329.                             case 'Z':
  330.                                 Undo( myData );        /* undo */
  331.                                 break;
  332.                             case 'x':
  333.                             case 'X':
  334.                                 Cut( myData );        /* cut */
  335.                                 break;
  336.                             case 'c':
  337.                             case 'C':
  338.                                 Copy( myData );        /* copy */
  339.                                 break;
  340.                             case 'v':
  341.                             case 'V':
  342.                                 Paste( myData );    /* paste */
  343.                                 break;
  344.                         }
  345.                     }
  346.                     else
  347.                     {
  348.                         KeyPress( myData, evt );    /* process other keystroke */
  349.                     }
  350.                 break;
  351.                 
  352.             case undoDev:    /* user picked UNDO from the Edit menu */
  353.                 Undo( myData );
  354.                 break;
  355.                 
  356.             case cutDev:    /* user picked CUT from the Edit menu */
  357.                 Cut( myData );
  358.                 break;
  359.                 
  360.             case copyDev:    /* user picked COPY from the Edit menu */
  361.                 Copy( myData );
  362.                 break;
  363.                 
  364.             case pasteDev:    /* user picked PASTE from the Edit menu */
  365.                 Paste( myData );
  366.                 break;
  367.                 
  368.             case clearDev:    /* user picked CLEAR from the Edit menu */
  369.                 Clear( myData );
  370.                 break;
  371.         }
  372.     return result;
  373. }
  374.  
  375.  
  376. myDataPtr    InitCP( DialogPtr theCP, short numItems )
  377. {
  378.     short        itemType;        /* these 3 local vars that can be used to */
  379.     Handle        itemHandle;        /* manipulate items in the control     */
  380.     Rect        itemRect;        /* panel dialog */
  381.     myDataPtr    myData;            /* a pointer to our shared data structure */
  382.     
  383.     memAddrHdl    memAddr;        /* Handle to the rsrc containing the addr of our */
  384.                                 /* shared memory data structure */
  385.     CPprefsPtr    myPrefs;        /* pointer to our preferences resource struct */
  386.     
  387.     /*    At this point, the control panel has just been opened. */
  388.     
  389.     /*    Attempt to load the resource containing the addr of our shared memory struct */
  390.     
  391.         memAddr = (memAddrHdl)Get1Resource( kMemAddrType, kMemAddrID );
  392.         
  393.         if ( !memAddr )        /* could not load resource */
  394.         {
  395.             return NULL;    /* return NULL to indicate an error */
  396.         }
  397.         else
  398.         {
  399.             myData = (myDataPtr)((*memAddr)->theAddr); /* get addr of shared memory */
  400.                 
  401.             ReleaseResource( (Handle)memAddr );    /* release the rsrc - we have the info */
  402.             
  403.             /* check the check value in the shared data to see if this is really */
  404.             /* the data */
  405.             
  406.             if ( myData->checkValue != kCheckValue )
  407.                 return NULL;    /* return NULL to indicate an error */
  408.         }
  409.             
  410.     /*    Wait until the data structure is not being used by someone else */
  411.     
  412.         while ( myData->inUse ) {}
  413.         
  414.     /*    Now mark the data structure as being in use by setting the inUse flag to true */
  415.     
  416.         myData->inUse = true;
  417.     
  418.     /*    Set up data structure with info about us. */
  419.     
  420.         myData->CPdialogPtr = theCP;        /* dialog pointer for the panel window */
  421.         myData->CPitems = numItems;        /* number of items in the dialog */
  422.     
  423.     /*    Load the control panel preferences resource.  Leave it unlocked except when
  424.      *    when we need to lock it.  When the control panel is closed, the resource
  425.      *    will be released.
  426.      */
  427.         
  428.         myData->CPprefsRsrc =
  429.             (CPprefsHandle)Get1Resource( kCPprefsRsrcType, kCPprefsRsrcID );
  430.         
  431.         if ( myData->CPprefsRsrc )
  432.         {
  433.             LOCKP;                                /* it's there - lock it down and */
  434.             myPrefs = (*(myData->CPprefsRsrc));    /* dereference for easy access */
  435.                                                 /* since it's locked */
  436.         }
  437.         else    /* it's not there - create a new resource */
  438.         {
  439.             myData->CPprefsRsrc =
  440.                 (CPprefsHandle)NewHandleClear( sizeof( CPprefsStruct ) );
  441.             
  442.             if ( myData->CPprefsRsrc )
  443.             {
  444.                 LOCKP;                                    /* lock the new handle */
  445.                 myPrefs = (*(myData->CPprefsRsrc));    /* dereference for easy access */
  446.                                                         /* since it's locked */
  447.                 
  448.                 myPrefs->On = true;                    /* default is to set both of */
  449.                 myPrefs->ShowIcon = true;            /* these to true */
  450.                 
  451.                 AddResource( (Handle)myData->CPprefsRsrc, kCPprefsRsrcType,
  452.                     kCPprefsRsrcID, "\pPreferences" );
  453.             }
  454.             else    /* unable to create new Handle for resource */
  455.             {
  456.                 myData->inUse = false;
  457.                 return NULL;            /* exit with an error */
  458.             }
  459.         }
  460.         
  461.     /*    Set all controls to their correct values. */
  462.     
  463.         /* Get the ON button item */
  464.         
  465.             GetDItem( myData->CPdialogPtr, kCPOnRadioButton,
  466.                 &itemType, &itemHandle, &itemRect );
  467.                 
  468.             if ( myPrefs->On )
  469.                 SetCtlValue( (ControlHandle)itemHandle, 1 );
  470.             else
  471.                 SetCtlValue( (ControlHandle)itemHandle, 0 );
  472.                 
  473.         /* Get the OFF button item */
  474.         
  475.             GetDItem( myData->CPdialogPtr, kCPOffRadioButton,
  476.                 &itemType, &itemHandle, &itemRect );
  477.                 
  478.             if ( myPrefs->On )
  479.                 SetCtlValue( (ControlHandle)itemHandle, 0 );
  480.             else
  481.                 SetCtlValue( (ControlHandle)itemHandle, 1 );
  482.                 
  483.         /* Get the Show Icon check box item */
  484.         
  485.             GetDItem( myData->CPdialogPtr, kCPShowIconBox,
  486.                 &itemType, &itemHandle, &itemRect );
  487.             
  488.             if ( myPrefs->ShowIcon )
  489.                 SetCtlValue( (ControlHandle)itemHandle, 1 );
  490.             else
  491.                 SetCtlValue( (ControlHandle)itemHandle, 0 );
  492.     
  493.     /*    Unlock the prefs rsrc, but don't allow it to be purged */
  494.     
  495.         HNoPurge( (Handle)myData->CPprefsRsrc );
  496.         UNLOCKP;
  497.  
  498.     /*    Done with the data structure for now */
  499.     
  500.         myData->inUse = false;
  501.     
  502.     return myData;
  503. }
  504.  
  505.  
  506. void    CloseCP( myDataPtr myData )
  507. {
  508.     /*    Here, we would want to destroy anything we created while the control panel
  509.      *    was "up."  The only thing left should be the shared data structure (which
  510.      *    we never destroy).  Leaving things lying around in memory can only lead to
  511.      *    system bombs.  If we wanted to save any settings to disk, this would
  512.      *    be the place to do it.
  513.      */
  514.      
  515.      CPprefsHandle        prefsHandle;
  516.      
  517.      /* Wait until our data structure is not in use */
  518.      
  519.          while ( myData->inUse ) {}
  520.          
  521.      /* Now that it's free, mark it as in use for us */
  522.      
  523.          myData->inUse = true;
  524.      
  525.      /* Write our preferences resource back to the resource file */
  526.      
  527.          prefsHandle = myData->CPprefsRsrc;
  528.          ChangedResource( (Handle)prefsHandle );
  529.          WriteResource( (Handle)prefsHandle );
  530.      
  531.      /* Save the on/off status of the control panel in the CPon field of the */
  532.      /* shared data structure. */
  533.      
  534.          myData->CPon = (*prefsHandle)->On;
  535.          
  536.      /* Unlock the resource and release it.  We'll reload it next time we're opened. */
  537.      
  538.          UNLOCKP;
  539.          ReleaseResource( (Handle)prefsHandle );
  540.          myData->CPprefsRsrc = NULL;
  541.          prefsHandle = NULL;
  542.          
  543.      /* Now we're through using our shared data structure */
  544.      
  545.          myData->inUse = false;
  546. }
  547.  
  548.  
  549. void    Hit( myDataPtr myData, short whichItem )
  550. {
  551.     /*    The user has pressed a button or clicked in a text editing field in the
  552.      *    control panel.  Handle the 'hit' here.
  553.      */
  554.      
  555.     short        itemType;        /* these 3 local vars that can be used to */
  556.     Handle        itemHandle;        /* manipulate items in the control     */
  557.     Rect        itemRect;        /* panel dialog */
  558.  
  559.     CPprefsHandle    prefsHandle;    /* used to more conveniently access the prefs rsrc */
  560.     
  561.     LOCKP;
  562.     prefsHandle = myData->CPprefsRsrc;
  563.     
  564.     switch ( whichItem )
  565.     {
  566.         case kCPAboutButton:
  567.             DoInfoDialog( kAboutDialogID );
  568.             break;
  569.             
  570.         case kCPOnRadioButton:
  571.             if ( !(*prefsHandle)->On )    /* if off */
  572.             {
  573.                 GetDItem( myData->CPdialogPtr, kCPOnRadioButton,
  574.                     &itemType, &itemHandle, &itemRect );
  575.                 SetCtlValue( (ControlHandle)itemHandle, 1 );
  576.                 
  577.                 GetDItem( myData->CPdialogPtr, kCPOffRadioButton,
  578.                     &itemType, &itemHandle, &itemRect );
  579.                 SetCtlValue( (ControlHandle)itemHandle, 0 );
  580.                 
  581.                 (*prefsHandle)->On = true;
  582.                 
  583.                 if ( !myData->patched )
  584.                     DoInfoDialog( kRestartDialogID );
  585.             }
  586.             break;
  587.             
  588.         case kCPOffRadioButton:
  589.             if ( (*prefsHandle)->On )    /* if on */
  590.             {
  591.                 GetDItem( myData->CPdialogPtr, kCPOnRadioButton,
  592.                     &itemType, &itemHandle, &itemRect );
  593.                 SetCtlValue( (ControlHandle)itemHandle, 0 );
  594.                 
  595.                 GetDItem( myData->CPdialogPtr, kCPOffRadioButton,
  596.                     &itemType, &itemHandle, &itemRect );
  597.                 SetCtlValue( (ControlHandle)itemHandle, 1 );
  598.                 
  599.                 (*prefsHandle)->On = false;
  600.             }
  601.             break;
  602.  
  603.         case kCPShowIconBox:
  604.             GetDItem( myData->CPdialogPtr, kCPShowIconBox,
  605.                 &itemType, &itemHandle, &itemRect );
  606.  
  607.             if ( (*prefsHandle)->ShowIcon )    /* if on */
  608.             {
  609.                 SetCtlValue( (ControlHandle)itemHandle, 0 );        /* turn it off */
  610.                 (*prefsHandle)->ShowIcon = false;
  611.             }
  612.             else
  613.             {
  614.                 SetCtlValue( (ControlHandle)itemHandle, 1 );        /* turn it on */
  615.                 (*prefsHandle)->ShowIcon = true;
  616.             }
  617.             break;
  618.     }
  619.     UNLOCKP;
  620. }
  621.  
  622.  
  623. void    Twiddle( myDataPtr myData )
  624. {
  625.     /*    The user isn't doing anything at the moment, so take this time to do
  626.      *    odds and ends (if needed) in this idle time.
  627.      */
  628.  
  629.  
  630. }
  631.  
  632.  
  633. void    Update( myDataPtr myData )
  634. {
  635.     /*    We need to redraw the panel because something has screwed it up (like
  636.      *    another window moved from in front of it).  This is the same as in any
  637.      *    application except we don't call BeginUpdate() and EndUpdate().  The
  638.      *    Dialog Manager should take care of redrawing any controls.
  639.      */
  640.      
  641. }
  642.  
  643.  
  644. void    Activate( myDataPtr myData )
  645. {
  646.     /*    We're becoming active either because we were just opened, or we were in
  647.      *    the background and we're being brought to the foreground.  Take care of
  648.      *    hiliting text fields or list items or whatever.
  649.      */
  650.      
  651. }
  652.  
  653.  
  654. void    Deactivate( myDataPtr myData )
  655. {
  656.     /*    We're becoming inactive because we're being sent to the background.  Take
  657.      *    care of unhiliting text fields, list items, or whatever.
  658.      */
  659.  
  660. }
  661.  
  662.  
  663. void    KeyPress( myDataPtr myData, EventRecord *event )
  664. {
  665.     /*    The user has pressed a key on the keyboard (or a combination of keys).  In
  666.      *    any case, a keyboard event has been generated.  The main routine has already
  667.      *    checked for command key menu equivalents, so any real typing is handled
  668.      *    here (possibly by passing it on to textEdit if you have text fields).
  669.      *    I saw a note from Symantec in their cdev example that said text fields don't
  670.      *    seem to work correctly in control panels, so they convert theirs to user
  671.      *    items (at least while the panel's open).  I haven't tried it.
  672.      */
  673.  
  674. }
  675.  
  676.  
  677. void    Undo( myDataPtr myData )
  678. {
  679.     /*    User has selected UNDO from the Edit menu.  Undo the last action here if
  680.      *    it's appropriate and you've implemented an undo.  Otherwise, ignore.
  681.      */
  682.  
  683.     SysBeep( 3 );
  684. }
  685.  
  686.  
  687. void    Cut( myDataPtr myData )
  688. {
  689.     /*    User has selected CUT from the Edit menu.  If you have a text field that
  690.      *    is active, pass this along to textEdit.  Otherwise, ignore.
  691.      */
  692.     
  693.     SysBeep( 3 );
  694. }
  695.  
  696.  
  697. void    Copy( myDataPtr myData )
  698. {
  699.     /*    User has selected COPY from the Edit menu.  If you have a text field that
  700.      *    is active, pass this along to textEdit.  Otherwise, ignore.
  701.      */
  702.     
  703.     SysBeep( 3 );
  704. }
  705.  
  706.  
  707. void    Paste( myDataPtr myData )
  708. {
  709.     /*    User has selected PASTE from the Edit menu.  If you have a text field that
  710.      *    is active, pass this along to textEdit.  Otherwise, ignore.
  711.      */
  712.     
  713.     SysBeep( 3 );
  714. }
  715.  
  716.  
  717. void    Clear( myDataPtr myData )
  718. {
  719.     /*    User has selected CLEAR from the Edit menu.  If you have a text field that
  720.      *    is active, pass this along to textEdit.  Otherwise, ignore.
  721.      */
  722.     
  723.     SysBeep( 3 );
  724. }
  725.  
  726.  
  727. void    DoInfoDialog( short theDialogID )
  728. {
  729.     /*    This routine displays a dialog that tells the user of an error
  730.      *    or conveys some other information in a simple dialog with just
  731.      *    an OK button.
  732.      */
  733.     
  734.     WindowPtr        winMgrPort;        /* store current window mgr port here */
  735.     WindowPtr        currentPort;    /* store the current port here */
  736.     DialogPtr        theDlg;            /* to store our dialog in */
  737.     
  738.     short        itemType;        /* these 3 local variables are used to */
  739.     Handle        itemHandle;        /* manipulate items in the dialog.     */
  740.     Rect        itemRect;
  741.  
  742.     short        itemHit;        /* use with ModalDialog */
  743.     Point        refPt;            /* a reference point */
  744.     
  745.     /*    Get the window manager port and the current port (our control panel)
  746.      *    Then convert the upper left corner of the control panel to a global
  747.      *    point for referencing our dialog.
  748.      */
  749.      
  750.          GetWMgrPort( &winMgrPort );
  751.          GetPort( ¤tPort );
  752.          
  753.          SetPt( &refPt, 0, 0 );
  754.          LocalToGlobal( &refPt );
  755.          refPt.h += 107;        /* move to right over actual panel */
  756.          refPt.v += 80;        /* also move it down some */
  757.          
  758.     /*    Now, load our dialog resource, move it on top of the control panel,
  759.      *    make it the current port, then make it visible (the resource should
  760.      *    mark the dialog as NOT initially visible.
  761.      */
  762.     
  763.         theDlg = GetNewDialog( theDialogID, NULL, (WindowPtr)-1L );
  764.         
  765.         /* This is an example - move your about dialog wherever you want */
  766.         
  767.         MoveWindow( theDlg, refPt.h, refPt.v, true );
  768.         
  769.         SetPort( theDlg );
  770.         
  771.         ShowWindow( theDlg );
  772.     
  773.      /*    Get the OK button item and draw a bold border around it to show that
  774.       *    it's the default button.
  775.       */
  776.      
  777.          GetDItem( theDlg, kTheOKButton, &itemType, &itemHandle, &itemRect );
  778.          InsetRect( &itemRect, -4, -4 );
  779.          PenSize( 3, 3 );
  780.          FrameRoundRect( &itemRect, 16, 16 );
  781.          PenSize( 1, 1 );
  782.      
  783.      /*    Loop and call ModalDialog until the user presses the OK button */
  784.      
  785.          ModalDialog( NULL, &itemHit );
  786.          while ( itemHit != kRestartOKButton )
  787.              ModalDialog( NULL, &itemHit );
  788.          
  789.      /*    Now get rid of the dialog and set the port back to the control panel */
  790.      
  791.          DisposDialog( theDlg );
  792.          SetPort( currentPort );
  793. }
  794.