TweetFollow Us on Twitter

MACINTOSH C

Demonstration Program

Go to Contents
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
// Controls3.h
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
//
// This program demonstrates the creation and handling of those controls not demonstrated
// in the programs Controls1 and Controls2 (Chapter 7), with the exception of List boxes
// and determinate progress bars.
// 
// The program utilises the following resources:
//
// „  An 'MBAR' resource, and 'MENU' resources for Apple, File, Edit, and Demonstration
//    menus (preload, non-purgeable).
//
// „  'MENU' resources (non-purgeable) for bevel button menus and for a pop-up group box.
//
// „  A 'WIND' resource (purgeable) (initially not visible).
//
// „  'DLOG' resources and associated 'DITL', 'dlgx' and 'dftb' resources (purgeable).
//
// „  'CNTL' resources (purgeable).
//
// „  A 'tab#' resource (purgeable.
//
// „  An icon family resource (purgeable).
//
// „  'PICT' resources (purgeable).
//
// „  'cicn' resources (purgeable).
//
// „  'STR#' resources (purgeable).
//
// „  'TEXT' and 'styl' resources (purgeable).
//
// „  'hrct' and an 'hwin' resources (preload, purgeable), which provide help 
//    balloons describing  the various controls.  
//
// „  A 'SIZE' resource with the acceptSuspendResumeEvents, doesActivateOnFGSwitch,
//    and is32BitCompatible flags set.    
//
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

// ............................................................................. includes

#include <Appearance.h>
#include <ControlDefinitions.h>
#include <Devices.h>
#include <Gestalt.h>
#include <LowMem.h>
#include <Sound.h>
#include <ToolUtils.h>
#include <Resources.h>

// .............................................................................. defines

#define rMenubar                128
#define mApple                  128
#define  iAbout                  1
#define mFile                    129
#define  iQuit                  11
#define mDemonstration          131
#define  iBevelAndImage          1
#define  iTabEditClock          2
#define  iGroupArrowsProgress    3
#define  iSliders                4
#define rBevelImageWindow        128
#define  cBevelButton1          128
#define  cBevelButton2          129
#define  cBevelButton3          130
#define  cBevelButton4          131
#define  cBevelButton5          132
#define  cBevelButton6          133
#define  cBevelButton7          134
#define  cBevelButton8          135
#define  cBevelButton9          136
#define  cBevelButton10          137
#define  cBevelButton11          138
#define  cBevelButton12          139
#define  cBevelButton13          140
#define  cBevelButton14          141
#define  cBevelButton15          142
#define  cBevelButton16          143
#define  cBevelButton17          144
#define  cBevelButton18          145
#define  cBevelButton19          146
#define  cBevelButton20          147
#define  cBevelButton21          148
#define  cImageWell1            149
#define  cImageWell2            150
#define  cPicture1              151
#define  cPicture2              152
#define  cColourIcon1            153
#define  cColourIcon2            154
#define  cIconSuite1            155
#define  cIconSuite2            156
#define  cWindowHeader          157
#define  rPartCodeStrings        128
#define  rGraphicAlignStrings    129
#define  rTextAlignStrings      130
#define  rTextPlacementStrings  131
#define rTabEditClockDialog      128
#define  iTabs                  2
#define  tabEditText            1
#define  tabClocks              2
#define  iEditTextUserPane      3
#define  iEditText1              5
#define  iEditText2              7
#define  iEditText3              9
#define  iExtractEditText        10
#define  iClocksUserPane        12
#define  iImageWellEditText      11
#define  iClocks1                14
#define  iClocks2                16
#define  iClocks3                18
#define  iExtractClocks          19
#define  iImageWellClocks        20
#define  kLeftArrow              0x1C
#define  kRightArrow            0x1D
#define  kUpArrow                0x1E
#define  kDownArrow              0x1F
#define  kBackspace              0x08
#define rGroupArrowsProgDialog  129
#define  iCheckboxGroup          2
#define  iRadioGroupColour      3
#define  iStaticTextColourDepth  7
#define  iPopupGroup            8
#define  iUserPaneNamesInitials  9
#define  iRadioGroupNames        10
#define  iCheckboxShowInitials  13
#define  iUserPaneScoreAverage  15
#define  iRadioGroupScores      16
#define  iCheckboxShowAverages  19
#define  iStaticTextCache        26
#define  iLittleArrows          27
#define  iPushButtonExtract      28
#define  iImageWell              29
#define  iDisclosureTriangle    31
#define  iStaticTextDisclosure  32
#define  iProgressBar            34
#define rSlidersDialog          131
#define  iSlider1                2
#define  iSlider2                3
#define  iSlider3                4
#define  iSlider4                5
#define  iSlider1StaticText      9
#define  iSlider2StaticText      11
#define  iSlider3StaticText      13
#define  iSlider4StaticText      15
#define  iSlider5                17
#define  iUserPane1              18
#define  iSlider6                19
#define rAboutDialog             132
#define MAXLONG                  0x7FFFFFFF
#define MIN(a,b)                 ((a) < (b) ? (a) : (b))

// ............................................................................. typedefs

typedef struct
{
  ControlHandle  bevelButton1Hdl;
  ControlHandle  bevelButton2Hdl;
  ControlHandle  bevelButton3Hdl;
  ControlHandle  bevelButton4Hdl;
  ControlHandle  bevelButton5Hdl;
  ControlHandle  bevelButton6Hdl;
  ControlHandle  bevelButton7Hdl;
  ControlHandle  bevelButton8Hdl;
  ControlHandle  bevelButton9Hdl;
  ControlHandle  bevelButton10Hdl;
  ControlHandle  bevelButton11Hdl;
  ControlHandle  bevelButton12Hdl;
  ControlHandle  bevelButton13Hdl;
  ControlHandle  bevelButton14Hdl;
  ControlHandle  bevelButton15Hdl;
  ControlHandle  bevelButton16Hdl;
  ControlHandle  bevelButton17Hdl;
  ControlHandle  bevelButton18Hdl;
  ControlHandle  bevelButton19Hdl;
  ControlHandle  bevelButton20Hdl;
  ControlHandle  bevelButton21Hdl;
  ControlHandle  imageWell1Hdl;
  ControlHandle  imageWell2Hdl;
  ControlHandle  picture1Hdl;
  ControlHandle  picture2Hdl;
  ControlHandle  colourIcon1Hdl;
  ControlHandle  colourIcon2Hdl;
  ControlHandle  iconSuite1Hdl;
  ControlHandle  iconSuite2Hdl;
  ControlHandle  windowHeaderHdl;
} BevelDocStruc;

typedef BevelDocStruc **BevelDocStrucHandle;

// .................................................................. function prototypes

void  main                        (void);
void  doInitManagers              (void);
void  doGetControls                (WindowPtr);
void  doEvents                    (EventRecord *);
void  doMouseDown                  (EventRecord *);
void  doMenuChoice                (SInt32);
void  doUpdate                    (EventRecord *);
void  doActivate                  (EventRecord *);
void  doActivateWindow            (WindowPtr,Boolean);
void  doConcatPStrings            (Str255,Str255);
void  doCopyPString                (Str255,Str255);
void  doGetDepthAndDevice          (void);
void  doBevelImagePictIcon        (void);
void  doBevelImagePictIconContent  (EventRecord *,WindowPtr);
void  doDrawPartCode              (WindowPtr,ControlHandle,SInt16,SInt16);
void  doGraphicAlignment          (WindowPtr,ControlHandle,ControlHandle);
void  doTextAlignment              (WindowPtr,ControlHandle,ControlHandle);
void  doTextOffset                (WindowPtr,ControlHandle,ControlHandle);
void  doTextPlacement              (WindowPtr,ControlHandle,ControlHandle);
void  doDrawMessage                (WindowPtr,Boolean);
void  doDrawLegends                (Boolean);
void  doTabEditClock              (void);
void  doExtractEditText            (DialogPtr);
void  doExtractDateTime            (DialogPtr);
void  doGroupArrowsProgress        (void);
void  doCheckBoxGroupBox          (DialogPtr);
void  doPopupGroupBox              (DialogPtr);
void  doAsynchronousAndProgress    (DialogPtr);
void  doExtractCurrentStatus      (DialogPtr);
void  doSliderUserPane            (void);
void  doDrawSliderValues          (DialogPtr,ControlHandle);
void  doAboutBox                  (void);

pascal Boolean      eventFilter                (DialogPtr,EventRecord *,SInt16 *);
pascal void          editTextValidator          (ControlHandle controlHdl);
pascal ControlKeyFilterResult  numericFilter    (ControlHandle,SInt16 *,SInt16 *,SInt16 *);
pascal void          arrowsActionFunction      (ControlHandle,SInt16);
pascal void          sliderActionFunction1      (ControlHandle,SInt16);
pascal void          sliderActionFunction2      (ControlHandle,SInt16);
pascal void          userPaneDrawFunction      (ControlHandle,SInt16);
pascal void          userPaneActivateFunction  (ControlHandle,Boolean);

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
// Controls3.c
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

// ............................................................................. includes

#include "Controls3.h"

// ..................................................................... global variables

Boolean  gInBackground;
Boolean  gDone;
Str255  gCurrentString;
Boolean  gBevelAndImageActive        = false;
Boolean  gGroupArrowsProgressActive  = false;
Boolean  gSlidersActive              = false;
Boolean  gPixelDepth;
Boolean  gIsColourDevice;

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× main

void  main(void)
{
  OSErr        osError;
  SInt32      response;
  Boolean      macOS85Present = false;
  Handle      menubarHdl;
  MenuHandle  menuHdl;
  EventRecord  EventStructure;

  // ................................................................ initialise managers

  doInitManagers();

  // ....................................... check whether Mac OS 8.5 or later is present

  osError = Gestalt(gestaltSystemVersion,&response);
  
  if(osError == noErr && response >= 0x00000850)
    macOS85Present = true;

  // .......................................................... set up menu bar and menus
  
  menubarHdl = GetNewMBar(rMenubar);
  if(menubarHdl == NULL)
    ExitToShell();
  SetMenuBar(menubarHdl);
  DrawMenuBar();

  menuHdl = GetMenuHandle(mApple);
  if(menuHdl == NULL)
    ExitToShell();
  else
    AppendResMenu(menuHdl,'DRVR');
    
  // .............. if Mac OS 8.5 or later not present, disable About. item in Apple menu

  if(!macOS85Present)
  {
    menuHdl = GetMenuHandle(mApple);
    DisableItem(menuHdl,iAbout);
  }

  // .................................................................... enter eventLoop

  gDone = false;

  while(!gDone)
  {
    if(WaitNextEvent(everyEvent,&EventStructure,MAXLONG,NULL))
      doEvents(&EventStructure);
  }
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doInitManagers

void  doInitManagers(void)
{
  MaxApplZone();
  MoreMasters();

  InitGraf(&qd.thePort);
  InitFonts();
  InitWindows();
  InitMenus();
  TEInit();
  InitDialogs(NULL);

  InitCursor();  
  FlushEvents(everyEvent,0);

  RegisterAppearanceClient();
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doEvents

void  doEvents(EventRecord *eventStrucPtr)
{
  SInt8    charCode;
  SInt32  menuChoice;
  SInt16  menuID, menuItem;

  switch(eventStrucPtr->what)
  {
    case keyDown:
    case autoKey:
      charCode = eventStrucPtr->message & charCodeMask;
      if((eventStrucPtr->modifiers & cmdKey) != 0)
      {
        menuChoice = MenuEvent(eventStrucPtr);
        menuID = HiWord(menuChoice);
        menuItem = LoWord(menuChoice);
        if(menuID == mFile && menuItem  == iQuit)
          gDone = true;
      }
      break;

    case mouseDown:
      doMouseDown(eventStrucPtr);
      break;

    case updateEvt:
      doUpdate(eventStrucPtr);
      break;

    case activateEvt:
      doActivate(eventStrucPtr);
      break;

    case osEvt:
      switch((eventStrucPtr->message >> 24) & 0x000000FF)
      {
        case suspendResumeMessage:
          gInBackground = (eventStrucPtr->message & resumeFlag) == 0;
          doActivateWindow(FrontWindow(),!gInBackground);
          break;
      }
      HiliteMenu(0);
      break;
  }
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doMouseDown

void  doMouseDown(EventRecord *eventStrucPtr)
{
  SInt16      partCode;
  WindowPtr    windowPtr;
  MenuHandle  menuHdl;

  partCode = FindWindow(eventStrucPtr->where,&windowPtr);
  
  switch(partCode)
  {
    case inMenuBar:
      menuHdl = GetMenuHandle(mDemonstration);
      if(gBevelAndImageActive)
        DisableItem(menuHdl,iBevelAndImage);
      else
        EnableItem(menuHdl,iBevelAndImage);
      doMenuChoice(MenuSelect(eventStrucPtr->where));
      break;

    case inContent:
      if(windowPtr != FrontWindow())
        SelectWindow(windowPtr);
      else
      {
        if(gBevelAndImageActive)
          doBevelImagePictIconContent(eventStrucPtr,windowPtr);
      }
      break;

    case inDrag:
      DragWindow(windowPtr,eventStrucPtr->where,&qd.screenBits.bounds);
      break;

    case inGoAway:
      if(TrackGoAway(windowPtr,eventStrucPtr->where) == true)
      {
        DisposeWindow(windowPtr);
        gBevelAndImageActive = false;
      }
      break;

  }
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doMenuChoice

void  doMenuChoice(SInt32 menuChoice)
{
  SInt16  menuID, menuItem;
  Str255  itemName;
  SInt16  daDriverRefNum;
         
  menuID = HiWord(menuChoice);
  menuItem = LoWord(menuChoice);

  if(menuID == 0)
    return;

  switch(menuID)
  {
    case mApple:
      if(menuItem == iAbout)
        doAboutBox();
      else
      {
        GetMenuItemText(GetMenuHandle(mApple),menuItem,itemName);
        daDriverRefNum = OpenDeskAcc(itemName);
      }
      break;

    case mFile:
      if(menuItem == iQuit)
        gDone = true;
      break;
      
    case mDemonstration:
      switch(menuItem)
      {
        case iBevelAndImage:
          gBevelAndImageActive = true;
          doBevelImagePictIcon();
          break;

        case iTabEditClock:
          doTabEditClock();
          break;

        case iGroupArrowsProgress:
          gGroupArrowsProgressActive = true;
          doGroupArrowsProgress();
          break;
        
        case iSliders:
          gSlidersActive = true;
          doSliderUserPane();
          break;
      }
      break;
  }

  HiliteMenu(0);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doUpdate

void  doUpdate(EventRecord *eventStrucPtr)
{
  WindowPtr  windowPtr;
  Boolean    drawMode = false;
    
  windowPtr = (WindowPtr) eventStrucPtr->message;

  BeginUpdate(windowPtr);

  if(gBevelAndImageActive)
  {
    SetPort(windowPtr);
    UpdateControls(windowPtr,windowPtr->visRgn);
    if(windowPtr == FrontWindow())
      drawMode = true;
    doDrawMessage(windowPtr,drawMode);
    doDrawLegends(drawMode);
  }
  
  EndUpdate(windowPtr);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doActivate

void  doActivate(EventRecord *eventStrucPtr)
{
  WindowPtr  windowPtr;
  Boolean    becomingActive;

  windowPtr = (WindowPtr) eventStrucPtr->message;
  becomingActive = ((eventStrucPtr->modifiers & activeFlag) == activeFlag);
  doActivateWindow(windowPtr,becomingActive);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doActivateWindow

void  doActivateWindow(WindowPtr windowPtr,Boolean becomingActive)
{  
  ControlHandle controlHdl;
    
  GetRootControl(windowPtr,&controlHdl);

  if(becomingActive)
  {
    if(gBevelAndImageActive)
    {
      ActivateControl(controlHdl);
      doDrawMessage(windowPtr,becomingActive);
      doDrawLegends(becomingActive);
    }
  }
  else
  {
    if(gBevelAndImageActive)
    {
      DeactivateControl(controlHdl);
      doDrawMessage(windowPtr,becomingActive);
      doDrawLegends(becomingActive);
    }
  }
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doConcatPStrings

void  doConcatPStrings(Str255 targetString,Str255 appendString)
{
  SInt16  appendLength;

  appendLength = MIN(appendString[0],255 - targetString[0]);

  if(appendLength > 0)
  {
    BlockMoveData(appendString+1,targetString+targetString[0]+1,(SInt32) appendLength);
    targetString[0] += appendLength;
  }
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doCopyPString

void  doCopyPString(Str255 sourceString,Str255 destinationString)
{
  SInt16  stringLength;

  stringLength = sourceString[0];
  BlockMove(sourceString + 1,destinationString + 1,stringLength);
  destinationString[0] = stringLength;
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doGetDepthAndDevice

void doGetDepthAndDevice(void)
{
  GDHandle  deviceHdl;

  deviceHdl = LMGetMainDevice();
  gPixelDepth = (*(*deviceHdl)->gdPMap)->pixelSize;
  if(BitTst(&(*deviceHdl)->gdFlags,gdDevType))
    gIsColourDevice = true;
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
// BevelImagePictIcon.c
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

// ............................................................................. includes

#include "Controls3.h"

// ..................................................................... global variables

extern Str255    gCurrentString;
extern Boolean  gInBackground;
extern SInt16    gPixelDepth;
extern Boolean  gIsColourDevice;

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doBevelImagePictIcon

void  doBevelImagePictIcon(void)
{
  WindowPtr            windowPtr;
  BevelDocStrucHandle  bevelDocStrucHdl;

  // ............................................ initial advisory text for window header

  doCopyPString("\pBalloon help is available",gCurrentString);

  // ... open a window, set font size, set Appearance-compliant colour/pattern for window

  if(!(windowPtr = GetNewCWindow(rBevelImageWindow,NULL,(WindowPtr)-1)))
    ExitToShell();

  SetPort(windowPtr);
  TextSize(10);
  
  SetThemeWindowBackground(windowPtr,kThemeBrushDialogBackgroundActive,true);

  // ...... get block for document structure, assign handle to window record refCon field

  if(!(bevelDocStrucHdl = (BevelDocStrucHandle) NewHandle(sizeof(BevelDocStruc))))
    ExitToShell();
  
  SetWRefCon(windowPtr,(SInt32) bevelDocStrucHdl);
  
  // .................................. get controls, adjust scroll bars, and show window

  doGetControls(windowPtr);
  ShowWindow(windowPtr);

  // ......... get pixel depth and whether colour device for certain Appearance functions   
  
  doGetDepthAndDevice();
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doGetControls

void  doGetControls(WindowPtr windowPtr)
{
  ControlHandle                controlHdl;
  BevelDocStrucHandle          bevelDocStrucHdl;
  ControlButtonTextPlacement  textPlacement = kControlBevelButtonPlaceAboveGraphic;
  Boolean                      centrePopupGlyph = true;
  ControlFontStyleRec          controlFontStyleStruc;

  // .......... create root control for window, get handle to window's document structure
  
  CreateRootControl(windowPtr,&controlHdl);

  bevelDocStrucHdl = (BevelDocStrucHandle) (GetWRefCon(windowPtr));

  // ................................................................... get the controls

  if(!((*bevelDocStrucHdl)->bevelButton1Hdl = GetNewControl(cBevelButton1,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton2Hdl = GetNewControl(cBevelButton2,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton3Hdl = GetNewControl(cBevelButton3,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton4Hdl = GetNewControl(cBevelButton4,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton5Hdl = GetNewControl(cBevelButton5,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton6Hdl = GetNewControl(cBevelButton6,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton7Hdl = GetNewControl(cBevelButton7,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton8Hdl = GetNewControl(cBevelButton8,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton9Hdl = GetNewControl(cBevelButton9,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton10Hdl = GetNewControl(cBevelButton10,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton11Hdl = GetNewControl(cBevelButton11,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton12Hdl = GetNewControl(cBevelButton12,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton13Hdl = GetNewControl(cBevelButton13,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton14Hdl = GetNewControl(cBevelButton14,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton15Hdl = GetNewControl(cBevelButton15,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton16Hdl = GetNewControl(cBevelButton16,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton17Hdl = GetNewControl(cBevelButton17,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton18Hdl = GetNewControl(cBevelButton18,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton19Hdl = GetNewControl(cBevelButton19,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton20Hdl = GetNewControl(cBevelButton20,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton21Hdl = GetNewControl(cBevelButton21,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->imageWell1Hdl = GetNewControl(cImageWell1,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->imageWell2Hdl = GetNewControl(cImageWell2,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->picture1Hdl = GetNewControl(cPicture1,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->picture2Hdl = GetNewControl(cPicture2,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->colourIcon1Hdl = GetNewControl(cColourIcon1,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->colourIcon2Hdl = GetNewControl(cColourIcon2,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->iconSuite1Hdl= GetNewControl(cIconSuite1,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->iconSuite2Hdl= GetNewControl(cIconSuite2,windowPtr)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->windowHeaderHdl = GetNewControl(cWindowHeader,windowPtr)))
    ExitToShell();

  // ................................... set text placement for 2nd and 21st bevel button

  SetControlData((*bevelDocStrucHdl)->bevelButton2Hdl,kControlNoPart,
                 kControlBevelButtonTextPlaceTag,sizeof(textPlacement),
                 (Ptr) &textPlacement);
  SetControlData((*bevelDocStrucHdl)->bevelButton21Hdl,kControlNoPart,
                 kControlBevelButtonTextPlaceTag,sizeof(textPlacement),
                 (Ptr) &textPlacement);
                 
  // ................................... set position of pop-up arrow in 6th bevel button

  SetControlData((*bevelDocStrucHdl)->bevelButton6Hdl,kControlNoPart,
                 kControlBevelButtonCenterPopupGlyphTag,sizeof(centrePopupGlyph),
                 (Ptr) ¢rePopupGlyph);

  // ........................... set font for 20th bevel button to small bold system font  

  controlFontStyleStruc.flags = kControlUseFontMask;
  controlFontStyleStruc.font = kControlFontSmallBoldSystemFont;
  SetControlFontStyle((*bevelDocStrucHdl)->bevelButton20Hdl,&controlFontStyleStruc);

  // ............................................ set 3rd bevel button to the mixed state

  SetControlValue((*bevelDocStrucHdl)->bevelButton3Hdl,2);
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doBevelImagePictIconContent

void  doBevelImagePictIconContent(EventRecord *eventStrucPtr,WindowPtr windowPtr)
{
  BevelDocStrucHandle  bevelDocStrucHdl;
  ControlHandle        controlHdl;
  SInt16              partCode, menuItem;

  bevelDocStrucHdl = (BevelDocStrucHandle) (GetWRefCon(windowPtr));

  SetPort(windowPtr);
  GlobalToLocal(&eventStrucPtr->where);
  partCode = FindControl(eventStrucPtr->where,windowPtr,&controlHdl);

  doDrawPartCode(windowPtr,(*bevelDocStrucHdl)->windowHeaderHdl,partCode,1234);

  if(partCode)
  {
    partCode = TrackControl(controlHdl,eventStrucPtr->where,NULL);

    if(controlHdl == (*bevelDocStrucHdl)->bevelButton1Hdl ||
       controlHdl == (*bevelDocStrucHdl)->bevelButton2Hdl ||
       controlHdl == (*bevelDocStrucHdl)->bevelButton3Hdl ||
       controlHdl == (*bevelDocStrucHdl)->bevelButton4Hdl ||
       controlHdl == (*bevelDocStrucHdl)->bevelButton9Hdl ||
       controlHdl == (*bevelDocStrucHdl)->bevelButton13Hdl ||
       controlHdl == (*bevelDocStrucHdl)->bevelButton14Hdl ||
       controlHdl == (*bevelDocStrucHdl)->bevelButton15Hdl ||
       controlHdl == (*bevelDocStrucHdl)->bevelButton16Hdl ||
       controlHdl == (*bevelDocStrucHdl)->bevelButton17Hdl)  
    {
      doDrawPartCode(windowPtr,(*bevelDocStrucHdl)->windowHeaderHdl,partCode,4321);
    }
    else if(controlHdl == (*bevelDocStrucHdl)->bevelButton5Hdl ||
            controlHdl == (*bevelDocStrucHdl)->bevelButton6Hdl ||
            controlHdl == (*bevelDocStrucHdl)->bevelButton7Hdl ||
            controlHdl == (*bevelDocStrucHdl)->bevelButton8Hdl)
    {
      if(partCode == kControlMenuPart)
      {
        GetControlData(controlHdl,kControlMenuPart,kControlBevelButtonMenuValueTag,
                       sizeof(menuItem),(Ptr) &menuItem,NULL);
        doDrawPartCode(windowPtr,(*bevelDocStrucHdl)->windowHeaderHdl,partCode,menuItem);
      }
      else
        doDrawPartCode(windowPtr,(*bevelDocStrucHdl)->windowHeaderHdl,partCode,4321);
    }
    else if(controlHdl == (*bevelDocStrucHdl)->bevelButton10Hdl ||
            controlHdl == (*bevelDocStrucHdl)->bevelButton11Hdl ||
            controlHdl == (*bevelDocStrucHdl)->bevelButton12Hdl)    
    {
      if(partCode != kControlNoPart)
      {
        SetControlValue((*bevelDocStrucHdl)->bevelButton10Hdl,0);
        SetControlValue((*bevelDocStrucHdl)->bevelButton11Hdl,0);
        SetControlValue((*bevelDocStrucHdl)->bevelButton12Hdl,0);
        SetControlValue(controlHdl,1);
      }
      doDrawPartCode(windowPtr,(*bevelDocStrucHdl)->windowHeaderHdl,partCode,4321);
    }
    else if(controlHdl == (*bevelDocStrucHdl)->bevelButton18Hdl)
    {
      doDrawPartCode(windowPtr,(*bevelDocStrucHdl)->windowHeaderHdl,partCode,4321);
      doGraphicAlignment(windowPtr,controlHdl,(*bevelDocStrucHdl)->windowHeaderHdl);
    }
    else if(controlHdl == (*bevelDocStrucHdl)->bevelButton19Hdl)
    {
      doDrawPartCode(windowPtr,(*bevelDocStrucHdl)->windowHeaderHdl,partCode,4321);
      doTextAlignment(windowPtr,controlHdl,(*bevelDocStrucHdl)->windowHeaderHdl);
    }
    else if(controlHdl == (*bevelDocStrucHdl)->bevelButton20Hdl)
    {
      doDrawPartCode(windowPtr,(*bevelDocStrucHdl)->windowHeaderHdl,partCode,4321);
      doTextOffset(windowPtr,controlHdl,(*bevelDocStrucHdl)->windowHeaderHdl);
    }
    else if(controlHdl == (*bevelDocStrucHdl)->bevelButton21Hdl)
    {
      doDrawPartCode(windowPtr,(*bevelDocStrucHdl)->windowHeaderHdl,partCode,4321);
      doTextPlacement(windowPtr,controlHdl,(*bevelDocStrucHdl)->windowHeaderHdl);
    }
    else
      doDrawPartCode(windowPtr,(*bevelDocStrucHdl)->windowHeaderHdl,partCode,4321);
  }
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doDrawPartCode

void  doDrawPartCode(WindowPtr windowPtr,ControlHandle windowHeaderHdl,SInt16 partCode,
                     SInt16 menuItem)
{
  SInt16  stringIndex;
  Str255  theString;
    
  if(partCode == kControlNoPart)
    stringIndex = 1;
  else if(partCode == kControlMenuPart)
    stringIndex = 2;
  else if(partCode == kControlTrianglePart)
    stringIndex = 3;
  else if(partCode == kControlEditTextPart)
    stringIndex = 4;
  else if(partCode == kControlPicturePart)
    stringIndex = 5;
  else if(partCode == kControlIconPart)
    stringIndex = 6;
  else if(partCode == kControlClockPart)
    stringIndex = 7;
  else if(partCode == kControlListBoxPart)
    stringIndex = 8;
  else if(partCode == kControlListBoxDoubleClickPart)
    stringIndex = 9;
  else if(partCode == kControlImageWellPart)
    stringIndex = 10;
  else if(partCode == kControlRadioGroupPart)
    stringIndex = 11;
  else if(partCode == kControlButtonPart)
    stringIndex = 12;
  else if(partCode == kControlIndicatorPart)
    stringIndex = 13;
  
  if(menuItem > 0 && menuItem < 1234)
  {
    doCopyPString("\pTrackControl returned ",gCurrentString);
    GetIndString(theString,rPartCodeStrings,stringIndex);
    doConcatPStrings(gCurrentString,theString);
    doConcatPStrings(gCurrentString,"\p    GetControlData returned menu item ");
    NumToString((SInt32) menuItem,theString);
    doConcatPStrings(gCurrentString,theString);
  }
  else if(menuItem == 1234 || menuItem == 4321)
  {
    if(menuItem == 1234)
      doCopyPString("\pMouse-down in ",gCurrentString);
    else if(menuItem == 4321)
      doCopyPString("\pTrackControl returned ",gCurrentString);
    GetIndString(theString,rPartCodeStrings,stringIndex);
    doConcatPStrings(gCurrentString,theString);
  }

  Draw1Control(windowHeaderHdl);
  doDrawMessage(windowPtr,!gInBackground);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doGraphicAlignment

void  doGraphicAlignment(WindowPtr windowPtr,ControlHandle controlHdl,
                         ControlHandle windowHeaderHdl)
{
  SInt16                        a;
  UInt32                        finalTicks;
  ControlButtonGraphicAlignment  alignmentConstant = 0;

  SetCursor(*(GetCursor(watchCursor)));
      
  for(a=1;a<10;a++)
  {
    Delay(60,&finalTicks);
    alignmentConstant++;
    if(alignmentConstant == 9)
      alignmentConstant = 0;
    SetControlData(controlHdl,kControlNoPart,kControlBevelButtonGraphicAlignTag,
                   sizeof(alignmentConstant),(Ptr) &alignmentConstant);
    Draw1Control(controlHdl);
    Draw1Control(windowHeaderHdl);
    GetIndString(gCurrentString,rGraphicAlignStrings,a);
    doDrawMessage(windowPtr,!gInBackground);
  }

  SetCursor(&qd.arrow);
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doTextAlignment

void  doTextAlignment(WindowPtr windowPtr,ControlHandle controlHdl,
                      ControlHandle windowHeaderHdl)
{
  SInt16                      a;
  UInt32                      finalTicks;
  ControlButtonTextAlignment  alignmentConstant = -3;
      
  SetCursor(*(GetCursor(watchCursor)));
      
  for(a=1;a<4;a++)
  {
    Delay(60,&finalTicks);
    alignmentConstant++;
    if(alignmentConstant == 0)
      alignmentConstant++;
    SetControlData(controlHdl,kControlNoPart,kControlBevelButtonTextAlignTag,
                   sizeof(alignmentConstant),(Ptr) &alignmentConstant);
    Draw1Control(controlHdl);
    Draw1Control(windowHeaderHdl);
    GetIndString(gCurrentString,rTextAlignStrings,a);
    doDrawMessage(windowPtr,!gInBackground);
  }

  SetCursor(&qd.arrow);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doTextOffset

void  doTextOffset(WindowPtr windowPtr,ControlHandle controlHdl,
                   ControlHandle windowHeaderHdl)
{
  ControlButtonTextAlignment  alignmentConstant;
  SInt16                      offset;
  UInt32                      finalTicks;
      
  SetCursor(*(GetCursor(watchCursor)));
      
  Draw1Control(windowHeaderHdl);
  doCopyPString("\pOffset from left",gCurrentString);
  doDrawMessage(windowPtr,!gInBackground);

  alignmentConstant = kControlBevelButtonAlignTextFlushLeft;
  SetControlData(controlHdl,kControlNoPart,kControlBevelButtonTextAlignTag,
                  sizeof(alignmentConstant),(Ptr) &alignmentConstant);
  Draw1Control(controlHdl);

  for(offset=1;offset<28;offset++)
  {
    Delay(15,&finalTicks);
    SetControlData(controlHdl,kControlNoPart,kControlBevelButtonTextOffsetTag,
                   sizeof(offset),(Ptr) &offset);
    Draw1Control(controlHdl);
  }
  
  Delay(60,&finalTicks);

  Draw1Control(windowHeaderHdl);
  doCopyPString("\pOffset from right",gCurrentString);
  doDrawMessage(windowPtr,!gInBackground);

  alignmentConstant = kControlBevelButtonAlignTextFlushRight;
  SetControlData(controlHdl,kControlNoPart,kControlBevelButtonTextAlignTag,
                  sizeof(alignmentConstant),(Ptr) &alignmentConstant);

  for(offset=0;offset<14;offset++)
  {
    Delay(15,&finalTicks);
    SetControlData(controlHdl,kControlNoPart,kControlBevelButtonTextOffsetTag,
                   sizeof(offset),(Ptr) &offset);
    Draw1Control(controlHdl);
  }

  SetCursor(&qd.arrow);
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doTextPlacement

void  doTextPlacement(WindowPtr windowPtr,ControlHandle controlHdl,
                   ControlHandle windowHeaderHdl)
{
  ControlButtonTextPlacement  placementConstant;
  UInt32                      finalTicks;
      
  SetCursor(*(GetCursor(watchCursor)));
      
  for(placementConstant = 1;placementConstant < 5;placementConstant++)
  {
    Delay(60,&finalTicks);
    SetControlData(controlHdl,kControlNoPart,kControlBevelButtonTextPlaceTag,
                   sizeof(placementConstant),(Ptr) &placementConstant);
    Draw1Control(controlHdl);
    Draw1Control(windowHeaderHdl);
    GetIndString(gCurrentString,rTextPlacementStrings,placementConstant);
    doDrawMessage(windowPtr,!gInBackground);
  }

  SetCursor(&qd.arrow);
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doDrawMessage

void  doDrawMessage(WindowPtr windowPtr,Boolean inState)
{
  SInt16  windowWidth, stringWidth;

  if(inState == kThemeStateActive)
    SetThemeTextColor(kThemeTextColorWindowHeaderActive,gPixelDepth,gIsColourDevice);
  else
    SetThemeTextColor(kThemeTextColorWindowHeaderInactive,gPixelDepth,gIsColourDevice);

  windowWidth = (windowPtr)->portRect.right - (windowPtr)->portRect.left;
  stringWidth = StringWidth(gCurrentString);
  MoveTo((windowWidth / 2) - (stringWidth / 2), 17);
  DrawString(gCurrentString);
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doDrawLegends

void  doDrawLegends(Boolean inState)
{
  if(inState == kThemeStateActive)
    SetThemeTextColor(kThemeTextColorWindowHeaderActive,gPixelDepth,gIsColourDevice);
  else
    SetThemeTextColor(kThemeTextColorWindowHeaderInactive,gPixelDepth,gIsColourDevice);

  MoveTo(30,63);
  DrawString("\pBevel sizes and bevel button content");
  MoveTo(313,63);
  DrawString("\pMenu position and behaviour");
  MoveTo(30,154);
  DrawString("\pBevel button behaviour");
  MoveTo(313,154);
  DrawString("\pGraphic/text alignment and offset");
  MoveTo(490,154);
  DrawString("\pText Placement");
  MoveTo(30,245);
  DrawString("\pImage wells");
  MoveTo(168,245);
  DrawString("\pPicture controls");
  MoveTo(313,245);
  DrawString("\pIcon controls (cicn)");
  MoveTo(451,245);
  DrawString("\pIcon controls (icon suite)");
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
// TabEditClock.c
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

// ............................................................................. includes

#include "Controls3.h"

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doTabEditClock

void  doTabEditClock(void)
{
  DialogPtr                      dialogPtr;
  ControlHandle                  controlHdl;
  Str255                        initialName = "\pYour name here";
  ControlEditTextSelectionRec    selectionRec;
  ControlKeyFilterUPP            numericFilterUPP;
  ModalFilterUPP                eventFilterUPP;
  ControlEditTextValidationUPP  editTextValidatorUPP;
  SInt16                        tabHit, itemHit;

  if(FrontWindow())
    doActivateWindow(FrontWindow(),false);
    
  if(!(dialogPtr = GetNewDialog(rTabEditClockDialog,NULL,(WindowPtr) -1)))
    ExitToShell();

  SetWTitle(dialogPtr,"\pTabs, Edit Text Fields, and Clocks");

  // ............................................. set default button and cursor tracking

  SetDialogDefaultItem(dialogPtr,kStdOkItemIndex);
  SetDialogTracksCursor(dialogPtr,true);

  // ................................................ hide user pane with embedded clocks

  GetDialogItemAsControl(dialogPtr,iClocksUserPane,&controlHdl);
  HideControl(controlHdl);

  // .......... assign some text to the first edit text control and select the whole text

  GetDialogItemAsControl(dialogPtr,iEditText1,&controlHdl);
  SetControlData(controlHdl,kControlNoPart,kControlEditTextTextTag,initialName[0],
                 (Ptr) &initialName[1]);
  selectionRec.selStart = 0;
  selectionRec.selEnd = 32767;
  SetControlData(controlHdl,kControlNoPart,kControlEditTextSelectionTag,
                 sizeof(selectionRec),(Ptr) &selectionRec);

  // ... create routine descriptors for event filter, key filter, and edit text validator

  eventFilterUPP        = NewModalFilterProc(eventFilter);
  numericFilterUPP      = NewControlKeyFilterProc(numericFilter);
  editTextValidatorUPP  = NewControlEditTextValidationProc(editTextValidator); 

  // ............. attach an edit text validation function to the first edit text control
  
  GetDialogItemAsControl(dialogPtr,iEditText1,&controlHdl);
  SetControlData(controlHdl,kControlNoPart,kControlEditTextValidationProcTag,
                 sizeof(editTextValidatorUPP),(Ptr) &editTextValidatorUPP);

// ......................... attach a key filter function to the second edit text control

  GetDialogItemAsControl(dialogPtr,iEditText2,&controlHdl);
  SetControlData(controlHdl,kControlNoPart,kControlEditTextKeyFilterTag,
                 sizeof(numericFilterUPP),(Ptr) &numericFilterUPP);

  // ............................................ show dialog and enter modal dialog loop

  ShowWindow(dialogPtr);

  do
  {
    ModalDialog(eventFilterUPP,&itemHit);

    if(itemHit == iTabs)
    {
      GetDialogItemAsControl(dialogPtr,iTabs,&controlHdl);
      tabHit = GetControlValue(controlHdl);
      
      if(tabHit == tabEditText)
      {
        SetWTitle(dialogPtr,"\pTabs, Edit Text Fields, and Clocks");

        GetDialogItemAsControl(dialogPtr,iClocksUserPane,&controlHdl);
        HideControl(controlHdl);

        GetDialogItemAsControl(dialogPtr,iEditTextUserPane,&controlHdl);
        ActivateControl(controlHdl);
        ShowControl(controlHdl);

        GetDialogItemAsControl(dialogPtr,iEditText1,&controlHdl);
        SetKeyboardFocus(dialogPtr,controlHdl,kControlFocusNextPart);
      }
      else if(tabHit == tabClocks)
      {
        SetWTitle(dialogPtr,"\pTabs, Clocks, and Edit Text Fields");

        GetDialogItemAsControl(dialogPtr,iEditTextUserPane,&controlHdl);
        DeactivateControl(controlHdl);
        HideControl(controlHdl);

        GetDialogItemAsControl(dialogPtr,iClocksUserPane,&controlHdl);
        ShowControl(controlHdl);

        GetDialogItemAsControl(dialogPtr,iClocks1,&controlHdl);
        SetKeyboardFocus(dialogPtr,controlHdl,kControlFocusNextPart);
      }
    }
    else if(itemHit == iExtractEditText)
    {
      GetDialogItemAsControl(dialogPtr,iImageWellEditText,&controlHdl);
      Draw1Control(controlHdl);
      doExtractEditText(dialogPtr);
    }
    else if(itemHit == iExtractClocks)
    {
      GetDialogItemAsControl(dialogPtr,iImageWellClocks,&controlHdl);
      Draw1Control(controlHdl);
      doExtractDateTime(dialogPtr);
    }
  } while(itemHit != kStdOkItemIndex);

  DisposeDialog(dialogPtr);
  DisposeRoutineDescriptor(eventFilterUPP);
  DisposeRoutineDescriptor(numericFilterUPP);
  DisposeRoutineDescriptor(editTextValidatorUPP);
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doExtractEditText

void  doExtractEditText(DialogPtr dialogPtr)
{
  GrafPtr        oldPort;
  RGBColor      saveBackColour, whiteColour = { 0xFFFF, 0xFFFF, 0xFFFF };
  SInt16        iType;
  Handle        theHandle;
  Rect          theRect;
  Str255        theString;
  ControlHandle  controlHdl;
  Size          actualSize;

  GetPort(&oldPort);
  SetPort(dialogPtr);
  GetBackColor(&saveBackColour);
  RGBBackColor(&whiteColour);
  
  GetDialogItem(dialogPtr,iEditText1,&iType,&theHandle,&theRect);
  GetDialogItemText(theHandle,theString);
  MoveTo(100,182);
  DrawString(theString);

  GetDialogItem(dialogPtr,iEditText2,&iType,&theHandle,&theRect);
  GetDialogItemText(theHandle,theString);
  MoveTo(100,196);
  DrawString(theString);

  GetDialogItemAsControl(dialogPtr,iEditText3,&controlHdl);
  GetControlDataSize(controlHdl,kControlEditTextPart,kControlEditTextTextTag,&actualSize);
  GetControlData(controlHdl,kControlNoPart,kControlEditTextPasswordTag,actualSize,
                 (Ptr) &theString[1],NULL);
  theString[0] = actualSize;
  MoveTo(100,208);
  DrawString(theString);

  RGBBackColor(&saveBackColour);
  SetPort(oldPort);
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doExtractDateTime

void  doExtractDateTime(DialogPtr dialogPtr)
{
  GrafPtr        oldPort;
  RGBColor      saveBackColour, whiteColour = { 0xFFFF, 0xFFFF, 0xFFFF };
  ControlHandle  controlHdl;
  LongDateRec    longDateTimeStruc;
  SInt16        second, minute, hour, day, month, year;
  Str255        theString, tempString;
    
  GetPort(&oldPort);
  SetPort(dialogPtr);
  GetBackColor(&saveBackColour);
  RGBBackColor(&whiteColour);

  GetDialogItemAsControl(dialogPtr,iClocks1,&controlHdl);
  GetControlData(controlHdl,kControlNoPart,kControlClockLongDateTag,
                 sizeof(longDateTimeStruc),(Ptr) &longDateTimeStruc,NULL);
  hour = longDateTimeStruc.ld.hour;
  minute = longDateTimeStruc.ld.minute;
  second = longDateTimeStruc.ld.second;
  doCopyPString("\pHour ",theString);  
  NumToString((SInt32) hour,tempString);
  doConcatPStrings(theString,tempString);
  doConcatPStrings(theString,"\p, Minute ");
  NumToString((SInt32) minute,tempString);
  doConcatPStrings(theString,tempString);
  doConcatPStrings(theString,"\p, Second ");
  NumToString((SInt32) second,tempString);
  doConcatPStrings(theString,tempString);
  MoveTo(100,182);
  DrawString(theString);
  
  GetDialogItemAsControl(dialogPtr,iClocks2,&controlHdl);
  GetControlData(controlHdl,kControlNoPart,kControlClockLongDateTag,
                 sizeof(longDateTimeStruc),(Ptr) &longDateTimeStruc,NULL);
  day = longDateTimeStruc.ld.day;
  month = longDateTimeStruc.ld.month;
  year = longDateTimeStruc.ld.year;
  doCopyPString("\pDay ",theString);  
  NumToString((SInt32) day,tempString);
  doConcatPStrings(theString,tempString);
  doConcatPStrings(theString,"\p, Month ");
  NumToString((SInt32) month,tempString);
  doConcatPStrings(theString,tempString);
  doConcatPStrings(theString,"\p, Year ");
  NumToString((SInt32) year,tempString);
  doConcatPStrings(theString,tempString);
  MoveTo(100,196);
  DrawString(theString);

  GetDialogItemAsControl(dialogPtr,iClocks3,&controlHdl);
  GetControlData(controlHdl,kControlNoPart,kControlClockLongDateTag,
                 sizeof(longDateTimeStruc),(Ptr) &longDateTimeStruc,NULL);
  month = longDateTimeStruc.ld.month;
  year = longDateTimeStruc.ld.year;
  doCopyPString("\pMonth ",theString);  
  NumToString((SInt32) month,tempString);
  doConcatPStrings(theString,tempString);
  doConcatPStrings(theString,"\p, Year ");
  NumToString((SInt32) year,tempString);
  doConcatPStrings(theString,tempString);
  MoveTo(100,210);
  DrawString(theString);

  RGBBackColor(&saveBackColour);
  SetPort(oldPort);
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× numericFilter

pascal ControlKeyFilterResult  numericFilter(ControlHandle controlHdl,SInt16* keyCode,
                                            SInt16 *charCode,SInt16 *modifiers)
{
  if(((char) *charCode >= '0') && ((char) *charCode <= '9'))
    return kControlKeyFilterPassKey;
  
  switch(*charCode)
  {
    case '-':
    case kLeftArrow:
    case kRightArrow:
    case kUpArrow:
    case kDownArrow:
    case kBackspace:
      return kControlKeyFilterPassKey;
      break;

    default:
      SysBeep(10);
      return kControlKeyFilterBlockKey;
      break;
  }
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× editTextValidator

pascal void  editTextValidator(ControlHandle controlHdl)
{
  Str255  oldText, newText;
  Size    actualSize;
  UInt8    a, count = 0;

  GetControlData(controlHdl,kControlNoPart,kControlEditTextTextTag,sizeof(oldText) -1,
                  (Ptr) &oldText[1],&actualSize);

  if(actualSize <= 255)
    oldText[0] = actualSize;
  else
    oldText[0] = 255;
    
  for(a=1;a<=oldText[0];a++)
  {
    if(((oldText[a] >= 'A') && (oldText[a] <= 'Z') ||
        (oldText[a] >= 'a') && (oldText[a] <= 'z')) ||
        (oldText[a] == ' ') || (oldText[a] == '.'))
    {
      newText[count + 1] = oldText[a];
      count++;  
    }
  }

  newText[0] = count;

  SetControlData(controlHdl,kControlNoPart,kControlEditTextTextTag,newText[0],
                 (Ptr) &newText[1]);
  
  Draw1Control(controlHdl);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
// GroupArrowsProgress.c
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

// ............................................................................. includes

#include "Controls3.h"

// ..................................................................... global variables

ControlHandle      gCacheSizeControlHdl;
ControlHandle      gLittleArrowsControlHdl;
ControlActionUPP  arrowsActionFunctionUPP;
extern Boolean    gGroupArrowsProgressActive;

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doTabEditClock

void  doGroupArrowsProgress(void)
{
  DialogPtr          dialogPtr;
  ControlHandle      controlHdl;
  ModalFilterUPP    eventFilterUPP;
  SInt16            controlValue, itemHit;
  Str255            theString;

  if(FrontWindow())
    doActivateWindow(FrontWindow(),false);

  if(!(dialogPtr = GetNewDialog(rGroupArrowsProgDialog,NULL,(WindowPtr) -1)))
    ExitToShell();

  // ................................................................. set default button

  SetDialogDefaultItem(dialogPtr,kStdOkItemIndex);

  // ...... create routine descriptors for event filter and little arrows action function

  eventFilterUPP = NewModalFilterProc((ProcPtr) eventFilter);
  arrowsActionFunctionUPP = NewControlActionProc((ProcPtr) arrowsActionFunction);

  // ........................................... set initial value for checkbox group box

  GetDialogItemAsControl(dialogPtr,iCheckboxGroup,&controlHdl);
  SetControlValue(controlHdl,1);

  // .................................. get and set initial cache value for little arrows

  GetDialogItemAsControl(dialogPtr,iLittleArrows,&gLittleArrowsControlHdl);
  NumToString((SInt32) GetControlValue(gLittleArrowsControlHdl),theString);
  doConcatPStrings(theString,"\pK");
  GetDialogItemAsControl(dialogPtr,iStaticTextCache,&gCacheSizeControlHdl);
  SetControlData(gCacheSizeControlHdl,kControlNoPart,kControlStaticTextTextTag,theString[0],
                 (Ptr) &theString[1]);

  // .......................................... hide second user pane in pop-up group box

  GetDialogItemAsControl(dialogPtr,iUserPaneScoreAverage,&controlHdl);
  HideControl(controlHdl);

  // ............................................. show dialog and enter ModalDialog loop

  ShowWindow(dialogPtr);

  do
  {
    ModalDialog(eventFilterUPP,&itemHit);

    if(itemHit == iCheckboxGroup)
    {
      doCheckBoxGroupBox(dialogPtr);
    }    
    else if(itemHit == iPopupGroup)
    {
      doPopupGroupBox(dialogPtr);
    }
    else if(itemHit == iCheckboxShowInitials)
    {
      GetDialogItemAsControl(dialogPtr,iCheckboxShowInitials,&controlHdl);
      controlValue = (!(GetControlValue(controlHdl)));
      SetControlValue(controlHdl,controlValue);
    }
    else if(itemHit == iCheckboxShowAverages)
    {
      GetDialogItemAsControl(dialogPtr,iCheckboxShowAverages,&controlHdl);
      controlValue = (!(GetControlValue(controlHdl)));
      SetControlValue(controlHdl,controlValue);
    }
    else if(itemHit == iDisclosureTriangle)
    {
      doAsynchronousAndProgress(dialogPtr);
    }
    else if(itemHit == iPushButtonExtract)
    {
      GetDialogItemAsControl(dialogPtr,iImageWell,&controlHdl);
      Draw1Control(controlHdl);
      doExtractCurrentStatus(dialogPtr);
    }
  } while(itemHit != kStdOkItemIndex);

  // ........................................................................... clean up

  DisposeDialog(dialogPtr);
  DisposeRoutineDescriptor(eventFilterUPP);
  DisposeRoutineDescriptor(arrowsActionFunctionUPP);

  gGroupArrowsProgressActive = false;
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doCheckBoxGroupBox

void  doCheckBoxGroupBox(DialogPtr dialogPtr)
{
  ControlHandle  controlHdl;
  SInt16        controlValue;

  GetDialogItemAsControl(dialogPtr,iCheckboxGroup,&controlHdl);
  controlValue = (!(GetControlValue(controlHdl)));
  SetControlValue(controlHdl,controlValue);
  
  if(controlValue == 0)
  {
    GetDialogItemAsControl(dialogPtr,iRadioGroupColour,&controlHdl);
    DeactivateControl(controlHdl);  
    GetDialogItemAsControl(dialogPtr,iStaticTextColourDepth,&controlHdl);
    DeactivateControl(controlHdl);  
  }
  else if(controlValue == 1)
  {
    GetDialogItemAsControl(dialogPtr,iRadioGroupColour,&controlHdl);
    ActivateControl(controlHdl);  
    GetDialogItemAsControl(dialogPtr,iStaticTextColourDepth,&controlHdl);
    ActivateControl(controlHdl);  
  }
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doPopupGroupBox

void  doPopupGroupBox(DialogPtr dialogPtr)
{
  ControlHandle  controlHdl;
  SInt16        controlValue;

  GetDialogItemAsControl(dialogPtr,iPopupGroup,&controlHdl);
  controlValue = GetControlValue(controlHdl);
  
  if(controlValue == 1)
  {
    GetDialogItemAsControl(dialogPtr,iUserPaneScoreAverage,&controlHdl);
    HideControl(controlHdl);
    GetDialogItemAsControl(dialogPtr,iUserPaneNamesInitials,&controlHdl);
    ShowControl(controlHdl);
  }
  else if(controlValue == 2)
  {
    GetDialogItemAsControl(dialogPtr,iUserPaneNamesInitials,&controlHdl);
    HideControl(controlHdl);
    GetDialogItemAsControl(dialogPtr,iUserPaneScoreAverage,&controlHdl);
    ShowControl(controlHdl);
  }
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doAsynchronousAndProgress

void  doAsynchronousAndProgress(DialogPtr dialogPtr)
{
  ControlHandle  controlHdl;
  SInt16        controlValue;
  Handle        ditlHdl;
  Boolean        indeterminateFlag = 1;
  Str255        expandString   = "\pHide Progress Indicator and Asynchronous Arrows";
  Str255        collapseString = "\pShow Progress Indicator and Asynchronous Arrows";

  GetDialogItemAsControl(dialogPtr,iDisclosureTriangle,&controlHdl);
  controlValue = (!(GetControlValue(controlHdl)));
  SetControlValue(controlHdl,controlValue);

  if(controlValue == 1)
  {
    ditlHdl = GetResource('DITL',130);
    AppendDITL(dialogPtr,ditlHdl,appendDITLBottom);
    ReleaseResource(ditlHdl);

    GetDialogItemAsControl(dialogPtr,iProgressBar,&controlHdl);
    SetControlData(controlHdl,kControlNoPart,kControlProgressBarIndeterminateTag,
                   sizeof(indeterminateFlag),(Ptr) &indeterminateFlag);

    GetDialogItemAsControl(dialogPtr,kStdOkItemIndex,&controlHdl);
    MoveControl(controlHdl,267,336);
    
    GetDialogItemAsControl(dialogPtr,iStaticTextDisclosure,&controlHdl);
    SetControlData(controlHdl,kControlNoPart,kControlStaticTextTextTag,
                   expandString[0],(Ptr) &expandString[1]);
    Draw1Control(controlHdl);
        
  }
  else if(controlValue == 0)
  {
    GetDialogItemAsControl(dialogPtr,kStdOkItemIndex,&controlHdl);
    MoveControl(controlHdl,267,259);

    SizeWindow(dialogPtr,348,302,false);
    GetDialogItemAsControl(dialogPtr,iStaticTextDisclosure,&controlHdl);
    SetControlData(controlHdl,kControlNoPart,kControlStaticTextTextTag,
                   collapseString[0],(Ptr) &collapseString[1]);
    Draw1Control(controlHdl);
  }
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doExtractCurrentStatus

void  doExtractCurrentStatus(DialogPtr dialogPtr)
{
  GrafPtr        oldPort;
  RGBColor      saveBackColour, whiteColour = { 0xFFFF, 0xFFFF, 0xFFFF };
  ControlHandle  controlHdl;
  SInt16        controlValue;
  Str255        theString;

  GetPort(&oldPort);
  SetPort(dialogPtr);
  GetBackColor(&saveBackColour);
  RGBBackColor(&whiteColour);

  GetDialogItemAsControl(dialogPtr,iCheckboxGroup,&controlHdl);
  controlValue = GetControlValue(controlHdl);  
  MoveTo(98,191);
  if(controlValue)
  {
    doCopyPString("\pUse colour,",theString);
    GetDialogItemAsControl(dialogPtr,iRadioGroupColour,&controlHdl);
    controlValue = GetControlValue(controlHdl);
    if(controlValue == 1)
      doConcatPStrings(theString,"\p 8 bit.");
    else if(controlValue == 2)
      doConcatPStrings(theString,"\p 16 bit.");
    else if(controlValue == 3)
      doConcatPStrings(theString,"\p 32 bit.");
  }
  else
    doCopyPString("\pDont use colour.",theString);

  DrawString(theString);    

  GetDialogItemAsControl(dialogPtr,iPopupGroup,&controlHdl);
  controlValue = GetControlValue(controlHdl);  
  MoveTo(98,205);
  if(controlValue == 1)
  {
    doCopyPString("\pPlayer, ",theString);
    GetDialogItemAsControl(dialogPtr,iRadioGroupNames,&controlHdl);
    controlValue = GetControlValue(controlHdl);
    if(controlValue == 1)
      doConcatPStrings(theString,"\pname first,");
    else if(controlValue == 2)
      doConcatPStrings(theString,"\pname last,");
    GetDialogItemAsControl(dialogPtr,iCheckboxShowInitials,&controlHdl);
    controlValue = GetControlValue(controlHdl);
    if(controlValue == 1)
      doConcatPStrings(theString,"\p show number.");
    else if(controlValue == 0)
      doConcatPStrings(theString,"\p no number.");
  }
  else if(controlValue == 2)
  {
    doCopyPString("\pScore, ",theString);
    GetDialogItemAsControl(dialogPtr,iRadioGroupScores,&controlHdl);
    controlValue = GetControlValue(controlHdl);
    if(controlValue == 1)
      doConcatPStrings(theString,"\pbatting, ");
    else if(controlValue == 2)
      doConcatPStrings(theString,"\pbowling, ");
    GetDialogItemAsControl(dialogPtr,iCheckboxShowAverages,&controlHdl);
    controlValue = GetControlValue(controlHdl);
    if(controlValue == 1)
      doConcatPStrings(theString,"\pshow average.");
    else if(controlValue == 0)
      doConcatPStrings(theString,"\pno average.");
  }

  DrawString(theString);

  MoveTo(98,219);
  DrawString("\pCache size: ");
  GetDialogItemAsControl(dialogPtr,iLittleArrows,&controlHdl);
  NumToString((SInt32) GetControlValue(controlHdl),theString);
  DrawString(theString);
    
  RGBBackColor(&saveBackColour);
  SetPort(oldPort);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
// Sliders.c 
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

// ............................................................................. includes

#include "Controls3.h"

// ..................................................................... global variables

ControlActionUPP             sliderActionFunction1UPP;
ControlActionUPP             sliderActionFunction2UPP;
ControlUserPaneDrawUPP       userPaneDrawFunctionUPP;
ControlUserPaneActivateUPP   userPaneActivateFunctionUPP;
ControlHandle                gSlider1Hdl;
ControlHandle                gSlider2Hdl;
ControlHandle                gSlider3Hdl;
ControlHandle                gSlider4Hdl;
ControlHandle                gSlider5Hdl;
ControlHandle                gSlider6Hdl;
RGBColor                     gRedColour  = { 0x0000, 0x0000, 0x0000 };
RGBColor                     gBlueColour  = { 0x0000, 0x0000, 0x0000 };
Boolean                      gDrawActivated = true;
extern Boolean               gSlidersActive;

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doSliderUserPane

void  doSliderUserPane(void)
{
  DialogPtr       dialogPtr;
  ModalFilterUPP  eventFilterUPP;
  ControlHandle   controlHdl;
  SInt16          itemHit;

  if(FrontWindow())
    doActivateWindow(FrontWindow(),false);

  if(!(dialogPtr = GetNewDialog(rSlidersDialog,NULL,(WindowPtr) -1)))
    ExitToShell();

  // ................................................................. set default button

  SetDialogDefaultItem(dialogPtr,kStdOkItemIndex);

  // ................................ create routine descriptor for event filter function

  eventFilterUPP = NewModalFilterProc(eventFilter);

  // ............................. create routine descriptors for slider action functions

  sliderActionFunction1UPP = NewControlActionProc((ProcPtr) sliderActionFunction1);
  sliderActionFunction2UPP = NewControlActionProc((ProcPtr) sliderActionFunction2);

  // ........ create routine descriptors for user pane functions, set user pane functions

  userPaneDrawFunctionUPP = NewControlUserPaneDrawProc(userPaneDrawFunction);
  GetDialogItemAsControl(dialogPtr,iUserPane1,&controlHdl);
  SetControlData(controlHdl,kControlNoPart,kControlUserPaneDrawProcTag, 
                 sizeof(userPaneDrawFunctionUPP),(Ptr) &userPaneDrawFunctionUPP);

  userPaneActivateFunctionUPP = NewControlUserPaneActivateProc(userPaneActivateFunction);
  GetDialogItemAsControl(dialogPtr,iUserPane1,&controlHdl);
  SetControlData(controlHdl,kControlNoPart,kControlUserPaneActivateProcTag, 
                 sizeof(userPaneActivateFunctionUPP),(Ptr) &userPaneActivateFunctionUPP);

  // ...... get control handles of, and draw initial control values for, top four sliders
  
  GetDialogItemAsControl(dialogPtr,iSlider1,&gSlider1Hdl);
  doDrawSliderValues(dialogPtr,gSlider1Hdl);
  GetDialogItemAsControl(dialogPtr,iSlider2,&gSlider2Hdl);
  doDrawSliderValues(dialogPtr,gSlider2Hdl);
  GetDialogItemAsControl(dialogPtr,iSlider3,&gSlider3Hdl);
  doDrawSliderValues(dialogPtr,gSlider3Hdl);
  GetDialogItemAsControl(dialogPtr,iSlider4,&gSlider4Hdl);
  doDrawSliderValues(dialogPtr,gSlider4Hdl);

  // .................. get control handles and values for bottom two sliders, set colour

  GetDialogItemAsControl(dialogPtr,iSlider5,&gSlider5Hdl);
  gRedColour.red = 2 * GetControlValue(gSlider5Hdl);
  GetDialogItemAsControl(dialogPtr,iSlider6,&gSlider6Hdl);
  gBlueColour.blue = 2 * GetControlValue(gSlider5Hdl);

  // ............................................. show dialog and enter ModalDialog loop

  ShowWindow(dialogPtr);

  do
  {
    ModalDialog(eventFilterUPP,&itemHit);
  } while(itemHit != kStdOkItemIndex);

  // ........................................................................... clean up

  DisposeDialog(dialogPtr);
  DisposeRoutineDescriptor(eventFilterUPP);
  DisposeRoutineDescriptor(sliderActionFunction1UPP);
  DisposeRoutineDescriptor(sliderActionFunction2UPP);
  DisposeRoutineDescriptor(userPaneDrawFunctionUPP);
  DisposeRoutineDescriptor(userPaneActivateFunctionUPP);
  gSlidersActive = false;
}

// ................................................................... doDrawSliderValues

void  doDrawSliderValues(DialogPtr dialogPtr,ControlHandle controlHdl)
{
  Str255  theString;
  SInt16  staticTextItem;

  NumToString((SInt32) GetControlValue(controlHdl),theString);

  if(controlHdl == gSlider1Hdl)
    staticTextItem = iSlider1StaticText;
  else if(controlHdl == gSlider2Hdl)
    staticTextItem = iSlider2StaticText;
  else if(controlHdl == gSlider3Hdl)
    staticTextItem = iSlider3StaticText;
  else if(controlHdl == gSlider4Hdl)
    staticTextItem = iSlider4StaticText;

  GetDialogItemAsControl(dialogPtr,staticTextItem,&controlHdl);
  SetControlData(controlHdl,kControlNoPart,kControlStaticTextTextTag,theString[0],
                 (Ptr) &theString[1]);
  Draw1Control(controlHdl);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× userPaneDrawFunction

pascal void  userPaneDrawFunction(ControlHandle theControl,SInt16 thePart)
{
  Rect  theRect;

  SetRect(&theRect,225,186,239,200);
  DrawThemeGenericWell(&theRect,gDrawActivated,true);

  if(gDrawActivated)
  {
    RGBForeColor(&gRedColour);
    PaintRect(&theRect);
  }

  SetRect(&theRect,225,207,239,221);
  DrawThemeGenericWell(&theRect,gDrawActivated,true);

  if(gDrawActivated)
  {
    RGBForeColor(&gBlueColour);
    PaintRect(&theRect);
  }
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× userPaneActivateFunction

pascal void  userPaneActivateFunction(ControlHandle control,Boolean activating)
{
  if(activating)
    gDrawActivated = true;
  else
    gDrawActivated = false;
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
// TextBox.c.c
//×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

// ............................................................................. includes

#include "Controls3.h"

// ........................................................................... doAboutBox

void  doAboutBox(void)
{
  DialogPtr        dialogPtr;
  ModalFilterUPP  eventFilterUPP;
  SInt16          itemHit;
    
  if(FrontWindow())
    doActivateWindow(FrontWindow(),false);
    
  if(!(dialogPtr = GetNewDialog(rAboutDialog,NULL,(WindowPtr) -1)))
    ExitToShell();

  SetWTitle(dialogPtr,"\pAbout Box (Text Boxes)");

  // ................................................................. set default button

  SetDialogDefaultItem(dialogPtr,kStdOkItemIndex);
  
  // ......................................... create routine descriptor for event filter

  eventFilterUPP = NewModalFilterProc(eventFilter);

  // ............................................ show dialog and enter modal dialog loop

  ShowWindow(dialogPtr);

  do
  {
    ModalDialog(eventFilterUPP,&itemHit);
  } while(itemHit != kStdOkItemIndex);

  DisposeDialog(dialogPtr);
  DisposeRoutineDescriptor(eventFilterUPP);
}  

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××/
// Callbacks.c
//×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

// ............................................................................. includes

#include "Controls3.h"

// ..................................................................... global variables

extern Boolean          gGroupArrowsProgressActive;
extern Boolean          gSlidersActive;
extern ControlActionUPP  arrowsActionFunctionUPP;
extern ControlActionUPP  sliderActionFunction1UPP;
extern ControlActionUPP  sliderActionFunction2UPP;
extern ControlHandle    gLittleArrowsControlHdl;
extern ControlHandle    gCacheSizeControlHdl;
extern ControlHandle    gSlider1Hdl;
extern ControlHandle    gSlider2Hdl;
extern ControlHandle    gSlider3Hdl;
extern ControlHandle    gSlider4Hdl;
extern ControlHandle    gSlider5Hdl;
extern ControlHandle    gSlider6Hdl;
extern RGBColor          gRedColour;
extern RGBColor          gBlueColour;

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× eventFilter

pascal Boolean  eventFilter(DialogPtr dialogPtr,EventRecord *eventStrucPtr,
                            SInt16 *itemHit)
{
  Boolean        handledEvent;
  GrafPtr        oldPort;
  Point          mouseXY;
  ControlHandle  controlHdl;

  handledEvent = false;

  if((eventStrucPtr->what == updateEvt) && 
     ((WindowPtr) eventStrucPtr->message != dialogPtr))
  {
    doUpdate(eventStrucPtr);
  }
  else
  {
    GetPort(&oldPort);
    SetPort(dialogPtr);

    if(gGroupArrowsProgressActive)
    {
      if(eventStrucPtr->what == mouseDown)
      {
        mouseXY = eventStrucPtr->where;
        GlobalToLocal(&mouseXY);
        if(FindControl(mouseXY,dialogPtr,&controlHdl))
        {
          if(controlHdl == gLittleArrowsControlHdl)
          {
            TrackControl(controlHdl,mouseXY,arrowsActionFunctionUPP);
            handledEvent = true;
          }
        }
      }
    }
    else if(gSlidersActive)
    {
      if(eventStrucPtr->what == mouseDown)
      {
        mouseXY = eventStrucPtr->where;
        GlobalToLocal(&mouseXY);
        if(FindControl(mouseXY,dialogPtr,&controlHdl))
        {
          if(controlHdl == gSlider1Hdl || controlHdl == gSlider2Hdl)
          {
            TrackControl(controlHdl,mouseXY,NULL);
            doDrawSliderValues(dialogPtr,controlHdl);
            handledEvent = true;
          }
          else if(controlHdl == gSlider3Hdl || controlHdl == gSlider4Hdl)
          {
            TrackControl(controlHdl,mouseXY,sliderActionFunction1UPP);
            handledEvent = true;
          }
          else if(controlHdl == gSlider5Hdl || controlHdl == gSlider6Hdl)
          {
            TrackControl(controlHdl,mouseXY,sliderActionFunction2UPP);
            handledEvent = true;
          }
        }
      }
    }
    else
    {
      handledEvent = StdFilterProc(dialogPtr,eventStrucPtr,itemHit);
    }

    SetPort(oldPort);
  }

  return(handledEvent);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× arrowsActionFunction

pascal void  arrowsActionFunction(ControlHandle controlHdl,SInt16 partCode)
{
  Str255  theString;
  SInt32  controlValue;

  if(partCode)
  {
    controlValue = GetControlValue(controlHdl);

    switch(partCode)
    {
      case kControlUpButtonPart:
        controlValue += 32;
        if(controlValue > GetControlMaximum(controlHdl))
        {
          controlValue = GetControlMaximum(controlHdl);
          return;
        }
      break;
      
      case kControlDownButtonPart:
        controlValue -= 32;
        if(controlValue < GetControlMinimum(controlHdl))
        {
          controlValue = GetControlMinimum(controlHdl);
          return;
        }
        break;
    }

    SetControlValue(controlHdl,controlValue);

    NumToString((SInt32) controlValue,theString);
    doConcatPStrings(theString,"\pK");
    SetControlData(gCacheSizeControlHdl,kControlNoPart,kControlStaticTextTextTag,
                   theString[0],(Ptr) &theString[1]);
    Draw1Control(gCacheSizeControlHdl);
  }
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× sliderActionFunction1

pascal void  sliderActionFunction1(ControlHandle controlHdl,SInt16 partCode)
{
  SInt16    staticTextItem;
  Str255    theString;
  DialogPtr  dialogPtr;

  NumToString((SInt32) GetControlValue(controlHdl),theString);

  dialogPtr = (*controlHdl)->contrlOwner;

  if(controlHdl == gSlider3Hdl)
    staticTextItem = iSlider3StaticText;
  else if(controlHdl == gSlider4Hdl)
    staticTextItem = iSlider4StaticText;

  GetDialogItemAsControl(dialogPtr,staticTextItem,&controlHdl);
  SetControlData(controlHdl,kControlNoPart,kControlStaticTextTextTag,theString[0],
                 (Ptr) &theString[1]);
  Draw1Control(controlHdl);
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× sliderActionFunction2

pascal void  sliderActionFunction2(ControlHandle controlHdl,SInt16 partCode)
{
  SInt16  controlValue;
  Rect    theRect;

  controlValue = GetControlValue(controlHdl);

  if(controlHdl == gSlider5Hdl)
  {
    gRedColour.red = 2 * controlValue;
    RGBForeColor(&gRedColour);
    SetRect(&theRect,225,186,239,200);
  }
  else if(controlHdl == gSlider6Hdl)
  {
    gBlueColour.blue = 2 * controlValue;
    RGBForeColor(&gBlueColour);
    SetRect(&theRect,225,207,239,221);
  }
  
  PaintRect(&theRect);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

Demonstration Program Comments

When this program is run, the user should:

*   Choose the About Controls3... item from the Apple menu to view an About dialog 
    containing  a standard Text Box control and an auto-scrolling Text Box control. 
    (Note:  If Mac OS 8.5 is not present, the About Controls3... item will be disabled 
    and this action will not be possible.)

*   Choose items from the Demonstration menu to view and operate the various controls.

*   Choose Show Balloons from the Help menu and note the information (and, in some cases,
    the instructions) in the help balloons as the cursor is moved over the various 
    controls in the window and dialog boxes.

*   Click in the Finder and then back in the window/dialog box, noting control
    activation/deactivation.

*   In the Bevel Buttons, Image Wells, Picture Controls, and Icon Controls window:

    *   Click in the various controls, noting in the window header the control part code
        returned by FindControl (or immediately by TrackControl in the case of the 
        non-tracking icon controls).

    *   Click in the various controls and then release the mouse button both within and
        outside the control, noting the control part code returned by TrackControl.

*   In the Tab, Edit Text, and Clock Controls dialog box:

    *   In the Edit Text Controls tab:

        *   Change the keyboard focus using the tab key and mouse clicks.

        *   Enter a name, age, and password, noting the effect of the key filter 
            function attached to the "Age" edit text control and the behaviour of the 
            "Password" edit text control.

        *   Paste some text containing characters other than alphabetic characters, the 
            space character, and the period character to the "Name" edit text control,
            noting that the edit text validation function strips out the "illegal" 
            characters.
            
        *   Note the cursor shape change when the cursor is over the top two edit text 
            fields.

        *   Click the Extract push button to extract and display the contents of the 
            edit text controls.

     *  In the Clock Controls Tab:

        *   Change the keyboard focus using the tab key and mouse clicks.

        *   Change the clock setting by typing and by using the integral little 
              arrows.

        *   Click the Extract push button to extract and display the clock settings.

*   In the Group Boxes, Arrows, and Progress Bar dialog box:

    *   Change the group box settings, the settings of the controls within the group 
        boxes, and the (simulated) cache size setting controlled by the little arrows, 
        and then click the Extract button to extract and display the settings of the 
        various controls.

    *   Click the disclosure triangle to show and hide the asynchronous arrows and 
         indeterminate progress bar.

*   In the Sliders and User Pane Functions dialog:

    *   Operate the sliders and note the difference in the appearance of the dragged
        indicator in the live scrolling and non-live scrolling variants of the sliders.

    *   Note the appearance, in the activated and deactivated modes, of the two custom
        "controls" to the right of the two horizontal sliders.  Also note that these
        controls are re-drawn, in the appropriate mode, when an overlaying window or
        help balloon is removed.

Control3.h

#define

After the usual constants relating to the menu bar resource, menu resources and IDs,
and menu items are established, constants are established for the resource IDs and dialog
item numbers associated with the various demonstrations.

#typedef

A variable of type BevelDocStruc will be used to hold handles to the various controls
created in the Bevel Buttons, Image Wells, Picture Controls, and Icon Controls window.

Control3.c

Controls3.c is simply the basic "engine" which supports the demonstration.  There is
nothing in this file which has not featured in previous demonstration programs.

Global Variables

gBevelAndImageActive will be set to true while the Bevel Buttons, Image Wells, Picture
Controls, and Icon Controls window is open. gGroupArrowsProgressActive will be set to
true while the Group Boxes, Arrows, and Progress Bar dialog box is open.  gSlidersActive
will be set to true while the Sliders and User Pane Functions dialog is open.

main

The Gestalt call determines whether Mac OS 8.5 or later is present.  If so, the 
About Controls 3... item in the Apple menu is disabled.  (The dialog box opened when 
this item is chosen contains Text Box controls, the CDEFs for which are only included 
with Mac OS 8.5 and later.)

doMouseDown

In the inContent case, if a mouse-down occurs in the Bevel Buttons, Image Wells, Picture
Controls, and Icon Controls window when it is the front window, the function
doBevelImagePictIconContent is called.

In the inGoAway case, the Bevel Buttons, Image Wells, Picture Controls, and Icon Controls
window is disposed of and the global variable gBevelAndImageActive is set to false.

doMenuChoice

In the mDemonstration case, the relevant application-defined function is called when the
user chooses items in the Demonstration menu.  In three cases, the relevant global
variable is also set to true.

doUpdate

If the Bevel Buttons, Image Wells, Picture Controls, and Icon Controls window is open,
UpdateControls is called to redraw the controls in the appropriate mode.  Also, two
application-defined functions are called to draw the current window header string and the
legends in the appropriate mode.

doActivateWindow

If the Bevel Buttons, Image Wells, Picture Controls, and Icon Controls window is open,
and if it receives an activate event, GetRootControl is called to get a handle to the
root control created for the window by the application (see below).  The controls are
then activated or deactivated en masse, and the window header string and the legends are
re-drawn in the appropriate mode.

BevelImagePictIcon.c

BevelImagePictIcon.c contains most of the source code relating to the Bevel Buttons,
Image Wells, Picture Controls, and Icon Controls window.

doBevelImagePictIcon

doBevelImagePictIcon opens a window, creates a relocatable block for a structure of type
BevelDocStruc (to whose fields handles to the various controls will be assigned) and
assigns the handle to this block to the refCon field of the window structure.

First, some initial advisory text for display in the window header is assigned to a
global variable.  The call to GetNewCWindow then creates the window.  (Note that error
handling here and in other areas of the demonstration is somewhat rudimentary in that the
program simply terminates.)  The window's graphics port is set as the current port for
drawing and the window's text size is set to 10pt.

The call to SetThemeWindowBackground sets an Appearance-compliant colour/pattern for the
window's content area.  NewHandle creates the block for the variable of type
BevelDocStruc and SetWRefCon assigns the handle to the block to the window structure's
refCon field.

Before ShowWindow is called to make the window visible, the application-defined function
doGetControls is called to create the controls.  The call to doGetDepthAndDevice assigns
appropriate values to two global variables required in later calls to the Appearance
Manager function SetThemeTextColor.

doGetControls

doGetControls creates the controls from the various 'CNTL' resources.

At the first line, the root control is created.  The first control created must be always
be the root control (which is implemented as a user pane).

A handle to the structure in which the handles to the control structures will be stored
is then retrieved.  The following calls to GetNewControl create a control structure for
each control, insert the structure into the control list for the specified window and
draw the control.  At the same time, the handle to each control is assigned to the
appropriate field of the window's "document" structure.

At the next block, SetControlData is twice called with the
kControlBevelButtonTextPlaceTag control data tag constant.  The bevel button text
placement constant passed in these calls causes the text in the specified bevel buttons
to be placed above the graphic.

At the next block, SetControlData is called with the
kControlBevelButtonCenterPopupGlyphTag control data tag constant to cause the pop-up
glyph in the specified bevel button to be centred.

At the next block, the font for the text in the specified bevel button is changed.  The
flags and font fields of a control font style structure are assigned constants so that
the following call to SetControlFontStyle will set the font to the small emphasised
system font.

The final line sets the value of the specified bevel button to 2, causing it to appear in
the mixed state.

doBevelImagePictIconContent

Recall that, if a mouse-down occurs in the Bevel Buttons, Image Wells, Picture Controls,
and Icon Controls window when it is the front window, doBevelImagePictIconContent is
called to further handle the event.

At the first line a handle to the structure containing handles to all the controls is
obtained.

The call to GlobalToLocal changes the coordinates at which the mouse-down occurred to the
local coordinates required by the following call to FindControl.  The constant
representing the part code returned by FindControl is then drawn in the window header.

If the part code returned by FindControl is not kControlNoPart (0), meaning that an
enabled control was under the mouse cursor at the time of the mouse-down, the if block
executes.  TrackControl takes control while the mouse button remains down, returning a
part code when the button is released.

In the case of the first 10 specified controls (bevel buttons), the control part code
returned by TrackControl is simply drawn in the window header.

The next four controls are bevel button with menus.  In these cases, if the part code
returned indicates that the mouse button was released while the cursor was within the
menu, GetControlData is called with the kControlBevelButtonMenuValueTag tag constant to
get the menu item number.  The part code and menu item number are then drawn in the
window header.  If the cursor was not in the menu when the mouse button was released, the
part code returned by TrackControl is drawn in the window header.

The 10th, 11th, and 12th bevel buttons have toggle behaviour.  With some assistance from
the application, they behave like radio buttons.  If the control in which the mouse-down
occurred was one of these bevel buttons, and if the cursor was still within the control
when the mouse button was released, SetControlValue is called to set the three controls
to the unchecked state, following which the selected control is set to the checked state. 
Either way, the part code returned by TrackControl is drawn in the window header.

The 18th bevel button is used to demonstrate bevel button graphic alignments using a
single bevel button.  A mouse-down within this button causes the application-defined
function doGraphicAlignment to be called.

The 19th bevel button is used to demonstrate bevel button text alignments using a single
bevel button.  A mouse-down within this button causes the application-defined function
doTextAlignment to be called.

The 20th bevel button is used to demonstrate text offsetting using a single bevel button. 
A mouse-down within this button causes the application-defined function doTextOffset to
be called.

The 21st bevel button is used to demonstrate bevel button text placement in relation to
the bevel button's graphic using a single bevel button.  A mouse-down within this button
causes the application-defined function doTextPlacement to be called.

Finally, if the mouse-down was in an image well, picture control, or icon control, and
except for the non-tracking picture and icon control variants, the part code returned by
TrackControl is drawn in the window header.

doDrawPartCode

doDrawPartCode takes part codes and menu item numbers and assembles them into descriptive
strings for drawing in the window header.  The constants used are stored in 'STR#'
resources, and are retrieved using GetIndString.  In the final two lines, Draw1Control is
called to redraw the window header control (in effect erasing the current text drawn
within the window header area) and doDrawMessage is called to draw the assembled string.

doGraphicAlignment

doGraphicAlignment is called to demonstrate the effect of all bevel button graphic
alignment constants except kControlBevelButtonAlignSysDirection.  Each time around the
for loop, the alignment constant is changed before SetControlData is called with the
kControlBevelButtonGraphicAlignTag tag constant to set the alignment, Draw1Control is
called to redraw the bevel button, and the alignment constant used during that pass is
drawn in the window header.

doTextAlignment

doTextAlignment is called to demonstrate the effect of all bevel button text alignment
constants except kControlBevelButtonAlignTextSysDirection.  Each time around the for
loop, the alignment constant is changed before SetControlData is called with the
kControlBevelButtonTextAlignTag tag constant to set the alignment, Draw1Control is called
to redraw the bevel button, and the alignment constant used during that pass is drawn in
the window header.

doTextOffset

doTextOffset is called to demonstrate text offsetting from the left and the right within
a bevel button.  For the purposes of the demonstration, two animations involving
incrementing offsets values are used.  Prior to first animation, SetControlData is called
with the kControlBevelButtonTextOffsetTag tag to align the text on the left. Prior to
second animation, SetControlData is called with the kControlBevelButtonTextOffsetTag tag
to align the text on the right.  Within the for loops, SetControlData is called with the
kControlBevelButtonTextOffsetTag tag to offset the text from the left or right by the
specified number of pixels, and Draw1Control re-draws the control.

doTextPlacement

doTextPlacement is called to demonstrate the effect of all bevel button text placement
constants except kControlBevelButtonPlaceSysDirection.  Within a for loop which
increments the text placement constant, SetControlData is called with the
kControlBevelButtonTextPlaceTag tag and Draw1Control re-draws the control.

doDrawMessage and doDrawLegends

doDrawMessage and doDrawLegends are incidental to the demonstration.  Both functions draw
text in the window in an Appearance-compliant colour which depends on whether the window
is currently in front or in the background.

TabEditClock.c

TabEditClock.c creates a movable modal dialog in which is demonstrated a tab control,
edit text controls and clock controls.  An application-defined numeric key filter function
is attached to the second edit text control.  The third edit text control is for password
input.  The controls displayed by each tab are embedded in user panes.

The kDialogFlagsUsesControlHierarchy flag is set in the 'dlgx' resources for all dialogs
used in the demonstration.  Recall that this means that the Dialog Manager creates a root
control in the dialog and establishes an embedding hierarchy, that all dialog items
automatically become controls, and that the Dialog Manager uses AutoEmbedControl to
position dialog items in an embedding hierarchy based on both visual containment and
their item list number.

The dialog item list used by the dialog created by TabEditClock.c is shown in the
following, in which the indentation represents the embedding hierarchy:

1.   OK push button primitive.
2.   Tab control (kTabControlLargeProc variant).
     Visually contains the two user panes (items 3 and 12) and thus automatically 
     embeds those items.
     3.   User pane control with kControlSupportsEmbedding feature bit set (initial
          value set to 2).
          Visually contains items 4 to 11 and thus automatically embeds those items.
          4.   Static text primitive "Name:".
          5    Edit text primitive.
          6.   Static text primitive "Age:".
          7.   Edit text primitive.
          8.   Static text primitive "Password:".
          9.   Edit text control (kControlEditTextPasswordProc variant).
          10.  Extract push button primitive.
          11.  Image well control.
     12.  User pane control with kControlSupportsEmbedding feature bit set (initial
          value set to 2).
          Visually contains items 13 to 20 and thus automatically embeds those items.
          13.   Static text primitive "Hours, Mins, Secs:".
          14.   Clock control (kControlClockTimeSecondsProc variant).
          15.   Static text primitive "Date, Month, Year:".
          16.   Clock control (kControlClockDateProc variant).
          17.   Static text primitive "Month, Year:".
          18.   Clock control (kControlClockMonthYearProc variant).
          19.   Extract push button primitive.
          20.   Image well control.
21.   Clock control (kControlClockTimeSecondsProc variant, live, display only.)
22.   Group box (kControlGroupBoxSecondaryTextTitleProc variant).
      Visually contains item 23 and thus automatically embeds that item:
      23.   Static text primitive.

doTabEditClock

doTabEditClock creates the dialog, calls ModalDialog to handle events in the dialog, and
disposes of the dialog when the user hits the OK push button.

Firstly, and as is always required when a dialog box is to be displayed, the front window
(if one exists) is explicitly deactivated.

The call to GetNewDialog creates the dialog.  The call to SetWTitle sets the window's
title so as to force an association with the 'hrct' resource containing the help balloons
for the Edit Text Control tab.  (Later calls to SetWTitle in this function are used for
similar purposes.)

SetDialogDefaultItem tells the Dialog Manager which is the default push button item, to
alias the Return and Enter keys to that item, and to draw the default ring around that
item.  SetDialogTracksCursor will cause the Dialog Manager to change the cursor shape to
the I-Beam cursor whenever the cursor is over an edit text control specified in the 
'DITL' as an edit text primitive.

The first call to GetDialogItemAsControl gets a handle to the user pane used for the
clocks tab.  HideControls hides this user pane and all the controls automatically
embedded within it.

At the next block, SetControlData is called with the kControlEditTextTextTag tag to
assign some text to the first edit text control.  The fields of an edit text selection
structure are then assigned values which will cause the following call to SetControlData
to select the entire edit text control.

The next block creates routine descriptors for application-defined event filter, key 
filter, and edit text validator functions.  (The event filter function is defined in 
the source code file Callbacks.c.)  SetControlData is then called with the 
kControlEditTextValidationProcTag tag to attach the edit text validation function to 
the first edit text control.  SetControlData is then called again with the 
kControlEditTextKeyFilterTag tag to attach the key filter function to the second edit 
text control.

With those preliminaries attended to, ShowWindow is called to display the window,
following which the ModalDialog loop is entered.  The loop will execute until the user
hits the OK push button. Note that the previously created UPP is passed in the filterProc
parameter of ModalDialog.

When a mouse-down event occurs in an enabled item, ModalDialog returns the item number of
the item hit.  If the item hit was the tab item, GetDialogItemAsControl is called to get
a handle to the tab control and GetControlValue is called to determine which of the two
tabs was hit.  If the tab hit was the Edit Text Controls tab, the Clock Controls user 
pane is hidden, the Edit Text Controls user pane is shown, and the keyboard focus is 
set to the first edit text control.  If the tab hit was the Clock Controls tab, the 
Edit Text Controls user pane is hidden, the Clock Controls user pane is shown, and the 
keyboard focus is set to the first clock control.

If the item hit was the Extract push button in the Edit Text Controls pane, the image 
well control is re-drawn to erase any previous text and an application-defined function 
is called to extract and display the contents of the edit text controls.

If the item hit was the Extract push button in the Clock Controls pane, the image well
control is re-drawn to erase any previous text and an application-defined function is
called to extract and display the contents of the clock controls.

When the user hits the OK button, DisposeDialog closes the dialog and disposes of the
associated memory, and the routine descriptors associated with the event filter function
and key filter function are disposed of.

doExtractEditText

doExtractEditText extracts the text from the edit text controls and draws it in the
image well area.  In the case of the Password edit text control, the text extracted is 
the actual password typed, not the bullet text.

In the case of the first two edit text controls, GetDialogItem is used to get the handle
to the hText field of the TERec structure used by the item.  This is where the 
characters are located.  (Exactly what is returned in the iHandle field of a 
GetDialogItem call depends on the item type.)  GetDialogItemText then copies these 
characters to a variable of type Str255.

In the case of the third (password) edit text control, GetDialogItemAsControl gets a 
handle to the control.  GetControlDataSize is then called with the 
kControlEditTextTextTag tag to get the number of characters and GetControlData is called 
with the kControlEditTextPasswordTag to get the clear password text from the 
control.

doExtractDateTime

doExtractDateTime gets the settings in the three clock controls into a long date
structure, extracts the content of the relevant fields of that structure, and draws that
content in the image well area.

For each clock, GetControlData is called with the kControlClockLongDateTag tag to get the
information into a long date structure.  The rest of the code simply converts the values
in the relevant fields of this structure to strings, which are concatenated with other
identifying strings prior to being drawn in the image well.

numericFilter

numericFilter is the key filter function attached to the second edit text control.

The character code passed to this function by the control is first examined to determine
whether it represents the numeric characters between 0 and 9 inclusive.  If so, the
function returns kControlKeyFilterPassKey, meaning that the character is to be accepted. 
If a return is not effected at that point, the character code is further examined to
determine whether it represents one of the arrow keys or the "dash" character.  If so,
kControlKeyFilterPassKey is returned.  If not, the system alert sound is played and
kControlKeyFilterBlockKey is returned, meaning that the character is to be rejected.

editTextValidator

editTextValidator is the edit text validation function attached to the first edit 
text control.

The call to GetControlData gets the text to be examined from the control into the 
variable oldText.  The next block sets the length byte in oldText to the actual number 
of characters in the text, limited to 255 characters.  The for loop then examines each 
character and, if it is an alphabetic character, the space character, or the period 
character, inserts it into the newText variable and increments a variable which is 
eventually used to set the length byte of newText.  When the if loop exits, the length 
byte is set and SetControlData is called to put the replacement text into the control. 
Finally, Draw1Control redraws the control.

GroupArrowsProgress.c

GroupArrowsProgress.c creates a movable modal dialog in which is demonstrated a checkbox
group box, a pop-up group box, little arrows, a disclosure triangle, asynchronous arrows,
and an indeterminate progress bar.

The checkbox group box contains a static text item and three radio buttons.  The radio
buttons are embedded in a radio group.  The pop-up group box contains two user panes. 
Embedded in each user pane are a checkbox and a radio group.  Embedded in each radio
group are two radio buttons.

The dialog item list used by the dialog created by GroupArrowsProgress.c is shown in the
following, in which the indentation represents the embedding hierarchy:

1.   Push button primitive.
2.   Group box control (kControlGroupBoxCheckboxProc variant).
     3.   Radio group control.
          4.   Radio button primitive.
          5.   Radio button primitive.
          6.   Radio button primitive.
     7.   Checkbox primitive.
8.   Group box control(kControlGroupBoxPopupButtonProc variant).
     9.   User pane control with kControlSupportsEmbedding feature bit set (initial
          value set to 2).
          10.   Radio group control
                11.   Radio button primitive.
                12.   Radio button primitive.
          13.   Checkbox primitive.
          14.   Static text primitive.
     15.   User pane control with kControlSupportsEmbedding feature bit set (initial
           value set to 2).
          16.   Radio group control
                17.   Radio button primitive.
                18.   Radio button primitive.
          19.   Checkbox primitive.
          20.   Static text primitive.
21.   Group box control (kControlGroupBoxSecondaryTextTitleProc variant).
          22.   Static text primitive.
23.   Group box control (kControlGroupBoxSecondaryTextTitleProc variant).
          24.   Static text primitive.
          25.   Placard control.
                26.   Static text primitive.
          27.   Little arrows control.
28.   Extract push button primitive.
29.   Image well
30.   Separator line
31.   Disclosure triangle (kControlTriangleProc variant).
32.   Static text primitive.

A second dialog item list resource, containing an asynchronous arrows control and a
progress bar control, is appended to the dialog when the disclosure triangle is clicked.

doTabEditClock

doTabEditClock creates the dialog, calls ModalDialog to handle events until the user hits
the OK push button, and then disposes of the dialog.

At the first two lines, if the Bevel Buttons, Image Wells, Picture Controls, and Icon
Controls window is open, it is explicitly deactivated.

The call to GetNewDialog creates the dialog and SetDialogDefaultItem establishes the OK
push button as the default push button.

The next two lines create routine descriptors for the application-defined event filter
function and an application-defined action function for the little arrows control.  (The
event filter function is in the source code file Callbacks.c.)

The next block sets the initial value of the checkbox group box to 1 (checked).

The little arrows are used to set a (simulated) cache size, which is displayed in a
static text item overlayed on a placard item.  The little arrows initial value is set in
the "CNTL' resource to 96.  The first three lines of the next block extract this value,
convert it to a string and append the character "K".  SetControlData is then called with
the kControlStaticTextTextTag to set this string in the static text item.

The second user pane in the pop-up group box is then hidden before the call to
ShowWindow, following which the ModalDialog loop is entered.  Note that the UPP
associated with the application-defined event filter function is passed in the filterProc
parameter of ModalDialog.

If ModalDialog reports that the item hit was the checkbox group box's checkbox or the
pop-up group box's pop-up menu, application-defined functions are called to further
handle the hit.

if the item hit was one of the checkboxes within the pop-up group box, the control's
control value is set so that the control is checked if it was unchecked, or unchecked if
it was checked.

If the item hit was the disclosure triangle, an application-defined function is called to
further handle the hit.

If the item hit was the Extract push button, Draw1Control is called to redraw the image
well, thus erasing any previous text in the well, and an application-defined function is
called to ectract the control settings and draw them in the image well area.

Note that hits on the radio buttons will be handled automatically by the radio group
controls in which they are embedded.  The radio group control will set the new control
values according to which radio button is hit, and will change the checked/unchecked
appearance of the radio buttons to match.

Note also that mouse-down events in the little arrows are detected and handled in the
event filter function.  (See the source code file Callbacks.c.)

When the OK button is hit, the loop exits, DisposeDialog closes the dialog and disposes
of the associated memory, and the two previously created routine descriptors are disposed
of.  In addition, the global variable which flags that the dialog was open is set to
false.

doCheckBoxGroupBox

doCheckBoxGroupBox further handles a hit in the checkbox group box's checkbox.

The first three lines flip the control's value; that is, if the control's value was 1
(checked), it is set to 0 (unchecked), and vice versa.

If the new value of the control is 0 (unchecked), the radio group and checkbox within the
group box are deactivated.  Since the radio buttons are embedded in the radio group, they
will also be deactivated when the radio group is deactivated.

If the new value of the control is 1 (checked), the radio group and checkbox within the
group box are activated.  Since the radio buttons are embedded in the radio group, they
will also be activated when the radio group is activated.

doPopupGroupBox

doPopupGroupBox further handles a hit in the pop-up group box's pop-up menu button.

The first two lines get the control's value, which represents the menu item chosen. 
Depending on the item chosen, the appropriate user panes are hidden or shown, thus hiding
or showing all controls embedded in each user pane.

doAsynchronousAndProgress

doAsynchronousAndProgress further handles a hit in the disclosure triangle.

The first three lines flip the control's value; that is, if the control's value was 1
(expanded), it is set to 0 (collapsed), and vice versa.

If the new control value is 1 (expanded), GetResource is called to load the item list
resource containing the asynchronous arrows and progress bar items.  AppendDITL is then
called to append these items to the end of the dialog's item list.  The constant passed
in the third parameter of this call causes the dialog box to be expanded downwards to
accommodate the new items.  SetControlData is then called with the
kControlProgressBarIndeterminateTag tag to make the progress bar an indeterminate
progress bar.

Not previously mentioned is the fact that the appended 'DITL' resource contains a static
text item, with not text, the function of which is simply to expand the dialog further
downwards to accommodate a move of the OK push button.  The call to MoveControl moves the
OK push button to a position below the asynchronous arrows and progress bar.

Finally, SetControlData is called with the kControlStaticTextTextTag tag to change the
text in the static text field adjacent to the disclosure triangle.  Draw1Control re-draws
the control to display the changed text.

If the new disclosure triangle control value is 0 (collapsed), the OK button is moved
back to its previous location, SizeWindow is called to resize the window to its previous
size, SetControlData is called with the kControlStaticTextTextTag tag to change the text
in the static text field adjacent to the disclosure triangle, and Draw1Control re-draws
the control to display the changed text.

doExtractCurrentStatus

doExtractCurrentStatus is called when the Extract push button is hit.  It simply extracts
the values of the various controls, builds up strings based on those values, and draws
those strings in the image well area.

Note in the second last block that the value of the little arrows control represents the
current (simulated) cache size.  The little arrows control value is set within the action
function arrowsActionFunction in the source code file Callbacks.c.

Sliders.c

Sliders.c creates a movable modal dialog box in which is demonstrated various slider
control variants and two simple user pane functions.

doSliderUserPane

doSliderUserPane creates the dialog, calls ModalDialog to handle events until the user
hits the OK push button, and then disposes of the dialog.

At the first two lines, if the Bevel Buttons, Image Wells, Picture Controls, and Icon
Controls window is open, it is explicitly deactivated.

The call to GetNewDialog creates the dialog and SetDialogDefaultItem establishes the OK
push button as the default push button.

The next three lines create routine descriptors for the application-defined event filter
function and two application-defined action functions for the live-feedback slider
variants, one for the two at top right of the dialog and one for the two horizontal
sliders.  (The event filter function  and the action functions are in the source code
file Callbacks.c.)

The next two blocks creates routine descriptors for two user pane functions (one a draw
function and one an activate function), and attach these functions to a user pane located
immediately to the right of the two horizontal sliders.

The next block assign handles to the first four sliders to global variables and call an
application-defined function to draw the respective control values in static text items
located immediately below the sliders.

The following four lines assign handles to the horizontal sliders to global variables and
assign a value based on the current slider control values to the red and blue fields of
two global variables of type RGBColor.

The call to ShowWindow makes the dialog visible before the ModalDialog loop is entered. 
This loop executes until the OK button is hit, at which time DisposeDialog is called to
remove the dialog and dispose of its associated memory, the previously created routine
descriptors are disposed of, and the global variable which flags that the Sliders dialog
is open is assigned false.

doDrawSliderValues

doDrawSliderValue is called by doSliderUserPane to draw the initial control values of the
four top sliders in the static text fields immediately below the sliders.  

The first line gets the control's value and converts it to a string.  The next block
determines, on the basis of the received control handle, which is the target static text
item.  SetControlData is then called with the kControlStaticTextTextTag tag to set the
text, and Draw1Control re-draws the static text control.

As will be seen, this function is also called from within the event filter function when
a mouse-down has been detected within the two non-live-scrolling sliders.

userPaneDrawFunction

userPaneDrawFunction will be called whenever an update event is received.  This will
occur when the dialog is opened and, subsequently, when an overlaying window or help
balloon is removed from the area occupied by the user pane (to the immediate right of the
horizontal sliders).

The two calls to DrawThemeGenericWell draw two Appearance image well primitives to the
right of the horizontal sliders.  The global variable gDrawActivated determines whether
the primitive is drawn with an activated or deactivated appearance.

If the global variable gDrawActivated indicates that the interior of the well should be
drawn, the foreground colour for each interior is set to that stored in global variables
and PaintRect is called to paint the interior in that colour.  (As will be seen, the
value stored in these global variables is changed by the action function called while the
mouse button remains down in the slider's indicators.)

If gDrawActivated indicates that the interior of the well should be displayed with a
deactivated appearance, the interior is left as drawn by DrawThemeGenericWell, that is,
white.

userPaneActivateFunction

The kControlWantsActivate feature bit is set in the user pane on creation, that is, the
control's minimum value in the 'CNTL' resource is set to 16.  This ensures that this
function will be called when the dialog receives activate events.

Depending on whether the dialog is about to be activated or deactivated, the global
variable gDrawActivated is set to true or false.  As has been seen, this global variable
controls the way in which the image well primitive and the interior of the image well is
drawn.

TextBox.c

doAboutBox is called when the user chooses About Controls3... from the Apple menu.  It
opens a movable modal dialog containing a standard and scrolling text box controls.

Callbacks.c

Callbacks.c contains the event filter function used by all movable modal dialogs and
three action functions, one for the little arrows, one for the live-feedback sliders at
top right of the dialog, and one for the horizontal live-feedback sliders.

eventFilter

The event filter function eventFilter is identical to the event filter function
introduced at Chapter 8 - Dialogs and Alerts except that it intercepts mouse-down events
in the little arrows and sliders and informs ModalDialog that it has handled those
events.

At the second and third if statements, if the Group Boxes, Arrows, and Progress Bar
dialog is currently open, and if the event is a mouse-down event, the location of the
mouse-down is extracted from the where field of the event structure and converted to the
local coordinates required by the following call to FindControl.  If FindControl
determines that there is an enabled control under the mouse cursor, and if that control
is the little arrows control, TrackControl is called to handle all user interaction while
the mouse button remains down.  While the mouse button remains down, TrackControl
continually calls the action function whose routine descriptor is pointed to by the UPP
passed in the third parameter.  When the mouse button is released, the function exits
with true being returned to ModalDialog.

if, on the other hand, the Sliders and User Pane Functions dialog is open, and if the
event is a mouse-down event, and if FindControl reports an enabled control, and if that
control is one of the two non-live-feedback sliders, TrackControl is called to handle all
user interaction while the mouse button remains down.  When the mouse button is released,
the application-defined function doDrawSliderValues is called to draw the new control
value in the static text item below the slider.  Once again, the function then exits with
true being returned to ModalDialog.

If the mouse-down was in one of the two live-feedback sliders at the top right of the
dialog, TrackControl is called with a UPP to the first slider action function passed in
the third parameter.

If the mouse-down was in one of the two horizontal live-feedback sliders, TrackControl is
called with a UPP to the second slider action function passed in the third parameter.

arrowsActionFunction

arrowsActionFunction is the action function for the little arrows.  It is called
continually by TrackControl while the mouse button remains down.

if the mouse cursor is still within the control, GetControlValue is called to get the
current control value.  The function then switches according to the part code.  If the
cursor is in the top arrow, the control's value is increased by 32 unless this would
cause the value to exceed the control's maximum value (set in the 'CNTL' resource to
7680).  If the cursor is in the bottom arrow, the control's value is decreased by 32
unless this would cause the value to be lower that the control's minimum value (set in
the 'CNTL' resource to 96).

If the control's value was increased or decreased within the switch, SetControlValue is
called to set the new control value, and the final block sets the new text for the Cache
size static text item and re-draws the item.

sliderActionFunction1

sliderActionFunction1 is the action function for the live-feedback sliders at the top
right of the dialog.  It is called continually by TrackControl while the mouse button
remains down.

GetControlValue gets the control's current value and NumToString converts it to a string
for display.  The next line gets the pointer to the control's owning window required by
the call to GetDialogItemAsControl.  The if block determines which of the two sliders the
mouse is down in.  The last two lines set the text in the appropriate static text control
and redraw the control.

sliderActionFunction2

sliderActionFunction3 is the action function for the horizontal live-feedback sliders. 
It is called continually by TrackControl while the mouse button remains down.

GetControlValue gets the control's current value.  If the slider is the top horizontal
slider, the red field of the RGBColor global variable gRedColor is assigned a new value
based on the control's current value, and the local Rect variable is assigned the
coordinates of the image well at the right of the slider.  If the slider is the bottom
horizontal slider, the blue field of the RGBColor global variable gBlueColor is assigned
a new value based on the control's current value, and the local Rect variable is assigned
the coordinates of the image well at the right of the slider.

Finally, PaintRect is called to paint the interior area of the relevant image well in the
new colour.
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Summon your guild and prepare for war in...
Netmarble is making some pretty big moves with their latest update for Seven Knights Idle Adventure, with a bunch of interesting additions. Two new heroes enter the battle, there are events and bosses abound, and perhaps most interesting, a huge... | Read more »
Make the passage of time your plaything...
While some of us are still waiting for a chance to get our hands on Ash Prime - yes, donā€™t remind me I could currently buy him this month Iā€™m barely hanging on - Digital Extremes has announced its next anticipated Prime Form for Warframe. Starting... | Read more »
If you can find it and fit through the d...
The holy trinity of amazing company names have come together, to release their equally amazing and adorable mobile game, Hamster Inn. Published by HyperBeard Games, and co-developed by Mum Not Proud and Little Sasquatch Studios, it's time to... | Read more »
Amikin Survival opens for pre-orders on...
Join me on the wonderful trip down the inspiration rabbit hole; much as Palworld seemingly ā€œborrowedā€ many aspects from the hit Pokemon franchise, it is time for the heavily armed animal survival to also spawn some illegitimate children as Helio... | Read more »
PUBG Mobile teams up with global phenome...
Since launching in 2019, SpyxFamily has exploded to damn near catastrophic popularity, so it was only a matter of time before a mobile game snapped up a collaboration. Enter PUBG Mobile. Until May 12th, players will be able to collect a host of... | Read more »
Embark into the frozen tundra of certain...
Chucklefish, developers of hit action-adventure sandbox game Starbound and owner of one of the cutest logos in gaming, has released their roguelike deck-builder Wildfrost. Created alongside developers Gaziter and Deadpan Games, Wildfrost will... | Read more »
MoreFun Studios has announced Season 4,...
Tension has escalated in the ever-volatile world of Arena Breakout, as your old pal Randall Fisher and bosses Fred and Perrero continue to lob insults and explosives at each other, bringing us to a new phase of warfare. Season 4, Into The Fog of... | Read more »
Top Mobile Game Discounts
Every day, we pick out a curated list of the best mobile discounts on the App Store and post them here. This list won't be comprehensive, but it every game on it is recommended. Feel free to check out the coverage we did on them in the links below... | Read more »
Marvel Future Fight celebrates nine year...
Announced alongside an advertising image I can only assume was aimed squarely at myself with the prominent Deadpool and Odin featured on it, Netmarble has revealed their celebrations for the 9th anniversary of Marvel Future Fight. The Countdown... | Read more »
HoYoFair 2024 prepares to showcase over...
To say Genshin Impact took the world by storm when it was released would be an understatement. However, I think the most surprising part of the launch was just how much further it went than gaming. There have been concerts, art shows, massive... | Read more »

Price Scanner via MacPrices.net

Amazon is offering a $100 discount on every M...
Amazon is offering a $100 instant discount on each configuration of Appleā€™s new 13ā€³ M3 MacBook Air, in Midnight, this weekend. These are the lowest prices currently available for new 13ā€³ M3 MacBook... Read more
You can save $300-$480 on a 14-inch M3 Pro/Ma...
Apple has 14ā€³ M3 Pro and M3 Max MacBook Pros in stock today and available, Certified Refurbished, starting at $1699 and ranging up to $480 off MSRP. Each model features a new outer case, shipping is... Read more
24-inch M1 iMacs available at Apple starting...
Apple has clearance M1 iMacs available in their Certified Refurbished store starting at $1049 and ranging up to $300 off original MSRP. Each iMac is in like-new condition and comes with Appleā€™s... Read more
Walmart continues to offer $699 13-inch M1 Ma...
Walmart continues to offer new Apple 13ā€³ M1 MacBook Airs (8GB RAM, 256GB SSD) online for $699, $300 off original MSRP, in Space Gray, Silver, and Gold colors. These are new MacBook for sale by... Read more
B&H has 13-inch M2 MacBook Airs with 16GB...
B&H Photo has 13ā€³ MacBook Airs with M2 CPUs, 16GB of memory, and 256GB of storage in stock and on sale for $1099, $100 off Appleā€™s MSRP for this configuration. Free 1-2 day delivery is available... Read more
14-inch M3 MacBook Pro with 16GB of RAM avail...
Apple has the 14ā€³ M3 MacBook Pro with 16GB of RAM and 1TB of storage, Certified Refurbished, available for $300 off MSRP. Each MacBook Pro features a new outer case, shipping is free, and an Apple 1-... Read more
Apple M2 Mac minis on sale for up to $150 off...
Amazon has Appleā€™s M2-powered Mac minis in stock and on sale for $100-$150 off MSRP, each including free delivery: ā€“ Mac mini M2/256GB SSD: $499, save $100 ā€“ Mac mini M2/512GB SSD: $699, save $100 ā€“... Read more
Amazon is offering a $200 discount on 14-inch...
Amazon has 14-inch M3 MacBook Pros in stock and on sale for $200 off MSRP. Shipping is free. Note that Amazonā€™s stock tends to come and go: ā€“ 14ā€³ M3 MacBook Pro (8GB RAM/512GB SSD): $1399.99, $200... Read more
Sunday Sale: 13-inch M3 MacBook Air for $999,...
Several Apple retailers have the new 13ā€³ MacBook Air with an M3 CPU in stock and on sale today for only $999 in Midnight. These are the lowest prices currently available for new 13ā€³ M3 MacBook Airs... Read more
Multiple Apple retailers are offering 13-inch...
Several Apple retailers have 13ā€³ MacBook Airs with M2 CPUs in stock and on sale this weekend starting at only $849 in Space Gray, Silver, Starlight, and Midnight colors. These are the lowest prices... Read more

Jobs Board

Relationship Banker - *Apple* Valley Financ...
Relationship Banker - Apple Valley Financial Center APPLE VALLEY, Minnesota **Job Description:** At Bank of America, we are guided by a common purpose to help Read more
IN6728 Optometrist- *Apple* Valley, CA- Tar...
Date: Apr 9, 2024 Brand: Target Optical Location: Apple Valley, CA, US, 92308 **Requisition ID:** 824398 At Target Optical, we help people see and look great - and Read more
Medical Assistant - Orthopedics *Apple* Hil...
Medical Assistant - Orthopedics Apple Hill York Location: WellSpan Medical Group, York, PA Schedule: Full Time Sign-On Bonus Eligible Remote/Hybrid Regular Apply Now Read more
*Apple* Systems Administrator - JAMF - Activ...
ā€¦**Public Trust/Other Required:** None **Job Family:** Systems Administration **Skills:** Apple Platforms,Computer Servers,Jamf Pro **Experience:** 3 + years of Read more
Liquor Stock Clerk - S. *Apple* St. - Idaho...
Liquor Stock Clerk - S. Apple St. Boise Posting Begin Date: 2023/10/10 Posting End Date: 2024/10/14 Category: Retail Sub Category: Customer Service Work Type: Part Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.