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

Whitethorn Games combines two completely...
If you have ever gone fishing then you know that it is a lesson in patience, sitting around waiting for a bite that may never come. Well, that's because you have been doing it wrong, since as Whitehorn Games now demonstrates in new release Skate... | Read more »
Call of Duty Warzone is a Waiting Simula...
It's always fun when a splashy multiplayer game comes to mobile because they are few and far between, so I was excited to see the notification about Call of Duty: Warzone Mobile (finally) launching last week and wanted to try it out. As someone who... | Read more »
Albion Online introduces some massive ne...
Sandbox Interactive has announced an upcoming update to its flagship MMORPG Albion Online, containing massive updates to its existing guild Vs guild systems. Someone clearly rewatched the Helms Deep battle in Lord of the Rings and spent the next... | Read more »
Chucklefish announces launch date of the...
Chucklefish, the indie London-based team we probably all know from developing Terraria or their stint publishing Stardew Valley, has revealed the mobile release date for roguelike deck-builder Wildfrost. Developed by Gaziter and Deadpan Games, the... | Read more »
Netmarble opens pre-registration for act...
It has been close to three years since Netmarble announced they would be adapting the smash series Solo Leveling into a video game, and at last, they have announced the opening of pre-orders for Solo Leveling: Arise. [Read more] | Read more »
PUBG Mobile celebrates sixth anniversary...
For the past six years, PUBG Mobile has been one of the most popular shooters you can play in the palm of your hand, and Krafton is celebrating this milestone and many years of ups by teaming up with hit music man JVKE to create a special song for... | Read more »
ASTRA: Knights of Veda refuse to pump th...
In perhaps the most recent example of being incredibly eager, ASTRA: Knights of Veda has dropped its second collaboration with South Korean boyband Seventeen, named so as it consists of exactly thirteen members and a video collaboration with Lee... | Read more »
Collect all your cats and caterpillars a...
If you are growing tired of trying to build a town with your phone by using it as a tiny, ineffectual shover then fear no longer, as Independent Arts Software has announced the upcoming release of Construction Simulator 4, from the critically... | Read more »
Backbone complete its lineup of 2nd Gene...
With all the ports of big AAA games that have been coming to mobile, it is becoming more convenient than ever to own a good controller, and to help with this Backbone has announced the completion of their 2nd generation product lineup with their... | Read more »
Zenless Zone Zero opens entries for its...
miHoYo, aka HoYoverse, has become such a big name in mobile gaming that it's hard to believe that arguably their flagship title, Genshin Impact, is only three and a half years old. Now, they continue the road to the next title in their world, with... | Read more »

Price Scanner via MacPrices.net

B&H has Apple’s 13-inch M2 MacBook Airs o...
B&H Photo has 13″ MacBook Airs with M2 CPUs and 256GB of storage in stock and on sale for up to $150 off Apple’s new MSRP, starting at only $849. Free 1-2 day delivery is available to most US... Read more
M2 Mac minis on sale for $100-$200 off MSRP,...
B&H Photo has Apple’s M2-powered Mac minis back in stock and on sale today for $100-$200 off MSRP. Free 1-2 day shipping is available for most US addresses: – Mac mini M2/256GB SSD: $499, save $... Read more
Mac Studios with M2 Max and M2 Ultra CPUs on...
B&H Photo has standard-configuration Mac Studios with Apple’s M2 Max & Ultra CPUs in stock today and on Easter sale for $200 off MSRP. Their prices are the lowest available for these models... Read more
Deal Alert! B&H Photo has Apple’s 14-inch...
B&H Photo has new Gray and Black 14″ M3, M3 Pro, and M3 Max MacBook Pros on sale for $200-$300 off MSRP, starting at only $1399. B&H offers free 1-2 day delivery to most US addresses: – 14″ 8... Read more
Department Of Justice Sets Sights On Apple In...
NEWS – The ball has finally dropped on the big Apple. The ball (metaphorically speaking) — an antitrust lawsuit filed in the U.S. on March 21 by the Department of Justice (DOJ) — came down following... Read more
New 13-inch M3 MacBook Air on sale for $999,...
Amazon has Apple’s new 13″ M3 MacBook Air on sale for $100 off MSRP for the first time, now just $999 shipped. Shipping is free: – 13″ MacBook Air (8GB RAM/256GB SSD/Space Gray): $999 $100 off MSRP... Read more
Amazon has Apple’s 9th-generation WiFi iPads...
Amazon has Apple’s 9th generation 10.2″ WiFi iPads on sale for $80-$100 off MSRP, starting only $249. Their prices are the lowest available for new iPads anywhere: – 10″ 64GB WiFi iPad (Space Gray or... Read more
Discounted 14-inch M3 MacBook Pros with 16GB...
Apple retailer Expercom has 14″ MacBook Pros with M3 CPUs and 16GB of standard memory discounted by up to $120 off Apple’s MSRP: – 14″ M3 MacBook Pro (16GB RAM/256GB SSD): $1691.06 $108 off MSRP – 14... Read more
Clearance 15-inch M2 MacBook Airs on sale for...
B&H Photo has Apple’s 15″ MacBook Airs with M2 CPUs (8GB RAM/256GB SSD) in stock today and on clearance sale for $999 in all four colors. Free 1-2 delivery is available to most US addresses.... Read more
Clearance 13-inch M1 MacBook Airs drop to onl...
B&H has Apple’s base 13″ M1 MacBook Air (Space Gray, Silver, & Gold) in stock and on clearance sale today for $300 off MSRP, only $699. Free 1-2 day shipping is available to most addresses in... Read more

Jobs Board

Medical Assistant - Surgical Oncology- *Apple...
Medical Assistant - Surgical Oncology- Apple Hill Location: WellSpan Medical Group, York, PA Schedule: Full Time Sign-On Bonus Eligible Remote/Hybrid Regular Apply Read more
Omnichannel Associate - *Apple* Blossom Mal...
Omnichannel Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Cashier - *Apple* Blossom Mall - JCPenney (...
Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Mall Read more
Operations Associate - *Apple* Blossom Mall...
Operations Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Business Analyst | *Apple* Pay - Banco Popu...
Business Analyst | Apple PayApply now " Apply now + Apply Now + Start applying with LinkedIn Start + Please wait Date:Mar 19, 2024 Location: San Juan-Cupey, PR Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.