home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / macfe / central / CAppleEventHandler.cp < prev    next >
Encoding:
Text File  |  1998-04-08  |  58.3 KB  |  1,916 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. // CAppleEventHandler.cp
  20.  
  21. // ---- Apple Events
  22. #include "CAppleEventHandler.h"
  23.  
  24.  
  25. /*-------------------------------------------------------------*/
  26. //                    Includes
  27. /*-------------------------------------------------------------*/
  28.  
  29. // --- just in case
  30. #include "uapp.h"
  31.  
  32. // --- Netscape macfe
  33. #include "Netscape_Constants.h"
  34. #include "earlmgr.h"
  35. #include "findw.h"
  36. #include "macgui.h"
  37. #include "macutil.h"
  38. #include "CBookmarksAttachment.h"
  39. #include "BookmarksFile.h"
  40. #include "mimages.h"
  41. #include "mplugin.h"
  42.  
  43. #if defined (JAVA)
  44. #include "mjava.h"
  45. #endif /* defined (JAVA) */
  46.  
  47. #include "mregistr.h"
  48. #include "prefw.h"
  49. #include "resae.h"
  50. #include "resgui.h"
  51. #include "uerrmgr.h"
  52. #include "ufilemgr.h"
  53.  
  54. // -- For getting Profile information
  55. #include "prefapi.h"
  56.  
  57. // --- Netscape Misc
  58. #include "CEditorWindow.h"
  59. #include "CBrowserWindow.h"
  60.  
  61. // --- Just plain Misc
  62. #include "mkutils.h" // only for  FREEIF() macro.  JRM 96/10/17
  63.  
  64. // --- Natscape NS
  65. #include "CNSContextCallbacks.h"
  66.  
  67. // --- Natscape Browser
  68. #include "CBrowserContext.h"
  69. #include "CBrowserWindow.h"
  70.  
  71. // --- Natscape MailNews
  72. #ifdef MOZ_MAIL_NEWS
  73. #include "MailNewsSearch.h"
  74. #include "MailNewsFilters.h"
  75. #include "MailNewsAddressBook.h"
  76. #include "MailNewsClasses.h"
  77. #include "MailNewsgroupWindow_Defines.h"
  78. #endif // MOZ_MAIL_NEWS
  79. #include "BrowserClasses.h"
  80.  
  81. // --- Mac Toolbox
  82. #include <Displays.h>        // For the display notice event
  83. #include <Balloons.h>
  84. #include <Errors.h>
  85. #include <EPPC.h>
  86.  
  87.  
  88.  
  89. #include "CURLDispatcher.h"
  90. #include "xp.h"
  91.  
  92. /*--------------------------------------------------------------*/
  93. //        Constructor, Destructor and Dispach
  94. /*--------------------------------------------------------------*/
  95.  
  96. /*----------------------------------------------------------------
  97.     CAppleEventHandler::CAppleEventHandler
  98.     Constructor
  99. ----------------------------------------------------------------*/
  100. CAppleEventHandler::CAppleEventHandler()
  101. {
  102.     // Remember our one instance
  103.     sAppleEventHandler = this;
  104.     
  105.     // We assume not operating in kiosk mode unless told otherwise
  106.     fKioskMode = KioskOff;
  107.     
  108. }
  109. /*----------------------------------------------------------------
  110.     CAppleEventHandler::~CAppleEventHandler
  111.     Destructor
  112. ----------------------------------------------------------------*/
  113. CAppleEventHandler::~CAppleEventHandler()
  114. {
  115.     // Reste to NULL, we're gone
  116.     sAppleEventHandler = NULL;
  117. }
  118.  
  119. /*----------------------------------------------------------------
  120.     CAppleEventHandler::HandleAppleEvent
  121.     AppleEvent Dispach Here
  122.     In: & AppleEvent    Incoming apple event
  123.         & ReplyEvent    Reply event we can attach result info to
  124.         & Descriptor    OUtgoing descriptor
  125.           AppleEvent ID    The Apple Event ID we were called with.
  126.     Out: Event Handled by CAppleEvent
  127. ----------------------------------------------------------------*/
  128. void CAppleEventHandler::HandleAppleEvent(
  129.     const AppleEvent    &inAppleEvent,
  130.     AppleEvent            &outAEReply,
  131.     AEDesc                &outResult,
  132.     long                inAENumber)
  133. {
  134.     switch (inAENumber)
  135.     {
  136.         case AE_GetURL:
  137.         case AE_OpenURL:
  138.         case AE_OpenProfileManager:
  139.                                                 // Required Suite
  140.         case ae_OpenApp:
  141.         case ae_OpenDoc:
  142.         case ae_PrintDoc:
  143.         case ae_Quit:
  144.             break;
  145.             
  146.         default:
  147.             if (!(CFrontApp::GetApplication() && CFrontApp::GetApplication()->HasProperlyStartedUp()))
  148.             {
  149.                 // Ignore all apple events handled by this handler except get url, open
  150.                 // url and the required suite until we have properly started up.
  151.                 return;            
  152.             }
  153.             break;
  154.     }
  155.  
  156.     switch (inAENumber) {    
  157.     
  158.         // ### Mac URL standard Suite
  159.         // -----------------------------------------------------------
  160.         case AE_GetURL:    // Direct object - url, cwin - HyperWindow
  161.             HandleGetURLEvent( inAppleEvent, outAEReply, outResult, inAENumber );
  162.             break;
  163.             
  164.         // ### Spyglass Suite
  165.         // -----------------------------------------------------------
  166.         case AE_OpenURL:
  167.             HandleOpenURLEvent( inAppleEvent, outAEReply, outResult, inAENumber );
  168.             break;
  169.             
  170.         case AE_CancelProgress:
  171.             HandleCancelProgress( inAppleEvent, outAEReply, outResult, inAENumber);
  172.             break;
  173.             
  174.         case AE_FindURL:        // located elsewhere
  175.             CFileMgr::sFileManager.HandleFindURLEvent(inAppleEvent, outAEReply, outResult, inAENumber);
  176.             break;
  177.  
  178.         case AE_ShowFile:
  179.             HandleShowFile(inAppleEvent, outAEReply, outResult, inAENumber);
  180.             break;
  181.             
  182.         case AE_ParseAnchor:
  183.             HandleParseAnchor(inAppleEvent, outAEReply, outResult, inAENumber);
  184.             break;
  185.             
  186.         case AE_SpyActivate:
  187.             HandleSpyActivate(inAppleEvent, outAEReply, outResult, inAENumber);
  188.             break;
  189.             
  190.         case AE_SpyListWindows:
  191.             HandleSpyListWindows(inAppleEvent, outAEReply, outResult, inAENumber);
  192.             break;
  193.             
  194.         case AE_GetWindowInfo:
  195.             HandleSpyGetWindowInfo(inAppleEvent, outAEReply, outResult, inAENumber);
  196.             break;
  197.             
  198.         case AE_RegisterWinClose:
  199.         case AE_UnregisterWinClose:
  200.             HandleWindowRegistration(inAppleEvent, outAEReply, outResult, inAENumber);
  201.             break;
  202.             
  203.         // --- These Spyglass events are handled elswhere
  204.         case AE_RegisterViewer:
  205.             CPrefs::sMimeTypes.HandleRegisterViewerEvent( inAppleEvent, outAEReply, outResult, inAENumber );
  206.             break;
  207.             
  208.         case AE_UnregisterViewer:
  209.             CPrefs::sMimeTypes.HandleUnregisterViewerEvent( inAppleEvent, outAEReply, outResult, inAENumber );
  210.             break;
  211.             
  212.         case AE_RegisterProtocol:
  213.         case AE_UnregisterProtocol:
  214.         case AE_RegisterURLEcho:
  215.         case AE_UnregisterURLEcho:
  216.             CNotifierRegistry::HandleAppleEvent(inAppleEvent, outAEReply, outResult, inAENumber);
  217.             break;
  218.  
  219.             
  220.         // ### Netscape Experimental Suite
  221.         // -----------------------------------------------------------
  222.         case AE_OpenBookmark:
  223.             HandleOpenBookmarksEvent( inAppleEvent, outAEReply, outResult, inAENumber );
  224.             break;
  225.             
  226.         case AE_ReadHelpFile:
  227.             HandleReadHelpFileEvent( inAppleEvent, outAEReply, outResult, inAENumber );
  228.             break;
  229.             
  230.         case AE_Go:
  231.             HandleGoEvent (inAppleEvent, outAEReply, outResult, inAENumber );
  232.             break;
  233.             
  234.         case AE_GetWD:    // Return Working Directory
  235.             HandleGetWDEvent( inAppleEvent, outAEReply, outResult, inAENumber );
  236.             break;
  237.         
  238.         case AE_OpenProfileManager:
  239.             CFrontApp::sApplication->ProperStartup( NULL, FILE_TYPE_PROFILES );
  240.             break;
  241.                 
  242.         case AE_OpenAddressBook:
  243.             HandleOpenAddressBookEvent( inAppleEvent, outAEReply, outResult, inAENumber );
  244.             break;
  245.         
  246.         case AE_OpenComponent:
  247.             HandleOpenComponentEvent( inAppleEvent, outAEReply, outResult, inAENumber );
  248.             break;
  249.  
  250.         case AE_HandleCommand:
  251.             HandleCommandEvent( inAppleEvent, outAEReply, outResult, inAENumber );
  252.             break;
  253.             
  254.         case AE_GetActiveProfile:
  255.             HandleGetActiveProfileEvent( inAppleEvent, outAEReply, outResult, inAENumber );
  256.             break;
  257.             
  258.         // ### ????  2014 looks like it's a core suite thing, but not defined in the aedt
  259.         // -----------------------------------------------------------
  260. /*        case 2014:        // Display has changed. Maybe in 2.0, should change the pictures
  261.             {
  262.                 StAEDescriptor displayDesc;
  263.                 OSErr err = AEGetParamDesc(&inAppleEvent,kAEDisplayNotice,typeWildCard,&displayDesc.mDesc);
  264.                 if (err == noErr)
  265.                     SysBeep(1);
  266.             }
  267.             break;
  268. */        
  269.  
  270.         // ### If all else fails behave like a word processor
  271.         // -----------------------------------------------------------
  272.         default:
  273.             CFrontApp::sApplication->LDocApplication::HandleAppleEvent( inAppleEvent, outAEReply, outResult, inAENumber );
  274.             break;
  275.     }
  276. }
  277.  
  278. /*--------------------------------------------------------------------------*/
  279. /*            ----  Mac URL standard, supported by many apps   ----            */
  280. /*--------------------------------------------------------------------------*/    
  281.  
  282. /*----------------------------------------------------------------
  283.     CAppleEventHandler::HandleGetURLEvent            Suite:URL
  284.     Dispach the URL event to the correct window and let the
  285.     window handle the event.
  286.  
  287. GetURL: Loads the URL (optionaly to disk)
  288.  
  289.     GetURL  string  -- The url 
  290.         [to  file specification]     -- file the URL should be loaded into  
  291.         [inside  reference]          -- Window the URL should be loaded to
  292.         [from  string]                 -- Refererer, to be sent with the HTTP request
  293. ----------------------------------------------------------------*/
  294. void CAppleEventHandler::HandleGetURLEvent(
  295.     const AppleEvent    &inAppleEvent,
  296.     AppleEvent            &outAEReply,
  297.     AEDesc                &outResult,
  298.     long                /*inAENumber*/)
  299. {
  300.     // We need to make sure
  301.     
  302.     CFrontApp::sApplication->ProperStartup( NULL, FILE_TYPE_GETURL );
  303.  
  304.     // Get the window, and let it handle the event
  305.     StAEDescriptor    keyData;
  306.     OSErr err = ::AEGetKeyDesc(&inAppleEvent, AE_www_typeWindow, typeWildCard,&keyData.mDesc);
  307.     
  308.     // TODO: handle dispatching to storage
  309.     
  310.     if (CFrontApp::GetApplication()->HasProperlyStartedUp())
  311.     {
  312.         // A window was specified, open the url in that window
  313.         if ((err == noErr) && (keyData.mDesc.descriptorType == typeObjectSpecifier))
  314.         {
  315.             StAEDescriptor    theToken;
  316.             err = ::AEResolve(&keyData.mDesc, kAEIDoMinimum, &theToken.mDesc);
  317.             ThrowIfOSErr_(err);
  318.             LModelObject * model = CFrontApp::sApplication->GetModelFromToken(theToken.mDesc);
  319.             ThrowIfNil_(model);
  320.             
  321.             CBrowserWindow* win = dynamic_cast<CBrowserWindow*>(model);
  322.             ThrowIfNil_(win);
  323.             
  324.             CBrowserWindow::HandleGetURLEvent(inAppleEvent, outAEReply, outResult, win);        
  325.         }
  326.         // No window or file specified, we will open the url in the frontmost
  327.         // browser window or a new browser window if there are no open browser
  328.         // windows.
  329.         // Or no browser window if one is not appropriate.  Good grief! jrm.
  330.         else
  331.         {
  332.             try
  333.             {
  334.                 MoreExtractFromAEDesc::DispatchURLDirectly(inAppleEvent);
  335.             }
  336.             catch (...)
  337.             {
  338.                 // Get a window
  339.                 
  340.                 CBrowserWindow* win = CBrowserWindow::FindAndShow(true);
  341.                 ThrowIfNil_(win);
  342.                     
  343.                 // Let the window handle the event
  344.                 
  345.                 CBrowserWindow::HandleGetURLEvent(inAppleEvent, outAEReply, outResult, win);
  346.             }
  347.         }
  348.     }
  349.     else
  350.     {
  351.         CBrowserWindow::HandleGetURLEvent(inAppleEvent, outAEReply, outResult);        
  352.     }
  353. } // CAppleEventHandler::HandleGetURLEvent
  354.  
  355. /*--------------------------------------------------------------------------*/
  356. /*                     ----   The Spygless Suite   ----                        */
  357. /*--------------------------------------------------------------------------*/    
  358.  
  359. #define errMakeNewWindow 100
  360.  
  361. /*----------------------------------------------------------------
  362.     CAppleEventHandler::HandleOpenURLEvent        Suite:Spyglass
  363.     Open to a URL
  364.     In: Incoming apple event, reply event, outtgoing descriptor, eventID
  365.  
  366.         Flavors of OpenURL
  367.         #define AE_spy_openURL        'OURL'    // typeChar OpenURL
  368.             AE_spy_openURL_into            // typeFSS into
  369.             AE_spy_openURL_wind            // typeLongInteger windowID
  370.             AE_spy_openURL_flag            // typeLongInteger flags
  371.                 4 bits used.
  372.                 1 = 
  373.                 2 = 
  374.                 4 = 
  375.                 8 = Open into editor window
  376.             AE_spy_openURL_post            // typeWildCard post data
  377.             AE_spy_openURL_mime            // typeChar MIME type
  378.             AE_spy_openURL_prog            // typePSN Progress app
  379.             
  380.     Just like with GetURL, figure out the window, and let it handle the load
  381.     Arguments we care about: AE_spy_openURL_wind
  382.     
  383.     Out: OpenURLEvent handled
  384. ----------------------------------------------------------------*/
  385. void CAppleEventHandler::HandleOpenURLEvent(
  386.     const AppleEvent    &inAppleEvent,
  387.     AppleEvent            &outAEReply,
  388.     AEDesc                &outResult,
  389.     long                /*inAENumber*/)
  390. {
  391.     // We need to make sure
  392.     CFrontApp::sApplication->ProperStartup( NULL, FILE_TYPE_GETURL );
  393.     
  394.     // Get the Flags to see if we want an editor
  395.     try
  396.     {
  397.         long flags;
  398.         DescType realType;
  399.         Size actualSize;
  400.         OSErr err = ::AEGetParamPtr(&inAppleEvent, AE_spy_openURL_flag, typeLongInteger,
  401.                          &realType, &flags, sizeof(flags), &actualSize);
  402.         ThrowIfOSErr_(err);
  403. #ifdef EDITOR
  404.         if (flags & 0x8)
  405.         {
  406.             // Get the url (in case we want an editor)
  407.             char* url = NULL;
  408.             MoreExtractFromAEDesc::GetCString(inAppleEvent, keyDirectObject, url);
  409.             ThrowIfNil_(url);
  410.             // MAJOR CRASHING BUG!!!  if building Akbar 3.0 we should NOT CALL MakeEditWindow!!!
  411.             URL_Struct * request = NET_CreateURLStruct (url, NET_DONT_RELOAD);
  412.             XP_FREE (url);
  413.             ThrowIfNil_(request);
  414.             CEditorWindow::MakeEditWindow( NULL, request);
  415.             return;
  416.         }
  417. #endif // EDITOR
  418.     }
  419.     catch(...)
  420.     {
  421.     }
  422.  
  423.     if (CFrontApp::GetApplication()->HasProperlyStartedUp())
  424.     {
  425.         // Get the window, and let it handle the event
  426.         try
  427.         {
  428.             Int32 windowID;
  429.             Size realSize;
  430.             OSType realType;
  431.             
  432.             OSErr err = ::AEGetParamPtr(&inAppleEvent, AE_spy_openURL_wind, typeLongInteger,
  433.                              &realType, &windowID, sizeof(windowID), &realSize);
  434.             ThrowIfOSErr_(err);
  435.             
  436.             // If 0 then create a new window,  
  437.             //    If FFFF set to front most window
  438.             CBrowserWindow* win = NULL;
  439.             if (windowID == 0)
  440.             {
  441.                 win = CURLDispatcher::CreateNewBrowserWindow();
  442.             }
  443.             else if (windowID == 0xFFFFFFFF)    // Frontmost  window
  444.                 win = CBrowserWindow::FindAndShow();
  445.             else
  446.                 win = CBrowserWindow::GetWindowByID(windowID);
  447.             
  448.             ThrowIfNil_(win);
  449.             CBrowserWindow::HandleOpenURLEvent(inAppleEvent, outAEReply, outResult, win);        
  450.         }
  451.         catch(...)
  452.         {
  453.             MoreExtractFromAEDesc::DispatchURLDirectly(inAppleEvent);
  454.             return;
  455.         }            
  456.     }
  457.     else
  458.     {
  459.         CBrowserWindow::HandleOpenURLEvent(inAppleEvent, outAEReply, outResult);        
  460.     }
  461. } // CAppleEventHandler::HandleOpenURLEvent
  462.  
  463.  
  464. /*----------------------------------------------------------------
  465.     ShowFile
  466.     Similar to odoc, except that it takes a few extra arguments
  467.     keyDirectObject    file spec
  468.     AE_spy_showFile_mime MIME type (optional)
  469.     AE_spy_showFile_win window ID (optional)
  470.     AE_spy_showFile_url url (optional)
  471.  
  472.     ShowFile: Similar to OpenDocuments, except that it specifies the parent 
  473.         URL, and MIME type of the file
  474.         
  475.     ShowFile  
  476.         alias                      -- File to open
  477.         [MIME type  string]      -- MIME type
  478.         [Window ID  integer]      -- Window to open the file in
  479.         [URL  string]              -- Use this as a base URL
  480.         
  481.     Result:   
  482.         integer                  -- Window ID of the loaded window. 
  483.             0 means ShowFile failed, 
  484.             FFFFFFF means that data was not appropriate type to display in the browser.
  485. ----------------------------------------------------------------*/
  486. void CAppleEventHandler::HandleShowFile(const AppleEvent    &inAppleEvent, 
  487.         AppleEvent& /*outAEReply*/, AEDesc& /*outResult*/, long /*inAENumber*/)
  488. {
  489. Assert_(false);
  490.     char * url = NULL;
  491.     char * mimeType = NULL;
  492.     CBrowserWindow * win = NULL;
  493.     FSSpec fileSpec;
  494.     Boolean hasFileSpec = FALSE;
  495.     OSErr err;
  496.     Size    realSize;
  497.     OSType    realType;
  498.     
  499.     // Get the file specs
  500.     err = ::AEGetKeyPtr(&inAppleEvent, keyDirectObject, typeFSS,
  501.                         &realType, &fileSpec, sizeof(fileSpec), &realSize);
  502.     ThrowIfOSErr_(err);
  503.     
  504.     // Get the window
  505.     try
  506.     {
  507.         Int32 windowID;
  508.         err = ::AEGetParamPtr(&inAppleEvent, AE_spy_openURL_wind, typeLongInteger,
  509.                          &realType, &windowID, sizeof(windowID), &realSize);
  510.         ThrowIfOSErr_(err);
  511.         win = CBrowserWindow::GetWindowByID(windowID);
  512.         ThrowIfNil_(win);
  513.     }
  514.     catch (...)
  515.     {
  516.         win = CBrowserWindow::FindAndShow();
  517.         ThrowIfNil_(win);
  518.     }
  519.     
  520.     // Get the url
  521.     try
  522.     {
  523.         MoreExtractFromAEDesc::GetCString(inAppleEvent, AE_spy_showFile_url, url);
  524.     }
  525.     catch(...)
  526.     {
  527.     }
  528.         
  529.     // Get the mime type
  530.     try
  531.     {
  532.         MoreExtractFromAEDesc::GetCString(inAppleEvent, AE_spy_showFile_mime, mimeType);
  533.     }
  534.     catch(...)
  535.     {
  536.     }
  537.     
  538.     CFrontApp::sApplication->OpenLocalURL(&fileSpec, win, mimeType);
  539. }
  540.  
  541. /*----------------------------------------------------------------
  542.     ParseAnchor AppleEvent
  543.     Gets the URL, the relative url, and returns the full url of the relative
  544.  
  545.     arse anchor: Resolves the relative URL
  546.     parse anchor  
  547.         string                  -- Main URL
  548.         relative to  string      -- Relative URL
  549.     Result:   
  550.         string                  -- Parsed  URL
  551. ----------------------------------------------------------------*/
  552. void CAppleEventHandler::HandleParseAnchor(const AppleEvent    
  553.         &inAppleEvent, AppleEvent &outAEReply, AEDesc& /*outResult*/, long /*inAENumber*/)
  554. {
  555.     char * url = nil;
  556.     char * relative = nil;
  557.     char * parsed = nil;
  558.     MoreExtractFromAEDesc::GetCString(inAppleEvent, keyDirectObject, url);
  559.     MoreExtractFromAEDesc::GetCString(inAppleEvent, AE_spy_parse_rel, relative);
  560.     parsed = NET_MakeAbsoluteURL(url, relative);
  561.     ThrowIfNil_(parsed);
  562.     
  563.     OSErr err = ::AEPutParamPtr(&outAEReply, keyAEResult, typeChar, parsed, strlen(parsed));
  564.     if (parsed)
  565.         XP_FREE(parsed);
  566. }
  567.  
  568. /*----------------------------------------------------------------
  569.     HandleCancelProgress
  570.     Find the context with this transaction ID, and cancel it
  571.     In: Incoming apple event, reply event, outtgoing descriptor, eventID
  572.     Out: OpenURLEvent handled
  573.     
  574.     cancel progress: 
  575.         Interrupts the download of the document in the given window
  576.         
  577.     cancel progress  
  578.         integer                  -- progress ID, obtained from the progress app
  579.         [in window  integer]     -- window ID of the progress to cancel
  580. ----------------------------------------------------------------*/
  581. void CAppleEventHandler::HandleCancelProgress(const AppleEvent    &inAppleEvent,
  582.                                     AppleEvent            & /* outAEReply */,
  583.                                     AEDesc                & /* outResult */,
  584.                                     long                /* inAENumber */)
  585. {
  586.     // Find the window with this transaction, and let it handle the event
  587.     
  588.     try
  589.     {
  590.         Int32 transactionID;
  591.         StAEDescriptor    transDesc;
  592.         Boolean hasTransactionID = FALSE;
  593.         Boolean hasWindowID = FALSE;
  594.         try
  595.         {
  596.             OSErr err = ::AEGetKeyDesc(&inAppleEvent, keyDirectObject, typeWildCard, &transDesc.mDesc);
  597.             ThrowIfOSErr_(err);
  598.             UExtractFromAEDesc::TheInt32(transDesc.mDesc, transactionID);
  599.             hasTransactionID = TRUE;
  600.         }
  601.         catch(...)
  602.         {
  603.         }
  604.         try
  605.         {
  606.             OSErr err = ::AEGetKeyDesc(&inAppleEvent, AE_spy_CancelProgress_win, typeWildCard, &transDesc.mDesc);
  607.             ThrowIfOSErr_(err);
  608.             UExtractFromAEDesc::TheInt32(transDesc.mDesc, transactionID);
  609.             hasWindowID = TRUE;
  610.         }
  611.         catch(...)
  612.         {
  613.         }
  614.         
  615.         CBrowserWindow* window;
  616.         if (!hasTransactionID && !hasWindowID)    // No arguments, interrupt frontmost by default
  617.             {
  618.             window = CBrowserWindow::FindAndShow();
  619.             if (window && window->GetWindowContext())
  620.                 NET_InterruptWindow(*(window->GetWindowContext()));
  621.             }
  622.         else
  623.             {
  624.             CMediatedWindow* theWindow;
  625.             CWindowIterator iter(WindowType_Browser);
  626.             while (iter.Next(theWindow))
  627.                 {
  628.                 CBrowserWindow* theBrowserWindow = dynamic_cast<CBrowserWindow*>(theWindow);
  629.                 CNSContext* nsContext = theBrowserWindow->GetWindowContext();
  630.                 if (((nsContext->GetTransactionID() == transactionID) && hasTransactionID) 
  631.                     || ((nsContext->GetContextUniqueID() == transactionID) && hasWindowID))
  632.                     NET_InterruptWindow(*nsContext);
  633.                 }
  634.             }
  635.     }
  636.     catch(...)
  637.     {
  638.     }
  639. }
  640.  
  641.  
  642. /*----------------------------------------------------------------
  643.     webActivate: Makes Netscape the frontmost application, and selects a given 
  644.         window. This event is here for suite completeness/ cross-platform 
  645.         compatibility only, you should use standard AppleEvents instead.
  646.         
  647.     webActivate  
  648.         integer              -- window to bring to front
  649. ----------------------------------------------------------------*/
  650. void CAppleEventHandler::HandleSpyActivate(const AppleEvent    &inAppleEvent, AppleEvent& /*outAEReply*/,
  651.                             AEDesc& /*outResult*/, long /*inAENumber*/)
  652. {
  653.     Size realSize;
  654.     OSType realType;
  655.     CBrowserWindow * win = NULL;
  656.     OSErr err;
  657.     
  658.     MakeFrontApplication();
  659.     // Get the window, and select it
  660.     try
  661.     {
  662.         Int32 windowID;
  663.         
  664.         err = ::AEGetParamPtr(&inAppleEvent, AE_spy_openURL_wind, typeLongInteger,
  665.                          &realType, &windowID, sizeof(windowID), &realSize);
  666.         ThrowIfOSErr_(err);
  667.  
  668.         win = CBrowserWindow::GetWindowByID(windowID);
  669.         if (win == nil)
  670.             Throw_(errAENoSuchObject);
  671.         UDesktop::SelectDeskWindow(win);
  672.     }
  673.     catch(...){}
  674. }
  675.  
  676. /*----------------------------------------------------------------
  677.     list windows: Lists the IDs of all the hypertext windows
  678.     
  679.     list windows
  680.     Result:   
  681.         list          -- List of unique IDs of all the hypertext windows
  682. ----------------------------------------------------------------*/
  683. void
  684. CAppleEventHandler::HandleSpyListWindows(
  685.     const AppleEvent&    inAppleEvent,
  686.     AppleEvent&            outAEReply,
  687.     AEDesc&                outResult,
  688.     long                inAENumber)
  689. {
  690. #pragma unused(inAppleEvent, outResult, inAENumber) 
  691.  
  692.     AEDescList windowList;
  693.     windowList.descriptorType = typeNull;
  694.     OSErr err;
  695.     
  696.     try
  697.     {
  698.         // Create a descriptor list, and add a windowID for each browser window to the list
  699.  
  700.         CMediatedWindow*     theWindow = NULL;
  701.         DataIDT                windowType = WindowType_Browser;
  702.         CWindowIterator        iter(windowType);
  703.         
  704.         err = ::AECreateList(nil, 0, FALSE, &windowList);
  705.         ThrowIfOSErr_(err);
  706.  
  707.         while (iter.Next(theWindow))
  708.         {
  709.             CBrowserWindow* theBrowserWindow = dynamic_cast<CBrowserWindow*>(theWindow);
  710.             ThrowIfNil_(theBrowserWindow);
  711.             
  712.             CBrowserContext* theBrowserContext = (CBrowserContext*)theBrowserWindow->GetWindowContext();
  713.             ThrowIfNil_(theBrowserContext);
  714.             
  715.             StAEDescriptor    theIDDesc(theBrowserContext->GetContextUniqueID());
  716.             err = ::AEPutDesc(&windowList, 0, &theIDDesc.mDesc);
  717.             ThrowIfOSErr_(err);
  718.         }
  719.     }
  720.     catch (...)
  721.     {
  722.         if (windowList.descriptorType != typeNull)
  723.             ::AEDisposeDesc(&windowList);
  724.         throw;
  725.     }
  726.  
  727.     err = ::AEPutParamDesc(&outAEReply, keyAEResult, &windowList);
  728.     ThrowIfOSErr_(err);
  729.     ::AEDisposeDesc(&windowList);
  730. }
  731.  
  732.  
  733. /*----------------------------------------------------------------
  734.     Gets the window information, a list containing URL and title
  735.     ## Another redundant event that has an equivalent event already 
  736.     specified by Apple
  737.  
  738.     get window info: 
  739.     Returns the information about the window as a list. 
  740.     Currently the list contains the window title and the URL. 
  741.     ## You can get the same information using standard Apple Event GetProperty.
  742.     
  743.     get window info  
  744.         integer              -- window ID
  745.     Result:   
  746.         list                -- contains URL and title strings
  747. ----------------------------------------------------------------*/
  748. void CAppleEventHandler::HandleSpyGetWindowInfo(const AppleEvent    &inAppleEvent, AppleEvent &outAEReply,
  749.                             AEDesc& /*outResult*/, long /*inAENumber*/)
  750. {
  751.     Size realSize;
  752.     OSType realType;
  753.     CBrowserWindow * win = NULL;            // Window
  754.     OSErr err;
  755.     AEDescList volatile propertyList;
  756.     propertyList.descriptorType = typeNull;
  757.     
  758.     try
  759.     {
  760.             // Get the window, and list its properties
  761.         Int32 windowID;
  762.         
  763.         err = ::AEGetParamPtr(&inAppleEvent, keyDirectObject, typeLongInteger,
  764.                          &realType, &windowID, sizeof(windowID), &realSize);
  765.         ThrowIfOSErr_(err);
  766.         win = CBrowserWindow::GetWindowByID(windowID);
  767.         if (win == nil)
  768.             Throw_(errAENoSuchObject);
  769.         
  770.             // Create the list
  771.         err = ::AECreateList(nil, 0, FALSE, &propertyList);
  772.         ThrowIfOSErr_(err);
  773.         
  774.             // Put the URL as the first item in the list
  775.         cstring url = win->GetWindowContext()->GetCurrentURL();
  776.         err = ::AEPutPtr(&propertyList, 1, typeChar, (char*)url, url.length());
  777.         ThrowIfOSErr_(err);
  778.         
  779.             // Put the title as the second item in the list
  780.         CStr255 ptitle;
  781.         GetWTitle(win->GetMacPort(), ptitle);
  782.         cstring ctitle((char*)ptitle);
  783.         err = ::AEPutPtr(&propertyList, 2, typeChar, (char*)ctitle, ctitle.length());
  784.         ThrowIfOSErr_(err);
  785.         
  786.             // Put the list as the reply
  787.         err = ::AEPutParamDesc(&outAEReply, keyAEResult, &propertyList);
  788.         ::AEDisposeDesc(&propertyList);
  789.     }
  790.     catch(...)
  791.     {
  792.         if (propertyList.descriptorType != typeNull)
  793.             ::AEDisposeDesc(&propertyList);
  794.         throw;        
  795.     }
  796. }
  797.  
  798. /*----------------------------------------------------------------
  799.     register window close: 
  800.     Netscape will notify registered application when this window closes
  801.     
  802.     register window close  
  803.         'sign'          -- Application signature for window  
  804.         integer          -- window ID
  805.         
  806.     [Result:   boolean]  -- true if successful
  807.  
  808.     unregister window close: 
  809.     Undo for register window close unregister window close  
  810.     
  811.         'sign'          -- Application signature for window  
  812.         integer          -- window ID
  813.         
  814.     [Result:   boolean]  -- true if successful
  815. ----------------------------------------------------------------*/
  816. void CAppleEventHandler::HandleWindowRegistration(const AppleEvent    &inAppleEvent, AppleEvent &outAEReply,
  817.                             AEDesc &outResult, long inAENumber)
  818. {
  819.     Size realSize;
  820.     OSType realType;
  821.     CBrowserWindow * win = NULL;
  822.     OSErr err;
  823.  
  824.     // Get the window, and select it
  825.     Int32 windowID;
  826.     
  827.     err = ::AEGetParamPtr(&inAppleEvent, AE_spy_registerWinClose_win, typeLongInteger,
  828.                      &realType, &windowID, sizeof(windowID), &realSize);
  829.     ThrowIfOSErr_(err);
  830.     
  831.     win = CBrowserWindow::GetWindowByID(windowID);
  832.     if (win == nil)
  833.         Throw_(errAENoSuchObject);
  834.     win->HandleAppleEvent(inAppleEvent, outAEReply, outResult, inAENumber);
  835. }
  836.  
  837.  
  838.  
  839. /*--------------------------------------------------------------------------*/
  840. /*                ----   Experimental Netscape Suite    ----                    */
  841. /*--------------------------------------------------------------------------*/                    
  842.  
  843. /*----------------------------------------------------------------
  844.     Open bookmark: Reads in a bookmark file
  845.     
  846.     Open bookmark  
  847.         alias  -- If not available, reloads the current bookmark file
  848. ----------------------------------------------------------------*/
  849. void CAppleEventHandler::HandleOpenBookmarksEvent( const AppleEvent    &inAppleEvent,
  850.                                     AppleEvent            & /*outAEReply*/,
  851.                                     AEDesc                & /*outResult*/,
  852.                                     long                /*inAENumber*/)
  853. {
  854.     FSSpec fileSpec;
  855.     Boolean hasFileSpec = FALSE;
  856.     OSErr err;
  857.     Size    realSize;
  858.     OSType    realType;
  859.  
  860.     char * path = NULL;
  861.     
  862.     // Get the file specs
  863.     err = ::AEGetKeyPtr(&inAppleEvent, keyDirectObject, typeFSS,
  864.                             &realType, &fileSpec, sizeof(fileSpec), &realSize);
  865.  
  866.     // If none, use the default file
  867.     //        I hate this glue to uapp.  Will change as soon as all AE stuff
  868.     //        is working.
  869.     if (err != noErr)
  870.         path = GetBookmarksPath( fileSpec, TRUE );
  871.     else
  872.         path = GetBookmarksPath( fileSpec, FALSE );
  873.     
  874.     ThrowIfNil_(path);
  875.     
  876.     DebugStr("\pNot implemented");
  877. //ÑÑÑ    CBookmarksContext::Initialize();
  878. //ÑÑÑ    BM_ReadBookmarksFromDisk( *CBookmarksContext::GetInstance(), path, NULL );
  879. }
  880.  
  881. /*----------------------------------------------------------------
  882.     Open AddressBook: Opens the address book
  883.     
  884.     Open AddressBook  
  885. ----------------------------------------------------------------*/
  886. void CAppleEventHandler::HandleOpenAddressBookEvent( 
  887.                                     const AppleEvent    &/*inAppleEvent*/,
  888.                                     AppleEvent            & /*outAEReply*/,
  889.                                     AEDesc                & /*outResult*/,
  890.                                     long                /*inAENumber*/)
  891. {
  892. #ifdef MOZ_MAIL_NEWS
  893.     CAddressBookManager::ShowAddressBookWindow();
  894. #endif // MOZ_MAIL_NEWS
  895. }
  896.  
  897.  
  898. /*----------------------------------------------------------------
  899.     Open Component: Opens the component specified in the parameter
  900.     to the Apple Event.
  901.     
  902.     HandleOpenComponentEvent
  903. ----------------------------------------------------------------*/
  904. void CAppleEventHandler::HandleOpenComponentEvent( 
  905.                                     const AppleEvent    &inAppleEvent,
  906.                                     AppleEvent            & /*outAEReply*/,
  907.                                     AEDesc                & /*outResult*/,
  908.                                     long                /*inAENumber*/)
  909. {    
  910.     OSType        componentType;
  911.     DescType    returnedType;
  912.     Size        gotSize = 0;
  913.     
  914.     OSErr err = ::AEGetKeyPtr(&inAppleEvent, keyDirectObject, typeEnumerated, &returnedType, &componentType,
  915.             sizeof(OSType), &gotSize);
  916.  
  917.     if (err == noErr && gotSize == sizeof(OSType))
  918.     {                      
  919.         switch (componentType)
  920.         {
  921.             case AE_www_comp_navigator:
  922.                 CFrontApp::sApplication->ObeyCommand(cmd_BrowserWindow);
  923.                 break;
  924.  
  925. #ifdef MOZ_MAIL_NEWS
  926.             case AE_www_comp_inbox:
  927.                 CFrontApp::sApplication->ObeyCommand(cmd_Inbox);
  928.                 break;
  929.                         
  930.             case AE_www_comp_collabra:
  931.                 CFrontApp::sApplication->ObeyCommand(cmd_MailNewsFolderWindow);
  932.                 break;
  933. #endif // MOZ_MAIL_NEWS
  934. #ifdef EDITOR
  935.             case AE_www_comp_composer:
  936.                 CFrontApp::sApplication->ObeyCommand(cmd_NewWindowEditor);
  937.                 break;
  938. #endif // EDITOR
  939. #if !defined(MOZ_LITE) && !defined(MOZ_MEDIUM)
  940.             case AE_www_comp_conference:
  941.                 CFrontApp::sApplication->ObeyCommand(cmd_LaunchConference);
  942.                 break;
  943.                 
  944.             case AE_www_comp_calendar:
  945.                 CFrontApp::sApplication->ObeyCommand(cmd_LaunchCalendar);
  946.                 break;
  947.                 
  948.             case AE_www_comp_ibmHostOnDemand:
  949.                 CFrontApp::sApplication->ObeyCommand(cmd_Launch3270);
  950.                 break;
  951. #endif
  952. #ifdef MOZ_NETCAST
  953.             case AE_www_comp_netcaster:
  954.                 CFrontApp::sApplication->ObeyCommand(cmd_LaunchNetcaster);
  955.                 break;
  956. #endif // MOZ_NETCAST
  957.             default:
  958.                 ; //do nothing
  959.         }
  960.     }
  961. }
  962.  
  963.  
  964. /*----------------------------------------------------------------
  965.     HandleCommandEvent
  966.     
  967.     Get new mail
  968. ----------------------------------------------------------------*/
  969. void CAppleEventHandler::HandleCommandEvent( 
  970.                                     const AppleEvent    & inAppleEvent,
  971.                                     AppleEvent            & /*outAEReply*/,
  972.                                     AEDesc                & /*outResult*/,
  973.                                     long                /*inAENumber*/)
  974. {    
  975.  
  976.     long        commandID;
  977.     DescType    returnedType;
  978.     Size        gotSize = 0;
  979.     
  980.     OSErr err = ::AEGetKeyPtr(&inAppleEvent, keyDirectObject, typeEnumerated, &returnedType,
  981.             &commandID, sizeof(long), &gotSize);
  982.  
  983.     if (err == noErr && gotSize == sizeof(long))
  984.     {                      
  985. // Is this really only for mail????
  986. #ifdef MOZ_MAIL_NEWS
  987.     CFrontApp::sApplication->ObeyCommand(commandID);
  988. #endif // MOZ_MAIL_NEWS
  989.  
  990.  
  991.     }
  992. }
  993.  
  994.  
  995. /*----------------------------------------------------------------
  996.     Read help file: 
  997.     Reads in the help file (file should be in the help file format)
  998.     ## Questions about the new help file system, ask montulli
  999.         
  1000.     Read help file  
  1001.         alias
  1002.         [with index  string]      -- Index to the help file. Defaults to  ╘DEFAULT╒)
  1003.         [search text  string]      -- Optional text to search for
  1004. ----------------------------------------------------------------*/
  1005. void CAppleEventHandler::HandleReadHelpFileEvent(const AppleEvent    &inAppleEvent,
  1006.                                     AppleEvent            & /*outAEReply*/,
  1007.                                     AEDesc                & /*outResult*/,
  1008.                                     long                /*inAENumber*/)
  1009. {
  1010.     FSSpec fileSpec;
  1011.     char * map_file_url = NULL;
  1012.     char * help_id = NULL;
  1013.     char * search_text = NULL;
  1014.     OSErr err;
  1015.     Size    realSize;
  1016.     OSType    realType;
  1017.  
  1018.     CFrontApp::sApplication->ProperStartup(NULL, FILE_TYPE_NONE);
  1019.  
  1020.     try
  1021.     {
  1022.         // Get the file specs
  1023.         err = ::AEGetKeyPtr(&inAppleEvent, keyDirectObject, typeFSS,
  1024.                                 &realType, &fileSpec, sizeof(fileSpec), &realSize);
  1025.         ThrowIfOSErr_(err);
  1026.         
  1027.         map_file_url = CFileMgr::GetURLFromFileSpec( fileSpec );
  1028.         ThrowIfNil_(map_file_url);
  1029.  
  1030.         // Get the help text
  1031.         
  1032.         try
  1033.         {
  1034.             MoreExtractFromAEDesc::GetCString(inAppleEvent, AE_www_ReadHelpFileID, help_id);
  1035.         }
  1036.         catch(...)
  1037.         {
  1038.         }
  1039.             
  1040.         // Get the search text (optional)
  1041.         try
  1042.         {
  1043.             MoreExtractFromAEDesc::GetCString(inAppleEvent, AE_www_ReadHelpFileSearchText, search_text);
  1044.         }
  1045.         catch(...)
  1046.         {}
  1047.     }
  1048.     catch(...)
  1049.     {
  1050.         throw;
  1051.     }
  1052.     
  1053.         // Will using the bookmark context as a dummy work?
  1054.     DebugStr("\pNot implemented");
  1055. //ÑÑÑ    CBookmarksContext::Initialize();
  1056. //ÑÑÑ    NET_GetHTMLHelpFileFromMapFile(*CBookmarksContext::GetInstance(),
  1057. //                              map_file_url, help_id, search_text);
  1058.     
  1059.     FREEIF(map_file_url);
  1060.     FREEIF(help_id);
  1061.     FREEIF(search_text);
  1062. }
  1063.  
  1064. /*----------------------------------------------------------------
  1065.     Go: navigate a window: back, forward, again(reload), home)
  1066.     Go  
  1067.         reference          -- window
  1068.         direction          again/home/backward/forward
  1069. ----------------------------------------------------------------*/
  1070. void CAppleEventHandler::HandleGoEvent( 
  1071.     const AppleEvent    &inAppleEvent,
  1072.     AppleEvent            &outAEReply,
  1073.     AEDesc                &outResult,
  1074.     long                inAENumber)
  1075. {
  1076.     // We need to make sure
  1077.     
  1078.     CFrontApp::sApplication->ProperStartup( NULL, FILE_TYPE_GETURL );
  1079.     CBrowserWindow * win = NULL;
  1080.  
  1081.     // Get the window.  If it is a Browser window then
  1082.     //    decode the AE and send a message.
  1083.     
  1084.     // The keyData.mDesc should be a ref to a browser window 
  1085.     // If we get it successfulle (ie the user included the "in window 1" 
  1086.     // then we can get a hold of the actual BrowserWindow object by using
  1087.     // AEResolve and GetModelFromToken somehow
  1088.     StAEDescriptor    keyData;
  1089.     OSErr err = ::AEGetKeyDesc(&inAppleEvent, AE_www_typeWindow, typeWildCard, &keyData.mDesc);
  1090.     if ((err == noErr) && (keyData.mDesc.descriptorType == typeObjectSpecifier))
  1091.     {
  1092.         StAEDescriptor    theToken;
  1093.         err = ::AEResolve(&keyData.mDesc, kAEIDoMinimum, &theToken.mDesc);
  1094.         ThrowIfOSErr_(err);
  1095.         LModelObject * model = CFrontApp::sApplication->GetModelFromToken(theToken.mDesc);
  1096.         ThrowIfNil_(model);
  1097.         model->HandleAppleEvent(inAppleEvent, outAEReply, outResult, inAENumber);
  1098.  
  1099.     // else the user did not provide an inside reference "inside window 1"
  1100.     // so send back an error    
  1101.     }else{
  1102.         
  1103.     }
  1104. }
  1105.  
  1106. /*----------------------------------------------------------------
  1107.     Get workingURL: 
  1108.         Get the path to the running application in URL format.  
  1109.         This will allow a script to construct a relative URL
  1110.         
  1111.     Get workingURL
  1112.     Result:   
  1113.         'tTXT'  -- Will return text of the from ╥FILE://foo/applicationname╙
  1114. ----------------------------------------------------------------*/
  1115. void CAppleEventHandler::HandleGetWDEvent( 
  1116.     const AppleEvent    & /*inAppleEvent */,
  1117.     AppleEvent            & outAEReply,
  1118.     AEDesc                & /*outResult */,
  1119.     long                /*inAENumber */)
  1120. {
  1121.     char        *pathBlock = NULL;
  1122.     Size        pathLength;
  1123.     OSErr        err;
  1124.  
  1125.     // Grab the URL of the running application
  1126.     pathBlock = PathURLFromProcessSignature (emSignature, 'APPL');
  1127.     
  1128.     if (outAEReply.dataHandle != NULL && pathBlock != NULL)
  1129.     {
  1130.         pathLength = XP_STRLEN(pathBlock);
  1131.         
  1132.         err = AEPutParamPtr( &outAEReply, 
  1133.             keyDirectObject, 
  1134.             typeChar, 
  1135.             pathBlock, pathLength);
  1136.     }
  1137.     
  1138.     if (pathBlock)
  1139.         XP_FREE(pathBlock);
  1140.     
  1141. }
  1142.  
  1143.  
  1144. /*----------------------------------------------------------------
  1145.     HandleGetActiveProfileEvent: 
  1146.         Get the name of the active profile from the prefs.
  1147.     
  1148.     Result:   
  1149.         'tTXT'  -- Will return text of the profile name
  1150. ----------------------------------------------------------------*/
  1151. void CAppleEventHandler::HandleGetActiveProfileEvent( 
  1152.     const AppleEvent    & /*inAppleEvent */,
  1153.     AppleEvent            &outAEReply,
  1154.     AEDesc                & /*outResult */,
  1155.     long                /*inAENumber */)
  1156. {
  1157.     char     profileName[255];
  1158.     int     len = 255;
  1159.     OSErr    err = noErr;
  1160.     
  1161.     err =  PREF_GetCharPref("profile.name", profileName, &len);
  1162.     
  1163.     if (err == PREF_NOERROR && outAEReply.dataHandle != nil) {
  1164.     
  1165.             err = AEPutParamPtr( &outAEReply, 
  1166.                 keyDirectObject, 
  1167.                 typeChar, 
  1168.                 profileName, strlen(profileName));
  1169.     }
  1170. }
  1171.  
  1172.  
  1173. /*--------------------------------------------------------------------------*/
  1174. /*                ----   Apple Event Object Model support   ----                */
  1175. /*--------------------------------------------------------------------------*/    
  1176.  
  1177. void CAppleEventHandler::GetSubModelByUniqueID(DescType inModelID, const AEDesc    &inKeyData, AEDesc &outToken) const
  1178. {
  1179.     switch (inModelID)
  1180.     {
  1181.     case cWindow:        // The hyperwindows have unique IDs that can be resolved
  1182.                         // FFFFFFFFF is the front window, 0 is a new window
  1183.         Int32 windowID;
  1184.         UExtractFromAEDesc::TheInt32(inKeyData, windowID);
  1185.         LWindow*    foundWindow = NULL;
  1186.         
  1187.         foundWindow = CBrowserWindow::GetWindowByID(windowID);
  1188.         if (foundWindow == NULL)
  1189.             ThrowOSErr_(errAENoSuchObject);
  1190.         else
  1191.             CFrontApp::sApplication->PutInToken(foundWindow, outToken);    
  1192.         break;
  1193.     default:
  1194.         CFrontApp::sApplication->LDocApplication::GetSubModelByUniqueID(inModelID, inKeyData, outToken);
  1195.         break;
  1196.     }
  1197. }
  1198.  
  1199. void CAppleEventHandler::GetAEProperty(DescType inProperty,
  1200.                             const AEDesc    &inRequestedType,
  1201.                             AEDesc            &outPropertyDesc) const
  1202. {
  1203.     OSErr err;
  1204.     
  1205.     switch (inProperty)
  1206.     {
  1207.         case AE_www_typeApplicationAlert:    // application that handles alerts
  1208.             err = ::AECreateDesc(typeType, &ErrorManager::sAlertApp,
  1209.                                 sizeof(ErrorManager::sAlertApp), &outPropertyDesc);
  1210.             ThrowIfOSErr_(err);
  1211.             break;
  1212.             
  1213.         case AE_www_typeKioskMode:
  1214.             err = ::AECreateDesc(typeLongInteger, (const void *)fKioskMode,
  1215.                                 sizeof(fKioskMode), &outPropertyDesc);
  1216.             break;
  1217.             
  1218.         default:
  1219.             CFrontApp::sApplication->LApplication::GetAEProperty(inProperty, inRequestedType, outPropertyDesc);
  1220.             break;
  1221.     }
  1222. }
  1223.  
  1224. void CAppleEventHandler::SetAEProperty(DescType inProperty,
  1225.                             const AEDesc    &inValue,
  1226.                             AEDesc            &outPropertyDesc)
  1227. {
  1228.  
  1229.     switch (inProperty) {
  1230.     case AE_www_typeApplicationAlert:    // application that handles alerts
  1231.         try
  1232.         {
  1233.             OSType newSig;
  1234.             UExtractFromAEDesc::TheType(inValue, newSig);
  1235.             ErrorManager::sAlertApp = newSig;
  1236.         }
  1237.         catch(...)    // In case of error, revert to self
  1238.         {
  1239.             ErrorManager::sAlertApp = emSignature;
  1240.         }
  1241.         break;
  1242.     case AE_www_typeKioskMode:
  1243.         try
  1244.         {
  1245.             Boolean menuBarModeChangeBroadcasted = false;
  1246.             Int32 kMode;
  1247.             UExtractFromAEDesc::TheInt32(inValue, kMode);
  1248.             
  1249.             if ((kMode == KioskOn) && (fKioskMode != KioskOn))
  1250.             {
  1251.                 fKioskMode = KioskOn;
  1252.                 // SetMenubar(KIOSK_MENUBAR);        ÑÑÑ this is currently handled by the chrome structure, below
  1253.                 //                                        BUT, they want three states for menu bars, and the field is only a boolean
  1254.                                 
  1255.                 CMediatedWindow*    theIterWindow = NULL;
  1256.                 DataIDT                windowType = WindowType_Browser;
  1257.                 CWindowIterator        theWindowIterator(windowType);
  1258.                 
  1259.                 while (theWindowIterator.Next(theIterWindow))
  1260.                 {
  1261.                     CBrowserWindow* theBrowserWindow = dynamic_cast<CBrowserWindow*>(theIterWindow);
  1262.                     if (theBrowserWindow != nil)
  1263.                     {
  1264.                         Chrome            aChrome;
  1265.                         theBrowserWindow->GetChromeInfo(&aChrome);
  1266.                         aChrome.show_button_bar = 0;
  1267.                         aChrome.show_url_bar = 0;
  1268.                         aChrome.show_directory_buttons = 0;
  1269.                         aChrome.show_security_bar = 0;
  1270.                         aChrome.show_menu = 0;        // ÑÑÑ this isn't designed correctly!    deeje 97-03-13
  1271.                         
  1272.                         // Make sure we only broadcast the menubar mode change once!
  1273.                         theBrowserWindow->SetChromeInfo(&aChrome, !menuBarModeChangeBroadcasted);
  1274.                         if (!menuBarModeChangeBroadcasted)
  1275.                         {
  1276.                             menuBarModeChangeBroadcasted = true;
  1277.                         }
  1278.                     }
  1279.                 }
  1280.             }
  1281.             else if ((kMode == KioskOff) && (fKioskMode != KioskOff))
  1282.             {
  1283.                 fKioskMode = KioskOff;
  1284.                 // SetMenubar(MAIN_MENUBAR);        ÑÑÑ this is currently handled by the chrome structure, below
  1285.                 //                                        BUT, they want three states for menu bars, and the field is only a boolean
  1286.                                 
  1287.                 CMediatedWindow*    theIterWindow = NULL;
  1288.                 DataIDT                windowType = WindowType_Browser;
  1289.                 CWindowIterator        theWindowIterator(windowType);
  1290.                 
  1291.                 while (theWindowIterator.Next(theIterWindow))
  1292.                 {
  1293.                     CBrowserWindow* theBrowserWindow = dynamic_cast<CBrowserWindow*>(theIterWindow);
  1294.                     if (theBrowserWindow != nil)
  1295.                     {
  1296.                         Chrome            aChrome;
  1297.                         theBrowserWindow->GetChromeInfo(&aChrome);
  1298.                         aChrome.show_button_bar = CPrefs::GetBoolean(CPrefs::ShowToolbar);
  1299.                         aChrome.show_url_bar = CPrefs::GetBoolean(CPrefs::ShowURL);
  1300.                         aChrome.show_directory_buttons = CPrefs::GetBoolean(CPrefs::ShowDirectory);
  1301.                         aChrome.show_security_bar = CPrefs::GetBoolean(CPrefs::ShowToolbar) || CPrefs::GetBoolean(CPrefs::ShowURL);
  1302.                         aChrome.show_menu = 1;        // ÑÑÑ this isn't designed correctly!    deeje 97-03-13
  1303.                         
  1304.                         // Make sure we only broadcast the menubar mode change once!
  1305.                         theBrowserWindow->SetChromeInfo(&aChrome, !menuBarModeChangeBroadcasted);
  1306.                         if (!menuBarModeChangeBroadcasted)
  1307.                         {
  1308.                             menuBarModeChangeBroadcasted = true;
  1309.                         }
  1310.                     }
  1311.                 }
  1312.             }
  1313.             
  1314.         }
  1315.         catch(...)
  1316.         {}
  1317.         break;
  1318.     default:
  1319.         CFrontApp::sApplication->LApplication::SetAEProperty(inProperty, inValue, outPropertyDesc);
  1320.         break;
  1321.     }
  1322.     
  1323.     
  1324. }
  1325.  
  1326. /*--------------------------------------------------------------------------*/
  1327. /*            ----   Eudora (send) Mail Suite   ----                            */
  1328. /*--------------------------------------------------------------------------*/    
  1329.  
  1330.  
  1331. /*-------------------------------------------------------------*/
  1332. //     class EudoraSuite        This supports sending to Eudora
  1333. //    Tools used to communicate with Eudora
  1334. //    The only real use these have is if we are operating in
  1335. //    Browser-only mode and the user wishes to use Eudora to
  1336. //    handle mail functions.
  1337. //
  1338. /*-------------------------------------------------------------*/
  1339.  
  1340.  
  1341. // --------------------------------------------------------------
  1342. /*    This makes a Null AppleEvent descriptor.    
  1343.              */
  1344. // --------------------------------------------------------------
  1345. void EudoraSuite::MakeNullDesc (AEDesc *theDesc)
  1346. {
  1347.     theDesc->descriptorType = typeNull;
  1348.     theDesc->dataHandle = nil;
  1349. }
  1350.  
  1351. // --------------------------------------------------------------
  1352. /*    This makes a string AppleEvent descriptor.   
  1353.     In: A pascal string
  1354.         Pointer to an AEDesc.
  1355.         
  1356.     Out: AEDesc of type TEXT created and returned. */
  1357. // --------------------------------------------------------------
  1358. OSErr EudoraSuite::MakeStringDesc (Str255 theStr,AEDesc *theDesc)
  1359. {
  1360.     return AECreateDesc(kAETextSuite, &theStr[1], StrLength(theStr), theDesc);
  1361. }
  1362.  
  1363. // --------------------------------------------------------------
  1364. /*    This stuffs the required parameters into the AppleEvent. 
  1365.              */
  1366. // --------------------------------------------------------------
  1367.  
  1368.  
  1369. OSErr EudoraSuite::CreateObjSpecifier (AEKeyword theClass,AEDesc theContainer,
  1370.         AEKeyword theForm,AEDesc theData, Boolean /*disposeInputs*/,AEDesc *theSpec)
  1371. {
  1372.     AEDesc theRec;
  1373.     OSErr    err;
  1374.     
  1375.     err = AECreateList(nil,0,true,&theRec);
  1376.     if (!err)
  1377.         err = AEPutKeyPtr(&theRec,keyAEKeyForm,typeEnumeration,&theForm,sizeof(theForm));
  1378.     if (!err)
  1379.         err = AEPutKeyPtr(&theRec,keyAEDesiredClass,cType,&theClass,sizeof(theClass));
  1380.     if (!err)
  1381.         err = AEPutKeyDesc(&theRec,keyAEKeyData,&theData);
  1382.     if (!err)
  1383.         err = AEPutKeyDesc(&theRec,keyAEContainer,&theContainer);
  1384.     if (!err)
  1385.         err = AECoerceDesc(&theRec,cObjectSpecifier,theSpec);
  1386.     AEDisposeDesc(&theRec);
  1387.     return err;
  1388. }
  1389.  
  1390. // --------------------------------------------------------------
  1391. /*    This creates an AEDesc for the current message.
  1392.     (The current message index = 1)     
  1393.  
  1394.     In:    Pointer to AEDesc to return
  1395.     Out: AEDesc constructed. */
  1396. // --------------------------------------------------------------
  1397.  
  1398. OSErr EudoraSuite::MakeCurrentMsgSpec (AEDesc *theSpec)
  1399. {
  1400.     AEDesc theContainer,theIndex;
  1401.     OSErr    err;
  1402.     long    msgIndex = 1;
  1403.  
  1404.     EudoraSuite::MakeNullDesc (&theContainer);
  1405.     err = AECreateDesc(cLongInteger, &msgIndex, sizeof(msgIndex), &theIndex);
  1406.     if (!err)
  1407.         err = EudoraSuite::CreateObjSpecifier(cEuMessage, theContainer,
  1408.                 formAbsolutePosition, theIndex, true, theSpec);
  1409.                 
  1410.     AEDisposeDesc(&theContainer);
  1411.     AEDisposeDesc(&theIndex);
  1412.     
  1413.     return err;
  1414. }
  1415.  
  1416.  
  1417. // --------------------------------------------------------------
  1418. /*    Send a given Apple Event.  Special case for Eudora, should
  1419.     be rewritten, but it works for the moment.
  1420.     In:    AppleEvent
  1421.     Out: Event sent  */
  1422. // --------------------------------------------------------------
  1423. OSErr EudoraSuite::SendEvent (AppleEvent *theEvent)
  1424. {
  1425.     AppleEvent theReply;
  1426.     OSErr err;
  1427.     
  1428.     EudoraSuite::MakeNullDesc(&theReply);
  1429.     err = AESend(theEvent,&theReply,kAENoReply + kAENeverInteract 
  1430.             + kAECanSwitchLayer+kAEDontRecord,kAENormalPriority,-1,nil,nil);
  1431.  
  1432.     AEDisposeDesc(&theReply);
  1433.     AEDisposeDesc(theEvent);
  1434.  
  1435.     return err;
  1436. }
  1437.  
  1438. // --------------------------------------------------------------
  1439. /*    Create an Apple Event to be sent to Eudora
  1440.     In:    Event Class
  1441.         Event ID
  1442.         Ptr to Apple Event
  1443.     Out: Event constructed and returned.  */
  1444. // --------------------------------------------------------------
  1445. OSErr EudoraSuite::MakeEvent (AEEventClass eventClass,AEEventID eventID,AppleEvent *theEvent)
  1446. {
  1447.     AEAddressDesc theTarget;
  1448.     OSType theSignature;
  1449.     OSErr    err;
  1450.     
  1451.     theSignature = kEudoraSuite;
  1452.     err = AECreateDesc(typeApplSignature,&theSignature,sizeof(theSignature),&theTarget);
  1453.     if (!err)
  1454.         err = AECreateAppleEvent(eventClass,eventID,&theTarget,0,0,theEvent);
  1455.     AEDisposeDesc(&theTarget);
  1456.     return err;
  1457. }
  1458.  
  1459. // --------------------------------------------------------------
  1460. /*    This sets the data in a specified field. It operates on the frontmost message 
  1461.     in Eudora. It is the equivalent of sending the following AppleScript:
  1462.     set field "fieldname" of message 0 to "data"
  1463.  
  1464.     Examples for setting up a complete mail message:
  1465.         EudoraSuite::SendSetData("\pto",toRecipientPtr);
  1466.         EudoraSuite::SendSetData("\pcc",ccRecipientPtr);
  1467.         EudoraSuite::SendSetData("\pbcc",bccRecipientPtr);
  1468.         EudoraSuite::SendSetData("\psubject",subjectPtr);
  1469.         EudoraSuite::SendSetData("\p",bodyPtr);
  1470.         
  1471.     In:    Field to set the data in (Subject, Address, Content, etc)
  1472.         Pointer to text data.
  1473.         Size of pointer (allows us to work with XP_Ptrs).
  1474.     Out: Apple Event sent to Eudora, setting a given field.  */
  1475. // --------------------------------------------------------------
  1476. OSErr EudoraSuite::SendSetData(Str31 theFieldName, Ptr thePtr, long thePtrSize)
  1477. {
  1478.     AEDesc theMsg,theName,theFieldSpec,theText;
  1479.     AppleEvent theEvent;
  1480.     OSErr err;
  1481.     Handle theData;
  1482.     
  1483.     theData = NewHandle(thePtrSize);
  1484.     BlockMove((Ptr)thePtr,*theData,thePtrSize);
  1485.  
  1486.     if (theData != nil)
  1487.         {
  1488.  
  1489.             err = EudoraSuite::MakeCurrentMsgSpec(&theMsg);
  1490.             if (!err)
  1491.                 err = EudoraSuite::MakeStringDesc(theFieldName,&theName);
  1492.             if (!err)
  1493.                 err = EudoraSuite::CreateObjSpecifier(cEuField,theMsg,formName,theName,true,&theFieldSpec);
  1494.             if (!err)
  1495.                 err = EudoraSuite::MakeEvent(kAECoreSuite,kAESetData,&theEvent);
  1496.             if (!err)
  1497.                 err = AEPutParamDesc(&theEvent,keyAEResult,&theFieldSpec);
  1498.             AEDisposeDesc(&theFieldSpec);
  1499.                 
  1500.             theText.descriptorType = typeChar;
  1501.             theText.dataHandle = theData;
  1502.             if (!err)
  1503.                 err = AEPutParamDesc(&theEvent,keyAEData,&theText);
  1504.             if (!err)
  1505.                 err = EudoraSuite::SendEvent(&theEvent);
  1506.  
  1507.             DisposeHandle(theText.dataHandle);
  1508.             AEDisposeDesc(&theText);
  1509.             AEDisposeDesc(&theMsg);
  1510.             AEDisposeDesc(&theName);
  1511.         }
  1512.     DisposeHandle(theData);
  1513.     return err;
  1514.     
  1515. }
  1516. // --------------------------------------------------------------
  1517. /*    Everything you need to tell Eudora to construct a new message
  1518.     and send it.
  1519.     In:    Pointer to the list of e mail addresses to send TO
  1520.         Pointer to the list of e mail addresses to send CC
  1521.         Pointer to the list of e mail addresses to send BCC
  1522.         Pointer to the Subject text
  1523.         Priority level of message.
  1524.         Pointer to the contents of the mail
  1525.         Pointer to an FSSpec (or null if none) for an enclosure.
  1526.     Out: Apple Events sent to Eudora telling it to construct the
  1527.         message and send it. */
  1528. // --------------------------------------------------------------
  1529.  
  1530. OSErr  EudoraSuite::SendMessage(
  1531.     Ptr        toRecipientPtr, 
  1532.     Ptr        ccRecipientPtr,
  1533.     Ptr        bccRecipientPtr,
  1534.     Ptr        subjectPtr,
  1535.     XP_HUGE_CHAR_PTR        bodyPtr,
  1536.     long    thePriority,
  1537.     FSSpec    *theEnclosurePtr)
  1538. {    
  1539.     AEDesc nullSpec,theName,theFolder,theMailbox,theInsertRec,theInsl,msgSpec,theEnclList;
  1540.     OSType thePos,theClass;
  1541.     AppleEvent theEvent;
  1542.     OSErr     err;
  1543.     
  1544.         
  1545. /* This section creates a new message and places it at the end of the out mailbox.
  1546.    It is equivalent to  the following AppleScript:
  1547.         make message at end of mailbox "out" of mail folder ""
  1548. */
  1549.  
  1550.  
  1551.     MakeNullDesc(&nullSpec);
  1552.     err = MakeStringDesc("\p",&theName);
  1553.     if (!err)
  1554.         err = EudoraSuite::CreateObjSpecifier(cEuMailfolder,nullSpec,formName,theName,true,&theFolder);
  1555.  
  1556.  
  1557.     if (!err)
  1558.         err = MakeStringDesc("\pout",&theName);
  1559.     if (!err)
  1560.         err = EudoraSuite::CreateObjSpecifier(cEuMailbox,theFolder,formName,theName,true,&theMailbox);
  1561.     if (!err)
  1562.         err = AECreateList(nil,0,true,&theInsertRec);
  1563.     if (!err)
  1564.         err = AEPutKeyDesc(&theInsertRec,keyAEObject,&theMailbox);
  1565.  
  1566.  
  1567.     thePos=kAEEnd;
  1568.     if (!err)
  1569.         err = AEPutKeyPtr(&theInsertRec,keyAEPosition,typeEnumeration,&thePos,sizeof(thePos));
  1570.  
  1571.     if (!err)
  1572.         err = AECoerceDesc(&theInsertRec,typeInsertionLoc,&theInsl);
  1573.  
  1574.     if (!err)
  1575.         err = EudoraSuite::MakeEvent(kAECoreSuite,kAECreateElement,&theEvent);
  1576.     if (!err)
  1577.         err = AEPutParamDesc(&theEvent,keyAEInsertHere,&theInsl);
  1578.  
  1579.     AEDisposeDesc(&nullSpec);
  1580.     AEDisposeDesc(&theName);
  1581.     AEDisposeDesc(&theFolder);
  1582.     AEDisposeDesc(&theMailbox);
  1583.     AEDisposeDesc(&theInsertRec);
  1584.     AEDisposeDesc(&theInsl);
  1585.  
  1586.     theClass=cEuMessage;
  1587.     if (!err)
  1588.         err = AEPutParamPtr(&theEvent,keyAEObjectClass,cType,&theClass,sizeof(theClass));
  1589.     if (!err)
  1590.         err = EudoraSuite::SendEvent(&theEvent);
  1591.  
  1592.  
  1593. /* This section fills in various fields.
  1594.    It is equivalent to  the following AppleScript:
  1595.         set field "to" of message 0 to "data"
  1596. */
  1597.  
  1598.     if (!err) {
  1599.         if ( toRecipientPtr )
  1600.         err = SendSetData("\pto",toRecipientPtr, GetPtrSize(toRecipientPtr));
  1601.     }
  1602.     
  1603.     if (!err) {
  1604.         if ( ccRecipientPtr )
  1605.         err = SendSetData("\pcc",ccRecipientPtr, GetPtrSize(ccRecipientPtr));
  1606.     }
  1607.     if (!err) {
  1608.         if ( bccRecipientPtr ) 
  1609.         err = SendSetData("\pbcc",bccRecipientPtr, GetPtrSize(bccRecipientPtr));
  1610.     }
  1611.     
  1612.     if (!err)
  1613.         err = SendSetData("\psubject",subjectPtr, GetPtrSize(subjectPtr));
  1614.     if (!err)
  1615.         err = SendSetData("\p",bodyPtr, XP_STRLEN(bodyPtr) );
  1616.  
  1617. /* This sets the priority of the message. See the constants defined above for the legal
  1618.    values.
  1619. */
  1620.     
  1621.     err = Set_Eudora_Priority(thePriority);        
  1622.         
  1623.  
  1624. /* This attaches a file to the Eudora message provided it is a proper FSSpec. */
  1625.     if (StrLength(theEnclosurePtr->name)>0)
  1626.         {
  1627.             if (!err)
  1628.                 err = MakeCurrentMsgSpec(&msgSpec);
  1629.             if (!err)
  1630.                 err = EudoraSuite::MakeEvent(kEudoraSuite,kEuAttach,&theEvent);
  1631.             if (!err)
  1632.                 err = AEPutParamDesc(&theEvent,keyAEResult,&msgSpec);
  1633.                 if (!err)
  1634.                     err = AECreateList(nil,0,false,&theEnclList);
  1635.                 if (!err)
  1636.                     err = AEPutPtr(&theEnclList,0,typeFSS,&theEnclosurePtr->name,
  1637.                         sizeof(theEnclosurePtr->name) );
  1638.                 if (!err)
  1639.                     err = AEPutParamDesc(&theEvent,keyEuDocumentList,&theEnclList);
  1640.                 if (!err)
  1641.                     err = EudoraSuite::SendEvent(&theEvent);
  1642.                 AEDisposeDesc(&msgSpec);
  1643.                 AEDisposeDesc(&theEnclList);
  1644.             }
  1645.  
  1646.  
  1647. /* This tells Eudora to queue the current message. */
  1648.     if (!err)
  1649.         err = EudoraSuite::MakeCurrentMsgSpec(&msgSpec);
  1650.     if (!err)
  1651.         err = EudoraSuite::MakeEvent(kEudoraSuite,kEuQueue,&theEvent);
  1652.     if (!err)
  1653.         err = AEPutParamDesc(&theEvent,keyAEResult,&msgSpec);
  1654.     AEDisposeDesc(&msgSpec);
  1655.     if (!err)
  1656.         err = EudoraSuite::SendEvent(&theEvent);
  1657.         
  1658.     return err;
  1659.  
  1660. }
  1661.  
  1662. // --------------------------------------------------------------
  1663. /*    Given the priority of a message, this sets the priority in the message.
  1664.     This same type of procedure can be used for many of the AppleScript commands in
  1665.     the form of:     set <item> of message 0 to <data>
  1666.     
  1667.     */
  1668. // --------------------------------------------------------------
  1669.  
  1670. OSErr EudoraSuite::Set_Eudora_Priority(long thePriority)
  1671. {
  1672.   AEDesc theMsg,theData,thePropSpec,thePriorityDesc;
  1673.   AppleEvent theEvent;
  1674.   OSErr theErr;
  1675.   AEKeyword theProperty;
  1676.   Handle h;
  1677.  
  1678.   theErr = MakeCurrentMsgSpec(&theMsg);
  1679.  
  1680.   theProperty = pEuPriority;
  1681.   AECreateDesc(typeType,&theProperty,sizeof (theProperty),&thePriorityDesc);
  1682.  
  1683.   if (!theErr)
  1684.      theErr = CreateObjSpecifier(typeProperty,theMsg,typeProperty,thePriorityDesc,true,&thePropSpec);
  1685.   if (!theErr)
  1686.     theErr = MakeEvent(kAECoreSuite,kAESetData,&theEvent);
  1687.  
  1688.   if (!theErr)
  1689.     theErr = AEPutKeyDesc(&theEvent, keyDirectObject, &thePropSpec);
  1690.   if (!theErr)
  1691.     theErr = AEDisposeDesc(&thePropSpec);
  1692.  
  1693.   h = NewHandle (sizeof(thePriority));
  1694.   BlockMove ((Ptr)&thePriority,*h,sizeof(thePriority));
  1695.   theData.descriptorType = typeInteger;
  1696.   theData.dataHandle = h;
  1697.   if (!theErr)
  1698.     theErr=AEPutParamDesc(&theEvent,keyAEData,&theData);
  1699.   if (!theErr)
  1700.     theErr = SendEvent(&theEvent);
  1701.     DisposeHandle(h);
  1702.     AEDisposeDesc(&theMsg);
  1703.     AEDisposeDesc(&theData);
  1704.     AEDisposeDesc(&thePriorityDesc);
  1705.  
  1706.    return theErr;
  1707.  
  1708. }
  1709.  
  1710.  
  1711.  
  1712. /*-------------------------------------------------------------*/
  1713. //     class MoreExtractFromAEDesc
  1714. //    Apple event helpers -- extension of UExtractFromAEDesc.h
  1715. //    All the miscelaneous AppleEvent helper routines.
  1716. /*-------------------------------------------------------------*/
  1717.  
  1718.  
  1719. // --------------------------------------------------------------
  1720. /*    Given an AppleEvent, locate a string given a keyword and
  1721.     return the string
  1722.     In:    Event to search
  1723.         AEKeyword assocaated with the string
  1724.         C string ptr
  1725.     Out: Pointer to a newly created C string returned */
  1726. // --------------------------------------------------------------
  1727. void MoreExtractFromAEDesc::GetCString(const AppleEvent    &inAppleEvent, 
  1728.                         AEKeyword keyword, char * & s)
  1729. {
  1730.     StAEDescriptor desc;
  1731.     OSErr err = ::AEGetParamDesc(&inAppleEvent,keyword,typeWildCard,&desc.mDesc);
  1732.     
  1733.     ThrowIfOSErr_(err);
  1734.     TheCString(desc, s);
  1735. }
  1736.  
  1737. // --------------------------------------------------------------
  1738. /*    Given an AEDesc of type typeChar, return its string.
  1739.     In:    AEDesc containing a string
  1740.         C string ptr
  1741.     Out: Pointer to a newly created C string returned */
  1742. // --------------------------------------------------------------
  1743. void MoreExtractFromAEDesc::TheCString(const AEDesc &inDesc, char * & outPtr)
  1744. {
  1745.     outPtr = nil;
  1746.     Handle    dataH;
  1747.     AEDesc    coerceDesc = {typeNull, nil};
  1748.     if (inDesc.descriptorType == typeChar) {
  1749.         dataH = inDesc.dataHandle;        // Descriptor is the type we want
  1750.     
  1751.     } else {                            // Try to coerce to the desired type
  1752.         if (AECoerceDesc(&inDesc, typeChar, &coerceDesc) == noErr) {
  1753.                                         // Coercion succeeded
  1754.             dataH = coerceDesc.dataHandle;
  1755.  
  1756.         } else {                        // Coercion failed
  1757.             ThrowOSErr_(errAETypeError);
  1758.         }
  1759.     }
  1760.     
  1761.     Int32    strLength = GetHandleSize(dataH);
  1762.     outPtr = (char *)XP_ALLOC(strLength+1);    // +1 for NULL ending
  1763.     ThrowIfNil_( outPtr );
  1764.     // Terminate the string
  1765.     BlockMoveData(*dataH, outPtr, strLength);
  1766.     outPtr[strLength] = 0;
  1767.     
  1768.     if (coerceDesc.dataHandle != nil) {
  1769.         AEDisposeDesc(&coerceDesc);
  1770.     }
  1771. }
  1772.  
  1773. // --------------------------------------------------------------
  1774. /*    Add an error string and error code to an AppleEvent.
  1775.     Typically used when constructing the return event when an
  1776.     error occured
  1777.     In:    Apple Event to append to
  1778.         Error string
  1779.         Error code
  1780.     Out: keyErrorNum and keyErrorSting AEDescs are added to the Event. */
  1781. // --------------------------------------------------------------
  1782. void MoreExtractFromAEDesc::MakeErrorReturn(AppleEvent &event,const 
  1783.         CStr255& errorString, OSErr errorCode)
  1784. {
  1785.     StAEDescriptor    errorNum(errorCode);
  1786.     StAEDescriptor    errorText((ConstStringPtr)errorString);
  1787.     // We can ignore the errors. If error occurs, it only means that the reply is not handled
  1788.     OSErr err = ::AEPutParamDesc(&event, keyErrorNumber, &errorNum.mDesc);
  1789.     err = ::AEPutParamDesc(&event, keyErrorString, &errorText.mDesc);    
  1790. }
  1791.  
  1792. // --------------------------------------------------------------
  1793. /*    Display an error dialog if the given AppleEvent contains
  1794.     a keyErrorNumber.  a keyErrorString is optional and will be
  1795.     displayed if present
  1796.     In:    Apple Event
  1797.     Out: Error dialog displayed if error data present. */
  1798. // --------------------------------------------------------------
  1799. Boolean MoreExtractFromAEDesc::DisplayErrorReply(AppleEvent &reply)
  1800. {
  1801.     DescType realType;
  1802.     Size actualSize;
  1803.     OSErr    errNumber;
  1804.     Str255 errorString;
  1805.     // First check for errors
  1806.     errNumber = AEUtilities::EventHasErrorReply(reply);
  1807.     if (errNumber == noErr)
  1808.         return false;
  1809.     
  1810.     // server returned an error, so get error string
  1811.     OSErr err = ::AEGetParamPtr(&reply, keyErrorString, typeChar, 
  1812.                         &realType, &errorString[1], sizeof(errorString)-1, 
  1813.                         &actualSize);
  1814.     if (err == noErr)
  1815.     {
  1816.         errorString[0] = actualSize > 255 ? 255 : actualSize;
  1817.         ErrorManager::ErrorNotify(errNumber, errorString);
  1818.     }
  1819.     else
  1820.         ErrorManager::ErrorNotify(errNumber, (unsigned char *)*GetString(AE_ERR_RESID));
  1821.     return TRUE;
  1822. }
  1823.  
  1824. // --------------------------------------------------------------
  1825. /*    Return the process serial number of the sending process.
  1826.     In:    Apple Event send by some app.
  1827.     Out: ProcessSerialNumber of the sending app. */
  1828. // --------------------------------------------------------------
  1829. ProcessSerialNumber    MoreExtractFromAEDesc::ExtractAESender(const AppleEvent &inAppleEvent)
  1830. {
  1831.     Size realSize;
  1832.     DescType realType;
  1833.     TargetID target;
  1834.     ProcessSerialNumber psn;
  1835.  
  1836.     OSErr err = AEGetAttributePtr(&inAppleEvent, keyAddressAttr, typeTargetID, &realType, 
  1837.                                     &target, sizeof(target), &realSize);
  1838.     ThrowIfOSErr_(err);
  1839.     err = ::GetProcessSerialNumberFromPortName(&target.name,&psn);
  1840.     ThrowIfOSErr_(err);
  1841.     return psn;
  1842. }
  1843.  
  1844. //-----------------------------------
  1845. void MoreExtractFromAEDesc::DispatchURLDirectly(const AppleEvent &inAppleEvent)
  1846. //-----------------------------------
  1847. {
  1848.     char *url = NULL;
  1849.     MoreExtractFromAEDesc::GetCString(inAppleEvent, keyDirectObject, url);
  1850.     ThrowIfNil_(url);
  1851.     URL_Struct * request = NET_CreateURLStruct (url, NET_DONT_RELOAD);
  1852.     XP_FREE (url);
  1853.     ThrowIfNil_(request);
  1854.     request->internal_url = TRUE; // for attachments in mailto: urls.
  1855.     CURLDispatcher::DispatchURL(request, NULL);
  1856. }
  1857.  
  1858.  
  1859. /*-------------------------------------------------------------*/
  1860. //     class AEUtilities
  1861. //    Some more simple Apple Event utility routines.
  1862. /*-------------------------------------------------------------*/
  1863.  
  1864. // --------------------------------------------------------------
  1865. /*    CreateAppleEvent
  1866.     Create a new Apple Event from scratch.
  1867.     In:    Apple Event suite
  1868.         Apple Event ID
  1869.         Ptr to return Apple Event
  1870.         ProcessSerialNumber of the target app to send event to.
  1871.     Out:A new Apple Event is created.  More data may be added to
  1872.         the event simply by calling AEPutParamDesc or AEPutParamPtr */
  1873. // --------------------------------------------------------------
  1874.  
  1875. OSErr AEUtilities::CreateAppleEvent(OSType suite, OSType id, 
  1876.         AppleEvent &event, ProcessSerialNumber targetPSN)
  1877. {
  1878.     AEAddressDesc progressApp;
  1879.     OSErr err = ::AECreateDesc(typeProcessSerialNumber, &targetPSN, 
  1880.                              sizeof(targetPSN), &progressApp);
  1881.     if (err)
  1882.         return err;
  1883.     err = ::AECreateAppleEvent(suite, id,
  1884.                                     &progressApp,
  1885.                                     kAutoGenerateReturnID,
  1886.                                     kAnyTransactionID,
  1887.                                     &event);
  1888.     AEDisposeDesc(&progressApp);
  1889.     return err;
  1890. }
  1891.  
  1892. // --------------------------------------------------------------
  1893. /*    Check to see if there is an error in the given AEvent.
  1894.     We simply return an OSError equiv to the error value
  1895.     in the event.  If none exists (or an error took place
  1896.     during access) we return 0.
  1897.     In:    Apple Event to test
  1898.     Out:Error value returned */
  1899. // --------------------------------------------------------------
  1900. OSErr AEUtilities::EventHasErrorReply(AppleEvent & reply)
  1901. {
  1902.     if (reply.descriptorType == typeNull)
  1903.         return noErr;
  1904.         
  1905.     long    errNumber;
  1906.     Size realSize;
  1907.     DescType realType;
  1908.     OSErr err = ::AEGetParamPtr(&reply, keyErrorNumber, typeLongInteger, 
  1909.                         &realType, &errNumber, sizeof(errNumber), 
  1910.                         &realSize);
  1911.     if (err == noErr)
  1912.         return errNumber;
  1913.     else
  1914.         return noErr; 
  1915. }
  1916.