📄 hurl.cpp
字号:
// Add the URL as the direct object
err = AEPutParamPtr(theAppleEventPtr, keyDirectObject, typeChar, pURL, strlen(pURL));
require_noerr(err, CouldntPutDirectObject);
{
// Add the targetted window parameter
const long kSameWindow = -1, kNewWindow = 0;
long window = bNewWindow ? kNewWindow : kSameWindow;
err = AEPutParamPtr(theAppleEventPtr, kOpenUrlWindowID, typeLongInteger, &window, sizeof(window));
require_noerr(err, CouldntPutWindow);
(void) AEDisposeDesc(&target);
return TRUE;
}
// error handling: reverse-order cleanup
CouldntPutWindow:
CouldntPutDirectObject:
(void) AEDisposeDesc(theAppleEventPtr);
AECreateAppleEventFailed:
(void) AEDisposeDesc(&target);
CreateDescFailed:
return FALSE;
}
BOOL MakeOpenDocumentsEventFromURL(OSType appSignature, const char* pURL, AEDesc *theAppleEventPtr, Boolean bNewWindow)
{
#ifdef _MAC_UNIX
HX_ASSERT("unimplemented" == NULL);
#else
AEDesc target;
OSErr err;
AliasHandle alias = NULL;
CHXFileSpecifier fileSpec;
FSRef fileRef;
theAppleEventPtr->dataHandle = NULL;
target.dataHandle = NULL;
fileSpec.SetFromURL(pURL);
require(CHXFileSpecUtils::FileExists(fileSpec), bail);
fileRef = (FSRef) fileSpec;
// Create an application signature address.
err = AECreateDesc(typeApplSignature, &appSignature, sizeof(OSType), &target);
require_noerr(err, bail);
// Create the Apple event
err = AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments, &target,
kAutoGenerateReturnID, kAnyTransactionID, theAppleEventPtr);
require_noerr(err, bail);
// Add an alias as the direct object
err = FSNewAlias(NULL, &fileRef, &alias);
require_noerr(err, bail);
err = AEPutParamPtr(theAppleEventPtr, keyDirectObject, typeAlias, *alias, ::GetHandleSize((Handle) alias));
require_noerr(err, bail);
(void) AEDisposeDesc(&target);
DisposeHandle((Handle) alias);
return TRUE;
// error handling: reverse-order cleanup
bail:
if (theAppleEventPtr->dataHandle) (void) AEDisposeDesc(theAppleEventPtr);
if (target.dataHandle) (void) AEDisposeDesc(&target);
if (alias) DisposeHandle((Handle) alias);
return FALSE;
#endif
}
#if defined(_CARBON) || defined(_MAC_UNIX)
BOOL GetPreferredOrSystemBrowser(IHXPreferences* pPrefs, FSRef *outBrowserFSRef, OSType *outBrowserSignature)
{
#ifdef _MAC_UNIX
HX_ASSERT("GetPreferredOrSystemBrowser unimplemented" == NULL);
#else
FSRef browserFSRef;
OSType defaultBrowserSignature;
BOOL bSuccess;
ZeroInit(&browserFSRef);
bSuccess = GetPreferredBrowser(pPrefs, &browserFSRef, &defaultBrowserSignature);
if (!bSuccess)
{
// there isn't a preferred browser in prefs; get one from InternetConfig, or else look
// for any of our known browsers
unsigned char *kDontCareBrowserName = NULL;
OSErr err;
err = HXInternetConfigMac::GetHTTPHelper(&defaultBrowserSignature, kDontCareBrowserName);
if (err == noErr)
{
err = GetApplicationFSRefFromSignature(defaultBrowserSignature, &browserFSRef);
}
if (err != noErr)
{
defaultBrowserSignature = NETSCAPE_CREATOR;
for (int idx = 0; BrowserCreators[idx] != 0; idx++)
{
if (noErr == GetApplicationFSRefFromSignature(BrowserCreators[idx], &browserFSRef))
{
defaultBrowserSignature = BrowserCreators[idx];
break;
}
}
}
if (err == noErr)
{
bSuccess = TRUE;
}
}
if (outBrowserSignature) *outBrowserSignature = defaultBrowserSignature;
if (outBrowserFSRef) *outBrowserFSRef = browserFSRef;
return bSuccess;
#endif
}
BOOL GetPreferredBrowser(IHXPreferences* pPrefs, FSRef *outBrowserFSRef, OSType *outBrowserSignature)
{
#ifdef _MAC_UNIX
HX_ASSERT("GetPreferredBrowser unimplemented" == NULL);
#else
HX_RESULT res;
OSStatus err;
const char* theBrowserPref;
FinderInfo fileInfo;
IHXBuffer* pBuffer = NULL;
check(outBrowserFSRef != NULL && outBrowserSignature != NULL);
require_nonnull_quiet(pPrefs, NoPrefsAvailable);
res = pPrefs->ReadPref("PreferredBrowser", pBuffer);
require_quiet(SUCCEEDED(res), CantGetPreferredBrowser);
theBrowserPref = (const char*) pBuffer->GetBuffer();
require_nonnull(theBrowserPref, CantGetPrefFromBuffer);
require_quiet(strlen(theBrowserPref) > 1, NoBrowserSet);
if (strlen(theBrowserPref) == 4)
{
// the pref is an OSType
*outBrowserSignature = *(OSType *) theBrowserPref;
err = GetApplicationFSRefFromSignature(*outBrowserSignature, outBrowserFSRef);
require_noerr_quiet(err, CantGetBrowserFSRef);
}
else
{
// the pref is a persistent file spec or a path
CHXFileSpecifier browserSpec;
(void) browserSpec.SetFromPersistentString(theBrowserPref);
require(browserSpec.IsSet(), CantMakeBrowserSpec);
*outBrowserFSRef = (FSRef) browserSpec;
err = FSGetFinderInfo(outBrowserFSRef, &fileInfo, NULL, NULL);
require_noerr_quiet(err, CantGetBrowserType);
*outBrowserSignature = fileInfo.file.fileCreator;
}
HX_RELEASE(pBuffer);
return TRUE;
CantGetBrowserType:
CantGetAppRef:
CantMakeBrowserSpec:
CantGetBrowserFSRef:
NoBrowserSet:
CantGetPrefFromBuffer:
HX_RELEASE(pBuffer);
CantGetPreferredBrowser:
NoPrefsAvailable:
return FALSE;
#endif
}
static BOOL LaunchMacBrowserCarbon(const char* pURL, IHXPreferences* pPrefs, BOOL bBringToFront, BOOL bNewWindow)
{
#ifdef _MAC_UNIX
HX_ASSERT("LaunchMacBrowserCarbon unimplemented" == NULL);
#else
FSRef browserFSRef;
//BOOL bSuccess;
OSType defaultBrowserSignature;
OSType openBrowserSignature;
OSStatus err;
BOOL bLaunched;
int idx;
bLaunched = FALSE;
// get the preferred browser from prefs, if it's available; otherwise, find some other browser
// to default to
defaultBrowserSignature = 0;
ZeroInit(&browserFSRef);
GetPreferredOrSystemBrowser(pPrefs, &browserFSRef, &defaultBrowserSignature);
// see if the preferred browser, or any other, is running
openBrowserSignature = 0;
if (CheckForApplicationRunning(defaultBrowserSignature))
{
openBrowserSignature = defaultBrowserSignature;
}
else
{
for (idx = 0; BrowserCreators[idx] != 0; idx++)
{
if (CheckForApplicationRunning(BrowserCreators[idx]))
{
openBrowserSignature = BrowserCreators[idx];
break;
}
}
}
// CZ 10/29/02 - if a browser is running and the current app is that browser
// then we must be running the embedded player
// in this case don't force the browser to come to the front
// ie. a hurl from the embedded player shouldn't bring the browser to the front
if (GetCurrentAppSignature() == openBrowserSignature)
{
bBringToFront = FALSE;
}
// GR 10/1/02 Nasty hack: Netscape 6 and 7 can't deal with URLs in standard OS X format, so
// for that browser and for local URLs only, we'll make a bogus old-style file:/// URL
// by taking a full path and replacing colons with slashes
CHXString strNetscapeLocalURL;
if (openBrowserSignature == 'MOSS' || (openBrowserSignature == 0 && defaultBrowserSignature == 'MOSS'))
{
CHXFileSpecifier fileSpec;
fileSpec.SetFromURL(pURL);
if (fileSpec.IsSet())
{
CHXString strPathMunge = fileSpec.GetPathName();
for (int idx = 0; idx < strPathMunge.GetLength(); idx++)
{
if (strPathMunge[idx] == ':') strPathMunge.SetAt(idx, '/');
else if (strPathMunge[idx] == '/') strPathMunge.SetAt(idx, ':');
}
strPathMunge.FindAndReplace(" ", "%20", TRUE);
strNetscapeLocalURL = "file:///";
strNetscapeLocalURL += strPathMunge;
pURL = (const char *) strNetscapeLocalURL;
}
}
// try to send the URL via an Apple event to an open browser
if (openBrowserSignature)
{
const BOOL bAsync = TRUE;
bLaunched = SendOpenURLOrdered(openBrowserSignature, pURL, bAsync, bBringToFront, bNewWindow);
}
// if necessary, launch a browser
if (!bLaunched)
{
if (IsRunningNativeOnMacOSX())
{
CHXFileSpecifier tempSpec;
if (IsLocalFileURLAPotentialProblemBecauseOfPercentEncodedUTF8Chars(pURL))
{
// we handle the UTF8 problem only with local files; avoid the problem
// by opening file document directly instead of using a temp file
tempSpec.SetFromURL(pURL);
}
else
{
// Is OS X we can't pass an Apple event with the launch (can we?), so we'll make a document to
// open which redirects to the real page
// make a temp file with the redirect to the real URL; we do this for network URLs
// or for local URLs that don't have UTF-8
CHXDirSpecifier tempDirSpec;
CHXString strRedirect;
const BOOL kReplaceExistingTempFile = TRUE;
strRedirect = "<HEAD>\n<META HTTP-EQUIV=\"refresh\" CONTENT=\"0;URL=";
strRedirect += pURL;
strRedirect += "\">\n</HEAD>\n";
// make a file spec for a temp file, create the file and open it,
// and write the redirect into the file
tempDirSpec = CHXFileSpecUtils::MacFindFolder(kOnAppropriateDisk, kChewableItemsFolderType);
tempSpec = CHXFileSpecUtils::GetUniqueTempFileSpec(tempDirSpec, "HX_hurl_%.html", "%");
check(tempSpec.IsSet());
err = CHXFileSpecUtils::WriteTextFile(tempSpec, strRedirect, kReplaceExistingTempFile);
check_noerr(err);
}
// launch the browser with that temp file
if (err == noErr)
{
LSLaunchFSRefSpec launchSpec;
ZeroInit(&launchSpec);
launchSpec.appRef = &browserFSRef;
launchSpec.numDocs = 1;
launchSpec.itemRefs = (FSRef *) tempSpec;
launchSpec.launchFlags = kLSLaunchDefaults | (bBringToFront ? 0 : kLSLaunchDontSwitch);
err = LSOpenFromRefSpec(&launchSpec, NULL); // NULL -> don't care about FSRef of launched app
}
if (err == noErr)
{
bLaunched = TRUE;
}
}
else
{
// OS 9 launch
AppleEvent theEvent;
if (MakeOpenURLEvent(defaultBrowserSignature, pURL, &theEvent, bNewWindow))
{
ProcessSerialNumber* kDontCareAboutPSN = NULL;
short launchFlags;
FSSpec appSpec;
launchFlags = (launchContinue | launchNoFileFlags);
if (!bBringToFront)
{
launchFlags |= launchDontSwitch;
}
err = FindApplicationBySignature(defaultBrowserSignature, &appSpec);
if (err == noErr)
{
err = FSpLaunchApplicationWithParamsAndFlags(&appSpec, &theEvent,
kDontCareAboutPSN, launchFlags);
}
if (err == noErr)
{
bLaunched = TRUE;
}
(void) AEDisposeDesc(&theEvent);
}
}
}
// last ditch effort is to rely on InternetConfig
if (!bLaunched)
{
err = HXInternetConfigMac::LaunchURL(pURL);
if (err == noErr)
{
bLaunched = TRUE;
}
}
return bLaunched;
#endif
}
Boolean IsLocalFileURLAPotentialProblemBecauseOfPercentEncodedUTF8Chars(const char *pURL)
{
// In Mac OS X, 8-bit characters become %-encoded Unicode in the URL, like
// this:
// folder
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -