home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / macfe / central / errmgr.cp < prev    next >
Encoding:
Text File  |  1998-04-08  |  12.6 KB  |  458 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. // errmgr.cp, Mac front end ErrorManager
  20.  
  21. // Editorial comments:
  22. //
  23. //        Viewing some of this code may make you scream in panic
  24. //        Don't try this at home
  25. //        Use only under medical supervision
  26.  
  27. #include "uerrmgr.h"
  28.  
  29. #include <UDesktop.h>
  30. #include "uapp.h"
  31. #include "PascalString.h"
  32. #include "xpassert.h"
  33. #include "macutil.h"
  34. #include "resgui.h"
  35. #include "xp_error.h"
  36. #include "UTextBox.h"
  37. #include "resdef.h"
  38. #include "macfeprefs.h"
  39. // Apple
  40. #include <Notification.h>
  41. #include <Resources.h>
  42. #include <AppleEvents.h>
  43. #include <Dialogs.h>
  44.  
  45. #include <Icons.h>
  46.  
  47. #include "libi18n.h"
  48.  
  49. static void InitializeStrings();    // Need proto to use before declaration
  50.  
  51. OSType ErrorManager::sAlertApp = emSignature;
  52.  
  53. // Converts an OSErr to appropriate string.
  54. // Just prints the number for now, might do something more
  55. // useful in the future
  56. const CStr255 ErrorManager::OSNumToStr(OSErr err)
  57. {
  58.     Str255 str;
  59.     NumToString((long)err, str);
  60.     CStr255 retStr(str);
  61.     return retStr;
  62. }
  63.  
  64. // PrepareToInteract makes sure that this is the frontmost application.
  65. // If Netscape is not in the foreground, it blinks the small icon in
  66. // the menu bar until the user brings us to front
  67. void ErrorManager::PrepareToInteract()
  68. {
  69.     TryToInteract(10000000);
  70. }
  71.  
  72. // TryToInteract tries to bring Netscape to foreground (like PrepareToInteract)
  73. // If user does not bring Netscape to foreground in 900 seconds, 
  74. // it returns FALSE;
  75. Boolean ErrorManager::TryToInteract(long wait)
  76. {
  77.     ProcessSerialNumber netscapeProcess, frontProcess;
  78.     OSErr err = ::GetCurrentProcess(&netscapeProcess);
  79.     Boolean inFront = IsFrontApplication();
  80.     if (!inFront)
  81.     {
  82.         unsigned long start, currentTime;
  83.         ::GetDateTime(&start);
  84.         currentTime = start;
  85.         NMRec nmRec;
  86.         Handle iconSuite;
  87.         err = ::GetIconSuite (&iconSuite, 128,svAllSmallData);
  88.         nmRec.qLink = 0;
  89.         nmRec.qType = nmType;
  90.         nmRec.nmMark = true;
  91.         nmRec.nmIcon = iconSuite;
  92.         nmRec.nmStr = NULL;
  93.         nmRec.nmSound = (Handle)-1;
  94.         nmRec.nmResp = NULL;
  95.         err = ::NMInstall(&nmRec);    // Remove the call automatically
  96.         if (err == noErr)
  97.         {
  98.             while (!inFront && ((currentTime - start) < wait))
  99.             {
  100.                 EventRecord event;
  101.                 ::WaitNextEvent(0, &event, 30, NULL);
  102.                 ::GetFrontProcess(&frontProcess);
  103.                 ::GetDateTime(¤tTime);
  104.                 ::SameProcess(&frontProcess, &netscapeProcess, &inFront);
  105.             }
  106.             ::NMRemove(&nmRec);
  107.         }
  108. #if defined(DEBUG) && defined(ALEKS)
  109.         XP_Abort();
  110. #endif
  111.         UDesktop::Resume();    // Because the resume event gets eaten up by dialog box
  112. // Now, process any update events, so that our windows get refreshed properly
  113.         EventRecord event;
  114.         while (::WaitNextEvent(updateEvt, &event, 1, NULL))
  115.             (CFrontApp::GetApplication())->DispatchEvent(event);
  116.     }
  117.     return inFront;
  118. }
  119.  
  120. // Class that resizes the alert dialog
  121.  
  122. // Resizes 
  123. void ShrinkToFitAlertDialog(cstring & temp);
  124. void ShrinkToFitAlertDialog(cstring & temp)
  125. {
  126.     Handle ditl = ::GetResource('DITL', ALRT_PlainAlert);
  127.     StHandleLocker lock(ditl);
  128.     Handle alrt = ::GetResource('ALRT', ALRT_PlainAlert);
  129.     StHandleLocker lock2(alrt);
  130.     
  131. // ÑÑÑ WARNING ÑÑÑ <ftang> 
  132. //     You need to consider the PAD byte after each string
  133. #define IncludePadByte(a)        (((a) & 1) ? ((a) +1) : (a))
  134.  
  135.     // This ugliness happens because my pointer arithmetic was messed up otherwise
  136.     UInt32 tmp = (UInt32)*ditl;
  137.     Rect * okRect = (Rect*)(tmp + 0x6);
  138.     // Offset + length of the OK string
  139.     Rect * editRect = (Rect*)(tmp + 0x14 + IncludePadByte(*(uint8*)(tmp + 0xF)));
  140.     StTextState textState;
  141.     TextFont(0);
  142.     TextSize(12);
  143.     short height = UTextBox::TextBoxDialogHeight((char*)temp, temp.length(), editRect,
  144.                     teForceLeft, 0);
  145.     if (height < 50)    // Need to make place for the icon
  146.         height = 50;
  147.     editRect->bottom = editRect->top + height;
  148.     okRect->top = editRect->bottom + 8;
  149.     okRect->bottom = okRect->top + 20;
  150. // Get the window resource
  151. // Strange thing here: after ALRT is called for the first time,
  152. // altrRect gets altered. Its top/left are strange (>30000)
  153. // So I reset them, and everything seems to work
  154. // I bet that the toolbox guys are storing alert state in these
  155.     Rect * alrtRect = (Rect*)*alrt;
  156.     alrtRect->top = 100;
  157.     alrtRect->bottom = alrtRect->top+ okRect->bottom + 8;
  158.     alrtRect->left = 185;
  159.     alrtRect->right = 577;
  160. }
  161.  
  162. void ShrinkToFitYorNDialog(cstring & temp);
  163. void ShrinkToFitYorNDialog(cstring & temp)
  164. {
  165.     Handle ditl = ::GetResource('DITL', ALRT_YorNAlert);
  166.     StHandleLocker lock(ditl);
  167.     Handle alrt = ::GetResource('ALRT', ALRT_YorNAlert);
  168.     StHandleLocker lock2(alrt);
  169.     // This ugliness happens because my pointer arithmetic was messed up otherwise
  170.     UInt32 base = (UInt32)*ditl;
  171.  
  172. // ÑÑÑ WARNING ÑÑÑ <ftang> 
  173. //     You need to consider the PAD byte after each string
  174.  
  175.     Rect * yesRect = (Rect*)(base + 0x6);
  176.     UInt8 * yesLen = (UInt8 *)(base + 0xF);
  177.     
  178.     Rect * noRect = (Rect*)(base + 0x14 + IncludePadByte(*yesLen));
  179.     UInt8 * noLen = (UInt8 *)(base + 0x1D + IncludePadByte(*yesLen));
  180.     Rect * editRect = (Rect*)(base + 0x22 + IncludePadByte(*yesLen) + IncludePadByte(*noLen));
  181.     StTextState textState;
  182.     TextFont(0);
  183.     TextSize(12);
  184.     short height = UTextBox::TextBoxDialogHeight((char*)temp, temp.length(), editRect,
  185.                     teForceLeft, 0);
  186.     if (height < 50)    // Need to make place for the icon
  187.         height = 50;
  188.     editRect->bottom = editRect->top + height;
  189.     yesRect->top = editRect->bottom + 8;
  190.     yesRect->bottom = yesRect->top + 20;
  191.     noRect->top = editRect->bottom + 8;
  192.     noRect->bottom = noRect->top + 20;
  193. // Get the window resource
  194. // Strange thing here: after ALRT is called for the first time,
  195. // altrRect gets altered. Its top/left are strange (>30000)
  196. // So I reset them, and everything seems to work
  197. // I bet that the toolbox guys are storing alert state in these
  198.     Rect * alrtRect = (Rect*)*alrt;
  199.     alrtRect->top = 185;
  200.     alrtRect->bottom = alrtRect->top+ yesRect->bottom + 8;
  201.     alrtRect->left = 185;
  202.     alrtRect->right = 590;
  203. }
  204.  
  205.     // Displays a vanilla alert. All strings inside the alert are 
  206.     // supplied by caller
  207. void ErrorManager::PlainAlert(const CStr255& s1, const char * s2, const char * s3, const char * s4)
  208. {
  209.     if (sAlertApp != emSignature)
  210.         return;
  211.     if (!TryToInteract(900))    // If we time out, go away
  212.         return;
  213.     CStr255 S1(s1);
  214.     CStr255 S2(s2);
  215.     CStr255 S3(s3);
  216.     CStr255 S4(s4);
  217.     ConvertCRtoLF(S1);
  218.     ConvertCRtoLF(S2);
  219.     ConvertCRtoLF(S3);
  220.     ConvertCRtoLF(S4);
  221.     ParamText(S1, S2, S3, S4);
  222.     cstring temp;
  223.     temp += s1;
  224.     temp += s2;
  225.     temp += s3;
  226.     temp += s4;
  227.     ShrinkToFitAlertDialog(temp);
  228.     UDesktop::Deactivate();
  229.     ::CautionAlert(ALRT_PlainAlert, NULL);
  230.     UDesktop::Activate();
  231. }
  232.  
  233. void ErrorManager::PlainAlert( short resID )
  234. {
  235.     InitializeStrings();
  236.     
  237.     if (sAlertApp != emSignature)
  238.         return;
  239.  
  240.     CStr255            cstr[ 4 ];
  241.     StringHandle    strings[ 4 ];
  242.         
  243.     if ( !TryToInteract(900))
  244.         return;
  245.     
  246.     for ( short i = 0; i <= 3; i++ )
  247.     {
  248.         strings[ i ] = GetString( resID + i );
  249.         if ( strings[ i ] )
  250.             cstr[ i ] = **( (CStr255**)strings[ i ] );
  251.     }
  252.  
  253.     ParamText( cstr[ 0 ], cstr[ 1 ], cstr[ 2 ], cstr[ 3 ] );
  254.     cstring temp;
  255.     temp += cstr[ 0 ];
  256.     temp += cstr[ 1 ];
  257.     temp += cstr[ 2 ];
  258.     temp += cstr[ 3 ];
  259.     ShrinkToFitAlertDialog(temp);    // Size the dalog
  260.     UDesktop::Deactivate();
  261.     ::CautionAlert( ALRT_PlainAlert, NULL );
  262.     UDesktop::Activate();
  263. }
  264.  
  265. // Displays a yes or no alert. All strings inside the alert are 
  266. // supplied by caller
  267. Boolean ErrorManager::PlainConfirm(const char * s1, const char * s2, const char * s3, const char * s4)
  268. {
  269.     if (sAlertApp != emSignature)
  270.         return FALSE;
  271.  
  272.     if (!TryToInteract(900))    // If we time out, go away
  273.         return false;
  274.     CStr255 S1(s1);
  275.     CStr255 S2(s2);
  276.     CStr255 S3(s3);
  277.     CStr255 S4(s4);
  278.     ConvertCRtoLF(S1);
  279.     ConvertCRtoLF(S2);
  280.     ConvertCRtoLF(S3);
  281.     ConvertCRtoLF(S4);
  282.     
  283.     // pkc (6/6/96) Hack to stuff s1 into CStr255's if it's the
  284.     // only string passed in.
  285.     if( S1.Length() < strlen(s1) && s2 == NULL )
  286.     {
  287.         int storedLength = S1.Length();
  288.         S2 += (s1 + storedLength);
  289.         ConvertCRtoLF(S2);
  290.         storedLength += S2.Length();
  291.         if( storedLength < strlen(s1) )
  292.         {
  293.             S3 += (s1 + storedLength);
  294.             ConvertCRtoLF(S3);
  295.             storedLength += S3.Length();
  296.             if( storedLength < strlen(s1) )
  297.             {
  298.                 S4 += (s1 + storedLength);
  299.                 ConvertCRtoLF(S4);
  300.             }
  301.         }
  302.     }
  303.     
  304.     cstring temp;
  305.     temp += s1;
  306.     temp += s2;
  307.     temp += s3;
  308.     temp += s4;
  309.     ParamText(S1, S2, S3, S4);
  310.     ShrinkToFitYorNDialog(temp);
  311.     UDesktop::Deactivate();
  312.     int confirm = ::CautionAlert(ALRT_YorNAlert, NULL);
  313.     UDesktop::Activate();
  314.     return (confirm == 1);
  315. }
  316.  
  317. void ErrorManager::ErrorNotify(OSErr err, const CStr255& message)
  318. {
  319.         if (sAlertApp != emSignature)
  320.                 return;
  321.         CStr255 errNum = OSNumToStr(err);
  322.         PlainAlert(message, errNum);
  323. }
  324.  
  325. char * XP_GetString( int resID )
  326. {
  327.     XP_ASSERT( ( SHRT_MIN < resID ) && ( resID < SHRT_MAX ) );
  328.     return GetCString( resID + RES_OFFSET);
  329. }
  330.  
  331. static void XPStringsNotFoundAlert()
  332. {
  333.     Str255 stringsFileName;
  334.     
  335.     GetIndString(stringsFileName, 14000, 2); // From Bootstrap.rsrc.
  336.     ParamText(stringsFileName, NULL, NULL, NULL);
  337.     Alert (14003, NULL);
  338.     ExitToShell();
  339. }
  340.  
  341. //-----------------------------------
  342. static void InitializeStrings()
  343. {
  344.     static Boolean initialized = false;
  345.     if (initialized)
  346.         return;
  347.  
  348.     initialized = true;
  349.     
  350.     //    Locate and load all the XP string resources
  351.     //    in the "Netscape Resources" file
  352.     //    inside the "Essential Files" folder.
  353.     
  354.     FSSpec stringsFolderSpec;
  355.     
  356.     if (FindGutsFolder(&stringsFolderSpec) != noErr)
  357.         XPStringsNotFoundAlert();
  358.     
  359.     CInfoPBRec pb;
  360.     
  361.     pb.dirInfo.ioNamePtr = stringsFolderSpec.name;
  362.     pb.dirInfo.ioVRefNum = stringsFolderSpec.vRefNum;
  363.     pb.dirInfo.ioFDirIndex = 0;
  364.     pb.dirInfo.ioDrDirID = stringsFolderSpec.parID;
  365.     
  366.     if (PBGetCatInfoSync(&pb) != noErr)
  367.         XPStringsNotFoundAlert();
  368.  
  369.     Str255 stringFileName;
  370.     GetIndString(stringFileName, 14000, 2);
  371.     
  372.     FSSpec stringsFileSpec;
  373.     if (FSMakeFSSpec(pb.dirInfo.ioVRefNum, pb.dirInfo.ioDrDirID,
  374.         stringFileName, &stringsFileSpec) != noErr)
  375.         XPStringsNotFoundAlert();
  376.     
  377.     short currentFileRefNum = CurResFile();
  378.     short stringsFileRefNum = FSpOpenResFile(&stringsFileSpec, fsCurPerm);
  379.     
  380.     if (ResError() != noErr)
  381.         XPStringsNotFoundAlert();
  382.         
  383.     MoveResourceMapBelowApp();
  384.  
  385.     UseResFile(currentFileRefNum);
  386. } // InitializeStrings
  387.  
  388. void MoveResourceMapBelowApp()
  389. {
  390. #if PRAGMA_ALIGN_SUPPORTED
  391. #pragma options align=mac68k
  392. #else
  393. #error "There'll probably be a bug here."
  394. #endif
  395.     
  396.     //    Partial definition of "private" Resource Manager structure.
  397.     struct ResourceMap
  398.     {
  399.         char header[16];
  400.         ResourceMap **next;
  401.         short fileRefNum;
  402.     };
  403.     
  404. #if PRAGMA_ALIGN_SUPPORTED
  405. #pragma options align=reset
  406. #endif
  407.     
  408.     short applicationRefNum = LMGetCurApRefNum();
  409.     ResourceMap **stringsFileMap = (ResourceMap **)LMGetTopMapHndl();
  410.     
  411.     //    Find the application's resource map.
  412.     for (ResourceMap **map = stringsFileMap; map; map = (*map)->next)
  413.     {
  414.         if ((*map)->fileRefNum == applicationRefNum)
  415.         {
  416.             //    Move the strings file below the application
  417.             //    in the current resource chain.
  418.             //    (Kids, don't do this at home!)
  419.             ResourceMap **top = (*stringsFileMap)->next;
  420.             LMSetTopMapHndl((Handle)top);
  421.             LMSetCurMap((*top)->fileRefNum);
  422.             (*stringsFileMap)->next = (*map)->next;
  423.             (*map)->next = stringsFileMap;
  424.             break;
  425.         }
  426.     }
  427.  
  428. //-----------------------------------
  429. char* GetCString( short resID )
  430. {
  431.     CStr255 pstring = GetPString(resID);
  432.     return (char*)pstring;
  433. } // GetCString
  434.  
  435. //-----------------------------------
  436. CStr255 GetPString( ResIDT resID )
  437. {
  438.     InitializeStrings();
  439.     StringHandle sh = GetString( resID );
  440.     if (sh && *sh)
  441.     {
  442.         StHandleLocker aLock((Handle)sh); // probably not necessary
  443.         return **(CStr255**)sh; // copy to caller's string.
  444.     }
  445.     CStr255 result; // initialized to empty by constructor.
  446.     return result; // This copies the string to the caller's string.    
  447. } // GetPString
  448.  
  449. char * INTL_ResourceCharSet(void)
  450. {
  451.     char *cbuf;
  452.     cbuf = (char *)GetCString(CHARSET_RESID);
  453.     if (cbuf[0] == '\0')
  454.         return "x-mac-roman";
  455.     return cbuf;  
  456. }
  457.