home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 October: Mac OS SDK / Dev.CD Oct 96 SDK / Dev.CD Oct 96 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc Source Code / DocShell / OpenDocX.cpp < prev    next >
Encoding:
Text File  |  1996-04-22  |  18.2 KB  |  609 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        OpenDocX.cpp
  3.  
  4.     Contains:    OpenDoc™ launcher application
  5.  
  6.     Owned by:    Nick Pilch
  7.  
  8.     Copyright:    © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <5>    .04.1996    NP        1337753: Never show splash screen.
  13.          <4>     3/14/96    NP        1258295: Displayed alert when app is
  14.                                     double-clicked.
  15.          <3>     1/15/96    TJ        Cleaned Up
  16.          <2>     1/15/96    JA        1269485: Display splash screen only 1st
  17.                                     time launched.
  18.         <26>    10/27/95    TÇ        Remove code which checks for 32 bit
  19.                                     addressing.
  20.         <25>    10/25/95    TÇ        1281409 GM: OpenDoc needs an AboutBox.
  21.         <24>    10/24/95    CC        1290114: Unload the scrap earlier to avoid
  22.                                     segment loader errors or crash on low
  23.                                     application heap space.
  24.         <23>     9/29/95    eeh        1287262: use ShellDef.h
  25.         <22>     8/26/95    TÇ        1269688 FB1:  There is an unnecessary
  26.                                     variable
  27.         <21>     6/23/95    CC        1260976: Added UnloadScrap() after toolbox
  28.                                     initialization.
  29.         <20>     5/19/95    TÇ        1249396 (was BB) OpenDoc shell should
  30.                                     serialize stationery creation., 1235942
  31.                                     Launching the OpenDoc pref file causes a
  32.                                     1000 exception to be thrown, 1234877 BB:
  33.                                     OpenDoc creates a bad document if
  34.                                     stationary launch fails.
  35.         <19>     4/15/95    TÇ        #1236388 The launcher splash screen no
  36.                                     longer goes away when a document window is
  37.                                     opened
  38.         <18>      4/7/95    eeh        1234548: check for 24-bit mode
  39.         <17>      4/7/95    eeh        1221297: generalize ODOC handler to
  40.                                     HandleRequiredEvent
  41.         <16>     3/31/95    TÇ        1223445 Launcher barfs generating
  42.                                     stationery from R/O library
  43.                                     1223493 BB: Creating a stationary under low
  44.                                     disk space.
  45.                                     1226040 Launcher crashes if CFM68K is not
  46.                                     installed.
  47.                                     1222903 Launcher doesn't check whether it
  48.                                     could open the resource file for a library.
  49.                                     1233754 OpenDoc™ Launcher splash screen
  50.                                     should use vers 2 resource.
  51.         <15>     2/20/95    TÇ        #1210979 BB: 5-$ Bugs need to be evaluated
  52.                                     and removed from Shell
  53.                                     #1221861 BB: Incomplete AOCE support needs
  54.                                     to be removed from OpenDoc
  55.         <14>      2/2/95    CG        Added qd global.
  56.         <13>      2/2/95    CG        #1205177:  "Editors" and "OpenDoc
  57.                                     Libraries" folders are being registered
  58.                                     with cfm (PPC only).
  59.         <12>      1/9/95    NP        1209979: No changes. Check in to force
  60.                                     rebuild for old runtime.
  61.         <11>      1/6/95    jpa        Fix error reporting in HandleOpenDocuments.
  62.                                     [1198075]
  63.         <10>    12/20/94    jpa        Wait longer for CFM error event [1198075]
  64.          <9>     12/5/94    jpa        Catch CFM errors on document launch.
  65.                                     Display splash screen. [1198075]
  66.          <8>    10/12/94    TÇ        68K: check to see if an AEDesc is null
  67.                                     before disposing
  68.          <7>     9/15/94    TÇ        #1183572 implement OpenDoc Shell PlugIns,
  69.                                     got rid of a few warnings
  70.          <6>      9/8/94    eeh        #1185443: fix HandleOpenDocuments to
  71.                                     preserve "special params".
  72.          <5>     8/25/94    TÇ        #1183223 Enabled launching of documents in
  73.                                     folders other than that of the OpenDoc
  74.                                     libraries
  75.          <4>     7/25/94    TÇ        added Jens' fixes for better error
  76.                                     reporting and a few bug fixes of my own
  77.          <3>     7/19/94    TÇ        fixed a bug in ODXstrncpy
  78.          <2>     7/14/94    TÇ        changed resource copying code to using
  79.                                     constant names instead of hard coded
  80.                                     constants (for PPC)
  81.          <1>     7/13/94    TÇ        first checked in
  82.          <0>     6/27/94    SV        SOMverted
  83.         <11>     4/19/94    TÇ        Don't append a null character onto the end
  84.                                     of the name of the stationery file because
  85.                                     AFP chokes on it.
  86.         <10>     4/18/94    TÇ        Another fix for Symantec.  This time to
  87.                                     ODXstrncpy.
  88.          <9>     4/18/94    HL        Fixed Symantec Compilation.
  89.          <8>     4/18/94    TÇ        #1144379 Stationery model & generation have
  90.                                     been fixed to enable dragging & dropping of
  91.                                     stationery onto open documents.
  92.          <7>     4/11/94    TÇ        #1155854 Use CustomPutFile for Save A Copy.
  93.                                     Checks to make sure document's resource
  94.                                     fork was properly opened.
  95.          <6>     3/24/94    eeh        bug #1153053: Changes for PPC nativity (or
  96.                                     is it nativeness...?)
  97.          <5>     3/17/94    CG        #1151392: Removed #include ConstDef.h.
  98.          <4>     3/16/94    eeh        bug #1149649 cont'd: CopyNonDPParams needed
  99.                                     a return statement for Symantec
  100.          <3>     3/16/94    eeh        bug #1149649: added CopyNonDPParams
  101.          <2>     3/10/94    eeh        bug #1149632: added alias param to
  102.                                     LaunchDocument()
  103.         <14>      2/9/94    TÇ        PowerPC header fixes
  104.         <13>     1/18/94    TÇ        conserve type and creator of documents
  105.                                     being opened
  106.         <12>    12/17/93    TÇ        removed bogus semicolon at the end of the
  107.                                     line "    if (needUpdate);"
  108.         <11>    12/17/93    eeh        Code to install 'scsz' resource in
  109.                                     documents.
  110.         <10>     12/1/93    TÇ        added calls to FlushInstructionCache()
  111.                                     FlushDataCache() right before
  112.                                     LaunchApplication to fix 040 data cache vs.
  113.                                     instruction cache problem with copying
  114.                                     resources as data then launching a document
  115.                                     which uses them as code.
  116.          <9>    11/30/93    TÇ        added a cast to Ptr to pacify CFront
  117.          <8>    11/23/93    TÇ        mostly formatting
  118.          <7>    10/28/93    TÇ        use sizeof(FSSpec) instead of
  119.                                     GetPtrSize(theDocument)
  120.          <6>    10/27/93    TÇ        more of the same.
  121.          <5>    10/26/93    TÇ        nil out fields of AEDesc.
  122.          <4>    10/26/93    TÇ        add code to construct 'ODOC' aevt and pass
  123.                                     it along in the LaunchApplication call to
  124.                                     the document being launched
  125.          <3>    10/26/93    TÇ        need to also use CODE 2 "32-bit blah blah
  126.                                     blah" resource
  127.          <2>    10/23/93    TÇ        added code to verify and update CODE 0,
  128.                                     CODE 1, and SIZE -1 resource in documents
  129.                                     before they are launched
  130.          <1>    10/18/93    TÇ        first checked in
  131.  
  132.     To Do:
  133.     In Progress:
  134.         
  135. */
  136.  
  137.  
  138.  
  139. /*
  140.  
  141. This is the OpenDoc™ extension which is actually an application.
  142. The sole purpose of this extension is to satisfy the currnt "APPL" launching model in the Finder.
  143. When OpenDoc™ documents are double-clicked in the Finder, 
  144. Finder notices that the creator of the documents is the same as this extension,
  145. then launches this extension with those documents.
  146. The OpenDoc™ extension verifies and fixes if necessary,
  147. the resources in the documents,
  148. then launches the documents using the ProcessManager directly and quits.
  149.  
  150. */
  151.  
  152. #define ppcinterfaces        /* keeps GX headers quiet */
  153.  
  154. #ifndef __TYPES__
  155. #include <Types.h>
  156. #endif
  157.  
  158. #ifndef __GESTALTEQU__
  159. #include <GestaltEqu.h>
  160. #endif
  161.  
  162. #ifndef __TEXTUTILS__
  163. #include <TextUtils.h>
  164. #endif
  165.  
  166. #ifndef __OSEVENTS__
  167. #include <OSEvents.h>
  168. #endif
  169.  
  170. #ifndef __QUICKDRAW__
  171. #include <Quickdraw.h>
  172. #endif
  173.  
  174. #ifndef __FONTS__
  175. #include <Fonts.h>
  176. #endif
  177.  
  178. #ifndef __FILES__
  179. #include <Files.h>
  180. #endif
  181.  
  182. #ifndef __RESOURCES__
  183. #include <Resources.h>
  184. #endif
  185.  
  186. #ifndef __EVENTS__
  187. #include <Events.h>
  188. #endif
  189.  
  190. #ifndef __APPLEEVENTS__
  191. #include <AppleEvents.h>
  192. #endif
  193.  
  194. #ifndef __DIALOGS__
  195. #include <Dialogs.h>
  196. #endif
  197.  
  198. #ifndef __MENUS__
  199. #include <Menus.h>
  200. #endif
  201.  
  202. #ifndef __OSUTILS__
  203. #include <OSUtils.h>
  204. #endif
  205.  
  206. #ifndef __TOOLUTILS__
  207. #include <ToolUtils.h>
  208. #endif
  209.  
  210. #ifndef __ERRORS__
  211. #include <Errors.h>
  212. #endif
  213.  
  214. #ifndef __SCRAP__
  215. #include <Scrap.h>
  216. #endif
  217.  
  218.  
  219. #ifndef _REGISTER_
  220. #include <RegisterFileLibs.h>
  221. #endif
  222.  
  223. #ifndef _SHELLDEF_
  224. #include "ShellDef.h"
  225. #endif
  226.  
  227. #ifndef _ODPRCS_
  228. #include "ODPrcs.h"
  229. #endif
  230.  
  231. #ifndef _ODXDEF_
  232. #include "ODXDef.h"
  233. #endif
  234.  
  235. //==============================================================================
  236. // Constants
  237. //==============================================================================
  238.  
  239. const short kLaunchFailedAlert = 130;
  240. const short kGenericLaunchFailedAlert = 129;
  241.  
  242.  
  243. const long kQuitDelay          =  1 * 60;        /* Wait 1 second for an Apple event */
  244. const long kWaitForErrorDelay =  8 * 60;        /* Wait 8 seconds after trying to launch */
  245.  
  246.  
  247. #define SPLASHSCREEN 0                /* 1 enables splash screen, 0 disables */
  248.  
  249. //==============================================================================
  250. // Globals
  251. //==============================================================================
  252.  
  253. #ifndef __MWERKS__
  254. QDGlobals qd;
  255. #endif
  256.  
  257. //==============================================================================
  258. // Macros
  259. //==============================================================================
  260.  
  261. #define CHECK(EXPR)    if((err=(EXPR)) == noErr) ; else return err
  262.  
  263. //==============================================================================
  264. // Function Prototypes
  265. //==============================================================================
  266.  
  267. static DialogPtr    gSplashScreen = NULL;
  268. static long            gQuitTime;
  269.  
  270.  
  271. void            main( );
  272. static void        MainEventLoop( );
  273. static Boolean    FirstTimeLaunched( );
  274. static Boolean    ColorScreen( );
  275. static void     ReportError(StringPtr docName, OSErr err);
  276.  
  277. //static OSErr    CheckAppleEventForMissingParams(AppleEvent *theAppleEvent);
  278. extern "C" {
  279. static pascal OSErr    HandleOpenAppEvent(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon);
  280. static pascal OSErr    HandleRequiredEvent(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon);
  281. static pascal OSErr    NoOpAEHandler(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon);
  282. static pascal OSErr    HandleLaunchFailed(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon);
  283. }
  284.  
  285. //==============================================================================
  286. // OpenDocX Main and Event Loop
  287. //==============================================================================
  288.  
  289. //------------------------------------------------------------------------------
  290. // main
  291. //------------------------------------------------------------------------------
  292.  
  293. void main(void)
  294. {
  295.     MaxApplZone();
  296.     MoreMasters();
  297.  
  298.     // The scrap is copied into our application heap when the process is launched,
  299.     // occuping space otherwise used for launching documents.
  300.     // If the scrap is just the right size (approx. 30K), there isn't enough
  301.     // heap space left to launch a single document (the launcher will bail with 
  302.     // error -108).  Worse, if the scrap is just the right size, around 40K, 
  303.     // InitWindows will hang the system.  To avoid this, always unload the scrap.
  304.     // Testing for a nil scrap handle seems to avoid a write to nil by UnloadScrap.
  305.     // [cc]
  306.     if ( InfoScrap()->scrapHandle != nil )
  307.         UnloadScrap();
  308.  
  309.     InitGraf((Ptr)&qd.thePort);
  310.     InitFonts();
  311.     InitWindows();
  312.     InitMenus();
  313.     TEInit();
  314.     InitDialogs(nil);
  315.  
  316.     long gestaltResponse;
  317.     if ((Gestalt(gestaltCFMAttr, &gestaltResponse) != noErr) ||
  318.         !(gestaltResponse & (1<<gestaltCFMPresent)))
  319.     {
  320.         ReportError("\p",fragMgrInitErr);
  321.         return;
  322.     }
  323.         
  324.     SetCursor(*GetCursor(watchCursor));
  325.  
  326.     AEEventHandlerUPP odocUPP = NewAEEventHandlerProc(HandleRequiredEvent);
  327.     (void) AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
  328.             odocUPP, 0, false);
  329.     (void) AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
  330.             odocUPP, 0, false);
  331.  
  332.     AEEventHandlerUPP openAppUPP = NewAEEventHandlerProc(HandleOpenAppEvent);
  333.     (void) AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
  334.             openAppUPP, 0, false); // no refcon, not system handler
  335.  
  336. //    AEEventHandlerUPP noOpUPP = NewAEEventHandlerProc(NoOpAEHandler);
  337. //    (void) AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
  338. //            noOpUPP, 0, false);
  339. //    (void) AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
  340. //            noOpUPP, 0, false);
  341.  
  342.     // Install a handler for both "launch-failed" notification events
  343.     // so we can notify the user:
  344.     AEEventHandlerUPP handleErrUPP = NewAEEventHandlerProc(HandleLaunchFailed);
  345.     (void) AEInstallEventHandler(kCoreEventClass, kAEApplicationDied,
  346.             handleErrUPP, 0, false);
  347.     (void) AEInstallEventHandler(kCFMLaunchFailedEventClass, kCFMLaunchFailedEventID,
  348.             handleErrUPP, 0, false);
  349.     
  350.     MainEventLoop();
  351. }
  352.  
  353. //------------------------------------------------------------------------------
  354. //  MainEventLoop
  355. //------------------------------------------------------------------------------
  356.  
  357. static void MainEventLoop(void)
  358. {
  359.     EventRecord        anEvent;
  360.     
  361.     FlushEvents(everyEvent,0);
  362.     
  363. #if SPLASHSCREEN
  364.     if( !AreODDocumentsRunning() && FirstTimeLaunched() )
  365.         gSplashScreen = ShowAboutScreen();
  366. #endif
  367.  
  368.     for( gQuitTime=TickCount()+kQuitDelay; TickCount()<gQuitTime; ) {
  369.         (void) WaitNextEvent(everyEvent,&anEvent,5,(RgnHandle) nil);
  370.         switch (anEvent.what)
  371.         {
  372.             case nullEvent:
  373.                 break;
  374.             
  375.             case osEvt:
  376.                 break;
  377.  
  378.             case kHighLevelEvent:
  379.                 AEProcessAppleEvent(&anEvent);
  380.                 break;
  381.             
  382.             default:
  383.                 if( IsDialogEvent(&anEvent) ) {
  384.                     DialogPtr whichDlog;
  385.                     short itemHit;
  386.                     if( DialogSelect(&anEvent,&whichDlog,&itemHit) && itemHit>0 )
  387.                         return;
  388.                 } else
  389.                     return;
  390.         }
  391.     }
  392. }
  393.  
  394. //------------------------------------------------------------------------------
  395. // FirstTimeLaunched
  396. //------------------------------------------------------------------------------
  397.  
  398. static Boolean FirstTimeLaunched( )
  399. {
  400.     /* To figure out if this is the first time launched today, check the mod
  401.        date of the "OpenDoc Preferences" file and compare it with today's date.
  402.        If it's earlier, this is the first time today; set the mod date to the
  403.        current date/time to signal that the launcher has run today. */
  404.     
  405.     FSSpec prefss;
  406.     if( GetPrefsFileSpec(&prefss) != noErr )
  407.         return true;
  408.     
  409.     CInfoPBRec pb;
  410.     pb.hFileInfo.ioNamePtr = prefss.name;
  411.     pb.hFileInfo.ioFDirIndex = 0;
  412.     pb.hFileInfo.ioVRefNum = prefss.vRefNum;
  413.     pb.hFileInfo.ioDirID = prefss.parID;
  414.     OSErr error = PBGetCatInfoSync(&pb);
  415.     if( error )
  416.         return (error==fnfErr);
  417.     
  418.     // Convert mod-time to date format, and get current date:
  419.     DateTimeRec prefsDate,curDate;
  420.     SecondsToDate(pb.hFileInfo.ioFlMdDat,&prefsDate);
  421.     GetTime(&curDate);
  422.  
  423.     // Compare:
  424.     if( prefsDate.year==curDate.year && prefsDate.month==curDate.month && prefsDate.day==curDate.day )
  425.         return false;
  426.     
  427.     // Not yet launched today. Bump mod date of file & return true:
  428.     GetDateTime(&pb.hFileInfo.ioFlMdDat);
  429.     pb.hFileInfo.ioDirID = prefss.parID;
  430.     PBSetCatInfoSync(&pb);
  431.     return true;
  432. }
  433.  
  434. //==============================================================================
  435. // Error reporting
  436. //==============================================================================
  437.  
  438. static void ReportError(StringPtr docName, OSErr err)
  439. {    
  440.     // If it's not legal to interact with the user, do nothing:
  441.     if(AEInteractWithUser(0,NULL,NULL) == errAENoUserInteraction)
  442.         return;
  443.     
  444.     // Bring myself to the front:
  445.     ProcessSerialNumber psn;
  446.     psn.highLongOfPSN = 0;
  447.     psn.lowLongOfPSN = kCurrentProcess;
  448.     SetFrontProcess(&psn);
  449.     
  450. #if SPLASHSCREEN
  451.     if( gSplashScreen ) {
  452.         DisposeDialog(gSplashScreen);
  453.         gSplashScreen = NULL;
  454.     }
  455. #endif
  456.  
  457.     // Display the alert:
  458.     short alertID = docName[0] ?kODXErrAlert :kODXAnonErrAlert;
  459.     if( Get1Resource('ALRT',alertID) ) {
  460.         unsigned char errStr[12];
  461.         NumToString(err,errStr);
  462.         ParamText(docName,errStr,NULL,NULL);
  463.         InitCursor();
  464.         StopAlert(alertID, NULL);
  465.     } else {
  466.         SysBeep(3);
  467.         SysBeep(3);
  468.     }
  469. }
  470.  
  471. //==============================================================================
  472. // Apple Event handlers
  473. //==============================================================================
  474.  
  475. //------------------------------------------------------------------------------
  476. // HandleRequiredEvent
  477. //------------------------------------------------------------------------------
  478.  
  479. pascal OSErr HandleRequiredEvent(AppleEvent *theAppleEvent,
  480.         AppleEvent * /*reply*/,long /*refCon*/)
  481. {
  482.     AEDescList    documentList;
  483.     long        documentCount;
  484.     OSErr        err = noErr;
  485.     FSSpec        theFSSpec;
  486.  
  487.     GetOpenDocBinaryFileSpec(kODNULL); // Sets up CFM search paths.
  488.     
  489.     CHECK(AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,&documentList));
  490.     CHECK(AECountItems(&documentList,&documentCount));
  491.     DescType evtID;
  492.     DescType ignoreType;
  493.     Size ignoreActual;
  494.     CHECK( AEGetAttributePtr( theAppleEvent, keyEventIDAttr, typeType,
  495.             &ignoreType, &evtID, sizeof(evtID), &ignoreActual ));
  496.  
  497.     err = noErr;
  498.     
  499.     FSSpec        seedFSSpec;
  500.     seedFSSpec.name[0] = 0;
  501.  
  502.     AEDesc        documentDesc;
  503.     
  504.     while (documentCount && (err == noErr))
  505.     {
  506.         AEKeyword    theAEKeyword;
  507.         
  508.         CHECK(AEGetNthDesc(&documentList, documentCount, typeWildCard,
  509.                 &theAEKeyword, &documentDesc));
  510.         if( GetDescFSSpec(&documentDesc,theFSSpec) != noErr )
  511.             theFSSpec.name[0] = 0;
  512.         err = VerifyAndLaunchDocumentStub(&documentDesc, kODNULL,
  513.                 kODNULL, evtID, &seedFSSpec);
  514.         --documentCount;
  515.         // Note: documentDesc gets leaked everytime through this loop
  516.         // Doesn't matter since the launcher quits soon anyway.
  517.         // And, the last documentDesc is necessary for launching a seed.
  518.     }
  519.     
  520.     if (seedFSSpec.name[0] != 0)
  521.         err= LaunchDocumentStub(&documentDesc, &seedFSSpec, kODNULL,
  522.                 kODNULL, kODNULL, evtID);
  523.         
  524.     if (err)
  525.         ReportError(theFSSpec.name, err);
  526.     else
  527.         gQuitTime = TickCount() + kWaitForErrorDelay;    // Give time for error to come back
  528.  
  529.     return err;
  530. }
  531.     
  532. //------------------------------------------------------------------------------
  533. // HandleOpenAppEvent
  534. //
  535. //    We only expect to handle open-document events. If we get an open-application
  536. //    event, then the user must have double-clicked us. This doesn't do anything,
  537. //    so we put up an alert telling him so.
  538. //------------------------------------------------------------------------------
  539.  
  540. static pascal OSErr HandleOpenAppEvent(
  541.     AppleEvent * /*theAppleEvent*/,
  542.     AppleEvent * /*reply*/,
  543.     long /*refCon*/)
  544. {
  545.     SetCursor(&qd.arrow);
  546.     CautionAlert(kODXDoubleClickAlert, NULL);
  547.     return noErr;
  548. }
  549.  
  550. //------------------------------------------------------------------------------
  551. // NoOpAEHandler
  552. //
  553. //    NP: No reason to have this as far as I know
  554. //------------------------------------------------------------------------------
  555.  
  556. static pascal OSErr NoOpAEHandler(
  557.     AppleEvent * /*theAppleEvent*/,
  558.     AppleEvent * /*reply*/,
  559.     long /*refCon*/)
  560. {
  561.     return(noErr);
  562. }
  563.  
  564. static pascal OSErr
  565. HandleLaunchFailed( AppleEvent *ae, AppleEvent * /*reply*/, long /*refCon*/ )
  566. {
  567.      // This is an Apple Event handler that catches launch-failed events.
  568.     
  569.     long launchError;
  570.     unsigned char launchErrorString[12];
  571.     Str255 appName, libName;
  572.     
  573.     GetLaunchFailedParams(ae, launchError,NULL,appName,libName);
  574.     if( launchError==noErr )
  575.         return noErr;
  576.         
  577.     NumToString(launchError,launchErrorString);
  578.  
  579.     {
  580.         // Force myself to the foreground:
  581.         ProcessSerialNumber psn = {0,kCurrentProcess};
  582.         (void) SetFrontProcess(&psn);
  583.     }
  584.     
  585. #if SPLASHSCREEN
  586.     if( gSplashScreen ) {
  587.         DisposeDialog(gSplashScreen);
  588.         gSplashScreen = NULL;
  589.     }
  590. #endif
  591.  
  592.     InitCursor();
  593.     if( appName[0]==0 ) {
  594.         ParamText(NULL,launchErrorString,NULL,NULL);
  595.         StopAlert(kGenericLaunchFailedAlert,NULL);
  596.     } else {
  597.         short index;
  598.         Str255 errorDescription;
  599.         if( launchError <= -2800 && launchError >= -2824 )
  600.             index = 2-2800-launchError;        // Maps -2800..-2824 -> 2..26
  601.         else
  602.             index = 1;
  603.         GetIndString(errorDescription, kLaunchFailedErrStrings,index);
  604.         ParamText(appName,errorDescription,libName,launchErrorString);
  605.         StopAlert(kLaunchFailedAlert,NULL);
  606.     }
  607.     return noErr;
  608. }
  609.