Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Clipboard.c
/* |
File: Clipboard.c |
Contains: Clipboard support for simple text application. |
Version: SimpleText 1.4 or later |
** Copyright 1993-1996 Apple Computer. All rights reserved. |
** |
** You may incorporate this sample code into your applications without |
** restriction, though the sample code has been provided "AS IS" and the |
** responsibility for its operation is 100% yours. However, what you are |
** not permitted to do is to redistribute the source as "DSC Sample Code" |
** after having made changes. If you're going to re-distribute the source, |
** we require that you make it clear in the source that the code was |
** descended from Apple Sample Code, but that you've made changes. |
*/ |
#include "MacIncludes.h" |
#include "Clipboard.h" |
// -------------------------------------------------------------------------------------------------------------- |
// GLOBALS FOR THIS FILE ONLY |
// -------------------------------------------------------------------------------------------------------------- |
static Handle gScrapHandle; |
static long gCurrentOffset; |
static QDProcsPtr gSavedProcs; |
static QDProcs gMyProcs; |
static CQDProcs gMyColorProcs; |
// -------------------------------------------------------------------------------------------------------------- |
// INTERNAL ROUTINES |
// -------------------------------------------------------------------------------------------------------------- |
static pascal void GetPICTData(Ptr dataPtr, short byteCount) |
/* |
replacement for the QuickDraw bottleneck routine |
*/ |
{ |
long longCount = byteCount; |
BlockMoveData((*gScrapHandle)+gCurrentOffset, dataPtr, longCount); |
gCurrentOffset += longCount; |
} // GetPICTData |
#if GENERATINGCFM |
static RoutineDescriptor gGetPICTDataRD = BUILD_ROUTINE_DESCRIPTOR(uppQDGetPicProcInfo, GetPICTData); |
static QDGetPicUPP gGetPICTData = &gGetPICTDataRD; |
#else |
static QDGetPicUPP gGetPICTData = NewQDGetPicProc(GetPICTData); |
#endif |
// -------------------------------------------------------------------------------------------------------------- |
static OSErr DrawPictureFromHandleAndOffset( |
Rect * pWhereToDraw, // draw picture at this location |
Handle sourceHandle, // handle containing data |
long sourceOffset) // offset within handle to start at |
{ |
OSErr anErr; |
Rect whereToDraw = *pWhereToDraw; |
PicHandle tempPict = (PicHandle) NewHandle(sizeof(Picture)); |
anErr = MemError(); |
nrequire(anErr, FailedNewHandle); |
// calculate the rectangle in which to draw, save the picture header into |
// our handle |
{ |
PicPtr pPicture; |
pPicture = (PicPtr)((*sourceHandle) + sourceOffset); |
whereToDraw.right = whereToDraw.left + pPicture->picFrame.right - pPicture->picFrame.left; |
whereToDraw.bottom = whereToDraw.top + pPicture->picFrame.bottom - pPicture->picFrame.top; |
BlockMoveData((Ptr)pPicture, (Ptr)*tempPict, sizeof(Picture)); |
} |
// store into globals for our GetPicProc in preparation for the draw |
gScrapHandle = sourceHandle; |
gCurrentOffset = sourceOffset + sizeof(Picture); |
// install our GetPic proc |
if (gMachineInfo.theEnvirons.hasColorQD) |
SetStdCProcs(&gMyColorProcs); |
else |
SetStdProcs(&gMyProcs); |
gMyProcs.getPicProc = gGetPICTData; |
gMyColorProcs.getPicProc = gGetPICTData; |
gSavedProcs = (*qd.thePort).grafProcs; |
if (gMachineInfo.theEnvirons.hasColorQD) |
(*qd.thePort).grafProcs = (QDProcsPtr)&gMyColorProcs; |
else |
(*qd.thePort).grafProcs = &gMyProcs; |
// Draw the picture |
DrawPicture(tempPict, &whereToDraw); |
// remove our GetPic proc |
(*qd.thePort).grafProcs = gSavedProcs; |
DisposeHandle((Handle)tempPict); |
// FALL THROUGH EXCEPTION HANDLING |
FailedNewHandle: |
return anErr; |
} // DrawPictureFromHandleAndOffset |
// -------------------------------------------------------------------------------------------------------------- |
// OOP INTERFACE ROUTINES |
// -------------------------------------------------------------------------------------------------------------- |
static OSErr ClipboardUpdateWindow(WindowRef pWindow, WindowDataPtr pData) |
{ |
#pragma unused (pData) |
OSErr anErr; |
FontInfo theInfo; |
long scrapResult; |
long offset; |
ResType validScrapType = '????'; |
Rect topAreaRect; |
RgnHandle oldClip = NewRgn(); |
// clear out any data that was there before |
GetClip(oldClip); |
EraseRect(&GetWindowPort(pWindow)->portRect); |
// get that scrap! |
anErr = LoadScrap(); |
nrequire(anErr, LoadScrap); |
// figure out the scrap type and offset |
{ |
short i = 0; |
ResType scrapTypes[] = {'TEXT', 'PICT', '????'}; |
while (scrapTypes[i] != '????') |
{ |
scrapResult = GetScrap(nil, scrapTypes[i], &offset); |
if (scrapResult > 0) |
{ |
validScrapType = scrapTypes[i]; |
break; |
} |
++i; |
} |
} |
// setup for the drawing |
TextFont(applFont); |
TextSize(9); |
GetFontInfo(&theInfo); |
// caclulate our area at the top to say what type of contents the scrap is |
topAreaRect = GetWindowPort(pWindow)->portRect; |
topAreaRect.bottom = topAreaRect.top + theInfo.ascent + theInfo.descent + theInfo.leading * 2 + 2; |
// draw two lines under the area to separate it from the rest of the window |
MoveTo(topAreaRect.left, topAreaRect.bottom - 2); |
Line(topAreaRect.right - topAreaRect.left, 0); |
Move(0, 2); |
Line(-(topAreaRect.right - topAreaRect.left), 0); |
// draw a string describing the contents |
{ |
Str255 theString; |
switch (validScrapType) |
{ |
case 'PICT': |
GetIndString(theString, kClipboardStrings, iClipboardPICT); |
break; |
case 'TEXT': |
GetIndString(theString, kClipboardStrings, iClipboardText); |
break; |
default: |
if (InfoScrap()->scrapCount == 0) |
GetIndString(theString, kClipboardStrings, iClipboardNone); |
else |
GetIndString(theString, kClipboardStrings, iClipboardUnknown); |
break; |
} |
MoveTo(topAreaRect.left + 4, topAreaRect.bottom - 4); |
DrawString(theString); |
} |
// calculate the part *not* in our top area |
topAreaRect.top = topAreaRect.bottom+1; |
topAreaRect.bottom = GetWindowPort(pWindow)->portRect.bottom; |
// remember the scrap count -- if it changes, we do an update! |
((ClipboardDataPtr)pData)->scrapCount = InfoScrap()->scrapCount; |
// now, draw the contents, if we have a legal type to use |
{ |
Rect clipArea = topAreaRect; |
Handle scrapHandle = InfoScrap()->scrapHandle; |
clipArea.right -= 15; |
clipArea.bottom -= 15; |
ClipRect(&clipArea); |
switch (validScrapType) |
{ |
case 'PICT': |
DrawPictureFromHandleAndOffset(&clipArea, |
scrapHandle, offset); |
break; |
case 'TEXT': |
{ |
char oldState; |
oldState = HGetState(scrapHandle); |
HLock(scrapHandle); |
clipArea.right -= 15; |
clipArea.bottom -= 15; |
TETextBox(*scrapHandle+offset, scrapResult, &clipArea, teJustLeft); |
} |
break; |
} |
} |
// finally draw the grow icon, but omit our top area rect from the drawing |
ClipRect(&topAreaRect); |
DrawGrowIcon(pWindow); |
SetClip(oldClip); |
DisposeRgn(oldClip); |
UnloadScrap(); |
// FALL THROUGH EXCEPTION HANDLING |
LoadScrap: |
return anErr; |
} // ClipboardUpdateWindow |
// -------------------------------------------------------------------------------------------------------------- |
static Boolean ClipboardFilterEvent(WindowRef pWindow, WindowDataPtr pData, EventRecord *pEvent) |
{ |
// Force an update on scrap changes during activate/deactivate. |
switch (pEvent->what) |
{ |
case nullEvent: |
case activateEvt: |
if (LoadScrap() == noErr) |
{ |
PScrapStuff pScrap = InfoScrap(); |
if (pScrap->scrapCount != ((ClipboardDataPtr)pData)->scrapCount) |
{ |
GrafPtr pPort = (GrafPtr)GetWindowPort(pWindow); |
SetPort(pPort); |
InvalRect(&pPort->portRect); |
} |
} |
break; |
// Follow the HI guidelines and hide the clipboard when we are suspended. |
case osEvt: |
if (((pEvent->message >> 24) & 0x0FF) == suspendResumeMessage) |
{ |
if((pEvent->message & resumeFlag)==0) // suspending |
{ |
HideWindow(pWindow); |
pWindow = FrontWindow(); |
if (pWindow) |
HiliteWindow(pWindow, false); |
} |
else // resuming |
ShowWindow(pWindow); |
} |
break; |
} // switch(what) |
return false; |
} // ClipboardFilterEvent |
// -------------------------------------------------------------------------------------------------------------- |
static OSErr ClipboardKeyEvent(WindowRef pWindow, WindowDataPtr pData, EventRecord *pEvent, Boolean isMotionKey) |
{ |
#pragma unused(pWindow, pData, pEvent, isMotionKey) |
return noErr; |
} // ClipboardKeyEvent |
// -------------------------------------------------------------------------------------------------------------- |
static OSErr ClipboardGetBalloon(WindowRef pWindow, WindowDataPtr pData, |
Point *localMouse, short * returnedBalloonIndex, Rect *returnedRectangle) |
{ |
#pragma unused (pWindow, pData, localMouse, returnedRectangle) |
*returnedBalloonIndex = iNoBalloon; |
return noErr; |
} // ClipboardGetBalloon |
// -------------------------------------------------------------------------------------------------------------- |
static OSErr ClipboardGetDocumentRect(WindowRef pWindow, WindowDataPtr pData, |
LongRect * documentRectangle, Boolean forGrow) |
{ |
#pragma unused (pWindow, pData, forGrow) |
Rect maxSize = (**GetGrayRgn()).rgnBBox; |
RectToLongRect(&maxSize, documentRectangle); |
return noErr; |
} // ClipboardGetDocumentRect |
// -------------------------------------------------------------------------------------------------------------- |
static OSErr ClipboardCloseWindow(WindowRef pWindow, void* refCon) |
{ |
#pragma unused(pWindow,refCon) |
ChangeCommandName(cShowClipboard, kClipboardStrings, iClipboardShow); |
UnloadScrap(); |
return noErr; |
} // ClipboardCloseWindow |
// -------------------------------------------------------------------------------------------------------------- |
static OSErr ClipboardMakeWindow(WindowRef pWindow, WindowDataPtr pData) |
{ |
#pragma unused (pWindow) |
pData->hasGrow = true; |
pData->pFilterEvent = (FilterEventProc) ClipboardFilterEvent; |
pData->pKeyEvent = (KeyEventProc) ClipboardKeyEvent; |
pData->pGetBalloon = (GetBalloonProc) ClipboardGetBalloon; |
pData->pUpdateWindow = (UpdateWindowProc) ClipboardUpdateWindow; |
pData->pGetDocumentRect = (GetDocumentRectProc) ClipboardGetDocumentRect; |
pData->pCloseWindow = (CloseWindowProc) ClipboardCloseWindow; |
pData->contentRect.right = pData->contentRect.left + |
qd.screenBits.bounds.right - qd.screenBits.bounds.left - 96; |
pData->contentRect.bottom = pData->contentRect.top + 150; |
MoveWindow(pWindow, |
qd.screenBits.bounds.left + 4, |
qd.screenBits.bounds.bottom - 154, false); |
ChangeCommandName(cShowClipboard, kClipboardStrings, iClipboardHide); |
return noErr; |
} // ClipboardMakeWindow |
// -------------------------------------------------------------------------------------------------------------- |
OSErr ClipboardPreflightWindow(PreflightPtr pPreflightData) |
{ |
pPreflightData->resourceID = kClipboardWindowID; |
pPreflightData->continueWithOpen = true; |
pPreflightData->makeProcPtr = ClipboardMakeWindow; |
pPreflightData->storageSize = sizeof(ClipboardDataRecord); |
return noErr; |
} // ClipboardPreflightWindow |
// -------------------------------------------------------------------------------------------------------------- |
void ClipboardGetFileTypes(OSType * pFileTypes, OSType * pDocumentTypes, short * numTypes) |
{ |
#pragma unused (pFileTypes, pDocumentTypes, numTypes) |
} // ClipboardGetFileTypes |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14