/* -*- 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 "rosetta.h" #include "res\appicon.h" #include "dialog.h" #include "mainfrm.h" #include "custom.h" #include "shcut.h" #include "edt.h" #include "prmon.h" #include "fegui.h" #include "prefapi.h" #include #include "secrng.h" #include "mailmisc.h" #include "ipframe.h" #include "mnprefs.h" #include "secnav.h" #include "edprops.h" //xpstrsw header is for resource switcher that will hold the proper instance handle for each stringloaded #include "xpstrsw.h" #ifndef _AFXDLL #define new DEBUG_NEW // MSVC Debugging new...goes to regular new in release mode #endif #ifdef __BORLANDC__ #define _lseek lseek #endif MODULE_PRIVATE char * XP_CacheFileName(); static HPALETTE ghPalette = NULL; static CMapWordToPtr gBitmapMap; static HFONT ghFont = NULL; // Load a string, stored as RCDATA, from the resource file. The // caller must free the pointer that is returned char * wfe_LoadResourceString (LPCSTR lpszName) { HRSRC hrsrc; HGLOBAL hRes; LPSTR lpszString; hrsrc = ::FindResource(AfxGetResourceHandle(), lpszName, RT_RCDATA); if (!hrsrc) { TRACE1("wfe_LoadResourceString cannot find resource: %s\n", lpszName); return NULL; } hRes = ::LoadResource(AfxGetResourceHandle(), hrsrc); if (!hRes) { TRACE1("wfe_LoadResourceString cannot load resource: %s\n", lpszName); return NULL; } lpszString = (LPSTR)::LockResource(hRes); if (!lpszString) { TRACE1("wfe_LoadResourceString cannot lock resource: %s\n", lpszName); ::FreeResource(hRes); return NULL; } // Return a copy of the string lpszString = XP_STRDUP(lpszString); #ifndef XP_WIN32 ::UnlockResource(hRes); #endif ::FreeResource(hRes); return lpszString; } #define MAXSTRINGLEN 8192 // Load a string from resource table //Added pSwitcher to allow us to dictate which HINSTANCE to load the string from. if NULL, we use AfxGetResourceHandle //mjudge 10-30-97 char * szLoadString( UINT iID , ResourceSwitcher *pSwitcher/*=NULL*/) { // These strings MUST be static so they don't live on the stack. Since we // will be returning a pointer to one of these strings, we want the info // to be there once we exit this function // This implements a circular buffer: its size depends on how many times the // szLoadString function will be called in a single function call. For // example, if you do this: // // MessageBox ( NULL, // szLoadString(IDS_ERROR1), // szLoadString(IDS_MSGBOXTITLE), // MB_OK ); // // We need at least 2 strings here. We should be safe with four. static int iWhichString = 0; static char *szLoadedStrings[4] = { NULL, NULL, NULL, NULL }; if ( !szLoadedStrings[iWhichString] ) { szLoadedStrings[iWhichString] = new char[MAXSTRINGLEN]; } // This implements a circular buffer using the four strings. This means that // the pointer you get back from szLoadString will have the correct string in // it until szLoadString has been called four more times. char *szLoadedString = szLoadedStrings[iWhichString]; iWhichString = (iWhichString + 1) % 4; szLoadedString[0] = 0; // Init the string to emptyville. // This allows loading of strings greater than 255 characters. If the // first character of the string is an exclamation point, this means to // tack on the string with a value of ID+1. This continues until // the next string does not exist or the first character is not an // exclamation point // These are just normal local variables used for looping and return values // and string magic char szLoadBuffer[256]; BOOL bKeepLoading; HINSTANCE hResourceHandle; if (NULL== pSwitcher) hResourceHandle=AfxGetResourceHandle(); else hResourceHandle=pSwitcher->GetResourceHandle(); do { bKeepLoading = FALSE; if (LoadString ( hResourceHandle, iID, szLoadBuffer, sizeof(szLoadBuffer))) { if ('!' == *szLoadBuffer) { // Continuation char found. Keep the loop going bKeepLoading = TRUE; // Assume next entry in string table is in numerical order iID++; strcat ( szLoadedString, szLoadBuffer + 1 ); } else { strcat ( szLoadedString, szLoadBuffer ); } } } while (bKeepLoading); return szLoadedString; } #ifdef XP_WIN16 #define INVALID_HANDLE_VALUE NULL // 16 Bit FindFirstFile, second parameter void *b must be of type struct // _find_t *. Return value if successful will just be this same // structure, otherwise INVALID_HANDLE_VALUE. PRIVATE char *cp_filesystems = "\\*.*"; // See _dos_findfirst on how to read the structure _find_t members. void * FindFirstFile(const char * a, void * b) { // First off, our void * coming in is actually a dirStruct. auto dirStruct *dSp = (dirStruct *)b; // See if the dir we're looking at is a root of a file system; string indicates this. // If so, we have to hack a way to provide drive letters and such in the listing. if(XP_STRCMP(a, cp_filesystems) == 0) { dSp->c_checkdrive = 'A'; } else { // +2 because +1 means to return false in find next. dSp->c_checkdrive = 'Z' + 2; } // If we're going after the root, then we have to loop through all the drives until we find one.... Ugh. // The way to tell if we're currently looking for file systems, is if c_checkdrive is a valid drive letter. if(dSp->c_checkdrive == 'A') { // Save the drive we're on currently. auto int i_current = _getdrive(); while(dSp->c_checkdrive <= 'Z') { // If we can change to a drive, then it is valid. // I would think that there is a better way to do this, but all the examples that I've seen do this // exact thing. if(_chdrive(dSp->c_checkdrive - 'A' + 1) == 0) { break; } // Drive we checked wasn't valid. Go on to the next one. dSp->c_checkdrive++; } // Restore the original drive. _chdrive(i_current); // If we found a valid drive, we need to dup it's name in the findfirst stuff to pass it back in the name field. // Also, increment on to the next drive. // Members of the _find_t data structure aren't set up correctly.... They don't seem to be referenced anywhere, // so I'm not going to bother. if(dSp->c_checkdrive <= 'Z') { dSp->file_data.name[0] = dSp->c_checkdrive; dSp->file_data.name[1] = '|'; dSp->file_data.name[2] = '\0'; dSp->c_checkdrive++; // Just return b, as it is the void dSp, and we will soon be seeing it again in findnext.... return(b); } // If we found no valid drives, then we need to return an invalid state. return(INVALID_HANDLE_VALUE); } // Specify what type of files you'd like to find. See _dos_findfirst. auto unsigned u_finding = _A_NORMAL | _A_RDONLY | _A_ARCH | _A_SUBDIR; if(_dos_findfirst(a, u_finding, &(dSp->file_data)) == 0) { // Success, just return the structure containing the info. // b should not be altered! Only read information from the // structure. return(b); } return(INVALID_HANDLE_VALUE); } int FindNextFile(void * a, void * b) { // a and b are actually the same. // Check to see if we are still searching drives from findfirst. auto dirStruct *dSp = (dirStruct *)a; if(dSp->c_checkdrive <= 'Z') { // Save the drive we're on currently. auto int i_current = _getdrive(); while(dSp->c_checkdrive <= 'Z') { // If we can change to a drive, then it is valid. if(_chdrive(dSp->c_checkdrive - 'A' + 1) == 0) { break; } // Drive we checked wasn't valid. Go on to the next one. dSp->c_checkdrive++; } // Restore the original drive. _chdrive(i_current); // If we found a valid drive, we need to dup it's name in the findfirst stuff to pass it back in the name field. // Also, increment on to the next drive. // Members of the _find_t data structure aren't set up correctly.... They don't seem to be referenced anywhere, // so I'm not going to bother. if(dSp->c_checkdrive <= 'Z') { dSp->file_data.name[0] = dSp->c_checkdrive; dSp->file_data.name[1] = '|'; dSp->file_data.name[2] = '\0'; dSp->c_checkdrive++; // Just return as findnext return(TRUE); } } if(dSp->c_checkdrive == 'Z' + 1) { // Special case where we will stop looking for file systems to list. Return as though we failed. return(FALSE); } // Just call _dos_findnext with a, since a and b are actually the // same. Return true if successful. if(_dos_findnext(&(dSp->file_data)) == 0) { return(TRUE); } return(FALSE); } void FindClose(void * a) { // Do nothing. It's up to the caller to get rid of *a since we // created nothing. } #endif // // Return a string the same as the In string but with all of the \n's replaced // with \r\n's // MODULE_PRIVATE char * FE_Windowsify(const char * In) { char *Out; char *o, *i; int32 len; if(!In) return NULL; // if every character is a \n then new string is twice as long len = (int32) XP_STRLEN(In) * 2 + 1; Out = (char *) XP_ALLOC(len); if(!Out) return NULL; // Move the characters over one by one. If the current character is // a \n replace add a \r before moving the \n over for(i = (char *) In, o = Out; i && *i; *o++ = *i++) if(*i == '\n') *o++ = '\r'; // Make sure our new string is NULL terminated *o = '\0'; return(Out); } // middle cuts string into a string of iNum length. If bModifyString is // FALSE (the default), a copy is made which the caller must free PUBLIC char * fe_MiddleCutString(char *pString ,int iNum, BOOL bModifyString) { ASSERT(pString); if (!pString) return NULL; // If the caller wants us to allocate a new string, just dup the string // that was passed in since the result can't be any longer if (!bModifyString) { pString = strdup(pString); if (!pString) { TRACE0("fe_MiddleCutString: strdup failed!\n"); return NULL; } } // Make sure the length to cut to is something sensible ASSERT(iNum > 3); if (iNum <= 3) return pString; // don't bother... // We need to call i18n function for multibyte charset (e.g. Japanese SJIS) // int16 csid = CIntlWin::GetSystemLocaleCsid(); if (csid & MULTIBYTE) { INTL_MidTruncateString (csid, pString, pString, iNum); return pString; } // See if there is any work to do int nLen = strlen(pString); if (nLen > iNum) { int nLeftChars = (iNum - 3) / 2; int nRightChars = iNum - 3 - nLeftChars; // Insert the ellipsis pString[nLeftChars] = '.'; pString[nLeftChars + 1] = '.'; pString[nLeftChars + 2] = '.'; // Use the right "nRightChars" characters strcpy(pString + nLeftChars + 3, pString + nLen - nRightChars); } return pString; } /* puts up a FE security dialog * * Should return TRUE if the url should continue to * be loaded * Should return FALSE if the url should be aborted */ PUBLIC Bool FE_SecurityDialog(MWContext * context, int message, XP_Bool *prefs_toggle) { if (theApp.m_bKioskMode) return TRUE; if(context) { CDialogSecurity box(message, prefs_toggle, ABSTRACTCX(context)->GetDialogOwner()); return(box.DoModal()); } else { CDialogSecurity box(message, prefs_toggle, NULL); return(box.DoModal()); } } // Save the cipher preference to the preferences file // XXX - jsw - remove me extern "C" void FE_SetCipherPrefs(MWContext *context, char *cipher) { } // Retrieve the cipger preferences. The caller is expected to free // the returned string // XXX - jsw - remove me extern "C" char * FE_GetCipherPrefs(void) { return NULL; } // Return some spanked out full path on the mac. // For windows, we just return what was passed in. // We must provide it in a seperate buffer, otherwise they might change // the original and change also what they believe to be saved. extern "C" char *WH_FilePlatformName(const char *pName) { if(pName) { return XP_STRDUP(pName); } return NULL; } /* char ch; // Byte, not Character, to be located * const char* cpStr; // Null-terminated string * uint16 iCSID; // file system id or win_csid * jliu@09/08/97 */ char* intl_strrchr( char* cpStr, char ch, uint16 iCSID ) { if( cpStr == NULL || *cpStr == NULL ) return NULL; if( ( iCSID & MULTIBYTE ) == 0 || ( ch & 0x80 ) != 0 ) return strrchr( cpStr, ch ); char* cpLastChar = NULL; while( *cpStr != NULL ){ if( *cpStr == ch ) cpLastChar = cpStr++; else if( ( *cpStr & 0x80 ) == 0 ) cpStr++; else cpStr = INTL_NextChar( iCSID, cpStr ); } return cpLastChar; } /* const char* cpStr; // Null-terminated string * uint16 iCSID; // file system id or win_csid * jliu@09/08/97 */ BOOL intl_IsEndWithBS( char* cpStr, uint16 iCSID ) { if( cpStr == NULL || *cpStr == NULL ) return FALSE; int len = strlen( cpStr ); // how many bytes in cpStr if( cpStr[len-1] != '\\' ) return FALSE; if( ( iCSID & MULTIBYTE ) == 0 ) return TRUE; char* cpLastChar = NULL; while( *cpStr != NULL ){ cpLastChar = cpStr; cpStr = INTL_NextChar( iCSID, cpStr ); } return *cpLastChar == '\\'; } extern "C" char * FE_GetProgramDirectory(char *buffer, int length) { ::GetModuleFileName(theApp.m_hInstance, buffer, length); // Find the trailing slash. // char *pSlash = ::strrchr(buffer, '\\'); char* pSlash = intl_strrchr( buffer, '\\', CIntlWin::GetSystemLocaleCsid() ); if(pSlash) { *(pSlash+1) = '\0'; } else { buffer[0] = '\0'; } return (buffer); } char* XP_TempDirName(void) { char *tmp = theApp.m_pTempDir; if (!tmp) return XP_STRDUP("."); return XP_STRDUP(tmp); } // Windows _tempnam() lets the TMP environment variable override things sent in // so it look like we're going to have to make a temp name by hand // // The user should *NOT* free the returned string. It is stored in static space // and so is not valid across multiple calls to this function // // The names generated look like // c:\netscape\cache\m0.moz // c:\netscape\cache\m1.moz // up to... // c:\netscape\cache\m9999999.moz // after that if fails // PUBLIC char * xp_TempFileName(int type, const char * request_prefix, const char * extension, char* file_buf) { const char * directory = NULL; char * ext = NULL; // file extension if any char * prefix = NULL; // file prefix if any XP_Bool bDirSlash = FALSE; XP_StatStruct statinfo; int status; // // based on the type of request determine what directory we should be // looking into // switch(type) { case xpCache: directory = theApp.m_pCacheDir; ext = ".MOZ"; prefix = CACHE_PREFIX; break; #ifdef MOZ_MAIL_NEWS case xpSNewsRC: case xpNewsRC: case xpNewsgroups: case xpSNewsgroups: case xpTemporaryNewsRC: directory = g_MsgPrefs.m_csNewsDir; ext = (char *)extension; prefix = (char *)request_prefix; break; case xpMailFolderSummary: case xpMailFolder: directory = g_MsgPrefs.m_csMailDir; ext = (char *)extension; prefix = (char *)request_prefix; break; case xpAddrBook: //changed jonm-- to support multi-profile //directory = theApp.m_pInstallDir->GetCharValue(); directory = (const char *)theApp.m_UserDirectory; if ((request_prefix == 0) || (XP_STRLEN (request_prefix) == 0)) prefix = "abook"; ext = ".nab"; break; #endif // MOZ_MAIL_NEWS case xpCacheFAT: directory = theApp.m_pCacheDir; prefix = "fat"; ext = "db"; break; case xpJPEGFile: directory = theApp.m_pTempDir; ext = ".jpg"; prefix = (char *)request_prefix; break; case xpPKCS12File: directory = theApp.m_pTempDir; ext = ".p12"; prefix = (char *)request_prefix; break; case xpURL: { if (request_prefix) { if ( XP_STRRCHR(request_prefix, '/') ) { const char *end; XP_StatStruct st; directory = (char *)request_prefix; end = directory + XP_STRLEN(directory) - 1; if ( *end == '/' || *end == '\\' ) { bDirSlash = TRUE; } if (XP_Stat (directory, &st, xpURL)) XP_MakeDirectoryR (directory, xpURL); ext = (char *)extension; prefix = (char *)"su"; break; } } // otherwise, fall through } case xpTemporary: default: directory = theApp.m_pTempDir; ext = (char *)extension; prefix = (char *)request_prefix; break; } if(!directory) return(NULL); if(!prefix) prefix = "X"; if(!ext) ext = ".TMP"; // We need to base our temporary file names on time, and not on sequential // addition because of the cache not being updated when the user // crashes and files that have been deleted are over written with // other files; bad data. // The 52 valid DOS file name characters are // 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_^$~!#%&-{}@`'() // We will only be using the first 32 of the choices. // // Time name format will be M+++++++.MOZ // Where M is the single letter prefix (can be longer....) // Where +++++++ is the 7 character time representation (a full 8.3 // file name will be made). // Where .MOZ is the file extension to be used. // // In the event that the time requested is the same time as the last call // to this function, then the current time is incremented by one, // as is the last time called to facilitate unique file names. // In the event that the invented file name already exists (can't // really happen statistically unless the clock is messed up or we // manually incremented the time), then the times are incremented // until an open name can be found. // // time_t (the time) has 32 bits, or 4,294,967,296 combinations. // We will map the 32 bits into the 7 possible characters as follows: // Starting with the lsb, sets of 5 bits (32 values) will be mapped // over to the appropriate file name character, and then // incremented to an approprate file name character. // The left over 2 bits will be mapped into the seventh file name // character. // int i_letter, i_timechars, i_numtries = 0; char ca_time[8]; time_t this_call = (time_t)0; // We have to base the length of our time string on the length // of the incoming prefix.... // i_timechars = 8 - strlen(prefix); // Infinite loop until the conditions are satisfied. // There is no danger, unless every possible file name is used. // while(1) { // We used to use the time to generate this. // Now, we use some crypto to avoid bug #47027 RNG_GenerateGlobalRandomBytes((void *)&this_call, sizeof(this_call)); // Convert the time into a 7 character string. // Strip only the signifigant 5 bits. // We'll want to reverse the string to make it look coherent // in a directory of file names. // for(i_letter = 0; i_letter < i_timechars; i_letter++) { ca_time[i_letter] = (char)((this_call >> (i_letter * 5)) & 0x1F); // Convert any numbers to their equivalent ascii code // if(ca_time[i_letter] <= 9) { ca_time[i_letter] += '0'; } // Convert the character to it's equivalent ascii code // else { ca_time[i_letter] += 'A' - 10; } } // End the created time string. // ca_time[i_letter] = '\0'; // Reverse the time string. // _strrev(ca_time); // Create the fully qualified path and file name. // if (bDirSlash) sprintf(file_buf, "%s%s%s%s", directory, prefix, ca_time, ext); else sprintf(file_buf, "%s\\%s%s%s", directory, prefix, ca_time, ext); // Determine if the file exists, and mark that we've tried yet // another file name (mark to be used later). // // Use the system call instead of XP_Stat since we already // know the name and we don't want recursion // status = _stat(file_buf, &statinfo); i_numtries++; // If it does not exists, we are successful, return the name. // if(status == -1) { /* don't generate a directory as part of the * cache temp names. When the cache file name * is passed into the other XP_File functions * we will append the cache directory to the name * to get the complete path. * This will allow the cache to be moved around * and for netscape to be used to generate external * cache FAT's. :lou */ if(type == xpCache ) sprintf(file_buf, "%s%s%s", prefix, ca_time, ext); // TRACE("Temp file name is %s\n", file_buf); return(file_buf); } // If there is no room for additional characters in the time, // we'll have to return NULL here, or we go infinite. // This is a one case scenario where the requested prefix is // actually 8 letters long. // Infinite loops could occur with a 7, 6, 5, etc character prefixes // if available files are all eaten up (rare to impossible), in // which case, we should check at some arbitrary frequency of // tries before we give up instead of attempting to Vulcanize // this code. Live long and prosper. // if(i_timechars == 0) { break; } else if(i_numtries == 0x00FF) { break; } } // Requested name is thought to be impossible to generate. // TRACE("No more temp file names....\n"); return(NULL); } PUBLIC char * WH_TempFileName(int type, const char * request_prefix, const char * extension) { static char file_buf[_MAX_PATH]; /* protected by _pr_TempName_lock */ char* result; result = XP_STRDUP(xp_TempFileName(type, request_prefix, extension, file_buf)); return result; } // // Return a string that is equal to the NetName string but with the // cross-platform characters changed back into DOS characters // The caller is responsible for XP_FREE()ing the return string // MODULE_PRIVATE char * XP_NetToDosFileName(const char * NetName) { char *p, *newName; if(!NetName) return NULL; // If the name is only '/' or begins '//' keep the // whole name else strip the leading '/' BOOL bChopSlash = FALSE; if(NetName[0] == '/') bChopSlash = TRUE; // save just / as a path if(NetName[0] == '/' && NetName[1] == '\0') bChopSlash = FALSE; // spanky Win9X path name if(NetName[0] == '/' && NetName[1] == '/') bChopSlash = FALSE; if(bChopSlash) newName = XP_STRDUP(&(NetName[1])); else newName = XP_STRDUP(NetName); if(!newName) return NULL; if( newName[1] == '|' ) newName[1] = ':'; for(p = newName; *p; p++){ if( *p == '/' ) *p = '\\'; } return(newName); } /* implement an lseek using _lseek that * writes zero's when extending a file * beyond the end. * This function attemps to override * the standard lseek. */ extern "C" long wfe_lseek(int fd, long offset, int origin) { long cur_pos; long end_pos; long seek_pos; if(origin == SEEK_CUR) { if(offset < 1) return(_lseek(fd, offset, SEEK_CUR)); cur_pos = _lseek(fd, 0, SEEK_CUR); if(cur_pos < 0) return(cur_pos); } end_pos = _lseek(fd, 0, SEEK_END); if(end_pos < 0) return(end_pos); if(origin == SEEK_SET) seek_pos = offset; else if(origin == SEEK_CUR) seek_pos = cur_pos + offset; else if(origin == SEEK_END) seek_pos = end_pos + offset; else { assert(0); return(-1); } /* the seek position desired is before the * end of the file. We don't need * to do anything special except the seek. */ if(seek_pos <= end_pos) return(_lseek(fd, seek_pos, SEEK_SET)); /* the seek position is beyond the end of the * file. Write zero's to the end. * * we are already at the end of the file so * we just need to "write()" zeros for the * difference between seek_pos-end_pos and * then seek to the position to finish * the call */ { char buffer[1024]; long len = seek_pos-end_pos; memset(&buffer, 0, 1024); while(len > 0) { write(fd, &buffer, CASTINT((1024 > len ? len : 1024))); len -= 1024L; } return(_lseek(fd, seek_pos, SEEK_SET)); } } // // Returns the absolute name of a file // // The result of this function can be used with the standard // open/fopen ansi file functions // The caller is responsible for XP_FREE()ing the string -*myName // PUBLIC char * xp_FileName(const char * name, XP_FileType type, char* *myName) { uint16 iFileSystemCSID = CIntlWin::GetSystemLocaleCsid(); // this file system csid, not win_csid char * newName = NULL; char * netLibName = NULL; BOOL bNeedToRegister = FALSE; // == do we need to register a new // newshost->file name mapping char * prefStr = NULL; CString csHostName; CString csHost; struct _stat sInfo; int iDot; int iColon; CString fileName; char* tempName = NULL; switch(type) { case xpCacheFAT: newName = (char *) XP_ALLOC(_MAX_PATH); sprintf(newName, "%s\\fat.db", (const char *)theApp.m_pCacheDir); break; case xpExtCacheIndex: newName = (char *) XP_ALLOC(_MAX_PATH); sprintf(newName, "%s\\extcache.fat", (const char *)theApp.m_pCacheDir); break; // larubbio case xpSARCacheIndex: newName = (char *) XP_ALLOC(_MAX_PATH); sprintf(newName, "%s\\archive.fat", theApp.m_pSARCacheDir); break; case xpHTTPCookie: newName = (char *) XP_ALLOC(_MAX_PATH); //sprintf(newName, "%s\\cookies.txt", theApp.m_pInstallDir->GetCharValue()); // changed -- jonm to support multi-profile sprintf(newName, "%s\\cookies.txt", (const char *)theApp.m_UserDirectory); break; #if defined(CookieManagement) case xpHTTPCookiePermission: newName = (char *) XP_ALLOC(_MAX_PATH); //sprintf(newName, "%s\\cookperm.txt", theApp.m_pInstallDir->GetCharValue()); // changed -- jonm to support multi-profile sprintf(newName, "%s\\cookperm.txt", (const char *)theApp.m_UserDirectory); break; #endif #if defined(SingleSignon) case xpHTTPSingleSignon: newName = (char *) XP_ALLOC(_MAX_PATH); //sprintf(newName, "%s\\signons.txt", theApp.m_pInstallDir->GetCharValue()); // changed -- jonm to support multi-profile sprintf(newName, "%s\\signons.txt", (const char *)theApp.m_UserDirectory); break; #endif #ifdef MOZ_MAIL_NEWS case xpSNewsRC: case xpNewsRC: // see if we are asking about the default news host // else look up in netlib if ( !name || !strlen(name) ) name = g_MsgPrefs.m_csNewsHost; netLibName = NET_MapNewsrcHostToFilename((char *)name, (type == xpSNewsRC), FALSE); // if we found something in our map just skip the rest of this stuff if(netLibName && *netLibName) { newName = XP_STRDUP(netLibName); break; } // whatever name we eventually end up with we will need to register it // before we leave the function bNeedToRegister = TRUE; // If we are on the default host see if there is a newsrc file in the // news directory. If so, that is what we want if(!stricmp(name, g_MsgPrefs.m_csNewsHost)) { csHostName = g_MsgPrefs.m_csNewsDir; csHostName += "\\newsrc"; if(_stat((const char *) csHostName, &sInfo) == 0) { newName = XP_STRDUP((const char *) csHostName); break; } } // See if we are going to be able to build a file name based // on the hostname csHostName = g_MsgPrefs.m_csNewsDir; csHostName += '\\'; // build up '.rc' so we can tell how long its going to be // we will use that as the default name to try if(type == xpSNewsRC) csHost += 's'; csHost += name; // if we have a news host news.foo.com we just want to use the "news" // part iDot = csHost.Find('.'); if(iDot != -1) csHost = csHost.Left(iDot); #ifdef XP_WIN16 if(csHost.GetLength() > 8) csHost = csHost.Left(8); #endif iColon = csHost.Find(':'); if (iColon != -1) { // Windows file system seems to do horrid things if you have // a filename with a colon in it. csHost = csHost.Left(iColon); } csHost += ".rc"; // csHost is now of the form .rc and is in 8.3 format // if we are on a Win16 box csHostName += csHost; // looks like a file with that name already exists -- panic if(_stat((const char *) csHostName, &sInfo) != -1) { char host[5]; // else generate a new file in news directory strncpy(host, name, 4); host[4] = '\0'; newName = WH_TempFileName(type, host, ".rc"); if(!newName) return(NULL); } else { newName = XP_STRDUP((const char *) csHostName); } break; case xpNewsrcFileMap: // return name of FAT file in news directory newName = (char *) XP_ALLOC(_MAX_PATH); sprintf(newName, "%s\\fat", (const char *)g_MsgPrefs.m_csNewsDir); break; case xpNewsgroups: case xpSNewsgroups: // look up in netlib if ( !name || !strlen(name) ) name = g_MsgPrefs.m_csNewsHost; netLibName = NET_MapNewsrcHostToFilename((char *)name, (type == xpSNewsgroups), TRUE); if(!netLibName) { csHostName = g_MsgPrefs.m_csNewsDir; csHostName += '\\'; if(type == xpSNewsgroups) csHost += 's'; csHost += name; // see if we can just use ".rcg" // it might be news.foo.com so just take "news" int iDot = csHost.Find('.'); if(iDot != -1) csHost = csHost.Left(iDot); #ifdef XP_WIN16 if(csHost.GetLength() > 8) csHost = csHost.Left(8); #endif iColon = csHost.Find(':'); if (iColon != -1) { // Windows file system seems to do horrid things if you have // a filename with a colon in it. csHost = csHost.Left(iColon); } csHost += ".rcg"; // csHost is now of the form .rcg csHostName += csHost; // looks like a file with that name already exists -- panic if(_stat((const char *) csHostName, &sInfo) != -1) { char host[5]; // else generate a new file in news directory strncpy(host, name, 4); host[4] = '\0'; newName = WH_TempFileName(type, host, ".rcg"); if(!newName) return(NULL); } else { newName = XP_STRDUP((const char *) csHostName); } if ( !name || !strlen(name)) NET_RegisterNewsrcFile(newName,(char *)(const char *)g_MsgPrefs.m_csNewsHost, (type == xpSNewsgroups), TRUE ); else NET_RegisterNewsrcFile(newName,(char*)name,(type == xpSNewsgroups), TRUE ); } else { newName = XP_STRDUP(netLibName); } break; case xpMimeTypes: name = NULL; break; #endif // MOZ_MAIL_NEWS case xpGlobalHistory: newName = (char *) XP_ALLOC(_MAX_PATH); // changed -- jonm to support multi-profile sprintf(newName, "%s\\%s.hst", (const char *)theApp.m_UserDirectory, XP_AppName); break; case xpGlobalHistoryList: newName = (char *) XP_ALLOC(_MAX_PATH); sprintf( newName, "%s\\ns_hstry.htm" ); break; case xpKeyChain: name = NULL; break; /* larubbio */ case xpSARCache: if(!name) { return NULL; } newName = (char *) XP_ALLOC(_MAX_PATH); sprintf(newName, "%s\\%s", theApp.m_pSARCacheDir, name); break; case xpCache: if(!name) { tempName = WH_TempFileName(xpCache, NULL, NULL); if (!tempName) return NULL; name = tempName; } newName = (char *) XP_ALLOC(_MAX_PATH); if ((strchr(name,'|') || strchr(name,':'))) { // Local File URL if find a | if(name[0] == '/') strcpy(newName,name+1); // skip past extra slash else strcpy(newName,name); // absolute path is valid } else { sprintf(newName, "%s\\%s", (const char *)theApp.m_pCacheDir, name); } break; case xpBookmarks: case xpHotlist: if (!name || !strlen(name)) name = theApp.m_pBookmarkFile; break; case xpSocksConfig: prefStr = NULL; PREF_CopyCharPref("browser.socksfile_location",&prefStr); name = prefStr; break; case xpCertDB: newName = (char *) XP_ALLOC(_MAX_PATH); if ( name ) { sprintf(newName, "%s\\cert%s.db", (const char *)theApp.m_UserDirectory, name); } else { sprintf(newName, "%s\\cert.db", (const char *)theApp.m_UserDirectory); } break; case xpCertDBNameIDX: newName = (char *) XP_ALLOC(_MAX_PATH); sprintf(newName, "%s\\certni.db", (const char *)theApp.m_UserDirectory); break; case xpKeyDB: newName = (char *) XP_ALLOC(_MAX_PATH); if ( name ) { sprintf(newName, "%s\\key%s.db", (const char *)theApp.m_UserDirectory, name); } else { sprintf(newName, "%s\\key.db", (const char *)theApp.m_UserDirectory); } break; case xpSecModuleDB: newName = (char *) XP_ALLOC(_MAX_PATH); sprintf(newName, "%s\\secmod.db", (const char *)theApp.m_UserDirectory); break; case xpSignedAppletDB: newName = (char *) XP_ALLOC(_MAX_PATH); if ( name ) { sprintf(newName, "%s\\signed%s.db", (const char *)theApp.m_UserDirectory, name); } else { sprintf(newName, "%s\\signed.db", (const char *)theApp.m_UserDirectory); } break; #ifdef MOZ_MAIL_NEWS case xpAddrBook: { #ifdef XP_WIN16 if(!name || !strlen(name) ) newName = WH_TempName(type, NULL); #else newName = (char *) XP_ALLOC(_MAX_PATH); strcpy(newName, name); // strip off the extension char * pEnd = max(strrchr(newName, '\\'), strrchr(newName, '/')); if(!pEnd) pEnd = newName; pEnd = strchr(pEnd, '.'); if(pEnd) *pEnd = '\0'; strcat(newName, ".nab"); #endif } break; case xpAddrBookNew: { newName = (char *) XP_ALLOC(_MAX_PATH); sprintf(newName, "%s\\%s", (const char *)theApp.m_UserDirectory, name); break; } break; case xpVCardFile: { newName = (char *) XP_ALLOC(_MAX_PATH); strcpy(newName, name); // strip off the extension char * pEnd = max(strrchr(newName, '\\'), strrchr(newName, '/')); if(!pEnd) pEnd = newName; pEnd = strchr(pEnd, '.'); if(pEnd) *pEnd = '\0'; strcat(newName, ".vcf"); } break; case xpLDIFFile: { newName = (char *) XP_ALLOC(_MAX_PATH); strcpy(newName, name); // strip off the extension char * pEnd = max(strrchr(newName, '\\'), strrchr(newName, '/')); if(!pEnd) pEnd = newName; pEnd = strchr(pEnd, '.'); if(pEnd) *pEnd = '\0'; #ifdef XP_WIN16 strcat(newName, ".ldi"); #else strcat(newName, ".ldif"); #endif } break; case xpTemporaryNewsRC: { CString csHostName = g_MsgPrefs.m_csNewsDir; csHostName += "\\news.tmp"; newName = XP_STRDUP((const char *) csHostName); } break; #endif // MOZ_MAIL_NEWS case xpPKCS12File: { newName = (char *) XP_ALLOC(_MAX_PATH); strcpy(newName, name); // strip off the extension char * pEnd = max(strrchr(newName, '\\'), strrchr(newName, '/')); if(!pEnd) pEnd = newName; pEnd = strchr(pEnd, '.'); if(pEnd) *pEnd = '\0'; strcat(newName, ".p12"); } break; case xpTemporary: if(!name || !strlen(name) ) newName = WH_TempName(type, NULL); break; #ifdef MOZ_MAIL_NEWS case xpMailFolder: if(!name) name = g_MsgPrefs.m_csMailDir; break; case xpMailFolderSummary: { newName = (char *) XP_ALLOC(_MAX_PATH); strcpy(newName, name); // strip off the extension char * pEnd = max(strrchr(newName, '\\'), strrchr(newName, '/')); if(!pEnd) pEnd = newName; #ifdef XP_WIN16 // backend won't allow '.' in win16 folder names, but just to be safe. pEnd = strchr(pEnd, '.'); if(pEnd) *pEnd = '\0'; #endif strcat(newName, ".snm"); } break; case xpMailSort: newName = (char *) XP_ALLOC(_MAX_PATH); // if name is not null or empty, it's probably the host name for the imap server. // This will need to be extended to support per publc folder filters if (name && strlen(name) > 0) sprintf(newName, "%s\\ImapMail\\%s\\rules.dat", (const char *)theApp.m_UserDirectory, name); else sprintf(newName, "%s\\rules.dat", (const char *)g_MsgPrefs.m_csMailDir); break; case xpNewsSort: newName = (char *) XP_ALLOC(_MAX_PATH); sprintf(newName, "%s\\%s", (const char *)g_MsgPrefs.m_csNewsDir, name); break; case xpMailFilterLog: newName = (char *) XP_ALLOC(_MAX_PATH); sprintf(newName, "%s\\mailfilt.log", (const char *)g_MsgPrefs.m_csMailDir); break; case xpNewsFilterLog: newName = (char *) XP_ALLOC(_MAX_PATH); sprintf(newName, "%s\\newsfilt.log", (const char *)g_MsgPrefs.m_csNewsDir); break; case xpMailSubdirectory: { newName = (char *) XP_ALLOC(_MAX_PATH); strcpy(newName, name); // strip off the trailing slash if any char * pEnd = max(strrchr(newName, '\\'), strrchr(newName, '/')); if(!pEnd) pEnd = newName; strcat(newName, ".sbd"); } break; #endif // MOZ_MAIL_NEWS case xpMailPopState: newName = (char *) XP_ALLOC(_MAX_PATH); sprintf(newName, "%s\\%s\\popstate.dat", (const char *)theApp.m_UserDirectory, name); break; // name of global cross-platform registry case xpRegistry: // eventually need to support arbitrary names; this is the default newName = (char *) XP_ALLOC(_MAX_PATH); if ( newName != NULL ) { GetWindowsDirectory(newName, _MAX_PATH); int namelen = strlen(newName); //if ( newName[namelen-1] == '\\' ) if( intl_IsEndWithBS( newName, iFileSystemCSID ) ) namelen--; strcpy(newName+namelen, "\\nsreg.dat"); } break; // name of news group database #ifdef MOZ_MAIL_NEWS case xpXoverCache: newName = (char *) XP_ALLOC(_MAX_PATH); sprintf(newName, "%s\\%s", (const char *)g_MsgPrefs.m_csNewsDir, name); break; #endif // MOZ_MAIL_NEWS case xpProxyConfig: newName = (char *) XP_ALLOC(_MAX_PATH); //sprintf(newName, "%s\\proxy.cfg", theApp.m_pInstallDir->GetCharValue()); sprintf(newName, "%s\\proxy.cfg", (const char *)theApp.m_UserDirectory); break; // add any cases where no modification is necessary here // The name is fine all by itself, no need to modify it case xpFileToPost: case xpExtCache: case xpURL: // name is OK as it is break; #ifdef MOZ_MAIL_NEWS case xpNewsHostDatabase: newName = (char *) XP_ALLOC(_MAX_PATH); sprintf(newName, "%s\\news.db", (const char *)g_MsgPrefs.m_csNewsDir); break; case xpImapRootDirectory: newName = PR_smprintf ("%s\\ImapMail", (const char *)theApp.m_UserDirectory); break; case xpImapServerDirectory: { int len = 0; char *tempImapServerDir = XP_STRDUP(name); char *imapServerDir = tempImapServerDir; #ifdef XP_WIN16 // first, truncate it to 8 characters if ((len = XP_STRLEN(imapServerDir)) > 8) { imapServerDir = imapServerDir + len - 8; } // Now, replace all illegal characters with '_' const char *illegalChars = "\"/\\[]:;=,|?<>*$. "; for (char *possibleillegal = imapServerDir; *possibleillegal; ) if (XP_STRCHR(illegalChars, *possibleillegal) || ((unsigned char)*possibleillegal < 31) ) *possibleillegal++ = '_'; else possibleillegal = INTL_NextChar( iFileSystemCSID, possibleillegal ); #endif newName = PR_smprintf ("%s\\ImapMail\\%s", (const char *)theApp.m_UserDirectory, imapServerDir); if (tempImapServerDir) XP_FREE(tempImapServerDir); } break; case xpJSMailFilters: newName = PR_smprintf("%s\\filters.js", (const char *)g_MsgPrefs.m_csMailDir); break; #endif // MOZ_MAIL_NEWS case xpJSHTMLFilters: newName = PR_smprintf("%s\\hook.js", (const char *)theApp.m_UserDirectory); break; case xpFolderCache: newName = PR_smprintf ("%s\\summary.dat", (const char *)theApp.m_UserDirectory); break; case xpCryptoPolicy: newName = (char *) XP_ALLOC(_MAX_PATH); FE_GetProgramDirectory(newName, _MAX_PATH); strcat(newName, "moz40p3"); break; case xpJSCookieFilters: newName = PR_smprintf("%s\\cookies.js", (const char *)theApp.m_UserDirectory); break; #ifdef MOZ_LOC_INDEP case xpLIClientDB: newName = (char *) XP_ALLOC(_MAX_PATH); sprintf(newName, "%s\\locindep.dat", (const char *)theApp.m_UserDirectory); break; case xpLIPrefs: newName = (char *) XP_ALLOC(_MAX_PATH); sprintf(newName, "%s\\liprefs.js", (const char *)theApp.m_UserDirectory); break; #endif /* MOZ_LOC_INDEP */ HG06197 default: ASSERT(0); /* all types should be covered */ break; } #ifdef MOZ_MAIL_NEWS // make sure we have the correct newsrc file registered for next time if((type == xpSNewsRC || type == xpNewsRC) && bNeedToRegister) NET_RegisterNewsrcFile(newName, (char *)name, (type == xpSNewsRC), FALSE ); #endif // determine what file we are supposed to load and make sure it looks // like a DOS pathname and not some unixy punk name if(newName) { *myName = XP_NetToDosFileName((const char*)newName); XP_FREE(newName); } else { *myName = XP_NetToDosFileName((const char*)name); } if (tempName) XP_FREE(tempName); if (prefStr) XP_FREE(prefStr); // whee, we're done return(*myName); } // // Open a file with the given name // If a special file type is provided we might need to get the name // out of the preferences list // PUBLIC XP_File XP_FileOpen(const char * name, XP_FileType type, const XP_FilePerm perm) { XP_File fp; char *filename = WH_FileName(name, type); if(!filename || !(*filename)) return(NULL); // THIS MUST BE DONE FIRST TO PLUG WIN OS SECURITY HOLE. // Do not allow UNC pathnames if the command line stated so. if(xpURL == type && FALSE == theApp.m_bUNC) { // Make sure we have enough buffer to check. if(filename && filename[0] && filename[1]) { if( ('\\' == filename[0] && '\\' == filename[1]) || ('/' == filename[0] && '/' == filename[1]) || ('\\' == filename[0] && '/' == filename[1]) || ('/' == filename[0] && '\\' == filename[1]) ) { // Presumed UNC format (or likely to not open in the first place). // Denied. XP_FREE(filename); return(NULL); } } } #ifdef DEBUG_nobody TRACE("Opening a file type (%d) permissions: %s (%s)\n", type, perm, filename); #endif #ifdef XP_WIN32 if (type == xpURL) { HANDLE hFile; DWORD dwType; // Check if we're trying to open a device. We don't allow this hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile != INVALID_HANDLE_VALUE) { dwType = GetFileType(hFile); CloseHandle(hFile); if (dwType != FILE_TYPE_DISK) { XP_FREE(filename); return NULL; } } } #endif #ifdef XP_WIN16 // Windows uses ANSI codepage, DOS uses OEM codepage, fopen takes OEM codepage // That's why we need to do conversion here. CString oembuff = filename; oembuff.AnsiToOem(); fp = fopen(oembuff, (char *) perm); if (fp && type == xpURL) { union _REGS inregs, outregs; // Check if we opened a device. Execute an Interrupt 21h to invoke // MS-DOS system call 44h inregs.x.ax = 0x4400; // MS-DOS function to get device information inregs.x.bx = _fileno(fp); _int86(0x21, &inregs, &outregs); if (outregs.x.dx & 0x80) { // It's a device. Don't allow any reading/writing fclose(fp); XP_FREE(filename); return NULL; } } #else fp = fopen(filename, (char *) perm); #endif XP_FREE(filename); return(fp); } // // Rename tmpname to fname // int XP_FileRename(const char *tmpname, XP_FileType tmptype, const char *fname, XP_FileType ftype) { char * pOldName = WH_FileName(tmpname, tmptype); char * pNewName = WH_FileName(fname, ftype); if(!pOldName || !pNewName) return(-1); #ifdef XP_WIN32 // try using win32 system call. If that fails, do what the old code did. if (MoveFileEx(pOldName, pNewName, MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING)) { XP_FREE(pOldName); XP_FREE(pNewName); return 0; } #endif // lets try ANSI first int status = rename(pOldName, pNewName); // if rename failed try to just copy if(status == -1) { if(WFE_CopyFile(pOldName, pNewName)) { // we were at least able to copy the file so return the correct // status and get rid of the old file status = 0; remove(pOldName); } } // clean up XP_FREE(pOldName); XP_FREE(pNewName); return(status); } // // Make a directory with the given name (may need WH_FileName munging first) // int XP_MakeDirectory(const char* name, XP_FileType type) { char * pName = WH_FileName(name, type); if(pName) { int dir; dir = mkdir(pName); XP_FREE(pName); return(dir); } else return(-1); } // // Remove a directory with the given name // int XP_RemoveDirectory (const char *name, XP_FileType type) { int ret = -1; char *pName = WH_FileName (name, type); if (pName) { ret = rmdir (pName); XP_FREE(pName); } return ret; } /**************************************************************************** * * XP_FileTruncate * * PARAMETERS: * name - filename to be truncated * length - desired size (in bytes) for the truncated file * * RETURNS: * Non-negative if successful, -1 if an exception occurs * * DESCRIPTION: * This function is called to truncate (or extend) a given file. * ****************************************************************************/ int XP_FileTruncate(const char * name, XP_FileType type, int32 length) { int nRtn = 0; char * szFileName = WH_FileName(name, type); if (szFileName != NULL) { TRY { CFile file(szFileName, CFile::modeReadWrite); file.SetLength((DWORD)length); file.Close(); } CATCH(CFileException, e) { nRtn = -1; #ifdef _DEBUG afxDump << "File exception: " << e->m_cause << "\n"; #endif } END_CATCH XP_FREE(szFileName); } /* end if */ else { nRtn = -1; } /* end else */ return(nRtn); } // END OF FUNCTION XP_FileTruncate() // // Mimic unix stat call // Return -1 on error // PUBLIC int XP_Stat(const char * name, XP_StatStruct * info, XP_FileType type) { char * filename = WH_FileName(name, type); int res; if(!info || !filename) return(-1); // THIS MUST BE DONE FIRST TO PLUG WIN OS SECURITY HOLE. // Do not allow UNC pathnames if the command line stated so. if(xpURL == type && FALSE == theApp.m_bUNC) { // Make sure we have enough buffer to check. if(filename && filename[0] && filename[1]) { if( ('\\' == filename[0] && '\\' == filename[1]) || ('/' == filename[0] && '/' == filename[1]) || ('\\' == filename[0] && '/' == filename[1]) || ('/' == filename[0] && '\\' == filename[1]) ) { // Presumed UNC format (or likely to not open in the first place). // Denied. XP_FREE(filename); return(-1); } } } // Strip off final slash on directory names // BUT we will need to make sure we have c:\ NOT c: int len = XP_STRLEN(filename) - 1; if(len > 1 && filename[len] == '\\' && filename[len -1] != ':'){ uint16 iFileSystemCSID = CIntlWin::GetSystemLocaleCsid(); // this file system csid, not win_csid if( intl_IsEndWithBS( filename, iFileSystemCSID ) ) filename[len] = '\0'; } #ifdef XP_WIN16 // Also, if we are looking at something like "c:", we won't call stat at // all, as we never know if they have a diskette in drive A or such // and don't want to stall waiting. // Be very strict on what we let into this statement, though. if(len == 1 && filename[len] == ':') { // Set the stat info ourselves. The numbers were generic, taken // from a _stat call to "c:\" // Is this a hack, or what? info->st_atime = info->st_ctime = info->st_mtime = 315561600L; info->st_uid = 0; info->st_gid = 0; info->st_size = (_off_t) 0; info->st_rdev = info->st_dev = filename[len - 1] - 'A'; info->st_mode = 16895; info->st_nlink = 1; res = 0; } else { // Windows uses ANSI codepage, DOS uses OEM codepage, _stat takes OEM codepage // That's why we need to do conversion here. CString oembuff = filename; oembuff.AnsiToOem(); res = _stat(oembuff, info); } #else // XP_WIN16 // Normal file or directory. res = _stat(filename, info); #endif XP_FREE(filename); return(res); } PUBLIC XP_Dir XP_OpenDir(const char * name, XP_FileType type) { XP_Dir dir; char * filename = WH_FileName(name, type); uint16 iFileSystemCSID = CIntlWin::GetSystemLocaleCsid(); // this file system csid, not win_csid CString foo; if(!filename) return NULL; // THIS MUST BE DONE FIRST TO PLUG WIN OS SECURITY HOLE. // Do not allow UNC pathnames if the command line stated so. if(xpURL == type && FALSE == theApp.m_bUNC) { // Make sure we have enough buffer to check. if(filename && filename[0] && filename[1]) { if( ('\\' == filename[0] && '\\' == filename[1]) || ('/' == filename[0] && '/' == filename[1]) || ('\\' == filename[0] && '/' == filename[1]) || ('/' == filename[0] && '\\' == filename[1]) ) { // Presumed UNC format (or likely to not open in the first place). // Denied. XP_FREE(filename); return(NULL); } } } dir = (XP_Dir) new DIR; // For directory names we need \*.* at the end, if and only if there is an actual name specified. foo += filename; //if(filename[XP_STRLEN(filename) - 1] != '\\') if( !intl_IsEndWithBS( filename, iFileSystemCSID ) ) foo += '\\'; foo += "*.*"; dir->directoryPtr = FindFirstFile((const char *) foo, &(dir->data)); XP_FREE(filename); if(dir->directoryPtr == INVALID_HANDLE_VALUE) { delete dir; return(NULL); } else { return(dir); } } // // HACK:- use a static location cuz unix does it that way even // though it makes for non-reentrant code // PUBLIC XP_DirEntryStruct * XP_ReadDir(XP_Dir dir) { static XP_DirEntryStruct dirEntry; if(dir && dir->directoryPtr) { #ifdef XP_WIN16 XP_STRCPY(dirEntry.d_name, dir->data.file_data.name); #else XP_STRCPY(dirEntry.d_name, dir->data.cFileName); #endif if(FindNextFile(dir->directoryPtr, &(dir->data)) == FALSE) { FindClose(dir->directoryPtr); dir->directoryPtr = NULL; } return(&dirEntry); } else { return(NULL); } } // // Close the directory // PUBLIC void XP_CloseDir(XP_Dir dir) { if (dir) { if (dir->directoryPtr) FindClose (dir->directoryPtr); delete dir; } } // // Return 0 on success, -1 on failure. Silly unix weenies // PUBLIC int XP_FileRemove(const char * name, XP_FileType type) { char *filename = WH_FileName(name, type); if(!filename) return(-1); #ifdef MOZ_MAIL_NEWS if(type == xpNewsRC || type == xpNewsgroups) NET_UnregisterNewsHost( name, FALSE); else if(type == xpSNewsRC || type == xpSNewsgroups) NET_UnregisterNewsHost(name, TRUE); #endif // MOZ_MAIL_NEWS int status = remove(filename); XP_FREE(filename); return(status); } BOOL XP_RemoveDirectoryRecursive(const char *name, XP_FileType type) { XP_DirEntryStruct *entry; XP_StatStruct statbuf; BOOL ret = TRUE; CString dot = "."; CString dotdot = ".."; int status; XP_Dir dir = XP_OpenDir(name, type); if (!dir) return FALSE; // Go through the directory entries and delete appropriately while ((entry = XP_ReadDir(dir))) { CString child; child = name; child += "\\"; child += entry->d_name; if (!(status = XP_Stat(child, &statbuf, type))) if (entry->d_name == dot || entry->d_name == dotdot) { // Do nothing, rmdir will clean these up } else if ((statbuf.st_mode & _S_IFMT) == _S_IFDIR) // _S_ISDIR() isn't on Win16 { // Recursive call to clean out subdirectory if (!XP_RemoveDirectoryRecursive(child, type)) ret = FALSE; } else { // Everything that's not a directory is a file! if (XP_FileRemove(child, type) != 0) ret = FALSE; } } // OK, remove the top-level directory if we can if (XP_RemoveDirectory(name, type) != 0) ret = FALSE; XP_CloseDir(dir); return ret; } // Should be self-explanitory --- return TRUE on success FALSE on failure BOOL WFE_MoveFile(const char *cpSrc, const char *cpTarg) { #ifdef XP_WIN32 return MoveFile(cpSrc, cpTarg); // overwrite existing target file #else // lets try ANSI first int status = rename(cpSrc, cpTarg); // if rename failed try to just copy if(status !=0) { if(WFE_CopyFile(cpSrc, cpTarg)) { // we were at least able to copy the file so return the correct // status and get rid of the old file status = 0; remove(cpSrc); return TRUE; } else return FALSE; } else return TRUE; #endif } // Should be self-explanitory --- return TRUE on success FALSE on failure BOOL WFE_CopyFile(const char *cpSrc, const char *cpTarg) { #ifdef XP_WIN32 return CopyFile(cpSrc, cpTarg, FALSE); // overwrite existing target file #else CFile cfSource; CFile cfTarget; TRY { Bool fail; /* Open returns 0 on failure */ fail = cfSource.Open(cpSrc, CFile::modeRead | CFile::shareExclusive); if (fail == 0) return (FALSE); fail = cfTarget.Open(cpTarg, CFile::modeWrite | CFile::modeCreate | CFile::shareExclusive); if (fail == 0) return (FALSE); } CATCH(CFileException, e) { // Couldn't do it, just return. return(FALSE); } END_CATCH // Copy the thing. char *pBuffer = new char[8192]; UINT uAmount; do { uAmount = 8192; TRY { uAmount = cfSource.Read((void *)pBuffer, uAmount); cfTarget.Write((void *)pBuffer, uAmount); } CATCH(CFileException, e) { // don't know why we failed, but assume we're done. // perhaps end of file. break; } END_CATCH } while(uAmount != 0); // Clean up the buffer. // Files close up automagically. delete []pBuffer; return(TRUE); #endif } /* copy the file specified by the first argument * over the newsrc file. The second argument specifies * the hostname for this newsrc or "" if it is the default * host. * * The first filename argument was generated by a call to WH_TempName * with an enum of "xpTemporaryNewsRC" * * Should return TRUE on success or FALSE on failure. */ extern "C" Bool XP_File_CopyOverNewsRC(const char *newfile, const char *news_hostname, Bool is_secure) { #ifdef MOZ_MAIL_NEWS char *pRCName = NET_MapNewsrcHostToFilename((char *)news_hostname, is_secure, FALSE); // Is the current rc valid? if(pRCName == NULL) { return(FALSE); } // Are we getting a valid filename? if(newfile == NULL) { return(FALSE); } // Does the new one exist? CFileStatus rStatus; if(CFile::GetStatus(newfile, rStatus) == 0) { return(FALSE); } // Does the old one exist? // If so, we should remove it. if(CFile::GetStatus(pRCName, rStatus) != 0) { // Attempt to remove. TRY { CFile::Remove(pRCName); } CATCH(CFileException, e) { return(FALSE); } END_CATCH } TRY { // Attempt a speedy rename. CFile::Rename(newfile, pRCName); } CATCH(CFileException, e) { // Rename didn't work, attempt to copy, as fast as possible. if(FALSE == WFE_CopyFile(newfile, pRCName)) { // Uh, like we lost the newsrc file permanently here!!!!!!!!!! ASSERT(0); return(FALSE); } // Should remove the temp file now, as it is expected to go away. TRY { CFile::Remove(newfile); } CATCH(CFileException, e) { // Leave it lying around, not much we can do. return(TRUE); } END_CATCH } END_CATCH #endif // MOZ_MAIL_NEWS return(TRUE); } extern "C" XP_Bool XP_FileNameContainsBadChars (const char *name) { #ifdef XP_WIN16 char *badChars = "\\/:*?\"<>| ,+"; #else char *badChars = "\\/:*?\"<>|"; #endif XP_ASSERT( name != NULL ); uint len = XP_STRLEN(badChars); if( len < 1 ) return FALSE; uint16 iFileSystemCSID = CIntlWin::GetSystemLocaleCsid(); // this file system csid, not win_csid while( *name != NULL ){ for (uint j = 0; j < len; j++) if (*name == badChars[j]) return TRUE; name = INTL_NextChar( iFileSystemCSID, (char*)name ); } return FALSE; } // Print a trace message to the console // #ifdef DEBUG PUBLIC void FE_Trace(const char * msg) { /* This used to be just TRACE(msg), but that's a mistake -- * if msg happens to have a '%' in it, TRACE will * interpret the '%' as the beginning of an argument to be * printf'd and look up the stack and try to * interpret random data as the argument. At a minimum this * leads to corrupt trace info. Usually it causes bus errors. */ TRACE("%s", msg); } #endif PUBLIC void FE_ConnectToRemoteHost(MWContext * context, int url_type, char * hostname, char * port, char * username) { LPSTR lpszCommand; UINT iRet; ASSERT(url_type == FE_TN3270_URL_TYPE || url_type == FE_TELNET_URL_TYPE || url_type == FE_RLOGIN_URL_TYPE); #ifdef _WIN32 BOOL checkRegistry = TRUE; CInternetShortcut InternetShortcut; if (InternetShortcut.ShellSupport() && !theApp.m_bParseTelnetURLs) { SHELLEXECUTEINFO sei; // Build the command string if (port) lpszCommand = PR_smprintf("%s://%s:%s", url_type == FE_TN3270_URL_TYPE ? "tn3270" : "telnet", hostname, port); else lpszCommand = PR_smprintf("%s://%s", url_type == FE_TN3270_URL_TYPE ? "tn3270" : "telnet", hostname); // Use ShellExecuteEx to launch sei.cbSize = sizeof(sei); sei.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS; sei.hwnd = NULL; sei.lpVerb = NULL; // default to Open sei.lpFile = lpszCommand; sei.lpParameters = NULL; sei.lpDirectory = NULL; sei.nShow = SW_SHOW; ShellExecuteEx(&sei); iRet = (UINT)sei.hInstApp; XP_FREE(lpszCommand); checkRegistry = iRet < 32; } if (checkRegistry) { #endif // _WIN32 char szBuf[_MAX_PATH]; LONG lResult; LONG cbData; HKEY hKey; // Build the shell\open key for the file type class PR_snprintf(szBuf, sizeof(szBuf), "%s\\shell\\open", url_type == FE_TN3270_URL_TYPE ? "tn3270" : "telnet"); // Open the key lResult = RegOpenKey(HKEY_CLASSES_ROOT, szBuf, &hKey); if (lResult != ERROR_SUCCESS) { // Nothing registered for the file type class FE_Alert(context, szLoadString(IDS_NO_VIEWER_CONFIGD)); return; } // Get the Open command string cbData = sizeof(szBuf); lResult = RegQueryValue(hKey, "command", szBuf, &cbData); RegCloseKey(hKey); if (lResult == ERROR_SUCCESS) { LPSTR lpszApp = szBuf; LPSTR lpszArg; // Strip off any command line options lpszArg = strstr(lpszApp, "%1"); if ( !lpszArg ) { // Look for "%l", instead. lpszArg = strstr(lpszApp, "%l"); } if (lpszArg) *lpszArg = '\0'; // null terminate the string here // Build the WinExec command line if (port) lpszCommand = PR_smprintf("%s %s %s", lpszApp, hostname, port); else lpszCommand = PR_smprintf("%s %s", lpszApp, hostname); // Run it iRet = (UINT)WinExec(lpszCommand, SW_SHOW); XP_FREE(lpszCommand); // If the error is file not found or path not found report it here; otherwise // report it below if (iRet == 2 || iRet == 3) { LPSTR lpszMsg; lpszMsg = PR_smprintf(szLoadString(IDS_UNABLE_FIND_APP), lpszApp); if (lpszMsg) { FE_Alert(context, lpszMsg); XP_FREE(lpszMsg); } return; } } #ifdef _WIN32 } #endif // _WIN32 // See if it worked if (iRet < 32) { LPSTR lpszMsg; lpszMsg = PR_smprintf(szLoadString(IDS_UNABLE_TO_LAUNCH_APP), iRet); if (lpszMsg) { FE_Alert(context, lpszMsg); XP_FREE(lpszMsg); } } else { FE_Progress(context, szLoadString(IDS_SPAWNING_APP)); if (username) { LPSTR lpszMsg; lpszMsg = PR_smprintf(szLoadString(IDS_LOGIN_AS), username); if (lpszMsg) { FE_Alert(context, lpszMsg); XP_FREE(lpszMsg); } } } } PUBLIC void *FE_AboutData (const char *which, char **data_ret, int32 *length_ret, char **content_type_ret) { char *loc = (char*)strchr (which, '?'); char *which2; char *tmp; if (loc) *loc++ = 0; BOOL bHandled = FALSE; if(FALSE == bHandled) { char *pCompare = strdup(which); if(pCompare) { char *pReplace = strchr(pCompare, '.'); if(pReplace) { *pReplace = '_'; } HINSTANCE hInst = AfxGetResourceHandle(); if(hInst) { HRSRC hFound = FindResource(hInst, pCompare, RT_RCDATA); free(pCompare); pCompare = NULL; if(hFound) { HGLOBAL hRes = LoadResource(hInst, hFound); hFound = NULL; if(hRes) { char *pBytes = (char *)LockResource(hRes); if(pBytes) { // Check for identifying bin2rc string. if(!strcmp(pBytes, "bin2rc generated resource")) { pBytes += 26; // length + 1 // Next is a content-type. // The mime type should be something we recognize. // Assign in a constant string only. if(!stricmp(pBytes, IMAGE_GIF)) { *content_type_ret = IMAGE_GIF; } else if(!stricmp(pBytes, IMAGE_JPG)) { *content_type_ret = IMAGE_JPG; } pBytes += strlen(pBytes) + 1; // length + 1 // Next is the size of the data if we are willing. if(*content_type_ret) { *length_ret = strtol(pBytes, NULL, 10); } pBytes += strlen(pBytes) + 1; // length + 1 // Next is the data if any. if(*length_ret) { *data_ret = (char *)malloc(*length_ret); if(*data_ret) { memcpy(*data_ret, pBytes, *length_ret); bHandled = TRUE; } else { // Unable to alloc. // Clear out. *content_type_ret = NULL; *length_ret = 0; } } } pBytes = NULL; } UnlockResource(hRes); FreeResource(hRes); hRes = NULL; } } } } } if(FALSE == bHandled) { which2 = strdup (which); for (tmp = which2; *tmp; tmp++) *tmp += 69; char *a = NULL; if (!strcmp (which2, "")) { // about: CString csVersion, csBuildNumber; char *tmpversionBuf; csVersion = XP_AppVersion; csVersion = csVersion.Left(csVersion.Find("]") + 1); tmpversionBuf = (char *)XP_ALLOC(15); //Loading from netscape.exe instead of resdll.dll since the string has been moved #109455 LoadString(::AfxGetInstanceHandle(), IDS_APP_BUILD_NUMBER, tmpversionBuf, 15); csBuildNumber = tmpversionBuf; if (tmpversionBuf) XP_FREE(tmpversionBuf); csVersion+=csBuildNumber; char *pSSLVersion = NULL; char *pSSLString = NULL; HG83722 char *pSp = szLoadString(IDS_ABOUT_0); /* Null pointer check */ if (pSp && pSSLString) { a = (char *)malloc(strlen(pSp) + strlen(pSSLString) + strlen(csVersion) * 2 + 48); sprintf(a, pSp, (const char *)csVersion, (const char *)csVersion, pSSLString); } else a = strdup(pSp); /* Free string space if allocated */ if (pSSLString) free(pSSLString); if (pSSLVersion) free(pSSLVersion); } else if (!strcmp (which, "mailintro")) a = strdup(szLoadString(IDS_MAIL_0)); else if (!strcmp (which, "license")) a = wfe_LoadResourceString("license"); else if (!strcmp (which, "mozilla")) a = strdup (szLoadString(IDS_MOZILLA_0)); else if (!strcmp (which2, "\250\264\265\276\267\256\254\255\271")) a = strdup(szLoadString(IDS_COPYRIGHT_0)); else if (!strcmp (which2, "\247\261\246\263\260")) a = strdup (""); #ifdef EDITOR else if (!strcmp (which, "editfilenew")) a = strdup (EDT_GetEmptyDocumentString()); #endif // EDITOR else if (!strcmp(which, "plugins")) a = wfe_LoadResourceString("aboutplg"); else { char *p[] = { "\234\255\246\271\250\255\252\274\145\271\246\261\260\256\263\154\145\154\247\264\272\271\161\145\214\252\264\267\254\256\145\214\272\263\256\263\270\260\256\204", "\224\255\145\264\255\163\145\145\236\264\272\267\145\265\267\256\263\271\252\267\154\270\145\264\263\145\253\256\267\252\146", "\225\264\274\252\267\214\232\216\146", 0 }; static int n = 0; char *x = a = strdup(p[n]); if(x) while(*x) *x++ -= 69; if ( !p[++n] ) n = 0; } if (a) { // for (tmp = a; *tmp; tmp++) *tmp -= 69; *data_ret = a; *length_ret = strlen (*data_ret); *content_type_ret = TEXT_MDL; if(!strcmp (which, "license")) *content_type_ret = TEXT_PLAIN; #ifdef DEBUG // Produce some hard to debug situations here manually. if(!stricmp(which, "WM_ENDSESSION")) { // Shutdown of the system case. FEU_FrameBroadcast(TRUE, WM_QUERYENDSESSION, 1, 0); FEU_FrameBroadcast(FALSE, WM_ENDSESSION, 1, 0); } else if(!stricmp(which, "debug")) { DebugBreak(); } else if(!stricmp(which, "PostQuitMessage")) { PostQuitMessage(0); } #endif } else { *data_ret = 0; *length_ret = 0; *content_type_ret = 0; } free (which2); } return(*data_ret); } /*****/ PUBLIC void FE_FreeAboutData(void *data, const char *which2) { if(data) { free(data); data = NULL; } } char *XP_PlatformPartialPathToXPPartialPath (const char *platformName) { return XP_STRDUP(platformName); } char *XP_PlatformFileToURL (const char *platformName) { CString csXPName; WFE_ConvertFile2Url (csXPName, platformName); return XP_STRDUP(csXPName); } void WFE_ConvertFile2Url(CString& csUrl, const char *pLocalFileName) { uint16 iFileSystemCSID = CIntlWin::GetSystemLocaleCsid(); // this file system csid, not win_csid // First empty the returning url, in case it has something in it. csUrl.Empty(); // If there's nothing to convert, return now. if(pLocalFileName == NULL || *pLocalFileName == '\0') { return; } // A CString we can muck with. CString csLocal = pLocalFileName; if (csLocal.GetLength() > 4) { if ( !strnicmp(&pLocalFileName[strlen(pLocalFileName)-4],".lnk",4)) { char szName[_MAX_PATH]; HRESULT hRes = ::ResolveShortCut(NULL, pLocalFileName, szName); if (SUCCEEDED(hRes)) { csLocal = szName; } } else if (!strnicmp(&pLocalFileName[strlen(pLocalFileName)-4],".url",4)) { CInternetShortcut InternetShortcut; if (InternetShortcut.ShellSupport()) { // got a valid .URL internet shortcut file char szNew[_MAX_PATH]; CInternetShortcut Shortcut (pLocalFileName); Shortcut.GetURL(szNew,sizeof(szNew)); csUrl = szNew; return; } } } // Convert $ROOT to the directory of the executable. if(csLocal.Left(5) == "$ROOT") { char aPath[_MAX_PATH]; ::GetModuleFileName(theApp.m_hInstance, aPath, _MAX_PATH); // Find the trailing slash. char *pSlash = intl_strrchr(aPath, '\\', iFileSystemCSID); if(pSlash) { *pSlash = '\0'; } else { aPath[0] = '\0'; } csLocal = aPath + csLocal.Right(csLocal.GetLength() - 5); } // Convert local file paths which have a drive letter to an appropriate URL. // This means we must always have a fully qualified file path in order to convert // these correctly. const char* src = csLocal.GetBuffer( csLocal.GetLength() ) + 2; const char* end = src + csLocal.GetLength() - 2; if(csLocal.GetLength() >= 2 && csLocal[1] == ':') { csUrl += "file:///"; csUrl += csLocal[0]; csUrl += '|'; #ifdef BUG93660_4_05_FIX for(int iTraverse = 2; iTraverse < csLocal.GetLength(); iTraverse++) { if(csLocal[iTraverse] == '\\') { // bug 93660 -- double byte file name gets truncated // We don't want to replace the backslash with // forwardslash in case of the double byte file name // iTraverse starts with 2; iTraverse - 1 will not go // negative if (CIntlWin::GetSystemLocaleCsid() & MULTIBYTE && INTL_IsLeadByte(CIntlWin::GetSystemLocaleCsid(), csLocal[iTraverse-1])) { csUrl += csLocal[iTraverse]; } else { csUrl += '/'; } } else { csUrl += csLocal[iTraverse]; } } #endif } // Convert microsoft network paths. else if(csLocal.Left(2) == "\\\\" || csLocal.Left(2) == "//") { csUrl += "file:////"; } else { // This was a normal URL. // Don't corrupt it. csUrl = pLocalFileName; src = end = NULL; } if( src != NULL ){ while( src < end ){ if( *src == '\\'){ csUrl += '/'; src++; } else { const char* next = INTL_NextChar( iFileSystemCSID, (char*)src ); ASSERT( next <= end ); while( src < next ) csUrl += *src++; } } csLocal.ReleaseBuffer(); } // This seems to be missing cases such as "..\foo" // Replace all "\" with "/" Note: only do this for the file: protocol or if there is no // specified protocol type; this way we won't munge things like mocha: and mailbox: int nUrlType = NET_URL_Type(csUrl); if (nUrlType == FILE_TYPE_URL || nUrlType == 0) { char* src = csUrl.GetBuffer( csUrl.GetLength() ); while( *src != NULL ){ if( *src == '\\' ) *src++ = '/'; else src = INTL_NextChar( iFileSystemCSID, src ); } csUrl.ReleaseBuffer(); } // Check for a file url with an extra slash. // This is special case code to make sure an arbitrary number // of slashes sends the file URL as a microsoft network // path. // Go recursive, minus one slash. if(csUrl.Left(10) == "file://///") { CString csLeft = csUrl.Left(9); CString csRight = csUrl.Right(csUrl.GetLength() - 10); WFE_ConvertFile2Url(csUrl, (const char *)(csLeft + csRight)); } } extern CString WFE_EscapeURL(const char* url) { CString urlStr(url); CString encoded; int l = urlStr.GetLength(); for (int i = 0; i < l; i++) { char c = urlStr[i]; if (c == ' ') encoded += "%20"; else encoded += c; } return encoded; } extern void FE_SetRefreshURLTimer(MWContext *pContext, URL_Struct *URL_s) { // Purpose: Set a delayed load timer for a window for a particular URL. // Arguments: pContext The context that we're in. We are only interested on wether or not there appears to be a Frame/hence document. // ulSeconds The number of seconds that will pass before we attempt the reload. // Returns: void // Comments: // Revision History: // 02-17-95 created GAB // 07-22-95 modified to use new context. // 05-03-96 modified to use new API outside of idle loop. // // Only do this if it is a window context from the back end. if( URL_s->dont_cache) URL_s->force_reload = NET_SUPER_RELOAD; if(ABSTRACTCX(pContext) && ABSTRACTCX(pContext)->IsWindowContext()) { FEU_ClientPull(pContext, URL_s->refresh * 1000, NET_CreateURLStruct(URL_s->refresh_url, URL_s->force_reload), FO_CACHE_AND_PRESENT, FALSE); } } #if defined XP_WIN16 && defined DEBUG void AfxDebugBreak() { _asm { int 3 }; } #endif extern "C" void XP_Assert(int stuff) { ASSERT(stuff); } extern "C" void fe__assert(void *, void *, unsigned) { #ifdef DEBUG TRACE("lowest level Assertion failure!\n"); AfxDebugBreak(); #endif } extern "C" void fe_abort(void) { #ifdef DEBUG TRACE("lowest level Abortion called!\n"); AfxDebugBreak(); #endif } extern "C" void XP_AssertAtLine( char *pFileName, int iLine ){ #ifdef DEBUG #ifdef XP_WIN32 if( AfxAssertFailedLine( pFileName, iLine) ) #endif { AfxDebugBreak(); } #endif } // Draws a 3D button exactly as Windows95 style void WFE_DrawWindowsButtonRect(HDC hDC, LPRECT lpRect, BOOL bPushed) { HPEN penHighlight = ::CreatePen(PS_SOLID, 1, bPushed ? sysInfo.m_clrBtnShadow : sysInfo.m_clrBtnHilite); HPEN penShadow = ::CreatePen(PS_SOLID, 1, bPushed ? sysInfo.m_clrBtnHilite : sysInfo.m_clrBtnShadow); HPEN penBlack = ::CreatePen(PS_SOLID, 1, RGB(0,0,0)); // Top and left HPEN penOld = (HPEN)::SelectObject(hDC, bPushed ? penBlack : penHighlight); ::MoveToEx(hDC, lpRect->left, lpRect->bottom, NULL); ::LineTo(hDC, lpRect->left, lpRect->top); ::LineTo(hDC, lpRect->right+1, lpRect->top); // Bottom and right ::SelectObject(hDC, bPushed ? penHighlight : penBlack); ::MoveToEx(hDC, lpRect->left+1, lpRect->bottom, NULL); ::LineTo(hDC, lpRect->right, lpRect->bottom); ::LineTo(hDC, lpRect->right, lpRect->top); // Shadow color line inside to black line ::SelectObject(hDC, penShadow); ::MoveToEx(hDC, lpRect->left+1, lpRect->bottom-1, NULL); if( bPushed ) { ::LineTo(hDC, lpRect->left+1, lpRect->top-1); ::LineTo(hDC, lpRect->right-1, lpRect->top-1); } else { ::LineTo(hDC, lpRect->right-1, lpRect->bottom-1); ::LineTo(hDC, lpRect->right-1, lpRect->top+1); } // Cleanup ::SelectObject(hDC, penOld); ::DeleteObject(penShadow); ::DeleteObject(penHighlight); ::DeleteObject(penBlack); } //============================================================= DrawHighlight // Draw the highlight around the area void WFE_DrawHighlight( HDC hDC, LPRECT lpRect, COLORREF clrTopLeft, COLORREF clrBottomRight ) { HPEN hpenTopLeft = ::CreatePen( PS_SOLID, 0, clrTopLeft ); HPEN hpenBottomRight = ::CreatePen( PS_SOLID, 0, clrBottomRight ); HPEN hpenOld = (HPEN) ::SelectObject( hDC, hpenTopLeft ); ::MoveToEx( hDC, lpRect->left, lpRect->bottom, NULL ); ::LineTo( hDC, lpRect->left, lpRect->top ); ::LineTo( hDC, lpRect->right - 1, lpRect->top ); ::SelectObject( hDC, hpenBottomRight ); ::LineTo( hDC, lpRect->right - 1, lpRect->bottom - 1); ::LineTo( hDC, lpRect->left, lpRect->bottom - 1); ::SelectObject( hDC, hpenOld ); VERIFY(::DeleteObject( hpenTopLeft )); VERIFY(::DeleteObject( hpenBottomRight )); } //============================================================ DrawRaisedRect void WFE_DrawRaisedRect( HDC hDC, LPRECT lpRect ) { RECT rcTmp = *lpRect; ::InflateRect( &rcTmp, -1, -1 ); #ifdef _WIN32 WFE_DrawHighlight( hDC, &rcTmp, GetSysColor( COLOR_3DLIGHT ), GetSysColor( COLOR_3DSHADOW ) ); WFE_DrawHighlight( hDC, lpRect, GetSysColor( COLOR_3DHILIGHT ), GetSysColor( COLOR_3DDKSHADOW ) ); #else WFE_DrawHighlight( hDC, lpRect, GetSysColor( COLOR_BTNHIGHLIGHT ), GetSysColor( COLOR_BTNSHADOW ) ); WFE_DrawHighlight( hDC, &rcTmp, GetSysColor( COLOR_BTNHIGHLIGHT ), GetSysColor( COLOR_BTNSHADOW ) ); #endif } //=========================================================== DrawLoweredRect void WFE_DrawLoweredRect( HDC hDC, LPRECT lpRect ) { RECT rcTmp = *lpRect; ::InflateRect( &rcTmp, -1, -1 ); #ifdef _WIN32 WFE_DrawHighlight( hDC, &rcTmp, GetSysColor( COLOR_3DSHADOW ), GetSysColor( COLOR_3DLIGHT ) ); WFE_DrawHighlight( hDC, lpRect, GetSysColor( COLOR_3DDKSHADOW ), GetSysColor( COLOR_3DHILIGHT) ); #else WFE_DrawHighlight( hDC, &rcTmp, GetSysColor( COLOR_BTNSHADOW ), GetSysColor( COLOR_BTNHIGHLIGHT ) ); WFE_DrawHighlight( hDC, lpRect, GetSysColor( COLOR_BTNSHADOW ), GetSysColor( COLOR_BTNHIGHLIGHT ) ); #endif } void WFE_Draw3DButtonRect( HDC hDC, LPRECT lpRect, BOOL bPushed ) { if ( bPushed ) { WFE_DrawLoweredRect( hDC, lpRect ); } else { WFE_DrawRaisedRect( hDC, lpRect ); } } void WFE_MakeTransparentBitmap( HDC hDC, HBITMAP hBitmap ) { BITMAP bm; COLORREF cColor; HBITMAP bmAndBack, bmAndObject, bmAndMem; HGDIOBJ bmBackOld, bmObjectOld, bmMemOld; HDC hdcTemp, hdcMem, hdcBack, hdcObject; VERIFY( ::GetObject( hBitmap, sizeof(BITMAP), (LPSTR)&bm ) ); // Create some DCs to hold temporary data. hdcTemp = CreateCompatibleDC(hDC); hdcBack = CreateCompatibleDC(hDC); hdcObject = CreateCompatibleDC(hDC); hdcMem = CreateCompatibleDC(hDC); SelectObject( hdcTemp, hBitmap ); // Monochrome DC bmAndBack = CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 1, NULL); // Monochrome DC bmAndObject = CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 1, NULL); bmAndMem = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight); // Each DC must select a bitmap object to store pixel data. bmBackOld = ::SelectObject(hdcBack, bmAndBack); bmObjectOld = ::SelectObject(hdcObject, bmAndObject); bmMemOld = ::SelectObject(hdcMem, bmAndMem); // Set the background color of the source DC to the color // contained in the parts of the bitmap that should be transparent cColor = SetBkColor(hdcTemp, RGB_TRANSPARENT ); // Create the object mask for the bitmap by performing a BitBlt // from the source bitmap to a monochrome bitmap. BitBlt(hdcObject, 0, 0, bm.bmWidth, bm.bmHeight, hdcTemp, 0, 0, SRCCOPY); // Set the background color of the source DC back to the original // color. SetBkColor(hdcTemp, cColor); // Create the inverse of the object mask. BitBlt(hdcBack, 0, 0, bm.bmWidth, bm.bmHeight, hdcObject, 0, 0, NOTSRCCOPY); // Fill the background of the mem DC with the system background color. FillRect( hdcMem, CRect( 0, 0, bm.bmWidth, bm.bmHeight ), CreateSolidBrush( GetSysColor( COLOR_BTNFACE ) ) ); // Mask out the places where the bitmap will be placed. BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdcObject, 0, 0, SRCAND); // Mask out the transparent colored pixels on the bitmap. BitBlt(hdcTemp, 0, 0, bm.bmWidth, bm.bmHeight, hdcBack, 0, 0, SRCAND); // XOR the bitmap with the background on the destination DC. BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdcTemp, 0, 0, SRCPAINT); // Copy the results back to the source bitmap. BitBlt(hdcTemp, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY); // Delete the memory bitmaps. VERIFY(DeleteObject(SelectObject(hdcBack, bmBackOld))); VERIFY(DeleteObject(SelectObject(hdcObject, bmObjectOld))); VERIFY(DeleteObject(SelectObject(hdcMem, bmMemOld))); // Delete the memory DCs. VERIFY(DeleteDC(hdcMem)); VERIFY(DeleteDC(hdcBack)); VERIFY(DeleteDC(hdcObject)); VERIFY(DeleteDC(hdcTemp)); } #define RGB_TO_RGBQUAD(r,g,b) (RGB(b,g,r)) #define CLR_TO_RGBQUAD(clr) (RGB(GetBValue(clr), GetGValue(clr), GetRValue(clr))) HBITMAP WFE_LoadSysColorBitmap( HINSTANCE hInst, LPCSTR lpszResourceName ) { struct COLORMAP { // use DWORD instead of RGBQUAD so we can compare two RGBQUADs easily DWORD rgbqFrom; int iSysColorTo; }; static const COLORMAP sysColorMap[] = { // mapping from color in DIB to system color { RGB_TO_RGBQUAD(0x00, 0x00, 0x00), COLOR_BTNTEXT }, // black { RGB_TO_RGBQUAD(0x80, 0x80, 0x80), COLOR_BTNSHADOW }, // dark grey { RGB_TO_RGBQUAD(0xC0, 0xC0, 0xC0), COLOR_BTNFACE }, // bright grey { RGB_TO_RGBQUAD(0xFF, 0xFF, 0xFF), COLOR_BTNHIGHLIGHT }, // white { RGB_TO_RGBQUAD(0xFF, 0x00, 0xFF), COLOR_BTNFACE } // hot pink }; const int nMaps = 5; HRSRC hRsrc = ::FindResource(hInst, lpszResourceName, RT_BITMAP); HGLOBAL hglb; if ((hglb = LoadResource(hInst, hRsrc)) == NULL) return NULL; LPBITMAPINFOHEADER lpBitmap = (LPBITMAPINFOHEADER)LockResource(hglb); if (lpBitmap == NULL) return NULL; // make copy of BITMAPINFOHEADER so we can modify the color table int nColorTableSize = 1 << lpBitmap->biBitCount; UINT nSize = CASTUINT(lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD)); LPBITMAPINFOHEADER lpBitmapInfo = (LPBITMAPINFOHEADER)::malloc(nSize); if (lpBitmapInfo == NULL) return NULL; memcpy(lpBitmapInfo, lpBitmap, nSize); // color table is in RGBQUAD DIB format DWORD* pColorTable = (DWORD*)(((LPBYTE)lpBitmapInfo) + (UINT)lpBitmapInfo->biSize); for (int iColor = 0; iColor < nColorTableSize; iColor++) { // look for matching RGBQUAD color in original for (int i = 0; i < nMaps; i++) { if (pColorTable[iColor] == sysColorMap[i].rgbqFrom) { pColorTable[iColor] = CLR_TO_RGBQUAD(::GetSysColor(sysColorMap[i].iSysColorTo)); break; } } } int nWidth = (int)lpBitmapInfo->biWidth; int nHeight = (int)lpBitmapInfo->biHeight; HDC hDCScreen = ::GetDC(NULL); HBITMAP hbm = ::CreateCompatibleBitmap(hDCScreen, nWidth, nHeight); if (hbm != NULL) { HDC hDCGlyphs = ::CreateCompatibleDC(hDCScreen); HBITMAP hbmOld = (HBITMAP)::SelectObject(hDCGlyphs, hbm); LPBYTE lpBits; lpBits = (LPBYTE)(lpBitmap + 1); lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD); StretchDIBits(hDCGlyphs, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight, lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS, SRCCOPY); SelectObject(hDCGlyphs, hbmOld); ::DeleteDC(hDCGlyphs); } ::ReleaseDC(NULL, hDCScreen); // free copy of bitmap info struct and resource itself ::free(lpBitmapInfo); ::FreeResource(hglb); return hbm; } ///////////////////////////////////////////////////////////////////////////// // equivalent to LoadBitmap(), except uses pDC for // correct color mapping of BMP into pDC's palette. HBITMAP wfe_LoadBitmap(HINSTANCE hInst, HDC hDC, LPCSTR pszBmName ) { int iFrames; if ((pszBmName == MAKEINTRESOURCE(IDB_ANIM_0)) && (CUST_IsCustomAnimation(&iFrames))) { char *pFile=NULL,*pUrl=NULL; HBITMAP hCust = NULL; CString csProfileFile; int iError = PREF_CopyConfigString("toolbar.logo.win_large_file",&pFile); ASSERT(iError != PREF_ERROR); // we need to first check the profile for the file (for PE) and then resort to the default of the EXE dir csProfileFile = theApp.m_UserDirectory; csProfileFile += "\\"; csProfileFile += pFile; hCust = WFE_LoadBitmapFromFile(csProfileFile); if (!hCust) // try the default place hCust = WFE_LoadBitmapFromFile(pFile); if (pFile) XP_FREE(pFile); if (hCust) return hCust; } if ((pszBmName == MAKEINTRESOURCE(IDB_ANIMSMALL_0)) && (CUST_IsCustomAnimation(&iFrames))) { char *pFile=NULL,*pUrl=NULL; HBITMAP hCust = NULL; CString csProfileFile; int iError = PREF_CopyConfigString("toolbar.logo.win_small_file",&pFile); ASSERT(iError != PREF_ERROR); // we need to first check the profile for the file (for PE) and then resort to the default of the EXE dir csProfileFile = theApp.m_UserDirectory; csProfileFile += "\\"; csProfileFile += pFile; hCust = WFE_LoadBitmapFromFile(csProfileFile); if (!hCust) // try the default place hCust = WFE_LoadBitmapFromFile(pFile); if (pFile) XP_FREE(pFile); if (hCust) return hCust; } // get the resource from the file HBITMAP hBmp = (HBITMAP)FindResource(hInst, pszBmName, RT_BITMAP); ASSERT(hBmp != NULL); if(!hBmp) return NULL; HGLOBAL hRes = LoadResource(hInst, (HRSRC)hBmp); ASSERT(hRes != NULL); if(!hRes) return NULL; LPBITMAPINFO pPackedDib = (LPBITMAPINFO)(LockResource(hRes)); ASSERT(pPackedDib != NULL); if(!pPackedDib) return NULL; // build a DDB header for pDC BITMAPINFOHEADER bmihDDB; memcpy(&bmihDDB, pPackedDib, sizeof(BITMAPINFOHEADER)); bmihDDB.biBitCount = GetDeviceCaps( hDC, BITSPIXEL); bmihDDB.biClrUsed = 0; bmihDDB.biClrImportant = 0; // create the DDB int iColorTableSize = (1 << pPackedDib->bmiHeader.biBitCount) * sizeof(RGBQUAD); void* pBits = ((char*)pPackedDib) + pPackedDib->bmiHeader.biSize + iColorTableSize; HBITMAP hDDB = CreateDIBitmap(hDC, &bmihDDB, CBM_INIT, pBits, pPackedDib, DIB_RGB_COLORS); // done, clean up UnlockResource(hRes); BOOL bResult = FreeResource(hRes); return hDDB; } static int FindColorIndex(LPRGBQUAD pColors, int nNumColors, COLORREF color) { for(int i = 0; i < nNumColors; i++) { if(pColors[i].rgbRed == GetRValue(color) && pColors[i].rgbGreen == GetGValue(color) && pColors[i].rgbBlue == GetBValue(color)) { return i; } } return -1; } // Loads a bitmap and returns the handle. Retrieves the color of the // first pixel in the image and replaces that entry in the color table // with clrBackground HBITMAP WFE_LoadTransparentBitmap(HINSTANCE hInstance, HDC hDC, COLORREF clrBackground, COLORREF clrTransparent, HPALETTE hPalette, UINT nResID) { // Find the resource HRSRC hrsrc = FindResource(hInstance, MAKEINTRESOURCE(nResID), RT_BITMAP); assert(hrsrc); if (!hrsrc) return NULL; // Get a handle for the resource HGLOBAL hglb = LoadResource(hInstance, hrsrc); if (!hglb) return NULL; // Get a pointer to the BITMAPINFOHEADER LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)LockResource(hglb); // We expect a 4-bpp or 8-bpp image only assert(lpbi->biBitCount == 4 || lpbi->biBitCount == 8); if (lpbi->biBitCount != 4 && lpbi->biBitCount != 8) { UnlockResource(hglb); FreeResource(hglb); return NULL; } #ifdef XP_WIN32 // make copy of BITMAPINFOHEADER so we can modify the color table int nColorTableSize = 1 << lpbi->biBitCount; UINT nSize = CASTUINT(lpbi->biSize + nColorTableSize * sizeof(RGBQUAD)); LPBITMAPINFOHEADER lpBitmapInfo = (LPBITMAPINFOHEADER)::malloc(nSize); if (lpBitmapInfo == NULL) return NULL; memcpy(lpBitmapInfo, lpbi, nSize); // color table is in RGBQUAD DIB format LPRGBQUAD pColors = (LPRGBQUAD)((LPSTR)lpBitmapInfo + lpBitmapInfo->biSize); LPRGBQUAD pOldColors = (LPRGBQUAD)((LPSTR)lpbi + lpbi->biSize); UINT nClrUsed = lpbi->biClrUsed == 0 ? 1 << lpbi->biBitCount : (UINT)lpbi->biClrUsed; LPBYTE lpBits = (LPBYTE)(pOldColors + nClrUsed); #else LPRGBQUAD pColors = (LPRGBQUAD)((LPSTR)lpbi + (WORD)lpbi->biSize); UINT nClrUsed = lpbi->biClrUsed == 0 ? 1 << lpbi->biBitCount : (UINT)lpbi->biClrUsed; LPBYTE lpBits = (LPBYTE)(pColors + nClrUsed); #endif // Munge the color table entry // int nIndex = lpbi->biBitCount == 8 ? *lpBits : *lpBits & 0xF; int nIndex = FindColorIndex(pColors, nClrUsed, clrTransparent); pColors[nIndex].rgbGreen = GetGValue(clrBackground); pColors[nIndex].rgbRed = GetRValue(clrBackground); pColors[nIndex].rgbBlue = GetBValue(clrBackground); // Create the DDB HBITMAP hBitmap; HPALETTE hOldPalette = SelectPalette(hDC, hPalette, FALSE); #ifdef XP_WIN32 hBitmap = CreateDIBitmap(hDC, lpBitmapInfo, CBM_INIT, lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS); ::free(lpBitmapInfo); #else hBitmap = CreateDIBitmap(hDC, lpbi, CBM_INIT, lpBits, (LPBITMAPINFO)lpbi, DIB_RGB_COLORS); //Restore the bitmap in case we want to go through this process again pColors[nIndex].rgbRed = GetRValue(clrTransparent); pColors[nIndex].rgbGreen = GetGValue(clrTransparent); pColors[nIndex].rgbBlue = GetBValue(clrTransparent); #endif // The parent should unselect the palette when they got destroy. SelectPalette(hDC, hOldPalette, TRUE); // Release the resource UnlockResource(hglb); FreeResource(hglb); return hBitmap; } void WFE_InitializeUIPalette(HDC hDC) { IL_IRGB transparentColor; transparentColor.index = 0; transparentColor.red = 255; transparentColor.green = 0; transparentColor.blue = 255; if(ghPalette == NULL) { ghPalette = CDCCX::CreateColorPalette(hDC, transparentColor, 8); } } BOOL WFE_IsGlobalPalette(HPALETTE hPal) { return (hPal == ghPalette); } HPALETTE WFE_GetUIPalette(CWnd* parent) { // for normal case. if (!parent) return ghPalette; else if (parent->IsKindOf(RUNTIME_CLASS(CGenericFrame))) { CWinCX* pcxWin = ((CGenericFrame*)parent)->GetMainWinContext(); if (pcxWin) { HPALETTE hPalette = pcxWin->GetPalette(); if (hPalette) return hPalette; else return ghPalette; } else return ghPalette; } else if (parent->IsKindOf(RUNTIME_CLASS(CInPlaceFrame))) { // for OLE // XXX write me. CWinCX *pWinCX = (CWinCX*)FEU_GetLastActiveFrameContext(); if (pWinCX) { HPALETTE hPalette = pWinCX->GetPalette(); if (hPalette) return hPalette; else return ghPalette; } else return ghPalette; } else // for other case. return ghPalette; } void WFE_DestroyUIPalette(void) { if(ghPalette) DeleteObject(ghPalette); } typedef struct { COLORREF clrBackground; HBITMAP bitmap; } BitmapMapEntry; // if bTransparent is FALSE then clrBackground and clrTransparent are ignored HBITMAP WFE_LookupLoadAndEnterBitmap(HDC hDC, UINT nID, BOOL bTransparent, HPALETTE hPalette, COLORREF clrBackground, COLORREF clrTransparent) { HINSTANCE hInst = AfxGetResourceHandle(); HBITMAP hBitmap; BitmapMapEntry *pEntry = NULL; if(!gBitmapMap.Lookup(nID, (void*&)pEntry) || pEntry->clrBackground != clrBackground) { HPALETTE hOldPalette = SelectPalette(hDC, hPalette, FALSE); if(bTransparent) hBitmap = WFE_LoadTransparentBitmap(hInst, hDC, clrBackground, clrTransparent, hPalette, nID); else { hBitmap = wfe_LoadBitmap(hInst, hDC, MAKEINTRESOURCE(nID)); } if(!pEntry) pEntry = new BitmapMapEntry; pEntry->clrBackground = clrBackground; pEntry->bitmap = hBitmap; gBitmapMap.SetAt(nID, (void*&)pEntry); ::SelectPalette(hDC, hOldPalette, TRUE); } return pEntry->bitmap; } void WFE_RemoveBitmapFromMap(UINT nID) { BitmapMapEntry *pEntry = NULL; if(gBitmapMap.Lookup(nID, (void*&)pEntry)) { ::DeleteObject(pEntry->bitmap); delete pEntry; gBitmapMap.RemoveKey(nID); } } void WFE_DestroyBitmapMap(void) { POSITION pos; WORD dwKey; BitmapMapEntry *pEntry = NULL; // also destroy bitmaps; pos = gBitmapMap.GetStartPosition(); while(pos) { gBitmapMap.GetNextAssoc(pos, dwKey,(void *&)pEntry); DeleteObject(pEntry->bitmap); delete pEntry; } gBitmapMap.RemoveAll(); } HFONT WFE_GetUIFont(HDC hDC) { #ifdef XP_WIN32 if (sysInfo.m_bWin4 == TRUE) ghFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT); else #endif if (sysInfo.m_bDBCS == FALSE) ghFont = (HFONT) GetStockObject(ANSI_VAR_FONT); else { if (ghFont == NULL) { LOGFONT lf; XP_MEMSET(&lf,0,sizeof(LOGFONT)); lf.lfPitchAndFamily = FF_SWISS; lf.lfCharSet = IntlGetLfCharset(0); lf.lfHeight = -MulDiv(8, GetDeviceCaps(hDC, LOGPIXELSY), 72); strcpy(lf.lfFaceName, IntlGetUIPropFaceName(0)); lf.lfWeight = 400; ghFont = theApp.CreateAppFont( lf ); } } return ghFont; } void WFE_DestroyUIFont(void) { } CFrameWnd *WFE_GetOwnerFrame(CWnd *pWnd) { return pWnd->GetTopLevelFrame(); } int WFE_FindMenu(CMenu *pMenu, CString& menuItemName) { if (!pMenu) return -1; int nCount = pMenu->GetMenuItemCount(); for(int i = 0; i < nCount; i++) { char lpszMenuString[64]; pMenu->GetMenuString(i, lpszMenuString, 64, MF_BYPOSITION); if(strcmp( lpszMenuString, menuItemName) == 0) return i; } return -1; } int WFE_FindMenuItem(CMenu *pMenu, UINT nCommand) { if (!pMenu) return -1; int nCount = pMenu->GetMenuItemCount(); for(int i = 0; i < nCount; i++) { UINT nID = pMenu->GetMenuItemID(i); if(nID == nCommand) return i; } return -1; } #ifdef FEATURE_LOAD_BITMAP_FILES #include "loadbmps.i00" #endif HBITMAP WFE_LoadBitmapFromFile (const char* szFileName) { HBITMAP hRetval = NULL; #ifdef FEATURE_LOAD_BITMAP_FILES hRetval = wfe_loadbitmapfromfile(szFileName); #else #ifdef _WIN32 // This only works on >= 95 and NT4. hRetval = (HBITMAP)LoadImage(NULL, szFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE); #endif #endif return(hRetval); } void WFE_FillSolidRect(CDC *pDC, CRect crRect, COLORREF rgbFill) { #ifdef XP_WIN32 pDC->FillSolidRect(crRect, rgbFill); #else ::SetBkColor(pDC->m_hDC, rgbFill); ::ExtTextOut(pDC->m_hDC, 0, 0, ETO_OPAQUE, crRect, NULL, 0, NULL); #endif } #define STRING_ELLIPSES _T("...") int WFE_DrawTextEx( int iCSID, HDC hdc, LPTSTR lpchText, int cchText, LPRECT lprc, UINT dwDTFormat, UINT dwMoreFormat ) { if (cchText < 0) cchText = _tcslen(lpchText); /* DrawTextEx does not handle DT_END_ELLIPSIS so please do not use the follwoing code to do optomization. #ifdef XP_WIN32 if ((dwMoreFormat == WFE_DT_CROPRIGHT) && sysInfo.m_bWin4) { dwDTFormat |= DT_END_ELLIPSIS; return CIntlWin::DrawTextEx(iCSID, hdc, (LPTSTR) lpchText, cchText, lprc, dwDTFormat, NULL); } #endif */ LPTSTR pString = NULL; CSize cs = CIntlWin::GetTextExtent( iCSID, hdc, lpchText, cchText); if (cs.cx > (lprc->right - lprc->left) ) { int iEllipsesLength = _tcslen(STRING_ELLIPSES); pString = new _TCHAR[cchText + iEllipsesLength + 2]; if (!pString) { ASSERT(0); return 0; } _tcscpy(pString,lpchText); switch(dwMoreFormat) { case WFE_DT_CROPRIGHT: { int iEnd = cchText; while( cs.cx > (lprc->right - lprc->left) ) { int iNewEnd = INTL_PrevCharIdxInText(iCSID, (unsigned char*) lpchText, iEnd); if ((iNewEnd == 0) || (iNewEnd == iEnd)) { delete [] pString; return cs.cy; } iEnd = iNewEnd; _tcscpy(&pString[iNewEnd], STRING_ELLIPSES); cs = CIntlWin::GetTextExtent( iCSID, hdc, pString, strlen(pString)); } } break; case WFE_DT_CROPCENTER: { int iRemove = 0; while( cs.cx > (lprc->right - lprc->left) ) { if (++iRemove >= cchText) { delete [] pString; return cs.cy; } INTL_MidTruncateString(iCSID, lpchText, pString, cchText-iRemove); cs = CIntlWin::GetTextExtent( iCSID, hdc, pString, strlen(pString)); } } break; case WFE_DT_CROPLEFT: { int iBegin = 0; while( cs.cx > (lprc->right - lprc->left) ) { int iNewBegin = INTL_NextCharIdxInText(iCSID, (unsigned char*) lpchText, iBegin); if ((iNewBegin >= cchText) || (iNewBegin == iBegin)) { delete [] pString; return cs.cy; } iBegin = iNewBegin; _tcscpy(pString, STRING_ELLIPSES); _tcscpy(&pString[iEllipsesLength], &lpchText[iNewBegin]); cs = CIntlWin::GetTextExtent( iCSID, hdc, pString, strlen(pString)); } } break; } lpchText = pString; } int res = CIntlWin::DrawText( iCSID, hdc, (LPTSTR) lpchText, -1, lprc, dwDTFormat ); if (pString) delete [] pString; return res; } #ifdef __BORLANDC__ #define _S_IFREG S_IFREG #endif // If pszLocalName is not NULL, we return the full pathname // in local platform syntax, even if file is not found. // Caller must free this string. // Returns TRUE if file already exists // MODULE_PRIVATE Bool XP_ConvertUrlToLocalFile( const char * szURL, char **pszLocalName) { BOOL bFileFound = FALSE; // Default assumes no file found - no local filename if ( pszLocalName ) { *pszLocalName = NULL; } // Must have "file:" URL type and at least 1 character after "///" if ( szURL == NULL || !NET_IsLocalFileURL((char*)szURL) || XP_STRLEN(szURL) <= 8 ) { return FALSE; } // Extract file path from URL: e.g. "/c|/foo/file.html" char *szPath = NET_ParseURL( szURL, GET_PATH_PART); if ( szPath == NULL ) { return FALSE; } // Get filename - skip over initial "/" char *szFileName; if (szPath[0] == '/' && szPath[1] == '/') { // bug 35222, if url is a shared Windows (NT or Win95) directory using UNC name, // don't skip over the first slash, WH_FileName will do the right thing. // I have the suspicion that we should never be skipping the first slash, that // WH_FileName knows what to do, but I don't want to make a risky change now. szFileName = WH_FileName(szPath, xpURL); } else { szFileName = WH_FileName(szPath+1, xpURL); } XP_FREE(szPath); // Test if file exists XP_StatStruct statinfo; if ( -1 != XP_Stat(szFileName, &statinfo, xpURL) && statinfo.st_mode & _S_IFREG ) { bFileFound = TRUE; } if ( pszLocalName ) { // Pass string to caller // (we didn't change it, so there's no need to XP_STRDUP) *pszLocalName = szFileName; } return bFileFound; } // Create a backup filename for renaming current file before saving data // Input should be be URL file type "file:///..." // Caller must free the string with XP_FREE // MODULE_PRIVATE char * XP_BackupFileName( const char * szURL ) { char * szFileName; // Must have "file:" URL type and at least 1 character after "///" if ( szURL == NULL || !NET_IsLocalFileURL((char*)szURL) || XP_STRLEN(szURL) <= 8 ) { return NULL; } // Add extra space for 8+3 temp filename, but subtract for "file:///" szFileName = (char *) XP_ALLOC((XP_STRLEN(szURL)+5)*sizeof(char)); if ( szFileName == NULL ) { return NULL; } // Get filename but ignore "file:///" { char* filename; if (szURL[8] == '/') { // bug 35222, if url is a shared Windows (NT or Win95) directory using UNC name, // don't skip over the first slash, WH_FileName will do the right thing. // I have the suspicion that we should never be skipping the first slash, that // WH_FileName knows what to do, but I don't want to make a risky change now. filename = WH_FileName(szURL+7, xpURL); } else { filename = WH_FileName(szURL+8, xpURL); } if (!filename) return NULL; XP_STRCPY(szFileName,filename); XP_FREE(filename); } #ifdef XP_WIN16 char * pEnd = szFileName + XP_STRLEN( szFileName ); while ( *pEnd != '\\' && pEnd != szFileName ) { if ( *pEnd == '.' ) { // Truncate at current extension *pEnd = '\0'; } pEnd--; } #endif // Add extension to the filename XP_STRCAT( szFileName, ".BAK" ); return szFileName; } // Copy file routine for Editor - ask user permission // to overwrite existing file. // Params may be local file format or "file://" URL format, // and assumes full pathnames BOOL FE_CopyFile(const char *cpSrc, const char *cpTarg) { char * szSrc = NULL; char * szTarg = NULL; BOOL bFreeSrc = FALSE; BOOL bFreeTarg = FALSE; BOOL bSrcExists = TRUE; BOOL bTargExists = FALSE; XP_StatStruct statinfo; CString csMsg; BOOL bResult = FALSE; if ( NET_IsLocalFileURL((char*)cpSrc) ){ bSrcExists = XP_ConvertUrlToLocalFile(cpSrc, &szSrc); bFreeSrc = (szSrc != NULL); } else { // Use supplied name - assume its a file szSrc = (char*)cpSrc; bSrcExists = (-1 != XP_Stat(cpSrc, &statinfo, xpURL)) && (statinfo.st_mode & _S_IFREG); } if ( bSrcExists ){ if ( NET_IsLocalFileURL((char*)cpTarg) ){ bTargExists = XP_ConvertUrlToLocalFile(cpTarg, &szTarg); bFreeTarg = (szTarg != NULL); } else { bTargExists = (-1 != XP_Stat(cpTarg, &statinfo, xpURL)) && (statinfo.st_mode & _S_IFREG); // Use supplied name - assume its a file szTarg = (char*)cpTarg; } if ( bTargExists ) { AfxFormatString1(csMsg, IDS_WARN_REPLACE_FILE, szTarg); if ( IDYES == MessageBox( NULL, csMsg, szLoadString(IDS_COPY_FILE), MB_YESNO | MB_ICONQUESTION) ) { bResult = WFE_CopyFile(szSrc, szTarg); } } else { bResult = WFE_CopyFile(szSrc, szTarg); } if ( !bResult ) { AfxFormatString1(csMsg, IDS_ERR_COPY_FILE, szSrc); MessageBox( NULL, csMsg, szLoadString(IDS_COPY_FILE), MB_OK | MB_ICONSTOP); } } else { // Can't copy if no source! AfxFormatString1(csMsg, IDS_ERR_SRC_NOT_FOUND, szSrc); MessageBox( NULL, csMsg, szLoadString(IDS_COPY_FILE), MB_OK | MB_ICONSTOP); } if ( bFreeSrc ) { XP_FREE(szSrc); } if ( bFreeTarg ) { XP_FREE(szTarg); } return bResult; } // CLM: Some simple functions to aid in COLORREF to LO_Color conversions // Fill a LoColor structure void WFE_SetLO_Color( COLORREF crColor, LO_Color *pLoColor ) { if ( pLoColor ) { pLoColor->red = GetRValue(crColor); pLoColor->green = GetGValue(crColor); pLoColor->blue = GetBValue(crColor); } } // This allocates a new LoColor structure if it // does not exist void WFE_SetLO_ColorPtr( COLORREF crColor, LO_Color **ppLoColor ) { if ( ppLoColor == NULL ) { return; } if ( *ppLoColor == NULL ) { *ppLoColor = XP_NEW( LO_Color ); } (*ppLoColor)->red = GetRValue(crColor); (*ppLoColor)->green = GetGValue(crColor); (*ppLoColor)->blue = GetBValue(crColor); } // Convert a LO_Color structure or get the default // default document colors COLORREF WFE_LO2COLORREF( LO_Color * pLoColor, int iColorIndex ) { #ifdef MOZ_NGLAYOUT XP_ASSERT(0); return 0; #else COLORREF crColor = 0; if ( pLoColor ) { crColor = RGB( pLoColor->red, pLoColor->green, pLoColor->blue); } else { crColor = RGB(lo_master_colors[iColorIndex].red, lo_master_colors[iColorIndex].green, lo_master_colors[iColorIndex].blue); } return crColor; #endif /* MOZ_NGLAYOUT */ } // Parse a "#FFEEAA" style color string into colors make a COLORREF BOOL WFE_ParseColor(char *pRGB, COLORREF * pCRef ) { #ifdef MOZ_NGLAYOUT XP_ASSERT(0); return FALSE; #else uint8 red, green, blue; BOOL bColorsFound = LO_ParseRGB(pRGB, &red, &green, &blue); if ( bColorsFound ) { *pCRef = RGB( red, green, blue); } return bColorsFound; #endif /* MOZ_NGLAYOUT */ } // Helper to clear data void WFE_FreeLO_Color(LO_Color_struct **ppLo) { if ( *ppLo ) { XP_FREE( *ppLo ); *ppLo = NULL; } } #ifdef EDITOR // Get current color at caret or within a selection COLORREF WFE_GetCurrentFontColor(MWContext * pMWContext) { COLORREF crColor = DEFAULT_COLORREF; EDT_CharacterData *pCharData = EDT_GetCharacterData(pMWContext); if( !pMWContext ){ return crColor; } if( pCharData && 0 != (pCharData->mask & TF_FONT_COLOR) ){ // We are sure about the color if( pCharData->pColor ){ // If we have a LO_Color struct, then use its color crColor = WFE_LO2COLORREF( pCharData->pColor, LO_COLOR_FG ); } } else { // We are not sure of color crColor = MIXED_COLORREF; } if(pCharData) EDT_FreeCharacterData(pCharData); return crColor; } #endif // EDITOR /******************************************************************************/ /* Thread-safe entry points: */ extern PRMonitor* _pr_TempName_lock; char * WH_TempName(XP_FileType type, const char * prefix) { static char buf[_MAX_PATH]; /* protected by _pr_TempName_lock */ char* result; result = XP_STRDUP(xp_TempFileName(type, prefix, NULL, buf)); return result; } // The caller is responsible for XP_FREE()ing the return string PUBLIC char * WH_FileName (const char *name, XP_FileType type) { char* myName; char* result; /* ** I'm not sure this lock is really needed by windows, but just ** to be safe: */ result = xp_FileName(name, type, &myName); return myName; } int32 FE_LPtoDPoint(MWContext *pContext, int32 logicalPoint) { int32 iRetval = logicalPoint; CAbstractCX *pAbstract = ABSTRACTCX(pContext); if(pAbstract && pAbstract->IsDCContext()) { CDCCX *pCx = CXDC(pContext); HDC hDC = pCx->GetContextDC(); if(hDC) { POINT tempPoint; tempPoint.x = 1; tempPoint.y = logicalPoint; // it is printing, convert them from device point to logical point for printers if( TRUE == ::LPtoDP(hDC, &tempPoint, 1) ) iRetval = tempPoint.y; } } return(iRetval); } /******************************************************************************/ #ifdef XP_WIN16 static UINT PASCAL DirOpenHookProc( HWND hDlg, /* window handle of the dialog box */ UINT message, /* type of message */ UINT wParam, /* message-specific information */ LONG lParam) #else static BOOL APIENTRY DirOpenHookProc( HWND hDlg, /* window handle of the dialog box */ UINT message, /* type of message */ UINT wParam, /* message-specific information */ LONG lParam) #endif { switch (message) { case WM_INITDIALOG: //We must put something in this field, even though it is hidden. This is //because if this field is empty, or has something like "*.txt" in it, //and the user hits OK, the dlg will NOT close. We'll jam something in //there (like "k5bg") so when the user hits OK, the dlg terminates. //Note that we'll deal with the "k5bg" during return processing (see below) SetDlgItemText(hDlg, edt1, "k5bg"); break; } return (FALSE); } ///////////////////////////////////////////////////////////////////////////// // CDirDialog CDirDialog::CDirDialog(CWnd* pParent, LPCTSTR pInitDir) : CFileDialog(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, NULL, pParent) { m_szIniFile[0] = '\0'; m_ofn.lStructSize = sizeof(OPENFILENAME); m_ofn.hwndOwner = pParent->GetSafeHwnd(); m_ofn.hInstance = AfxGetResourceHandle(); m_ofn.lpstrFile = m_szIniFile; m_ofn.nMaxFile = 132; m_ofn.lpstrFilter = NULL; m_ofn.lpstrCustomFilter = NULL; m_ofn.lpstrInitialDir = pInitDir; m_ofn.lpstrFileTitle = NULL; m_ofn.nMaxFileTitle = 132; m_ofn.lpstrDefExt = (LPSTR)NULL; m_ofn.lpstrDefExt = ""; #ifdef XP_WIN32 m_ofn.Flags = OFN_NOCHANGEDIR | OFN_ENABLETEMPLATE | OFN_ENABLEHOOK |OFN_NONETWORKBUTTON |OFN_LONGNAMES; m_ofn.lpfnHook = (LPOFNHOOKPROC)DirOpenHookProc; #else m_ofn.Flags = OFN_NOCHANGEDIR | OFN_ENABLETEMPLATE | OFN_ENABLEHOOK; m_ofn.lpfnHook = &DirOpenHookProc; #endif m_ofn.lpTemplateName = (LPTSTR)MAKEINTRESOURCE(FILEOPENORD); } void CDirDialog::DoDataExchange(CDataExchange* pDX) { CFileDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CDirDialog, CFileDialog) END_MESSAGE_MAP() void FE_PokeLibSecOnIdle() { long lVal; DWORD dwVal; HWND hWnd; BYTE buf[20]; int nBytes; nBytes = RNG_GetNoise(buf, sizeof(buf)); RNG_RandomUpdate(buf, nBytes); dwVal = GetMessagePos(); // mouse position based RNG_RandomUpdate(&dwVal, sizeof(dwVal)); lVal = GetMessageTime(); // time from startup to last message RNG_RandomUpdate(&lVal, sizeof(lVal)); lVal = GetTickCount(); // we are about to go idle so this is probably RNG_RandomUpdate(&lVal, sizeof(lVal)); // different from the one above hWnd = GetClipboardOwner(); // 2 or 4 bytes RNG_RandomUpdate((void *)&hWnd, sizeof(HWND)); } void WFE_DrawDragRect(CDC* pdc, LPCRECT lpRect, SIZE size, LPCRECT lpRectLast, SIZE sizeLast, CBrush* pBrush, CBrush* pBrushLast) { #ifdef XP_WIN32 pdc->DrawDragRect(lpRect, size, lpRectLast, sizeLast, pBrush, pBrushLast); #endif } void FE_GetDocAndWindowPosition(MWContext * context, int32 *pX, int32 *pY, int32 *pWidth, int32 *pHeight ) { if(context && ABSTRACTCX(context) && ABSTRACTCX(context)->IsWindowContext() == TRUE) { CPaneCX *pPaneCX = VOID2CX(context->fe.cx, CPaneCX); *pX = pPaneCX->GetOriginX(); *pY = pPaneCX->GetOriginY(); // When we report the size to layout, we must always take care to subtract // for the size of the scrollbars if we have dynamic or always on // scrollers. if(pPaneCX->DynamicScrollBars() == FALSE && pPaneCX->IsHScrollBarOn() == FALSE && pPaneCX->IsVScrollBarOn() == FALSE) { *pWidth = pPaneCX->GetWidth(); *pHeight = pPaneCX->GetHeight(); } else { *pWidth = pPaneCX->GetWidth() - sysInfo.m_iScrollWidth; *pHeight = pPaneCX->GetHeight() - sysInfo.m_iScrollHeight; } } else { // No window here.... ASSERT(0); *pX = *pY = *pHeight = *pWidth = 0; } } /* Convert an HTML SIZE param value (1-7) into POINT-SIZE value */ int16 FE_CalcFontPointSize(MWContext * pMWContext, intn iSize, XP_Bool bFixedWidth) { if( pMWContext /*&& wfe_iFontSizeMode == ED_FONTSIZE_ADVANCED*/ ) { EncodingInfo *pEncoding = theApp.m_pIntlFont->GetEncodingInfo(pMWContext); int iBaseSize = bFixedWidth ? pEncoding->iFixSize : pEncoding->iPropSize; CDCCX *pDC = VOID2CX(pMWContext->fe.cx, CDCCX); if( pDC && iSize >= MIN_FONT_SIZE && iSize <= MAX_FONT_SIZE ) return (int16)(pDC->CalcFontPointSize(iSize, iBaseSize)); } return 0; }