TweetFollow Us on Twitter

MACINTOSH C

Demonstration Program

Go to Contents
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
// Scrap.c
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
// 
// This program utilises the desk scrap and Scrap Manager routines to allow the user to:
//
// „  Cut, copy and clear pictures from, and paste pictures to, two windows opened by the
//    program.
//
// „  Paste pictures cut or copied from another application to the two windows opened
//    by the program.
//
// „  Open and close a Clipboard window, in which the current contents of the desk scrap
//    are displayed.
//
// In addition to the pictures cut and copied from either the program's windows or from
// another application's windows, the Clipboard window will display text copied to the
// desk scrap as a result of text cut and copy operations in another application.  The
// program, however, does not support the pasting of this text to documents displayed in
// the program's windows.  (The demonstration program at Chapter 19 - Text and TextEdit
// shows how to cut, copy and paste text from and to a TextEdit edit structure using the
// desk scrap.)   
//
// The program utilises the following resources:
//
// „  An 'MBAR' resource, and 'MENU' resources for Apple, File, and Edit menus (preload, 
//    non-purgeable).  
//
// „  Three 'WIND' resources (purgeable) (initially visible), two for the program's main
//    windows and one for the Clipboard window.  
//
// „  A 'PICT' resource (non-purgeable) containing a picture which may be cut, copied,
//    and pasted between the windows.
//
// „  A 'STR#' resource (purgeable) containing strings to be displayed in the error
//    Alert.  
//
// „  A 'SIZE' resource with the acceptSuspendResumeEvents, doesActivateOnFGSwitch, and
//    is32BitCompatible flags set.
//
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

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

#include <Appearance.h>
#include <Devices.h>
#include <LowMem.h>
#include <Scrap.h>
#include <Sound.h>
#include <ToolUtils.h>

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

#define mApple            128
#define  iAbout           1
#define mFile             129
#define  iClose           4
#define  iQuit            11
#define mEdit             130
#define  iCut             3
#define  iCopy            4
#define  iPaste           5
#define  iClear           6
#define  iClipboard       9
#define rMenubar          128
#define rWindow           128
#define rClipboardWindow  130
#define rPicture          128
#define rErrorStrings     128
#define  eFailMenu        1
#define  eFailWindow      2
#define  eFailDocStruc    3
#define  eZeroScrap       4
#define  ePutScrap        5
#define  eNoPictInScrap   6
#define kDocumentType     1
#define kClipboardType    2
#define MAXLONG           0x7FFFFFFF

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

typedef struct
{
  PicHandle pictureHdl;
  Boolean   selectFlag;
  SInt16    windowType;
} docStructure, **docStructureHandle;

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

Boolean   gDone;
Boolean   gInBackground;
SInt16    gPixelDepth;  
Boolean   gIsColourDevice      = false;
WindowPtr gWindowPtrs[2];
WindowPtr gClipboardWindowPtr  = NULL;
Boolean   gClipboardShowing    = false;

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

void  main                  (void);
void  doInitManagers        (void);
void  doEvents              (EventRecord *);
void  doUpdate              (EventRecord *);
void  doOSEvent             (EventRecord *);
void  doAdjustMenus         (void);
void  doMenuChoice          (SInt32);
void  doErrorAlert          (SInt16);
void  doOpenWindows         (void);
void  doCloseWindow         (void);
void  doInContent           (Point);
void  doCutCopyCommand      (Boolean);
void  doPasteCommand        (void);
void  doClearCommand        (void);
void  doClipboardCommand    (void);
void  doDrawClipboardWindow (void);
void  doDrawPictureWindow   (WindowPtr);
Rect  doSetDestRect         (Rect *,WindowPtr);
void  doGetDepthAndDevice   (void);

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

void  main(void)
{
  Handle      menubarHdl;
  MenuHandle  menuHdl;
  Boolean     gotEvent;
  EventRecord eventStructure;
  
  // ................................................................ initialise managers

  doInitManagers();

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

  menuHdl = GetMenuHandle(mApple);
  if(menuHdl == NULL)
    doErrorAlert(eFailMenu);
  else
    AppendResMenu(menuHdl,'DRVR');

  // ....................................................................... open windows 

  doOpenWindows();

  // ........... get pixel depth and whether colour device for function SetThemeTextColor   
  
  doGetDepthAndDevice();

  // .................................................................... enter eventLoop
  
  gDone = false;

  while(!gDone)
  {
    gotEvent = WaitNextEvent(everyEvent,&eventStructure,MAXLONG,NULL);

    if(gotEvent)
      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)
{
  WindowPtr windowPtr;
  SInt16    partCode;
  SInt8      charCode;

  switch(eventStrucPtr->what)
  {
    case mouseDown:
      partCode = FindWindow(eventStrucPtr->where,&windowPtr);

      switch(partCode)
      {
        case inMenuBar:
          doAdjustMenus();
          doMenuChoice(MenuSelect(eventStrucPtr->where));
          break;

        case inContent:
          if(windowPtr != FrontWindow())
            SelectWindow(windowPtr);
          else
            doInContent(eventStrucPtr->where);
          break;

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

        case inGoAway:
          if(TrackGoAway(windowPtr,eventStrucPtr->where) == true)
            doCloseWindow();
          break;
      }
      break;

    case keyDown:
    case autoKey:
      charCode = eventStrucPtr->message & charCodeMask;
      if((eventStrucPtr->modifiers & cmdKey) != 0)
      {
        doAdjustMenus();
        doMenuChoice(MenuEvent(eventStrucPtr));
      }
      break;

    case updateEvt:
      doUpdate(eventStrucPtr);
      break;

    case activateEvt:
      windowPtr = (WindowPtr) eventStrucPtr->message;
      if(windowPtr == gClipboardWindowPtr)
        doDrawClipboardWindow();
      break;

    case osEvt:
      doOSEvent(eventStrucPtr);
      HiliteMenu(0);
      break;
  }
}

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

void  doUpdate(EventRecord *eventStrucPtr)
{
  WindowPtr           windowPtr;
  docStructureHandle  docStrucHdl;
  SInt32              windowType;

  windowPtr = (WindowPtr) eventStrucPtr->message;
  docStrucHdl = (docStructureHandle) GetWRefCon(windowPtr);
  windowType = (*docStrucHdl)->windowType;

  BeginUpdate(windowPtr);

  if(windowType == kDocumentType)
  {
    if((*docStrucHdl)->pictureHdl != NULL)
      doDrawPictureWindow(windowPtr);
  }
  else if(windowType == kClipboardType)
    doDrawClipboardWindow();

  EndUpdate(windowPtr);
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doOSEvent

void  doOSEvent(EventRecord *eventStrucPtr)
{
  switch((eventStrucPtr->message >> 24) & 0x000000FF)
  {
    case suspendResumeMessage:
      gInBackground = (eventStrucPtr->message & resumeFlag) == 0;
      if(gClipboardWindowPtr && gClipboardShowing)
      {
        if(gInBackground)
          ShowHide(gClipboardWindowPtr);
        else
          ShowWindow(gClipboardWindowPtr);
      }
      break;

    case mouseMovedMessage:
      break;
  }
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doAdjustMenus

void  doAdjustMenus(void)
{
  MenuHandle          fileMenuHdl, editMenuHdl;
  docStructureHandle  docStrucHdl;
  SInt32              scrapOffset;

  fileMenuHdl = GetMenuHandle(mFile);
  editMenuHdl = GetMenuHandle(mEdit);

  docStrucHdl = (docStructureHandle) GetWRefCon(FrontWindow());

  if((*docStrucHdl)->windowType == kClipboardType)
    EnableItem(fileMenuHdl,iClose);
  else
    DisableItem(fileMenuHdl,iClose);

  if((*docStrucHdl)->pictureHdl && (*docStrucHdl)->selectFlag)
  {
    EnableItem(editMenuHdl,iCut);
    EnableItem(editMenuHdl,iCopy);
    EnableItem(editMenuHdl,iClear);
  }
  else
  {
    DisableItem(editMenuHdl,iCut);
    DisableItem(editMenuHdl,iCopy);
    DisableItem(editMenuHdl,iClear);
  }

  if(GetScrap(NULL,'PICT',&scrapOffset)  && (*docStrucHdl)->windowType != kClipboardType)
    EnableItem(editMenuHdl,iPaste);
  else
    DisableItem(editMenuHdl,iPaste);

  DrawMenuBar();
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× 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)
        SysBeep(10);
      else
      {
        GetMenuItemText(GetMenuHandle(mApple),menuItem,itemName);
        daDriverRefNum = OpenDeskAcc(itemName);
      }
      break;

    case mFile:
      if(menuItem == iClose)
        doCloseWindow();
      else if(menuItem == iQuit)
        gDone = true;
      break;

    case mEdit:
      switch(menuItem)
      {
        case iCut:
          doCutCopyCommand(true);
          break;

        case iCopy:
          doCutCopyCommand(false);
          break;

        case iPaste:
          doPasteCommand();
          break;

        case iClear:
          doClearCommand();
          break;

        case iClipboard:
          doClipboardCommand();
          break;
      }
      break;    
  }

  HiliteMenu(0);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doErrorAlert

void  doErrorAlert(SInt16 errorCode)
{
  AlertStdAlertParamRec paramRec;
  Str255                errorString;
  SInt16                itemHit;

  paramRec.movable        = true;
  paramRec.helpButton     = false;
  paramRec.filterProc     = NULL;
  paramRec.defaultText    = (StringPtr) kAlertDefaultOKText;
  paramRec.cancelText     = NULL;
  paramRec.otherText      = NULL;
  paramRec.defaultButton  = kAlertStdAlertOKButton;
  paramRec.cancelButton   = 0;
  paramRec.position       = kWindowDefaultPosition;

  GetIndString(errorString,rErrorStrings,errorCode);

  if(errorCode < ePutScrap)
  {
    StandardAlert(kAlertStopAlert,errorString,NULL,¶mRec,&itemHit);
    ExitToShell();
  }
  else
    StandardAlert(kAlertCautionAlert,errorString,NULL,¶mRec,&itemHit);
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doOpenWindows

void  doOpenWindows(void)
{
  SInt16              a;
  WindowPtr           windowPtr;
  docStructureHandle  docStrucHdl;

  for(a=0;a<2;a++)
  {
    if(!(windowPtr = GetNewCWindow(rWindow + a,NULL,(WindowPtr)-1)))
      doErrorAlert(eFailWindow);
    gWindowPtrs[a] = windowPtr;

    if(!(docStrucHdl = (docStructureHandle) NewHandle(sizeof(docStructure))))
      doErrorAlert(eFailDocStruc);
    SetWRefCon(windowPtr,(SInt32) docStrucHdl);

    (*docStrucHdl)->pictureHdl = NULL;
    (*docStrucHdl)->windowType = kDocumentType;
    (*docStrucHdl)->selectFlag = false;
  }

  SetPort(windowPtr);

  (*docStrucHdl)->pictureHdl = GetPicture(rPicture);
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doCloseWindow

void  doCloseWindow(void)
{
  WindowPtr           windowPtr;
  docStructureHandle  docStrucHdl;
  MenuHandle          editMenuHdl;

  windowPtr = FrontWindow();
  docStrucHdl = (docStructureHandle) GetWRefCon(windowPtr);

  if((*docStrucHdl)->windowType == kClipboardType)
  {
    DisposeWindow(windowPtr);
    gClipboardWindowPtr = NULL;
    gClipboardShowing = false;
    editMenuHdl = GetMenu(mEdit);
    SetMenuItemText(editMenuHdl,iClipboard,"\pShow Clipboard");
  }
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doInContent

void  doInContent(Point mouseXY)
{
  WindowPtr           windowPtr;
  docStructureHandle  docStrucHdl;
  GrafPtr             oldPort;
  Rect                pictRect;

  windowPtr = FrontWindow();
  docStrucHdl = (docStructureHandle) GetWRefCon(windowPtr);

  if((*docStrucHdl)->windowType == kClipboardType)
    return;

  GetPort(&oldPort);
  SetPort(windowPtr);

  if((*docStrucHdl)->pictureHdl != NULL)
  {
    pictRect = doSetDestRect(&(*(*docStrucHdl)->pictureHdl)->picFrame,windowPtr);

    GlobalToLocal(&mouseXY);

    if(PtInRect(mouseXY,&pictRect) && (*docStrucHdl)->selectFlag == false)
    {
      (*docStrucHdl)->selectFlag = true;
      InvertRect(&pictRect);
    }
    else if(!PtInRect(mouseXY,&pictRect) && (*docStrucHdl)->selectFlag == true)
    {
      (*docStrucHdl)->selectFlag = false;
      InvertRect(&pictRect);
    }
  }

  SetPort(oldPort);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doCutCopyCommand

void  doCutCopyCommand(Boolean cutFlag)
{
  WindowPtr           windowPtr;
  docStructureHandle  docStrucHdl;  
  Size                dataLength;
  SInt32              errorCode;
  GrafPtr             oldPort;

  windowPtr = FrontWindow();
  docStrucHdl = (docStructureHandle) GetWRefCon(windowPtr);

  if((*docStrucHdl)->selectFlag == false)
    return;

  if(ZeroScrap() == noErr)
  {
    dataLength = GetHandleSize((Handle) (*docStrucHdl)->pictureHdl);
    HLock((Handle) (*docStrucHdl)->pictureHdl);

    errorCode = PutScrap((SInt32) dataLength,'PICT',
                         *((Handle) (*docStrucHdl)->pictureHdl));
    if(errorCode != noErr)
      doErrorAlert(ePutScrap);

    HUnlock((Handle) (*docStrucHdl)->pictureHdl);
  }
  else
    doErrorAlert(eZeroScrap);

  if(cutFlag)
  {
    GetPort(&oldPort);
    SetPort(windowPtr);

    DisposeHandle((Handle) (*docStrucHdl)->pictureHdl);
    (*docStrucHdl)->pictureHdl = NULL;
    (*docStrucHdl)->selectFlag = false;
    EraseRect(&windowPtr->portRect);

    SetPort(oldPort);
  }

  if(gClipboardWindowPtr != NULL)
    doDrawClipboardWindow();
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doPasteCommand

void  doPasteCommand(void)
{
  WindowPtr           windowPtr;
  docStructureHandle  docStrucHdl;  
  GrafPtr             oldPort;
  SInt32              sizeOfPictData, scrapOffset;
  Handle              tempHdl;
  Rect                destRect;  

  windowPtr = FrontWindow();
  docStrucHdl = (docStructureHandle) GetWRefCon(windowPtr);

  GetPort(&oldPort);
  SetPort(windowPtr);  

  sizeOfPictData = GetScrap(NULL,'PICT',&scrapOffset);
  if(sizeOfPictData > 0)
  {
    tempHdl = NewHandle((Size) sizeOfPictData);  
    HLock(tempHdl);

    sizeOfPictData = GetScrap(tempHdl,'PICT',&scrapOffset);

    EraseRect(&windowPtr->portRect);
    (*docStrucHdl)->selectFlag = false;
    destRect = doSetDestRect(&(*(PicHandle) tempHdl)->picFrame,windowPtr);

    DrawPicture((PicHandle) tempHdl,&destRect);

    if((*docStrucHdl)->pictureHdl != NULL)
      DisposeHandle((Handle) (*docStrucHdl)->pictureHdl);

    (*docStrucHdl)->pictureHdl = (PicHandle) NewHandle((Size) sizeOfPictData);
    BlockMoveData(*tempHdl,*((*docStrucHdl)->pictureHdl),(Size) sizeOfPictData);

    HUnlock(tempHdl);
    DisposeHandle(tempHdl);
  }

  SetPort(oldPort);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doClearCommand

void  doClearCommand(void)
{
  WindowPtr           windowPtr;
  docStructureHandle  docStrucHdl;  
  GrafPtr             oldPort;

  windowPtr = FrontWindow();
  docStrucHdl = (docStructureHandle) GetWRefCon(windowPtr);

  GetPort(&oldPort);
  SetPort(windowPtr);

  DisposeHandle((Handle) (*docStrucHdl)->pictureHdl);
  (*docStrucHdl)->pictureHdl = NULL;
  (*docStrucHdl)->selectFlag = false;
  EraseRect(&windowPtr->portRect);

  SetPort(oldPort);
}

// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doClipboardCommand

void  doClipboardCommand(void)
{
  MenuHandle          editMenuHdl;
  docStructureHandle  docStrucHdl;  

  editMenuHdl = GetMenu(mEdit);

  if(gClipboardWindowPtr == NULL)
  {
    if(!(gClipboardWindowPtr = GetNewCWindow(rClipboardWindow,NULL,(WindowPtr)-1)))
      doErrorAlert(eFailWindow);
    if(!(docStrucHdl = (docStructureHandle) NewHandle(sizeof(docStructure))))
      doErrorAlert(eFailDocStruc);
    SetWRefCon(gClipboardWindowPtr,(SInt32) docStrucHdl);
    (*docStrucHdl)->windowType = kClipboardType;

    gClipboardShowing = true;

    SetMenuItemText(editMenuHdl,iClipboard,"\pHide Clipboard");
  }
  else
  {
    if(gClipboardShowing)
    {
      HideWindow(gClipboardWindowPtr);
      gClipboardShowing = false;
      SetMenuItemText(editMenuHdl,iClipboard,"\pShow Clipboard");
    }
    else
    {
      ShowWindow(gClipboardWindowPtr);
      gClipboardShowing = true;
      SetMenuItemText(editMenuHdl,iClipboard,"\pHide Clipboard");        
    }
  }
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doDrawClipboardWindow

void  doDrawClipboardWindow(void)
{
  GrafPtr   oldPort;
  Rect      theRect, destRect;  
  RGBColor  blackColour = { 0x0000, 0x0000, 0x0000 };
  SInt32    sizeOfPictData, sizeOfTextData, scrapOffset;
  Handle    tempHdl;
  
  GetPort(&oldPort);
  SetPort(gClipboardWindowPtr);  

  EraseRect(&gClipboardWindowPtr->portRect);

  SetRect(&theRect,-1,-1,597,24);
  DrawThemeWindowHeader(&theRect,gClipboardWindowPtr == FrontWindow());

  if(gClipboardWindowPtr == FrontWindow())
    SetThemeTextColor(kThemeActiveWindowHeaderTextColor,gPixelDepth,gIsColourDevice);
  else
    SetThemeTextColor(kThemeInactiveWindowHeaderTextColor,gPixelDepth,gIsColourDevice);

  TextSize(10);
  MoveTo(7,16);
  DrawString("\pClipboard Contents:");

  sizeOfPictData = GetScrap(NULL,'PICT',&scrapOffset);
  if(sizeOfPictData > 0)
  {
    MoveTo(105,16);
    DrawString("\pPicture");

    tempHdl = NewHandle((Size) sizeOfPictData);  
    HLock(tempHdl);

    sizeOfPictData = GetScrap(tempHdl,'PICT',&scrapOffset);

    destRect = (*(PicHandle) tempHdl)->picFrame;
    OffsetRect(&destRect,-((*(PicHandle) tempHdl)->picFrame.left - 2),
                         -((*(PicHandle) tempHdl)->picFrame.top - 26));
    DrawPicture((PicHandle) tempHdl,&destRect);

    HUnlock(tempHdl);
    DisposeHandle(tempHdl);
  }

  sizeOfTextData = GetScrap(NULL,'TEXT',&scrapOffset);
  if(sizeOfTextData > 0)
  {
    MoveTo(105,16);
    DrawString("\pText");
  
    tempHdl = NewHandle((Size) sizeOfTextData);  
    HLock(tempHdl);
  
    sizeOfTextData = GetScrap(tempHdl,'TEXT',&scrapOffset);

    destRect = gClipboardWindowPtr->portRect;
    destRect.top += 24;
    InsetRect(&destRect,2,2);

    RGBForeColor(&blackColour);
    
    TETextBox(*tempHdl,sizeOfTextData,&destRect,0);

    HUnlock(tempHdl);
    DisposeHandle(tempHdl);
  }

  SetPort(oldPort);
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doDrawPictureWindow

void  doDrawPictureWindow(WindowPtr windowPtr)
{
  GrafPtr             oldPort;
  Rect                destRect;
  docStructureHandle  docStrucHdl;

  GetPort(&oldPort);
  SetPort(windowPtr);

  docStrucHdl = (docStructureHandle) GetWRefCon(windowPtr);
  destRect = doSetDestRect(&(*(*docStrucHdl)->pictureHdl)->picFrame,windowPtr);

  DrawPicture((*docStrucHdl)->pictureHdl,&destRect);

  if((*docStrucHdl)->selectFlag)
    InvertRect(&destRect);

  SetPort(oldPort);
}

// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doSetDestRect

Rect  doSetDestRect(Rect *picFrame,WindowPtr windowPtr)
{
  Rect    destRect;
  SInt16  diffX, diffY;

  destRect = *picFrame;

  OffsetRect(&destRect,-(*picFrame).left,-(*picFrame).top);

  diffX = (windowPtr->portRect.right - windowPtr->portRect.left) - 
          ((*picFrame).right - (*picFrame).left);
  diffY = (windowPtr->portRect.bottom - windowPtr->portRect.top) - 
          ((*picFrame).bottom - (*picFrame).top);
            
  OffsetRect(&destRect,diffX / 2,diffY / 2);
  
  return(destRect);
}

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

void doGetDepthAndDevice(void)
{
  GDHandle  deviceHdl;

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

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

Demonstration Program Comments

When this program is run, the user should choose the Edit menu's Show Clipboard command
to open the Clipboard window.  The user should then cut, copy, clear and paste the
supplied picture from/to the two windows opened by the program, noting the effect on the
desk scrap as displayed in the Clipboard window.  (The picture inverts when the user
selects it with the mouse.)  The user should also copy some text from another
application's window and observe the changes to the contents of the Clipboard window.

The user should note that, when the Clipboard window is open and showing, it will be
hidden when the program is sent to the background and shown again when the program is
brought to the foreground.

The user may also copy pictures from another application's window and paste them in the
demonstration program's windows.

#define

kDocumentType and kClipboardType will enable the program to distinguish between the two
"document" windows opened by the program and the Clipboard window.

#typedef

Document structures will be attached to each of the two document windows.  docStructure
is the associated data type.

Global Variables

gDone controls program termination.  gInBackground relates to foreground/background
switching. The values assigned to gPixelDepth and gIsColourDevice will be used by the
Appearance Manager function SetThemeTextColor.

The WindowPtrs for the two document windows will be copied into the elements of
gWindowPtrs.  gClipBoardWindowPtr will be assigned the WindowPtr for the Clipboard window
when it is opened by the user.  gClipBoardShowing will keep track of whether the
Clipboard window is currently hidden or showing.

doEvents

Note that, in the case of an activate event for the Clipboard window, the
application-defined function doDrawClipBoardWindow is called.

doUpdate

If the window is of the document type (as opposed to the Clipboard type), and if the
window's document structure currently contains a picture, the application-defined
function doDrawPicture is called to draw that picture.  If the window is the Clipboard
window, the application-defined function doDrawClipboardWindow is called to draw the
Clipboard window.

doOSEvent

The if statement tests whether the Clipboard window has been opened by the user and
whether it should be showing when the demonstration program is in the foreground.  If the
window has previously been opened and gClipboardShowing contains true, and if the event
is a suspend event, the window is hidden.  If the event is a resume event, the window is
shown..  Note that ShowHide, rather than HideWindow is called to hide the window.  This 
is to prevent activation of the first document window in the list when the Clipboard 
window is in front and the application is switched out.

doAdjustMenus

If the front window is the Clipboard window, the Close item is enabled, otherwise it is
disabled.  If the document contains a picture and that picture is currently selected, the
Cut, Copy, and Clear items are enabled, otherwise they are disabled.  If the desk scrap
contains data of type 'PICT' and the front window is not the Clipboard window, the Paste
item is enabled, otherwise it is disabled.

doOpenWindows

doOpenWindows opens the two document windows, creates document structures for each
window, attaches the document structures to the windows and initialises the fields of the
document structures.  The graphics port of the second window created is then set as the
current port and a picture is read in from a resource, its handle being assigned to the
pictureHdl field of the second window's document structure.

doCloseWindow

doCloseWindow closes the Clipboard window (the only window that can be closed from within
the program).

If the window is the Clipboard window, The window is disposed of, the global variable
which contains its pointer is set to NULL, the global variable which keeps track of
whether the window is showing or hidden is set to false, and the text of the Show/Hide
Clipboard menu item is set to Show Clipboard.

doInContent

doInContent handles mouse-down events in the content region of a document window.  If the
window contains a picture, and if the mouse-down was inside the picture, the picture is
selected.  If the window contains a picture, and if the mouse-down was outside the
picture, the picture is deselected.

The first two lines get a pointer the front window and a handle to its document
structure.  If the front window is the Clipboard window, the function returns
immediately.  GetPort and SetPort save the current graphics port and make the graphics
port associated with the front window the current graphics port.

If the front window contains a picture the following occurs.  The application-defined
function doSetDestRect is called to return a rectangle of the same dimensions as that
contained in the picture structure's picFrame field, but centred laterally and vertically
in the window.  GlobalToLocal converts the mouse-down coordinates to local coordinates
preparatory to the call to PtInRect.  If the mouse-down occurred within the rectangle and
the picture has not yet been selected, the document structure's selectFlag field is set
to true and the picture is inverted.  If the mouse-down occurred outside the rectangle
and the picture is currently selected, the document structure's selectFlag field is set
to false, and the picture is re-inverted.

doCutCopyCommand

doCutCopyCommand handles the user's choice of the Cut and Copy items in the Edit menu.

The first two lines get a pointer to the front window and a handle to that window's
document structure.

If the selectFlag field of the document structure contains false (meaning that the
picture has not been selected), the function returns immediately.  (Note that no check is
made as to whether the front window is the Clipboard window because the menu adjustment
function disables the Cut and Copy items when the Clipboard window is the front window,
meaning that this function can never be called when the Clipboard window is in front.)

ZeroScrap attempts to purge the desk scrap.  If the call is successful, GetHandleSize
gets the size of the picture structure, HLock locks the picture structure, PutScrap
copies the picture to the desk scrap, and HUnlock unlocks the picture structure.  If the
calls to ZeroScrap and PutScrap are not successful, a caution alert is displayed to
advise the user of the error.

If the menu choice was the Cut item, additional action is taken.  Preparatory to a call
to EraseRect, the current graphics port is saved and the front window's port is made the
current port.  DisposeHandle is called to dispose of the picture structure and the
document structure's pictureHdl and selectFlag fields are set to NULL and false
respectively.  EraseRect then erases the picture.

Finally, and importantly, if the Clipboard window has previously been opened by the user,
an application defined function is called to draw the current contents of the desk scrap
in the Clipboard window.

doPasteCommand

doPasteCommand handles the user's choice of the Paste item from the Edit menu.  Note that
no check is made as to whether the front window is the Clipboard window because the menu
adjustment function disables the Paste item when the Clipboard window is the front
window, meaning that this function can never be called when the Clipboard window is in
front.

In order to determine whether the desk scrap contains data of type 'PICT', GetScrap is
called with the destHandle parameter set to NULL.  The following occurs if data of type
'PICT' is present in the desk scrap.

NewHandle and HLock create and lock a relocatable block of a size equivalent to the
'PICT' data in the scrap.  GetScrap is called again to copy the 'PICT' data in the scrap
to the newly-created relocatable block.  EraseRect erases the front window and the next
line sets the selectFlag field of the document structure associated with the front window
to false.  The call to the application-defined function doSetDestRect returns a
destination rectangle of the same dimensions as the picFrame rectangle but centred in the
front window.  DrawPicture draws the picture in this rectangle.

If the document structure currently contains a picture, DisposeHandle is called to
dispose of the picture structure.  NewHandle creates a new relocatable block the size of 
'PICT' data and assigns its handle to the pictureHdl field of the document structure. 
BlockMoveData then copies the bytes in the relocatable block created at the first line in
the if block to this new relocatable block.  HUnlock and DisposeHandle then dispose of
the block created at the first line in the if block.

doClearCommand

doClearCommand handles the user's choice of the Clear item in the Edit menu.

Note that, as was the case in the doCutCopyCommand function, no check is made as to
whether the front window is the Clipboard window because the menu adjustment function
disables the Clear item when the Clipboard window is the front window.

DisposeHandle dispose of the picture structure.  The next two three lines set the
pictureHdl field of the document structure to NULL, set the selectFlag field of the
document structure to false, and erase the window's port rectangle.

doClipboardCommand

doClipboardCommand handles the user's choice of the Show/Hide Clipboard command in the
Edit menu.

The first line gets the handle to the Edit menu.  This will be required in order to
toggle the Show/Hide Clipboard item's text between Show Clipboard and Hide Clipboard.

The if statement checks whether the Clipboard window has been created.  If not, the
Clipboard window is created by the call to GetNewCWindow, a document structure is created
and attached to the window, the windowType field of the document structure is set to
indicate that the window is of the Clipboard type, a global variable which keeps track of
whether the Clipboard window is currently showing or hidden is set to true, and the text
of the menu item is set to Hide Clipboard.

If the Clipboard window has previously been created, and if the window is currently
showing, the window is hidden, the Clipboard-showing flag is set to false, and the item's
text is set to Show Clipboard.  If the window is not currently showing, the window is
made visible, the Clipboard-showing flag is set to true, and the item's text is set to
Hide Clipboard.

doDrawClipboardWindow

doDrawClipboardWindow draws the contents of the desk scrap in the Clipboard window.  It
supports the drawing of both 'PICT' and 'TEXT' data.

The first three lines save the current graphics port, make the Clipboard window's
graphics port the current graphics port and erase the window's content region.

DrawThemeWindowHeader draws a window header in the top of the window.  Text describing
the type of data in the desk scrap will be drawn in this header.  The theme-compliant
colour for this text is set at the next four lines.  The following three lines set the
text size to 10pt and draw some text in the header.

The call to GetScrap, with NULL passed as the destHandle parameter, checks whether data
of type 'PICT' exists in the desk scrap.  If so, the following occurs.  The word
"Picture" is drawn in the window header.  A relocatable block the size of the 'PICT' data
is created and locked and GetScrap is called once again to copy the 'PICT' data from the
scrap into the newly-created block.  A destination rectangle, based on the rectangle in
the picFrame field of the picture structure, is created with its left and top fields set
to two pixels inside that part of the content area not occupied by the window header. 
The picture is then drawn in this destination rectangle, following which the relocatable
block created earlier is unlocked and disposed of.

The next call to GetScrap checks whether data of type 'TEXT' exists in the desk scrap. 
If so, much the same procedure is followed, the differences being that the word "Text" is
drawn in the window header, the destination rectangle is set to two pixels inside that
part of the content area not occupied by the window header., and the text is drawn in
this rectangle using TETextBox.  (TETextBox is a TextEdit routine, and is described at
Chapter 19 - Text and TextEdit.)

doDrawPictureWindow

doDrawPictureWindow draws the picture belonging to a document window in that window.

The third line gets the handle to the window's document structure.  The call to the
application-defined function doSetDestRect returns a rectangle of the same dimensions as
that contained in the picFrame field of the picture structure (the handle to which is
contained in the pictureHdl field of the document structure), but centred in the window. 
DrawPicture draws the picture specified in the window's document structure in this
rectangle.

If the selectFlag field of the document structure indicates that the picture is currently
selected, the call to InvertRect inverts the picture.

doSetDestRect

doSetDestRect takes the rectangle contained in the picFrame field of a picture structure
and returns a rectangle of the same dimensions but centred in the window's port
rectangle.

The first line makes a local Rect variable equal to the rectangle in the picFrame field. 
OffsetRect then offsets this rectangle so that its left and top fields both contain 0. 
The next four lines calculate the differences between the widths and heights of the
rectangle and the window's port rectangle.  This is used at the next call to OffsetRect
to further offset the rectangle to the middle of the port rectangle.  The rectangle is
then returned to the calling function.
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Pack a magnifying glass and practice you...
Somehow it has already been a year since Torchlight: Infinite launched, and XD Games is celebrating by blending in what sounds like a truly fantastic new update. Fans of Cthulhu rejoice, as Whispering Mist brings some horror elements, and tests... | Read more »
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 »

Price Scanner via MacPrices.net

Every model of Appleā€™s 13-inch M3 MacBook Air...
Best Buy has Apple 13ā€³ MacBook Airs with M3 CPUs in stock and on sale today for $100 off MSRP. Prices start at $999. Their prices are the lowest currently available for new 13ā€³ M3 MacBook Airs among... Read more
Sunday Sale: Apple iPad Magic Keyboards for 1...
Walmart has Apple Magic Keyboards for 12.9ā€³ iPad Pros, in Black, on sale for $150 off MSRP on their online store. Sale price for online orders only, in-store price may vary. Order online and choose... Read more
Apple Watch Ultra 2 now available at Apple fo...
Apple has, for the first time, begun offering Certified Refurbished Apple Watch Ultra 2 models in their online store for $679, or $120 off MSRP. Each Watch includes Appleā€™s standard one-year warranty... Read more
AT&T has the iPhone 14 on sale for only $...
AT&T has the 128GB Apple iPhone 14 available for only $5.99 per month for new and existing customers when you activate unlimited service and use AT&Tā€™s 36 month installment plan. The fine... Read more
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

Jobs Board

*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
IT Systems Engineer ( *Apple* Platforms) - S...
IT Systems Engineer ( Apple Platforms) at SpaceX Hawthorne, CA SpaceX was founded under the belief that a future where humanity is out exploring the stars is Read more
Nurse Anesthetist - *Apple* Hill Surgery Ce...
Nurse Anesthetist - Apple Hill Surgery Center Location: WellSpan Medical Group, York, PA Schedule: Full Time Sign-On Bonus Eligible Remote/Hybrid Regular Apply Now Read more
Housekeeper, *Apple* Valley Village - Cassi...
Apple Valley Village Health Care Center, a senior care campus, is hiring a Part-Time Housekeeper to join our team! We will train you for this position! In this role, Read more
Sublease Associate Optometrist- *Apple* Val...
Sublease Associate Optometrist- Apple Valley, CA- Target Optical Date: Apr 20, 2024 Brand: Target Optical Location: Apple Valley, CA, US, 92307 **Requisition Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.