home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc™ Source Code / DocShell / RlShSync.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  11.4 KB  |  423 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        RlShSync.cpp
  3.  
  4.     Contains:    Document-synchronization stuff in the shell
  5.  
  6.     Owned by:    Nick Pilch
  7.     
  8.                 Portions by Mark Linton (see issue 23 of 'develop')
  9.  
  10.     Copyright:    © 1995 by Apple Computer, Inc., all rights reserved.
  11.  
  12.     Change History (most recent first):
  13.  
  14.          <2>     5/22/96    EL        #1304982: if file name is changed and there
  15.                                     is no other change, save the document so
  16.                                     that the property is updated immediately.
  17.          <6>     9/29/95    eeh        1287262: use ShellDef.h
  18.          <5>     9/12/95    JP        Check for null draft (build break)
  19.          <4>     9/11/95    JP        1269048 & 1283405: Cope with multiple
  20.                                     documents
  21.          <3>      9/5/95    TÇ        FBs: 1266428, 1274419, 1274421, 1274423,
  22.                                     1274429, 1274435 Fixed the Shell to handle
  23.                                     multiple documents in a process. Needed for
  24.                                     CyberDog.
  25.          <2>     8/15/95    TÇ        1261899 DocUtils getters should be renamed
  26.                                     Acquire___
  27.          <1>      8/8/95    jpa        first checked in
  28. */
  29.  
  30.  
  31. #ifndef _RLSHELL_
  32. #include "RlShell.h"
  33. #endif
  34.  
  35. #ifndef _SHELLDEF_
  36. #include "ShellDef.h"
  37. #endif
  38.  
  39. #ifndef SOM_ODDispatcher_xh
  40. #include <Disptch.xh>
  41. #endif
  42.  
  43. #ifndef SOM_ODWindowState_xh
  44. #include <WinStat.xh>
  45. #endif
  46.  
  47. #ifndef _DLOGUTIL_
  48. #include <DlogUtil.h>
  49. #endif
  50.  
  51. #ifndef _DOCUTILS_
  52. #include <DocUtils.h>
  53. #endif
  54.  
  55. #ifndef _INFOUTIL_
  56. #include <InfoUtil.h>
  57. #endif
  58.  
  59. #ifndef _PASCLSTR_
  60. #include <PasclStr.h>
  61. #endif
  62.  
  63. #ifndef _TEMPOBJ_
  64. #include <TempObj.h>
  65. #endif
  66.  
  67. #include <AppleEvents.h>
  68. #include <AERegistry.h>
  69. #include <Aliases.h>
  70. #include <Drag.h>
  71. #include <Folders.h>
  72. #include <Script.h>
  73.  
  74.  
  75. #undef ASK_SAVE_TO_TRASH    /* Define to ask user what to do when modified
  76.                                document is dragged to trash */
  77.  
  78.  
  79. //==============================================================================
  80. // Constants
  81. //==============================================================================
  82.  
  83. enum {                            // Buttons for kSHLDragToTrashAlert
  84.     kTrashSaveIndex = 1,
  85.     kTrashDontSaveIndex,
  86.     kTrashRetrieveIndex
  87. };
  88.  
  89. #ifndef kAEFinderSuite
  90. #define kAEFinderSuite 'fndr'
  91. #endif
  92.  
  93. #ifndef kAEPutAway
  94. #define kAEPutAway 'ptwy'
  95. #endif
  96.  
  97. const ODSShort kNumBetween = 20;
  98.  
  99.  
  100. //==============================================================================
  101. // Static Function Prototypes
  102. //==============================================================================
  103.  
  104. static void  ZoomWindowToTrash( WindowPtr );
  105. static OSErr SendFinderEvent(AEEventClass, AEEventID, const FSSpec& );
  106. static ODULong GetMostRecentVolModDate();
  107.  
  108.  
  109. //==============================================================================
  110. // Static Globals
  111. //==============================================================================
  112. static ODULong    lastChecked = 0;    // time of the last disk check
  113.  
  114. //==============================================================================
  115. // Shell Methods
  116. //==============================================================================
  117.  
  118. //-------------------------------------------------------------------------------------
  119. // RealShell::CheckFileLocation
  120. //-------------------------------------------------------------------------------------
  121.  
  122. ODBoolean
  123. RealShell::CheckFileLocation( )
  124. {
  125.     ODULong                n = 1;
  126.     ODULong                nowTime;
  127.     char                firstCStr[256], secondCStr[256];
  128.  
  129.     nowTime = GetMostRecentVolModDate();
  130.     if (nowTime == lastChecked)
  131.         return kODFalse;    // bail if we've already checked during this second
  132.     
  133.     ODDocument* document = ODGetNthOpenDocument(fEV, fSession, n);
  134.     RETURN_IF_NULL(document, kODFalse);
  135.  
  136.     while (document != kODNULL)
  137.     {
  138.         TempPlatformFile file = GetPlatformFileFromContainer(fEV, 
  139.                 document->GetContainer(fEV));
  140.         ODDraft* tempDraft = ODGetTempDraftFromOpenDocument(fEV, fSession, document);
  141.         if (tempDraft != kODNULL)
  142.         {
  143.             TempODPart root = ODAcquireRootPartOfDraft(fEV, tempDraft);
  144.             TempODName partName = ODGetPOName(fEV, root, kODNULL);
  145.             TempODName fileName = file->GetName();
  146.             
  147.             if(strcmp( GetITextString(partName, firstCStr),
  148.                     GetITextString(fileName, secondCStr) ) != 0)
  149.             {
  150.                 // Filename changed: save doc if no other change else rename root part
  151.                 
  152.                 if (!ODDocumentHasChanges(fEV, fSession, document))
  153.                     ODSaveDocument(fEV, fSession, document);
  154.                 else {
  155.                     ODSetPOName(fEV, root, fileName);
  156.                     ODRenamePartWindows(fEV, fSession, root, partName, fileName);
  157.                 }
  158.             }
  159.         }
  160.         
  161.         if(file->IsInTrash() ) {
  162.             // File has been moved to trash: close document.
  163. #ifdef ASK_SAVE_TO_TRASH
  164.             if( this->HasWriteAccess() && tempDraft && tempDraft->ChangedFromPrev(fEV) )
  165.                 this->Notify(&RealShell::NotifyDragToTrash);
  166.             else
  167. #endif
  168.                 this->CloseTrashedDocument(document, kAEYes);
  169.             return fDispatcher->ShouldExit(fEV);
  170.         } else
  171.             // If it's no longer in the trash, don't bother to notify:
  172.             this->CancelNotification(&RealShell::NotifyDragToTrash);
  173.         document = ODGetNthOpenDocument(fEV, fSession, ++n);
  174.     }
  175.     lastChecked = nowTime;
  176.     return kODFalse;
  177. }
  178.  
  179.  
  180. //-------------------------------------------------------------------------------------
  181. // RealShell::NotifyDragToTrash
  182. //-------------------------------------------------------------------------------------
  183.  
  184. void
  185. RealShell::NotifyDragToTrash( ODULong /*refCon*/ )
  186. {
  187. #ifdef ASK_SAVE_TO_TRASH
  188.     char    fileName[256];
  189.     this->GetUserFileName(fileName, 255);
  190.     CToPascalString(fileName);
  191.     ParamText((ConstStr255Param)fileName, kODNULL,kODNULL,kODNULL);
  192.  
  193.     ODSShort result= ShowAlert(fEV,kSHLDragToTrashAlert,GetODDialogFilter(),fSession);
  194.     if( result == kTrashRetrieveIndex )
  195.         SendFinderEvent(kAEFinderSuite,kAEPutAway, fFile.GetFileSpec());
  196.     else
  197.         this->CloseTrashedDocument( result==kTrashSaveIndex ?kAEYes :kAENo);
  198. #endif
  199. }
  200.  
  201.  
  202. void
  203. RealShell::CloseTrashedDocument(ODDocument* document, DescType saveOptions )
  204. {
  205.     ODSaveDocument(fEV, fSession, document);
  206.     {
  207.         TempODWindow w = fWindowState->AcquireFrontRootWindow(fEV);
  208.         ZoomWindowToTrash(w->GetPlatformWindow(fEV));
  209.     }
  210.     if (ODCloseDocument(fEV, fSession, document))
  211.         fDispatcher->Exit(fEV);
  212. }
  213.  
  214.  
  215. //==============================================================================
  216. // Static Functions
  217. //==============================================================================
  218.  
  219.  
  220. //-------------------------------------------------------------------------------------
  221. // GetTrashIconRect
  222. //-------------------------------------------------------------------------------------
  223.  
  224. static OSErr
  225. GetTrashIconRect(Rect *aRect) {
  226.     OSErr theError;
  227.     short theVRefNum;
  228.     long theDirID;
  229.     Str255 theName;
  230.     CInfoPBRec pb;
  231.     Point thePoint;
  232.     
  233.     theError = FindFolder(kOnSystemDisk, kTrashFolderType, kDontCreateFolder,
  234.         &theVRefNum, &theDirID);
  235.     if (theError == fnfErr) {
  236.         theError = FindFolder(kOnSystemDisk, kWhereToEmptyTrashFolderType, kDontCreateFolder,
  237.             &theVRefNum, &theDirID);
  238.     }
  239.     if (theError == noErr) {
  240.         pb.dirInfo.ioNamePtr = theName;
  241.         pb.dirInfo.ioVRefNum = theVRefNum;
  242.         pb.dirInfo.ioDrDirID = theDirID;
  243.         pb.dirInfo.ioFDirIndex = -1;    /* use ioDrDirID */
  244.         theError = PBGetCatInfoSync(&pb);
  245.         if (theError == noErr) {
  246.             thePoint.v = pb.dirInfo.ioDrUsrWds.frLocation.v;
  247.             thePoint.h = pb.dirInfo.ioDrUsrWds.frLocation.h;
  248.             LocalToGlobal(&thePoint);
  249.             aRect->top = thePoint.v;
  250.             aRect->left = thePoint.h;
  251.             aRect->bottom = aRect->top + 32;
  252.             aRect->right = aRect->left + 32;
  253.         }
  254.     }
  255.     return theError;
  256. }
  257.  
  258.  
  259. //-------------------------------------------------------------------------------------
  260. // UpdateDesktop
  261. //-------------------------------------------------------------------------------------
  262.  
  263. static void
  264. UpdateDesktop( )
  265. {
  266.     EventRecord theEvent;
  267.     (void)WaitNextEvent(0, &theEvent, 10, kODNULL);
  268. }
  269.  
  270. //-------------------------------------------------------------------------------------
  271. // ZoomWindowToTrash
  272. //-------------------------------------------------------------------------------------
  273.  
  274. static void
  275. ZoomWindowToTrash( WindowPtr aWindow )
  276. {
  277.     GrafPtr curPort, wmgrPort;
  278.     GetPort(&curPort);
  279.  
  280.     Rect theStartingRect, theEndingRect;
  281.     theStartingRect = aWindow->portRect;
  282.     SetPort(aWindow);
  283.     LocalToGlobal((Point*)&theStartingRect.top);
  284.     LocalToGlobal((Point*)&theStartingRect.bottom);
  285.  
  286.     HideWindow(aWindow);
  287.     UpdateDesktop();
  288.     GetWMgrPort(&wmgrPort);
  289.     SetPort(wmgrPort);
  290.  
  291.     OSErr theError = GetTrashIconRect(&theEndingRect);
  292.     if( !theError )
  293.         ZoomRects(&theStartingRect,&theEndingRect,kNumBetween,zoomNoAcceleration);
  294.  
  295.     SetPort(curPort);
  296. }
  297.  
  298.  
  299. #ifdef ASK_SAVE_TO_TRASH
  300.  
  301. //-------------------------------------------------------------------------------------
  302. // FindFinder
  303. //-------------------------------------------------------------------------------------
  304.  
  305. #define kSystemType    'FNDR'
  306. #define kFinderSig    'MACS'
  307.  
  308. static OSErr
  309. FindFinder(ProcessSerialNumberPtr aPSN)
  310. {
  311.     ProcessInfoRec    theProcessInfo;
  312.     FSSpec            theProcessFile;
  313.     Str31            theProcessName;
  314.     OSErr            theError = noErr;
  315.  
  316.     aPSN->lowLongOfPSN = 0;
  317.     aPSN->highLongOfPSN = kNoProcess;
  318.     theProcessInfo.processInfoLength = sizeof(ProcessInfoRec);
  319.     theProcessInfo.processName = theProcessName;
  320.     theProcessInfo.processAppSpec = &theProcessFile;
  321.     do {
  322.         theError = GetNextProcess(aPSN);
  323.         if (theError == noErr) {
  324.             GetProcessInformation(aPSN, &theProcessInfo);
  325.         }
  326.     } while(((theProcessInfo.processSignature != kFinderSig) ||
  327.         (theProcessInfo.processType != kSystemType)) &&
  328.         (theError == noErr));
  329.     return(theError);
  330. }
  331.  
  332.  
  333. //-------------------------------------------------------------------------------------
  334. // SendFinderEvent
  335. //-------------------------------------------------------------------------------------
  336.  
  337. static OSErr
  338. SendFinderEvent(AEEventClass aClass, AEEventID anID, 
  339.                 const FSSpec &aFile)
  340. {
  341.     OSErr theError;
  342.     AppleEvent theAppleEvent, theReplyEvent;
  343.     AEDesc targetAddrDesc, theFileDesc;
  344.     AEDescList theFileDescList;
  345.     AliasHandle theFileAlias;
  346.     ProcessSerialNumber theFinder;
  347.     
  348.     theAppleEvent.dataHandle = nil;
  349.     theFileDescList.dataHandle = nil;
  350.     theFileDesc.dataHandle = nil;
  351.     theFileAlias = nil;
  352.     theError = FindFinder(&theFinder);
  353.     if (theError == noErr) {    
  354.         theError = AECreateDesc(typeProcessSerialNumber, 
  355.             (Ptr)&theFinder, sizeof(ProcessSerialNumber), 
  356.             &targetAddrDesc);
  357.     }
  358.     if (theError == noErr) {    
  359.         theError = AECreateList(nil, 0, false, &theFileDescList);
  360.     }
  361.     if (theError == noErr) {
  362.         theError = NewAlias(nil, &aFile, &theFileAlias);
  363.     }
  364.     if (theError == noErr) {
  365.         HLock((Handle) theFileAlias);
  366.         theError = AECreateDesc(typeAlias, (Ptr) *theFileAlias, 
  367.             GetHandleSize((Handle) theFileAlias), &theFileDesc);
  368.         HUnlock((Handle) theFileAlias);
  369.     }
  370.     if (theError == noErr) {
  371.         theError = AEPutDesc(&theFileDescList, 0, &theFileDesc);
  372.     }
  373.     if (theError == noErr) {
  374.         theError = AECreateAppleEvent(aClass, anID, 
  375.             &targetAddrDesc, kAutoGenerateReturnID, 
  376.             kAnyTransactionID, &theAppleEvent);
  377.     }
  378.     if (theError == noErr) {
  379.         theError = AEPutParamDesc(&theAppleEvent, keyDirectObject, 
  380.             &theFileDescList);
  381.     }
  382.     if (theError == noErr) {
  383.         theError = AESend(&theAppleEvent, &theReplyEvent, 
  384.             kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer, 
  385.             kAENormalPriority, kAEDefaultTimeout, nil, nil);
  386.     }
  387.     if (theAppleEvent.dataHandle != nil) {
  388.         (void)AEDisposeDesc(&theAppleEvent);
  389.     }
  390.     if (theFileDescList.dataHandle != nil) {
  391.         (void)AEDisposeDesc(&theFileDescList);
  392.     }
  393.     if (theFileDesc.dataHandle != nil) {
  394.         (void)AEDisposeDesc(&theFileDesc);
  395.     }
  396.     if (theFileAlias != nil) {
  397.         DisposeHandle((Handle)theFileAlias);
  398.     }
  399.     return theError;
  400. }
  401.  
  402. #endif /*ASK_SAVE_TO_TRASH*/
  403.  
  404. ODULong
  405. GetMostRecentVolModDate()
  406. {
  407.     ODULong            bigModDate = 0;
  408.     OSErr            err = noErr;
  409.     ODSShort        index = 0;
  410.     HParamBlockRec    pb;
  411.     
  412.     pb.volumeParam.ioNamePtr = kODNULL; /* Don't care about name */
  413.     pb.volumeParam.ioVRefNum = 0;    /* Don't care about vRefNum */
  414.     while (err == noErr)
  415.     {
  416.         pb.volumeParam.ioVolIndex = ++index;
  417.         err = PBHGetVInfoSync(&pb);
  418.         if (err == noErr && pb.volumeParam.ioVLsMod > bigModDate)
  419.             bigModDate = pb.volumeParam.ioVLsMod;
  420.     }
  421.     return bigModDate;
  422. }
  423.