home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / feutil.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  79.5 KB  |  2,609 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. #include "stdafx.h"
  20. #include "fe_proto.h"
  21. #include "hiddenfr.h"
  22. #include "postal.h"
  23. #include "helper.h"
  24. #include "prefapi.h"
  25. #ifdef MOZ_MAIL_NEWS 
  26. #include "mailfrm.h"
  27. #endif // MOZ_MAIL_NEWS
  28. #include "toolbar2.h"
  29. #include "VerReg.h"
  30. #include "libmocha.h"
  31. #include "java.h"
  32. #include "ngdwtrst.h"
  33.  
  34. extern "C" {
  35. #include "xpgetstr.h"
  36. extern int XP_ALERT_NETCASTER_NO_JS;
  37. extern int XP_ALERT_CANT_RUN_NETCASTER;
  38. };
  39.  
  40.  
  41. //    File used to house all general purpose front end
  42. //        function which have no other specific home.
  43. //    All functions in this file should begin with FEU.
  44.  
  45. //    Way to get a frame window pointer out of a context ID.
  46. //    Must be of the appropriate type (Browser, mail, any, etc).
  47.  
  48. extern char szOLEFileType[MAX_INTERNAL_OLEFORMAT][4];
  49.  
  50. CFrameWnd *FEU_FindFrameByID(DWORD dwID, MWContextType cxType)
  51. {
  52.     //    Use the frame glue to do most of the work.
  53.     CFrameGlue *pFrameGlue = CFrameGlue::FindFrameByID(dwID, cxType);
  54.     if(pFrameGlue == NULL)    {
  55.         return(NULL);
  56.     }
  57.  
  58.     //    Return the frame window of the frame glue, can be NULL.
  59.     return(pFrameGlue->GetFrameWnd());
  60. }
  61.  
  62. //    Way to get a frame window that was last active browser window.
  63. CFrameWnd *FEU_GetLastActiveFrame(MWContextType cxType, int nFindEditor)
  64. {
  65.     //    Have the frame glue look it up.
  66.     CFrameGlue *pFrameGlue = CFrameGlue::GetLastActiveFrame(cxType, nFindEditor);
  67.     if(pFrameGlue == NULL)    {
  68.         return(NULL);
  69.     }
  70.  
  71.     //    Return the frame window as known by the glue.
  72.     return(pFrameGlue->GetFrameWnd());
  73. }
  74.  
  75. //    Way to get a frame window that was last active browser window.
  76. CAbstractCX *FEU_GetLastActiveFrameContext(MWContextType cxType, int nFindEditor)
  77. {
  78.     //    Have the frame glue look it up.
  79.     CFrameGlue *pFrameGlue = CFrameGlue::GetLastActiveFrame(cxType, nFindEditor);
  80.     if(pFrameGlue == NULL)    {
  81.         return(NULL);
  82.     }
  83.  
  84.     //    Return the frame window as known by the glue.
  85.     return(pFrameGlue->GetMainContext());
  86. }
  87.  
  88. CFrameWnd *FEU_GetLastActiveFrameByCustToolbarType(CString custToolbar, CFrameWnd *pCurrentFrame, BOOL bUseSaveInfo)
  89. {
  90.         //    Have the frame glue look it up.
  91.     CFrameGlue *pFrameGlue = CFrameGlue::GetLastActiveFrameByCustToolbarType(custToolbar, pCurrentFrame, bUseSaveInfo);
  92.     if(pFrameGlue == NULL)    {
  93.         return(NULL);
  94.     }
  95.  
  96.     //    Return the frame window as known by the glue.
  97.     return(pFrameGlue->GetFrameWnd());
  98.  
  99. }
  100.  
  101. // Way to get the bottommost frame of t ype cxType
  102. CFrameWnd *FEU_GetBottomFrame(MWContextType cxType, int nFindEditor)
  103. {
  104.  
  105.     CFrameGlue *pFrameGlue = CFrameGlue::GetBottomFrame(cxType, nFindEditor);
  106.     if(pFrameGlue == NULL)
  107.         return NULL;
  108.  
  109.     //Return the frame window as known by the glue.
  110.     return(pFrameGlue->GetFrameWnd());
  111.  
  112. }
  113.  
  114. //    Way to get a frame window that was last active browser window.
  115. int FEU_GetNumActiveFrames(MWContextType cxType, int nFindEditor)
  116. {
  117.     //    Have the frame glue look it up.
  118.     int nCount = CFrameGlue::GetNumActiveFrames(cxType, nFindEditor);
  119.  
  120.     //    Return the frame window as known by the glue.
  121.     return(nCount);
  122. }
  123.  
  124. //    Way to get the context ID out of the frame which was last active.
  125. //    Returns 0 on error.
  126. DWORD FEU_GetLastActiveFrameID(MWContextType cxType)
  127. {
  128.     DWORD dwRetval = 0;
  129.  
  130.     //    Look up the last active frame of said type.
  131.     CFrameGlue *pFrameGlue = CFrameGlue::GetLastActiveFrame(cxType);
  132.     if(pFrameGlue != NULL)    {
  133.         //    Must have a context.
  134.         if(pFrameGlue->GetActiveContext() != NULL)    {
  135.             dwRetval = pFrameGlue->GetActiveContext()->GetContextID();
  136.         }
  137.         else if(pFrameGlue->GetMainContext() != NULL)    {
  138.             dwRetval = pFrameGlue->GetMainContext()->GetContextID();
  139.         }
  140.     }
  141.  
  142.     return(dwRetval);
  143. }
  144.  
  145. //#ifndef NO_TAB_NAVIGATION 
  146. // Scroll the current MWContext so that the Rect is visible
  147. // FEU_MakeRectVisible() is subtracted from old FEU_MakeFormVisible(),
  148. // and is used not only for Form elements, but other Tabable
  149. // elements, such as links.
  150. void FEU_MakeRectVisible(MWContext *pContext, const UINT left, const UINT top, const UINT right, const UINT bottom)
  151. {
  152.     if(pContext == NULL )   
  153.         return;
  154.  
  155.     if(! ABSTRACTCX(pContext) || ! ABSTRACTCX(pContext)->IsWindowContext() ) 
  156.         return;
  157.  
  158.     LTRB Rect( left, top, right, bottom);
  159.     CPaneCX *pCX = PANECX(pContext);
  160.     int32 lX = pCX->GetOriginX();
  161.     int32 lY = pCX->GetOriginY();
  162.     BOOL bMove = FALSE;
  163.  
  164.     //  If the element is partially to the right of the screen, we only want to
  165.     //      move enough to get it fully on the screen.
  166.     if(Rect.left < pCX->GetOriginX() + pCX->GetWidth() &&
  167.         Rect.right > pCX->GetOriginX() + pCX->GetWidth() &&
  168.         Rect.Width() < pCX->GetWidth())   {
  169.         lX += Rect.right - (pCX->GetOriginX() + pCX->GetWidth());
  170.         bMove = TRUE;
  171.     }
  172.  
  173.     //  If the element is partially to the bottom of the screen, we only want to
  174.     //      move enough to get it fully onto the screen.
  175.     if(Rect.top < pCX->GetOriginY() + pCX->GetHeight() &&
  176.         Rect.bottom > pCX->GetOriginY() + pCX->GetHeight() &&
  177.         Rect.Height() < pCX->GetHeight()) {
  178.         lY += Rect.bottom - (pCX->GetOriginX() + pCX->GetHeight());
  179.         bMove = TRUE;
  180.     }
  181.  
  182.     //  If the element is not fully on the screen, then we want to move so that it
  183.     //      is on the screen at whatever cost that may be.
  184.     if(Rect.left < lX || Rect.left > lX + pCX->GetWidth() || Rect.top < lY ||
  185.         Rect.top > lY + pCX->GetHeight())  {
  186.         lX = Rect.left;
  187.         lY = Rect.top;
  188.         bMove = TRUE;
  189.     }
  190.  
  191.     //  Move if needed.
  192.     if(bMove)   {
  193.         FE_SetDocPosition(pContext, FE_VIEW, lX, lY);
  194.     }
  195.  
  196. }    // FEU_MakeRectVisible(
  197.  
  198. // old version is named as FEU_MakeFormVisible()
  199. // Scroll the current MWContext so that the child window is visible
  200. // New version.
  201. void FEU_MakeElementVisible(MWContext *pContext, LO_Any  *pElement)
  202. {
  203.     if( NULL == pElement)
  204.         return;
  205.     //  Figure up where the form element actually lies.
  206.     LTRB Rect;
  207.     Rect.left = pElement->x + pElement->x_offset;
  208.     Rect.top = pElement->y + pElement->y_offset;
  209.     Rect.right = Rect.left + pElement->width;
  210.     Rect.bottom = Rect.top + pElement->height;
  211.  
  212.     FEU_MakeRectVisible( pContext, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom) );
  213. }
  214. //#else    /* NO_TAB_NAVIGATION */
  215. //#endif    /* NO_TAB_NAVIGATION */
  216.  
  217. //    The purpose of FEU_AhAhAhAhStayingAlive is to house the one and only
  218. //        saturday night fever function; named after Chouck's idol.
  219. //    This function will attempt to do all that is necessary in order
  220. //        to keep the application's messages flowing and idle loops
  221. //        going when we need to finish an asynchronous operation
  222. //        synchronously.
  223. //    The current cases that cause this are RPC calls into the
  224. //        application where we need to return a value or produce output
  225. //        from only one entry point before returning to the caller.
  226. //
  227. //    If and when you modify this function, get your changes reviewed.
  228. //    It is too vital that this work, always.
  229. //
  230. //    The function only attempts to look at one message at a time, or
  231. //        propigate one idle call at a time, keeping it's own idle count.
  232. //    This is not a loop.  YOU must provide the loop which calls this function.
  233. //
  234. //    Due to the nature and order of which we process windows messages, this
  235. //        can seriously mess with the flow of control through the client.
  236. //    If there is any chance at all that you can ensure that you are at the
  237. //        bottom of the message queue before doing this, then please take those
  238. //        measures.
  239. extern "C" void FEU_StayingAlive()
  240. {
  241.     static long lIdleCounter = 0;
  242.  
  243.     //    Stage 1.
  244.     //    See if there are any messages which need to be propigated.
  245.     MSG msg;
  246.     if(::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE))    {
  247.         BOOL bPumpVal = theApp.NSPumpMessage();
  248.  
  249.         //    If this assertion fails, then we received a WM_QUIT, and 
  250.         //        the user is about to receive a dialog from the OS saying
  251.         //        we are not responding to the system's request to shut down.
  252.         //    Nothing we can do and still accomplish what we are trying to do....
  253.         ASSERT(bPumpVal);
  254.  
  255.         //    Reset the idle counter.
  256.         lIdleCounter = 0;
  257.     }
  258.     else    {
  259.         //    Stage 2.
  260.         //    Call the Apps Idle loop.
  261.         //    Ignore wether or not it says it needs or does not need more idle time.
  262.         //    It is wholly dependent upon wether or not there are events in the queue.
  263.         theApp.OnIdle(lIdleCounter++);
  264.     }
  265. }
  266.  
  267. //    A utility function to block returning until a context is no longer
  268. //        found in the context list.
  269. void FEU_BlockUntilDestroyed(DWORD dwContextID)
  270. {
  271.     TRACE("Entering FEU_BlockUntilDestroyed(%lu)\n", dwContextID);
  272.  
  273.     //    Loop until the context is not in the context list, meaning it
  274.     //        has been destroyed.
  275.     while(CAbstractCX::FindContextByID(dwContextID) != NULL)    {
  276.         //    Keep the app going.
  277.         FEU_StayingAlive();
  278.     }
  279.  
  280.     TRACE("Leaving FEU_BlockUntilDestroyed(%lu)\n", dwContextID);
  281. }
  282.  
  283. //
  284. // Dynamically open the MAPI libraries for mail posting
  285. //
  286. void FEU_OpenMapiLibrary() 
  287. {
  288.     BOOL bLoadOK = FALSE;
  289.  
  290.     theApp.m_fnOpenMailSession = NULL;
  291.     theApp.m_fnComposeMailMessage = NULL;
  292.     theApp.m_fnUnRegisterMailClient = NULL; 
  293.     theApp.m_fnShowMailBox = NULL;
  294.     theApp.m_fnShowMessageCenter = NULL;
  295.     theApp.m_fnCloseMailSession = NULL;
  296.     theApp.m_fnGetMenuItemString = NULL;
  297.  
  298.     UINT fuErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX);
  299.  
  300.     char * prefStr = NULL;
  301.     PREF_CopyCharPref("mail.altmail_dll",&prefStr);
  302.     theApp.m_hPostalLib = LoadLibrary(prefStr);
  303.     if (prefStr) XP_FREE(prefStr);
  304.  
  305.     SetErrorMode(fuErrorMode);
  306. #ifdef XP_WIN32 
  307.     if(theApp.m_hPostalLib) 
  308.     {
  309. #else 
  310.     if(theApp.m_hPostalLib > HINSTANCE_ERROR) 
  311.     { 
  312. #endif
  313.         //If we don't find "ShowMailBox" then we know it's either an old or invalid dll
  314.         SHOWMAILBOX testProc = (SHOWMAILBOX)::GetProcAddress(theApp.m_hPostalLib, "ShowMailBox");
  315.         if(testProc) 
  316.         {
  317.             REGISTERMAIL regProc = (REGISTERMAIL)::GetProcAddress(theApp.m_hPostalLib, "RegisterMailClient");
  318.             theApp.m_fnOpenMailSession = 
  319.                 (OPENMAIL)::GetProcAddress(theApp.m_hPostalLib, "OpenMailSession");
  320.             theApp.m_fnComposeMailMessage = 
  321.                 (COMPOSEMAIL)::GetProcAddress(theApp.m_hPostalLib, "ComposeMailMessage");
  322.             theApp.m_fnUnRegisterMailClient = 
  323.                 (UNREGISTERMAIL)::GetProcAddress(theApp.m_hPostalLib, "UnRegisterMailClient");
  324.             theApp.m_fnShowMailBox =  
  325.                 (SHOWMAILBOX)::GetProcAddress(theApp.m_hPostalLib, "ShowMailBox"); 
  326.             theApp.m_fnShowMessageCenter =  
  327.                 (SHOWMESSAGECENTER)::GetProcAddress(theApp.m_hPostalLib, "ShowMessageCenter"); 
  328.             theApp.m_fnCloseMailSession =  
  329.                 (CLOSEMAIL)::GetProcAddress(theApp.m_hPostalLib, "CloseMailSession"); 
  330.             theApp.m_fnGetMenuItemString =
  331.                 (GETMENUITEMSTRING)::GetProcAddress(theApp.m_hPostalLib, "GetMenuItemString"); 
  332.  
  333.             if(theApp.m_fnOpenMailSession && theApp.m_fnComposeMailMessage && theApp.m_fnUnRegisterMailClient
  334.                 && theApp.m_fnShowMailBox && theApp.m_fnShowMessageCenter && theApp.m_fnCloseMailSession
  335.                 && theApp.m_fnGetMenuItemString && regProc)
  336.             {
  337.                 POSTCODE status = (*regProc) (theApp.m_pHiddenFrame->m_hWnd, "Netscape Mail System");
  338.                 if(status == POST_OK)
  339.                     bLoadOK = TRUE;
  340.                 else
  341.                     MessageBox(NULL, szLoadString(IDS_ALTMAIL_REGISTER_FAILED), szLoadString(AFX_IDS_APP_TITLE), MB_OK | MB_ICONEXCLAMATION); 
  342.             }
  343.             else
  344.                 MessageBox(NULL, szLoadString(IDS_ALTMAIL_MISSING_FUNCTIONS), szLoadString(AFX_IDS_APP_TITLE), MB_OK | MB_ICONEXCLAMATION); 
  345.         } 
  346.         else
  347.             MessageBox(NULL, szLoadString(IDS_ALTMAIL_OLD_DLL), szLoadString(AFX_IDS_APP_TITLE), MB_OK | MB_ICONEXCLAMATION); 
  348.     }
  349.     else 
  350.     { 
  351.         #ifdef XP_WIN16
  352.             //In Win16 the LoadLibrary returns < 32 when it fails
  353.             //and since we check m_hPostalLib != NULL throughout
  354.             //the code let's set m_hPostalLib to NULL.
  355.             theApp.m_hPostalLib = NULL;
  356.         #endif
  357.  
  358.         MessageBox(NULL, szLoadString(IDS_ALTMAIL_MISSING_DLL), szLoadString(AFX_IDS_APP_TITLE), MB_OK | MB_ICONEXCLAMATION); 
  359.     } 
  360.  
  361.     if(!bLoadOK && theApp.m_hPostalLib)
  362.     {
  363.         FreeLibrary(theApp.m_hPostalLib);
  364.         theApp.m_hPostalLib = NULL;
  365.     }
  366. }
  367.  
  368. void FEU_CloseMapiLibrary()
  369. {
  370.     if(theApp.m_fnCloseMailSession) 
  371.         (*theApp.m_fnCloseMailSession) ();
  372.     if(theApp.m_fnUnRegisterMailClient)
  373.         (*theApp.m_fnUnRegisterMailClient) ();
  374.     if(theApp.m_hPostalLib)
  375.         FreeLibrary(theApp.m_hPostalLib);
  376.     theApp.m_hPostalLib = NULL;
  377.  
  378.     // call init if reload
  379.     theApp.m_bInitMapi = TRUE;
  380.  
  381.     // clear out all function pointers
  382.     theApp.m_fnOpenMailSession = NULL;
  383.     theApp.m_fnComposeMailMessage = NULL;
  384.     theApp.m_fnUnRegisterMailClient = NULL; 
  385.     theApp.m_fnShowMailBox = NULL; 
  386.     theApp.m_fnShowMessageCenter = NULL;
  387.     theApp.m_fnCloseMailSession = NULL;
  388.     theApp.m_fnGetMenuItemString = NULL;
  389. }
  390.  
  391. #ifdef XP_WIN16
  392. //    16 bits needs a GetDiskFreeSpace call.
  393. BOOL GetDiskFreeSpace(LPCTSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
  394.     LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters)
  395. {
  396.     //    Init.
  397.     *lpSectorsPerCluster = 0;
  398.     *lpBytesPerSector = 0;
  399.     *lpNumberOfFreeClusters = 0;
  400.     *lpTotalNumberOfClusters = 0;
  401.  
  402.     //    Saftey dance.
  403.     if(lpRootPathName == NULL)    {
  404.         return(FALSE);
  405.     }
  406.     unsigned uDrive = 0;
  407.     if(strlen(lpRootPathName) > 1 && lpRootPathName[1] == ':')    {
  408.         //    Determine what drive we're looking at.
  409.         uDrive = toupper(*lpRootPathName) - 'A' + 1;
  410.         if(uDrive < 1 || uDrive > 26)    {
  411.             //    Use default drive....
  412.             uDrive = 0;
  413.         }
  414.     }
  415.  
  416.     //    Ask for amount of free disk space.
  417.     _diskfree_t dtFree;
  418.     memset(&dtFree, 0, sizeof(dtFree));
  419.     if(_dos_getdiskfree(uDrive, &dtFree))    {
  420.         //    Call failure.
  421.         return(FALSE);
  422.     }
  423.  
  424.     //    assign what we found out.
  425.     *lpSectorsPerCluster = dtFree.sectors_per_cluster;
  426.     *lpBytesPerSector = dtFree.bytes_per_sector;
  427.     *lpNumberOfFreeClusters = dtFree.avail_clusters;
  428.     *lpTotalNumberOfClusters = dtFree.total_clusters;
  429.  
  430.     //    Success.
  431.     return(TRUE);
  432. }
  433. #endif
  434.  
  435. //    See if content length can fit on a disk.
  436. //    If not, ask the user to confirm what they want (to write anyway).
  437. //    pFileName should contain the full path information for the file.
  438. //    All failures in this code mean success, actual errors should be
  439. //        found by other code attempting to open or write the file.
  440. //    Only on user denial to write will this code return failure.
  441.  
  442. // Implemented in femess.cpp, declared in msgcom.h
  443. extern "C" uint32 FE_DiskSpaceAvailable (MWContext *context, const char *lpszPath );
  444.  
  445. BOOL FEU_ConfirmFreeDiskSpace(MWContext *pContext, const char *pFileName, int32 lContentLength)
  446. {
  447.     //    Absence of context means success since can't confirm space with user.
  448.     if(pContext == NULL)    {
  449.         return(TRUE);
  450.     }
  451.  
  452.     //    Absence of a valid content length means success.
  453.     if(lContentLength <= 0)    {
  454.         TRACE("Invalid content length, can't check free disk space.\n");
  455.         return(TRUE);
  456.     }
  457.  
  458.     DWORD dwFreeSpace = FE_DiskSpaceAvailable( pContext, pFileName );
  459.  
  460.     //    If the length is greater than this, we need to confirm with the user on what to do.
  461.     if(dwFreeSpace < (DWORD)lContentLength)    {
  462.         //    Ask the user.
  463.         CString csAsk;
  464.         csAsk.LoadString(IDS_CONFIRM_DISK_SPACE);
  465.         size_t stSize = strlen(pFileName) + csAsk.GetLength() + 10;
  466.         char *pBuffer = new char[stSize];
  467.         if(pBuffer != NULL)    {
  468.             sprintf(pBuffer, csAsk, pFileName);
  469.             BOOL bRetval = FE_Confirm(pContext, pBuffer);
  470.             delete [] pBuffer;
  471.             return(bRetval);
  472.         }
  473.     }
  474.  
  475.     //    Let it happen.
  476.     return(TRUE);
  477. }
  478.  
  479. #if defined(XP_WIN16)
  480. //    There is literally no 32 bit equivalent for GetFreeSystemResources.
  481. //    Usually set pString to the file name, and iDigit to the line number.
  482. //    bBox controls wether or not a trace message will be used, or a dialog box.
  483. void FEU_FreeResources(const char *pString, int iDigit, BOOL bBox)
  484. {
  485.     UINT uSystem = GetFreeSystemResources(GFSR_SYSTEMRESOURCES);
  486.     UINT uGdi = GetFreeSystemResources(GFSR_GDIRESOURCES);
  487.     UINT uUser = GetFreeSystemResources(GFSR_USERRESOURCES);
  488.  
  489.     char aBuffer[1024];
  490.     sprintf(aBuffer, "%s:%d\n%u System\n%u GDI\n%u User\n", pString, iDigit, uSystem, uGdi, uUser);
  491.  
  492.     if(bBox)    {
  493.         ::MessageBox(NULL, aBuffer, "Resources", MB_OK);
  494.     }
  495.     TRACE(aBuffer);
  496. }
  497. #endif
  498.  
  499. //    Remove all trailing backslashes from the string.
  500. char *FEU_NoTrailingBackslash(char *pBackslash)    {
  501.     if(pBackslash)    {
  502.         int32 lTempLen = XP_STRLEN(pBackslash);
  503.         while(lTempLen)    {
  504.             lTempLen--;    //    Back off one for comparison of the last char.
  505.             if(*(pBackslash + lTempLen) == '\\')    {
  506.                 //    Knock it off.
  507.                 *(pBackslash + lTempLen) = '\0';
  508.             }
  509.             else    {
  510.                 //    No more backslashes to whack on the end.
  511.                 break;
  512.             }
  513.         }
  514.     }
  515.  
  516.     return(pBackslash);
  517. }
  518.  
  519. //  Replace all occurrences of original in pStr with new
  520. void FEU_ReplaceChar(char *pStr, char original, char replace)
  521. {
  522.     char *pFound;
  523.  
  524.     while((pFound = strchr(pStr, original)) != NULL) {
  525.         *pFound = replace;
  526.     }
  527. }
  528.  
  529. CString FEU_EscapeAmpersand(CString str)
  530. {
  531.  
  532.     CString newStr(""), leftStr, rightStr;
  533.     int nIndex;
  534.     rightStr = str;
  535.  
  536.     while((nIndex = rightStr.Find('&')) != -1)
  537.     {
  538.         leftStr = rightStr.Left(nIndex);
  539.         newStr = newStr + leftStr;
  540.         newStr = newStr + "&&";
  541.         rightStr = rightStr.Right(rightStr.GetLength() - nIndex - 1);
  542.     }
  543.  
  544.     // put in everything after the last ampersand.
  545.     newStr = newStr + rightStr;
  546.     return newStr;
  547.  
  548. }
  549.  
  550.  
  551.  
  552. //  Write string values to the registry in the said location.
  553. BOOL FEU_RegistryWizard(HKEY hRoot, const char *pKey, const char *pValue)
  554. {
  555.     if(!pKey)   {
  556.         return(FALSE);
  557.     }
  558.  
  559.     HKEY hKey;
  560.     LONG lResultCreate = RegCreateKey(hRoot, pKey, &hKey);
  561.  
  562.     if(lResultCreate != ERROR_SUCCESS)    {
  563.         return(FALSE);
  564.     }
  565.  
  566.     LONG lResultValue = RegSetValue(hKey, NULL, REG_SZ,
  567.                           pValue ? pValue : "",
  568.                           pValue ? XP_STRLEN(pValue) + 1 : 1);
  569.  
  570.     LONG lResultClose = RegCloseKey(hKey);
  571.  
  572.     if(lResultValue != ERROR_SUCCESS || lResultClose != ERROR_SUCCESS)  {
  573.         return(FALSE);
  574.     }
  575.  
  576.     return(TRUE);
  577. }
  578.  
  579.  
  580. // support quoted name.
  581. // clapse multiple space is not quoted.
  582. int FEU_ExtractCommaDilimetedFontName(const char *pArgList, int offSetByte, char *argItem)
  583. {
  584.     int        theQuote = '\0';
  585.     int        length = 0;
  586.     int        isLastSpace = 0;
  587.     
  588.     const char *pTraverse = pArgList + offSetByte;
  589.     *argItem = '\0';
  590.  
  591.     //  Handle all stupidness.
  592.     if(pTraverse == NULL || *pTraverse == '\0' || offSetByte < 0)    {
  593.         return(0);        // no arg found
  594.     }
  595.  
  596.     // skip leading space
  597.     while(*pTraverse && isspace(*pTraverse))  
  598.         pTraverse++;
  599.     
  600.     // See if this arg is quoted
  601.     theQuote = '\0';
  602.     if( *pTraverse == '"' || *pTraverse == '\'' ) {
  603.         theQuote = *pTraverse++;
  604.     }
  605.  
  606.     if( theQuote != '\0' ) {
  607.         // quoted arg
  608.         while( *pTraverse ) {
  609.             if( *pTraverse != theQuote ) {
  610.                 *argItem++ = * pTraverse++;
  611.                 length++;
  612.                 if( length >= MAXFONTFACENAME -1 ) {
  613.                     // overflow
  614.                     *(--argItem) = '\0';
  615.                     return(-1);       
  616.                 }
  617.             } else {
  618.                 *argItem = '\0';    // terminate
  619.                 pTraverse++;        // skip the quote
  620.                 break;
  621.             }
  622.         }
  623.  
  624.         // we passed the quote, now get over the comma
  625.         // ignore any char between closing quote and comma
  626.         while( *pTraverse && *pTraverse != ',' )     
  627.             pTraverse++;
  628.         
  629.         if( *pTraverse == ',' )
  630.             pTraverse++;
  631.     
  632.         return( pTraverse - pArgList );   // offset for next arg
  633.  
  634.     } 
  635.     
  636.     // arg without quote
  637.     while( *pTraverse && *pTraverse != ',' ) {
  638.         if( isLastSpace && isspace(*pTraverse) ) {
  639.             pTraverse++;           // clapse multiple space
  640.             continue;
  641.         } else {
  642.             isLastSpace = isspace(*pTraverse);
  643.             *argItem++ = *pTraverse++;
  644.             length++;
  645.             if( length >= MAXFONTFACENAME -1 ) {
  646.                 // overflow
  647.                 *(--argItem) = '\0';
  648.                 return(-1);       
  649.             }
  650.         }
  651.     }    // while( *pTraverse  )
  652.  
  653.     *argItem = '\0';        // terminator
  654.     // remove trailing space
  655.     while( --length && isspace( *(--argItem) ) )
  656.         *argItem = '\0';        // terminator
  657.  
  658.  
  659.     if( *pTraverse == ',' )
  660.         pTraverse++;
  661.  
  662.     return( pTraverse - pArgList );   // offset for next arg
  663. }
  664.  
  665. #ifdef not_support_quoted_font_face_name
  666. //  As the function indicates.
  667. //  Allocated return values to be freed by caller.
  668. char *FEU_ExtractCommaDilimetedString(const char *pArgList, int iArgToExtract)
  669. {
  670.     char *pRetval = NULL;
  671.  
  672.     //  Handle all stupidness.
  673.     if(pArgList == NULL || iArgToExtract <= 0)    {
  674.         return(pRetval);
  675.     }
  676.  
  677.     //  Skip to comma of the arg in question.
  678.     const char *pTraverse = pArgList;
  679.     do  {
  680.         iArgToExtract--;
  681.         if(iArgToExtract)   {
  682.             //  Search for next comma.
  683.             pTraverse = strchr(pTraverse, ',');
  684.             if(pTraverse)   {
  685.                 //  Go past comma.
  686.                 pTraverse++;
  687.             }
  688.         }
  689.     } while(iArgToExtract && pTraverse);
  690.  
  691.     if(pTraverse)   {
  692.         //  Skip all whitespace before the string.
  693.         while(isspace(*pTraverse))  {
  694.             pTraverse++;
  695.         }
  696.  
  697.         //  Copy till next comma or end of string.
  698.         //  Make sure not empty.
  699.         char *pEnd = strchr(pTraverse, ',');
  700.         int iAlloc = 0;
  701.         if(pEnd == NULL)    {
  702.             iAlloc = strlen(pTraverse) + 1;
  703.         }
  704.         else    {
  705.             iAlloc = pEnd - pTraverse + 1;
  706.         }
  707.  
  708.         //  If we've something to allocate.
  709.         if(iAlloc)  {
  710.             pRetval = (char *)XP_ALLOC(iAlloc);
  711.             if(pRetval) {
  712.                 //  clear it out.
  713.                 memset(pRetval, 0, iAlloc);
  714.  
  715.                 //  Copy over the amount -1.
  716.                 strncpy(pRetval, pTraverse, iAlloc - 1);
  717.  
  718.                 //  Walk backwards through the string, clearing off
  719.                 //      any space.
  720.                 pEnd = pRetval + iAlloc - 2;
  721.                 while(pEnd >= pRetval && isspace(*pEnd))   {
  722.                     *pEnd = '\0';
  723.                     pEnd--;
  724.                 }
  725.             }
  726.         }
  727.     }
  728.  
  729.     return(pRetval);
  730. }
  731. #endif // not_support_quoted_font_face_name
  732.  
  733. //  As the function indicates.
  734. //  Allocated return values to be freed by caller.
  735. char *FEU_ExtractCommaDilimetedQuotedString(const char *pArgList, int iArgToExtract) {
  736.     char *pRetval = NULL;
  737.  
  738.     //  Handle all stupidness.
  739.     if(pArgList == NULL || iArgToExtract <= 0)    {
  740.         return(pRetval);
  741.     }
  742.  
  743.     //  Find the first argument.
  744.     //  First arg will be right after the first quote.
  745.     const char *pTraverse = pArgList;
  746.     while(*pTraverse != '\"' && *pTraverse != '\0')   {
  747.         pTraverse++;
  748.     }
  749.  
  750.     //  If we have an argument.
  751.     if(*pTraverse == '\"')  {
  752.         pTraverse++;
  753.  
  754.         //  Okay, we need to find out where the ending comma exists.
  755.         int iQuoteLevel = 1;
  756.         const char *pQuote = pTraverse;
  757.         while(iQuoteLevel)  {
  758.             //  Go until we reach another quote.
  759.             while(*pQuote != '\"' && *pQuote != '\0')    {
  760.                 pQuote++;
  761.             }
  762.  
  763.             //  Did we reach a quote?
  764.             if(*pQuote == '\"') {
  765.                 pQuote++;
  766.  
  767.                 //  Assume this is an ending quote if we can find a comma before another quote.
  768.                 iQuoteLevel--;
  769.                 if(iQuoteLevel == 0)    {
  770.                     //  Begin ananlysis.
  771.                     const char *pComma = pQuote;
  772.                     while(*pComma != '\"' && *pComma != ',' && *pComma != '\0') {
  773.                         pComma++;
  774.                     }
  775.  
  776.                     //  What are we lookit at?
  777.                     if(*pComma == '\"') {
  778.                         //  Another quote.
  779.                         //  Up the quote count by 2.
  780.                         iQuoteLevel += 2;
  781.                     }
  782.                     else if(*pComma == ',') {
  783.                         //  We're out of here!
  784.                         //  Is this the first argument, though?
  785.                         if(iArgToExtract != 1)  {
  786.                             //  What they want is a different one.
  787.                             //  Go recursive and let them pick up where we left off.
  788.                             pRetval = FEU_ExtractCommaDilimetedQuotedString(pComma + 1, iArgToExtract - 1);
  789.                         }
  790.                         else    {
  791.                             //  We have the argument they want.
  792.                             //  Exact dimenstion of the argument are from pTraverse to pQuote - 2;
  793.                             //  Cathch the boundry case of "",
  794.                             if(pQuote - 2 >= pTraverse) {
  795.                                 int iLength = pQuote - pTraverse;
  796.                                 pRetval = (char *)XP_ALLOC(iLength);
  797.                                 if(pRetval) {
  798.                                     memset(pRetval, 0, iLength);
  799.  
  800.                                     int iCounter = 0;
  801.                                     while(pTraverse <= pQuote - 2)  {
  802.                                         pRetval[iCounter] = *pTraverse;
  803.                                         pTraverse++;
  804.                                         iCounter++;
  805.                                     }
  806.                                 }
  807.                             }
  808.                         }
  809.                     }
  810.                     else    {
  811.                         //  End of string, get out of while loop.
  812.                         //  However, if this is the only argument we're looking for, we may already have
  813.                         //      what we need.
  814.                         if(iArgToExtract == 1)  {
  815.                             //  We have the argument they want.
  816.                             //  Exact dimenstion of the argument are from pTraverse to pQuote - 2;
  817.                             //  Cathch the boundry case of "",
  818.                             if(pQuote - 2 >= pTraverse) {
  819.                                 int iLength = pQuote - pTraverse;
  820.                                 pRetval = (char *)XP_ALLOC(iLength);
  821.                                 if(pRetval) {
  822.                                     memset(pRetval, 0, iLength);
  823.  
  824.                                     int iCounter = 0;
  825.                                     while(pTraverse <= pQuote - 2)  {
  826.                                         pRetval[iCounter] = *pTraverse;
  827.                                         pTraverse++;
  828.                                         iCounter++;
  829.                                     }
  830.                                 }
  831.                             }
  832.                         }
  833.                         break;
  834.                     }
  835.                 }
  836.             }
  837.             else    {
  838.                 //  end of string, just get out of the while loop.
  839.                 break;
  840.             }
  841.         }
  842.     }
  843.  
  844.     return(pRetval);
  845. }
  846.  
  847. /****************************************************************************
  848. *
  849. *    FEU_TransBlt
  850. *
  851. *    PARAMETERS:
  852. *        pSrcDC        - pointer to source DC (with selected image)
  853. *        pDstDC        - pointer to destination DC (where image is to be drawn)
  854. *        ptSrc        - source x,y coordinates
  855. *        ptDst        - destination x,y coordinates
  856. *        nWidth        - image width
  857. *        nHeight        - image height
  858. *        rgbTrans    - transparent (background) color = RGB(255, 0, 255)
  859. *
  860. *    RETURNS:
  861. *        TRUE if successful.
  862. *
  863. *    DESCRIPTION:
  864. *        This function is called to do a transparent BitBlt. The background
  865. *        or transparent color is given by rgbTrans, with the default being
  866. *        pink {RGB(255, 0, 255)}. Pixels of this color will be masked out, so
  867. *        that the image is drawn without disturbing the destination.
  868. *
  869. *        Note that all masking operations are done in a memory DC to avoid
  870. *        flicker. pDstDC should be an actual screen DC.
  871. *
  872. ****************************************************************************/
  873.  
  874. BOOL FEU_TransBlt(CDC * pSrcDC, CDC * pDstDC, const CPoint & ptSrc,
  875.     const CPoint & ptDst, int nWidth, int nHeight, HPALETTE hPalette,
  876.     const COLORREF rgbTrans /*= RGB(255, 0, 255)*/)
  877. {
  878.     return FEU_TransBlt( pDstDC->m_hDC, ptDst.x, ptDst.y, nWidth, nHeight,
  879.                          pSrcDC->m_hDC, ptSrc.x, ptSrc.y, hPalette, rgbTrans );
  880. }
  881.  
  882. // More useful version that migrates more sanely from BitBlt.
  883.  
  884. BOOL FEU_TransBlt(HDC hDstDC, int nXDest, int nYDest, int nWidth, int nHeight, 
  885.                   HDC hSrcDC, int nXSrc, int nYSrc, HPALETTE hPalette, COLORREF rgbTrans )
  886. {
  887.  
  888.     BOOL bRtn = TRUE;
  889.     
  890.     // We'll paint our bitmap using the "true mask" method for transparency.
  891.     // We assume a pre-designated color for the background (transparent) color,
  892.     // and create our monochrome mask at run time.
  893.         
  894.     // Create mask for transparent blits
  895.     HPALETTE hOldPal = ::SelectPalette(hSrcDC, hPalette, FALSE);
  896. //    ::RealizePalette(hSrcDC);
  897.     HDC hMaskDC = ::CreateCompatibleDC(hDstDC);
  898.     HBITMAP hbmMask = ::CreateBitmap(nWidth, nHeight, 1, 1, NULL);
  899.     HBITMAP hOldMaskBmp = (HBITMAP) ::SelectObject(hMaskDC, hbmMask);
  900.     COLORREF rgbOldBk = ::SetBkColor(hSrcDC, rgbTrans);      
  901.     ::BitBlt(hMaskDC, 0, 0, nWidth, nHeight, hSrcDC, nXSrc, nYSrc, SRCCOPY);
  902.     ::SetBkColor(hSrcDC, rgbOldBk);
  903.     ::SelectPalette(hSrcDC, hOldPal, TRUE);
  904.         
  905.     // First, copy the existing image from the destination to memory for
  906.     // flicker free painting.
  907.     HDC hMemDC = ::CreateCompatibleDC(hDstDC);
  908.     HBITMAP hbmMem = ::CreateCompatibleBitmap(hDstDC, nWidth, nHeight);
  909.     HBITMAP hOldMemBmp = (HBITMAP) ::SelectObject(hMemDC, hbmMem);
  910.     ::BitBlt(hMemDC, 0, 0, nWidth, nHeight, hDstDC, nXDest, nYDest, SRCCOPY);
  911.     
  912.     // Next, blit our bitmap, the mask, then our bitmap again to the memory
  913.     // DC using the proper raster ops.
  914.        COLORREF rgbOldTxt = ::SetTextColor(hMemDC, PALETTERGB(0, 0, 0));
  915.     rgbOldBk = SetBkColor(hMemDC, PALETTERGB(255, 255, 255));
  916.     ::BitBlt(hMemDC, 0, 0, nWidth, nHeight, hSrcDC, nXSrc, nYSrc, SRCINVERT);
  917.     ::BitBlt(hMemDC, 0, 0, nWidth, nHeight, hMaskDC, 0, 0, SRCAND);
  918.     ::BitBlt(hMemDC, 0, 0, nWidth, nHeight, hSrcDC, nXSrc, nYSrc, SRCINVERT);
  919.        ::SetTextColor(hMemDC, rgbOldTxt);
  920.     ::SetBkColor(hMemDC, rgbOldBk);
  921.     
  922.     // Finally, blit from memory DC back to the destination
  923.     bRtn = ::BitBlt(hDstDC, nXDest, nYDest, nWidth, nHeight, hMemDC, 0, 0,
  924.                     SRCCOPY);
  925.     
  926.     // Cleanup
  927.     ::SelectObject(hMaskDC, hOldMaskBmp);
  928.     VERIFY(::DeleteDC(hMaskDC));
  929.     VERIFY(::DeleteObject(hbmMask));
  930.     
  931.     ::SelectObject(hMemDC, hOldMemBmp);
  932.     VERIFY(::DeleteDC(hMemDC));
  933.     VERIFY(::DeleteObject(hbmMem));
  934.  
  935.     return(bRtn);
  936. } // END OF    FUNCTION FEU_TransBlt()
  937.  
  938. //  This function create because no one knows how to use SetWindowPlacement
  939. //      correctly.
  940. void FEU_InitWINDOWPLACEMENT(HWND hWindow, WINDOWPLACEMENT *pWindowPlacement)
  941. {
  942.     //  Safety
  943.     if(!pWindowPlacement)    {
  944.         return;
  945.     }
  946.  
  947.     //  Thrash to zero.
  948.     memset(pWindowPlacement, 0, sizeof(WINDOWPLACEMENT));
  949.  
  950.     //  Set the length member.
  951.     pWindowPlacement->length = sizeof(WINDOWPLACEMENT);
  952.  
  953.     //  Safety
  954.     if(!hWindow) {
  955.         return;
  956.     }
  957.  
  958.     //  Initialize the structure with the current window settings.
  959.     BOOL bGotIt = ::GetWindowPlacement(hWindow, pWindowPlacement);
  960.     ASSERT(bGotIt);
  961.  
  962.     //  Hacker now free to change members that need to be changed without
  963.     //      thrashing other stuff too.
  964. }
  965.  
  966. //  Mouse timer handler (to handle scrolling selections).
  967. MouseTimerData::MouseTimerData(MWContext *pContext)
  968. {
  969.     //  By default treat as a context notification.
  970.     m_pContext = pContext;
  971.     m_pType = m_ContextNotify;
  972. }
  973.  
  974. void FEU_MouseTimer(void *vpReallyMouseTimerData)
  975. {
  976.     //  Cast.
  977.     MouseTimerData *pData = (MouseTimerData *)vpReallyMouseTimerData;
  978.  
  979.     //  Decide what to do by type.
  980.     if(pData->m_pType == MouseTimerData::m_ContextNotify)   {
  981.         //  If the left button is down, we need to set up a timer to
  982.         //      call the mouse move function again so that scrolling selections
  983.         //      work correctly.
  984.         //  GARRETT:  PANECX will want the mouse stuff.
  985.         if(XP_IsContextInList(pData->m_pContext) &&
  986.             ABSTRACTCX(pData->m_pContext) &&
  987.             ABSTRACTCX(pData->m_pContext)->IsFrameContext())   {
  988.             CWinCX *pWinCX = WINCX(pData->m_pContext);
  989.  
  990.             //  Don't do autoscroll if left button isn't down and isn't
  991.             //      already an timout registered.
  992.             if(pWinCX->m_bLBDown && !pWinCX->m_bScrollingTimerSet)   {
  993.                 //  Set up the timer.
  994.                 MouseTimerData *pLater = new MouseTimerData(pData->m_pContext);
  995.                 if(pLater)  {
  996.                     //  Manually set to be a timer notification.
  997.                     pLater->m_pType = MouseTimerData::m_TimerNotify;
  998.  
  999.                     //  Set that the context has a scrolling timeout event.
  1000.                     pWinCX->m_bScrollingTimerSet = TRUE;
  1001.  
  1002.                     //  Set the timer to call us back in X number milliseconds.
  1003.                     FE_SetTimeout(FEU_MouseTimer, (void *)pLater, 100);
  1004.                 }
  1005.             }
  1006.         }
  1007.  
  1008.         //  Do not delete the passed in data.
  1009.         //  Up to the caller to do so.
  1010.     }
  1011.     else if(pData->m_pType == MouseTimerData::m_TimerNotify)    {
  1012.         //  If the left button is still down, we need to act like a mouse
  1013.         //      move occurred on the context so scrolling selections work.
  1014.         if(XP_IsContextInList(pData->m_pContext) &&
  1015.             ABSTRACTCX(pData->m_pContext) &&
  1016.             ABSTRACTCX(pData->m_pContext)->IsFrameContext())   {
  1017.             CWinCX *pWinCX = WINCX(pData->m_pContext);
  1018.             //  We need to remove the previously allocated mouse data that
  1019.             //      we allocated ourselves.
  1020.             delete pData;
  1021.  
  1022.             if(pWinCX->m_bLBDown && pWinCX->m_bScrollingTimerSet)   {
  1023.                 //  Clear the scrolling timer flag (do before call or won't
  1024.                 //      set another timeout).
  1025.                 pWinCX->m_bScrollingTimerSet = FALSE;
  1026.  
  1027.                 //  This will set up another timer if needed.
  1028.                 BOOL bReturnImmediately = FALSE;
  1029.                 pWinCX->OnMouseMoveCX(pWinCX->m_uMouseFlags, pWinCX->m_cpMMove, bReturnImmediately);
  1030.                 if(bReturnImmediately)  {
  1031.                     return;
  1032.                 }
  1033.             }
  1034.  
  1035.         }
  1036.  
  1037.     }
  1038. }
  1039.  
  1040. ///  Mouse timer handler (to handle moves outside the window.).
  1041. MouseMoveTimerData::MouseMoveTimerData(MWContext *pContext)
  1042. {
  1043.     //  By default treat as a context notification.
  1044.     m_pContext = pContext;
  1045. }
  1046.  
  1047. void FEU_MouseMoveTimer(void *vpReallyMouseMoveTimerData)
  1048. {
  1049.     //  Cast.
  1050.     MouseMoveTimerData *pData = (MouseMoveTimerData *)vpReallyMouseMoveTimerData;
  1051.     if (!pData)
  1052.     return;
  1053.  
  1054.     if(XP_IsContextInList(pData->m_pContext) &&
  1055.     ABSTRACTCX(pData->m_pContext) &&
  1056.     ABSTRACTCX(pData->m_pContext)->IsFrameContext())   {
  1057.     CWinCX *pWinCX = WINCX(pData->m_pContext);
  1058.  
  1059.     if(!pWinCX->m_bMouseMoveTimerSet)   {
  1060.             //  Set up the timer.
  1061.             MouseMoveTimerData *pLater = new MouseMoveTimerData(pData->m_pContext);
  1062.             if(pLater)  {
  1063.                 //  Set that the context has a mousemove timeout event.
  1064.                 pWinCX->m_bMouseMoveTimerSet = TRUE;
  1065.  
  1066.                 //  Set the timer to call us back in X number milliseconds.
  1067.                 FE_SetTimeout(FEU_MouseMoveTimer, (void *)pLater, 200);
  1068.             }
  1069.         }
  1070.  
  1071.     else {
  1072.         POINT mp;
  1073.         // get mouse position
  1074.         ::GetCursorPos(&mp);
  1075.  
  1076.         if ((::WindowFromPoint(mp) != pWinCX->GetPane()) && !pWinCX->m_bLBDown) {
  1077.         // We've moved outside the window.  Stop looping the timer and 
  1078.         // send a simulated mousemove to the view.
  1079.         delete pData;
  1080.  
  1081.         ::ScreenToClient(pWinCX->GetPane(), &mp);
  1082.  
  1083.                 BOOL bReturnImmediately = FALSE;
  1084.                 pWinCX->OnMouseMoveCX(pWinCX->m_uMouseFlags, mp, bReturnImmediately);
  1085.  
  1086.         pWinCX->m_bMouseMoveTimerSet = FALSE;
  1087.             }
  1088.         else {
  1089.         // We're still in the window.  Set another timer.
  1090.         FE_SetTimeout(FEU_MouseMoveTimer, (void *)pData, 200);
  1091.         }
  1092.         }
  1093.     }
  1094. }
  1095.  
  1096. //  Context wants to have idle processing check to see if any actions
  1097. //      need be taken with it.
  1098. class MWContextList {
  1099. public:
  1100.     MWContext *m_pContext;
  1101.     MWContextList *m_pNext;
  1102. };
  1103. MWContextList *listIdleContexts = NULL;
  1104. void *timerIdleContexts = NULL;
  1105. #define IDLETIMEOUT 50
  1106.  
  1107. void idleTimer(void *pNULL)
  1108. {
  1109.     timerIdleContexts = NULL;
  1110.     if(FEU_DoIdleProcessing())  {
  1111.         timerIdleContexts = FE_SetTimeout(idleTimer, NULL, IDLETIMEOUT);
  1112.     }
  1113. }
  1114.  
  1115. void FEU_RequestIdleProcessing(MWContext *pContext)
  1116. {
  1117.     //  Make sure not already in list.
  1118.     MWContextList *pTraverse = listIdleContexts;
  1119.     while(pTraverse)    {
  1120.         if(pTraverse->m_pContext == pContext)   {
  1121.             //  Already here, don't do it.
  1122.             return;
  1123.         }
  1124.         pTraverse = pTraverse->m_pNext;
  1125.     }
  1126.  
  1127.     //  Not in list, add to tail.
  1128.     MWContextList *pNewEntry = new MWContextList();
  1129.     if(pNewEntry)   {
  1130.         MWContextList **ppNext = &listIdleContexts;
  1131.         while(*ppNext)  {
  1132.             ppNext = &((*ppNext)->m_pNext);
  1133.         }
  1134.  
  1135.         pNewEntry->m_pNext = NULL;
  1136.         pNewEntry->m_pContext = pContext;
  1137.         *ppNext = pNewEntry;        
  1138.     }
  1139.  
  1140.     //  If we don't have a timer, then start one up.
  1141.     if(timerIdleContexts == NULL)   {
  1142.         timerIdleContexts = FE_SetTimeout(idleTimer, NULL, IDLETIMEOUT);
  1143.     }
  1144. }
  1145.  
  1146. BOOL FEU_DoIdleProcessing()
  1147. {
  1148.     //  Check our list and do one action per context at a time.
  1149.     //  Remove the context from the list if no known action need be
  1150.     //      taken with it.
  1151.     MWContextList *pEntry = listIdleContexts;
  1152.     if(pEntry)  {
  1153.         //  Do NOT use else ifs.  Instead use "if(bNoAction &&" everywhere
  1154.         //  Must set bNoAction to FALSE after an action is taken.
  1155.         BOOL bNoAction = TRUE;
  1156.  
  1157.         //  Context still valid?
  1158.         //  Could have been blown away since it registered.
  1159.         if(bNoAction && XP_IsContextInList(pEntry->m_pContext))  {
  1160.             //  Front end or XP context (XP not handled).
  1161.             //  Do not check the destroyed flag here, or contexts never
  1162.             //      get really freed off, instead tighten the called code.
  1163.             if(bNoAction && ABSTRACTCX(pEntry->m_pContext))  {
  1164.                 CAbstractCX *pCX = ABSTRACTCX(pEntry->m_pContext);
  1165.  
  1166.                 //  Lastly is the don't care case, abstract only.
  1167.                 if(bNoAction)   {
  1168.                     //    Do an interrupt if needed.
  1169.                     if(bNoAction && pCX->m_bIdleInterrupt == TRUE)    {
  1170.                         bNoAction = FALSE;
  1171.                         pCX->Interrupt();                        
  1172.                     }
  1173.                     //  Check for nice reloading.
  1174.                     if(bNoAction && pCX->GetContext()->reSize)  {
  1175.                         bNoAction = FALSE;
  1176.                         pCX->NiceReload();
  1177.                     }
  1178.                     //  Check for self destruct.
  1179.                     if(bNoAction && pCX->m_bIdleDestroy == TRUE) {
  1180.                         bNoAction = FALSE;
  1181.                         pCX->NiceDestroyContext();
  1182.                     }
  1183.                 }
  1184.             }
  1185.         }
  1186.  
  1187.         // Take it out of the list and free it since it's now idle.
  1188.         if(bNoAction)   {
  1189.             //  Removal from list.
  1190.             listIdleContexts = pEntry->m_pNext;
  1191.             //  Removal from the universe.
  1192.             delete pEntry;
  1193.         }
  1194.     }
  1195.  
  1196.     //  Return wether or not more entries exist (more time is needed).
  1197.     return(listIdleContexts == NULL ? FALSE : TRUE);
  1198. }
  1199.  
  1200. //  Function to handle client pull.
  1201. class ClientPullTimerData   {
  1202. public:
  1203.     MWContext *m_pContext;
  1204.     URL_Struct *m_pUrl;
  1205.     History_entry *m_pVerifyHistory;
  1206.     int m_iFormatOut;
  1207.     BOOL m_bCanInterrupt;
  1208. };
  1209. void FEU_ClientPull(MWContext *pContext, uint32 ulMilliseconds, URL_Struct *pUrl, int iFormatOut, BOOL bCanInterrupt)
  1210. {
  1211.     BOOL bSetToPull = FALSE;
  1212.  
  1213.     //  Safety dance.
  1214.     if(pUrl && pContext &&
  1215.         ABSTRACTCX(pContext) &&
  1216.         !ABSTRACTCX(pContext)->IsDestroyed())    {
  1217.         CAbstractCX *pCX = ABSTRACTCX(pContext);
  1218.  
  1219.         //  If we've already got a client pull timeout for the context, we
  1220.         //      should clear it (only want one of these at any given time).
  1221.         void *pClearMe = pCX->m_pClientPullTimeout;
  1222.         if(pClearMe)  {
  1223.             pCX->m_pClientPullTimeout = NULL;
  1224.             FE_ClearTimeout(pClearMe);
  1225.         }
  1226.  
  1227.         //  Same for the timeout's argument pointer, but it can be non-null
  1228.         //      even when the timeout pointer was null (if FEU_ClientPullNow
  1229.         //      calls us directly to try again in a second, and then returns
  1230.         //      early without deleting pData or clearing m_pClientPullData).
  1231.         //  Instead of freeing it and then immediately allocating a new one,
  1232.         //      just reuse it, but take care further below to clear pCX's
  1233.         //      pointer to it before deleting it, if FE_SetTimeout fails.
  1234.         ClientPullTimerData *pData =
  1235.             (ClientPullTimerData *)pCX->m_pClientPullData;
  1236.         if(!pData)  {
  1237.             //  Create a new client pull structure.
  1238.             pData = new ClientPullTimerData();
  1239.         }
  1240.  
  1241.         if(pData)   {
  1242.             //  Fill in the timer data.
  1243.             pData->m_pContext = pCX->GetContext();
  1244.             pData->m_pUrl = pUrl;
  1245.             pData->m_pVerifyHistory = pCX->GetContext()->hist.cur_doc_ptr;
  1246.             pData->m_iFormatOut = iFormatOut;
  1247.             pData->m_bCanInterrupt = bCanInterrupt;
  1248.  
  1249.             //  Tell the context about it.
  1250.             //  Register the timeout.
  1251.             pCX->m_pClientPullTimeout =
  1252.                 FE_SetTimeout(FEU_ClientPullNow, (void *)pData, ulMilliseconds);
  1253.  
  1254.             //  Looks like this will work.
  1255.             if(pCX->m_pClientPullTimeout)   {
  1256.                 pCX->m_pClientPullData = (void *)pData;
  1257.                 bSetToPull = TRUE;
  1258.             }
  1259.             else    {
  1260.                 pCX->m_pClientPullData = NULL;
  1261.                 delete pData;
  1262.             }
  1263.         }
  1264.     }
  1265.     
  1266.     if(!bSetToPull && pUrl)   {
  1267.         //  Can't do client pull on this context.
  1268.         NET_FreeURLStruct(pUrl);
  1269.     }
  1270. }
  1271.  
  1272. void FEU_ClientPullNow(void *vpReallyClientPullTimerData)
  1273. {
  1274.     ClientPullTimerData *pData = (ClientPullTimerData *)vpReallyClientPullTimerData;
  1275.     BOOL bPulledUrl = FALSE;
  1276.  
  1277.     //  Is the context still around?
  1278.     if(XP_IsContextInList(pData->m_pContext) &&
  1279.         ABSTRACTCX(pData->m_pContext) &&
  1280.         !ABSTRACTCX(pData->m_pContext)->IsDestroyed())  {
  1281.         CAbstractCX *pCX = ABSTRACTCX(pData->m_pContext);
  1282.  
  1283.         //  There must not be more than one pull timeout pending!
  1284.         XP_ASSERT(pData == pCX->m_pClientPullData);
  1285.  
  1286.         //  We are called only via FE_SetTimeout, so clear this pointer now
  1287.         //      before it dangles at free memory.
  1288.         pCX->m_pClientPullTimeout = NULL;
  1289.  
  1290.         //  Are we on the same history entry?
  1291.         if(pCX->GetContext()->hist.cur_doc_ptr == pData->m_pVerifyHistory)   {
  1292.             
  1293.             //  Client pull isn't allowed to interrupt.
  1294.             if(!pData->m_bCanInterrupt && XP_IsContextBusy(pCX->GetContext()))   {
  1295.                 //  Try again in a second.
  1296.                 FEU_ClientPull(pCX->GetContext(), 1000, pData->m_pUrl, pData->m_iFormatOut, FALSE);
  1297.  
  1298.                 //  Old data, if present, freed in FEU_ClientPull.
  1299.                 //  We can not continue, as the old data may now be gone,
  1300.                 //      and we look at the old timer pull data further below.
  1301.                 return;
  1302.             }
  1303.  
  1304.             //  Clear the members in the context before load,
  1305.             //      as they may be set again instantly and we
  1306.             //      get a double free below.
  1307.             pCX->m_pClientPullData = NULL;
  1308.  
  1309.             //  Ask for it now.
  1310.             pCX->GetUrl(pData->m_pUrl, pData->m_iFormatOut);
  1311.  
  1312.             //  Set that we've requested it.
  1313.             bPulledUrl = TRUE;
  1314.         }
  1315.         else    {
  1316.             //  Clear m_pClientPullData because we're about to free pData.
  1317.             pCX->m_pClientPullData = NULL;
  1318.         }
  1319.     }
  1320.  
  1321.     if(!bPulledUrl)    {
  1322.         //  Free off the URL struct ourselves.
  1323.         NET_FreeURLStruct(pData->m_pUrl);
  1324.     }
  1325.  
  1326.     //  Free off the timer data.
  1327.     delete pData;
  1328. }
  1329.  
  1330. //  Cause the global history to be saved periodically.
  1331. void FEU_GlobalHistoryTimeout(void *pNULL)
  1332. {
  1333.     //  Set the next timeout.
  1334.     FE_SetTimeout(FEU_GlobalHistoryTimeout, NULL, 120000UL);
  1335.  
  1336.     //  Flush it, if not first call.
  1337.     if(!pNULL)   {
  1338.         GH_SaveGlobalHistory();
  1339.     }
  1340. }
  1341.  
  1342. // This routine will return the handle of the pop-up menu whose first
  1343. // menu item has the specified command ID
  1344. HMENU FEU_FindSubmenu(HMENU hMenu, UINT nFirstCmdID)
  1345. {
  1346.     int nCount = ::GetMenuItemCount(hMenu);
  1347.  
  1348.     for (int i = 0; i < nCount; i++) {
  1349.         HMENU hSubmenu = ::GetSubMenu(hMenu, i);
  1350.  
  1351.         if (hSubmenu && (::GetMenuItemID(hSubmenu, 0) == nFirstCmdID))
  1352.             return hSubmenu;
  1353.     }
  1354.  
  1355.     return NULL;
  1356. }
  1357.  
  1358. char *pTipText = NULL;
  1359.  
  1360. // Get a resource string and extract the tooltip portion
  1361. //   if a '\n' is found in the string
  1362. //   USE RESULT QUICKLY! 
  1363. //   (String is in our temp buffer and should not be FREEd)
  1364. char * FEU_GetToolTipText( UINT nID )
  1365. {
  1366.     pTipText = szLoadString(nID);
  1367.     if( ! *pTipText ){
  1368.         return NULL;
  1369.     }
  1370.  
  1371.     // Scan for the '\n' separating status line hints from
  1372.     //   the tooltip text - use latter if found
  1373.     char *pTemp = pTipText;
  1374.     do {
  1375.         if( *pTemp == '\n' && *(pTemp+1) != '\0' ){
  1376.             pTipText = pTemp+1;
  1377.             // Find a second "\n" and terminate string there
  1378.             char * pBreak = strchr(pTipText, '\n');
  1379.             if( pBreak )
  1380.                 *pBreak = '\0';
  1381.             break;
  1382.         }
  1383.         pTemp++;
  1384.     } while( *pTemp != '\0' );
  1385.  
  1386.     return pTipText;
  1387. }
  1388.  
  1389.  
  1390. char *FE_FindFileExt(char * path)
  1391. {
  1392.     char *pRetval = NULL;
  1393.     if(path) {
  1394.         int len = strlen(path);
  1395.  
  1396.         char *ptr = path + len - 1;
  1397.         while ((*ptr != '.') && (len > 0)) {
  1398.             len--;
  1399.             if (len > 0) ptr--;
  1400.         }
  1401.         if (len > 0) {
  1402.             pRetval = ptr;
  1403.         }
  1404.     }
  1405.     return(pRetval);
  1406. }
  1407.  
  1408. void FE_LongNameToDosName(char* dest, char* source)
  1409. {
  1410.     ASSERT(dest && source);
  1411.     if(dest) {
  1412.         *dest = '\0';
  1413.         if(source) {
  1414.             char *ext = FE_FindFileExt(source);
  1415.  
  1416.             if (ext && (ext - source) > 8) {
  1417.                 // the Name is > dos file name
  1418.                 strncpy(dest, source, 8);
  1419.                 strncpy(&dest[8],ext, 4);
  1420.                 dest[12] = '\0';
  1421.             }
  1422.             else {
  1423.                 strcpy(dest, source);
  1424.             }
  1425.         }
  1426.     }
  1427. }
  1428. // This function will return FALSE, if we do not want to use the default type that libnet provide.
  1429.  
  1430. BOOL  FE_FileType(char * path, 
  1431.                     char * mimeType, 
  1432.                     char * encoding)
  1433. {
  1434.  
  1435.     // try to get the extension from the end of the string.
  1436.     char *ext = FE_FindFileExt(path);
  1437.     if (ext) {
  1438.         ext++; // move pass the '.';
  1439.  
  1440.         NET_cdataStruct *cdata;
  1441.         XP_List * list_ptr;
  1442.  
  1443.         list_ptr = cinfo_MasterListPointer();
  1444.         while((cdata = (NET_cdataStruct *) XP_ListNextObject(list_ptr)) != NULL)
  1445.         {
  1446.             if(cdata->ci.type && !strcasecomp(mimeType, cdata->ci.type)){
  1447.                 for (int i = 0; i <  cdata->num_exts; i++) {
  1448.                     if (strcasecomp(ext, cdata->exts[i]) == 0)
  1449.                         return TRUE;
  1450.                 }
  1451.             }
  1452.         }
  1453.  
  1454.     }
  1455.     return FALSE;
  1456. }
  1457.  
  1458. BOOL FEU_IsConferenceAvailable(void)
  1459. {
  1460.     CString install;
  1461.  
  1462. #ifdef WIN32
  1463.     install = FEU_GetInstallationDirectory(szLoadString(IDS_CONFERENCE_REGISTRY), szLoadString(IDS_PATHNAME));
  1464. #else ifdef XP_WIN16
  1465.     install = FEU_GetInstallationDirectory(szLoadString(IDS_CONFERENCE),szLoadString(IDS_INSTALL_DIRECTORY));
  1466. #endif
  1467.  
  1468.     return (!install.IsEmpty());
  1469. }
  1470.  
  1471. BOOL FEU_IsCalendarAvailable(void)
  1472. {
  1473.  
  1474. #ifdef _WIN32
  1475.     CString calRegistry;
  1476.  
  1477.     calRegistry.LoadString(IDS_CALENDAR_REGISTRY);
  1478.  
  1479.     calRegistry = FEU_GetCurrentRegistry(calRegistry);
  1480.     if(calRegistry.IsEmpty())
  1481.         return FALSE;
  1482.     CString install = FEU_GetInstallationDirectory(calRegistry, szLoadString(IDS_INSTALL_DIRECTORY));
  1483. #else
  1484.     
  1485.     CString install = FEU_GetInstallationDirectory(szLoadString(IDS_CALENDAR), szLoadString(IDS_INSTALL_DIRECTORY));
  1486.  
  1487. #endif
  1488.  
  1489.     return (!install.IsEmpty());
  1490.  
  1491.  
  1492. }
  1493.  
  1494. BOOL FEU_IsIBMHostOnDemandAvailable(void)
  1495. {
  1496.  
  1497.  
  1498. #ifdef _WIN32
  1499.     CString ibmHostRegistry;
  1500.  
  1501.     ibmHostRegistry.LoadString(IDS_3270_REGISTRY);
  1502.  
  1503.     ibmHostRegistry = FEU_GetCurrentRegistry(ibmHostRegistry);
  1504.     if(ibmHostRegistry.IsEmpty())
  1505.         return FALSE;
  1506.  
  1507.     CString install = FEU_GetInstallationDirectory(ibmHostRegistry, szLoadString(IDS_INSTALL_DIRECTORY));
  1508. #else 
  1509.     
  1510.     CString install = FEU_GetInstallationDirectory(szLoadString(IDS_3270), szLoadString(IDS_INSTALL_DIRECTORY));
  1511.     
  1512. #endif
  1513.  
  1514.     return (!install.IsEmpty());
  1515.  
  1516. }
  1517.  
  1518. BOOL FEU_IsAimAvailable(void)
  1519. {
  1520.     BOOL success = FALSE;
  1521.     char szPath[_MAX_PATH + 1];
  1522.     char shortPath[_MAX_PATH + 1];
  1523.  
  1524.     CString install("");
  1525.     unsigned long cbData = sizeof(szPath);
  1526.  
  1527. #ifdef _WIN32
  1528.     CString aimRegistry;
  1529.  
  1530.     aimRegistry.LoadString(IDS_AIM_REGISTRY);
  1531.  
  1532.     HKEY aimKey;
  1533.  
  1534.     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, aimRegistry, 0, KEY_QUERY_VALUE, &aimKey) != ERROR_SUCCESS)
  1535.       return FALSE;
  1536.  
  1537.     success = (RegQueryValueEx(aimKey, 0, NULL, NULL, (LPBYTE) szPath, &cbData) == ERROR_SUCCESS);
  1538.  
  1539.     GetShortPathName(szPath, shortPath, _MAX_PATH+1);
  1540.     install = shortPath;
  1541.  
  1542.     RegCloseKey(aimKey);
  1543. #endif // _WIN32
  1544.  
  1545. #ifdef XP_WIN16
  1546.     // Do the right thing
  1547.     GetPrivateProfileString("InstallRoot", "Path", "none", szPath, cbData, "aim.ini");
  1548.     install = szPath;
  1549.     if (install != "none")
  1550.     {
  1551.         success = TRUE;
  1552.         install = install + "\\aim.exe";
  1553.     }
  1554. #endif // XP_WIN16
  1555.  
  1556.     if (success)
  1557.     {
  1558.         char    szKey[_MAX_EXT + 1];  // space for '.'
  1559.         char    szClass[128];
  1560.         LONG    lResult;
  1561.         LONG    lcb;
  1562.  
  1563.         // Look up the file association key which maps a file extension
  1564.         // to a file class
  1565.         wsprintf(szKey, ".%s", "aim");
  1566.  
  1567.         lcb = sizeof(szClass);
  1568.         lResult = RegQueryValue(HKEY_CLASSES_ROOT, szKey, szClass, &lcb);
  1569.     
  1570. #ifdef _WIN32
  1571.         ASSERT(lResult != ERROR_MORE_DATA);
  1572. #endif
  1573.         if (lResult != ERROR_SUCCESS || lcb <= 1)
  1574.         {
  1575.             // Configure the MIME type, download prompt, etc. etc.
  1576.             NET_cdataStruct *launchData = fe_NewFileType("AOL Instant Messenger Launch",
  1577.                         "aim",
  1578.                         "application/x-aim",
  1579.                         install);  // Create and register the file type
  1580.             CHelperApp *pHelperApp = (CHelperApp *)launchData->ci.fe_data;
  1581.             pHelperApp->how_handle = HANDLE_SHELLEXECUTE;
  1582.         }
  1583.         else 
  1584.         {
  1585.             // The key exists but the application may be stale, i.e., it may have changed
  1586.             // on us.  Just write out the current path to the aimfile key.
  1587.             SetShellOpenCommand("aimfile", install);
  1588.         }
  1589.  
  1590. // Always write out the defaulticon info for Win32, since the AIM app may have moved.
  1591. #ifdef _WIN32
  1592.         CString iconPath = install + ",0";
  1593.         HKEY iconKey;
  1594.         if (RegCreateKey(HKEY_CLASSES_ROOT, "aimfile\\DefaultIcon", &iconKey) ==
  1595.                     ERROR_SUCCESS)
  1596.         {
  1597.             RegSetValue(iconKey, "", REG_SZ, iconPath, iconPath.GetLength());
  1598.             RegCloseKey(iconKey);
  1599.         }
  1600. #endif // _WIN32
  1601.  
  1602.         CString profileLaunch = theApp.m_UserDirectory + "\\launch.aim";
  1603.         FILE* fp = fopen(profileLaunch, "r");
  1604.         if (fp == NULL)
  1605.         {
  1606.             // Need to create launch.aim file in the user's dir.
  1607.             fp = fopen(profileLaunch, "w");
  1608.             fprintf(fp, "DWH\n");
  1609.             fclose(fp);
  1610.  
  1611.             // Need to add to personal toolbar
  1612.             CString convLaunch;
  1613.             WFE_ConvertFile2Url(convLaunch, profileLaunch);
  1614.             CString aimName;
  1615.             aimName.LoadString(ID_WINDOW_AIM);
  1616.             
  1617.  
  1618. /* MUST CONVERT AIM BOOKMARK CREATION TO AURORA (Dave H.)
  1619.             BM_Entry* newBookmark = BM_NewUrl(aimName, convLaunch, NULL, NULL);
  1620.             
  1621.             theApp.GetLinkToolbarManager().InitializeToolbarHeader();
  1622.             BM_Entry* pRoot = theApp.GetLinkToolbarManager().GetToolbarHeader();
  1623.  
  1624.  
  1625.             if (pRoot != NULL)
  1626.                 BM_PrependChildToHeader(theApp.m_pBmContext, pRoot, newBookmark);
  1627. */
  1628.         }
  1629.         else fclose(fp);
  1630.     }
  1631.  
  1632.     return success;
  1633. }
  1634.  
  1635. void FEU_OpenAim(void)
  1636. {
  1637.     char szPath[_MAX_PATH + 1];
  1638.     char shortPath[_MAX_PATH + 1];
  1639.  
  1640.     CString install("none");
  1641.     unsigned long cbData = sizeof(szPath);
  1642.  
  1643. #ifdef _WIN32
  1644.     CString aimRegistry;
  1645.     aimRegistry.LoadString(IDS_AIM_REGISTRY);
  1646.  
  1647.     HKEY aimKey;
  1648.  
  1649.     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, aimRegistry, 0, KEY_QUERY_VALUE, &aimKey) != ERROR_SUCCESS)
  1650.       return;
  1651.  
  1652.     if (RegQueryValueEx(aimKey, 0, NULL, NULL, (LPBYTE) szPath, &cbData) == ERROR_SUCCESS) 
  1653.     {
  1654.         RegCloseKey(aimKey);
  1655. #ifdef _WIN32
  1656.             GetShortPathName(szPath, shortPath, _MAX_PATH+1);
  1657.             install = shortPath;
  1658. #else
  1659.             install = szPath;
  1660. #endif
  1661.     }
  1662.     else return;
  1663.  
  1664. #endif // _WIN32
  1665.  
  1666. #ifdef XP_WIN16
  1667.     // Do the right thing
  1668.     GetPrivateProfileString("InstallRoot", "Path", "none", szPath, cbData, "aim.ini");
  1669.     install = szPath;
  1670.     if (install == "none")
  1671.        return;
  1672.     install = install + "\\aim.exe";
  1673. #endif // XP_WIN16
  1674.  
  1675.     WinExec(install, SW_SHOW);    
  1676. }
  1677.  
  1678. void FEU_OpenNetcaster(void)
  1679. {
  1680. #ifdef JAVA        
  1681.  
  1682.      if(FEU_IsNetcasterAvailable() == FALSE) {
  1683.         MessageBox(NULL, XP_GetString(XP_ALERT_CANT_RUN_NETCASTER), szLoadString(AFX_IDS_APP_TITLE), MB_OK | MB_ICONEXCLAMATION); 
  1684.          return;
  1685.     }
  1686.  
  1687.     if(!theApp.m_pNetcasterWindow) { 
  1688.          Chrome          netcasterChrome;
  1689.          URL_Struct*     URL_s, *splashURL_s;
  1690.          MWContext       *netcasterContext;
  1691.         REGERR            regErr = REGERR_FAIL;
  1692.         char            netcasterURL[300] = "";
  1693.         char            netcasterSplashURL[300] = "";
  1694.  
  1695.         // First, get the URL 
  1696.  
  1697.     /* Due to a bug using the Windows Registry to detect Netcaster
  1698.        installation with both Ratbert and Dogbert installed, we
  1699.        need check the XP registry first. If success, use that.  If
  1700.        failure (due to a bug), use Windows.  If both are installed
  1701.        to unique locations and then one of them deleted, Windows
  1702.        will return false, but the XP code should save our butts in
  1703.        95% of the cases by returning true.
  1704.  
  1705.        BTW, this code needs to be componentized more.  Since today
  1706.        is code freeze, I cut and posted code below to preserve existing
  1707.        code paths.  This code should be better organized for 4.03.
  1708.     */
  1709.  
  1710. #ifdef XP_WIN32
  1711.         
  1712.         regErr = VR_GetPath("Netcaster/tab.htm", 300, netcasterURL);
  1713.         VR_Close();
  1714.  
  1715.         if (regErr != REGERR_OK) {
  1716.  
  1717.             CString netcaster = "Software\\Netscape\\Netcaster\\";
  1718.  
  1719.             netcaster = FEU_GetCurrentRegistry(netcaster);
  1720.             if(netcaster.IsEmpty()) {
  1721.                 regErr = 3 ;
  1722.             } else {
  1723.  
  1724.                 CString install = FEU_GetInstallationDirectory(netcaster, szLoadString(IDS_INSTALL_DIRECTORY));
  1725.  
  1726.                 if(install.IsEmpty()) {
  1727.                     regErr = 3 ;
  1728.                 } else {
  1729.  
  1730.                     
  1731.                     strcpy(netcasterURL,install.GetBuffer(300));
  1732.  
  1733.                     XP_STRCAT(netcasterURL, "\\tab.htm") ;
  1734.  
  1735.                     strcpy(netcasterSplashURL,install.GetBuffer(300));
  1736.                     XP_STRCAT(netcasterSplashURL, "\\ncsplash.htm") ;
  1737.  
  1738.                     regErr = REGERR_OK ;
  1739.                 }
  1740.  
  1741.             }
  1742.         } else {
  1743.  
  1744.             REGERR            splashErr;
  1745.     
  1746.             splashErr = VR_GetPath("Netcaster/ncsplash.htm", 300, netcasterSplashURL);
  1747.             VR_Close();
  1748.  
  1749.             if (splashErr != REGERR_OK) {
  1750.  
  1751.                 CString netcaster = "Software\\Netscape\\Netcaster\\";
  1752.  
  1753.                 netcaster = FEU_GetCurrentRegistry(netcaster);
  1754.                 if(!netcaster.IsEmpty()) {
  1755.  
  1756.                     CString install = FEU_GetInstallationDirectory(netcaster, szLoadString(IDS_INSTALL_DIRECTORY));
  1757.  
  1758.                     if(!install.IsEmpty()) {
  1759.                         
  1760.                         strcpy(netcasterSplashURL,install.GetBuffer(300));
  1761.                         XP_STRCAT(netcasterSplashURL, "\\ncsplash.htm") ;
  1762.  
  1763.                     }
  1764.  
  1765.                 }
  1766.  
  1767.  
  1768.             }
  1769.  
  1770.         }
  1771. #else
  1772.         regErr = VR_GetPath("Netcaster/tab.htm", 300, netcasterURL);
  1773.         VR_Close();
  1774.  
  1775. #endif
  1776.         
  1777.  
  1778.         if (regErr == REGERR_OK) {
  1779.  
  1780.             // Now check to see if Java and JS are enabled
  1781.             if (!LM_GetMochaEnabled() || !LJ_GetJavaEnabled()) {
  1782.                 MessageBox(NULL, XP_GetString(XP_ALERT_NETCASTER_NO_JS), szLoadString(AFX_IDS_APP_TITLE), MB_OK | MB_ICONEXCLAMATION); 
  1783.                 return;
  1784.             }
  1785.  
  1786.             // First, bring up the splash screen, if it exists
  1787. #ifdef XP_WIN32
  1788.  
  1789.             if (XP_STRLEN(netcasterSplashURL) > 0) {
  1790.  
  1791.                 MWContext        *newContext;
  1792.  
  1793.                 memset(&netcasterChrome, 0, sizeof(Chrome));
  1794.                  netcasterChrome.type = MWContextBrowser;
  1795.                  netcasterChrome.w_hint = 400;
  1796.                  netcasterChrome.h_hint = 150;
  1797.                  netcasterChrome.l_hint = 100;
  1798.                  netcasterChrome.t_hint = 100;
  1799.                  netcasterChrome.topmost = FALSE;
  1800.                  netcasterChrome.z_lock = FALSE;
  1801.                  netcasterChrome.location_is_chrome = TRUE;
  1802.                  netcasterChrome.disable_commands = TRUE;
  1803.                  netcasterChrome.hide_title_bar = FALSE;
  1804.                  netcasterChrome.restricted_target = TRUE;
  1805.                  netcasterChrome.allow_close = TRUE;
  1806.                 netcasterChrome.show_bottom_status_bar = FALSE;
  1807.  
  1808.                 splashURL_s = NET_CreateURLStruct(netcasterSplashURL, NET_DONT_RELOAD);
  1809.  
  1810.                 newContext = FE_MakeNewWindow(NULL, 
  1811.                                  splashURL_s, 
  1812.                                   "Netcaster_Splash", 
  1813.                                   &netcasterChrome);
  1814.  
  1815.             }
  1816. #endif
  1817.  
  1818.              memset(&netcasterChrome, 0, sizeof(Chrome));
  1819.  
  1820.              netcasterChrome.w_hint = 22;
  1821.              netcasterChrome.h_hint = 55;
  1822.              netcasterChrome.l_hint = -300;
  1823.              netcasterChrome.t_hint = 0;
  1824.              netcasterChrome.topmost = TRUE;
  1825.              netcasterChrome.z_lock = TRUE;
  1826.              netcasterChrome.location_is_chrome = TRUE;
  1827.              netcasterChrome.disable_commands = TRUE;
  1828.              netcasterChrome.hide_title_bar = TRUE;
  1829.              netcasterChrome.restricted_target = TRUE;
  1830.              netcasterChrome.allow_close = TRUE;
  1831.  
  1832.             URL_s = NET_CreateURLStruct(netcasterURL, NET_DONT_RELOAD);
  1833.  
  1834.             netcasterContext = FE_MakeNewWindow(NULL, 
  1835.                                                  URL_s, 
  1836.                                                   "Netcaster_SelectorTab", 
  1837.                                                   &netcasterChrome);
  1838.  
  1839.             theApp.m_pNetcasterWindow = netcasterContext ;
  1840.  
  1841.  
  1842.         } else {
  1843.             MessageBox(NULL, XP_GetString(XP_ALERT_CANT_RUN_NETCASTER), szLoadString(AFX_IDS_APP_TITLE), MB_OK | MB_ICONEXCLAMATION); 
  1844.         } 
  1845.     } else {
  1846.  
  1847.         if(! ABSTRACTCX(theApp.m_pNetcasterWindow) || ! ABSTRACTCX(theApp.m_pNetcasterWindow)->IsFrameContext() ) {
  1848.             MessageBox(NULL, XP_GetString(XP_ALERT_CANT_RUN_NETCASTER), szLoadString(AFX_IDS_APP_TITLE), MB_OK | MB_ICONEXCLAMATION); 
  1849.             return;
  1850.         } else {
  1851.             // We are running, so give us focus...
  1852.             //theApp.m_pNetcasterWindow->fe.cx->SetFocus() ;
  1853.  
  1854.             if((theApp.m_pNetcasterWindow->fe.cx->IsFrameContext() == TRUE))  {
  1855.                 CWinCX *pWinCX = VOID2CX(theApp.m_pNetcasterWindow->fe.cx, CWinCX);
  1856.  
  1857.                 if (!pWinCX)
  1858.                     return ;
  1859.  
  1860.                 HWND hwnd = pWinCX->GetPane() ;
  1861.  
  1862.                 if (IsWindow(hwnd))
  1863.                     SetFocus(hwnd) ;
  1864.  
  1865.  
  1866.             }
  1867.  
  1868.         }
  1869.  
  1870.     }
  1871. #endif /* JAVA */        
  1872. }
  1873.  
  1874. BOOL FEU_IsNetcasterAvailable(void)
  1875. {
  1876. #ifdef JAVA 
  1877.  
  1878. #ifdef XP_WIN32
  1879.  
  1880.     /* Due to a bug using the Windows Registry to detect Netcaster
  1881.        installation with both Ratbert and Dogbert installed, we
  1882.        need check the XP registry first. If success, use that.  If
  1883.        failure (due to a bug), use Windows.  If both are installed
  1884.        to unique locations and then one of them was deleted, Windows
  1885.        will return false, but the XP code should save our butts in
  1886.        95% of the cases by returning true.
  1887.     */
  1888.  
  1889.     CString netcaster = "Software\\Netscape\\Netcaster\\";
  1890.  
  1891.     if (VR_InRegistry("Netcaster") == REGERR_OK) {
  1892.         
  1893.         // The registry may be invalid since the user can delete
  1894.         // the files.  Check to see if one of the files exists.        
  1895.         // I believe this checks file existence too....
  1896.         int rc = VR_ValidateComponent("Netcaster/tab.htm") ;
  1897.         
  1898.         if (rc == REGERR_OK) {
  1899.             VR_Close();
  1900.             return (TRUE) ;
  1901.         }
  1902.     } 
  1903.  
  1904.     VR_Close();
  1905.  
  1906.     /*
  1907.         begin Windows code check
  1908.     */
  1909.  
  1910.     netcaster = FEU_GetCurrentRegistry(netcaster);
  1911.  
  1912.     if(netcaster.IsEmpty())
  1913.         return FALSE;
  1914.     CString install = FEU_GetInstallationDirectory(netcaster, szLoadString(IDS_INSTALL_DIRECTORY));
  1915.  
  1916.     if (!install.IsEmpty()) {
  1917.  
  1918.         // stat the directory first
  1919.        struct _stat buf;
  1920.        int result;
  1921.  
  1922.        /* Get data associated with "stat.c": */
  1923.        result = _stat( install.GetBuffer(256), &buf );
  1924.  
  1925.        /* Check if statistics are valid: */
  1926.        if( result != 0 )
  1927.            return FALSE;
  1928.  
  1929.         return (TRUE);
  1930.     }
  1931. #endif
  1932. #endif /* JAVA */
  1933.     return (FALSE);
  1934.  
  1935. }
  1936.  
  1937.  
  1938. void  FE_ConvertSpace(char *newName)
  1939. {
  1940.     char *p;
  1941.  
  1942.     p = newName;
  1943.     if (strchr(p, '%')) {
  1944.         for(p = newName; *p; p++) {
  1945.             if ((*p == '%') && (*(p+1) == 0x32) && (*(p+2) == 0x30)) {
  1946.                 *p = ' ';
  1947.                 strcpy(p+1, p+3);
  1948.             }
  1949.         }
  1950.     }
  1951. }
  1952.  
  1953. #ifdef XP_WIN32
  1954. CString FEU_GetCurrentRegistry(const CString &componentString)
  1955. {
  1956.  
  1957.     HKEY hKey;
  1958.     LONG lResult;
  1959.     char szPath[_MAX_PATH + 1];
  1960.  
  1961.     CString currentVersion, main, currentRegString("");
  1962.     currentVersion.LoadString(IDS_CURRENTVERSION);
  1963.     main.LoadString(IDS_MAIN);
  1964.  
  1965.     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, componentString, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {
  1966.         unsigned long cbData = sizeof(szPath);
  1967.         lResult = RegQueryValueEx(hKey, currentVersion, NULL, NULL, (LPBYTE) szPath, &cbData);
  1968.  
  1969.         RegCloseKey(hKey);
  1970.         if(lResult == ERROR_SUCCESS)
  1971.         {
  1972.             currentRegString = componentString + szPath;
  1973.             currentRegString = currentRegString + main;
  1974.         }
  1975.     }
  1976.     return currentRegString;
  1977. }
  1978. #endif
  1979.  
  1980. CString FEU_GetInstallationDirectory(const CString &productString, const CString &installationString)
  1981. {      
  1982. #ifdef _WIN32
  1983.   
  1984.     
  1985.     HKEY hKey;
  1986.     LONG lResult;
  1987.     char szPath[_MAX_PATH + 1];
  1988.     CString install("");
  1989.  
  1990.     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, productString, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {
  1991.  
  1992.         unsigned long cbData = sizeof(szPath);
  1993.         lResult = RegQueryValueEx(hKey, installationString, NULL, NULL, (LPBYTE) szPath, &cbData);
  1994.  
  1995.         RegCloseKey(hKey);
  1996.         if(lResult == ERROR_SUCCESS)
  1997.             install = szPath;
  1998.     
  1999.     }
  2000.  
  2001.     return install;
  2002. #else ifdef XP_WIN16
  2003.     char szPath[_MAX_PATH + 1];
  2004.  
  2005.     const char *pOldProfile = theApp.m_pszProfileName;   
  2006.     
  2007.     UINT nSize = GetWindowsDirectory(szPath, _MAX_PATH + 1);
  2008.     XP_STRCPY(szPath + nSize, szLoadString(IDS_NSCPINI));
  2009.     theApp.m_pszProfileName = szPath;      
  2010.     
  2011.     CString version = theApp.GetProfileString(productString, szLoadString(IDS_CURRENTVERSION), NULL);
  2012.     if(version.IsEmpty())
  2013.     {    
  2014.         theApp.m_pszProfileName = pOldProfile; 
  2015.         return version;
  2016.     }
  2017.  
  2018.     CString currentVersion =  "-" + version; 
  2019.     currentVersion = productString + currentVersion;
  2020.     
  2021.     CString install = theApp.GetProfileString(currentVersion, installationString, NULL);
  2022.     
  2023.     theApp.m_pszProfileName = pOldProfile; 
  2024.         
  2025.     return install;
  2026. #endif 
  2027. }
  2028.  
  2029.  
  2030. //  Send/Post a message to all top level frames in our app.
  2031. void FEU_FrameBroadcast(BOOL bSend, UINT Msg, WPARAM wParam, LPARAM lParam)
  2032. {
  2033.     //  Go through list of frames.
  2034.     for(CGenericFrame *pFrame = theApp.m_pFrameList;
  2035.         pFrame != NULL;
  2036.         pFrame = pFrame->m_pNext) {
  2037.         if(pFrame->GetSafeHwnd()) {
  2038.             if(bSend)   {
  2039.                 pFrame->SendMessage(Msg, wParam, lParam);
  2040.             }
  2041.             else    {
  2042.                 pFrame->PostMessage(Msg, wParam, lParam);
  2043.             }
  2044.         }
  2045.     }
  2046.  
  2047.     //  Get the hidden one too.
  2048.     if(theApp.m_pMainWnd && theApp.m_pMainWnd->GetSafeHwnd())   {
  2049.         if(bSend)   {
  2050.             theApp.m_pMainWnd->SendMessage(Msg, wParam, lParam);
  2051.         }
  2052.         else    {
  2053.             theApp.m_pMainWnd->PostMessage(Msg, wParam, lParam);
  2054.         }
  2055.     }
  2056. }
  2057.  
  2058. void FEU_AltMail_ShowMailBox(void)
  2059. {
  2060.     if(theApp.m_bInitMapi) 
  2061.     {
  2062.         if(theApp.m_fnOpenMailSession) 
  2063.         {
  2064.             POSTCODE status = (*theApp.m_fnOpenMailSession) (NULL, NULL);
  2065.             if(status == POST_OK) 
  2066.                 theApp.m_bInitMapi = FALSE;
  2067.             else
  2068.                 return;
  2069.         }
  2070.     }
  2071.  
  2072.     if(theApp.m_fnShowMailBox)
  2073.         (*theApp.m_fnShowMailBox) ();
  2074. }
  2075.  
  2076. void FEU_AltMail_ShowMessageCenter(void)
  2077. {
  2078.     if(theApp.m_bInitMapi) 
  2079.     {
  2080.         if(theApp.m_fnOpenMailSession) 
  2081.         {
  2082.             POSTCODE status = (*theApp.m_fnOpenMailSession) (NULL, NULL);
  2083.             if(status == POST_OK) 
  2084.                 theApp.m_bInitMapi = FALSE;
  2085.             else
  2086.                 return;
  2087.         }
  2088.     }
  2089.  
  2090.     if(theApp.m_fnShowMessageCenter)
  2091.         (*theApp.m_fnShowMessageCenter) ();
  2092. }
  2093.  
  2094. //Modify communicators menu with alt mail specified menu
  2095. //Remove menu item if pszAltMailMenuStr is empty
  2096. void FEU_AltMail_ModifyMenu(CMenu* pMenuCommunicator, UINT uiCommunicatorMenuID, LPCSTR pszAltMailMenuStr)
  2097. {
  2098.     if(*pszAltMailMenuStr)
  2099.     {
  2100.         CString csNewMenuStr;
  2101.         #ifdef XP_WIN32
  2102.             if(pMenuCommunicator->GetMenuString(uiCommunicatorMenuID, csNewMenuStr, MF_BYCOMMAND))
  2103.         #else
  2104.             if(pMenuCommunicator->GetMenuString(uiCommunicatorMenuID, csNewMenuStr.GetBuffer(256), 256, MF_BYCOMMAND))
  2105.         #endif
  2106.         {
  2107.             #ifdef XP_WIN16
  2108.                 csNewMenuStr.ReleaseBuffer();
  2109.             #endif
  2110.  
  2111.             int iPos;
  2112.             if((iPos = csNewMenuStr.Find('\t')) != -1)
  2113.             {
  2114.                 //Accelerator present. Add it to the end of AltMail menu string
  2115.                 CString csAccel = csNewMenuStr.Right(csNewMenuStr.GetLength() - iPos);
  2116.                 csNewMenuStr = pszAltMailMenuStr + csAccel;
  2117.             }
  2118.             else //No accelerator. use alt mail str as is
  2119.                 csNewMenuStr = pszAltMailMenuStr;
  2120.  
  2121.             pMenuCommunicator->ModifyMenu(uiCommunicatorMenuID, MF_BYCOMMAND, uiCommunicatorMenuID, csNewMenuStr);
  2122.         }
  2123.     }
  2124.     else
  2125.         pMenuCommunicator->RemoveMenu(uiCommunicatorMenuID, MF_BYCOMMAND);
  2126. }
  2127.  
  2128. //Modify "Messenger MailBox" and "Message Center" menu items
  2129. //to strings supplied by the AltMail DLL
  2130. void FEU_AltMail_SetAltMailMenus(CMenu* pMenuCommunicator)
  2131. {
  2132.     char szAltMailMenuStr[_MAX_PATH];
  2133.  
  2134.     szAltMailMenuStr[0] = '\0';
  2135.     if(POST_OK == (*theApp.m_fnGetMenuItemString)(ALTMAIL_MenuMailBox, szAltMailMenuStr, _MAX_PATH))
  2136.         FEU_AltMail_ModifyMenu(pMenuCommunicator, ID_TOOLS_INBOX, szAltMailMenuStr);
  2137.  
  2138.     szAltMailMenuStr[0] = '\0';
  2139.     if(POST_OK == (*theApp.m_fnGetMenuItemString)(ALTMAIL_MenuMessageCenter, szAltMailMenuStr, _MAX_PATH))
  2140.         FEU_AltMail_ModifyMenu(pMenuCommunicator, ID_TOOLS_MAIL, szAltMailMenuStr);
  2141. }
  2142.  
  2143. BOOL FEU_Execute(MWContext *pContext, const char *pCommand, const char *pParams)
  2144. {
  2145.     BOOL bRetval = TRUE;
  2146.     BOOL bHandled = FALSE;
  2147.     HINSTANCE hSpawn = (HINSTANCE)2; // 2 is application not found.
  2148.  
  2149.     if(bHandled == FALSE) {
  2150.         hSpawn = ShellExecute(NULL, NULL, pCommand, pParams, NULL, SW_SHOW);
  2151.         if((int)hSpawn == 2 && pCommand && pParams) {
  2152.             //  Failure, Application not found.
  2153.             //  Some legacy helpers (netscape viewers section of preferences)
  2154.             //      specify switches in the pCommand such that ShellExecute
  2155.             //      fails.  Re-attempt with WinExec to see if it works
  2156.             //      correctly (CyberCash, Norton Anti-Virus).
  2157.             //  Both command and params are specified in this scenario.
  2158.             CString csCommand = CString(pCommand) + " " + CString(pParams);
  2159.             hSpawn = (HINSTANCE)WinExec(csCommand, SW_SHOW);
  2160.         }
  2161.         bHandled = TRUE;
  2162.     }
  2163.  
  2164.     if((int)hSpawn < 32)    {
  2165.         bRetval = FALSE;
  2166.  
  2167.         char szMsg[80];
  2168.         switch((int)hSpawn) {
  2169.         case 0:
  2170.         case 8:
  2171.             sprintf(szMsg, szLoadString(IDS_WINEXEC_0_8));
  2172.             break;
  2173.         case 2:                                      
  2174.         case 3:
  2175.             sprintf(szMsg, szLoadString(IDS_WINEXEC_2_3));
  2176.             break;
  2177.         case 10:
  2178.         case 11:
  2179.         case 12:
  2180.         case 13:
  2181.         case 14:
  2182.         case 15:
  2183.             sprintf(szMsg, szLoadString(IDS_WINEXEC_10_THRU_15));
  2184.             break;
  2185.         case 16:
  2186.             sprintf(szMsg, szLoadString(IDS_WINEXEC_16));
  2187.             break;
  2188.         case 21:
  2189.             sprintf(szMsg, szLoadString(IDS_WINEXEC_21));
  2190.             break;
  2191.         default:
  2192.             sprintf(szMsg, szLoadString(IDS_WINEXEC_XX), (UINT)hSpawn);
  2193.             break;
  2194.         }        
  2195.  
  2196.         FE_Alert(pContext, szMsg);
  2197.     }
  2198.  
  2199.     return(bRetval);
  2200. }
  2201.  
  2202.  
  2203. /*///////////////////////////////////////////////////////////////////////
  2204. // Find the executable which will handle the filename.                 //
  2205. // Retval BOOL:    Wether or not an executable was found.              //
  2206. // pFileName:      The content to be executed.                         //
  2207. // pExecutable:    Buffer to hold the name of executable if found.     //
  2208. // bIdentity:      Wether or not the pFileName can be the pExecutable. //
  2209. // bExtension:     Whether or not pFileName is actually an extension.  //
  2210. ///////////////////////////////////////////////////////////////////////*/
  2211. BOOL FEU_FindExecutable(const char *pFileName, char *pExecutable, BOOL bIdentity, BOOL bExtension) {
  2212.     BOOL bRetval = FALSE;
  2213.     BOOL bFound = FALSE;
  2214.     BOOL bFreeFileName = FALSE;
  2215.     
  2216.     char aViewer[_MAX_PATH];
  2217.     memset(aViewer, 0, sizeof(aViewer));
  2218.  
  2219.     //  pFileName may not be a file name, but an extension.
  2220.     //  We want to support just extensions for ease, so check on it.
  2221.     if(bExtension && pFileName) {
  2222.         //  We have an extension.
  2223.         //  Fill out the rest of the name.
  2224.         bFreeFileName = TRUE;
  2225.         pFileName = (const char *)WH_TempFileName(xpTemporary, "G", pFileName);
  2226.     }
  2227.  
  2228.     if(!bFound && pFileName && *pFileName) {
  2229.         //   Does pFileName actually exists, if not we will need to 
  2230.         //      create it temporarily so that ::FindExecutable will work.
  2231.         BOOL bCreatedFile = FALSE;
  2232.         if(_access(pFileName, 00) != 0) {
  2233.             HFILE hCreate = _lcreat(pFileName, 0);
  2234.             if(hCreate != HFILE_ERROR) {
  2235.                 bCreatedFile = TRUE;
  2236.                 _lclose(hCreate);
  2237.             }
  2238.         }
  2239.  
  2240.         HINSTANCE hRet = FindExecutable(pFileName, NULL, aViewer);
  2241.         if((int)hRet > 32) {
  2242.             //  Found a viewer.
  2243.             bFound = TRUE;
  2244.         }
  2245.         
  2246.         /* Cleanup */
  2247.         if(bCreatedFile) {
  2248.             _unlink(pFileName);
  2249.         }
  2250.     }
  2251.  
  2252.     //  Do we fill in the return value?
  2253.     //  Note that we fill it in regardless of the bIdentity flag.
  2254.     if(pExecutable)  {
  2255.         strcpy(pExecutable, aViewer);
  2256.     }
  2257.  
  2258.     //  Decide return value based on bIdentity if an EXE found.
  2259.     if(bFound)   {
  2260.         if(bIdentity) {
  2261.             bRetval = TRUE;
  2262.         }
  2263.         else {
  2264.             //  Must make sure executable and filename are not the
  2265.             //      same.
  2266.             //  Do a case insensitive comparison.
  2267.             char *pCompareFile = (char *)pFileName;
  2268.             char *pCompareExe = (char *)aViewer;
  2269.             
  2270.     #ifdef XP_WIN32
  2271.             //  On win32, we compare short names to avoid any confusion.
  2272.             char aShortFile[_MAX_PATH];
  2273.             char aShortExe[_MAX_PATH];
  2274.             
  2275.             memset(aShortFile, 0, sizeof(aShortFile));
  2276.             memset(aShortExe, 0, sizeof(aShortExe));
  2277.             
  2278.             GetShortPathName(pCompareFile, aShortFile, sizeof(aShortFile));
  2279.             GetShortPathName(pCompareExe, aShortExe, sizeof(aShortFile));
  2280.             
  2281.             pCompareFile = aShortFile;
  2282.             pCompareExe = aShortExe;
  2283.     #endif
  2284.  
  2285.             //  Case insensitive comparison.
  2286.             if(stricmp(pCompareFile, pCompareExe))   {
  2287.                 //  Not the same.
  2288.                 bRetval = TRUE;
  2289.             }
  2290.         }
  2291.     }
  2292.     
  2293.     if(bFreeFileName && pFileName) {
  2294.         XP_FREE((void *)pFileName);
  2295.         pFileName = NULL;
  2296.     }
  2297.  
  2298.     return(bRetval);
  2299. }
  2300.  
  2301. // Return TRUE if the given path points to an existing
  2302. //   directory.  Attempt to create the directory if we can
  2303. BOOL FEU_SanityCheckDir(const char * dir)
  2304. {
  2305.     int ret;
  2306.     XP_StatStruct statinfo; 
  2307.  
  2308.     ret = _stat((char *) dir, &statinfo);
  2309.     if(ret == -1) {
  2310.  
  2311.         // see if we can just create it
  2312. #ifdef __WATCOMC__
  2313.         ret = mkdir(dir);
  2314. #else
  2315.         ret = _mkdir(dir);
  2316. #endif
  2317.     
  2318.         // still couldn't create it
  2319.         if(ret == -1)
  2320.             return(FALSE);
  2321.  
  2322.     }
  2323.  
  2324.     return(TRUE);
  2325.     
  2326. }
  2327.  
  2328. // Return TRUE if the given file has a valid path           
  2329. BOOL FEU_SanityCheckFile(const char * file)
  2330. {
  2331.     int ret;
  2332.     XP_StatStruct statinfo; 
  2333.  
  2334.     ret = _stat((char *) file, &statinfo);
  2335.     if(ret == -1)
  2336.         return(FALSE);
  2337.     else
  2338.         return(TRUE);
  2339.     
  2340. }
  2341.  
  2342. void FEU_DeleteUrlData(URL_Struct *pUrl, MWContext *pCX)    {
  2343.     //    A Url is about to be removed.
  2344.     //    Clean up any extra stuff that we know about but Netlib doesn't.
  2345.     if(pUrl->ncapi_data != NULL)    {
  2346.         CNcapiUrlData *pUrlData = (CNcapiUrlData *)pUrl->ncapi_data;
  2347.         delete pUrlData;
  2348.     }
  2349. }
  2350.  
  2351.  
  2352.  
  2353. BOOL FEU_IsNetscapeFrame(CWnd* pFocusWnd) 
  2354. {
  2355.     if (pFocusWnd->IsKindOf(RUNTIME_CLASS(CGenericView))) 
  2356.         return TRUE;
  2357.     else if (pFocusWnd->IsKindOf(RUNTIME_CLASS(CGenericFrame)))
  2358.         return TRUE;
  2359. #ifdef MOZ_MAIL_NEWS      
  2360.     else if (pFocusWnd->IsKindOf(RUNTIME_CLASS(CMsgListFrame)))
  2361.         return TRUE;
  2362. #endif /* MOZ_MAIL_NEWS */      
  2363. //    else if (pFocusWnd->IsKindOf(RUNTIME_CLASS(CNSToolbar2)))
  2364. //        return TRUE;
  2365.     else return FALSE;
  2366.  
  2367. }
  2368.  
  2369. BOOL CALLBACK WinEnumProc(HWND hwnd, LPARAM lParam)
  2370. {
  2371.  // check to see if the Windows title is "Netscape's Hidden Frame"
  2372.  char winText[256];
  2373.  if (GetWindowText(hwnd, winText, sizeof(winText)) != 0)
  2374.  {
  2375.   if (lstrcmpi(winText, "Netscape's Hidden Frame") == 0)
  2376.   {
  2377.    *((HWND*)lParam) = hwnd;
  2378.    return(FALSE);
  2379.   }
  2380.  }
  2381.  return(TRUE);
  2382. }
  2383.  
  2384. extern "C"
  2385. HWND FindNavigatorHiddenWindow(void)
  2386. {
  2387.  // find Navigator's hidden frame
  2388.  HWND hWnd = NULL;
  2389.  EnumWindows(WinEnumProc, (LPARAM)&hWnd);
  2390.  return(hWnd);
  2391. }
  2392.  
  2393.  
  2394. //Used to determine initialization action.  If we detect a previous instance
  2395. //and it is in the middle of initializing, find out how far along it is by
  2396. //looking for it's hidden frame.  If the previous instance has a hidden frame
  2397. //then we return TRUE and alow the second instance to DDE to the first.  If it
  2398. //doesn't have a hidden frame, we wait for 10 seconds in the case that the first
  2399. //and the second instance started at nearly the same time. Thus, giving the first 
  2400. //instance a chance to create it's hidden frame and allowing the second instance
  2401. //to open a successful DDE conversation to the first instance.
  2402. //This function should be called from InitInstance prior to the Initialization of 
  2403. //the NetscapeSlaveClass.  This call is only need for win32.  This same call
  2404. //will be made for win16 but from the NAVSTART.EXE application.  
  2405. #ifdef XP_WIN32
  2406. BOOL BailOrStay(void)
  2407. {
  2408.     if (FindWindow("NetscapeSlaveClass",NULL))
  2409.     {
  2410.         if (!FindNavigatorHiddenWindow())
  2411.         {
  2412.             Sleep(10000);//give the first instance a chance to start
  2413.             if(!FindNavigatorHiddenWindow()) //If it's not present yet we just exit.
  2414.             {                                //First instance is probably running the profile manager.
  2415.                 return FALSE;
  2416.             }
  2417.         }            
  2418.     }
  2419.     return TRUE;
  2420. }
  2421. #endif
  2422.  
  2423. //  Do not change the current drive to a floppy.
  2424. BOOL FEU_GetSaveFileName(OPENFILENAME *pOFN)
  2425. {
  2426.     //  Check to see if the dialog will ignore directory changes.
  2427.     BOOL bCheckFloppy = (pOFN && !(pOFN->Flags & OFN_NOCHANGEDIR));
  2428.     char aOriginalPath[MAX_PATH];
  2429.     if(bCheckFloppy) {
  2430.         //  Make sure we're not already on a floppy.
  2431.         if(FEU_GetCurrentDriveType() == DRIVE_REMOVABLE) {
  2432.             //  We don't care what they do.
  2433.             bCheckFloppy = FALSE;
  2434.         }
  2435.         else {
  2436.             //  Save current directory.
  2437.             DWORD dwCopy = ::GetCurrentDirectory(sizeof(aOriginalPath), aOriginalPath);
  2438.             if(0 == dwCopy || sizeof(aOriginalPath) < dwCopy) {
  2439.                 //  On failure, switch to not care.
  2440.                 bCheckFloppy = FALSE;
  2441.             }
  2442.         }
  2443.     }
  2444.  
  2445.     BOOL bRetval = ::GetSaveFileName(pOFN);
  2446.  
  2447.     //  Are we to check if we are on a floppy drive?
  2448.     if(bCheckFloppy) {
  2449.         BOOL bFloppy = (FEU_GetCurrentDriveType() == DRIVE_REMOVABLE);
  2450.         if(bFloppy) {
  2451.             //  Go back to a non-floppy location.
  2452.             //  Don't care on failure.
  2453.             ::SetCurrentDirectory(aOriginalPath);
  2454.         }
  2455.     }
  2456.  
  2457.     return(bRetval);
  2458. }
  2459.  
  2460. //  Do not change the current drive to a floppy.
  2461. BOOL FEU_GetOpenFileName(OPENFILENAME *pOFN)
  2462. {
  2463.     //  Check to see if the dialog will ignore directory changes.
  2464.     BOOL bCheckFloppy = (pOFN && !(pOFN->Flags & OFN_NOCHANGEDIR));
  2465.     char aOriginalPath[MAX_PATH];
  2466.     if(bCheckFloppy) {
  2467.         //  Make sure we're not already on a floppy.
  2468.         if(FEU_GetCurrentDriveType() == DRIVE_REMOVABLE) {
  2469.             //  We don't care what they do.
  2470.             bCheckFloppy = FALSE;
  2471.         }
  2472.         else {
  2473.             //  Save current directory.
  2474.             DWORD dwCopy = ::GetCurrentDirectory(sizeof(aOriginalPath), aOriginalPath);
  2475.             if(0 == dwCopy || sizeof(aOriginalPath) < dwCopy) {
  2476.                 //  On failure, switch to not care.
  2477.                 bCheckFloppy = FALSE;
  2478.             }
  2479.         }
  2480.     }
  2481.  
  2482.     BOOL bRetval = ::GetOpenFileName(pOFN);
  2483.  
  2484.     //  Are we to check if we are on a floppy drive?
  2485.     if(bCheckFloppy) {
  2486.         BOOL bFloppy = (FEU_GetCurrentDriveType() == DRIVE_REMOVABLE);
  2487.         if(bFloppy) {
  2488.             //  Go back to a non-floppy location.
  2489.             //  Don't care on failure.
  2490.             ::SetCurrentDirectory(aOriginalPath);
  2491.         }
  2492.     }
  2493.  
  2494.     return(bRetval);
  2495. }
  2496.  
  2497. //  Return the current Drive's type
  2498. UINT FEU_GetCurrentDriveType(void)
  2499. {
  2500. #ifdef XP_WIN16
  2501.     return(::GetDriveType(::_getdrive() - 1));
  2502. #else
  2503.     return(::GetDriveType(NULL));
  2504. #endif
  2505. }
  2506.  
  2507. #ifdef XP_WIN16
  2508. DWORD GetCurrentDirectory(DWORD nBufferLength, LPSTR lpBuffer)
  2509. {
  2510.     DWORD dwRetval = nBufferLength + MAX_PATH;
  2511.     char *pRetval = NULL;
  2512.     if(lpBuffer) {
  2513.         pRetval = _getcwd(lpBuffer, nBufferLength);
  2514.     }
  2515.     if(pRetval) {
  2516.         dwRetval = XP_STRLEN(lpBuffer);
  2517.     }
  2518.     return(dwRetval);
  2519. }
  2520.  
  2521. BOOL SetCurrentDirectory(LPCSTR lpPathName)
  2522. {
  2523.     BOOL bRetval = FALSE;
  2524.     if(lpPathName) {
  2525.         if(_chdir(lpPathName) == 0) {
  2526.             //  Must also change drive in 16 bits.
  2527.             char aDrive[_MAX_DRIVE];
  2528.             aDrive[0] = '\0';
  2529.             _splitpath(lpPathName, aDrive, NULL, NULL, NULL);
  2530.             if(aDrive[0]) {
  2531.                 //  A drive, convert to numeral.
  2532.                 aDrive[0] = toupper(aDrive[0]);
  2533.                 if(_chdrive(aDrive[0] - 'A' + 1) == 0) {
  2534.                     bRetval = TRUE;
  2535.                 }
  2536.             }
  2537.             else {
  2538.                 //  No drive, then a success.
  2539.                 bRetval = TRUE;
  2540.             }
  2541.         }
  2542.     }
  2543.     return(bRetval);
  2544. }
  2545. #endif
  2546.  
  2547. //  Determine the top most window below the given point.
  2548. //  No guarantees that the window belongs to our process, or what
  2549. //      type of window it is.
  2550. //  Invisible windows are not returned.
  2551. //  Disabled windows are not returned.
  2552. //
  2553. //  hWndTop same as GetTopWindow SDK function.
  2554. //  Point is in Screen coordinates.
  2555. HWND FEU_GetWindowFromPoint(HWND hWndTop, POINT *pPoint)
  2556. {
  2557.     HWND hRetval = NULL;
  2558.     if(pPoint) {
  2559.         HWND hTraverse = GetTopWindow(hWndTop);
  2560.         if(hTraverse) {
  2561.             RECT rWindow;
  2562.             do {
  2563.                 memset(&rWindow, 0, sizeof(rWindow));
  2564.                 GetWindowRect(hTraverse, &rWindow);
  2565.                 if(PtInRect(&rWindow, *pPoint)) {
  2566.                     if(!IsWindowVisible(hTraverse)) {
  2567.                         //  Skip this one.
  2568.                         continue;
  2569.                     }
  2570.                     if(!IsWindowEnabled(hTraverse)) {
  2571.                         //  Window is visible, but disabled.
  2572.                         //  Have to return NULL.
  2573.                         break;
  2574.                     }
  2575.                     hRetval = hTraverse;
  2576.                     break;
  2577.                 }
  2578.             } while(hTraverse = GetNextWindow(hTraverse, GW_HWNDNEXT));
  2579.         }
  2580.     }
  2581.     return(hRetval);
  2582. }
  2583.  
  2584. CNSGenFrame *FEU_GetDockingFrameFromPoint(POINT *pPoint)
  2585. {
  2586.     CNSGenFrame *pRetval = NULL;
  2587.     HWND hAttempt = FEU_GetWindowFromPoint(NULL, pPoint);
  2588.     if(hAttempt) {
  2589.         CWnd *pPerm = CWnd::FromHandlePermanent(hAttempt);
  2590.         if(pPerm && pPerm->IsKindOf(RUNTIME_CLASS(CNSGenFrame))) {
  2591.             CNSGenFrame *pDockable = (CNSGenFrame *)pPerm;
  2592.             if(pDockable->AllowDocking()) {
  2593.                 pRetval = pDockable;
  2594.             }
  2595.         }
  2596.     }
  2597.     return(pRetval);
  2598. }
  2599.  
  2600. extern "C" PRBool FE_IsNetscapeDefault(void) {
  2601.     return PR_TRUE;
  2602. }
  2603.  
  2604. extern "C" PRBool FE_MakeNetscapeDefault(void) {
  2605.     return PR_TRUE;
  2606. }
  2607.  
  2608.  
  2609.