MacTech Network:   MacForge.net  |  Computer Memory  |  Register Domains  |  Printer Supplies  |  Cables  |  iPod Deals  |  Mac Deals  |  Mac Book Shelf


  MacTech Magazine

The journal of Macintosh technology

 
 
Visit Smalldog.com

Magazine In Print
  About MacTech  
  Home Page  
  Subscribe  
  Archives DVD  
  Submit News  
  Submit a Tip!  
  Get a copy of MacTech RISK FREE  
Google
Entire Web
mactech.com
Mac Community
More...
MacTech Central
  by Category  
  by Company  
  by Product  
MacTech News
  MacTech News  
  Previous News  
  MacTech RSS  
Article Archives
  Show Indices  
  by Volume  
  by Author  
  Source Code FTP  
Inside MacTech
  Writer's Kit  
  Editorial Staff  
  Editorial Calendar  
  Back Issues  
  Advertising  
Contact Us
  Customer Service  
  MacTech Store  
  Legal/Disclaimers  
  Webmaster Feedback  

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 e