Back to index

lightning-sunbird  0.9+nobinonly
nsNativeAppSupportForCocoa.mm
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla Communicator client code.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1998
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #import <Cocoa/Cocoa.h>
00038 
00039 #include "nsNativeAppSupport.h"
00040 #include "nsString.h"
00041 
00042 #include <Gestalt.h>
00043 #include <Dialogs.h>
00044 #include <Resources.h>
00045 #include <TextUtils.h>
00046 
00047 #include "nsIObserver.h"
00048 
00049 #define rSplashDialog 512
00050 
00051 const OSType kNSCreator = 'MOSS';
00052 const OSType kMozCreator = 'MOZZ';
00053 const SInt16 kNSCanRunStrArrayID = 1000;
00054 const SInt16 kAnotherVersionStrIndex = 1;
00055 
00056 class nsSplashScreenCocoa : public nsISplashScreen,
00057                           public nsIObserver
00058 {
00059 public:
00060 
00061     // dialog itemse
00062     enum {
00063       eSplashPictureItem = 1,
00064       eSplashStatusTextItem    
00065     };
00066     
00067             nsSplashScreenCocoa();    
00068     virtual ~nsSplashScreenCocoa();
00069 
00070     NS_DECL_ISUPPORTS
00071 
00072     NS_IMETHOD Show();
00073     NS_IMETHOD Hide();
00074 
00075     NS_DECL_NSIOBSERVER
00076 
00077 protected:
00078 
00079     DialogPtr mDialog;
00080 
00081 }; // class nsSplashScreenCocoa
00082 
00083 
00084 nsSplashScreenCocoa::nsSplashScreenCocoa()
00085 : mDialog(nsnull)
00086 {
00087 }
00088 
00089 
00090 nsSplashScreenCocoa::~nsSplashScreenCocoa()
00091 {
00092   Hide();
00093 }
00094 
00095 
00096 NS_IMPL_ISUPPORTS2(nsSplashScreenCocoa, nsISplashScreen, nsIObserver)
00097 
00098 NS_IMETHODIMP
00099 nsSplashScreenCocoa::Show()
00100 {
00101 printf("-- nsSplashScreenCocoa::Show()\n");
00102 #if 0
00103   mDialog = ::GetNewDialog(rSplashDialog, nil, (WindowPtr)-1L);
00104   if (!mDialog) return NS_ERROR_FAILURE;
00105 
00106   ::ShowWindow(GetDialogWindow(mDialog));
00107   ::SetPortDialogPort(mDialog);
00108 
00109   ::DrawDialog(mDialog);    // we don't handle events for this dialog, so we
00110                             // need to draw explicitly. Yuck.
00111 #endif
00112   return NS_OK;
00113 }
00114 
00115 NS_IMETHODIMP
00116 nsSplashScreenCocoa::Hide()
00117 {
00118 printf("-- nsSplashScreenCocoa::Hide()\n");
00119 #if 0
00120   if (mDialog)
00121   {
00122     ::DisposeDialog( mDialog );
00123     mDialog = nsnull;
00124   }
00125 #endif
00126   return NS_OK;
00127 }
00128 
00129 
00130 NS_IMETHODIMP
00131 nsSplashScreenCocoa::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData)
00132 {
00133   // update a string in the dialog
00134   
00135   nsCAutoString statusString;
00136   statusString.AssignWithConversion(someData);
00137 printf("\n[[[ Splash Screen -- %s ]]]\n\n", (const char *)statusString.get());
00138 
00139 #if 0
00140   Handle    item = nsnull;
00141   Rect      itemRect;
00142   short     itemType;
00143   ::GetDialogItem(mDialog, eSplashStatusTextItem, &itemType, &item, &itemRect);
00144   if (!item) return NS_OK;
00145   
00146   // convert string to Pascal string
00147   Str255    statusPStr;
00148   PRInt32   maxLen = statusString.Length();
00149   if (maxLen > 254)
00150     maxLen = 254;
00151   strncpy((char *)&statusPStr[1], (const char *)statusString, maxLen);
00152   statusPStr[0] = maxLen;
00153   
00154   ::SetDialogItemText(item, statusPStr);
00155   ::DrawDialog(mDialog);
00156 #endif
00157   return NS_OK;
00158 }
00159 
00160 
00161 #pragma mark -
00162 
00163 nsresult NS_CreateSplashScreen(nsISplashScreen**aResult)
00164 {
00165   if ( aResult ) {  
00166       *aResult = new nsSplashScreenCocoa;
00167       if ( *aResult ) {
00168           NS_ADDREF( *aResult );
00169           return NS_OK;
00170       } else {
00171           return NS_ERROR_OUT_OF_MEMORY;
00172       }
00173   } else {
00174       return NS_ERROR_NULL_POINTER;
00175   }
00176 }
00177 
00178 // Snagged from mozilla/xpinstall/wizrd/mac/src/SetupTypeWin.c
00179 // VersGreaterThan4 - utility function to test if it's >4.x running
00180 static Boolean VersGreaterThan4(FSSpec *fSpec)
00181 {
00182   Boolean result = false;
00183   short fRefNum = 0;
00184   
00185   ::SetResLoad(false);
00186   fRefNum = ::FSpOpenResFile(fSpec, fsRdPerm);
00187   ::SetResLoad(true);
00188   if (fRefNum != -1)
00189   {
00190     Handle  h;
00191     h = ::Get1Resource('vers', 2);
00192     if (h && **(unsigned short**)h >= 0x0500)
00193       result = true;
00194     ::CloseResFile(fRefNum);
00195   }
00196     
00197   return result;
00198 }
00199 
00200 PRBool NS_CanRun() 
00201 {
00202   // init Cocoa before anything else happens, like showing the 
00203   // splash screen.
00204   // XXX We leak the pool, but that's ok, it'll go away when the app quits
00205   [NSApplication sharedApplication];
00206   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
00207   
00208   return PR_TRUE;
00209 #if 0
00210   // Check for running instances of Mozilla or Netscape. The real issue
00211   // is having more than one app use the same profile directory. That would
00212   // be REAL BAD!!!!!!!!
00213 
00214   // The code below is a copy of nsLocalFile::FindRunningAppBySignature which is
00215   // a non-static method. Sounds silly that I have to create an nsILocalFile
00216   // just to call that method. At any rate, don't think we want to go through
00217   // all that rigmarole during startup anyway.
00218 
00219   ProcessInfoRec  info;
00220   FSSpec          tempFSSpec;
00221   ProcessSerialNumber psn, nextProcessPsn;
00222 
00223   nextProcessPsn.highLongOfPSN = 0;
00224   nextProcessPsn.lowLongOfPSN  = kNoProcess;
00225 
00226   // first, get our psn so that we can exclude ourselves when searching
00227   err = ::GetCurrentProcess(&psn);
00228 
00229   if (err != noErr)
00230     return PR_FALSE;
00231 
00232   // We loop while err == noErr, which should mean all our calls are OK
00233   // The ways of 'break'-ing out of the loop are:
00234   //   GetNextProcess() fails (this includes getting procNotFound, meaning we're at the end of the process list),
00235   //   GetProcessInformation() fails
00236   // The ways we should fall out of the while loop are:
00237   //   GetIndString() fails, err == resNotFound,
00238   //   we found a running mozilla process or running Netscape > 4.x process, err == fnfErr
00239   while (err == noErr)
00240   {
00241     err = ::GetNextProcess(&nextProcessPsn);
00242     if (err != noErr)
00243       break; // most likely, end of process list
00244     info.processInfoLength = sizeof(ProcessInfoRec);
00245     info.processName = nil;
00246     info.processAppSpec = &tempFSSpec;
00247     err = ::GetProcessInformation(&nextProcessPsn, &info);
00248     if (err != noErr)
00249       break; // aww crap, GetProcessInfo() failed, we're outta here
00250 
00251     if (info.processSignature == kNSCreator || info.processSignature == kMozCreator)
00252     {
00253       // if the found process is us, obviously, it's okay if WE'RE running,
00254       if (!(info.processNumber.lowLongOfPSN == psn.lowLongOfPSN &&
00255             info.processNumber.highLongOfPSN == psn.highLongOfPSN))
00256       {
00257         // check to see if Netscape process is greater than Netscape 4.x or
00258         // if process is Mozilla
00259         if ((info.processSignature == kNSCreator && VersGreaterThan4(&tempFSSpec)) ||
00260              info.processSignature == kMozCreator)
00261         {
00262           // put up error dialog
00263           Str255 str;
00264           ::GetIndString(str, kNSCanRunStrArrayID, kAnotherVersionStrIndex);
00265           if (StrLength(str) == 0)
00266             err = resNotFound; // set err to something so that we return false
00267           else
00268           {
00269             SInt16 outItemHit;
00270             if (str)
00271               ::StandardAlert(kAlertStopAlert, str, nil, nil, &outItemHit);
00272             err = fnfErr; // set err to something so that we return false
00273           }
00274         }
00275       }
00276     }
00277   }
00278 
00279   if (err == noErr || err == procNotFound)
00280     return PR_TRUE;
00281 
00282   return PR_FALSE;
00283 #endif
00284 }