gecko-dev/cmd/winfe/feutil.cpp

2660 строки
78 KiB
C++
Executable File

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "stdafx.h"
#include "fe_proto.h"
#include "hiddenfr.h"
#include "postal.h"
#include "helper.h"
#include "prefapi.h"
#ifdef MOZ_MAIL_NEWS
#include "mailfrm.h"
#endif // MOZ_MAIL_NEWS
#include "toolbar2.h"
#include "VerReg.h"
#include "libmocha.h"
#include "ngdwtrst.h"
#if defined(OJI)
#include "jvmmgr.h"
#elif defined(JAVA)
#include "java.h"
#endif
extern "C" {
#include "xpgetstr.h"
extern int XP_ALERT_NETCASTER_NO_JS;
extern int XP_ALERT_CANT_RUN_NETCASTER;
};
// File used to house all general purpose front end
// function which have no other specific home.
// All functions in this file should begin with FEU.
// Way to get a frame window pointer out of a context ID.
// Must be of the appropriate type (Browser, mail, any, etc).
extern char szOLEFileType[MAX_INTERNAL_OLEFORMAT][4];
CFrameWnd *FEU_FindFrameByID(DWORD dwID, MWContextType cxType)
{
// Use the frame glue to do most of the work.
CFrameGlue *pFrameGlue = CFrameGlue::FindFrameByID(dwID, cxType);
if(pFrameGlue == NULL) {
return(NULL);
}
// Return the frame window of the frame glue, can be NULL.
return(pFrameGlue->GetFrameWnd());
}
// Way to get a frame window that was last active browser window.
CFrameWnd *FEU_GetLastActiveFrame(MWContextType cxType, int nFindEditor)
{
// Have the frame glue look it up.
CFrameGlue *pFrameGlue = CFrameGlue::GetLastActiveFrame(cxType, nFindEditor);
if(pFrameGlue == NULL) {
return(NULL);
}
// Return the frame window as known by the glue.
return(pFrameGlue->GetFrameWnd());
}
// Way to get a frame window that was last active browser window.
CAbstractCX *FEU_GetLastActiveFrameContext(MWContextType cxType, int nFindEditor)
{
// Have the frame glue look it up.
CFrameGlue *pFrameGlue = CFrameGlue::GetLastActiveFrame(cxType, nFindEditor);
if(pFrameGlue == NULL) {
return(NULL);
}
// Return the frame window as known by the glue.
return(pFrameGlue->GetMainContext());
}
CFrameWnd *FEU_GetLastActiveFrameByCustToolbarType(CString custToolbar, CFrameWnd *pCurrentFrame, BOOL bUseSaveInfo)
{
// Have the frame glue look it up.
CFrameGlue *pFrameGlue = CFrameGlue::GetLastActiveFrameByCustToolbarType(custToolbar, pCurrentFrame, bUseSaveInfo);
if(pFrameGlue == NULL) {
return(NULL);
}
// Return the frame window as known by the glue.
return(pFrameGlue->GetFrameWnd());
}
// Way to get the bottommost frame of t ype cxType
CFrameWnd *FEU_GetBottomFrame(MWContextType cxType, int nFindEditor)
{
CFrameGlue *pFrameGlue = CFrameGlue::GetBottomFrame(cxType, nFindEditor);
if(pFrameGlue == NULL)
return NULL;
//Return the frame window as known by the glue.
return(pFrameGlue->GetFrameWnd());
}
// Way to get a frame window that was last active browser window.
int FEU_GetNumActiveFrames(MWContextType cxType, int nFindEditor)
{
// Have the frame glue look it up.
int nCount = CFrameGlue::GetNumActiveFrames(cxType, nFindEditor);
// Return the frame window as known by the glue.
return(nCount);
}
// Way to get the context ID out of the frame which was last active.
// Returns 0 on error.
DWORD FEU_GetLastActiveFrameID(MWContextType cxType)
{
DWORD dwRetval = 0;
// Look up the last active frame of said type.
CFrameGlue *pFrameGlue = CFrameGlue::GetLastActiveFrame(cxType);
if(pFrameGlue != NULL) {
// Must have a context.
if(pFrameGlue->GetActiveContext() != NULL) {
dwRetval = pFrameGlue->GetActiveContext()->GetContextID();
}
else if(pFrameGlue->GetMainContext() != NULL) {
dwRetval = pFrameGlue->GetMainContext()->GetContextID();
}
}
return(dwRetval);
}
//#ifndef NO_TAB_NAVIGATION
// Scroll the current MWContext so that the Rect is visible
// FEU_MakeRectVisible() is subtracted from old FEU_MakeFormVisible(),
// and is used not only for Form elements, but other Tabable
// elements, such as links.
void FEU_MakeRectVisible(MWContext *pContext, const UINT left, const UINT top, const UINT right, const UINT bottom)
{
if(pContext == NULL )
return;
if(! ABSTRACTCX(pContext) || ! ABSTRACTCX(pContext)->IsWindowContext() )
return;
LTRB Rect( left, top, right, bottom);
CPaneCX *pCX = PANECX(pContext);
int32 lX = pCX->GetOriginX();
int32 lY = pCX->GetOriginY();
BOOL bMove = FALSE;
// If the element is partially to the right of the screen, we only want to
// move enough to get it fully on the screen.
if(Rect.left < pCX->GetOriginX() + pCX->GetWidth() &&
Rect.right > pCX->GetOriginX() + pCX->GetWidth() &&
Rect.Width() < pCX->GetWidth()) {
lX += Rect.right - (pCX->GetOriginX() + pCX->GetWidth());
bMove = TRUE;
}
// If the element is partially to the bottom of the screen, we only want to
// move enough to get it fully onto the screen.
if(Rect.top < pCX->GetOriginY() + pCX->GetHeight() &&
Rect.bottom > pCX->GetOriginY() + pCX->GetHeight() &&
Rect.Height() < pCX->GetHeight()) {
lY += Rect.bottom - (pCX->GetOriginX() + pCX->GetHeight());
bMove = TRUE;
}
// If the element is not fully on the screen, then we want to move so that it
// is on the screen at whatever cost that may be.
if(Rect.left < lX || Rect.left > lX + pCX->GetWidth() || Rect.top < lY ||
Rect.top > lY + pCX->GetHeight()) {
lX = Rect.left;
lY = Rect.top;
bMove = TRUE;
}
// Move if needed.
if(bMove) {
FE_SetDocPosition(pContext, FE_VIEW, lX, lY);
}
} // FEU_MakeRectVisible(
// old version is named as FEU_MakeFormVisible()
// Scroll the current MWContext so that the child window is visible
// New version.
void FEU_MakeElementVisible(MWContext *pContext, LO_Any *pElement)
{
if( NULL == pElement)
return;
// Figure up where the form element actually lies.
LTRB Rect;
Rect.left = pElement->x + pElement->x_offset;
Rect.top = pElement->y + pElement->y_offset;
Rect.right = Rect.left + pElement->width;
Rect.bottom = Rect.top + pElement->height;
FEU_MakeRectVisible( pContext, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom) );
}
//#else /* NO_TAB_NAVIGATION */
//#endif /* NO_TAB_NAVIGATION */
// The purpose of FEU_AhAhAhAhStayingAlive is to house the one and only
// saturday night fever function; named after Chouck's idol.
// This function will attempt to do all that is necessary in order
// to keep the application's messages flowing and idle loops
// going when we need to finish an asynchronous operation
// synchronously.
// The current cases that cause this are RPC calls into the
// application where we need to return a value or produce output
// from only one entry point before returning to the caller.
//
// If and when you modify this function, get your changes reviewed.
// It is too vital that this work, always.
//
// The function only attempts to look at one message at a time, or
// propigate one idle call at a time, keeping it's own idle count.
// This is not a loop. YOU must provide the loop which calls this function.
//
// Due to the nature and order of which we process windows messages, this
// can seriously mess with the flow of control through the client.
// If there is any chance at all that you can ensure that you are at the
// bottom of the message queue before doing this, then please take those
// measures.
extern "C" void FEU_StayingAlive()
{
static long lIdleCounter = 0;
// Stage 1.
// See if there are any messages which need to be propigated.
MSG msg;
if(::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE)) {
BOOL bPumpVal = theApp.NSPumpMessage();
// If this assertion fails, then we received a WM_QUIT, and
// the user is about to receive a dialog from the OS saying
// we are not responding to the system's request to shut down.
// Nothing we can do and still accomplish what we are trying to do....
ASSERT(bPumpVal);
// Reset the idle counter.
lIdleCounter = 0;
}
else {
// Stage 2.
// Call the Apps Idle loop.
// Ignore wether or not it says it needs or does not need more idle time.
// It is wholly dependent upon wether or not there are events in the queue.
theApp.OnIdle(lIdleCounter++);
}
}
// A utility function to block returning until a context is no longer
// found in the context list.
void FEU_BlockUntilDestroyed(DWORD dwContextID)
{
TRACE("Entering FEU_BlockUntilDestroyed(%lu)\n", dwContextID);
// Loop until the context is not in the context list, meaning it
// has been destroyed.
while(CAbstractCX::FindContextByID(dwContextID) != NULL) {
// Keep the app going.
FEU_StayingAlive();
}
TRACE("Leaving FEU_BlockUntilDestroyed(%lu)\n", dwContextID);
}
//
// Dynamically open the MAPI libraries for mail posting
//
void FEU_OpenMapiLibrary()
{
BOOL bLoadOK = FALSE;
theApp.m_fnOpenMailSession = NULL;
theApp.m_fnComposeMailMessage = NULL;
theApp.m_fnUnRegisterMailClient = NULL;
theApp.m_fnShowMailBox = NULL;
theApp.m_fnShowMessageCenter = NULL;
theApp.m_fnCloseMailSession = NULL;
theApp.m_fnGetMenuItemString = NULL;
UINT fuErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX);
char * prefStr = NULL;
PREF_CopyCharPref("mail.altmail_dll",&prefStr);
theApp.m_hPostalLib = LoadLibrary(prefStr);
if (prefStr) XP_FREE(prefStr);
SetErrorMode(fuErrorMode);
#ifdef XP_WIN32
if(theApp.m_hPostalLib)
{
#else
if(theApp.m_hPostalLib > HINSTANCE_ERROR)
{
#endif
//If we don't find "ShowMailBox" then we know it's either an old or invalid dll
SHOWMAILBOX testProc = (SHOWMAILBOX)::GetProcAddress(theApp.m_hPostalLib, "ShowMailBox");
if(testProc)
{
REGISTERMAIL regProc = (REGISTERMAIL)::GetProcAddress(theApp.m_hPostalLib, "RegisterMailClient");
theApp.m_fnOpenMailSession =
(OPENMAIL)::GetProcAddress(theApp.m_hPostalLib, "OpenMailSession");
theApp.m_fnComposeMailMessage =
(COMPOSEMAIL)::GetProcAddress(theApp.m_hPostalLib, "ComposeMailMessage");
theApp.m_fnUnRegisterMailClient =
(UNREGISTERMAIL)::GetProcAddress(theApp.m_hPostalLib, "UnRegisterMailClient");
theApp.m_fnShowMailBox =
(SHOWMAILBOX)::GetProcAddress(theApp.m_hPostalLib, "ShowMailBox");
theApp.m_fnShowMessageCenter =
(SHOWMESSAGECENTER)::GetProcAddress(theApp.m_hPostalLib, "ShowMessageCenter");
theApp.m_fnCloseMailSession =
(CLOSEMAIL)::GetProcAddress(theApp.m_hPostalLib, "CloseMailSession");
theApp.m_fnGetMenuItemString =
(GETMENUITEMSTRING)::GetProcAddress(theApp.m_hPostalLib, "GetMenuItemString");
if(theApp.m_fnOpenMailSession && theApp.m_fnComposeMailMessage && theApp.m_fnUnRegisterMailClient
&& theApp.m_fnShowMailBox && theApp.m_fnShowMessageCenter && theApp.m_fnCloseMailSession
&& theApp.m_fnGetMenuItemString && regProc)
{
POSTCODE status = (*regProc) (theApp.m_pHiddenFrame->m_hWnd, "Netscape Mail System");
if(status == POST_OK)
bLoadOK = TRUE;
else
MessageBox(NULL, szLoadString(IDS_ALTMAIL_REGISTER_FAILED), szLoadString(AFX_IDS_APP_TITLE), MB_OK | MB_ICONEXCLAMATION);
}
else
MessageBox(NULL, szLoadString(IDS_ALTMAIL_MISSING_FUNCTIONS), szLoadString(AFX_IDS_APP_TITLE), MB_OK | MB_ICONEXCLAMATION);
}
else
MessageBox(NULL, szLoadString(IDS_ALTMAIL_OLD_DLL), szLoadString(AFX_IDS_APP_TITLE), MB_OK | MB_ICONEXCLAMATION);
}
else
{
#ifdef XP_WIN16
//In Win16 the LoadLibrary returns < 32 when it fails
//and since we check m_hPostalLib != NULL throughout
//the code let's set m_hPostalLib to NULL.
theApp.m_hPostalLib = NULL;
#endif
MessageBox(NULL, szLoadString(IDS_ALTMAIL_MISSING_DLL), szLoadString(AFX_IDS_APP_TITLE), MB_OK | MB_ICONEXCLAMATION);
}
if(!bLoadOK && theApp.m_hPostalLib)
{
FreeLibrary(theApp.m_hPostalLib);
theApp.m_hPostalLib = NULL;
}
}
void FEU_CloseMapiLibrary()
{
if(theApp.m_fnCloseMailSession)
(*theApp.m_fnCloseMailSession) ();
if(theApp.m_fnUnRegisterMailClient)
(*theApp.m_fnUnRegisterMailClient) ();
if(theApp.m_hPostalLib)
FreeLibrary(theApp.m_hPostalLib);
theApp.m_hPostalLib = NULL;
// call init if reload
theApp.m_bInitMapi = TRUE;
// clear out all function pointers
theApp.m_fnOpenMailSession = NULL;
theApp.m_fnComposeMailMessage = NULL;
theApp.m_fnUnRegisterMailClient = NULL;
theApp.m_fnShowMailBox = NULL;
theApp.m_fnShowMessageCenter = NULL;
theApp.m_fnCloseMailSession = NULL;
theApp.m_fnGetMenuItemString = NULL;
}
#ifdef XP_WIN16
// 16 bits needs a GetDiskFreeSpace call.
BOOL GetDiskFreeSpace(LPCTSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters)
{
// Init.
*lpSectorsPerCluster = 0;
*lpBytesPerSector = 0;
*lpNumberOfFreeClusters = 0;
*lpTotalNumberOfClusters = 0;
// Saftey dance.
if(lpRootPathName == NULL) {
return(FALSE);
}
unsigned uDrive = 0;
if(strlen(lpRootPathName) > 1 && lpRootPathName[1] == ':') {
// Determine what drive we're looking at.
uDrive = toupper(*lpRootPathName) - 'A' + 1;
if(uDrive < 1 || uDrive > 26) {
// Use default drive....
uDrive = 0;
}
}
// Ask for amount of free disk space.
_diskfree_t dtFree;
memset(&dtFree, 0, sizeof(dtFree));
if(_dos_getdiskfree(uDrive, &dtFree)) {
// Call failure.
return(FALSE);
}
// assign what we found out.
*lpSectorsPerCluster = dtFree.sectors_per_cluster;
*lpBytesPerSector = dtFree.bytes_per_sector;
*lpNumberOfFreeClusters = dtFree.avail_clusters;
*lpTotalNumberOfClusters = dtFree.total_clusters;
// Success.
return(TRUE);
}
#endif
// See if content length can fit on a disk.
// If not, ask the user to confirm what they want (to write anyway).
// pFileName should contain the full path information for the file.
// All failures in this code mean success, actual errors should be
// found by other code attempting to open or write the file.
// Only on user denial to write will this code return failure.
// Implemented in femess.cpp, declared in msgcom.h
extern "C" uint32 FE_DiskSpaceAvailable (MWContext *context, const char *lpszPath );
BOOL FEU_ConfirmFreeDiskSpace(MWContext *pContext, const char *pFileName, int32 lContentLength)
{
// Absence of context means success since can't confirm space with user.
if(pContext == NULL) {
return(TRUE);
}
// Absence of a valid content length means success.
if(lContentLength <= 0) {
TRACE("Invalid content length, can't check free disk space.\n");
return(TRUE);
}
DWORD dwFreeSpace = FE_DiskSpaceAvailable( pContext, pFileName );
// If the length is greater than this, we need to confirm with the user on what to do.
if(dwFreeSpace < (DWORD)lContentLength) {
// Ask the user.
CString csAsk;
csAsk.LoadString(IDS_CONFIRM_DISK_SPACE);
size_t stSize = strlen(pFileName) + csAsk.GetLength() + 10;
char *pBuffer = new char[stSize];
if(pBuffer != NULL) {
sprintf(pBuffer, csAsk, pFileName);
BOOL bRetval = FE_Confirm(pContext, pBuffer);
delete [] pBuffer;
return(bRetval);
}
}
// Let it happen.
return(TRUE);
}
#if defined(XP_WIN16)
// There is literally no 32 bit equivalent for GetFreeSystemResources.
// Usually set pString to the file name, and iDigit to the line number.
// bBox controls wether or not a trace message will be used, or a dialog box.
void FEU_FreeResources(const char *pString, int iDigit, BOOL bBox)
{
UINT uSystem = GetFreeSystemResources(GFSR_SYSTEMRESOURCES);
UINT uGdi = GetFreeSystemResources(GFSR_GDIRESOURCES);
UINT uUser = GetFreeSystemResources(GFSR_USERRESOURCES);
char aBuffer[1024];
sprintf(aBuffer, "%s:%d\n%u System\n%u GDI\n%u User\n", pString, iDigit, uSystem, uGdi, uUser);
if(bBox) {
::MessageBox(NULL, aBuffer, "Resources", MB_OK);
}
TRACE(aBuffer);
}
#endif
// Remove all trailing backslashes from the string.
char *FEU_NoTrailingBackslash(char *pBackslash) {
if(pBackslash) {
int32 lTempLen = XP_STRLEN(pBackslash);
while(lTempLen) {
lTempLen--; // Back off one for comparison of the last char.
if(*(pBackslash + lTempLen) == '\\') {
// Knock it off.
*(pBackslash + lTempLen) = '\0';
}
else {
// No more backslashes to whack on the end.
break;
}
}
}
return(pBackslash);
}
// Replace all occurrences of original in pStr with new
void FEU_ReplaceChar(char *pStr, char original, char replace)
{
char *pFound;
while((pFound = strchr(pStr, original)) != NULL) {
*pFound = replace;
}
}
CString FEU_EscapeAmpersand(CString str)
{
CString newStr(""), leftStr, rightStr;
int nIndex;
rightStr = str;
while((nIndex = rightStr.Find('&')) != -1)
{
leftStr = rightStr.Left(nIndex);
newStr = newStr + leftStr;
newStr = newStr + "&&";
rightStr = rightStr.Right(rightStr.GetLength() - nIndex - 1);
}
// put in everything after the last ampersand.
newStr = newStr + rightStr;
return newStr;
}
// Write string values to the registry in the said location.
BOOL FEU_RegistryWizard(HKEY hRoot, const char *pKey, const char *pValue)
{
if(!pKey) {
return(FALSE);
}
HKEY hKey;
LONG lResultCreate = RegCreateKey(hRoot, pKey, &hKey);
if(lResultCreate != ERROR_SUCCESS) {
return(FALSE);
}
LONG lResultValue = RegSetValue(hKey, NULL, REG_SZ,
pValue ? pValue : "",
pValue ? XP_STRLEN(pValue) + 1 : 1);
LONG lResultClose = RegCloseKey(hKey);
if(lResultValue != ERROR_SUCCESS || lResultClose != ERROR_SUCCESS) {
return(FALSE);
}
return(TRUE);
}
// support quoted name.
// clapse multiple space is not quoted.
int FEU_ExtractCommaDilimetedFontName(const char *pArgList, int offSetByte, char *argItem)
{
int theQuote = '\0';
int length = 0;
int isLastSpace = 0;
const char *pTraverse = pArgList + offSetByte;
*argItem = '\0';
// Handle all stupidness.
if(pTraverse == NULL || *pTraverse == '\0' || offSetByte < 0) {
return(0); // no arg found
}
// skip leading space
while(*pTraverse && isspace(*pTraverse))
pTraverse++;
// See if this arg is quoted
theQuote = '\0';
if( *pTraverse == '"' || *pTraverse == '\'' ) {
theQuote = *pTraverse++;
}
if( theQuote != '\0' ) {
// quoted arg
while( *pTraverse ) {
if( *pTraverse != theQuote ) {
*argItem++ = * pTraverse++;
length++;
if( length >= MAXFONTFACENAME -1 ) {
// overflow
*(--argItem) = '\0';
return(-1);
}
} else {
*argItem = '\0'; // terminate
pTraverse++; // skip the quote
break;
}
}
// we passed the quote, now get over the comma
// ignore any char between closing quote and comma
while( *pTraverse && *pTraverse != ',' )
pTraverse++;
if( *pTraverse == ',' )
pTraverse++;
return( pTraverse - pArgList ); // offset for next arg
}
// arg without quote
while( *pTraverse && *pTraverse != ',' ) {
if( isLastSpace && isspace(*pTraverse) ) {
pTraverse++; // clapse multiple space
continue;
} else {
isLastSpace = isspace(*pTraverse);
*argItem++ = *pTraverse++;
length++;
if( length >= MAXFONTFACENAME -1 ) {
// overflow
*(--argItem) = '\0';
return(-1);
}
}
} // while( *pTraverse )
*argItem = '\0'; // terminator
// remove trailing space
while( --length && isspace( *(--argItem) ) )
*argItem = '\0'; // terminator
if( *pTraverse == ',' )
pTraverse++;
return( pTraverse - pArgList ); // offset for next arg
}
#ifdef not_support_quoted_font_face_name
// As the function indicates.
// Allocated return values to be freed by caller.
char *FEU_ExtractCommaDilimetedString(const char *pArgList, int iArgToExtract)
{
char *pRetval = NULL;
// Handle all stupidness.
if(pArgList == NULL || iArgToExtract <= 0) {
return(pRetval);
}
// Skip to comma of the arg in question.
const char *pTraverse = pArgList;
do {
iArgToExtract--;
if(iArgToExtract) {
// Search for next comma.
pTraverse = strchr(pTraverse, ',');
if(pTraverse) {
// Go past comma.
pTraverse++;
}
}
} while(iArgToExtract && pTraverse);
if(pTraverse) {
// Skip all whitespace before the string.
while(isspace(*pTraverse)) {
pTraverse++;
}
// Copy till next comma or end of string.
// Make sure not empty.
char *pEnd = strchr(pTraverse, ',');
int iAlloc = 0;
if(pEnd == NULL) {
iAlloc = strlen(pTraverse) + 1;
}
else {
iAlloc = pEnd - pTraverse + 1;
}
// If we've something to allocate.
if(iAlloc) {
pRetval = (char *)XP_ALLOC(iAlloc);
if(pRetval) {
// clear it out.
memset(pRetval, 0, iAlloc);
// Copy over the amount -1.
strncpy(pRetval, pTraverse, iAlloc - 1);
// Walk backwards through the string, clearing off
// any space.
pEnd = pRetval + iAlloc - 2;
while(pEnd >= pRetval && isspace(*pEnd)) {
*pEnd = '\0';
pEnd--;
}
}
}
}
return(pRetval);
}
#endif // not_support_quoted_font_face_name
// As the function indicates.
// Allocated return values to be freed by caller.
char *FEU_ExtractCommaDilimetedQuotedString(const char *pArgList, int iArgToExtract) {
char *pRetval = NULL;
// Handle all stupidness.
if(pArgList == NULL || iArgToExtract <= 0) {
return(pRetval);
}
// Find the first argument.
// First arg will be right after the first quote.
const char *pTraverse = pArgList;
while(*pTraverse != '\"' && *pTraverse != '\0') {
pTraverse++;
}
// If we have an argument.
if(*pTraverse == '\"') {
pTraverse++;
// Okay, we need to find out where the ending comma exists.
int iQuoteLevel = 1;
const char *pQuote = pTraverse;
while(iQuoteLevel) {
// Go until we reach another quote.
while(*pQuote != '\"' && *pQuote != '\0') {
pQuote++;
}
// Did we reach a quote?
if(*pQuote == '\"') {
pQuote++;
// Assume this is an ending quote if we can find a comma before another quote.
iQuoteLevel--;
if(iQuoteLevel == 0) {
// Begin ananlysis.
const char *pComma = pQuote;
while(*pComma != '\"' && *pComma != ',' && *pComma != '\0') {
pComma++;
}
// What are we lookit at?
if(*pComma == '\"') {
// Another quote.
// Up the quote count by 2.
iQuoteLevel += 2;
}
else if(*pComma == ',') {
// We're out of here!
// Is this the first argument, though?
if(iArgToExtract != 1) {
// What they want is a different one.
// Go recursive and let them pick up where we left off.
pRetval = FEU_ExtractCommaDilimetedQuotedString(pComma + 1, iArgToExtract - 1);
}
else {
// We have the argument they want.
// Exact dimenstion of the argument are from pTraverse to pQuote - 2;
// Cathch the boundry case of "",
if(pQuote - 2 >= pTraverse) {
int iLength = pQuote - pTraverse;
pRetval = (char *)XP_ALLOC(iLength);
if(pRetval) {
memset(pRetval, 0, iLength);
int iCounter = 0;
while(pTraverse <= pQuote - 2) {
pRetval[iCounter] = *pTraverse;
pTraverse++;
iCounter++;
}
}
}
}
}
else {
// End of string, get out of while loop.
// However, if this is the only argument we're looking for, we may already have
// what we need.
if(iArgToExtract == 1) {
// We have the argument they want.
// Exact dimenstion of the argument are from pTraverse to pQuote - 2;
// Cathch the boundry case of "",
if(pQuote - 2 >= pTraverse) {
int iLength = pQuote - pTraverse;
pRetval = (char *)XP_ALLOC(iLength);
if(pRetval) {
memset(pRetval, 0, iLength);
int iCounter = 0;
while(pTraverse <= pQuote - 2) {
pRetval[iCounter] = *pTraverse;
pTraverse++;
iCounter++;
}
}
}
}
break;
}
}
}
else {
// end of string, just get out of the while loop.
break;
}
}
}
return(pRetval);
}
/****************************************************************************
*
* FEU_TransBlt
*
* PARAMETERS:
* pSrcDC - pointer to source DC (with selected image)
* pDstDC - pointer to destination DC (where image is to be drawn)
* ptSrc - source x,y coordinates
* ptDst - destination x,y coordinates
* nWidth - image width
* nHeight - image height
* rgbTrans - transparent (background) color = RGB(255, 0, 255)
*
* RETURNS:
* TRUE if successful.
*
* DESCRIPTION:
* This function is called to do a transparent BitBlt. The background
* or transparent color is given by rgbTrans, with the default being
* pink {RGB(255, 0, 255)}. Pixels of this color will be masked out, so
* that the image is drawn without disturbing the destination.
*
* Note that all masking operations are done in a memory DC to avoid
* flicker. pDstDC should be an actual screen DC.
*
****************************************************************************/
BOOL FEU_TransBlt(CDC * pSrcDC, CDC * pDstDC, const CPoint & ptSrc,
const CPoint & ptDst, int nWidth, int nHeight, HPALETTE hPalette,
const COLORREF rgbTrans /*= RGB(255, 0, 255)*/)
{
return FEU_TransBlt( pDstDC->m_hDC, ptDst.x, ptDst.y, nWidth, nHeight,
pSrcDC->m_hDC, ptSrc.x, ptSrc.y, hPalette, rgbTrans );
}
// More useful version that migrates more sanely from BitBlt.
BOOL FEU_TransBlt(HDC hDstDC, int nXDest, int nYDest, int nWidth, int nHeight,
HDC hSrcDC, int nXSrc, int nYSrc, HPALETTE hPalette, COLORREF rgbTrans )
{
BOOL bRtn = TRUE;
// We'll paint our bitmap using the "true mask" method for transparency.
// We assume a pre-designated color for the background (transparent) color,
// and create our monochrome mask at run time.
// Create mask for transparent blits
HPALETTE hOldPal = ::SelectPalette(hSrcDC, hPalette, FALSE);
// ::RealizePalette(hSrcDC);
HDC hMaskDC = ::CreateCompatibleDC(hDstDC);
HBITMAP hbmMask = ::CreateBitmap(nWidth, nHeight, 1, 1, NULL);
HBITMAP hOldMaskBmp = (HBITMAP) ::SelectObject(hMaskDC, hbmMask);
COLORREF rgbOldBk = ::SetBkColor(hSrcDC, rgbTrans);
::BitBlt(hMaskDC, 0, 0, nWidth, nHeight, hSrcDC, nXSrc, nYSrc, SRCCOPY);
::SetBkColor(hSrcDC, rgbOldBk);
::SelectPalette(hSrcDC, hOldPal, TRUE);
// First, copy the existing image from the destination to memory for
// flicker free painting.
HDC hMemDC = ::CreateCompatibleDC(hDstDC);
HBITMAP hbmMem = ::CreateCompatibleBitmap(hDstDC, nWidth, nHeight);
HBITMAP hOldMemBmp = (HBITMAP) ::SelectObject(hMemDC, hbmMem);
::BitBlt(hMemDC, 0, 0, nWidth, nHeight, hDstDC, nXDest, nYDest, SRCCOPY);
// Next, blit our bitmap, the mask, then our bitmap again to the memory
// DC using the proper raster ops.
COLORREF rgbOldTxt = ::SetTextColor(hMemDC, PALETTERGB(0, 0, 0));
rgbOldBk = SetBkColor(hMemDC, PALETTERGB(255, 255, 255));
::BitBlt(hMemDC, 0, 0, nWidth, nHeight, hSrcDC, nXSrc, nYSrc, SRCINVERT);
::BitBlt(hMemDC, 0, 0, nWidth, nHeight, hMaskDC, 0, 0, SRCAND);
::BitBlt(hMemDC, 0, 0, nWidth, nHeight, hSrcDC, nXSrc, nYSrc, SRCINVERT);
::SetTextColor(hMemDC, rgbOldTxt);
::SetBkColor(hMemDC, rgbOldBk);
// Finally, blit from memory DC back to the destination
bRtn = ::BitBlt(hDstDC, nXDest, nYDest, nWidth, nHeight, hMemDC, 0, 0,
SRCCOPY);
// Cleanup
::SelectObject(hMaskDC, hOldMaskBmp);
VERIFY(::DeleteDC(hMaskDC));
VERIFY(::DeleteObject(hbmMask));
::SelectObject(hMemDC, hOldMemBmp);
VERIFY(::DeleteDC(hMemDC));
VERIFY(::DeleteObject(hbmMem));
return(bRtn);
} // END OF FUNCTION FEU_TransBlt()
// This function create because no one knows how to use SetWindowPlacement
// correctly.
void FEU_InitWINDOWPLACEMENT(HWND hWindow, WINDOWPLACEMENT *pWindowPlacement)
{
// Safety
if(!pWindowPlacement) {
return;
}
// Thrash to zero.
memset(pWindowPlacement, 0, sizeof(WINDOWPLACEMENT));
// Set the length member.
pWindowPlacement->length = sizeof(WINDOWPLACEMENT);
// Safety
if(!hWindow) {
return;
}
// Initialize the structure with the current window settings.
BOOL bGotIt = ::GetWindowPlacement(hWindow, pWindowPlacement);
ASSERT(bGotIt);
// Hacker now free to change members that need to be changed without
// thrashing other stuff too.
}
// Mouse timer handler (to handle scrolling selections).
MouseTimerData::MouseTimerData(MWContext *pContext)
{
// By default treat as a context notification.
m_pContext = pContext;
m_pType = m_ContextNotify;
}
void FEU_MouseTimer(void *vpReallyMouseTimerData)
{
// Cast.
MouseTimerData *pData = (MouseTimerData *)vpReallyMouseTimerData;
// Decide what to do by type.
if(pData->m_pType == MouseTimerData::m_ContextNotify) {
// If the left button is down, we need to set up a timer to
// call the mouse move function again so that scrolling selections
// work correctly.
// GARRETT: PANECX will want the mouse stuff.
if(XP_IsContextInList(pData->m_pContext) &&
ABSTRACTCX(pData->m_pContext) &&
ABSTRACTCX(pData->m_pContext)->IsFrameContext()) {
CWinCX *pWinCX = WINCX(pData->m_pContext);
// Don't do autoscroll if left button isn't down and isn't
// already an timout registered.
if(pWinCX->m_bLBDown && !pWinCX->m_bScrollingTimerSet) {
// Set up the timer.
MouseTimerData *pLater = new MouseTimerData(pData->m_pContext);
if(pLater) {
// Manually set to be a timer notification.
pLater->m_pType = MouseTimerData::m_TimerNotify;
// Set that the context has a scrolling timeout event.
pWinCX->m_bScrollingTimerSet = TRUE;
// Set the timer to call us back in X number milliseconds.
FE_SetTimeout(FEU_MouseTimer, (void *)pLater, 100);
}
}
}
// Do not delete the passed in data.
// Up to the caller to do so.
}
else if(pData->m_pType == MouseTimerData::m_TimerNotify) {
// If the left button is still down, we need to act like a mouse
// move occurred on the context so scrolling selections work.
if(XP_IsContextInList(pData->m_pContext) &&
ABSTRACTCX(pData->m_pContext) &&
ABSTRACTCX(pData->m_pContext)->IsFrameContext()) {
CWinCX *pWinCX = WINCX(pData->m_pContext);
// We need to remove the previously allocated mouse data that
// we allocated ourselves.
delete pData;
if(pWinCX->m_bLBDown && pWinCX->m_bScrollingTimerSet) {
// Clear the scrolling timer flag (do before call or won't
// set another timeout).
pWinCX->m_bScrollingTimerSet = FALSE;
// This will set up another timer if needed.
BOOL bReturnImmediately = FALSE;
pWinCX->OnMouseMoveCX(pWinCX->m_uMouseFlags, pWinCX->m_cpMMove, bReturnImmediately);
if(bReturnImmediately) {
return;
}
}
}
}
}
/// Mouse timer handler (to handle moves outside the window.).
MouseMoveTimerData::MouseMoveTimerData(MWContext *pContext)
{
// By default treat as a context notification.
m_pContext = pContext;
}
void FEU_MouseMoveTimer(void *vpReallyMouseMoveTimerData)
{
// Cast.
MouseMoveTimerData *pData = (MouseMoveTimerData *)vpReallyMouseMoveTimerData;
if (!pData)
return;
if(XP_IsContextInList(pData->m_pContext) &&
ABSTRACTCX(pData->m_pContext) &&
ABSTRACTCX(pData->m_pContext)->IsFrameContext()) {
CWinCX *pWinCX = WINCX(pData->m_pContext);
if(!pWinCX->m_bMouseMoveTimerSet) {
// Set up the timer.
MouseMoveTimerData *pLater = new MouseMoveTimerData(pData->m_pContext);
if(pLater) {
// Set that the context has a mousemove timeout event.
pWinCX->m_bMouseMoveTimerSet = TRUE;
// Set the timer to call us back in X number milliseconds.
FE_SetTimeout(FEU_MouseMoveTimer, (void *)pLater, 200);
}
}
else {
POINT mp;
// get mouse position
::GetCursorPos(&mp);
if ((::WindowFromPoint(mp) != pWinCX->GetPane()) && !pWinCX->m_bLBDown) {
// We've moved outside the window. Stop looping the timer and
// send a simulated mousemove to the view.
delete pData;
::ScreenToClient(pWinCX->GetPane(), &mp);
BOOL bReturnImmediately = FALSE;
pWinCX->OnMouseMoveCX(pWinCX->m_uMouseFlags, mp, bReturnImmediately);
pWinCX->m_bMouseMoveTimerSet = FALSE;
}
else {
// We're still in the window. Set another timer.
FE_SetTimeout(FEU_MouseMoveTimer, (void *)pData, 200);
}
}
}
}
// Context wants to have idle processing check to see if any actions
// need be taken with it.
class MWContextList {
public:
MWContext *m_pContext;
MWContextList *m_pNext;
};
MWContextList *listIdleContexts = NULL;
void *timerIdleContexts = NULL;
#define IDLETIMEOUT 50
void idleTimer(void *pNULL)
{
timerIdleContexts = NULL;
if(FEU_DoIdleProcessing()) {
timerIdleContexts = FE_SetTimeout(idleTimer, NULL, IDLETIMEOUT);
}
}
void FEU_RequestIdleProcessing(MWContext *pContext)
{
// Make sure not already in list.
MWContextList *pTraverse = listIdleContexts;
while(pTraverse) {
if(pTraverse->m_pContext == pContext) {
// Already here, don't do it.
return;
}
pTraverse = pTraverse->m_pNext;
}
// Not in list, add to tail.
MWContextList *pNewEntry = new MWContextList();
if(pNewEntry) {
MWContextList **ppNext = &listIdleContexts;
while(*ppNext) {
ppNext = &((*ppNext)->m_pNext);
}
pNewEntry->m_pNext = NULL;
pNewEntry->m_pContext = pContext;
*ppNext = pNewEntry;
}
// If we don't have a timer, then start one up.
if(timerIdleContexts == NULL) {
timerIdleContexts = FE_SetTimeout(idleTimer, NULL, IDLETIMEOUT);
}
}
BOOL FEU_DoIdleProcessing()
{
// Check our list and do one action per context at a time.
// Remove the context from the list if no known action need be
// taken with it.
MWContextList *pEntry = listIdleContexts;
if(pEntry) {
// Do NOT use else ifs. Instead use "if(bNoAction &&" everywhere
// Must set bNoAction to FALSE after an action is taken.
BOOL bNoAction = TRUE;
// Context still valid?
// Could have been blown away since it registered.
if(bNoAction && XP_IsContextInList(pEntry->m_pContext)) {
// Front end or XP context (XP not handled).
// Do not check the destroyed flag here, or contexts never
// get really freed off, instead tighten the called code.
if(bNoAction && ABSTRACTCX(pEntry->m_pContext)) {
CAbstractCX *pCX = ABSTRACTCX(pEntry->m_pContext);
// Lastly is the don't care case, abstract only.
if(bNoAction) {
// Do an interrupt if needed.
if(bNoAction && pCX->m_bIdleInterrupt == TRUE) {
bNoAction = FALSE;
pCX->Interrupt();
}
// Check for nice reloading.
if(bNoAction && pCX->GetContext()->reSize) {
bNoAction = FALSE;
pCX->NiceReload();
}
// Check for self destruct.
if(bNoAction && pCX->m_bIdleDestroy == TRUE) {
bNoAction = FALSE;
pCX->NiceDestroyContext();
}
}
}
}
// Take it out of the list and free it since it's now idle.
if(bNoAction) {
// Removal from list.
listIdleContexts = pEntry->m_pNext;
// Removal from the universe.
delete pEntry;
}
}
// Return wether or not more entries exist (more time is needed).
return(listIdleContexts == NULL ? FALSE : TRUE);
}
// Function to handle client pull.
class ClientPullTimerData {
public:
MWContext *m_pContext;
URL_Struct *m_pUrl;
History_entry *m_pVerifyHistory;
int m_iFormatOut;
BOOL m_bCanInterrupt;
};
void FEU_ClientPull(MWContext *pContext, uint32 ulMilliseconds, URL_Struct *pUrl, int iFormatOut, BOOL bCanInterrupt)
{
BOOL bSetToPull = FALSE;
// Safety dance.
if(pUrl && pContext &&
ABSTRACTCX(pContext) &&
!ABSTRACTCX(pContext)->IsDestroyed()) {
CAbstractCX *pCX = ABSTRACTCX(pContext);
// If we've already got a client pull timeout for the context, we
// should clear it (only want one of these at any given time).
void *pClearMe = pCX->m_pClientPullTimeout;
if(pClearMe) {
pCX->m_pClientPullTimeout = NULL;
FE_ClearTimeout(pClearMe);
}
// Same for the timeout's argument pointer, but it can be non-null
// even when the timeout pointer was null (if FEU_ClientPullNow
// calls us directly to try again in a second, and then returns
// early without deleting pData or clearing m_pClientPullData).
// Instead of freeing it and then immediately allocating a new one,
// just reuse it, but take care further below to clear pCX's
// pointer to it before deleting it, if FE_SetTimeout fails.
ClientPullTimerData *pData =
(ClientPullTimerData *)pCX->m_pClientPullData;
if(!pData) {
// Create a new client pull structure.
pData = new ClientPullTimerData();
}
if(pData) {
// Fill in the timer data.
pData->m_pContext = pCX->GetContext();
pData->m_pUrl = pUrl;
pData->m_pVerifyHistory = pCX->GetContext()->hist.cur_doc_ptr;
pData->m_iFormatOut = iFormatOut;
pData->m_bCanInterrupt = bCanInterrupt;
// Tell the context about it.
// Register the timeout.
pCX->m_pClientPullTimeout =
FE_SetTimeout(FEU_ClientPullNow, (void *)pData, ulMilliseconds);
// Looks like this will work.
if(pCX->m_pClientPullTimeout) {
pCX->m_pClientPullData = (void *)pData;
bSetToPull = TRUE;
}
else {
pCX->m_pClientPullData = NULL;
delete pData;
}
}
}
if(!bSetToPull && pUrl) {
// Can't do client pull on this context.
NET_FreeURLStruct(pUrl);
}
}
void FEU_ClientPullNow(void *vpReallyClientPullTimerData)
{
ClientPullTimerData *pData = (ClientPullTimerData *)vpReallyClientPullTimerData;
BOOL bPulledUrl = FALSE;
// Is the context still around?
if(XP_IsContextInList(pData->m_pContext) &&
ABSTRACTCX(pData->m_pContext) &&
!ABSTRACTCX(pData->m_pContext)->IsDestroyed()) {
CAbstractCX *pCX = ABSTRACTCX(pData->m_pContext);
// There must not be more than one pull timeout pending!
XP_ASSERT(pData == pCX->m_pClientPullData);
// We are called only via FE_SetTimeout, so clear this pointer now
// before it dangles at free memory.
pCX->m_pClientPullTimeout = NULL;
// Are we on the same history entry?
if(pCX->GetContext()->hist.cur_doc_ptr == pData->m_pVerifyHistory) {
// Client pull isn't allowed to interrupt.
if(!pData->m_bCanInterrupt && XP_IsContextBusy(pCX->GetContext())) {
// Try again in a second.
FEU_ClientPull(pCX->GetContext(), 1000, pData->m_pUrl, pData->m_iFormatOut, FALSE);
// Old data, if present, freed in FEU_ClientPull.
// We can not continue, as the old data may now be gone,
// and we look at the old timer pull data further below.
return;
}
// Clear the members in the context before load,
// as they may be set again instantly and we
// get a double free below.
pCX->m_pClientPullData = NULL;
// Ask for it now.
pCX->GetUrl(pData->m_pUrl, pData->m_iFormatOut);
// Set that we've requested it.
bPulledUrl = TRUE;
}
else {
// Clear m_pClientPullData because we're about to free pData.
pCX->m_pClientPullData = NULL;
}
}
if(!bPulledUrl) {
// Free off the URL struct ourselves.
NET_FreeURLStruct(pData->m_pUrl);
}
// Free off the timer data.
delete pData;
}
// Cause the global history to be saved periodically.
void FEU_GlobalHistoryTimeout(void *pNULL)
{
// Set the next timeout.
FE_SetTimeout(FEU_GlobalHistoryTimeout, NULL, 120000UL);
// Flush it, if not first call.
if(!pNULL) {
GH_SaveGlobalHistory();
}
}
// This routine will return the handle of the pop-up menu whose first
// menu item has the specified command ID
HMENU FEU_FindSubmenu(HMENU hMenu, UINT nFirstCmdID)
{
int nCount = ::GetMenuItemCount(hMenu);
for (int i = 0; i < nCount; i++) {
HMENU hSubmenu = ::GetSubMenu(hMenu, i);
if (hSubmenu && (::GetMenuItemID(hSubmenu, 0) == nFirstCmdID))
return hSubmenu;
}
return NULL;
}
char *pTipText = NULL;
// Get a resource string and extract the tooltip portion
// if a '\n' is found in the string
// USE RESULT QUICKLY!
// (String is in our temp buffer and should not be FREEd)
char * FEU_GetToolTipText( UINT nID )
{
pTipText = szLoadString(nID);
if( ! *pTipText ){
return NULL;
}
// Scan for the '\n' separating status line hints from
// the tooltip text - use latter if found
char *pTemp = pTipText;
do {
if( *pTemp == '\n' && *(pTemp+1) != '\0' ){
pTipText = pTemp+1;
// Find a second "\n" and terminate string there
char * pBreak = strchr(pTipText, '\n');
if( pBreak )
*pBreak = '\0';
break;
}
pTemp++;
} while( *pTemp != '\0' );
return pTipText;
}
char *FE_FindFileExt(char * path)
{
char *pRetval = NULL;
if(path) {
int len = strlen(path);
char *ptr = path + len - 1;
while ((*ptr != '.') && (len > 0)) {
len--;
if (len > 0) ptr--;
}
if (len > 0) {
pRetval = ptr;
}
}
return(pRetval);
}
void FE_LongNameToDosName(char* dest, char* source)
{
ASSERT(dest && source);
if(dest) {
*dest = '\0';
if(source) {
char *ext = FE_FindFileExt(source);
if (ext && (ext - source) > 8) {
// the Name is > dos file name
strncpy(dest, source, 8);
strncpy(&dest[8],ext, 4);
dest[12] = '\0';
}
else {
strcpy(dest, source);
}
}
}
}
// This function will return FALSE, if we do not want to use the default type that libnet provide.
BOOL FE_FileType(char * path,
char * mimeType,
char * encoding)
{
// try to get the extension from the end of the string.
char *ext = FE_FindFileExt(path);
if (ext) {
ext++; // move pass the '.';
NET_cdataStruct *cdata;
XP_List * list_ptr;
list_ptr = cinfo_MasterListPointer();
while((cdata = (NET_cdataStruct *) XP_ListNextObject(list_ptr)) != NULL)
{
if(cdata->ci.type && !strcasecomp(mimeType, cdata->ci.type)){
for (int i = 0; i < cdata->num_exts; i++) {
if (strcasecomp(ext, cdata->exts[i]) == 0)
return TRUE;
}
}
}
}
return FALSE;
}
BOOL FEU_IsConferenceAvailable(void)
{
CString install;
#ifdef WIN32
install = FEU_GetInstallationDirectory(szLoadString(IDS_CONFERENCE_REGISTRY), szLoadString(IDS_PATHNAME));
#else ifdef XP_WIN16
install = FEU_GetInstallationDirectory(szLoadString(IDS_CONFERENCE),szLoadString(IDS_INSTALL_DIRECTORY));
#endif
return (!install.IsEmpty());
}
BOOL FEU_IsCalendarAvailable(void)
{
#ifdef _WIN32
CString calRegistry;
calRegistry.LoadString(IDS_CALENDAR_REGISTRY);
calRegistry = FEU_GetCurrentRegistry(calRegistry);
if(calRegistry.IsEmpty())
return FALSE;
CString install = FEU_GetInstallationDirectory(calRegistry, szLoadString(IDS_INSTALL_DIRECTORY));
#else
CString install = FEU_GetInstallationDirectory(szLoadString(IDS_CALENDAR), szLoadString(IDS_INSTALL_DIRECTORY));
#endif
return (!install.IsEmpty());
}
BOOL FEU_IsIBMHostOnDemandAvailable(void)
{
#ifdef _WIN32
CString ibmHostRegistry;
ibmHostRegistry.LoadString(IDS_3270_REGISTRY);
ibmHostRegistry = FEU_GetCurrentRegistry(ibmHostRegistry);
if(ibmHostRegistry.IsEmpty())
return FALSE;
CString install = FEU_GetInstallationDirectory(ibmHostRegistry, szLoadString(IDS_INSTALL_DIRECTORY));
#else
CString install = FEU_GetInstallationDirectory(szLoadString(IDS_3270), szLoadString(IDS_INSTALL_DIRECTORY));
#endif
return (!install.IsEmpty());
}
BOOL FEU_IsAimAvailable(void)
{
BOOL success = FALSE;
char szPath[_MAX_PATH + 1];
char shortPath[_MAX_PATH + 1];
CString install("");
unsigned long cbData = sizeof(szPath);
#ifdef _WIN32
CString aimRegistry;
aimRegistry.LoadString(IDS_AIM_REGISTRY);
HKEY aimKey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, aimRegistry, 0, KEY_QUERY_VALUE, &aimKey) != ERROR_SUCCESS)
return FALSE;
success = (RegQueryValueEx(aimKey, 0, NULL, NULL, (LPBYTE) szPath, &cbData) == ERROR_SUCCESS);
GetShortPathName(szPath, shortPath, _MAX_PATH+1);
install = shortPath;
RegCloseKey(aimKey);
#endif // _WIN32
#ifdef XP_WIN16
// Do the right thing
GetPrivateProfileString("InstallRoot", "Path", "none", szPath, cbData, "aim.ini");
install = szPath;
if (install != "none")
{
success = TRUE;
install = install + "\\aim.exe";
}
#endif // XP_WIN16
if (success)
{
char szKey[_MAX_EXT + 1]; // space for '.'
char szClass[128];
LONG lResult;
LONG lcb;
// Look up the file association key which maps a file extension
// to a file class
wsprintf(szKey, ".%s", "aim");
lcb = sizeof(szClass);
lResult = RegQueryValue(HKEY_CLASSES_ROOT, szKey, szClass, &lcb);
#ifdef _WIN32
ASSERT(lResult != ERROR_MORE_DATA);
#endif
if (lResult != ERROR_SUCCESS || lcb <= 1)
{
// Configure the MIME type, download prompt, etc. etc.
NET_cdataStruct *launchData = fe_NewFileType("AOL Instant Messenger Launch",
"aim",
"application/x-aim",
install); // Create and register the file type
CHelperApp *pHelperApp = (CHelperApp *)launchData->ci.fe_data;
pHelperApp->how_handle = HANDLE_SHELLEXECUTE;
}
else
{
// The key exists but the application may be stale, i.e., it may have changed
// on us. Just write out the current path to the aimfile key.
SetShellOpenCommand("aimfile", install);
}
// Always write out the defaulticon info for Win32, since the AIM app may have moved.
#ifdef _WIN32
CString iconPath = install + ",0";
HKEY iconKey;
if (RegCreateKey(HKEY_CLASSES_ROOT, "aimfile\\DefaultIcon", &iconKey) ==
ERROR_SUCCESS)
{
RegSetValue(iconKey, "", REG_SZ, iconPath, iconPath.GetLength());
RegCloseKey(iconKey);
}
#endif // _WIN32
CString profileLaunch = theApp.m_UserDirectory + "\\launch.aim";
FILE* fp = fopen(profileLaunch, "r");
if (fp == NULL)
{
// Need to create launch.aim file in the user's dir.
fp = fopen(profileLaunch, "w");
fprintf(fp, "DWH\n");
fclose(fp);
// Need to add to personal toolbar
CString convLaunch;
WFE_ConvertFile2Url(convLaunch, profileLaunch);
CString aimName;
aimName.LoadString(ID_WINDOW_AIM);
/* MUST CONVERT AIM BOOKMARK CREATION TO AURORA (Dave H.)
BM_Entry* newBookmark = BM_NewUrl(aimName, convLaunch, NULL, NULL);
theApp.GetLinkToolbarManager().InitializeToolbarHeader();
BM_Entry* pRoot = theApp.GetLinkToolbarManager().GetToolbarHeader();
if (pRoot != NULL)
BM_PrependChildToHeader(theApp.m_pBmContext, pRoot, newBookmark);
*/
}
else fclose(fp);
}
return success;
}
void FEU_OpenAim(void)
{
char szPath[_MAX_PATH + 1];
char shortPath[_MAX_PATH + 1];
CString install("none");
unsigned long cbData = sizeof(szPath);
#ifdef _WIN32
CString aimRegistry;
aimRegistry.LoadString(IDS_AIM_REGISTRY);
HKEY aimKey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, aimRegistry, 0, KEY_QUERY_VALUE, &aimKey) != ERROR_SUCCESS)
return;
if (RegQueryValueEx(aimKey, 0, NULL, NULL, (LPBYTE) szPath, &cbData) == ERROR_SUCCESS)
{
RegCloseKey(aimKey);
#ifdef _WIN32
GetShortPathName(szPath, shortPath, _MAX_PATH+1);
install = shortPath;
#else
install = szPath;
#endif
}
else return;
#endif // _WIN32
#ifdef XP_WIN16
// Do the right thing
GetPrivateProfileString("InstallRoot", "Path", "none", szPath, cbData, "aim.ini");
install = szPath;
if (install == "none")
return;
install = install + "\\aim.exe";
#endif // XP_WIN16
WinExec(install, SW_SHOW);
}
void FEU_OpenNetcaster(void)
{
#ifdef JAVA
if(FEU_IsNetcasterAvailable() == FALSE) {
MessageBox(NULL, XP_GetString(XP_ALERT_CANT_RUN_NETCASTER), szLoadString(AFX_IDS_APP_TITLE), MB_OK | MB_ICONEXCLAMATION);
return;
}
if(!theApp.m_pNetcasterWindow) {
Chrome netcasterChrome;
URL_Struct* URL_s, *splashURL_s;
MWContext *netcasterContext;
REGERR regErr = REGERR_FAIL;
char netcasterURL[300] = "";
char netcasterSplashURL[300] = "";
// First, get the URL
/* Due to a bug using the Windows Registry to detect Netcaster
installation with both Ratbert and Dogbert installed, we
need check the XP registry first. If success, use that. If
failure (due to a bug), use Windows. If both are installed
to unique locations and then one of them deleted, Windows
will return false, but the XP code should save our butts in
95% of the cases by returning true.
BTW, this code needs to be componentized more. Since today
is code freeze, I cut and posted code below to preserve existing
code paths. This code should be better organized for 4.03.
*/
#ifdef XP_WIN32
regErr = VR_GetPath("Netcaster/tab.htm", 300, netcasterURL);
VR_Close();
if (regErr != REGERR_OK) {
CString netcaster = "Software\\Netscape\\Netcaster\\";
netcaster = FEU_GetCurrentRegistry(netcaster);
if(netcaster.IsEmpty()) {
regErr = 3 ;
} else {
CString install = FEU_GetInstallationDirectory(netcaster, szLoadString(IDS_INSTALL_DIRECTORY));
if(install.IsEmpty()) {
regErr = 3 ;
} else {
strcpy(netcasterURL,install.GetBuffer(300));
XP_STRCAT(netcasterURL, "\\tab.htm") ;
strcpy(netcasterSplashURL,install.GetBuffer(300));
XP_STRCAT(netcasterSplashURL, "\\ncsplash.htm") ;
regErr = REGERR_OK ;
}
}
} else {
REGERR splashErr;
splashErr = VR_GetPath("Netcaster/ncsplash.htm", 300, netcasterSplashURL);
VR_Close();
if (splashErr != REGERR_OK) {
CString netcaster = "Software\\Netscape\\Netcaster\\";
netcaster = FEU_GetCurrentRegistry(netcaster);
if(!netcaster.IsEmpty()) {
CString install = FEU_GetInstallationDirectory(netcaster, szLoadString(IDS_INSTALL_DIRECTORY));
if(!install.IsEmpty()) {
strcpy(netcasterSplashURL,install.GetBuffer(300));
XP_STRCAT(netcasterSplashURL, "\\ncsplash.htm") ;
}
}
}
}
#else
regErr = VR_GetPath("Netcaster/tab.htm", 300, netcasterURL);
VR_Close();
#endif
if (regErr == REGERR_OK) {
BOOL javaEnabled = FALSE;
#if defined(OJI)
JVMMgr* jvmMgr = JVM_GetJVMMgr();
if (jvmMgr) {
NPIJVMPlugin* jvm = jvmMgr->GetJVM();
if (jvm) {
javaEnabled = jvm->GetJVMEnabled();
jvm->Release();
}
jvmMgr->Release();
}
#elif defined(JAVA)
javaEnabled = LJ_GetJavaEnabled();
#endif
// Now check to see if Java and JS are enabled
if (!LM_GetMochaEnabled() || !javaEnabled) {
MessageBox(NULL, XP_GetString(XP_ALERT_NETCASTER_NO_JS), szLoadString(AFX_IDS_APP_TITLE), MB_OK | MB_ICONEXCLAMATION);
return;
}
// First, bring up the splash screen, if it exists
#ifdef XP_WIN32
if (XP_STRLEN(netcasterSplashURL) > 0) {
MWContext *newContext;
memset(&netcasterChrome, 0, sizeof(Chrome));
netcasterChrome.type = MWContextBrowser;
netcasterChrome.w_hint = 400;
netcasterChrome.h_hint = 150;
netcasterChrome.l_hint = 100;
netcasterChrome.t_hint = 100;
netcasterChrome.topmost = FALSE;
netcasterChrome.z_lock = FALSE;
netcasterChrome.location_is_chrome = TRUE;
netcasterChrome.disable_commands = TRUE;
netcasterChrome.hide_title_bar = FALSE;
netcasterChrome.restricted_target = TRUE;
netcasterChrome.allow_close = TRUE;
netcasterChrome.show_bottom_status_bar = FALSE;
splashURL_s = NET_CreateURLStruct(netcasterSplashURL, NET_DONT_RELOAD);
newContext = FE_MakeNewWindow(NULL,
splashURL_s,
"Netcaster_Splash",
&netcasterChrome);
}
#endif
memset(&netcasterChrome, 0, sizeof(Chrome));
netcasterChrome.w_hint = 22;
netcasterChrome.h_hint = 55;
netcasterChrome.l_hint = -300;
netcasterChrome.t_hint = 0;
netcasterChrome.topmost = TRUE;
netcasterChrome.z_lock = TRUE;
netcasterChrome.location_is_chrome = TRUE;
netcasterChrome.disable_commands = TRUE;
netcasterChrome.hide_title_bar = TRUE;
netcasterChrome.restricted_target = TRUE;
netcasterChrome.allow_close = TRUE;
URL_s = NET_CreateURLStruct(netcasterURL, NET_DONT_RELOAD);
netcasterContext = FE_MakeNewWindow(NULL,
URL_s,
"Netcaster_SelectorTab",
&netcasterChrome);
theApp.m_pNetcasterWindow = netcasterContext ;
} else {
MessageBox(NULL, XP_GetString(XP_ALERT_CANT_RUN_NETCASTER), szLoadString(AFX_IDS_APP_TITLE), MB_OK | MB_ICONEXCLAMATION);
}
} else {
if(! ABSTRACTCX(theApp.m_pNetcasterWindow) || ! ABSTRACTCX(theApp.m_pNetcasterWindow)->IsFrameContext() ) {
MessageBox(NULL, XP_GetString(XP_ALERT_CANT_RUN_NETCASTER), szLoadString(AFX_IDS_APP_TITLE), MB_OK | MB_ICONEXCLAMATION);
return;
} else {
// We are running, so give us focus...
//theApp.m_pNetcasterWindow->fe.cx->SetFocus() ;
if((theApp.m_pNetcasterWindow->fe.cx->IsFrameContext() == TRUE)) {
CWinCX *pWinCX = VOID2CX(theApp.m_pNetcasterWindow->fe.cx, CWinCX);
if (!pWinCX)
return ;
HWND hwnd = pWinCX->GetPane() ;
if (IsWindow(hwnd))
SetFocus(hwnd) ;
}
}
}
#endif /* JAVA */
}
BOOL FEU_IsNetcasterAvailable(void)
{
#ifdef JAVA
#ifdef XP_WIN32
/* Due to a bug using the Windows Registry to detect Netcaster
installation with both Ratbert and Dogbert installed, we
need check the XP registry first. If success, use that. If
failure (due to a bug), use Windows. If both are installed
to unique locations and then one of them was deleted, Windows
will return false, but the XP code should save our butts in
95% of the cases by returning true.
*/
CString netcaster = "Software\\Netscape\\Netcaster\\";
if (VR_InRegistry("Netcaster") == REGERR_OK) {
// The registry may be invalid since the user can delete
// the files. Check to see if one of the files exists.
// I believe this checks file existence too....
int rc = VR_ValidateComponent("Netcaster/tab.htm") ;
if (rc == REGERR_OK) {
VR_Close();
return (TRUE) ;
}
}
VR_Close();
/*
begin Windows code check
*/
netcaster = FEU_GetCurrentRegistry(netcaster);
if(netcaster.IsEmpty())
return FALSE;
CString install = FEU_GetInstallationDirectory(netcaster, szLoadString(IDS_INSTALL_DIRECTORY));
if (!install.IsEmpty()) {
// stat the directory first
struct _stat buf;
int result;
/* Get data associated with "stat.c": */
result = _stat( install.GetBuffer(256), &buf );
/* Check if statistics are valid: */
if( result != 0 )
return FALSE;
return (TRUE);
}
#endif
#endif /* JAVA */
return (FALSE);
}
void FE_ConvertSpace(char *newName)
{
char *p;
p = newName;
if (strchr(p, '%')) {
for(p = newName; *p; p++) {
if ((*p == '%') && (*(p+1) == 0x32) && (*(p+2) == 0x30)) {
*p = ' ';
strcpy(p+1, p+3);
}
}
}
}
#ifdef XP_WIN32
CString FEU_GetCurrentRegistry(const CString &componentString)
{
HKEY hKey;
LONG lResult;
char szPath[_MAX_PATH + 1];
CString currentVersion, main, currentRegString("");
currentVersion.LoadString(IDS_CURRENTVERSION);
main.LoadString(IDS_MAIN);
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, componentString, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {
unsigned long cbData = sizeof(szPath);
lResult = RegQueryValueEx(hKey, currentVersion, NULL, NULL, (LPBYTE) szPath, &cbData);
RegCloseKey(hKey);
if(lResult == ERROR_SUCCESS)
{
currentRegString = componentString + szPath;
currentRegString = currentRegString + main;
}
}
return currentRegString;
}
#endif
CString FEU_GetInstallationDirectory(const CString &productString, const CString &installationString)
{
#ifdef _WIN32
HKEY hKey;
LONG lResult;
char szPath[_MAX_PATH + 1];
CString install("");
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, productString, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {
unsigned long cbData = sizeof(szPath);
lResult = RegQueryValueEx(hKey, installationString, NULL, NULL, (LPBYTE) szPath, &cbData);
RegCloseKey(hKey);
if(lResult == ERROR_SUCCESS)
install = szPath;
}
return install;
#else ifdef XP_WIN16
char szPath[_MAX_PATH + 1];
const char *pOldProfile = theApp.m_pszProfileName;
UINT nSize = GetWindowsDirectory(szPath, _MAX_PATH + 1);
XP_STRCPY(szPath + nSize, szLoadString(IDS_NSCPINI));
theApp.m_pszProfileName = szPath;
CString version = theApp.GetProfileString(productString, szLoadString(IDS_CURRENTVERSION), NULL);
if(version.IsEmpty())
{
theApp.m_pszProfileName = pOldProfile;
return version;
}
CString currentVersion = "-" + version;
currentVersion = productString + currentVersion;
CString install = theApp.GetProfileString(currentVersion, installationString, NULL);
theApp.m_pszProfileName = pOldProfile;
return install;
#endif
}
// Send/Post a message to all top level frames in our app.
void FEU_FrameBroadcast(BOOL bSend, UINT Msg, WPARAM wParam, LPARAM lParam)
{
// Go through list of frames.
for(CGenericFrame *pFrame = theApp.m_pFrameList;
pFrame != NULL;
pFrame = pFrame->m_pNext) {
if(pFrame->GetSafeHwnd()) {
if(bSend) {
pFrame->SendMessage(Msg, wParam, lParam);
}
else {
pFrame->PostMessage(Msg, wParam, lParam);
}
}
}
// Get the hidden one too.
if(theApp.m_pMainWnd && theApp.m_pMainWnd->GetSafeHwnd()) {
if(bSend) {
theApp.m_pMainWnd->SendMessage(Msg, wParam, lParam);
}
else {
theApp.m_pMainWnd->PostMessage(Msg, wParam, lParam);
}
}
}
void FEU_AltMail_ShowMailBox(void)
{
if(theApp.m_bInitMapi)
{
if(theApp.m_fnOpenMailSession)
{
POSTCODE status = (*theApp.m_fnOpenMailSession) (NULL, NULL);
if(status == POST_OK)
theApp.m_bInitMapi = FALSE;
else
return;
}
}
if(theApp.m_fnShowMailBox)
(*theApp.m_fnShowMailBox) ();
}
void FEU_AltMail_ShowMessageCenter(void)
{
if(theApp.m_bInitMapi)
{
if(theApp.m_fnOpenMailSession)
{
POSTCODE status = (*theApp.m_fnOpenMailSession) (NULL, NULL);
if(status == POST_OK)
theApp.m_bInitMapi = FALSE;
else
return;
}
}
if(theApp.m_fnShowMessageCenter)
(*theApp.m_fnShowMessageCenter) ();
}
//Modify communicators menu with alt mail specified menu
//Remove menu item if pszAltMailMenuStr is empty
void FEU_AltMail_ModifyMenu(CMenu* pMenuCommunicator, UINT uiCommunicatorMenuID, LPCSTR pszAltMailMenuStr)
{
if(*pszAltMailMenuStr)
{
CString csNewMenuStr;
#ifdef XP_WIN32
if(pMenuCommunicator->GetMenuString(uiCommunicatorMenuID, csNewMenuStr, MF_BYCOMMAND))
#else
if(pMenuCommunicator->GetMenuString(uiCommunicatorMenuID, csNewMenuStr.GetBuffer(256), 256, MF_BYCOMMAND))
#endif
{
#ifdef XP_WIN16
csNewMenuStr.ReleaseBuffer();
#endif
int iPos;
if((iPos = csNewMenuStr.Find('\t')) != -1)
{
//Accelerator present. Add it to the end of AltMail menu string
CString csAccel = csNewMenuStr.Right(csNewMenuStr.GetLength() - iPos);
csNewMenuStr = pszAltMailMenuStr + csAccel;
}
else //No accelerator. use alt mail str as is
csNewMenuStr = pszAltMailMenuStr;
pMenuCommunicator->ModifyMenu(uiCommunicatorMenuID, MF_BYCOMMAND, uiCommunicatorMenuID, csNewMenuStr);
}
}
else
pMenuCommunicator->RemoveMenu(uiCommunicatorMenuID, MF_BYCOMMAND);
}
//Modify "Messenger MailBox" and "Message Center" menu items
//to strings supplied by the AltMail DLL
void FEU_AltMail_SetAltMailMenus(CMenu* pMenuCommunicator)
{
char szAltMailMenuStr[_MAX_PATH];
szAltMailMenuStr[0] = '\0';
if(POST_OK == (*theApp.m_fnGetMenuItemString)(ALTMAIL_MenuMailBox, szAltMailMenuStr, _MAX_PATH))
FEU_AltMail_ModifyMenu(pMenuCommunicator, ID_TOOLS_INBOX, szAltMailMenuStr);
szAltMailMenuStr[0] = '\0';
if(POST_OK == (*theApp.m_fnGetMenuItemString)(ALTMAIL_MenuMessageCenter, szAltMailMenuStr, _MAX_PATH))
FEU_AltMail_ModifyMenu(pMenuCommunicator, ID_TOOLS_MAIL, szAltMailMenuStr);
}
BOOL FEU_Execute(MWContext *pContext, const char *pCommand, const char *pParams)
{
BOOL bRetval = TRUE;
BOOL bHandled = FALSE;
HINSTANCE hSpawn = (HINSTANCE)2; // 2 is application not found.
if(bHandled == FALSE) {
hSpawn = ShellExecute(NULL, NULL, pCommand, pParams, NULL, SW_SHOW);
if((int)hSpawn == 2 && pCommand && pParams) {
// Failure, Application not found.
// Some legacy helpers (netscape viewers section of preferences)
// specify switches in the pCommand such that ShellExecute
// fails. Re-attempt with WinExec to see if it works
// correctly (CyberCash, Norton Anti-Virus).
// Both command and params are specified in this scenario.
CString csCommand = CString(pCommand) + " " + CString(pParams);
hSpawn = (HINSTANCE)WinExec(csCommand, SW_SHOW);
}
bHandled = TRUE;
}
if((int)hSpawn < 32) {
bRetval = FALSE;
char szMsg[80];
switch((int)hSpawn) {
case 0:
case 8:
sprintf(szMsg, szLoadString(IDS_WINEXEC_0_8));
break;
case 2:
case 3:
sprintf(szMsg, szLoadString(IDS_WINEXEC_2_3));
break;
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
sprintf(szMsg, szLoadString(IDS_WINEXEC_10_THRU_15));
break;
case 16:
sprintf(szMsg, szLoadString(IDS_WINEXEC_16));
break;
case 21:
sprintf(szMsg, szLoadString(IDS_WINEXEC_21));
break;
default:
sprintf(szMsg, szLoadString(IDS_WINEXEC_XX), (UINT)hSpawn);
break;
}
FE_Alert(pContext, szMsg);
}
return(bRetval);
}
/*///////////////////////////////////////////////////////////////////////
// Find the executable which will handle the filename. //
// Retval BOOL: Wether or not an executable was found. //
// pFileName: The content to be executed. //
// pExecutable: Buffer to hold the name of executable if found. //
// bIdentity: Wether or not the pFileName can be the pExecutable. //
// bExtension: Whether or not pFileName is actually an extension. //
///////////////////////////////////////////////////////////////////////*/
BOOL FEU_FindExecutable(const char *pFileName, char *pExecutable, BOOL bIdentity, BOOL bExtension) {
BOOL bRetval = FALSE;
BOOL bFound = FALSE;
BOOL bFreeFileName = FALSE;
char aViewer[_MAX_PATH];
memset(aViewer, 0, sizeof(aViewer));
// pFileName may not be a file name, but an extension.
// We want to support just extensions for ease, so check on it.
if(bExtension && pFileName) {
// Do we need to add a period?
char aExt[_MAX_EXT];
if(*pFileName != '.') {
aExt[0] = '.';
aExt[1] = '\0';
strcat(aExt, pFileName);
pFileName = aExt;
}
// Fill out the rest of the name.
bFreeFileName = TRUE;
pFileName = (const char *)WH_TempFileName(xpTemporary, "G", pFileName);
}
if(!bFound && pFileName && *pFileName) {
// Does pFileName actually exists, if not we will need to
// create it temporarily so that ::FindExecutable will work.
BOOL bCreatedFile = FALSE;
if(_access(pFileName, 00) != 0) {
HFILE hCreate = _lcreat(pFileName, 0);
if(hCreate != HFILE_ERROR) {
bCreatedFile = TRUE;
_lclose(hCreate);
}
}
HINSTANCE hRet = FindExecutable(pFileName, NULL, aViewer);
if((int)hRet > 32) {
// Found a viewer.
bFound = TRUE;
}
/* Cleanup */
if(bCreatedFile) {
_unlink(pFileName);
}
}
// Do we fill in the return value?
// Note that we fill it in regardless of the bIdentity flag.
if(pExecutable) {
strcpy(pExecutable, aViewer);
}
// Decide return value based on bIdentity if an EXE found.
if(bFound) {
if(bIdentity) {
bRetval = TRUE;
}
else {
// Must make sure executable and filename are not the
// same.
// Do a case insensitive comparison.
char *pCompareFile = (char *)pFileName;
char *pCompareExe = (char *)aViewer;
#ifdef XP_WIN32
// On win32, we compare short names to avoid any confusion.
char aShortFile[_MAX_PATH];
char aShortExe[_MAX_PATH];
memset(aShortFile, 0, sizeof(aShortFile));
memset(aShortExe, 0, sizeof(aShortExe));
GetShortPathName(pCompareFile, aShortFile, sizeof(aShortFile));
GetShortPathName(pCompareExe, aShortExe, sizeof(aShortFile));
pCompareFile = aShortFile;
pCompareExe = aShortExe;
#endif
// Case insensitive comparison.
if(stricmp(pCompareFile, pCompareExe)) {
// Not the same.
bRetval = TRUE;
}
}
}
if(bFreeFileName && pFileName) {
XP_FREE((void *)pFileName);
pFileName = NULL;
}
return(bRetval);
}
// Return TRUE if the given path points to an existing
// directory. Attempt to create the directory if we can
BOOL FEU_SanityCheckDir(const char * dir)
{
int ret;
XP_StatStruct statinfo;
ret = _stat((char *) dir, &statinfo);
if(ret == -1) {
// see if we can just create it
#ifdef __WATCOMC__
ret = mkdir(dir);
#else
ret = _mkdir(dir);
#endif
// still couldn't create it
if(ret == -1)
return(FALSE);
}
return(TRUE);
}
// Return TRUE if the given file has a valid path
BOOL FEU_SanityCheckFile(const char * file)
{
int ret;
XP_StatStruct statinfo;
ret = _stat((char *) file, &statinfo);
if(ret == -1)
return(FALSE);
else
return(TRUE);
}
void FEU_DeleteUrlData(URL_Struct *pUrl, MWContext *pCX) {
// A Url is about to be removed.
// Clean up any extra stuff that we know about but Netlib doesn't.
if(pUrl->ncapi_data != NULL) {
CNcapiUrlData *pUrlData = (CNcapiUrlData *)pUrl->ncapi_data;
delete pUrlData;
}
}
BOOL FEU_IsNetscapeFrame(CWnd* pFocusWnd)
{
if (pFocusWnd->IsKindOf(RUNTIME_CLASS(CGenericView)))
return TRUE;
else if (pFocusWnd->IsKindOf(RUNTIME_CLASS(CGenericFrame)))
return TRUE;
#ifdef MOZ_MAIL_NEWS
else if (pFocusWnd->IsKindOf(RUNTIME_CLASS(CMsgListFrame)))
return TRUE;
#endif /* MOZ_MAIL_NEWS */
// else if (pFocusWnd->IsKindOf(RUNTIME_CLASS(CNSToolbar2)))
// return TRUE;
else return FALSE;
}
BOOL CALLBACK WinEnumProc(HWND hwnd, LPARAM lParam)
{
// check to see if the Windows title is "Netscape's Hidden Frame"
char winText[256];
if (GetWindowText(hwnd, winText, sizeof(winText)) != 0)
{
if (lstrcmpi(winText, "Netscape's Hidden Frame") == 0)
{
*((HWND*)lParam) = hwnd;
return(FALSE);
}
}
return(TRUE);
}
extern "C"
HWND FindNavigatorHiddenWindow(void)
{
// find Navigator's hidden frame
HWND hWnd = NULL;
EnumWindows(WinEnumProc, (LPARAM)&hWnd);
return(hWnd);
}
//Used to determine initialization action. If we detect a previous instance
//and it is in the middle of initializing, find out how far along it is by
//looking for it's hidden frame. If the previous instance has a hidden frame
//then we return TRUE and alow the second instance to DDE to the first. If it
//doesn't have a hidden frame, we wait for 10 seconds in the case that the first
//and the second instance started at nearly the same time. Thus, giving the first
//instance a chance to create it's hidden frame and allowing the second instance
//to open a successful DDE conversation to the first instance.
//This function should be called from InitInstance prior to the Initialization of
//the NetscapeSlaveClass. This call is only need for win32. This same call
//will be made for win16 but from the NAVSTART.EXE application.
#ifdef XP_WIN32
BOOL BailOrStay(void)
{
if (FindWindow("NetscapeSlaveClass",NULL))
{
if (!FindNavigatorHiddenWindow())
{
Sleep(10000);//give the first instance a chance to start
if(!FindNavigatorHiddenWindow()) //If it's not present yet we just exit.
{ //First instance is probably running the profile manager.
return FALSE;
}
}
}
return TRUE;
}
#endif
// Do not change the current drive to a floppy.
BOOL FEU_GetSaveFileName(OPENFILENAME *pOFN)
{
// Check to see if the dialog will ignore directory changes.
BOOL bCheckFloppy = (pOFN && !(pOFN->Flags & OFN_NOCHANGEDIR));
char aOriginalPath[MAX_PATH];
if(bCheckFloppy) {
// Make sure we're not already on a floppy.
if(FEU_GetCurrentDriveType() == DRIVE_REMOVABLE) {
// We don't care what they do.
bCheckFloppy = FALSE;
}
else {
// Save current directory.
DWORD dwCopy = ::GetCurrentDirectory(sizeof(aOriginalPath), aOriginalPath);
if(0 == dwCopy || sizeof(aOriginalPath) < dwCopy) {
// On failure, switch to not care.
bCheckFloppy = FALSE;
}
}
}
BOOL bRetval = ::GetSaveFileName(pOFN);
// Are we to check if we are on a floppy drive?
if(bCheckFloppy) {
BOOL bFloppy = (FEU_GetCurrentDriveType() == DRIVE_REMOVABLE);
if(bFloppy) {
// Go back to a non-floppy location.
// Don't care on failure.
::SetCurrentDirectory(aOriginalPath);
}
}
return(bRetval);
}
// Do not change the current drive to a floppy.
BOOL FEU_GetOpenFileName(OPENFILENAME *pOFN)
{
// Check to see if the dialog will ignore directory changes.
BOOL bCheckFloppy = (pOFN && !(pOFN->Flags & OFN_NOCHANGEDIR));
char aOriginalPath[MAX_PATH];
if(bCheckFloppy) {
// Make sure we're not already on a floppy.
if(FEU_GetCurrentDriveType() == DRIVE_REMOVABLE) {
// We don't care what they do.
bCheckFloppy = FALSE;
}
else {
// Save current directory.
DWORD dwCopy = ::GetCurrentDirectory(sizeof(aOriginalPath), aOriginalPath);
if(0 == dwCopy || sizeof(aOriginalPath) < dwCopy) {
// On failure, switch to not care.
bCheckFloppy = FALSE;
}
}
}
BOOL bRetval = ::GetOpenFileName(pOFN);
// Are we to check if we are on a floppy drive?
if(bCheckFloppy) {
BOOL bFloppy = (FEU_GetCurrentDriveType() == DRIVE_REMOVABLE);
if(bFloppy) {
// Go back to a non-floppy location.
// Don't care on failure.
::SetCurrentDirectory(aOriginalPath);
}
}
return(bRetval);
}
// Return the current Drive's type
UINT FEU_GetCurrentDriveType(void)
{
#ifdef XP_WIN16
return(::GetDriveType(::_getdrive() - 1));
#else
return(::GetDriveType(NULL));
#endif
}
#ifdef XP_WIN16
DWORD GetCurrentDirectory(DWORD nBufferLength, LPSTR lpBuffer)
{
DWORD dwRetval = nBufferLength + MAX_PATH;
char *pRetval = NULL;
if(lpBuffer) {
pRetval = _getcwd(lpBuffer, nBufferLength);
}
if(pRetval) {
dwRetval = XP_STRLEN(lpBuffer);
}
return(dwRetval);
}
BOOL SetCurrentDirectory(LPCSTR lpPathName)
{
BOOL bRetval = FALSE;
if(lpPathName) {
if(_chdir(lpPathName) == 0) {
// Must also change drive in 16 bits.
char aDrive[_MAX_DRIVE];
aDrive[0] = '\0';
_splitpath(lpPathName, aDrive, NULL, NULL, NULL);
if(aDrive[0]) {
// A drive, convert to numeral.
aDrive[0] = toupper(aDrive[0]);
if(_chdrive(aDrive[0] - 'A' + 1) == 0) {
bRetval = TRUE;
}
}
else {
// No drive, then a success.
bRetval = TRUE;
}
}
}
return(bRetval);
}
#endif
// Determine the top most window below the given point.
// No guarantees that the window belongs to our process, or what
// type of window it is.
// Invisible windows are not returned.
// Disabled windows are not returned.
//
// hWndTop same as GetTopWindow SDK function.
// Point is in Screen coordinates.
HWND FEU_GetWindowFromPoint(HWND hWndTop, POINT *pPoint)
{
HWND hRetval = NULL;
if(pPoint) {
HWND hTraverse = GetTopWindow(hWndTop);
if(hTraverse) {
RECT rWindow;
do {
memset(&rWindow, 0, sizeof(rWindow));
GetWindowRect(hTraverse, &rWindow);
if(PtInRect(&rWindow, *pPoint)) {
if(!IsWindowVisible(hTraverse)) {
// Skip this one.
continue;
}
if(!IsWindowEnabled(hTraverse)) {
// Window is visible, but disabled.
// Have to return NULL.
break;
}
hRetval = hTraverse;
break;
}
} while(hTraverse = GetNextWindow(hTraverse, GW_HWNDNEXT));
}
}
return(hRetval);
}
CNSGenFrame *FEU_GetDockingFrameFromPoint(POINT *pPoint)
{
CNSGenFrame *pRetval = NULL;
HWND hAttempt = FEU_GetWindowFromPoint(NULL, pPoint);
if(hAttempt) {
CWnd *pPerm = CWnd::FromHandlePermanent(hAttempt);
if(pPerm && pPerm->IsKindOf(RUNTIME_CLASS(CNSGenFrame))) {
CNSGenFrame *pDockable = (CNSGenFrame *)pPerm;
if(pDockable->AllowDocking()) {
pRetval = pDockable;
}
}
}
return(pRetval);
}
extern "C" PRBool FE_IsNetscapeDefault(void) {
return PR_TRUE;
}
extern "C" PRBool FE_MakeNetscapeDefault(void) {
return PR_TRUE;
}
// Use this to create some COM objects, as we need to switch to the
// directory where the .EXE sits if the current directory isn't
// the same, as the pref COM DLLs have relative paths in the
// registry.
HRESULT FEU_CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv)
{
HRESULT hRetval = NULL;
char aOrigDir[MAX_PATH + 1];
DWORD dwCheck = GetCurrentDirectory(sizeof(aOrigDir), aOrigDir);
ASSERT(dwCheck);
char aProgramDir[MAX_PATH + 1];
FE_GetProgramDirectory(aProgramDir, sizeof(aProgramDir));
BOOL bCheck = SetCurrentDirectory(aProgramDir);
ASSERT(bCheck);
hRetval = CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv);
BOOL bRestoreCheck = SetCurrentDirectory(aOrigDir);
ASSERT(bRestoreCheck);
return(hRetval);
}