home *** CD-ROM | disk | FTP | other *** search
/ QuickTime 2.0 Developer Kit / QuickTime 2.0 Developer Kit.iso / mac / MAC / Programming Stuff / Sample Code / Movie Toolbox / MovieBrowser / MovieBrowser.c < prev    next >
Encoding:
Text File  |  1994-12-11  |  29.8 KB  |  1,339 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        MovieBrowser.c
  3.  
  4.     Written by:    Peter Hoddie
  5.  
  6.     Copyright:    © 1992-1994 by Apple Computer, Inc., all rights reserved.
  7.  
  8.     Change History (most recent first):
  9.   <1>         12/8/94        khs        changed the format of the file to the new look and feel
  10.  
  11. */
  12.  
  13.  
  14. // INCLUDES
  15. #include <Aliases.h>
  16. #include <AppleEvents.h>
  17. #include <Dialogs.h>
  18. #include <Errors.h>
  19. #include <Events.h>
  20. #include <Memory.h>
  21. #include <Movies.h>
  22. #include <ToolUtils.h>
  23. #include <LowMem.h>
  24. #include <SegLoad.h>
  25. #include <Fonts.h>
  26. #include <GestaltEqu.h>
  27. #include <Devices.h>
  28. #include <Resources.h>
  29.  
  30.  
  31. // STRUCTURES
  32. typedef struct Document {
  33.     WindowPtr            w;
  34.     Movie                m;
  35.     MovieController        mc;
  36.  
  37.     short                page;
  38.     short                pageCount;
  39.  
  40.     short                curResID;
  41.     short                resRef;
  42.  
  43.     Track                firstTextTrack;
  44.  
  45.     FSSpec                fss;
  46.  
  47.     Rect                movieArea;
  48.     Rect                scrollArea;
  49.  
  50.     Boolean                noButtons;
  51.     Boolean                showController;
  52.  
  53.     Rect                sprocketsRectTop;
  54.     Rect                sprocketsRectBottom;
  55.  
  56.     Rect                scrollAndSprocketsArea;
  57.  
  58.     long                scrollOffset;
  59.     long                scrollPhaseShift;
  60.  
  61.     RGBColor            backgroundColor;
  62.  
  63.     Rect                thumbnailSize;
  64.  
  65.     TimeValue            **lastMovieTime;
  66.     Handle                names;
  67.  
  68.     PicHandle            titleBackground;
  69.     Rect                titleRect;
  70.     Rect                titleArea;
  71.  
  72.     Str255                movieName;
  73.     Point                titlePlace;
  74.  
  75.     short                lastPageClick;
  76.     unsigned long        lastPageClickTime;
  77. } Document, *DocumentPtr;
  78.  
  79. typedef long (*DocFunction)(DocumentPtr d, void *refCon);
  80.  
  81.  
  82. // FUNCTION PROTOTYPES
  83. void doAnAlert(StringPtr s, short err);
  84. void colorMenus(void);
  85. Boolean doMenuItem(long selection);
  86. void DoContentClick(DocumentPtr d, Point where, unsigned long clickTime);
  87.  
  88.  
  89. DocumentPtr OpenDocument(FSSpec *fss);
  90. void CloseDocument(DocumentPtr d);
  91. void GoToPage(DocumentPtr d, short pageNum);
  92. DocumentPtr GetWindowDocument(WindowPtr w);
  93. long ForEachDocument(DocFunction df, void *refCon);
  94. long TestOneEvent(DocumentPtr d, EventRecord *e);
  95. long IdleOneDocument(DocumentPtr d, void *refCon);
  96. PicHandle GetArrow(DocumentPtr d, Boolean right, Rect *bounds);
  97. void GetScrollArea(DocumentPtr d, Rect *bounds);
  98. void ActivateDocument(DocumentPtr d);
  99. void UpdateDocument(DocumentPtr d);
  100. void OpenFinderDocs(void);
  101. OSErr MissedAEParameters (AppleEvent *message);
  102. pascal OSErr OpenDocMessage(AppleEvent *message, AppleEvent *reply, long refcon);
  103. pascal OSErr QuitAppMessage(AppleEvent *message, AppleEvent *reply, long refcon);
  104.  
  105.  
  106. // GLOBALS
  107. short gAppResFile;
  108. Boolean gDone = false;
  109. GWorldPtr gSprockets = 0;
  110. Str255 gLastSearchText;
  111. unsigned long gLastWNETime;
  112. Boolean gInBackground = false;
  113. long gSysVersion = 0;
  114.  
  115.  
  116. // DEFINES
  117. // don't give the system too much time...
  118. #define kWNEInterval (90)
  119.  
  120. #define kBetweenThumbSize (2)
  121.  
  122.  
  123. // FUNCTIONS
  124. void doAnAlert(StringPtr s, short err)
  125. {
  126.     Str31 s1;
  127.  
  128.     NumToString(err, s1);
  129.     ParamText(s, err ? s1 : 0, 0, 0);
  130.     Alert(128, 0);
  131. }
  132.  
  133. void colorMenus(void)
  134. {
  135.     MenuHandle mh;
  136.     short count, i;
  137.     DocumentPtr d = GetWindowDocument(FrontWindow());
  138.  
  139.     mh = GetMHandle(129);
  140.     DisableItem(mh, 2);
  141.     if (FrontWindow()) EnableItem(mh, 2);
  142.  
  143.     mh = GetMHandle(130);
  144.     count = CountMItems(mh);
  145.     for (i = 1; i <= count; i++)
  146.         CheckItem(mh, i, d && (i == (d->page + 1)));
  147.  
  148.     mh = GetMHandle(131);
  149.     DisableItem(mh, 1);
  150.     DisableItem(mh, 3);
  151.     DisableItem(mh, 4);
  152.     DisableItem(mh, 5);
  153.     DisableItem(mh, 6);
  154.     DisableItem(mh, 8);
  155.     DisableItem(mh, 9);
  156.     DisableItem(mh, 11);
  157.     if (d) {
  158.         if (d->firstTextTrack) {
  159.             EnableItem(mh, 8);
  160.             if (gLastSearchText[0])
  161.                 EnableItem(mh, 9);
  162.         }
  163.         if (d->m)
  164.             EnableItem(mh, 4);
  165.  
  166.         EnableItem(mh, 11);
  167.         CheckItem(mh, 11, d->showController);
  168.     }
  169.     
  170. }
  171.  
  172. Boolean doMenuItem(long selection)
  173. {
  174.     short menu = HiWord(selection);
  175.     short item = LoWord(selection);
  176.     Boolean done = false;
  177.     DocumentPtr d = GetWindowDocument(FrontWindow());
  178.  
  179.     switch (menu) {
  180.         case 128:
  181.             if (item > 2) {
  182.                 Str255 daName;
  183.  
  184.                 GetItem(GetMHandle(128), item, daName);
  185.                 OpenDeskAcc(daName);
  186.             }
  187.             else {
  188.                 short item = 0;
  189.                 short saveRes = CurResFile();
  190.                 DialogPtr d;
  191.                 short kind;
  192.                 Handle h;
  193.                 Rect r;
  194.                 
  195.                 UseResFile(gAppResFile);
  196.                 d = GetNewDialog(129, nil, (WindowPtr)-1);
  197.  
  198.                 SetPort(d);
  199.                 GetDItem(d, 1, &kind, &h, &r);
  200.                 PenSize(3,3);
  201.                 InsetRect(&r,-4,-4);
  202.                 FrameRoundRect(&r,16,16);
  203.  
  204.                 while (d && (item != 1))
  205.                     ModalDialog(nil, &item);
  206.                 UseResFile(saveRes);
  207.  
  208.                 if (d) DisposDialog(d);
  209.             }
  210.             break;
  211.         case 129:
  212.             switch (item) {
  213.                 case 1:    {
  214.                         StandardFileReply reply;
  215.                         OSType docType = 'Dalí';
  216.                         
  217.                         StandardGetFilePreview(nil, 1, &docType, &reply);
  218.                         if (reply.sfGood)
  219.                             OpenDocument(&reply.sfFile);
  220.                         }
  221.                         break;
  222.                 case 2:    CloseDocument(d);
  223.                         break;
  224.                 case 4:    done = true;
  225.                         break;
  226.             }
  227.             break;
  228.         case 130:
  229.             GoToPage(GetWindowDocument(FrontWindow()), item - 1);
  230.             break;
  231.         case 131:
  232.             switch (item) {
  233.                 case 4:    if (d && d->m)
  234.                             PutMovieOnScrap(d->m, DoTheRightThing);
  235.                         break;
  236.                 case 8:    {
  237.                         DialogPtr dlg = GetNewDialog(130, nil, (WindowPtr)-1);
  238.                         short kind;
  239.                         Handle h;
  240.                         Rect r;
  241.                         short item = 0;
  242.                         Str255 str;
  243.                         ModalFilterProcPtr filter = nil;
  244.  
  245.                         if (!dlg) break;
  246.  
  247.                         // set up some dialog manager slime if not System 7
  248.                         if (gSysVersion < 7 ) {
  249.                             SetDialogDefaultItem(dlg, 1);
  250.                             SetDialogCancelItem(dlg, 2);
  251.                             SetDialogTracksCursor(dlg, true);
  252.                             GetStdFilterProc(&filter);
  253.                         }
  254.  
  255.                         GetDItem(dlg, 4, &kind, &h, &r);
  256.                         SetIText(h, gLastSearchText);
  257.                         SelIText(dlg, 4, 0, 32767);
  258.  
  259.                         while ((item != 1) && (item != 2))
  260.                             ModalDialog(filter, &item);
  261.  
  262.                         GetIText(h, str);
  263.                         DisposDialog(dlg);
  264.  
  265.                         if (item == 1 && str[0]) {
  266.                             BlockMove(str, gLastSearchText, sizeof(gLastSearchText));
  267.                             goto doSearch;
  268.                         }
  269.                         break;
  270.                     }
  271.                     case 9:    {
  272.                         TimeValue newTime;
  273.                         OSErr err;
  274.                         MediaHandler textHandler;
  275.                         long textOffset;
  276. doSearch:
  277.                         // text media handler really wants lower case letters, so make sure it gets 'em
  278.                         if (gSysVersion >= 7)
  279.                             LowerText((Ptr)&gLastSearchText[1], gLastSearchText[0]);
  280.                         else {
  281.                             short i = 0;
  282.                             while (i++ <= gLastSearchText[0]) {
  283.                                 char c = gLastSearchText[i];
  284.                                 if ((c >= 'A') && (c <= 'Z'))
  285.                                     gLastSearchText[i] -= 32;
  286.                             }
  287.                         }
  288.  
  289.                         textHandler = GetMediaHandler(GetTrackMedia(d->firstTextTrack));
  290.                         err = FindNextText(textHandler, (Ptr)&gLastSearchText[1], gLastSearchText[0],
  291.                                 findTextWrapAround, GetMovieTime(d->m, nil),
  292.                                 &newTime, nil, &textOffset);
  293.                         if (!err && (newTime != -1)) {
  294.                             TimeRecord tr;
  295.                             RGBColor rgb;
  296.                             
  297.                             tr.value.lo = newTime;
  298.                             tr.value.hi = 0;
  299.                             tr.scale = GetMovieTimeScale(d->m);
  300.                             tr.base = 0;
  301.                             MCDoAction(d->mc, mcActionGoToTime, &tr);
  302.                             rgb = (**((GrafVars **)((CGrafPtr)d->w)->grafVars)).rgbHiliteColor;
  303.  
  304.                             HiliteTextSample(textHandler, newTime, textOffset,
  305.                                 textOffset + gLastSearchText[0], &rgb);
  306.                         }
  307.                         else
  308.                             SysBeep(1);
  309.                     }
  310.                     break;
  311.                     case 11: {
  312.                         d->showController = !d->showController;
  313.                         MCSetVisible(d->mc, d->showController);
  314.                         break;
  315.                     }
  316.                     break;
  317.             }
  318.     }
  319.     HiliteMenu(0);
  320.  
  321.     return done;
  322. }
  323.  
  324.  
  325. DocumentPtr OpenDocument(FSSpec *fss)
  326. {
  327.     OSErr err;
  328.     DocumentPtr d;
  329.     Rect r;
  330.     Point center;
  331.     short resID;
  332.     Handle h;
  333.  
  334.     d = (DocumentPtr)NewPtrClear(sizeof(Document));
  335.     err = MemError();
  336.     if (err != noErr) goto bail;
  337.  
  338.     d->fss = *fss;
  339.  
  340.     d->resRef = FSpOpenResFile(fss, fsRdPerm);
  341.     if ((d->resRef == -1) || ResError()) {
  342.         err = resNotFound;
  343.         d->resRef = 0;
  344.         goto bail;
  345.     }
  346.  
  347.     d->lastPageClick = -1;
  348.     d->names = NewHandle(0);
  349.  
  350.     // count the pages, and rememeber their names
  351.     resID = 128;
  352.     SetResLoad(false);
  353.     do {
  354.         Handle r;
  355.         short id;
  356.         OSType rt;
  357.         Str255 name;
  358.  
  359.         r = Get1Resource(rAliasType, resID++);
  360.         if (r != NULL)
  361.             d->pageCount++;
  362.         else
  363.             break;
  364.  
  365.         // remember the name
  366.         GetResInfo(r, &id, &rt, name);
  367.         PtrAndHand(name, d->names, name[0] + 1);
  368.         err = MemError();
  369.         if (err != noErr) goto bail;
  370.     } while (true);
  371.     SetResLoad(true);
  372.  
  373.     // make the window
  374.     d->w = GetNewCWindow(128, nil, (WindowPtr)-1);
  375.     if (!d->w) {
  376.         err = memFullErr;
  377.         goto bail;
  378.     }
  379.     SetWTitle(d->w, fss->name);
  380.     TextFont(GetSysFont());
  381.  
  382.     // get back color
  383.     h = Get1Resource('RGB ', 128);
  384.     if (h != NULL) {
  385.         d->backgroundColor = **(RGBColor **)h;
  386.         ReleaseResource(h);
  387.     }
  388.     else {
  389.         short saveRes = CurResFile();
  390.  
  391.         UseResFile(gAppResFile);
  392.             d->backgroundColor = **(RGBColor **)Get1Resource('RGB ', 128);
  393.         UseResFile(saveRes);
  394.     }
  395.  
  396.     // pick up first thumbnail pict for measurement
  397.     h = Get1Resource('PICT', 128);
  398.     if (!h) {
  399.         err = resNotFound;
  400.         goto bail;
  401.     }
  402.     d->thumbnailSize = (**(PicHandle)h).picFrame;
  403.     OffsetRect(&d->thumbnailSize, -d->thumbnailSize.left, -d->thumbnailSize.top);
  404.     d->thumbnailSize.right += kBetweenThumbSize;
  405.  
  406.     // show a controller?
  407.     d->showController = false;
  408.     h = Get1Resource('MCmc', 128);
  409.     if (h) {
  410.         d->showController = **h;
  411.         ReleaseResource(h);
  412.     }
  413.  
  414.     // make page time table
  415.     d->lastMovieTime = (TimeValue **)NewHandleClear(d->pageCount * sizeof(TimeValue));
  416.     err = MemError();
  417.     if (err != noErr) goto bail;
  418.  
  419.     d->movieArea = **(Rect **)GetResource('RECT', 128);
  420.     ReleaseResource(GetResource('RECT', 128));
  421.     OffsetRect(&d->movieArea, -d->movieArea.left, -d->movieArea.top);
  422.  
  423.     // figure out what to use for title background
  424.     d->titleBackground = (PicHandle)Get1Resource('PICT', 1048);
  425.     if (!d->titleBackground) {
  426.         short saveRes = CurResFile();
  427.  
  428.         UseResFile(gAppResFile);
  429.             d->titleBackground = (PicHandle)GetPicture(1048);
  430.         UseResFile(saveRes);
  431.     }
  432.     LoadResource((Handle)d->titleBackground);
  433.     r = (**d->titleBackground).picFrame;
  434.     OffsetRect(&r, -r.left, -r.top);
  435.     OffsetRect(&r, (d->movieArea.right / 2) - (r.right / 2), 0);
  436.     d->titleRect = r;
  437.     OffsetRect(&d->titleRect, 0, (d->titleRect.bottom - d->titleRect.top) / 3);
  438.     InsetRect(&r, 0, -((d->titleRect.bottom - d->titleRect.top) / 3));
  439.     d->titleArea = r;
  440.  
  441.     OffsetRect(&d->movieArea, 0, d->titleArea.bottom);
  442.     SizeWindow(d->w, d->movieArea.right,
  443.         d->movieArea.bottom + d->thumbnailSize.bottom + (gSprockets->portRect.bottom * 2), false);
  444.  
  445.     // figure out how to keep things centered
  446.     GetScrollArea(d, &r);
  447.     d->scrollArea = r;
  448.     OffsetRect(&r, -r.left, -r.top);
  449.     d->scrollPhaseShift = (d->thumbnailSize.right) - (r.right % d->thumbnailSize.right)/2;
  450.  
  451.     // calculate sprockets rect
  452.     d->sprocketsRectTop = d->scrollArea;
  453.     d->sprocketsRectTop.bottom = d->scrollArea.top;
  454.     d->sprocketsRectTop.top -= gSprockets->portRect.bottom;
  455.  
  456.     d->sprocketsRectBottom = d->scrollArea;
  457.     d->sprocketsRectBottom.top = d->scrollArea.bottom;
  458.     d->sprocketsRectBottom.bottom += gSprockets->portRect.bottom;
  459.  
  460.     UnionRect(&d->scrollArea, &d->sprocketsRectTop, &d->scrollAndSprocketsArea);
  461.     UnionRect(&d->sprocketsRectBottom, &d->scrollAndSprocketsArea, &d->scrollAndSprocketsArea);
  462.  
  463.     SetWRefCon(d->w, (long)d);
  464.  
  465.     SetPort(d->w);
  466.  
  467.     r = d->w->portRect;
  468.     GetBestDeviceRect(nil, &r);
  469.     if (r.top == 0) r.top += GetMBarHeight();
  470.     center.h = (r.left + r.right) >> 1;
  471.     center.v = (r.top + r.bottom) >> 1;
  472.     r.left = center.h - (d->w->portRect.right >> 1);
  473.     r.right = r.left + d->w->portRect.right;
  474.     r.top = center.v - (d->w->portRect.bottom >> 1);
  475.     r.bottom = r.top + d->w->portRect.bottom;
  476.     MoveWindow(d->w, r.left, r.top, false);
  477.     AlignWindow(d->w, false, &d->movieArea, nil);
  478.     ShowWindow(d->w);
  479.  
  480.     GoToPage(d, d->page);
  481.  
  482. bail:
  483.     if (err) CloseDocument(d);
  484.  
  485.     return d;
  486. }
  487.  
  488. void CloseDocument(DocumentPtr d)
  489. {
  490.     if (!d) return;
  491.  
  492.     if (d->resRef) CloseResFile(d->resRef);
  493.     if (d->mc) DisposeMovieController(d->mc);
  494.     if (d->lastMovieTime) DisposHandle((Handle)d->lastMovieTime);
  495.     if (d->names) DisposHandle(d->names);
  496.     DisposeMovie(d->m);
  497.     if (d->w) DisposeWindow(d->w);
  498.     DisposPtr((Ptr)d);
  499.  
  500.     ActivateDocument(0);                // clear out the movies menu
  501. }
  502.  
  503. DocumentPtr GetWindowDocument(WindowPtr w)
  504. {
  505.     if (!w) return nil;
  506.  
  507.     if (((WindowPeek)w)->windowKind == userKind)
  508.         return (DocumentPtr)GetWRefCon(w);
  509.     else
  510.         return nil;
  511. }
  512.  
  513. void GoToPage(DocumentPtr d, short pageNum)
  514. {
  515.     OSErr err;
  516.     short resID;
  517.     Movie newMovie = nil;
  518.     Point where = {0,0};
  519.     Rect r;
  520.     short saveRes;
  521.     FSSpec movieFile;
  522.     Boolean whoCares;
  523.     short movieResRef;
  524.     AliasHandle alias;
  525.     RgnHandle rgn;
  526.     short trashID;
  527.     OSType trackType;
  528.  
  529.     if (pageNum < 0)
  530.         pageNum = d->pageCount - 1;
  531.     else
  532.         pageNum = pageNum % d->pageCount; 
  533.     resID = pageNum + 128;
  534.     if (resID == d->curResID) return;
  535.  
  536.     // resolve alias to the file
  537.     saveRes = CurResFile();
  538.     UseResFile(d->resRef);
  539.         alias = (AliasHandle)Get1Resource(rAliasType, resID);
  540.     UseResFile(saveRes);
  541.     if (!alias) return;
  542.     err = ResolveAlias((gSysVersion >= 7) ? &d->fss : 0, alias, &movieFile, &whoCares);
  543.     GetResInfo((Handle)alias, &trashID, &trackType, d->movieName);
  544.     ReleaseResource((Handle)alias);
  545.     if (err) return;
  546.  
  547.     // get the movie
  548.     SetCursor(*GetCursor(watchCursor));
  549.     OpenMovieFile(&movieFile, &movieResRef, fsRdPerm);
  550.         SetPort(d->w);
  551.         RGBBackColor(&d->backgroundColor);                // for erasing
  552.         err = NewMovieFromFile(&newMovie, movieResRef, nil, nil,
  553.                  newMovieActive, nil);
  554.         BackColor(whiteColor);
  555.     SetCursor(&qd.arrow);
  556.     CloseMovieFile(movieResRef);
  557.     if (err) return;
  558.  
  559.     // position new movie a little
  560.     GetMovieBox(newMovie, &r);
  561.     OffsetRect(&r, -r.left, -r.top);
  562.     SetMovieBox(newMovie, &r);
  563.  
  564.     // restore movie's previous time
  565.     SetMovieTimeValue(newMovie, (*d->lastMovieTime)[pageNum]);
  566.  
  567.     // position movie in window
  568.     if (d->mc) {
  569.         TimeValue saveTime;
  570.  
  571.         // invalidate the old one
  572.         rgn = MCGetWindowRgn(d->mc, d->w);
  573.         if (rgn) {
  574.             InvalRgn(rgn);
  575.             DisposeRgn(rgn);
  576.         }
  577.  
  578.         // store the old movie's time
  579.         saveTime = GetMovieTime(d->m, nil);
  580.         (*d->lastMovieTime)[d->page] = saveTime;
  581.  
  582.         SetMovieVolume(newMovie, GetMovieVolume(d->m));            // don't lose the volume setting
  583.  
  584.         // change the movie on the controller
  585.         MCSetVisible(d->mc, false);
  586.             MCSetMovie(d->mc, newMovie, d->w, where);
  587.             MCPositionController(d->mc, &d->movieArea, nil, 0);
  588.         if (d->showController)
  589.             MCSetVisible(d->mc, true);
  590.     }
  591.     else {
  592.         // create a new controller
  593.         d->mc = NewMovieController(newMovie, &d->movieArea, d->showController ? 0 : mcNotVisible);
  594.         if (!d->mc) return;
  595.         MCDoAction(d->mc, mcActionSetKeysEnabled, (void *)true);
  596.     }
  597.  
  598.     // update state
  599.     DisposeMovie(d->m);
  600.     d->m = newMovie;
  601.     d->curResID = resID;
  602.     d->page = pageNum;
  603.  
  604.     // look for text
  605.     {
  606.     long trackCount, i;
  607.  
  608.     d->firstTextTrack = nil;
  609.     trackCount = GetMovieTrackCount(d->m);
  610.     for (i=1; i<=trackCount; i++) {
  611.         Track t = GetMovieIndTrack(d->m, i);
  612.         OSType mediaType;
  613.  
  614.         GetMediaHandlerDescription(GetTrackMedia(t), &mediaType, nil, nil);
  615.         if (mediaType == 'text') {
  616.             d->firstTextTrack = t;
  617.             break;
  618.         }
  619.     }
  620.     }
  621.  
  622.     // invalidate the new one
  623.     rgn = MCGetWindowRgn(d->mc, d->w);
  624.     if (rgn) {
  625.         InvalRgn(rgn);
  626.         DisposeRgn(rgn);
  627.     }
  628.  
  629.     // update the title variables
  630.     {
  631.     FontInfo fi;
  632.     short width;    
  633.  
  634.     InvalRect(&d->titleRect);
  635.     GetFontInfo(&fi);
  636.     width = StringWidth(d->movieName);
  637.     d->titlePlace.h = ((d->titleRect.right + d->titleRect.left) / 2) - (width / 2);
  638.     d->titlePlace.v = ((d->titleRect.top + d->titleRect.bottom) / 2) + (fi.ascent / 2);
  639.     }
  640. }
  641.  
  642. void DoContentClick(DocumentPtr d, Point where, unsigned long clickTime)
  643. {
  644.     Rect r;
  645.     short scrollValue = 0;
  646.     unsigned long lastTicks = TickCount();
  647.     long delayTime = 15;
  648.     Rect mustRect = d->w->portRect;
  649.     PicHandle showPict = nil, restorePict = nil;
  650.  
  651.     if (!d) return;
  652.  
  653.     SetPort(d->w);
  654.     GlobalToLocal(&where);
  655.  
  656. tryAgain:
  657.     // try left arrow
  658.     GetArrow(d, false, &r);
  659.     if (PtInRect(where, &r) && PtInRect(where, &mustRect)) {
  660.         // go left
  661.         if (d->scrollOffset != 0)
  662.             d->scrollOffset--;
  663.         else
  664.             d->scrollOffset = d->pageCount - 1;
  665.         scrollValue = +1;
  666.         mustRect = r;
  667.         restorePict = GetPicture(1024);
  668.         showPict = GetPicture(1026);
  669.  
  670.         d->lastPageClick = -1;
  671.  
  672.         goto gotHit;
  673.     }
  674.  
  675.     // try right arrow
  676.     GetArrow(d, true, &r);
  677.     if (PtInRect(where, &r) && PtInRect(where, &mustRect)) {
  678.         // go right
  679.         if (d->scrollOffset != (d->pageCount - 1))
  680.             d->scrollOffset++;
  681.         else
  682.             d->scrollOffset = 0;
  683.         scrollValue = -1;
  684.         mustRect = r;
  685.         restorePict = GetPicture(1025);
  686.         showPict = GetPicture(1027);
  687.         goto gotHit;
  688.     }
  689.  
  690.     r = d->scrollArea;
  691.     if (PtInRect(where, &r) && PtInRect(where, &mustRect)) {
  692.         // clicked on an image
  693.         short internalOffset = (where.h - r.left + d->scrollPhaseShift) / d->thumbnailSize.right;
  694.         Boolean wasIn, inRect;
  695.         Rect clipRect;
  696.  
  697.         r = d->scrollArea;
  698.         ClipRect(&r);
  699.         clipRect = r;
  700.  
  701.         r.right = r.left + d->thumbnailSize.right;
  702.         OffsetRect(&r, internalOffset * d->thumbnailSize.right, 0);
  703.         OffsetRect(&r, -d->scrollPhaseShift, 0);
  704.         PenMode(patXor);
  705.         PenPat((ConstPatternParam)&qd.gray);
  706.         PenSize(3, 3);
  707.         FrameRect(&r);
  708.         wasIn = true;
  709.         while (StillDown()) {
  710.             GetMouse(&where);
  711.             inRect = PtInRect(where, &r);
  712.             if (inRect != wasIn) {
  713.                 FrameRect(&r);
  714.                 wasIn = inRect;
  715.             }
  716.             ClipRect(&d->w->portRect);
  717.                 ForEachDocument(IdleOneDocument, nil);
  718.             ClipRect(&clipRect);
  719.         }
  720.         if (wasIn) FrameRect(&r);
  721.         PenNormal();
  722.         ClipRect(&d->w->portRect);
  723.         if (wasIn) {
  724.             short newPage = (d->scrollOffset + internalOffset) % d->pageCount;
  725.             SInt32 dTime = LMGetDoubleTime();
  726.             
  727.             if (     (  d->lastPageClick == newPage) && 
  728.                     ( (d->lastPageClickTime + dTime) >= clickTime) 
  729.                ) {
  730.                 Fixed curRate;
  731.  
  732.                 MCDoAction(d->mc, mcActionGetPlayRate, &curRate);
  733.                 if (!curRate) {
  734.                     EventRecord whoCares;
  735.                     TimeValue t = GetMovieTime(d->m, nil);
  736.                     TimeValue movieDur = GetMovieDuration(d->m);
  737.                     Fixed preferredRate = GetMoviePreferredRate(d->m);
  738.  
  739.                     if (t == movieDur) t = 0;
  740.                     PrerollMovie(d->m, t, preferredRate);
  741.                     EventAvail(0, &whoCares);
  742.                     EventAvail(0, &whoCares);
  743.                     EventAvail(0, &whoCares);
  744.                     UpdateDocument(d);
  745.                     MCIdle(d->mc);
  746.                     MCIdle(d->mc);
  747.                     MCIdle(d->mc);
  748.                     MCDoAction(d->mc, mcActionPlay, (void *)preferredRate);
  749.                 }
  750.                 d->lastPageClick = -1;
  751.                 d->lastPageClickTime += 500;
  752.             }
  753.             else {
  754.                 if (newPage == d->page) {
  755.                     MCDoAction(d->mc, mcActionPlay, (void *)0);
  756.                     d->lastPageClick = newPage;
  757.                 }
  758.                 else {
  759.                     GoToPage(d, newPage);
  760.                     d->lastPageClick = newPage;
  761.                 }
  762.             }
  763.             d->lastPageClickTime = clickTime;
  764.         }
  765.         r = mustRect;
  766.         goto gotHit;
  767.     }
  768.  
  769. gotHit:
  770.     if (scrollValue) {
  771.         Rect r;
  772.         RgnHandle rgn;
  773.  
  774.         if (showPict) DrawPicture(showPict, &mustRect);
  775.         r = d->scrollArea;
  776.         rgn = NewRgn();
  777.         if (rgn != NULL) {
  778.             RGBBackColor(&d->backgroundColor);
  779.                 ScrollRect(&r, d->thumbnailSize.right * scrollValue, 0, rgn);
  780.             BackColor(whiteColor);
  781.             InvalRgn(rgn);
  782.             DisposeRgn(rgn);
  783.             UpdateDocument(d);
  784.             ClipRect(&d->w->portRect);
  785.             do {
  786.                 ForEachDocument(IdleOneDocument, nil);
  787.             } while (StillDown() && ((unsigned long)TickCount()) < (lastTicks + delayTime));
  788.             if (StillDown()) {
  789.                 lastTicks = TickCount();
  790.                 GetMouse(&where);
  791.                 delayTime -= 3;
  792.                 if (delayTime < 0) delayTime = 0;
  793.                 scrollValue = 0;
  794.                 goto tryAgain;
  795.             }
  796.         }
  797.     }
  798.     if (restorePict) DrawPicture(restorePict, &mustRect);
  799. }
  800.  
  801. PicHandle GetArrow(DocumentPtr d, Boolean right, Rect *bounds)
  802. {
  803.     PicHandle aPict;
  804.     Rect r;
  805.  
  806.     if (d->noButtons) {
  807.         SetRect(bounds, 0, 0, 0, 0);
  808.         return GetPicture(1024);
  809.     }
  810.  
  811.     if (!right) {
  812.         // left arrow
  813.         aPict = GetPicture(1024);
  814.         r = (**aPict).picFrame;
  815.         OffsetRect(&r, -r.left + 5, -r.top);
  816.         OffsetRect(&r, 0, d->w->portRect.bottom - r.bottom);
  817.     }
  818.     else {
  819.         // right arrow
  820.         aPict = GetPicture(1025);
  821.         r = (**aPict).picFrame;
  822.         OffsetRect(&r, -r.left, -r.top);
  823.         OffsetRect(&r, d->w->portRect.right - r.right - 5, d->w->portRect.bottom - r.bottom);
  824.     }
  825.     OffsetRect(&r, 0, -(d->thumbnailSize.bottom/2) + (r.bottom - r.top)/2);
  826.     OffsetRect(&r, 0, -(gSprockets->portRect.bottom * 3)/2);
  827.     if (bounds) *bounds = r;
  828.  
  829.     return aPict;
  830. }
  831.  
  832. void GetScrollArea(DocumentPtr d, Rect *bounds)
  833. {
  834.     Rect r, r1, r2;
  835.     short bottom;
  836.     long maxWidth = (d->pageCount * d->thumbnailSize.right);
  837.  
  838.     GetArrow(d, false, &r1);
  839.     GetArrow(d, true, &r2);
  840.     bottom = d->w->portRect.bottom - ((gSprockets->portRect.bottom * 3)/2);
  841.     SetRect(&r, r1.right, bottom - d->thumbnailSize.bottom, r2.left, bottom);
  842.     InsetRect(&r, 4, 0);
  843.  
  844.     if ((r.right - r.left) > maxWidth) {
  845.         // don't wrap
  846.         short center = (r1.right + r2.left) / 2;
  847.         r.right = r.left + maxWidth;
  848.         OffsetRect(&r, -r.left + (center - (r.right - r.left)/2), 0);
  849.         d->noButtons = true;
  850.     }
  851.  
  852.     *bounds = r;
  853. }
  854.  
  855. void UpdateDocument(DocumentPtr d)
  856. {
  857.     PicHandle aPict;
  858.     Rect r;
  859.     RgnHandle rgn = 0;
  860.     Rect scrollArea;
  861.  
  862.     if (!d) return;
  863.  
  864.     if (d->mc)
  865.         rgn = MCGetWindowRgn(d->mc, d->w);
  866.     scrollArea = d->scrollArea;
  867.     BeginUpdate(d->w);
  868.         SetPort(d->w);
  869.  
  870.         ClipRect(&d->w->portRect);
  871.         if (rgn) {
  872.             DiffRgn(d->w->clipRgn, rgn, d->w->clipRgn);
  873.             RectRgn(rgn, &d->scrollAndSprocketsArea);
  874.             DiffRgn(d->w->clipRgn, rgn, d->w->clipRgn);
  875.             RectRgn(rgn, &d->titleRect);
  876.             DiffRgn(d->w->clipRgn, rgn, d->w->clipRgn);
  877.         }
  878.  
  879.         RGBForeColor(&d->backgroundColor);
  880.             PaintRect(&d->w->portRect);
  881.         ForeColor(blackColor);
  882.  
  883.         if (rgn)
  884.             UnionRgn(d->w->clipRgn, rgn, d->w->clipRgn);
  885.  
  886.         // draw the title
  887.         LoadResource((Handle)d->titleBackground);
  888.         HNoPurge((Handle)d->titleBackground);
  889.             DrawPicture(d->titleBackground, &d->titleRect);
  890.         HPurge((Handle)d->titleBackground);
  891.         MoveTo(d->titlePlace.h, d->titlePlace.v);
  892.         TextFont(GetSysFont());
  893.         DrawString(d->movieName);
  894.  
  895.         // left arrow
  896.         aPict = GetArrow(d, false, &r);
  897.         DrawPicture(aPict, &r);
  898.  
  899.         // right arrow
  900.         aPict = GetArrow(d, true, &r);
  901.         DrawPicture(aPict, &r);
  902.  
  903.         // sprockets
  904.         {
  905.         Rect r1 = d->sprocketsRectTop;
  906.         Rect r2 = d->sprocketsRectBottom;
  907.         Rect clip;
  908.         short pageOffset;
  909.  
  910.         UnionRect(&r1, &r2, &clip);
  911.         ClipRect(&clip);
  912.  
  913.         pageOffset = d->scrollPhaseShift;
  914.         r1.left -= pageOffset;
  915.         r2.left = r1.left;
  916.  
  917.         r1.right = r1.left + gSprockets->portRect.right;
  918.         r2.right = r1.right;
  919.         while (r1.left < d->scrollArea.right) {
  920.             CopyBits((BitMap *)*gSprockets->portPixMap, &d->w->portBits, &gSprockets->portRect,
  921.                     &r1, srcCopy, nil);
  922.             CopyBits((BitMap *)*gSprockets->portPixMap, &d->w->portBits, &gSprockets->portRect,
  923.                     &r2, srcCopy, nil);
  924.             OffsetRect(&r1, gSprockets->portRect.right, 0);
  925.             OffsetRect(&r2, gSprockets->portRect.right, 0);
  926.         }
  927.         }
  928.  
  929.         // thumbnails
  930.         {
  931.         short firstPage;
  932.         short resID;
  933.         Rect thumbRect;
  934.         short saveRes = CurResFile();
  935.  
  936.         r = scrollArea;
  937.         ClipRect(&r);
  938.  
  939.         firstPage = d->scrollOffset;
  940.         resID = firstPage + 128;
  941.         thumbRect = r;
  942.         thumbRect.right = thumbRect.left + d->thumbnailSize.right;
  943.         OffsetRect(&thumbRect, -d->scrollPhaseShift, 0);
  944.         UseResFile(d->resRef);
  945.         while (thumbRect.left < r.right) {
  946.             Rect whoCares;
  947.  
  948.             if ((resID - 128) >= d->pageCount)
  949.                 resID = 128;
  950.  
  951.             if (SectRect(&(**d->w->visRgn).rgnBBox, &thumbRect, &whoCares)) {
  952.                 PicHandle p = GetPicture(resID);
  953.  
  954.                 MoveTo(thumbRect.left, thumbRect.top);
  955.                 LineTo(thumbRect.left, thumbRect.bottom);
  956.  
  957.                 MoveTo(thumbRect.right - 1, thumbRect.top);
  958.                 LineTo(thumbRect.right - 1, thumbRect.bottom);
  959.                 if (p) {
  960.                     Rect r = thumbRect;
  961.  
  962.                     r.right--;
  963.                     r.left++;
  964.  
  965.                     LoadResource((Handle)p);
  966.                     HNoPurge((Handle)p);
  967.                         DrawPicture(p, &r);
  968.                     HPurge((Handle)p);
  969.                 }
  970.             }
  971.  
  972.             OffsetRect(&thumbRect, d->thumbnailSize.right, 0);
  973.             resID++;
  974.         }
  975.         UseResFile(saveRes);
  976.         }
  977.  
  978.         ClipRect(&d->w->portRect);
  979.         
  980.         // dividing line
  981.         {
  982.         Rect r = d->scrollAndSprocketsArea;
  983.         RGBColor aColor;
  984.  
  985.         r.left = 0;
  986.         r.right = d->w->portRect.right;
  987.         r.top -= (gSprockets->portRect.bottom/2) + 2;
  988.  
  989.         aColor = d->backgroundColor;
  990.         aColor.red -= (aColor.red /6);
  991.         aColor.green -= (aColor.green /6);
  992.         aColor.blue -= (aColor.blue /6);
  993.         RGBForeColor(&aColor);
  994.         MoveTo(r.left, r.top);
  995.         LineTo(r.right, r.top);
  996.  
  997.         aColor = d->backgroundColor;
  998.         aColor.red += (aColor.red /6);
  999.         aColor.green += (aColor.green /6);
  1000.         aColor.blue += (aColor.blue /6);
  1001.         RGBForeColor(&aColor);
  1002.         MoveTo(r.left, r.top + 1);
  1003.         LineTo(r.right, r.top + 1);
  1004.         }
  1005.  
  1006.     EndUpdate(d->w);
  1007.     if (rgn) DisposeRgn(rgn);
  1008. }
  1009.  
  1010. void ActivateDocument(DocumentPtr d)
  1011. {
  1012.     MenuHandle mh = GetMHandle(130);
  1013.     short count, index = 0;
  1014.     Ptr p;
  1015.     char c[2];
  1016.  
  1017.     count = CountMItems(mh);
  1018.     while (count--)
  1019.         DelMenuItem(mh, count + 1);
  1020.  
  1021.     if (!d) return;
  1022.  
  1023.     count = d->pageCount;
  1024.     HLock(d->names);
  1025.     p = *d->names;
  1026.     c[0] = 1;
  1027.     c[1] = 'e';
  1028.     while (count--) {
  1029.         AppendMenu(mh, (StringPtr)&c);
  1030.         SetItem(mh, ++index, (StringPtr)p);
  1031.         p += (*p + 1);
  1032.     }
  1033.     HUnlock(d->names);
  1034. }
  1035.  
  1036. long IdleOneDocument(DocumentPtr d, void *refCon)
  1037. {
  1038.     if (d->mc)
  1039.         MCIdle(d->mc);
  1040.     return 0;
  1041. }
  1042.  
  1043. long ForEachDocument(DocFunction df, void *refCon)
  1044. {
  1045.     WindowPtr w = FrontWindow();
  1046.     long result = 0;
  1047.  
  1048.     while (w) {
  1049.         DocumentPtr d = GetWindowDocument(w);
  1050.         if (d) {
  1051.             result = (df)(d, refCon);
  1052.             if (result) break;
  1053.         }
  1054.         w = (WindowPtr)((WindowPeek)w)->nextWindow;
  1055.     }
  1056.  
  1057.     return result;
  1058. }
  1059.  
  1060. long TestOneEvent(DocumentPtr d, EventRecord *e)
  1061. {
  1062.     if (d->mc && d->m)
  1063.         return MCIsPlayerEvent(d->mc, e);
  1064.  
  1065.     return 0;
  1066. }
  1067.  
  1068. void OpenFinderDocs(void)
  1069. {
  1070.     short printIt, docCount;                // no printing
  1071.  
  1072.     CountAppFiles(&printIt, &docCount);
  1073.     
  1074.     if (docCount > 0) {
  1075.         short j;
  1076.  
  1077.         for(j = 1; j <= docCount; j++){
  1078.             FSSpec fss;
  1079.             AppFile apfile;
  1080.  
  1081.             GetAppFiles(j,&apfile);
  1082.             FSMakeFSSpec(apfile.vRefNum, 0, apfile.fName, &fss);
  1083.  
  1084.             OpenDocument(&fss);
  1085.             ClrAppFiles(j);
  1086.         }
  1087.     }
  1088. }
  1089.  
  1090. OSErr MissedAEParameters (AppleEvent *message)
  1091. {
  1092.     DescType typeCode;
  1093.     Size actualSize;
  1094.     OSErr err;
  1095.  
  1096.     err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
  1097.             &typeCode, nil, 0L, &actualSize);
  1098.     if (err == errAEDescNotFound)
  1099.         return(noErr);
  1100.     return(err = noErr ? errAEEventNotHandled : err);
  1101. }
  1102.  
  1103. pascal OSErr OpenDocMessage(AppleEvent *message, AppleEvent *reply, long refcon)
  1104. {
  1105.     FSSpec fss;
  1106.     AEDescList docList;
  1107.     long index, itemsInList;
  1108.     Size actualSize;
  1109.     AEKeyword keywd;
  1110.     DescType typeCode;
  1111.     OSErr err;
  1112.  
  1113.     if ((err = AEGetParamDesc(message, keyDirectObject, typeAEList, &docList)) != noErr)
  1114.         return(err);
  1115.     if ((err = MissedAEParameters(message)) != noErr)
  1116.         return(err);
  1117.     if ((err = AECountItems(&docList, &itemsInList)) != noErr)
  1118.         return(err);
  1119.  
  1120.     for (index = 1; index <= itemsInList; index++)
  1121.         {
  1122.         if ((err = AEGetNthPtr(&docList, index, typeFSS, &keywd, &typeCode,
  1123.                     (Ptr)&fss, sizeof(FSSpec), &actualSize)) != noErr)
  1124.             break;
  1125.             OpenDocument(&fss);
  1126.         }
  1127.  
  1128.     return(AEDisposeDesc(&docList));
  1129. }
  1130.  
  1131. pascal OSErr QuitAppMessage(AppleEvent *message, AppleEvent *reply, long refcon)
  1132. {
  1133.     OSErr err;
  1134.  
  1135.     if ((err = MissedAEParameters(message)) != noErr)
  1136.         return(err);
  1137.  
  1138.     gDone = true;
  1139.  
  1140.     return(noErr);
  1141. }
  1142.  
  1143. void main(void)
  1144. {
  1145.     OSErr err;
  1146.     long response;
  1147.  
  1148.     // initialize the world
  1149.     InitGraf(&qd.thePort);
  1150.     InitFonts();
  1151.     InitWindows();
  1152.     InitMenus();
  1153.     TEInit();
  1154.     InitDialogs(0L);
  1155.     InitCursor();
  1156.     MaxApplZone();
  1157.     
  1158.     // find the system version (used later)
  1159.     Gestalt(gestaltSystemVersion, &gSysVersion);
  1160.     gSysVersion = (gSysVersion >> 8) & 0x0F;
  1161.  
  1162.     // must have QuickTime around
  1163.     if (Gestalt(gestaltQuickTime, &response)) {
  1164.         doAnAlert("\pPlease install QuickTime™.", 0);
  1165.         return;
  1166.     }
  1167.  
  1168.     if (response < 0x01508000) {
  1169.         doAnAlert("\pMovieBrowser™ required QuickTime 1.5 or later.", 0);
  1170.         return;
  1171.     }
  1172.  
  1173.     err = EnterMovies();
  1174.     if (err) {
  1175.         doAnAlert("\pEnterMovies failed.", err);
  1176.         return;
  1177.     }
  1178.  
  1179.     SetMenuBar(GetNewMBar(128));
  1180.     DrawMenuBar();
  1181.  
  1182.     AddResMenu(GetMHandle(128), 'DRVR');
  1183.  
  1184.     gAppResFile = CurResFile();
  1185.     gLastSearchText[0] = 0;
  1186.     gLastWNETime = TickCount();
  1187.  
  1188.     // load up the sprockets picture
  1189.     {
  1190.     PicHandle p = GetPicture(1028);
  1191.     Rect r;
  1192.     CGrafPtr savePort;
  1193.     GDHandle saveGD;
  1194.  
  1195.     if (!p) return;
  1196.     r = (**p).picFrame;
  1197.     if (NewGWorld(&gSprockets, 1, &r, 0, 0, 0) != noErr) {
  1198.         doAnAlert("\pOut of memory", -108);
  1199.         return;
  1200.     }
  1201.     LockPixels(gSprockets->portPixMap);
  1202.  
  1203.     GetGWorld(&savePort, &saveGD);
  1204.     SetGWorld(gSprockets, nil);
  1205.         EraseRect(&r);
  1206.         DrawPicture(p, &r);
  1207.     SetGWorld(savePort, saveGD);
  1208.  
  1209.     ReleaseResource((Handle)p);
  1210.     }
  1211.  
  1212.     if((Gestalt(gestaltAppleEventsAttr, &response) ? false : response != 0)) {
  1213.         AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
  1214.                 (AEEventHandlerProcPtr)OpenDocMessage, 0, false);
  1215.         AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
  1216.                 (AEEventHandlerProcPtr)QuitAppMessage, 0, false);
  1217.     }
  1218.  
  1219.     OpenFinderDocs();
  1220.  
  1221.     do {
  1222.         EventRecord e;
  1223.         long result;
  1224.         DocumentPtr d;
  1225.         unsigned long ticksNow = TickCount();
  1226.         Boolean mustGetEvent = gInBackground;
  1227.  
  1228.         if (!mustGetEvent) {
  1229.             // see if we have a pending update
  1230.             WindowRef w = LMGetWindowList();
  1231.             while (w) {
  1232.                 if (!EmptyRect(&(**((WindowPeek)w)->updateRgn).rgnBBox)) {
  1233.                     mustGetEvent = true;
  1234.                     break;
  1235.                 }
  1236.                 w = (WindowPtr)(((WindowPeek)w)->nextWindow);
  1237.             }
  1238.         }
  1239.  
  1240.         if (mustGetEvent || ((gLastWNETime + kWNEInterval) < ticksNow)) {
  1241.             WaitNextEvent(everyEvent, &e, 0, nil);
  1242.             gLastWNETime = ticksNow;
  1243.         }
  1244.         else {
  1245.             if (OSEventAvail(mDownMask | keyDownMask, &e))
  1246.                 WaitNextEvent(everyEvent, &e, 0, nil);
  1247.             else
  1248.                 e.what = nullEvent;
  1249.         }
  1250.  
  1251. #ifdef THINK_C        
  1252.         result = ForEachDocument((DocFunction)TestOneEvent, &e);
  1253. #else
  1254.         result = ForEachDocument(TestOneEvent, &e);
  1255. #endif
  1256.         if (result) continue;
  1257.         switch (e.what) {
  1258.             case mouseDown:
  1259.                 {
  1260.                 short part;
  1261.                 WindowPtr whichWindow;
  1262.  
  1263.                 part = FindWindow(e.where, &whichWindow);
  1264.                 if (part) {
  1265.                     switch (part) {
  1266.                         case inMenuBar:
  1267.                                     colorMenus();
  1268.                                     gDone = doMenuItem(MenuSelect(e.where));
  1269.                                     break;
  1270.                         case inSysWindow:
  1271.                                     SystemClick(&e, whichWindow);
  1272.                                     break;
  1273.                         case inContent:
  1274.                                     if (whichWindow != FrontWindow()) {
  1275.                                         SelectWindow(whichWindow);
  1276.                                         break;
  1277.                                     }
  1278.                                     DoContentClick(GetWindowDocument(whichWindow), e.where, e.when);
  1279.                                     break;
  1280.                         case inDrag:
  1281.                                     d = GetWindowDocument(whichWindow);    
  1282.                                     if (d != NULL) {
  1283.                                         Rect r;
  1284.  
  1285.                                         GetMovieBox(d->m, &r);
  1286.                                         DragAlignedWindow(whichWindow, e.where, &qd.screenBits.bounds, &r, nil);
  1287.                                     }
  1288.                                     else
  1289.                                         DragWindow(whichWindow, e.where, &qd.screenBits.bounds);
  1290.                                     break;
  1291.                         case inGrow:
  1292.                                     break;
  1293.                         case inGoAway:
  1294.                                     if (TrackGoAway(whichWindow, e.where))
  1295.                                         CloseDocument(GetWindowDocument(whichWindow));
  1296.                                     break;
  1297.                     }
  1298.                 }
  1299.                 }
  1300.                 break;
  1301.  
  1302.             case updateEvt:
  1303.                 UpdateDocument(GetWindowDocument((WindowPtr)e.message));
  1304.                 break;
  1305.             case keyDown:
  1306.                 {
  1307.                 char c;
  1308.  
  1309.                 c = e.message & charCodeMask;
  1310.                 if (e.modifiers & cmdKey) {
  1311.                     colorMenus();
  1312.                     gDone = doMenuItem(MenuKey(c));
  1313.                 }
  1314.                 }
  1315.                 break;
  1316.             case app4Evt:    
  1317.                 if ((e.message & 0xFF000000L) == 0x01000000L) {
  1318.                     if (e.message & 1) {
  1319.                         InitCursor();
  1320.                         ActivateDocument(GetWindowDocument(FrontWindow()));
  1321.                         gInBackground = false;
  1322.                     }
  1323.                     else
  1324.                         gInBackground = true;
  1325.                 }
  1326.                 break;
  1327.             case activateEvt:
  1328.                 ActivateDocument(GetWindowDocument((WindowPtr)e.message));
  1329.                 break;
  1330.             case kHighLevelEvent:
  1331.                 AEProcessAppleEvent(&e);
  1332.                 break;
  1333.         }
  1334.  
  1335.     } while (!gDone);
  1336.  
  1337.     // QuickTime will take care of cleaning up after itself...
  1338. }
  1339.