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.
MovieBrowser.c
/* |
File: MovieBrowser.c |
Written by: Peter Hoddie |
Copyright: © 1992-1994 by Apple Computer, Inc., all rights reserved. |
Change History (most recent first): |
<1> 12/8/94 khs changed the format of the file to the new look and feel |
*/ |
// INCLUDES |
#include <Aliases.h> |
#include <AppleEvents.h> |
#include <Dialogs.h> |
#include <Errors.h> |
#include <Events.h> |
#include <Memory.h> |
#include <Movies.h> |
#include <ToolUtils.h> |
#include <LowMem.h> |
#include <SegLoad.h> |
#include <Fonts.h> |
#include <GestaltEqu.h> |
#include <Devices.h> |
#include <Resources.h> |
// STRUCTURES |
typedef struct Document { |
WindowPtr w; |
Movie m; |
MovieController mc; |
short page; |
short pageCount; |
short curResID; |
short resRef; |
Track firstTextTrack; |
FSSpec fss; |
Rect movieArea; |
Rect scrollArea; |
Boolean noButtons; |
Boolean showController; |
Rect sprocketsRectTop; |
Rect sprocketsRectBottom; |
Rect scrollAndSprocketsArea; |
long scrollOffset; |
long scrollPhaseShift; |
RGBColor backgroundColor; |
Rect thumbnailSize; |
TimeValue **lastMovieTime; |
Handle names; |
PicHandle titleBackground; |
Rect titleRect; |
Rect titleArea; |
Str255 movieName; |
Point titlePlace; |
short lastPageClick; |
unsigned long lastPageClickTime; |
} Document, *DocumentPtr; |
typedef long (*DocFunction)(DocumentPtr d, void *refCon); |
// FUNCTION PROTOTYPES |
void doAnAlert(StringPtr s, short err); |
void colorMenus(void); |
Boolean doMenuItem(long selection); |
void DoContentClick(DocumentPtr d, Point where, unsigned long clickTime); |
DocumentPtr OpenDocument(FSSpec *fss); |
void CloseDocument(DocumentPtr d); |
void GoToPage(DocumentPtr d, short pageNum); |
DocumentPtr GetWindowDocument(WindowPtr w); |
long ForEachDocument(DocFunction df, void *refCon); |
long TestOneEvent(DocumentPtr d, EventRecord *e); |
long IdleOneDocument(DocumentPtr d, void *refCon); |
PicHandle GetArrow(DocumentPtr d, Boolean right, Rect *bounds); |
void GetScrollArea(DocumentPtr d, Rect *bounds); |
void ActivateDocument(DocumentPtr d); |
void UpdateDocument(DocumentPtr d); |
void OpenFinderDocs(void); |
OSErr MissedAEParameters (AppleEvent *message); |
pascal OSErr OpenDocMessage(AppleEvent *message, AppleEvent *reply, long refcon); |
pascal OSErr QuitAppMessage(AppleEvent *message, AppleEvent *reply, long refcon); |
// GLOBALS |
short gAppResFile; |
Boolean gDone = false; |
GWorldPtr gSprockets = 0; |
Str255 gLastSearchText; |
unsigned long gLastWNETime; |
Boolean gInBackground = false; |
long gSysVersion = 0; |
// DEFINES |
// don't give the system too much time... |
#define kWNEInterval (90) |
#define kBetweenThumbSize (2) |
// FUNCTIONS |
void doAnAlert(StringPtr s, short err) |
{ |
Str31 s1; |
NumToString(err, s1); |
ParamText(s, err ? s1 : 0, 0, 0); |
Alert(128, 0); |
} |
void colorMenus(void) |
{ |
MenuHandle mh; |
short count, i; |
DocumentPtr d = GetWindowDocument(FrontWindow()); |
mh = GetMHandle(129); |
DisableItem(mh, 2); |
if (FrontWindow()) EnableItem(mh, 2); |
mh = GetMHandle(130); |
count = CountMItems(mh); |
for (i = 1; i <= count; i++) |
CheckItem(mh, i, d && (i == (d->page + 1))); |
mh = GetMHandle(131); |
DisableItem(mh, 1); |
DisableItem(mh, 3); |
DisableItem(mh, 4); |
DisableItem(mh, 5); |
DisableItem(mh, 6); |
DisableItem(mh, 8); |
DisableItem(mh, 9); |
DisableItem(mh, 11); |
if (d) { |
if (d->firstTextTrack) { |
EnableItem(mh, 8); |
if (gLastSearchText[0]) |
EnableItem(mh, 9); |
} |
if (d->m) |
EnableItem(mh, 4); |
EnableItem(mh, 11); |
CheckItem(mh, 11, d->showController); |
} |
} |
Boolean doMenuItem(long selection) |
{ |
short menu = HiWord(selection); |
short item = LoWord(selection); |
Boolean done = false; |
DocumentPtr d = GetWindowDocument(FrontWindow()); |
switch (menu) { |
case 128: |
if (item > 2) { |
Str255 daName; |
GetItem(GetMHandle(128), item, daName); |
OpenDeskAcc(daName); |
} |
else { |
short item = 0; |
short saveRes = CurResFile(); |
DialogPtr d; |
short kind; |
Handle h; |
Rect r; |
UseResFile(gAppResFile); |
d = GetNewDialog(129, nil, (WindowPtr)-1); |
SetPort(d); |
GetDItem(d, 1, &kind, &h, &r); |
PenSize(3,3); |
InsetRect(&r,-4,-4); |
FrameRoundRect(&r,16,16); |
while (d && (item != 1)) |
ModalDialog(nil, &item); |
UseResFile(saveRes); |
if (d) DisposDialog(d); |
} |
break; |
case 129: |
switch (item) { |
case 1: { |
StandardFileReply reply; |
OSType docType = 'Dal'; |
StandardGetFilePreview(nil, 1, &docType, &reply); |
if (reply.sfGood) |
OpenDocument(&reply.sfFile); |
} |
break; |
case 2: CloseDocument(d); |
break; |
case 4: done = true; |
break; |
} |
break; |
case 130: |
GoToPage(GetWindowDocument(FrontWindow()), item - 1); |
break; |
case 131: |
switch (item) { |
case 4: if (d && d->m) |
PutMovieOnScrap(d->m, DoTheRightThing); |
break; |
case 8: { |
DialogPtr dlg = GetNewDialog(130, nil, (WindowPtr)-1); |
short kind; |
Handle h; |
Rect r; |
short item = 0; |
Str255 str; |
ModalFilterProcPtr filter = nil; |
if (!dlg) break; |
// set up some dialog manager slime if not System 7 |
if (gSysVersion < 7 ) { |
SetDialogDefaultItem(dlg, 1); |
SetDialogCancelItem(dlg, 2); |
SetDialogTracksCursor(dlg, true); |
GetStdFilterProc(&filter); |
} |
GetDItem(dlg, 4, &kind, &h, &r); |
SetIText(h, gLastSearchText); |
SelIText(dlg, 4, 0, 32767); |
while ((item != 1) && (item != 2)) |
ModalDialog(filter, &item); |
GetIText(h, str); |
DisposDialog(dlg); |
if (item == 1 && str[0]) { |
BlockMove(str, gLastSearchText, sizeof(gLastSearchText)); |
goto doSearch; |
} |
break; |
} |
case 9: { |
TimeValue newTime; |
OSErr err; |
MediaHandler textHandler; |
long textOffset; |
doSearch: |
// text media handler really wants lower case letters, so make sure it gets 'em |
if (gSysVersion >= 7) |
LowerText((Ptr)&gLastSearchText[1], gLastSearchText[0]); |
else { |
short i = 0; |
while (i++ <= gLastSearchText[0]) { |
char c = gLastSearchText[i]; |
if ((c >= 'A') && (c <= 'Z')) |
gLastSearchText[i] -= 32; |
} |
} |
textHandler = GetMediaHandler(GetTrackMedia(d->firstTextTrack)); |
err = FindNextText(textHandler, (Ptr)&gLastSearchText[1], gLastSearchText[0], |
findTextWrapAround, GetMovieTime(d->m, nil), |
&newTime, nil, &textOffset); |
if (!err && (newTime != -1)) { |
TimeRecord tr; |
RGBColor rgb; |
tr.value.lo = newTime; |
tr.value.hi = 0; |
tr.scale = GetMovieTimeScale(d->m); |
tr.base = 0; |
MCDoAction(d->mc, mcActionGoToTime, &tr); |
rgb = (**((GrafVars **)((CGrafPtr)d->w)->grafVars)).rgbHiliteColor; |
HiliteTextSample(textHandler, newTime, textOffset, |
textOffset + gLastSearchText[0], &rgb); |
} |
else |
SysBeep(1); |
} |
break; |
case 11: { |
d->showController = !d->showController; |
MCSetVisible(d->mc, d->showController); |
break; |
} |
break; |
} |
} |
HiliteMenu(0); |
return done; |
} |
DocumentPtr OpenDocument(FSSpec *fss) |
{ |
OSErr err; |
DocumentPtr d; |
Rect r; |
Point center; |
short resID; |
Handle h; |
d = (DocumentPtr)NewPtrClear(sizeof(Document)); |
err = MemError(); |
if (err != noErr) goto bail; |
d->fss = *fss; |
d->resRef = FSpOpenResFile(fss, fsRdPerm); |
if ((d->resRef == -1) || ResError()) { |
err = resNotFound; |
d->resRef = 0; |
goto bail; |
} |
d->lastPageClick = -1; |
d->names = NewHandle(0); |
// count the pages, and rememeber their names |
resID = 128; |
SetResLoad(false); |
do { |
Handle r; |
short id; |
OSType rt; |
Str255 name; |
r = Get1Resource(rAliasType, resID++); |
if (r != NULL) |
d->pageCount++; |
else |
break; |
// remember the name |
GetResInfo(r, &id, &rt, name); |
PtrAndHand(name, d->names, name[0] + 1); |
err = MemError(); |
if (err != noErr) goto bail; |
} while (true); |
SetResLoad(true); |
// make the window |
d->w = GetNewCWindow(128, nil, (WindowPtr)-1); |
if (!d->w) { |
err = memFullErr; |
goto bail; |
} |
SetWTitle(d->w, fss->name); |
TextFont(GetSysFont()); |
// get back color |
h = Get1Resource('RGB ', 128); |
if (h != NULL) { |
d->backgroundColor = **(RGBColor **)h; |
ReleaseResource(h); |
} |
else { |
short saveRes = CurResFile(); |
UseResFile(gAppResFile); |
d->backgroundColor = **(RGBColor **)Get1Resource('RGB ', 128); |
UseResFile(saveRes); |
} |
// pick up first thumbnail pict for measurement |
h = Get1Resource('PICT', 128); |
if (!h) { |
err = resNotFound; |
goto bail; |
} |
d->thumbnailSize = (**(PicHandle)h).picFrame; |
OffsetRect(&d->thumbnailSize, -d->thumbnailSize.left, -d->thumbnailSize.top); |
d->thumbnailSize.right += kBetweenThumbSize; |
// show a controller? |
d->showController = false; |
h = Get1Resource('MCmc', 128); |
if (h) { |
d->showController = **h; |
ReleaseResource(h); |
} |
// make page time table |
d->lastMovieTime = (TimeValue **)NewHandleClear(d->pageCount * sizeof(TimeValue)); |
err = MemError(); |
if (err != noErr) goto bail; |
d->movieArea = **(Rect **)GetResource('RECT', 128); |
ReleaseResource(GetResource('RECT', 128)); |
OffsetRect(&d->movieArea, -d->movieArea.left, -d->movieArea.top); |
// figure out what to use for title background |
d->titleBackground = (PicHandle)Get1Resource('PICT', 1048); |
if (!d->titleBackground) { |
short saveRes = CurResFile(); |
UseResFile(gAppResFile); |
d->titleBackground = (PicHandle)GetPicture(1048); |
UseResFile(saveRes); |
} |
LoadResource((Handle)d->titleBackground); |
r = (**d->titleBackground).picFrame; |
OffsetRect(&r, -r.left, -r.top); |
OffsetRect(&r, (d->movieArea.right / 2) - (r.right / 2), 0); |
d->titleRect = r; |
OffsetRect(&d->titleRect, 0, (d->titleRect.bottom - d->titleRect.top) / 3); |
InsetRect(&r, 0, -((d->titleRect.bottom - d->titleRect.top) / 3)); |
d->titleArea = r; |
OffsetRect(&d->movieArea, 0, d->titleArea.bottom); |
SizeWindow(d->w, d->movieArea.right, |
d->movieArea.bottom + d->thumbnailSize.bottom + (gSprockets->portRect.bottom * 2), false); |
// figure out how to keep things centered |
GetScrollArea(d, &r); |
d->scrollArea = r; |
OffsetRect(&r, -r.left, -r.top); |
d->scrollPhaseShift = (d->thumbnailSize.right) - (r.right % d->thumbnailSize.right)/2; |
// calculate sprockets rect |
d->sprocketsRectTop = d->scrollArea; |
d->sprocketsRectTop.bottom = d->scrollArea.top; |
d->sprocketsRectTop.top -= gSprockets->portRect.bottom; |
d->sprocketsRectBottom = d->scrollArea; |
d->sprocketsRectBottom.top = d->scrollArea.bottom; |
d->sprocketsRectBottom.bottom += gSprockets->portRect.bottom; |
UnionRect(&d->scrollArea, &d->sprocketsRectTop, &d->scrollAndSprocketsArea); |
UnionRect(&d->sprocketsRectBottom, &d->scrollAndSprocketsArea, &d->scrollAndSprocketsArea); |
SetWRefCon(d->w, (long)d); |
SetPort(d->w); |
r = d->w->portRect; |
GetBestDeviceRect(nil, &r); |
if (r.top == 0) r.top += GetMBarHeight(); |
center.h = (r.left + r.right) >> 1; |
center.v = (r.top + r.bottom) >> 1; |
r.left = center.h - (d->w->portRect.right >> 1); |
r.right = r.left + d->w->portRect.right; |
r.top = center.v - (d->w->portRect.bottom >> 1); |
r.bottom = r.top + d->w->portRect.bottom; |
MoveWindow(d->w, r.left, r.top, false); |
AlignWindow(d->w, false, &d->movieArea, nil); |
ShowWindow(d->w); |
GoToPage(d, d->page); |
bail: |
if (err) CloseDocument(d); |
return d; |
} |
void CloseDocument(DocumentPtr d) |
{ |
if (!d) return; |
if (d->resRef) CloseResFile(d->resRef); |
if (d->mc) DisposeMovieController(d->mc); |
if (d->lastMovieTime) DisposHandle((Handle)d->lastMovieTime); |
if (d->names) DisposHandle(d->names); |
DisposeMovie(d->m); |
if (d->w) DisposeWindow(d->w); |
DisposPtr((Ptr)d); |
ActivateDocument(0); // clear out the movies menu |
} |
DocumentPtr GetWindowDocument(WindowPtr w) |
{ |
if (!w) return nil; |
if (((WindowPeek)w)->windowKind == userKind) |
return (DocumentPtr)GetWRefCon(w); |
else |
return nil; |
} |
void GoToPage(DocumentPtr d, short pageNum) |
{ |
OSErr err; |
short resID; |
Movie newMovie = nil; |
Point where = {0,0}; |
Rect r; |
short saveRes; |
FSSpec movieFile; |
Boolean whoCares; |
short movieResRef; |
AliasHandle alias; |
RgnHandle rgn; |
short trashID; |
OSType trackType; |
if (pageNum < 0) |
pageNum = d->pageCount - 1; |
else |
pageNum = pageNum % d->pageCount; |
resID = pageNum + 128; |
if (resID == d->curResID) return; |
// resolve alias to the file |
saveRes = CurResFile(); |
UseResFile(d->resRef); |
alias = (AliasHandle)Get1Resource(rAliasType, resID); |
UseResFile(saveRes); |
if (!alias) return; |
err = ResolveAlias((gSysVersion >= 7) ? &d->fss : 0, alias, &movieFile, &whoCares); |
GetResInfo((Handle)alias, &trashID, &trackType, d->movieName); |
ReleaseResource((Handle)alias); |
if (err) return; |
// get the movie |
SetCursor(*GetCursor(watchCursor)); |
OpenMovieFile(&movieFile, &movieResRef, fsRdPerm); |
SetPort(d->w); |
RGBBackColor(&d->backgroundColor); // for erasing |
err = NewMovieFromFile(&newMovie, movieResRef, nil, nil, |
newMovieActive, nil); |
BackColor(whiteColor); |
SetCursor(&qd.arrow); |
CloseMovieFile(movieResRef); |
if (err) return; |
// position new movie a little |
GetMovieBox(newMovie, &r); |
OffsetRect(&r, -r.left, -r.top); |
SetMovieBox(newMovie, &r); |
// restore movie's previous time |
SetMovieTimeValue(newMovie, (*d->lastMovieTime)[pageNum]); |
// position movie in window |
if (d->mc) { |
TimeValue saveTime; |
// invalidate the old one |
rgn = MCGetWindowRgn(d->mc, d->w); |
if (rgn) { |
InvalRgn(rgn); |
DisposeRgn(rgn); |
} |
// store the old movie's time |
saveTime = GetMovieTime(d->m, nil); |
(*d->lastMovieTime)[d->page] = saveTime; |
SetMovieVolume(newMovie, GetMovieVolume(d->m)); // don't lose the volume setting |
// change the movie on the controller |
MCSetVisible(d->mc, false); |
MCSetMovie(d->mc, newMovie, d->w, where); |
MCPositionController(d->mc, &d->movieArea, nil, 0); |
if (d->showController) |
MCSetVisible(d->mc, true); |
} |
else { |
// create a new controller |
d->mc = NewMovieController(newMovie, &d->movieArea, d->showController ? 0 : mcNotVisible); |
if (!d->mc) return; |
MCDoAction(d->mc, mcActionSetKeysEnabled, (void *)true); |
} |
// update state |
DisposeMovie(d->m); |
d->m = newMovie; |
d->curResID = resID; |
d->page = pageNum; |
// look for text |
{ |
long trackCount, i; |
d->firstTextTrack = nil; |
trackCount = GetMovieTrackCount(d->m); |
for (i=1; i<=trackCount; i++) { |
Track t = GetMovieIndTrack(d->m, i); |
OSType mediaType; |
GetMediaHandlerDescription(GetTrackMedia(t), &mediaType, nil, nil); |
if (mediaType == 'text') { |
d->firstTextTrack = t; |
break; |
} |
} |
} |
// invalidate the new one |
rgn = MCGetWindowRgn(d->mc, d->w); |
if (rgn) { |
InvalRgn(rgn); |
DisposeRgn(rgn); |
} |
// update the title variables |
{ |
FontInfo fi; |
short width; |
InvalRect(&d->titleRect); |
GetFontInfo(&fi); |
width = StringWidth(d->movieName); |
d->titlePlace.h = ((d->titleRect.right + d->titleRect.left) / 2) - (width / 2); |
d->titlePlace.v = ((d->titleRect.top + d->titleRect.bottom) / 2) + (fi.ascent / 2); |
} |
} |
void DoContentClick(DocumentPtr d, Point where, unsigned long clickTime) |
{ |
Rect r; |
short scrollValue = 0; |
unsigned long lastTicks = TickCount(); |
long delayTime = 15; |
Rect mustRect = d->w->portRect; |
PicHandle showPict = nil, restorePict = nil; |
if (!d) return; |
SetPort(d->w); |
GlobalToLocal(&where); |
tryAgain: |
// try left arrow |
GetArrow(d, false, &r); |
if (PtInRect(where, &r) && PtInRect(where, &mustRect)) { |
// go left |
if (d->scrollOffset != 0) |
d->scrollOffset--; |
else |
d->scrollOffset = d->pageCount - 1; |
scrollValue = +1; |
mustRect = r; |
restorePict = GetPicture(1024); |
showPict = GetPicture(1026); |
d->lastPageClick = -1; |
goto gotHit; |
} |
// try right arrow |
GetArrow(d, true, &r); |
if (PtInRect(where, &r) && PtInRect(where, &mustRect)) { |
// go right |
if (d->scrollOffset != (d->pageCount - 1)) |
d->scrollOffset++; |
else |
d->scrollOffset = 0; |
scrollValue = -1; |
mustRect = r; |
restorePict = GetPicture(1025); |
showPict = GetPicture(1027); |
goto gotHit; |
} |
r = d->scrollArea; |
if (PtInRect(where, &r) && PtInRect(where, &mustRect)) { |
// clicked on an image |
short internalOffset = (where.h - r.left + d->scrollPhaseShift) / d->thumbnailSize.right; |
Boolean wasIn, inRect; |
Rect clipRect; |
r = d->scrollArea; |
ClipRect(&r); |
clipRect = r; |
r.right = r.left + d->thumbnailSize.right; |
OffsetRect(&r, internalOffset * d->thumbnailSize.right, 0); |
OffsetRect(&r, -d->scrollPhaseShift, 0); |
PenMode(patXor); |
PenPat((ConstPatternParam)&qd.gray); |
PenSize(3, 3); |
FrameRect(&r); |
wasIn = true; |
while (StillDown()) { |
GetMouse(&where); |
inRect = PtInRect(where, &r); |
if (inRect != wasIn) { |
FrameRect(&r); |
wasIn = inRect; |
} |
ClipRect(&d->w->portRect); |
ForEachDocument(IdleOneDocument, nil); |
ClipRect(&clipRect); |
} |
if (wasIn) FrameRect(&r); |
PenNormal(); |
ClipRect(&d->w->portRect); |
if (wasIn) { |
short newPage = (d->scrollOffset + internalOffset) % d->pageCount; |
SInt32 dTime = LMGetDoubleTime(); |
if ( ( d->lastPageClick == newPage) && |
( (d->lastPageClickTime + dTime) >= clickTime) |
) { |
Fixed curRate; |
MCDoAction(d->mc, mcActionGetPlayRate, &curRate); |
if (!curRate) { |
EventRecord whoCares; |
TimeValue t = GetMovieTime(d->m, nil); |
TimeValue movieDur = GetMovieDuration(d->m); |
Fixed preferredRate = GetMoviePreferredRate(d->m); |
if (t == movieDur) t = 0; |
PrerollMovie(d->m, t, preferredRate); |
EventAvail(0, &whoCares); |
EventAvail(0, &whoCares); |
EventAvail(0, &whoCares); |
UpdateDocument(d); |
MCIdle(d->mc); |
MCIdle(d->mc); |
MCIdle(d->mc); |
MCDoAction(d->mc, mcActionPlay, (void *)preferredRate); |
} |
d->lastPageClick = -1; |
d->lastPageClickTime += 500; |
} |
else { |
if (newPage == d->page) { |
MCDoAction(d->mc, mcActionPlay, (void *)0); |
d->lastPageClick = newPage; |
} |
else { |
GoToPage(d, newPage); |
d->lastPageClick = newPage; |
} |
} |
d->lastPageClickTime = clickTime; |
} |
r = mustRect; |
goto gotHit; |
} |
gotHit: |
if (scrollValue) { |
Rect r; |
RgnHandle rgn; |
if (showPict) DrawPicture(showPict, &mustRect); |
r = d->scrollArea; |
rgn = NewRgn(); |
if (rgn != NULL) { |
RGBBackColor(&d->backgroundColor); |
ScrollRect(&r, d->thumbnailSize.right * scrollValue, 0, rgn); |
BackColor(whiteColor); |
InvalRgn(rgn); |
DisposeRgn(rgn); |
UpdateDocument(d); |
ClipRect(&d->w->portRect); |
do { |
ForEachDocument(IdleOneDocument, nil); |
} while (StillDown() && ((unsigned long)TickCount()) < (lastTicks + delayTime)); |
if (StillDown()) { |
lastTicks = TickCount(); |
GetMouse(&where); |
delayTime -= 3; |
if (delayTime < 0) delayTime = 0; |
scrollValue = 0; |
goto tryAgain; |
} |
} |
} |
if (restorePict) DrawPicture(restorePict, &mustRect); |
} |
PicHandle GetArrow(DocumentPtr d, Boolean right, Rect *bounds) |
{ |
PicHandle aPict; |
Rect r; |
if (d->noButtons) { |
SetRect(bounds, 0, 0, 0, 0); |
return GetPicture(1024); |
} |
if (!right) { |
// left arrow |
aPict = GetPicture(1024); |
r = (**aPict).picFrame; |
OffsetRect(&r, -r.left + 5, -r.top); |
OffsetRect(&r, 0, d->w->portRect.bottom - r.bottom); |
} |
else { |
// right arrow |
aPict = GetPicture(1025); |
r = (**aPict).picFrame; |
OffsetRect(&r, -r.left, -r.top); |
OffsetRect(&r, d->w->portRect.right - r.right - 5, d->w->portRect.bottom - r.bottom); |
} |
OffsetRect(&r, 0, -(d->thumbnailSize.bottom/2) + (r.bottom - r.top)/2); |
OffsetRect(&r, 0, -(gSprockets->portRect.bottom * 3)/2); |
if (bounds) *bounds = r; |
return aPict; |
} |
void GetScrollArea(DocumentPtr d, Rect *bounds) |
{ |
Rect r, r1, r2; |
short bottom; |
long maxWidth = (d->pageCount * d->thumbnailSize.right); |
GetArrow(d, false, &r1); |
GetArrow(d, true, &r2); |
bottom = d->w->portRect.bottom - ((gSprockets->portRect.bottom * 3)/2); |
SetRect(&r, r1.right, bottom - d->thumbnailSize.bottom, r2.left, bottom); |
InsetRect(&r, 4, 0); |
if ((r.right - r.left) > maxWidth) { |
// don't wrap |
short center = (r1.right + r2.left) / 2; |
r.right = r.left + maxWidth; |
OffsetRect(&r, -r.left + (center - (r.right - r.left)/2), 0); |
d->noButtons = true; |
} |
*bounds = r; |
} |
void UpdateDocument(DocumentPtr d) |
{ |
PicHandle aPict; |
Rect r; |
RgnHandle rgn = 0; |
Rect scrollArea; |
if (!d) return; |
if (d->mc) |
rgn = MCGetWindowRgn(d->mc, d->w); |
scrollArea = d->scrollArea; |
BeginUpdate(d->w); |
SetPort(d->w); |
ClipRect(&d->w->portRect); |
if (rgn) { |
DiffRgn(d->w->clipRgn, rgn, d->w->clipRgn); |
RectRgn(rgn, &d->scrollAndSprocketsArea); |
DiffRgn(d->w->clipRgn, rgn, d->w->clipRgn); |
RectRgn(rgn, &d->titleRect); |
DiffRgn(d->w->clipRgn, rgn, d->w->clipRgn); |
} |
RGBForeColor(&d->backgroundColor); |
PaintRect(&d->w->portRect); |
ForeColor(blackColor); |
if (rgn) |
UnionRgn(d->w->clipRgn, rgn, d->w->clipRgn); |
// draw the title |
LoadResource((Handle)d->titleBackground); |
HNoPurge((Handle)d->titleBackground); |
DrawPicture(d->titleBackground, &d->titleRect); |
HPurge((Handle)d->titleBackground); |
MoveTo(d->titlePlace.h, d->titlePlace.v); |
TextFont(GetSysFont()); |
DrawString(d->movieName); |
// left arrow |
aPict = GetArrow(d, false, &r); |
DrawPicture(aPict, &r); |
// right arrow |
aPict = GetArrow(d, true, &r); |
DrawPicture(aPict, &r); |
// sprockets |
{ |
Rect r1 = d->sprocketsRectTop; |
Rect r2 = d->sprocketsRectBottom; |
Rect clip; |
short pageOffset; |
UnionRect(&r1, &r2, &clip); |
ClipRect(&clip); |
pageOffset = d->scrollPhaseShift; |
r1.left -= pageOffset; |
r2.left = r1.left; |
r1.right = r1.left + gSprockets->portRect.right; |
r2.right = r1.right; |
while (r1.left < d->scrollArea.right) { |
CopyBits((BitMap *)*gSprockets->portPixMap, &d->w->portBits, &gSprockets->portRect, |
&r1, srcCopy, nil); |
CopyBits((BitMap *)*gSprockets->portPixMap, &d->w->portBits, &gSprockets->portRect, |
&r2, srcCopy, nil); |
OffsetRect(&r1, gSprockets->portRect.right, 0); |
OffsetRect(&r2, gSprockets->portRect.right, 0); |
} |
} |
// thumbnails |
{ |
short firstPage; |
short resID; |
Rect thumbRect; |
short saveRes = CurResFile(); |
r = scrollArea; |
ClipRect(&r); |
firstPage = d->scrollOffset; |
resID = firstPage + 128; |
thumbRect = r; |
thumbRect.right = thumbRect.left + d->thumbnailSize.right; |
OffsetRect(&thumbRect, -d->scrollPhaseShift, 0); |
UseResFile(d->resRef); |
while (thumbRect.left < r.right) { |
Rect whoCares; |
if ((resID - 128) >= d->pageCount) |
resID = 128; |
if (SectRect(&(**d->w->visRgn).rgnBBox, &thumbRect, &whoCares)) { |
PicHandle p = GetPicture(resID); |
MoveTo(thumbRect.left, thumbRect.top); |
LineTo(thumbRect.left, thumbRect.bottom); |
MoveTo(thumbRect.right - 1, thumbRect.top); |
LineTo(thumbRect.right - 1, thumbRect.bottom); |
if (p) { |
Rect r = thumbRect; |
r.right--; |
r.left++; |
LoadResource((Handle)p); |
HNoPurge((Handle)p); |
DrawPicture(p, &r); |
HPurge((Handle)p); |
} |
} |
OffsetRect(&thumbRect, d->thumbnailSize.right, 0); |
resID++; |
} |
UseResFile(saveRes); |
} |
ClipRect(&d->w->portRect); |
// dividing line |
{ |
Rect r = d->scrollAndSprocketsArea; |
RGBColor aColor; |
r.left = 0; |
r.right = d->w->portRect.right; |
r.top -= (gSprockets->portRect.bottom/2) + 2; |
aColor = d->backgroundColor; |
aColor.red -= (aColor.red /6); |
aColor.green -= (aColor.green /6); |
aColor.blue -= (aColor.blue /6); |
RGBForeColor(&aColor); |
MoveTo(r.left, r.top); |
LineTo(r.right, r.top); |
aColor = d->backgroundColor; |
aColor.red += (aColor.red /6); |
aColor.green += (aColor.green /6); |
aColor.blue += (aColor.blue /6); |
RGBForeColor(&aColor); |
MoveTo(r.left, r.top + 1); |
LineTo(r.right, r.top + 1); |
} |
EndUpdate(d->w); |
if (rgn) DisposeRgn(rgn); |
} |
void ActivateDocument(DocumentPtr d) |
{ |
MenuHandle mh = GetMHandle(130); |
short count, index = 0; |
Ptr p; |
char c[2]; |
count = CountMItems(mh); |
while (count--) |
DelMenuItem(mh, count + 1); |
if (!d) return; |
count = d->pageCount; |
HLock(d->names); |
p = *d->names; |
c[0] = 1; |
c[1] = 'e'; |
while (count--) { |
AppendMenu(mh, (StringPtr)&c); |
SetItem(mh, ++index, (StringPtr)p); |
p += (*p + 1); |
} |
HUnlock(d->names); |
} |
long IdleOneDocument(DocumentPtr d, void *refCon) |
{ |
if (d->mc) |
MCIdle(d->mc); |
return 0; |
} |
long ForEachDocument(DocFunction df, void *refCon) |
{ |
WindowPtr w = FrontWindow(); |
long result = 0; |
while (w) { |
DocumentPtr d = GetWindowDocument(w); |
if (d) { |
result = (df)(d, refCon); |
if (result) break; |
} |
w = (WindowPtr)((WindowPeek)w)->nextWindow; |
} |
return result; |
} |
long TestOneEvent(DocumentPtr d, EventRecord *e) |
{ |
if (d->mc && d->m) |
return MCIsPlayerEvent(d->mc, e); |
return 0; |
} |
void OpenFinderDocs(void) |
{ |
short printIt, docCount; // no printing |
CountAppFiles(&printIt, &docCount); |
if (docCount > 0) { |
short j; |
for(j = 1; j <= docCount; j++){ |
FSSpec fss; |
AppFile apfile; |
GetAppFiles(j,&apfile); |
FSMakeFSSpec(apfile.vRefNum, 0, apfile.fName, &fss); |
OpenDocument(&fss); |
ClrAppFiles(j); |
} |
} |
} |
OSErr MissedAEParameters (AppleEvent *message) |
{ |
DescType typeCode; |
Size actualSize; |
OSErr err; |
err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard, |
&typeCode, nil, 0L, &actualSize); |
if (err == errAEDescNotFound) |
return(noErr); |
return(err = noErr ? errAEEventNotHandled : err); |
} |
pascal OSErr OpenDocMessage(AppleEvent *message, AppleEvent *reply, long refcon) |
{ |
FSSpec fss; |
AEDescList docList; |
long index, itemsInList; |
Size actualSize; |
AEKeyword keywd; |
DescType typeCode; |
OSErr err; |
if ((err = AEGetParamDesc(message, keyDirectObject, typeAEList, &docList)) != noErr) |
return(err); |
if ((err = MissedAEParameters(message)) != noErr) |
return(err); |
if ((err = AECountItems(&docList, &itemsInList)) != noErr) |
return(err); |
for (index = 1; index <= itemsInList; index++) |
{ |
if ((err = AEGetNthPtr(&docList, index, typeFSS, &keywd, &typeCode, |
(Ptr)&fss, sizeof(FSSpec), &actualSize)) != noErr) |
break; |
OpenDocument(&fss); |
} |
return(AEDisposeDesc(&docList)); |
} |
pascal OSErr QuitAppMessage(AppleEvent *message, AppleEvent *reply, long refcon) |
{ |
OSErr err; |
if ((err = MissedAEParameters(message)) != noErr) |
return(err); |
gDone = true; |
return(noErr); |
} |
void main(void) |
{ |
OSErr err; |
long response; |
// initialize the world |
InitGraf(&qd.thePort); |
InitFonts(); |
InitWindows(); |
InitMenus(); |
TEInit(); |
InitDialogs(0L); |
InitCursor(); |
MaxApplZone(); |
// find the system version (used later) |
Gestalt(gestaltSystemVersion, &gSysVersion); |
gSysVersion = (gSysVersion >> 8) & 0x0F; |
// must have QuickTime around |
if (Gestalt(gestaltQuickTime, &response)) { |
doAnAlert("\pPlease install QuickTimeª.", 0); |
return; |
} |
if (response < 0x01508000) { |
doAnAlert("\pMovieBrowserª required QuickTime 1.5 or later.", 0); |
return; |
} |
err = EnterMovies(); |
if (err) { |
doAnAlert("\pEnterMovies failed.", err); |
return; |
} |
SetMenuBar(GetNewMBar(128)); |
DrawMenuBar(); |
AddResMenu(GetMHandle(128), 'DRVR'); |
gAppResFile = CurResFile(); |
gLastSearchText[0] = 0; |
gLastWNETime = TickCount(); |
// load up the sprockets picture |
{ |
PicHandle p = GetPicture(1028); |
Rect r; |
CGrafPtr savePort; |
GDHandle saveGD; |
if (!p) return; |
r = (**p).picFrame; |
if (NewGWorld(&gSprockets, 1, &r, 0, 0, 0) != noErr) { |
doAnAlert("\pOut of memory", -108); |
return; |
} |
LockPixels(gSprockets->portPixMap); |
GetGWorld(&savePort, &saveGD); |
SetGWorld(gSprockets, nil); |
EraseRect(&r); |
DrawPicture(p, &r); |
SetGWorld(savePort, saveGD); |
ReleaseResource((Handle)p); |
} |
if((Gestalt(gestaltAppleEventsAttr, &response) ? false : response != 0)) { |
AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, |
(AEEventHandlerProcPtr)OpenDocMessage, 0, false); |
AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, |
(AEEventHandlerProcPtr)QuitAppMessage, 0, false); |
} |
OpenFinderDocs(); |
do { |
EventRecord e; |
long result; |
DocumentPtr d; |
unsigned long ticksNow = TickCount(); |
Boolean mustGetEvent = gInBackground; |
if (!mustGetEvent) { |
// see if we have a pending update |
WindowRef w = LMGetWindowList(); |
while (w) { |
if (!EmptyRect(&(**((WindowPeek)w)->updateRgn).rgnBBox)) { |
mustGetEvent = true; |
break; |
} |
w = (WindowPtr)(((WindowPeek)w)->nextWindow); |
} |
} |
if (mustGetEvent || ((gLastWNETime + kWNEInterval) < ticksNow)) { |
WaitNextEvent(everyEvent, &e, 0, nil); |
gLastWNETime = ticksNow; |
} |
else { |
if (OSEventAvail(mDownMask | keyDownMask, &e)) |
WaitNextEvent(everyEvent, &e, 0, nil); |
else |
e.what = nullEvent; |
} |
#ifdef THINK_C |
result = ForEachDocument((DocFunction)TestOneEvent, &e); |
#else |
result = ForEachDocument(TestOneEvent, &e); |
#endif |
if (result) continue; |
switch (e.what) { |
case mouseDown: |
{ |
short part; |
WindowPtr whichWindow; |
part = FindWindow(e.where, &whichWindow); |
if (part) { |
switch (part) { |
case inMenuBar: |
colorMenus(); |
gDone = doMenuItem(MenuSelect(e.where)); |
break; |
case inSysWindow: |
SystemClick(&e, whichWindow); |
break; |
case inContent: |
if (whichWindow != FrontWindow()) { |
SelectWindow(whichWindow); |
break; |
} |
DoContentClick(GetWindowDocument(whichWindow), e.where, e.when); |
break; |
case inDrag: |
d = GetWindowDocument(whichWindow); |
if (d != NULL) { |
Rect r; |
GetMovieBox(d->m, &r); |
DragAlignedWindow(whichWindow, e.where, &qd.screenBits.bounds, &r, nil); |
} |
else |
DragWindow(whichWindow, e.where, &qd.screenBits.bounds); |
break; |
case inGrow: |
break; |
case inGoAway: |
if (TrackGoAway(whichWindow, e.where)) |
CloseDocument(GetWindowDocument(whichWindow)); |
break; |
} |
} |
} |
break; |
case updateEvt: |
UpdateDocument(GetWindowDocument((WindowPtr)e.message)); |
break; |
case keyDown: |
{ |
char c; |
c = e.message & charCodeMask; |
if (e.modifiers & cmdKey) { |
colorMenus(); |
gDone = doMenuItem(MenuKey(c)); |
} |
} |
break; |
case app4Evt: |
if ((e.message & 0xFF000000L) == 0x01000000L) { |
if (e.message & 1) { |
InitCursor(); |
ActivateDocument(GetWindowDocument(FrontWindow())); |
gInBackground = false; |
} |
else |
gInBackground = true; |
} |
break; |
case activateEvt: |
ActivateDocument(GetWindowDocument((WindowPtr)e.message)); |
break; |
case kHighLevelEvent: |
AEProcessAppleEvent(&e); |
break; |
} |
} while (!gDone); |
// QuickTime will take care of cleaning up after itself... |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14