mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3400 lines
89 KiB
3400 lines
89 KiB
/*
|
|
Enhanced NCSA Mosaic from Spyglass
|
|
"Guitar"
|
|
|
|
Copyright 1994 Spyglass, Inc.
|
|
All Rights Reserved
|
|
|
|
Author(s):
|
|
Jim Seidman [email protected]
|
|
Albert Lee [email protected]
|
|
*/
|
|
|
|
#include "all.h"
|
|
|
|
#ifdef FEATURE_IAPI
|
|
|
|
extern HTList *protocols;
|
|
|
|
static DWORD g_DdeInst = 0; // DDE instance
|
|
|
|
static HSZ hszMosaic = 0; // "MOSAIC" string
|
|
static HSZ hszReturn = 0; // "Return" string
|
|
|
|
static struct hash_table *pTopicHash; // hash table to keep track of topics
|
|
static struct hash_table *pServerHash = NULL; // hash table to keep track of currently active servers
|
|
|
|
static char *pArgumentBuffer; // temporary argument buffer needed for parsing arguments
|
|
static int nArgumentBufferLength; // argument buffer length for pArgumentBuffer
|
|
static char *pArgReturnBuffer; // argument return buffer
|
|
static char *pCurrentArgPos; // current position within argument buffer
|
|
|
|
static long TransactionID = 1; // unique transaction ID
|
|
|
|
static struct TRANSACTIONMAPSTRUCT *pTransactionMap; // structure used to map incoming/outgoing transactions
|
|
|
|
static WORD ProtocolHelperID = 1; // unique protocol helper ID to be passed in response to RegisterProtocol
|
|
|
|
static char *pFileContent; // Used for Verity hack - holds content of local file
|
|
|
|
static struct VERSIONSTRUCT *pVersionList; // version list
|
|
|
|
static DDENOTIFYSTRUCT *pDNS = NULL;
|
|
|
|
//**************************************
|
|
// DNS functions
|
|
//**************************************
|
|
|
|
void AddDNS(DDENOTIFYSTRUCT *dns)
|
|
{
|
|
dns->next = pDNS;
|
|
dns->prev = NULL;
|
|
|
|
if (pDNS)
|
|
pDNS->prev = dns;
|
|
|
|
pDNS = dns;
|
|
}
|
|
|
|
void RemoveDNS(DDENOTIFYSTRUCT *dns)
|
|
{
|
|
if (dns->prev)
|
|
dns->prev->next = dns->next;
|
|
if (dns->next)
|
|
dns->next->prev = dns->prev;
|
|
|
|
if (pDNS == dns)
|
|
pDNS = dns->next;
|
|
|
|
if (dns->pURL)
|
|
GTR_FREE(dns->pURL);
|
|
|
|
if (dns->pOriginalProtocol)
|
|
GTR_FREE(dns->pOriginalProtocol);
|
|
|
|
GTR_FREE(dns);
|
|
}
|
|
|
|
//**************************************
|
|
// Support functions
|
|
//**************************************
|
|
|
|
static char *GetNextArgument(char *pString, long *pValue, BOOL bString)
|
|
{
|
|
static char *pNew, *pEnd;
|
|
char *pCurrent;
|
|
BOOL bIgnoreBlanks, bInsideQuote;
|
|
|
|
// Parses the given string and returns a pointer to the next argument, or NULL if error.
|
|
// pString = beginning of the string to start parsing, or NULL to continue parsing
|
|
// a previously passed string
|
|
// pValue = pointer to a long integer. This argument will be ignored if bString is
|
|
// TRUE. If a non-numeric argument was encountered when bString is FALSE,
|
|
// *pValue will be 0, but the return pointer from the function will be NULL.
|
|
// bString = specifies if the argument should be wrapped around by double quotes.
|
|
// If this value is TRUE and there are no double quotes, the function will
|
|
// return NULL
|
|
//
|
|
// RULES:
|
|
//
|
|
// - string arguments must start and end with double quotes (")
|
|
// - numeric arguments must not be in double quotes
|
|
// - a double quote should be denoted by \"
|
|
// - commas are used between arguments
|
|
// - it is acceptable to specify no argument, such as in ,,
|
|
// - hexadecimal notation is valid, such as 0x4f89
|
|
// - octal notation is valid, such as 076
|
|
// - decimal notation is valid, such as 23. Decimal numbers MUST NOT be preceded by a 0.
|
|
//
|
|
// example: "hello",-1,2,"what"
|
|
// 0x1920,,"test",""
|
|
|
|
if (pString)
|
|
{
|
|
// initial setup
|
|
|
|
if (pArgumentBuffer)
|
|
GTR_FREE(pArgumentBuffer);
|
|
nArgumentBufferLength = strlen(pString) + 1;
|
|
pArgumentBuffer = GTR_MALLOC(nArgumentBufferLength);
|
|
strcpy(pArgumentBuffer, pString);
|
|
pCurrentArgPos = pArgumentBuffer;
|
|
|
|
if (pArgReturnBuffer)
|
|
GTR_FREE(pArgReturnBuffer);
|
|
pArgReturnBuffer = GTR_MALLOC(nArgumentBufferLength);
|
|
memset(pArgReturnBuffer, 0, nArgumentBufferLength);
|
|
|
|
pNew = pArgReturnBuffer;
|
|
pEnd = pNew;
|
|
}
|
|
else
|
|
{
|
|
if (pCurrentArgPos >= pArgumentBuffer + nArgumentBufferLength)
|
|
return NULL; // can't go past end of string
|
|
pNew = pEnd;
|
|
}
|
|
|
|
// Start composing the argument
|
|
|
|
pCurrent = pCurrentArgPos;
|
|
|
|
bIgnoreBlanks = TRUE; // ignore all blanks if this flag is TRUE
|
|
bInsideQuote = FALSE; // TRUE if opening double quote has been encountered
|
|
|
|
while (*pCurrent)
|
|
{
|
|
if (*pCurrent == ' ' && bIgnoreBlanks)
|
|
pCurrent++;
|
|
else if (*pCurrent == '"')
|
|
{
|
|
bInsideQuote = !bInsideQuote;
|
|
if (!bInsideQuote)
|
|
bIgnoreBlanks = TRUE;
|
|
|
|
*pNew++ = *pCurrent++;
|
|
}
|
|
else if (*pCurrent == ',')
|
|
{
|
|
if (!bInsideQuote)
|
|
break;
|
|
else
|
|
*pNew++ = *pCurrent++;
|
|
}
|
|
else if (*pCurrent == '\\' && bInsideQuote)
|
|
{
|
|
// Check for \" which means to insert a single double quote
|
|
|
|
if (*(pCurrent + 1) == '"')
|
|
{
|
|
*pNew++ = '"';
|
|
pCurrent += 2;
|
|
}
|
|
else
|
|
*pNew++ = *pCurrent++;
|
|
}
|
|
else
|
|
{
|
|
*pNew++ = *pCurrent++;
|
|
bIgnoreBlanks = FALSE;
|
|
}
|
|
}
|
|
|
|
pCurrentArgPos = pCurrent + 1;
|
|
|
|
pNew = pEnd;
|
|
|
|
pEnd = pNew + strlen(pNew) - 1;
|
|
|
|
if (bString)
|
|
{
|
|
if (*pNew == '\0')
|
|
{
|
|
pEnd = pNew + 1;
|
|
return "";
|
|
}
|
|
|
|
if ((*pNew != '"') || (*pEnd != '"'))
|
|
return NULL;
|
|
|
|
*pEnd = '\0';
|
|
pEnd += 2;
|
|
|
|
strcpy(pNew, &pNew[1]);
|
|
|
|
return pNew;
|
|
}
|
|
else
|
|
{
|
|
if (*pNew == '\0')
|
|
{
|
|
*pValue = 0;
|
|
pEnd += 2;
|
|
return pNew;
|
|
}
|
|
|
|
if ((*pNew == '"') || (*(pEnd - 1) == '"'))
|
|
return NULL;
|
|
|
|
*pValue = strtoul(pNew, NULL, 0);
|
|
pEnd += 2;
|
|
|
|
return pNew;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
char *MakeQuotedString(char *pString)
|
|
{
|
|
int length;
|
|
char *pReturn, *pCurrent;
|
|
|
|
// This function converts the given string so that its content is wrapped within
|
|
// double quotes. Embedded double quotes will be changed to \".
|
|
//
|
|
// THE CALLER MUST FREE THE MEMORY RETURNED BY THIS FUNCTION.
|
|
|
|
if (!pString)
|
|
{
|
|
pReturn = GTR_MALLOC(3);
|
|
strcpy(pReturn, "\"\"");
|
|
|
|
return pReturn;
|
|
}
|
|
|
|
length = 2 * strlen(pString) + 4; // worst case + 1
|
|
pReturn = GTR_MALLOC(length);
|
|
memset(pReturn, 0, length);
|
|
pCurrent = pReturn;
|
|
|
|
*pCurrent++ = '"';
|
|
|
|
while (*pString)
|
|
{
|
|
if (*pString == '"')
|
|
{
|
|
*pCurrent++ = '\\';
|
|
*pCurrent++ = '"';
|
|
}
|
|
else
|
|
*pCurrent++ = *pString;
|
|
|
|
pString++;
|
|
}
|
|
|
|
*pCurrent = '"';
|
|
|
|
return pReturn;
|
|
}
|
|
|
|
static BOOL IsMimeSupported(char *pMime)
|
|
{
|
|
struct Viewer_Info *pvi;
|
|
int count;
|
|
int i;
|
|
char *pAtom;
|
|
|
|
count = Hash_Count(gPrefs.pHashViewers);
|
|
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
Hash_GetIndexedEntry(gPrefs.pHashViewers, i, NULL, NULL, (void **) &pvi);
|
|
|
|
if (pvi)
|
|
{
|
|
pAtom = HTAtom_name(pvi->atomMIMEType);
|
|
if (pAtom && _stricmp(pAtom, pMime) == 0)
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static struct Mwin *TW_FromTransactionID(long transID)
|
|
{
|
|
struct Mwin *tw = Mlist;
|
|
|
|
// Return the tw structure which matches the transaction ID
|
|
|
|
while (tw)
|
|
{
|
|
if (tw->transID == transID)
|
|
break;
|
|
tw = tw->next;
|
|
}
|
|
|
|
return tw;
|
|
}
|
|
|
|
static struct Mwin *TW_FromWindowID(long windowID)
|
|
{
|
|
struct Mwin *tw = Mlist;
|
|
|
|
// Return the tw structure which matches the transaction ID
|
|
|
|
if (windowID == 0xFFFFFFFF)
|
|
tw = TW_FindTopmostWindow();
|
|
else
|
|
{
|
|
while (tw)
|
|
{
|
|
if (tw->serialID == windowID)
|
|
break;
|
|
tw = tw->next;
|
|
}
|
|
}
|
|
|
|
return tw;
|
|
}
|
|
|
|
static struct TRANSACTIONMAPSTRUCT *TMS_FromTransactionID(long transID)
|
|
{
|
|
struct TRANSACTIONMAPSTRUCT *p;
|
|
|
|
for (p = pTransactionMap; p; p = p->next)
|
|
{
|
|
if (p->incoming_transID == transID)
|
|
return p;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
BOOL TMS_Remove(struct TRANSACTIONMAPSTRUCT *ptms)
|
|
{
|
|
struct TRANSACTIONMAPSTRUCT *pprev, *pcurrent;
|
|
|
|
pcurrent = pTransactionMap;
|
|
pprev = NULL;
|
|
|
|
while (pcurrent != ptms)
|
|
{
|
|
pprev = pcurrent;
|
|
pcurrent = ptms->next;
|
|
}
|
|
|
|
if (!pcurrent)
|
|
return FALSE;
|
|
|
|
if (pprev)
|
|
pprev->next = pcurrent->next;
|
|
else
|
|
pTransactionMap = pcurrent->next;
|
|
|
|
GTR_FREE(pcurrent);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static char *GetArgumentsFromFile(char *filename)
|
|
{
|
|
FILE *fp;
|
|
long filesize;
|
|
char *pTemp, *p1, *p2;
|
|
|
|
fp = fopen(filename, "rb"); // read as binary to avoid text translation
|
|
if (!fp)
|
|
return NULL;
|
|
|
|
fseek(fp, 0, SEEK_END);
|
|
filesize = ftell(fp);
|
|
|
|
pTemp = GTR_MALLOC(filesize + 1);
|
|
if (!pTemp)
|
|
{
|
|
fclose(fp);
|
|
return NULL;
|
|
}
|
|
|
|
fseek(fp, 0, SEEK_SET);
|
|
fread(pTemp, 1, filesize, fp);
|
|
pTemp[filesize] = '\0';
|
|
fclose(fp);
|
|
|
|
if (pFileContent)
|
|
GTR_FREE(pFileContent);
|
|
|
|
pFileContent = GTR_MALLOC(filesize + 1);
|
|
if (!pFileContent)
|
|
{
|
|
GTR_FREE(pFileContent);
|
|
return NULL;
|
|
}
|
|
|
|
// The receipient must delete the file
|
|
|
|
remove(filename);
|
|
|
|
// Now copy pTemp into pFileContent, stripping all CR and LF characters
|
|
|
|
for (p1 = pTemp, p2 = pFileContent; *p1; p1++)
|
|
{
|
|
if (*p1 != '\r' && *p1 != '\n')
|
|
*p2++ = *p1;
|
|
}
|
|
|
|
*p2 = '\0';
|
|
|
|
return pFileContent;
|
|
}
|
|
|
|
static HSZ CreateArgument(char *pApp, char *pBuffer)
|
|
{
|
|
struct VERSIONSTRUCT *pVersion;
|
|
char path[_MAX_PATH + 1], filename[_MAX_PATH + 1];
|
|
FILE *fp;
|
|
HSZ hszItem;
|
|
|
|
/*
|
|
Look for this application in the version list. If found, use the 1.0 hack (caret preceds a
|
|
file name containing the arguments). If not, use the old method, even though there is a risk
|
|
of arguments getting cut off.
|
|
*/
|
|
|
|
for (pVersion = pVersionList; pVersion; pVersion = pVersion->next)
|
|
{
|
|
if (_stricmp(pVersion->szApp, pApp) == 0)
|
|
break;
|
|
}
|
|
|
|
/* Do not create a file unless necessary */
|
|
|
|
if ((!pVersion) || (pVersion->major < 1) || (strlen(pBuffer) < 256))
|
|
hszItem = DdeCreateStringHandle(g_DdeInst, pBuffer, CP_WINANSI);
|
|
else
|
|
{
|
|
/* Get a temporary file name */
|
|
|
|
path[0] = 0;
|
|
PREF_GetTempPath(_MAX_PATH, path);
|
|
GetTempFileName(path, "A", 0, filename);
|
|
|
|
/* Write the arguments in the temp file */
|
|
|
|
fp = fopen(filename, "wb");
|
|
fwrite(pBuffer, 1, strlen(pBuffer), fp);
|
|
fclose(fp);
|
|
|
|
/* Create a file name spec (caret and filename) */
|
|
/* Borrow the path buffer */
|
|
|
|
sprintf(path, "^%s", filename);
|
|
hszItem = DdeCreateStringHandle(g_DdeInst, path, CP_WINANSI);
|
|
}
|
|
|
|
return hszItem;
|
|
}
|
|
|
|
//************************************************
|
|
// Dispatch function
|
|
//************************************************
|
|
|
|
HDDEDATA EXPENTRY DdeCallBack(WORD wType,
|
|
WORD wFmt,
|
|
HCONV hConv,
|
|
HSZ hsz1,
|
|
HSZ hsz2,
|
|
HDDEDATA hDDEData,
|
|
DWORD dwData1,
|
|
DWORD dwData2)
|
|
{
|
|
char szTopic[64];
|
|
char szItem[2048];
|
|
DDEHANDLECALLBACK pCallback;
|
|
int index;
|
|
char *pItem;
|
|
|
|
// The callback function allows the server to communicate
|
|
// with the DDEML, and thus, to the client. When the DDEML
|
|
// has something to tell the server, it calls the server's
|
|
// callback function. When the server has something to tell
|
|
// the DDEML (or the client), it does it through the callback
|
|
// function.
|
|
|
|
switch(wType)
|
|
{
|
|
case XTYP_REGISTER:
|
|
DdeQueryString(g_DdeInst, hsz1, szItem, sizeof(szItem), CP_WINANSI);
|
|
|
|
if (pServerHash)
|
|
Hash_Add(pServerHash, szItem, NULL, NULL);
|
|
|
|
XX_DMsg(DBG_SDI, ("DDE server %s is registering.\n", szItem));
|
|
return 0;
|
|
|
|
case XTYP_UNREGISTER:
|
|
DdeQueryString(g_DdeInst, hsz1, szItem, sizeof(szItem), CP_WINANSI);
|
|
|
|
if (pServerHash)
|
|
{
|
|
index = Hash_Find(pServerHash, szItem, NULL, NULL);
|
|
if (index != -1)
|
|
Hash_DeleteIndexedEntry(pServerHash, index);
|
|
}
|
|
|
|
XX_DMsg(DBG_SDI, ("DDE server %s is unregistering.\n", szItem));
|
|
return 0;
|
|
|
|
case XTYP_REQUEST:
|
|
case XTYP_POKE:
|
|
// Support topics here. We need to make sure that the topics are legitimate, by
|
|
// checking them in the topic hash table.
|
|
|
|
DdeQueryString(g_DdeInst, hsz1, szTopic, sizeof(szTopic), CP_WINANSI);
|
|
if (Hash_Find(pTopicHash, szTopic, NULL, (void **) &pCallback) == -1)
|
|
return 0;
|
|
|
|
DdeQueryString(g_DdeInst, hsz2, szItem, sizeof(szItem), CP_WINANSI);
|
|
|
|
if (szItem[0] == '^')
|
|
pItem = GetArgumentsFromFile(&szItem[1]);
|
|
else
|
|
pItem = szItem;
|
|
|
|
if (!pItem)
|
|
return 0;
|
|
else
|
|
return ((*pCallback)(pItem));
|
|
|
|
case XTYP_CONNECT:
|
|
return (HDDEDATA) (hszMosaic == hsz2);
|
|
|
|
case XTYP_ADVSTART:
|
|
case XTYP_ADVREQ:
|
|
case XTYP_ADVSTOP:
|
|
case XTYP_WILDCONNECT:
|
|
return DDE_FNOTPROCESSED;
|
|
|
|
default:
|
|
return (HDDEDATA) NULL;
|
|
}
|
|
}
|
|
|
|
//************************************************
|
|
// OpenURL functions
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_OpenURLResult(char *pItem)
|
|
{
|
|
char *pTransID, *pWindowID;
|
|
long lTransID, lWindowID;
|
|
struct TRANSACTIONMAPSTRUCT *ptms;
|
|
char szTemp[50];
|
|
HSZ hszService, hszTopic, hszItem;
|
|
HCONV hConv;
|
|
HDDEDATA hReturn;
|
|
DDENOTIFYSTRUCT *dns;
|
|
|
|
pTransID = GetNextArgument(pItem, &lTransID, FALSE);
|
|
if (!pTransID)
|
|
return 0;
|
|
|
|
pWindowID = GetNextArgument(NULL, &lWindowID, FALSE);
|
|
if (!pWindowID)
|
|
return 0;
|
|
|
|
// Look for the matching transaction in the transaction map.
|
|
// We need to pass the result to the original requester,
|
|
// translating the transaction ID as necessary.
|
|
|
|
ptms = TMS_FromTransactionID(lTransID);
|
|
if (!ptms)
|
|
return 0;
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if (dns->lTransID == ptms->outgoing_transID)
|
|
break;
|
|
}
|
|
|
|
if (!dns)
|
|
return 0;
|
|
|
|
hszService = DdeCreateStringHandle(g_DdeInst, dns->szResultApp, CP_WINANSI);
|
|
hszTopic = DdeCreateStringHandle(g_DdeInst, dns->szReturnTopic, CP_WINANSI);
|
|
|
|
hConv = DdeConnect(g_DdeInst, hszService, hszTopic, NULL);
|
|
|
|
if (hConv)
|
|
{
|
|
sprintf(szTemp, "%ld,%ld", ptms->outgoing_transID, lWindowID);
|
|
hszItem = DdeCreateStringHandle(g_DdeInst, szTemp, CP_WINANSI);
|
|
|
|
hReturn = DdeClientTransaction(NULL, 0, hConv, hszItem, CF_TEXT,
|
|
XTYP_POKE, DDE_TIMEOUT, NULL);
|
|
|
|
DdeDisconnect(hConv);
|
|
DdeFreeStringHandle(g_DdeInst, hszItem);
|
|
}
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszService);
|
|
DdeFreeStringHandle(g_DdeInst, hszTopic);
|
|
|
|
// Remove the structure from the transaction map list
|
|
|
|
TMS_Remove(ptms);
|
|
RemoveDNS(dns);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static HDDEDATA DDE_Handle_OpenURL(char *pItem)
|
|
{
|
|
char *pURL, *pFile, *pWindowID, *pFlags, *pFormData, *pMIMEType, *pProgressApp, *pResultApp;
|
|
long lWindowID, lFlags;
|
|
BOOL bNoDocCache, bNoImageCache, bBackground, bInvalidProtocol;
|
|
HDDEDATA result;
|
|
long retval = SDI_SUPER_ACK;
|
|
DDENOTIFYSTRUCT *dns, *dns2;
|
|
struct Mwin *tw;
|
|
struct TRANSACTIONMAPSTRUCT *tms;
|
|
HTList *cur;
|
|
HTProtocol *p;
|
|
char *pProtocol;
|
|
|
|
XX_DMsg(DBG_SDI, ("OpenURL received: %s\n", pItem));
|
|
|
|
pURL = GetNextArgument(pItem, NULL, TRUE);
|
|
if (!pURL)
|
|
return 0;
|
|
|
|
pFile = GetNextArgument(NULL, NULL, TRUE);
|
|
if (!pFile)
|
|
return 0;
|
|
|
|
pWindowID = GetNextArgument(NULL, &lWindowID, FALSE);
|
|
if (!pWindowID)
|
|
return 0;
|
|
|
|
pFlags = GetNextArgument(NULL, &lFlags, FALSE);
|
|
if (!pFlags)
|
|
return 0;
|
|
|
|
pFormData = GetNextArgument(NULL, NULL, TRUE);
|
|
if (!pFormData)
|
|
return 0;
|
|
|
|
pMIMEType = GetNextArgument(NULL, NULL, TRUE);
|
|
if (!pMIMEType)
|
|
return 0;
|
|
|
|
pProgressApp = GetNextArgument(NULL, NULL, TRUE);
|
|
if (!pProgressApp)
|
|
return 0;
|
|
|
|
pResultApp = GetNextArgument(NULL, NULL, TRUE);
|
|
if (!pResultApp)
|
|
{
|
|
// For compatibility with the older OpenURL spec, allow
|
|
// this argument to be absent.
|
|
|
|
pResultApp = "";
|
|
}
|
|
|
|
// If result application does not exist, progress cannot be sent.
|
|
// In this case, set progress app to an empty value.
|
|
|
|
if (pResultApp[0] == '\0')
|
|
pProgressApp = "";
|
|
|
|
XX_DMsg(DBG_SDI, ("OpenURL filtered: %s,%s,%s,%s,%s,%s,%s,%s\n",
|
|
pURL, pFile, pWindowID, pFlags, pFormData, pMIMEType, pProgressApp, pResultApp));
|
|
|
|
bNoDocCache = lFlags & OPENURL_IGNOREDOCCACHE;
|
|
bNoImageCache = lFlags & OPENURL_IGNOREIMAGECACHE;
|
|
bBackground = lFlags & OPENURL_BACKGROUNDMODE;
|
|
|
|
dns = (DDENOTIFYSTRUCT *) GTR_MALLOC(sizeof(DDENOTIFYSTRUCT));
|
|
memset(dns, 0, sizeof(DDENOTIFYSTRUCT));
|
|
|
|
strncpy(dns->szResultApp, pResultApp, sizeof(dns->szResultApp) - 1);
|
|
strcpy(dns->szReturnTopic, "WWW_OpenURLResult");
|
|
|
|
dns->lTransID = TransactionID;
|
|
|
|
AddDNS(dns);
|
|
|
|
if (pProgressApp[0] || pResultApp[0])
|
|
{
|
|
tms = GTR_MALLOC(sizeof(struct TRANSACTIONMAPSTRUCT));
|
|
memset(tms, 0, sizeof(struct TRANSACTIONMAPSTRUCT));
|
|
|
|
tms->outgoing_transID = TransactionID;
|
|
strncpy(tms->outgoing_app, pProgressApp, sizeof(tms->outgoing_app) - 1);
|
|
tms->next = pTransactionMap;
|
|
|
|
pTransactionMap = tms;
|
|
}
|
|
else
|
|
tms = NULL;
|
|
|
|
// If the protocol is not supported by Mosaic but is supported by a helper,
|
|
// start a windowless tw and pass the URL along.
|
|
|
|
pProtocol = GTR_strdup(pURL);
|
|
strtok(pProtocol, ":");
|
|
|
|
cur = protocols;
|
|
bInvalidProtocol = TRUE;
|
|
|
|
while ((p = (HTProtocol *) HTList_nextObject(cur)))
|
|
{
|
|
if (strcmp(p->name, pProtocol) == 0)
|
|
{
|
|
bInvalidProtocol = FALSE;
|
|
|
|
if (p->load == DDE_Custom_Protocol_Handler)
|
|
{
|
|
// We found the protocol
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bInvalidProtocol)
|
|
{
|
|
RemoveDNS(dns);
|
|
|
|
retval = SDI_INVALID_PROTOCOL;
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &retval, sizeof(retval),
|
|
0, hszReturn, CF_TEXT, 0);
|
|
|
|
return result;
|
|
}
|
|
|
|
if (p)
|
|
{
|
|
if (tms)
|
|
{
|
|
for (dns2 = pDNS; dns2; dns2 = dns2->next)
|
|
{
|
|
if ((dns2->pProtocol) &&
|
|
(_stricmp(pProtocol, dns2->pProtocol) == 0))
|
|
{
|
|
strcpy(tms->incoming_app, dns2->szResultApp);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// The URL contained a custom registered protocol. We need to issue an
|
|
// OpenURL here so that we can send back the result right away. If
|
|
// progress app is specified, change the progress to come to Mosaic so
|
|
// that it can be rerouted to the requester.
|
|
|
|
retval = SDI_Issue_OpenURL(pURL, pFile, &lWindowID, lFlags, pFormData,
|
|
pMIMEType, "MOSAIC", (pResultApp[0] ? "MOSAIC" : ""));
|
|
|
|
// The return value from SDI_Issue_OpenURL is really contained in lWindowID.
|
|
|
|
if (tms)
|
|
tms->incoming_transID = lWindowID;
|
|
|
|
// If the OpenURL requester did not specify to receive the OpenURLResult, then
|
|
// just super-ack it. Otherwise, send the transaction ID (unique to Mosaic -
|
|
// we provide the mapping)
|
|
|
|
if (pResultApp[0])
|
|
{
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &TransactionID, sizeof(TransactionID),
|
|
0, hszReturn, CF_TEXT, 0);
|
|
|
|
// Do not delete dns because we need it later to send OpenURLResult
|
|
}
|
|
else
|
|
{
|
|
retval = SDI_SUPER_ACK;
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &retval, sizeof(retval),
|
|
0, hszReturn, CF_TEXT, 0);
|
|
}
|
|
|
|
// Delete dns here because there is no OpenURLResult
|
|
|
|
if (retval == SDI_SUPER_ACK)
|
|
{
|
|
RemoveDNS(dns);
|
|
if (tms)
|
|
TMS_Remove(tms);
|
|
}
|
|
|
|
TransactionID++;
|
|
GTR_FREE(pProtocol);
|
|
|
|
return (result);
|
|
}
|
|
|
|
GTR_FREE(pProtocol);
|
|
|
|
// If file spec has been given, then this URL must be saved into the file. Since
|
|
// we need a tw structure to bring up the error in, we simply use the first tw
|
|
// structure we can grab.
|
|
|
|
if (pFile[0])
|
|
{
|
|
tw = NewMwin(GWINDOWLESS);
|
|
tw->transID = TransactionID;
|
|
|
|
// tw->szProgressApp is already NULLed
|
|
|
|
strncpy(tw->szProgressApp, pProgressApp, sizeof(tw->szProgressApp) - 1);
|
|
|
|
GTR_DoSDI(tw, pURL, NULL, pFile, TRUE);
|
|
|
|
if (pResultApp[0])
|
|
retval = TransactionID;
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &retval, sizeof(retval),
|
|
0, hszReturn, CF_TEXT, 0);
|
|
|
|
TransactionID++;
|
|
|
|
return result;
|
|
}
|
|
|
|
switch(lWindowID)
|
|
{
|
|
case 0:
|
|
//
|
|
// Open a new Window and put the URL there. Return a transaction ID for now
|
|
// since the operation is asynchronous.
|
|
|
|
XX_DMsg(DBG_SDI, ("OpenURL: Creating a new window\n"));
|
|
|
|
dns->bCreateNewWindow = TRUE;
|
|
|
|
if (pFormData[0])
|
|
GTR_NewWindow(pURL, NULL, TransactionID, bNoDocCache, bNoImageCache, pFormData, pProgressApp);
|
|
else
|
|
GTR_NewWindow(pURL, NULL, TransactionID, bNoDocCache, bNoImageCache, NULL, pProgressApp);
|
|
|
|
if (pResultApp[0])
|
|
retval = TransactionID;
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &retval, sizeof(retval),
|
|
0, hszReturn, CF_TEXT, 0);
|
|
|
|
TransactionID++;
|
|
|
|
return result;
|
|
|
|
case 0xFFFFFFFF:
|
|
//
|
|
// Use the most recently active window and put the URL there.
|
|
|
|
dns->bCreateNewWindow = FALSE;
|
|
|
|
tw = TW_FromWindowID(lWindowID);
|
|
if (!tw)
|
|
return 0;
|
|
|
|
XX_DMsg(DBG_SDI, ("OpenURL: Using most recently active window %d\n", tw->serialID));
|
|
|
|
if (!bBackground)
|
|
SetForegroundWindow(tw->hWndFrame);
|
|
|
|
tw->transID = TransactionID;
|
|
tw->bSuppressError = TRUE;
|
|
|
|
// tw->szProgressApp is already NULLed
|
|
|
|
strncpy(tw->szProgressApp, pProgressApp, sizeof(tw->szProgressApp) - 1);
|
|
|
|
if (pFormData[0])
|
|
TW_LoadDocument(tw, pURL, TRUE, TRUE, bNoDocCache, bNoImageCache, pFormData, NULL);
|
|
else
|
|
TW_LoadDocument(tw, pURL, TRUE, FALSE, bNoDocCache, bNoImageCache, NULL, NULL);
|
|
|
|
if (pResultApp[0])
|
|
retval = TransactionID;
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &retval, sizeof(retval),
|
|
0, hszReturn, CF_TEXT, 0);
|
|
|
|
TransactionID++;
|
|
|
|
return result;
|
|
|
|
default:
|
|
//
|
|
// Check if the specified window exists and use the window
|
|
|
|
dns->bCreateNewWindow = FALSE;
|
|
tw = TW_FromWindowID(lWindowID);
|
|
|
|
if (tw)
|
|
{
|
|
XX_DMsg(DBG_SDI, ("OpenURL: Using window %d\n", tw->serialID));
|
|
|
|
if (!bBackground)
|
|
SetForegroundWindow(tw->win);
|
|
|
|
tw->transID = TransactionID;
|
|
tw->bSuppressError = TRUE;
|
|
|
|
// tw->szProgressApp is already NULLed
|
|
|
|
strncpy(tw->szProgressApp, pProgressApp, sizeof(tw->szProgressApp) - 1);
|
|
|
|
if (pFormData[0])
|
|
TW_LoadDocument(tw, pURL, TRUE, TRUE, bNoDocCache, bNoImageCache, pFormData, NULL);
|
|
else
|
|
TW_LoadDocument(tw, pURL, TRUE, FALSE, bNoDocCache, bNoImageCache, NULL, NULL);
|
|
|
|
retval = tw->transID;
|
|
TransactionID++;
|
|
}
|
|
else
|
|
retval = 0;
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &retval, sizeof(retval),
|
|
0, hszReturn, CF_TEXT, 0);
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
static HDDEDATA DDE_Handle_GetHTTPHead(char *pItem)
|
|
{
|
|
char *pURL, *pResultApp;
|
|
HDDEDATA result;
|
|
long retval = SDI_SUPER_ACK;
|
|
DDENOTIFYSTRUCT *dns;
|
|
struct Mwin *tw;
|
|
char *pProtocol;
|
|
|
|
XX_DMsg(DBG_SDI, ("GetHTTPHead received: %s\n", pItem));
|
|
|
|
pURL = GetNextArgument(pItem, NULL, TRUE);
|
|
if (!pURL)
|
|
return 0;
|
|
|
|
pResultApp = GetNextArgument(NULL, NULL, TRUE);
|
|
if (!pResultApp)
|
|
return 0;
|
|
|
|
XX_DMsg(DBG_SDI, ("GetHTTPHead filtered: %s,%s\n",
|
|
pURL, pResultApp));
|
|
|
|
dns = (DDENOTIFYSTRUCT *) GTR_MALLOC(sizeof(DDENOTIFYSTRUCT));
|
|
if (!dns)
|
|
return 0;
|
|
|
|
memset(dns, 0, sizeof(DDENOTIFYSTRUCT));
|
|
|
|
strncpy(dns->szResultApp, pResultApp, sizeof(dns->szResultApp) - 1);
|
|
strcpy(dns->szReturnTopic, "WWW_GetHTTPHeadResult");
|
|
|
|
dns->lTransID = TransactionID;
|
|
|
|
// The protocol MUST be http. We process this using a windowless tw.
|
|
|
|
pProtocol = GTR_strdup(pURL);
|
|
strtok(pProtocol, ":");
|
|
if (0 != strcmp("http", pProtocol))
|
|
{
|
|
GTR_FREE(dns);
|
|
GTR_FREE(pProtocol);
|
|
|
|
retval = SDI_INVALID_PROTOCOL;
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &retval, sizeof(retval),
|
|
0, hszReturn, CF_TEXT, 0);
|
|
|
|
return result;
|
|
}
|
|
|
|
GTR_FREE(pProtocol);
|
|
|
|
tw = NewMwin(GWINDOWLESS);
|
|
tw->transID = TransactionID;
|
|
|
|
GTR_DoHTTPHead(tw, pURL);
|
|
|
|
if (pResultApp[0])
|
|
retval = TransactionID;
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &retval, sizeof(retval),
|
|
0, hszReturn, CF_TEXT, 0);
|
|
|
|
TransactionID++;
|
|
|
|
AddDNS(dns);
|
|
|
|
return result;
|
|
}
|
|
|
|
void SDI_Issue_BeginProgress(char *pProgress, long lTransID, char *pMessage, BOOL bInternalUse)
|
|
{
|
|
struct TRANSACTIONMAPSTRUCT *tms;
|
|
HSZ hszTopic, hszService, hszItem;
|
|
HDDEDATA hResult;
|
|
HCONV hConv;
|
|
char *p, *p1;
|
|
|
|
tms = pTransactionMap;
|
|
|
|
while (tms)
|
|
{
|
|
if ((strcmp(tms->outgoing_app, pProgress) == 0) &&
|
|
(tms->outgoing_transID == lTransID))
|
|
{
|
|
hszTopic = DdeCreateStringHandle(g_DdeInst, "WWW_BeginProgress", CP_WINANSI);
|
|
hszService = DdeCreateStringHandle(g_DdeInst, pProgress, CP_WINANSI);
|
|
|
|
hConv = DdeConnect(g_DdeInst, hszService, hszTopic, NULL);
|
|
if (hConv)
|
|
{
|
|
XX_DMsg(DBG_SDI, ("Issuing BeginProgress to %s.\n", pProgress));
|
|
|
|
p1 = MakeQuotedString(pMessage);
|
|
p = GTR_MALLOC(strlen(p1) + 50 + 1);
|
|
|
|
sprintf(p, "%ld,%s", tms->outgoing_transID, p1);
|
|
|
|
hszItem = CreateArgument(pProgress, p);
|
|
hResult = DdeClientTransaction(NULL, 0, hConv, hszItem, CF_TEXT, XTYP_POKE,
|
|
DDE_TIMEOUT, NULL);
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszItem);
|
|
|
|
GTR_FREE(p);
|
|
GTR_FREE(p1);
|
|
|
|
DdeDisconnect(hConv);
|
|
}
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszTopic);
|
|
DdeFreeStringHandle(g_DdeInst, hszService);
|
|
|
|
return;
|
|
}
|
|
|
|
tms = tms->next;
|
|
}
|
|
}
|
|
|
|
void SDI_Issue_SetProgressRange(char *pProgress, long lTransID, long lRange, BOOL bInternalUse)
|
|
{
|
|
struct TRANSACTIONMAPSTRUCT *tms;
|
|
HSZ hszTopic, hszService, hszItem;
|
|
HDDEDATA hResult;
|
|
HCONV hConv;
|
|
char szTemp[50];
|
|
|
|
tms = pTransactionMap;
|
|
|
|
while (tms)
|
|
{
|
|
if ((strcmp(tms->outgoing_app, pProgress) == 0) &&
|
|
(tms->outgoing_transID == lTransID))
|
|
{
|
|
hszTopic = DdeCreateStringHandle(g_DdeInst, "WWW_SetProgressRange", CP_WINANSI);
|
|
hszService = DdeCreateStringHandle(g_DdeInst, pProgress, CP_WINANSI);
|
|
|
|
hConv = DdeConnect(g_DdeInst, hszService, hszTopic, NULL);
|
|
if (hConv)
|
|
{
|
|
XX_DMsg(DBG_SDI, ("Issuing SetProgressRange to %s.\n", pProgress));
|
|
|
|
sprintf(szTemp, "%ld,%ld", tms->outgoing_transID, lRange);
|
|
|
|
hszItem = CreateArgument(pProgress, szTemp);
|
|
hResult = DdeClientTransaction(NULL, 0, hConv, hszItem, CF_TEXT, XTYP_POKE,
|
|
DDE_TIMEOUT, NULL);
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszItem);
|
|
|
|
DdeDisconnect(hConv);
|
|
}
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszTopic);
|
|
DdeFreeStringHandle(g_DdeInst, hszService);
|
|
|
|
return;
|
|
}
|
|
|
|
tms = tms->next;
|
|
}
|
|
}
|
|
|
|
void SDI_Issue_MakingProgress(struct Mwin *tw, char *pProgressApp, long lTransID,
|
|
char *pMessage, long lProgress, BOOL bInternalUse)
|
|
{
|
|
struct TRANSACTIONMAPSTRUCT *tms;
|
|
HSZ hszTopic, hszService, hszItem;
|
|
HDDEDATA hResult;
|
|
char *p, *p1;
|
|
BOOL bCancel;
|
|
HCONV hConv;
|
|
static char szLastMessage[1024]; /* Last message passed */
|
|
static long lLastProgress;
|
|
|
|
/* Only pass the progress message if something has changed */
|
|
/* Do this only for internally generated progress messages */
|
|
|
|
if (bInternalUse)
|
|
{
|
|
if ((strcmp(pMessage, szLastMessage) != 0) || (lProgress != lLastProgress))
|
|
{
|
|
strncpy(szLastMessage, pMessage, sizeof(szLastMessage) - 1);
|
|
szLastMessage[sizeof(szLastMessage) - 1] = '\0';
|
|
lLastProgress = lProgress;
|
|
}
|
|
else
|
|
return;
|
|
}
|
|
|
|
tms = pTransactionMap;
|
|
|
|
while (tms)
|
|
{
|
|
if ((strcmp(tms->outgoing_app, pProgressApp) == 0) &&
|
|
(tms->outgoing_transID == lTransID))
|
|
{
|
|
hszTopic = DdeCreateStringHandle(g_DdeInst, "WWW_MakingProgress", CP_WINANSI);
|
|
hszService = DdeCreateStringHandle(g_DdeInst, pProgressApp, CP_WINANSI);
|
|
|
|
hConv = DdeConnect(g_DdeInst, hszService, hszTopic, NULL);
|
|
if (hConv)
|
|
{
|
|
XX_DMsg(DBG_SDI, ("Issuing MakingProgress to %s.\n", pProgressApp));
|
|
|
|
p1 = MakeQuotedString(pMessage);
|
|
p = GTR_MALLOC(strlen(p1) + 100 + 1);
|
|
|
|
sprintf(p, "%ld,%s,%ld", tms->outgoing_transID, p1, lProgress);
|
|
|
|
hszItem = CreateArgument(pProgressApp, p);
|
|
hResult = DdeClientTransaction(NULL, 0, hConv, hszItem, CF_TEXT, XTYP_REQUEST,
|
|
DDE_TIMEOUT, NULL);
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszItem);
|
|
|
|
GTR_FREE(p);
|
|
GTR_FREE(p1);
|
|
|
|
// If hResult is valid and its value is TRUE, then kill the thread
|
|
|
|
if (hResult)
|
|
{
|
|
DdeGetData(hResult, (LPBYTE) &bCancel, sizeof(bCancel), 0);
|
|
if (bCancel && tw)
|
|
{
|
|
XX_DMsg(DBG_SDI, ("MakingProgress: Client aborted the process.\n"));
|
|
SDI_Issue_EndProgress(tms->outgoing_app, tms->outgoing_transID, bInternalUse);
|
|
Async_TerminateByWindow(tw);
|
|
}
|
|
}
|
|
|
|
DdeDisconnect(hConv);
|
|
}
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszTopic);
|
|
DdeFreeStringHandle(g_DdeInst, hszService);
|
|
|
|
return;
|
|
}
|
|
|
|
tms = tms->next;
|
|
}
|
|
}
|
|
|
|
void SDI_Issue_EndProgress(char *pProgress, long lTransID, BOOL bInternalUse)
|
|
{
|
|
struct TRANSACTIONMAPSTRUCT *tms;
|
|
HSZ hszTopic, hszService, hszItem;
|
|
HDDEDATA hResult;
|
|
HCONV hConv;
|
|
char *p;
|
|
|
|
tms = pTransactionMap;
|
|
|
|
while (tms)
|
|
{
|
|
if ((strcmp(tms->outgoing_app, pProgress) == 0) &&
|
|
(lTransID == tms->outgoing_transID))
|
|
{
|
|
hszTopic = DdeCreateStringHandle(g_DdeInst, "WWW_EndProgress", CP_WINANSI);
|
|
hszService = DdeCreateStringHandle(g_DdeInst, pProgress, CP_WINANSI);
|
|
|
|
hConv = DdeConnect(g_DdeInst, hszService, hszTopic, NULL);
|
|
if (hConv)
|
|
{
|
|
XX_DMsg(DBG_SDI, ("Issuing EndProgress to %s.\n", pProgress));
|
|
|
|
p = GTR_MALLOC(50 + 1);
|
|
sprintf(p, "%ld", tms->outgoing_transID);
|
|
|
|
hszItem = CreateArgument(pProgress, p);
|
|
hResult = DdeClientTransaction(NULL, 0, hConv, hszItem, CF_TEXT, XTYP_POKE,
|
|
DDE_TIMEOUT, NULL);
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszItem);
|
|
|
|
GTR_FREE(p);
|
|
|
|
DdeDisconnect(hConv);
|
|
}
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszTopic);
|
|
DdeFreeStringHandle(g_DdeInst, hszService);
|
|
|
|
return;
|
|
}
|
|
|
|
tms = tms->next;
|
|
}
|
|
}
|
|
|
|
//************************************************
|
|
// ShowFile
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_ShowFile(char *pItem)
|
|
{
|
|
char *pFileSpec, *pMIME, *pWindowID, *pURL, *pResultApp;
|
|
long lWindowID, transID;
|
|
struct Mwin *tw;
|
|
HDDEDATA result;
|
|
DDENOTIFYSTRUCT *dns;
|
|
|
|
pFileSpec = GetNextArgument(pItem, NULL, TRUE);
|
|
if (!pFileSpec)
|
|
return 0;
|
|
|
|
pMIME = GetNextArgument(NULL, NULL, TRUE);
|
|
if (!pMIME)
|
|
return 0;
|
|
|
|
pWindowID = GetNextArgument(NULL, &lWindowID, FALSE);
|
|
if (!pWindowID)
|
|
return 0;
|
|
|
|
pURL = GetNextArgument(NULL, NULL, TRUE);
|
|
if (!pURL)
|
|
return 0;
|
|
|
|
pResultApp = GetNextArgument(NULL, NULL, TRUE);
|
|
if (!pResultApp)
|
|
pResultApp = "";
|
|
|
|
// Check if we support the mime type
|
|
|
|
if (pMIME[0] && !IsMimeSupported(pMIME))
|
|
{
|
|
transID = SDI_INVALID_MIME;
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &transID, sizeof(transID), 0,
|
|
hszReturn, CF_TEXT, 0);
|
|
|
|
return result;
|
|
}
|
|
|
|
// Create the notify structure
|
|
|
|
dns = (DDENOTIFYSTRUCT *) GTR_MALLOC(sizeof(DDENOTIFYSTRUCT));
|
|
memset(dns, 0, sizeof(DDENOTIFYSTRUCT));
|
|
|
|
strncpy(dns->szResultApp, pResultApp, sizeof(dns->szResultApp) - 1);
|
|
strcpy(dns->szReturnTopic, "WWW_ShowFileResult");
|
|
dns->lTransID = TransactionID;
|
|
dns->pURL = GTR_strdup(pURL);
|
|
|
|
AddDNS(dns);
|
|
|
|
// Create a window if its ID is zero
|
|
|
|
if (lWindowID == 0)
|
|
{
|
|
dns->bCreateNewWindow = TRUE;
|
|
|
|
tw = NewMwin(GHTML);
|
|
if (!tw)
|
|
{
|
|
ERR_ReportError(NULL, SID_ERR_OUT_OF_MEMORY, NULL, NULL);
|
|
return 0;
|
|
}
|
|
|
|
if (!GDOC_NewWindow(tw))
|
|
{
|
|
CloseMwin(tw);
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tw = TW_FromWindowID(lWindowID);
|
|
if (!tw)
|
|
return 0;
|
|
}
|
|
|
|
// If the MIME type is suppoted by an SDI viewer, set the error
|
|
// code in tw->lErrorCode now so that when the result is issued,
|
|
// it will return the correct return code (-1 = improper type to
|
|
// handle in a Mosaic window)
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if (dns->mime_type == HTAtom_for(pMIME))
|
|
{
|
|
tw->lErrorOccurred = SDI_INVALID_MIME;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Open document asynchronously
|
|
|
|
tw->transID = TransactionID;
|
|
tw->bSuppressError = TRUE;
|
|
tw->SDI_MimeType = HTAtom_for(pMIME);
|
|
|
|
if (tw->SDI_url)
|
|
GTR_FREE(tw->SDI_url);
|
|
|
|
tw->SDI_url = GTR_strdup(pURL);
|
|
|
|
OpenLocalDocument(tw->win, pFileSpec);
|
|
|
|
TransactionID++;
|
|
|
|
if (pResultApp[0])
|
|
transID = tw->transID;
|
|
else
|
|
transID = SDI_SUPER_ACK;
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &transID, sizeof(transID), 0,
|
|
hszReturn, CF_TEXT, 0);
|
|
|
|
return result;
|
|
}
|
|
|
|
//************************************************
|
|
// Activate
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_Activate(char *pItem)
|
|
{
|
|
char *pWindowID, *pFlags;
|
|
long lWindowID, lFlags;
|
|
struct Mwin *tw;
|
|
HDDEDATA result;
|
|
|
|
// Activate the window with the given ID
|
|
|
|
XX_DMsg(DBG_SDI, ("SDI: Activating window %s\n", pItem));
|
|
|
|
pWindowID = GetNextArgument(pItem, &lWindowID, FALSE);
|
|
if (!pWindowID)
|
|
return 0;
|
|
|
|
pFlags = GetNextArgument(NULL, &lFlags, FALSE);
|
|
if (!pFlags)
|
|
return 0;
|
|
|
|
tw = TW_FromWindowID(lWindowID);
|
|
|
|
if (tw)
|
|
{
|
|
TW_RestoreWindow(tw->hWndFrame);
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &tw->serialID, sizeof(tw->serialID), 0,
|
|
hszReturn, CF_TEXT, 0);
|
|
}
|
|
else
|
|
{
|
|
lWindowID = 0;
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &lWindowID, sizeof(lWindowID), 0,
|
|
hszReturn, CF_TEXT, 0);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
//************************************************
|
|
// ListWindows
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_ListWindows(char *pItem)
|
|
{
|
|
long *pBuffer, *pEntry;
|
|
int count;
|
|
struct Mwin *tw;
|
|
HDDEDATA result;
|
|
|
|
tw = Mlist;
|
|
count = 0;
|
|
|
|
// count the number of open windows
|
|
|
|
while (tw && (tw->wintype == GHTML))
|
|
{
|
|
count++;
|
|
tw = tw->next;
|
|
}
|
|
|
|
// Pack the window IDs in a long array.
|
|
|
|
pBuffer = GTR_MALLOC((count + 1) * sizeof(long));
|
|
pEntry = pBuffer;
|
|
|
|
tw = Mlist;
|
|
|
|
pEntry[0] = count; // first 4 bytes = number of items to follow
|
|
count = 1;
|
|
|
|
while (tw && (tw->wintype == GHTML))
|
|
{
|
|
pEntry[count++] = tw->serialID;
|
|
tw = tw->next;
|
|
}
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) pBuffer, count * sizeof(long), 0,
|
|
hszReturn, CF_TEXT, 0);
|
|
|
|
GTR_FREE(pBuffer);
|
|
|
|
return result;
|
|
}
|
|
|
|
//************************************************
|
|
// GetWindowInfo
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_GetWindowInfo(char *pItem)
|
|
{
|
|
char *pBuffer, *pWindowID, *pAddress, *pTitle;
|
|
long lWindowID;
|
|
struct Mwin *tw;
|
|
HDDEDATA result;
|
|
|
|
pWindowID = GetNextArgument(pItem, &lWindowID, FALSE);
|
|
if (!pWindowID)
|
|
return 0;
|
|
|
|
tw = TW_FromWindowID(lWindowID);
|
|
if (!tw)
|
|
return 0;
|
|
|
|
pAddress = MakeQuotedString(tw->w3doc->szActualURL);
|
|
pTitle = MakeQuotedString(tw->w3doc->title);
|
|
|
|
pBuffer = GTR_MALLOC(strlen(pAddress) + strlen(pTitle) + 10);
|
|
memset(pBuffer, 0, strlen(pAddress) + strlen(pTitle) + 10);
|
|
|
|
strcpy(pBuffer, pAddress);
|
|
strcat(pBuffer, ",");
|
|
strcat(pBuffer, pTitle);
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) pBuffer, strlen(pBuffer) + 1, 0, hszReturn, CF_TEXT, 0);
|
|
|
|
GTR_FREE(pBuffer);
|
|
GTR_FREE(pAddress);
|
|
GTR_FREE(pTitle);
|
|
|
|
return result;
|
|
}
|
|
|
|
//************************************************
|
|
// ParseAnchor
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_ParseAnchor(char *pItem)
|
|
{
|
|
char *pMain, *pRelative, *pURL, *pReturn;
|
|
HDDEDATA result;
|
|
|
|
pMain = GetNextArgument(pItem, NULL, TRUE);
|
|
if (!pMain)
|
|
return 0;
|
|
|
|
pRelative = GetNextArgument(NULL, NULL, TRUE);
|
|
if (!pRelative)
|
|
return 0;
|
|
|
|
pURL = HTParse(pRelative, pMain, PARSE_ALL);
|
|
pReturn = MakeQuotedString(pURL);
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) pReturn, strlen(pReturn) + 1, 0, hszReturn, CF_TEXT, 0);
|
|
|
|
GTR_FREE(pURL);
|
|
GTR_FREE(pReturn);
|
|
|
|
return result;
|
|
}
|
|
|
|
//************************************************
|
|
// Exit
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_Exit(char *pItem)
|
|
{
|
|
// Close Mosaic. Return value does not matter.
|
|
|
|
PostMessage(wg.hWndHidden, WM_CLOSE, 0, 0);
|
|
return 0;
|
|
}
|
|
|
|
//************************************************
|
|
// RegisterURLEcho
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_RegisterURLEcho(char *pItem)
|
|
{
|
|
char *pApplication;
|
|
DDENOTIFYSTRUCT *dns;
|
|
long ret;
|
|
HDDEDATA result;
|
|
|
|
pApplication = GetNextArgument(pItem, NULL, TRUE);
|
|
if (!pApplication)
|
|
return 0;
|
|
|
|
// Make sure that this application has not already been
|
|
// registered for URL echo
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if ((_stricmp(dns->szReturnTopic, "WWW_URLEcho") == 0) &&
|
|
(_stricmp(dns->szResultApp, pApplication) == 0))
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// Add the echo request
|
|
|
|
dns = (DDENOTIFYSTRUCT *) GTR_MALLOC(sizeof(DDENOTIFYSTRUCT));
|
|
memset(dns, 0, sizeof(DDENOTIFYSTRUCT));
|
|
|
|
strcpy(dns->szResultApp, pApplication);
|
|
strcpy(dns->szReturnTopic, "WWW_URLEcho");
|
|
|
|
AddDNS(dns);
|
|
|
|
ret = TRUE;
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &ret, sizeof(ret), 0, hszReturn, CF_TEXT, 0);
|
|
|
|
return result;
|
|
}
|
|
|
|
//************************************************
|
|
// UnRegisterURLEcho
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_UnRegisterURLEcho(char *pItem)
|
|
{
|
|
char *pApplication;
|
|
DDENOTIFYSTRUCT *dns;
|
|
|
|
pApplication = GetNextArgument(pItem, NULL, TRUE);
|
|
if (!pApplication)
|
|
return 0;
|
|
|
|
// Look for the matching item and remove it
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if ((_stricmp(dns->szReturnTopic, "WWW_URLEcho") == 0) &&
|
|
(_stricmp(dns->szResultApp, pApplication) == 0))
|
|
{
|
|
RemoveDNS(dns);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//************************************************
|
|
// RegisterWindowClose
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_RegisterWindowClose(char *pItem)
|
|
{
|
|
char *pWindowID, *pApplication;
|
|
DDENOTIFYSTRUCT *dns;
|
|
long lWindowID;
|
|
struct Mwin *tw;
|
|
HDDEDATA result;
|
|
|
|
pApplication = GetNextArgument(pItem, NULL, TRUE);
|
|
if (!pApplication)
|
|
return 0;
|
|
|
|
pWindowID = GetNextArgument(NULL, &lWindowID, FALSE);
|
|
if (!pWindowID)
|
|
return 0;
|
|
|
|
// Make sure the window exists
|
|
|
|
tw = TW_FromWindowID(lWindowID);
|
|
if (!tw)
|
|
return 0;
|
|
|
|
// Make sure that this application has not already been
|
|
// registered for Window close
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if ((dns->lWindowID == lWindowID) &&
|
|
(_stricmp(dns->szReturnTopic, "WWW_WindowClose") == 0) &&
|
|
(_stricmp(dns->szResultApp, pApplication) == 0))
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// Add the request
|
|
|
|
dns = (DDENOTIFYSTRUCT *) GTR_MALLOC(sizeof(DDENOTIFYSTRUCT));
|
|
memset(dns, 0, sizeof(DDENOTIFYSTRUCT));
|
|
|
|
dns->lWindowID = lWindowID;
|
|
strcpy(dns->szResultApp, pApplication);
|
|
strcpy(dns->szReturnTopic, "WWW_WindowClose");
|
|
|
|
AddDNS(dns);
|
|
|
|
// Return the window ID
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &lWindowID, sizeof(lWindowID), 0, hszReturn, CF_TEXT, 0);
|
|
return result;
|
|
}
|
|
|
|
//************************************************
|
|
// UnRegisterWindowClose
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_UnRegisterWindowClose(char *pItem)
|
|
{
|
|
char *pWindowID, *pApplication;
|
|
DDENOTIFYSTRUCT *dns;
|
|
long lWindowID;
|
|
|
|
pApplication = GetNextArgument(pItem, NULL, TRUE);
|
|
if (!pApplication)
|
|
return 0;
|
|
|
|
pWindowID = GetNextArgument(NULL, &lWindowID, FALSE);
|
|
if (!pWindowID)
|
|
return 0;
|
|
|
|
// Look for the matching item and remove it
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if ((dns->lWindowID == lWindowID) &&
|
|
(_stricmp(dns->szReturnTopic, "WWW_WindowClose") == 0) &&
|
|
(_stricmp(dns->szResultApp, pApplication) == 0))
|
|
{
|
|
RemoveDNS(dns);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//************************************************
|
|
// RegisterProtocol
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_RegisterProtocol(char *pItem)
|
|
{
|
|
char *pApplication, *pProtocol;
|
|
DDENOTIFYSTRUCT *dns;
|
|
HTList *cur;
|
|
HTProtocol *p;
|
|
HDDEDATA result;
|
|
LONG ret;
|
|
|
|
pApplication = GetNextArgument(pItem, NULL, TRUE);
|
|
if (!pApplication)
|
|
return 0;
|
|
|
|
pProtocol = GetNextArgument(NULL, NULL, TRUE);
|
|
if (!pProtocol)
|
|
return 0;
|
|
|
|
// Make sure this protocol is not already handled by someone
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if (strcmp(dns->pProtocol, pProtocol) == 0)
|
|
return 0;
|
|
}
|
|
|
|
// Look for an existing protocol
|
|
|
|
dns = (DDENOTIFYSTRUCT *) GTR_MALLOC(sizeof(DDENOTIFYSTRUCT));
|
|
memset(dns, 0, sizeof(DDENOTIFYSTRUCT));
|
|
|
|
cur = protocols;
|
|
while ((p = (HTProtocol *) HTList_nextObject(cur)))
|
|
{
|
|
if (strcmp(p->name, pProtocol) == 0)
|
|
{
|
|
// Modify an existing protocol - but save the original one
|
|
|
|
dns->pOriginalProtocol = GTR_MALLOC(sizeof(HTProtocol));
|
|
memcpy(dns->pOriginalProtocol, p, sizeof(HTProtocol));
|
|
|
|
// The original name is hard-coded so don't attempt to free it!
|
|
|
|
p->name = GTR_strdup(pProtocol);
|
|
p->load = DDE_Custom_Protocol_Handler;
|
|
p->load_async = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!p)
|
|
{
|
|
// Add to protocol list
|
|
|
|
p = (HTProtocol *) GTR_MALLOC(sizeof(HTProtocol));
|
|
memset(p, 0, sizeof(HTProtocol));
|
|
|
|
p->name = GTR_strdup(pProtocol);
|
|
p->load = DDE_Custom_Protocol_Handler;
|
|
|
|
HTRegisterProtocol(p);
|
|
}
|
|
|
|
// Add the protocol to notification list
|
|
|
|
strcpy(dns->szResultApp, pApplication);
|
|
strcpy(dns->szReturnTopic, "WWW_OpenURL");
|
|
dns->pProtocol = GTR_strdup(pProtocol);
|
|
|
|
AddDNS(dns);
|
|
|
|
ret = MAKELONG(0, ProtocolHelperID);
|
|
if (ProtocolHelperID == 0x7FFF)
|
|
ProtocolHelperID = 1;
|
|
else
|
|
ProtocolHelperID++;
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &ret, sizeof(ret), 0,
|
|
hszReturn, CF_TEXT, 0);
|
|
|
|
return result;
|
|
}
|
|
|
|
//************************************************
|
|
// UnRegisterProtocol
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_UnRegisterProtocol(char *pItem)
|
|
{
|
|
char *pApplication, *pProtocol;
|
|
DDENOTIFYSTRUCT *dns;
|
|
HTList *cur;
|
|
HTProtocol *p;
|
|
|
|
pApplication = GetNextArgument(pItem, NULL, TRUE);
|
|
if (!pApplication)
|
|
return 0;
|
|
|
|
pProtocol = GetNextArgument(NULL, NULL, TRUE);
|
|
if (!pProtocol)
|
|
return 0;
|
|
|
|
// Remove the notification structure
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if ((strcmp(dns->pProtocol, pProtocol) == 0) &&
|
|
(_stricmp(dns->szResultApp, pApplication) == 0))
|
|
{
|
|
// Remove the protocol from the protocol list, if there was
|
|
// no original protocol. If there was an original protocol,
|
|
// then restore the old values.
|
|
|
|
cur = protocols;
|
|
while ((p = (HTProtocol *) HTList_nextObject(cur)))
|
|
{
|
|
if (strcmp(p->name, pProtocol) == 0)
|
|
{
|
|
if (!dns->pOriginalProtocol)
|
|
HTUnregisterProtocol(p);
|
|
else
|
|
{
|
|
GTR_FREE(p->name);
|
|
memcpy(p, dns->pOriginalProtocol, sizeof(HTProtocol));
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
RemoveDNS(dns);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//************************************************
|
|
// RegisterViewer
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_RegisterViewer(char *pItem)
|
|
{
|
|
char *pMIME, *pApplication, *pFlags;
|
|
struct Viewer_Info *pViewer, *pCurrent;
|
|
BOOL ret;
|
|
int index;
|
|
long lFlags;
|
|
HDDEDATA result;
|
|
DDENOTIFYSTRUCT *dns;
|
|
|
|
pApplication = GetNextArgument(pItem, NULL, TRUE);
|
|
if (!pApplication)
|
|
return 0;
|
|
|
|
pMIME = GetNextArgument(NULL, NULL, TRUE);
|
|
if (!pMIME)
|
|
return 0;
|
|
|
|
pFlags = GetNextArgument(NULL, &lFlags, FALSE);
|
|
if (!pFlags)
|
|
return 0;
|
|
|
|
// Force lFlags to always have ViewDocFile (for now)
|
|
|
|
lFlags |= 4;
|
|
|
|
XX_DMsg(DBG_SDI, ("RegisterViewer received: %s,%s,%d\n",
|
|
pApplication, pMIME, lFlags));
|
|
|
|
// Check for duplicates before adding to the registered list.
|
|
// Do not allow duplicates.
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if (dns->mime_type == HTAtom_for(pMIME))
|
|
{
|
|
XX_DMsg(DBG_SDI, ("RegisterViewer: duplicate found - fail \n"));
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
index = Hash_Find(gPrefs.pHashViewers, pMIME, NULL, (void **) &pCurrent);
|
|
|
|
if (index == -1)
|
|
{
|
|
pViewer = PREF_InitMIMEType(pMIME, pMIME, "", "", "", NULL, NULL);
|
|
|
|
strcpy(pViewer->szCurrentViewerServiceName, pApplication);
|
|
pViewer->bTemporaryStruct = TRUE;
|
|
pViewer->lCurrentViewerFlags = lFlags;
|
|
|
|
XX_DMsg(DBG_SDI, ("RegisterViewer: added to MIME list\n"));
|
|
}
|
|
else
|
|
{
|
|
strcpy(pCurrent->szCurrentViewerServiceName, pApplication);
|
|
pCurrent->lCurrentViewerFlags = lFlags;
|
|
|
|
XX_DMsg(DBG_SDI, ("RegisterViewer: modified existing MIME list\n"));
|
|
}
|
|
|
|
// Add the viewer to the transaction list
|
|
|
|
dns = (DDENOTIFYSTRUCT *) GTR_MALLOC(sizeof(DDENOTIFYSTRUCT));
|
|
memset(dns, 0, sizeof(DDENOTIFYSTRUCT));
|
|
|
|
strncpy(dns->szResultApp, pApplication, sizeof(dns->szResultApp) - 1);
|
|
dns->mime_type = HTAtom_for(pMIME);
|
|
|
|
AddDNS(dns);
|
|
|
|
ret = TRUE;
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &ret, sizeof(ret), 0, hszReturn, CF_TEXT, 0);
|
|
|
|
return result;
|
|
}
|
|
|
|
//************************************************
|
|
// UnRegisterViewer
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_UnRegisterViewer(char *pItem)
|
|
{
|
|
char *pMIME, *pApplication;
|
|
int index;
|
|
struct Viewer_Info *pCurrent;
|
|
DDENOTIFYSTRUCT *dns;
|
|
|
|
// Remove the viewer from the viewer list.
|
|
|
|
pApplication = GetNextArgument(pItem, NULL, TRUE);
|
|
if (!pApplication)
|
|
return 0;
|
|
|
|
pMIME = GetNextArgument(NULL, NULL, TRUE);
|
|
if (!pMIME)
|
|
return 0;
|
|
|
|
XX_DMsg(DBG_SDI, ("UnRegisterViewer received: %s,%s\n",
|
|
pApplication, pMIME));
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if (dns->mime_type == HTAtom_for(pMIME))
|
|
{
|
|
RemoveDNS(dns);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Now fix up the preferences
|
|
|
|
index = Hash_Find(gPrefs.pHashViewers, pMIME, NULL, (void **) &pCurrent);
|
|
if (index == -1)
|
|
return 0;
|
|
|
|
// If this is a temporary structure, remove it
|
|
|
|
if (pCurrent->bTemporaryStruct)
|
|
Hash_DeleteIndexedEntry(gPrefs.pHashViewers, index);
|
|
else
|
|
pCurrent->szCurrentViewerServiceName[0] = '\0';
|
|
|
|
return 0; // return code is meaningless
|
|
}
|
|
|
|
//************************************************
|
|
// RegisterAppClose
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_RegisterAppClose(char *pItem)
|
|
{
|
|
char *pApplication;
|
|
DDENOTIFYSTRUCT *dns;
|
|
HDDEDATA result;
|
|
BOOL ret;
|
|
|
|
pApplication = GetNextArgument(pItem, NULL, TRUE);
|
|
if (!pApplication)
|
|
return 0;
|
|
|
|
// Make sure that this application has not already been
|
|
// registered for app close
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if ((_stricmp(dns->szReturnTopic, "WWW_AppClose") == 0) &&
|
|
(_stricmp(dns->szResultApp, pApplication) == 0))
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// Add the request
|
|
|
|
dns = (DDENOTIFYSTRUCT *) GTR_MALLOC(sizeof(DDENOTIFYSTRUCT));
|
|
memset(dns, 0, sizeof(DDENOTIFYSTRUCT));
|
|
|
|
strcpy(dns->szResultApp, pApplication);
|
|
strcpy(dns->szReturnTopic, "WWW_AppClose");
|
|
|
|
AddDNS(dns);
|
|
|
|
// Return success
|
|
|
|
ret = TRUE;
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &ret, sizeof(ret), 0, hszReturn, CF_TEXT, 0);
|
|
|
|
return result;
|
|
}
|
|
|
|
//************************************************
|
|
// UnRegisterAppClose
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_UnRegisterAppClose(char *pItem)
|
|
{
|
|
char *pApplication;
|
|
DDENOTIFYSTRUCT *dns;
|
|
|
|
pApplication = GetNextArgument(pItem, NULL, TRUE);
|
|
if (!pApplication)
|
|
return 0;
|
|
|
|
// Look for the matching item and remove it
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if ((_stricmp(dns->szReturnTopic, "WWW_AppClose") == 0) &&
|
|
(_stricmp(dns->szResultApp, pApplication) == 0))
|
|
{
|
|
RemoveDNS(dns);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//************************************************
|
|
// QueryVersion
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_QueryVersion(char *pItem)
|
|
{
|
|
char *pApp, *pVersion, *p1;
|
|
long majorVersion, minorVersion;
|
|
int length;
|
|
HDDEDATA result;
|
|
struct VERSIONSTRUCT *pVersionItem;
|
|
|
|
XX_DMsg(DBG_SDI, ("QueryVersion received: %s\n", pItem));
|
|
|
|
pVersion = GetNextArgument(pItem, (long *) &majorVersion, FALSE);
|
|
if (!pVersion)
|
|
return 0;
|
|
|
|
pVersion = GetNextArgument(NULL, (long *) &minorVersion, FALSE);
|
|
if (!pVersion)
|
|
return 0;
|
|
|
|
// To remain compatible with version 0.9, allow NULL application names.
|
|
// Keep track of the version information only if the application name exists.
|
|
|
|
pApp = GetNextArgument(NULL, NULL, TRUE);
|
|
|
|
if (pApp)
|
|
{
|
|
// Add the information in the version structure list or modify
|
|
// an existing entry
|
|
|
|
for (pVersionItem = pVersionList; pVersionItem; pVersionItem = pVersionItem->next)
|
|
{
|
|
if (strncmp(pApp, pVersionItem->szApp, sizeof(pVersionItem->szApp) - 1) == 0)
|
|
break;
|
|
}
|
|
|
|
if (!pVersionItem)
|
|
{
|
|
pVersionItem = GTR_MALLOC(sizeof(struct VERSIONSTRUCT));
|
|
pVersionItem->next = pVersionList;
|
|
pVersionList = pVersionItem;
|
|
}
|
|
|
|
strncpy(pVersionItem->szApp, pApp, sizeof(pVersionItem->szApp) - 1);
|
|
pVersionItem->szApp[sizeof(pVersionItem->szApp) - 1] = '\0';
|
|
pVersionItem->major = majorVersion;
|
|
pVersionItem->minor = minorVersion;
|
|
}
|
|
|
|
// Now return the browser version and user agent
|
|
|
|
length = strlen(vv_UserAgentString) + 50;
|
|
|
|
pVersion = GTR_MALLOC(length);
|
|
if (!pVersion)
|
|
return 0;
|
|
|
|
memset(pVersion, 0, length);
|
|
|
|
// Version negotiation
|
|
|
|
if (majorVersion < 1)
|
|
{
|
|
minorVersion = 9; // version 0.9 is the minimum we can support
|
|
}
|
|
else if (majorVersion == 1)
|
|
{
|
|
minorVersion = 0; // version 1.0 is the maximum we can support
|
|
}
|
|
else
|
|
{
|
|
majorVersion = 1;
|
|
minorVersion = 0; // version 1.0 is the maximum we can support
|
|
}
|
|
|
|
p1 = MakeQuotedString(vv_UserAgentString);
|
|
sprintf(pVersion, "%d,%d,%s", majorVersion, minorVersion, p1);
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) pVersion, strlen(pVersion) + 1, 0, hszReturn, CF_TEXT, 0);
|
|
|
|
GTR_FREE(p1);
|
|
GTR_FREE(pVersion);
|
|
|
|
return result;
|
|
}
|
|
|
|
//************************************************
|
|
// CancelTransaction
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_CancelTransaction(char *pItem)
|
|
{
|
|
char *pTransID;
|
|
long lTransID;
|
|
struct Mwin *tw;
|
|
HDDEDATA result;
|
|
BOOL bCancel = FALSE;
|
|
DDENOTIFYSTRUCT *dns;
|
|
struct TRANSACTIONMAPSTRUCT *ptms;
|
|
char szTemp[50];
|
|
HSZ hszService, hszTopic, hszItem;
|
|
HCONV hConv;
|
|
HDDEDATA hReturn;
|
|
|
|
//pApplication = GetNextArgument(pItem, NULL, TRUE);
|
|
//if (!pApplication)
|
|
// return 0;
|
|
|
|
pTransID = GetNextArgument(pItem, &lTransID, FALSE);
|
|
if (!pTransID)
|
|
return 0;
|
|
|
|
// If the transaction is in the transaction map, we need to
|
|
// pass this information to another application.
|
|
// Can't use TMS_FromTransactionID here because we need to check
|
|
// for the outgoing ID instead of incoming ID.
|
|
|
|
for (ptms = pTransactionMap; ptms; ptms = ptms->next)
|
|
{
|
|
if (ptms->outgoing_transID == lTransID)
|
|
break;
|
|
}
|
|
|
|
if (ptms)
|
|
{
|
|
hszService = DdeCreateStringHandle(g_DdeInst, ptms->incoming_app, CP_WINANSI);
|
|
hszTopic = DdeCreateStringHandle(g_DdeInst, "WWW_CancelTransaction", CP_WINANSI);
|
|
|
|
hConv = DdeConnect(g_DdeInst, hszService, hszTopic, NULL);
|
|
|
|
if (hConv)
|
|
{
|
|
sprintf(szTemp, "%ld", ptms->incoming_transID);
|
|
hszItem = DdeCreateStringHandle(g_DdeInst, szTemp, CP_WINANSI);
|
|
|
|
hReturn = DdeClientTransaction(NULL, 0, hConv, hszItem, CF_TEXT,
|
|
XTYP_REQUEST, DDE_TIMEOUT, NULL);
|
|
|
|
DdeDisconnect(hConv);
|
|
DdeFreeStringHandle(g_DdeInst, hszItem);
|
|
|
|
if (hReturn)
|
|
DdeGetData(hReturn, (LPBYTE) &bCancel, sizeof(bCancel), 0);
|
|
}
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszService);
|
|
DdeFreeStringHandle(g_DdeInst, hszTopic);
|
|
|
|
if (bCancel)
|
|
{
|
|
// If a transaction gets canceled through CancelTransaction,
|
|
// then no OpenURLResult will be issued. So, we need to
|
|
// remove the tms structure from the transaction map list.
|
|
|
|
TMS_Remove(ptms);
|
|
}
|
|
|
|
// We can simply pass the same result that we received to the
|
|
// requester.
|
|
|
|
return (hReturn);
|
|
}
|
|
|
|
// Look for a match in the transaction list
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if (dns->lTransID == lTransID)
|
|
//(_stricmp(dns->szResultApp, pApplication) == 0))
|
|
{
|
|
// Found. Now cancel the transaction.
|
|
|
|
tw = Mlist;
|
|
|
|
while (tw)
|
|
{
|
|
if (tw->transID == lTransID)
|
|
{
|
|
Async_TerminateByWindow(tw);
|
|
|
|
// Return TRUE
|
|
|
|
bCancel = TRUE;
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &bCancel,
|
|
sizeof(bCancel), 0, hszReturn, CF_TEXT, 0);
|
|
|
|
return (result);
|
|
}
|
|
|
|
tw = tw->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Return FALSE
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &bCancel,
|
|
sizeof(bCancel), 0, hszReturn, CF_TEXT, 0);
|
|
return (result);
|
|
}
|
|
|
|
//************************************************
|
|
// DDE_Handle_BeginProgress
|
|
//************************************************
|
|
|
|
static HDDEDATA DDE_Handle_BeginProgress(char *pItem)
|
|
{
|
|
char *pTransID, *pMessage;
|
|
long lTransID;
|
|
struct Mwin *tw;
|
|
BOOL bReturn = TRUE;
|
|
HDDEDATA result;
|
|
struct TRANSACTIONMAPSTRUCT *ptms;
|
|
|
|
pTransID = GetNextArgument(pItem, &lTransID, FALSE);
|
|
if (!pTransID)
|
|
return 0;
|
|
|
|
pMessage = GetNextArgument(NULL, NULL, TRUE);
|
|
if (!pMessage)
|
|
return 0;
|
|
|
|
// Check the given transaction ID for a match within the transaction map.
|
|
// If there is a match then we are supposed to pass the progress message
|
|
// over to the requester.
|
|
|
|
ptms = TMS_FromTransactionID(lTransID);
|
|
if (ptms)
|
|
{
|
|
if (strcmp(ptms->incoming_app, ptms->outgoing_app) != 0)
|
|
{
|
|
SDI_Issue_BeginProgress(ptms->outgoing_app, ptms->outgoing_transID, pMessage, FALSE);
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &bReturn,
|
|
sizeof(bReturn), 0, hszReturn, CF_TEXT, 0);
|
|
|
|
return (result);
|
|
}
|
|
|
|
tw = TW_FromTransactionID(ptms->outgoing_transID);
|
|
}
|
|
else
|
|
tw = TW_FindTopmostWindow();
|
|
|
|
WAIT_Push(tw, waitNoInteract, pMessage);
|
|
WAIT_SetRange(tw, 0, 100, 100);
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &bReturn,
|
|
sizeof(bReturn), 0, hszReturn, CF_TEXT, 0);
|
|
return (result);
|
|
}
|
|
|
|
static HDDEDATA DDE_Handle_SetProgressRange(char *pItem)
|
|
{
|
|
char *pTransID, *pMax;
|
|
long lTransID, lMax;
|
|
BOOL bReturn = TRUE;
|
|
HDDEDATA result;
|
|
struct Mwin *tw;
|
|
struct TRANSACTIONMAPSTRUCT *ptms;
|
|
|
|
pTransID = GetNextArgument(pItem, &lTransID, FALSE);
|
|
if (!pTransID)
|
|
return 0;
|
|
|
|
pMax = GetNextArgument(NULL, &lMax, FALSE);
|
|
if (!pMax)
|
|
return 0;
|
|
|
|
// Check the given transaction ID for a match within the transaction map.
|
|
// If there is a match then we are supposed to pass the progress message
|
|
// over to the requester.
|
|
|
|
ptms = TMS_FromTransactionID(lTransID);
|
|
if (ptms)
|
|
{
|
|
if (strcmp(ptms->incoming_app, ptms->outgoing_app) != 0)
|
|
{
|
|
SDI_Issue_SetProgressRange(ptms->outgoing_app, ptms->outgoing_transID, lMax, FALSE);
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &bReturn,
|
|
sizeof(bReturn), 0, hszReturn, CF_TEXT, 0);
|
|
|
|
return (result);
|
|
}
|
|
tw = TW_FromTransactionID(ptms->outgoing_transID);
|
|
}
|
|
else
|
|
tw = TW_FindTopmostWindow();
|
|
|
|
WAIT_SetRange(tw, 0, 100, lMax);
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &bReturn,
|
|
sizeof(bReturn), 0, hszReturn, CF_TEXT, 0);
|
|
return (result);
|
|
}
|
|
|
|
static HDDEDATA DDE_Handle_MakingProgress(char *pItem)
|
|
{
|
|
char *pTransID, *pMessage, *pCurrent;
|
|
long lTransID, lCurrent;
|
|
BOOL bReturn = FALSE;
|
|
HDDEDATA result;
|
|
struct Mwin *tw;
|
|
struct TRANSACTIONMAPSTRUCT *ptms;
|
|
|
|
pTransID = GetNextArgument(pItem, &lTransID, FALSE);
|
|
if (!pTransID)
|
|
return 0;
|
|
|
|
pMessage = GetNextArgument(NULL, NULL, TRUE);
|
|
if (!pMessage)
|
|
return 0;
|
|
|
|
pCurrent = GetNextArgument(NULL, &lCurrent, FALSE);
|
|
if (!pCurrent)
|
|
return 0;
|
|
|
|
// Check the given transaction ID for a match within the transaction map.
|
|
// If there is a match then we are supposed to pass the progress message
|
|
// over to the requester.
|
|
|
|
ptms = TMS_FromTransactionID(lTransID);
|
|
if (ptms)
|
|
{
|
|
if (strcmp(ptms->incoming_app, ptms->outgoing_app) != 0)
|
|
{
|
|
SDI_Issue_MakingProgress(NULL, ptms->outgoing_app, ptms->outgoing_transID, pMessage, lCurrent, FALSE);
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &bReturn,
|
|
sizeof(bReturn), 0, hszReturn, CF_TEXT, 0);
|
|
|
|
return (result);
|
|
}
|
|
tw = TW_FromTransactionID(ptms->outgoing_transID);
|
|
}
|
|
else
|
|
tw = TW_FindTopmostWindow();
|
|
|
|
// Scale the current value down to 100% - we accept it only this way
|
|
|
|
if (tw->awi)
|
|
{
|
|
BHBar_SetStatusField(tw, pMessage);
|
|
lCurrent = 100 * lCurrent / tw->awi->nScalingDenominator;
|
|
UpdateThermometer(tw, (int) lCurrent);
|
|
}
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &bReturn,
|
|
sizeof(bReturn), 0, hszReturn, CF_TEXT, 0);
|
|
return (result);
|
|
}
|
|
|
|
static HDDEDATA DDE_Handle_EndProgress(char *pItem)
|
|
{
|
|
char *pTransID;
|
|
long lTransID;
|
|
struct Mwin *tw;
|
|
BOOL bReturn = TRUE;
|
|
HDDEDATA result;
|
|
struct TRANSACTIONMAPSTRUCT *ptms;
|
|
|
|
pTransID = GetNextArgument(pItem, &lTransID, FALSE);
|
|
if (!pTransID)
|
|
return 0;
|
|
|
|
// Check the given transaction ID for a match within the transaction map.
|
|
// If there is a match then we are supposed to pass the progress message
|
|
// over to the requester.
|
|
|
|
ptms = TMS_FromTransactionID(lTransID);
|
|
if (ptms)
|
|
{
|
|
if (strcmp(ptms->incoming_app, ptms->outgoing_app) != 0)
|
|
{
|
|
SDI_Issue_EndProgress(ptms->outgoing_app, ptms->outgoing_transID, FALSE);
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &bReturn,
|
|
sizeof(bReturn), 0, hszReturn, CF_TEXT, 0);
|
|
|
|
return (result);
|
|
}
|
|
tw = TW_FromTransactionID(ptms->outgoing_transID);
|
|
}
|
|
else
|
|
tw = TW_FindTopmostWindow();
|
|
|
|
WAIT_Pop(tw);
|
|
BHBar_SetStatusField(tw, "");
|
|
|
|
result = DdeCreateDataHandle(g_DdeInst, (LPBYTE) &bReturn,
|
|
sizeof(bReturn), 0, hszReturn, CF_TEXT, 0);
|
|
return (result);
|
|
}
|
|
|
|
//************************************************
|
|
//
|
|
// DDE ISSUE
|
|
//
|
|
//************************************************
|
|
|
|
BOOL SDI_Issue_ViewDocCache(struct Mwin *tw, HTFormat mime_type)
|
|
{
|
|
char *p, *p1;
|
|
char szWindowID[50];
|
|
DDENOTIFYSTRUCT *dns;
|
|
HSZ hszTopic, hszService, hszItem;
|
|
HCONV hConv;
|
|
BOOL result;
|
|
HDDEDATA hResult;
|
|
|
|
XX_DMsg(DBG_SDI, ("Inside ViewDocCache\n"));
|
|
|
|
sprintf(szWindowID, "%ld", tw->serialID);
|
|
p1 = MakeQuotedString(tw->request->destination->szActualURL);
|
|
|
|
p = GTR_MALLOC(strlen(p1) + strlen(szWindowID) + 10);
|
|
if (!p)
|
|
return TRUE; // abort
|
|
|
|
sprintf(p, "%s,%s", p1, szWindowID);
|
|
|
|
// Now find the app for the given MIME type
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if (dns->mime_type == mime_type)
|
|
break;
|
|
}
|
|
|
|
if (!dns)
|
|
return TRUE; // abort
|
|
|
|
// Now we found the item - Issue ViewDocCache
|
|
|
|
hszTopic = DdeCreateStringHandle(g_DdeInst, "WWW_ViewDocCache", CP_WINANSI);
|
|
hszService = DdeCreateStringHandle(g_DdeInst, dns->szResultApp, CP_WINANSI);
|
|
|
|
hConv = DdeConnect(g_DdeInst, hszService, hszTopic, NULL);
|
|
if (hConv)
|
|
{
|
|
hszItem = CreateArgument(dns->szResultApp, p);
|
|
hResult = DdeClientTransaction(NULL, 0, hConv, hszItem, CF_TEXT, XTYP_REQUEST,
|
|
DDE_TIMEOUT, NULL);
|
|
|
|
XX_DMsg(DBG_SDI, ("ViewDocCache result: %d\n", hResult));
|
|
|
|
if (!hResult)
|
|
result = FALSE; // document not in cache
|
|
else
|
|
DdeGetData(hResult, (LPBYTE) &result, sizeof(result), 0);
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszItem);
|
|
DdeDisconnect(hConv);
|
|
}
|
|
else
|
|
result = FALSE;
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszTopic);
|
|
DdeFreeStringHandle(g_DdeInst, hszService);
|
|
|
|
tw->bSuppressError = TRUE;
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL SDI_Issue_QueryViewer(struct Mwin *tw, HTFormat mime_type, char *pFilename, int nLength)
|
|
{
|
|
char *p, *p1, *p2, *pStripped;
|
|
DDENOTIFYSTRUCT *dns;
|
|
HSZ hszTopic, hszService, hszItem;
|
|
HCONV hConv;
|
|
HDDEDATA hResult;
|
|
BOOL ret;
|
|
char *pReturnedFileName;
|
|
|
|
XX_DMsg(DBG_SDI, ("Inside QueryViewer\n"));
|
|
|
|
p1 = MakeQuotedString(tw->request->destination->szActualURL);
|
|
p2 = MakeQuotedString(HTAtom_name(mime_type));
|
|
|
|
p = GTR_MALLOC(strlen(p1) + strlen(p2) + 10);
|
|
if (!p)
|
|
{
|
|
GTR_FREE(p1);
|
|
GTR_FREE(p2);
|
|
return FALSE; // abort
|
|
}
|
|
|
|
sprintf(p, "%s,%s", p1, p2);
|
|
|
|
// Now find the app for the given MIME type
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if (dns->mime_type == mime_type)
|
|
break;
|
|
}
|
|
|
|
if (!dns)
|
|
{
|
|
GTR_FREE(p1);
|
|
GTR_FREE(p2);
|
|
return FALSE;
|
|
}
|
|
|
|
// Now we found the item - Issue QueryViewer
|
|
|
|
hszTopic = DdeCreateStringHandle(g_DdeInst, "WWW_QueryViewer", CP_WINANSI);
|
|
hszService = DdeCreateStringHandle(g_DdeInst, dns->szResultApp, CP_WINANSI);
|
|
|
|
hConv = DdeConnect(g_DdeInst, hszService, hszTopic, NULL);
|
|
if (hConv)
|
|
{
|
|
hszItem = CreateArgument(dns->szResultApp, p);
|
|
hResult = DdeClientTransaction(NULL, 0, hConv, hszItem, CF_TEXT, XTYP_REQUEST,
|
|
DDE_TIMEOUT, NULL);
|
|
|
|
if (!hResult)
|
|
{
|
|
XX_DMsg(DBG_SDI, ("QueryViewer result: 0"));
|
|
|
|
GTR_FREE(p1);
|
|
GTR_FREE(p2);
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
pReturnedFileName = GTR_MALLOC(nLength + 1);
|
|
memset(pReturnedFileName, 0, nLength + 1);
|
|
DdeGetData(hResult, pReturnedFileName, nLength + 1, 0);
|
|
|
|
XX_DMsg(DBG_SDI, ("QueryViewer result: %s\n", pReturnedFileName));
|
|
|
|
if (pReturnedFileName[0] == '\0')
|
|
{
|
|
GTR_FREE(pReturnedFileName);
|
|
return FALSE;
|
|
}
|
|
|
|
strcpy(pFilename, pReturnedFileName);
|
|
GTR_FREE(pReturnedFileName);
|
|
|
|
// Strip off the enclosing double quotes
|
|
|
|
pStripped = GetNextArgument(pFilename, NULL, TRUE);
|
|
|
|
if (pStripped)
|
|
{
|
|
// If the string is empty, then return FALSE - this means
|
|
// that the helper app does not want to override the filename.
|
|
|
|
if (pStripped[0] == '\0')
|
|
{
|
|
GTR_FREE(p1);
|
|
GTR_FREE(p2);
|
|
return FALSE;
|
|
}
|
|
|
|
strcpy(pFilename, pStripped);
|
|
}
|
|
}
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszItem);
|
|
DdeDisconnect(hConv);
|
|
|
|
ret = TRUE;
|
|
}
|
|
else
|
|
ret = FALSE;
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszTopic);
|
|
DdeFreeStringHandle(g_DdeInst, hszService);
|
|
|
|
GTR_FREE(p1);
|
|
GTR_FREE(p2);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void SDI_Issue_ViewDocFile(char *pFilename, char *pURL, char *pMime, long lWindowID)
|
|
{
|
|
HCONV hConv;
|
|
HSZ hszService, hszTopic, hszItem;
|
|
char *pTemp, *p1, *p2, *p3;
|
|
int length;
|
|
HDDEDATA hReturn;
|
|
char szWindowID[50];
|
|
DDENOTIFYSTRUCT *dns;
|
|
|
|
XX_DMsg(DBG_SDI, ("Inside ViewDocFile\n"));
|
|
|
|
// Find the MIME type
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if (dns->mime_type == HTAtom_for(pMime))
|
|
break;
|
|
}
|
|
|
|
// Pass the file info to viewer
|
|
|
|
hszService = DdeCreateStringHandle(g_DdeInst, dns->szResultApp, CP_WINANSI);
|
|
hszTopic = DdeCreateStringHandle(g_DdeInst, "WWW_ViewDocFile", CP_WINANSI);
|
|
|
|
hConv = DdeConnect(g_DdeInst, hszService, hszTopic, NULL);
|
|
|
|
if (hConv)
|
|
{
|
|
sprintf(szWindowID, "%ld", lWindowID);
|
|
|
|
p1 = MakeQuotedString(pURL);
|
|
p2 = MakeQuotedString(pMime);
|
|
p3 = MakeQuotedString(pFilename);
|
|
|
|
length = strlen(p1) + strlen(p2) + strlen(szWindowID) + strlen(p3) + 10;
|
|
|
|
pTemp = GTR_MALLOC(length);
|
|
if (pTemp)
|
|
{
|
|
sprintf(pTemp, "%s,%s,%s,%s", p3, p1, p2, szWindowID);
|
|
hszItem = CreateArgument(dns->szResultApp, pTemp);
|
|
|
|
// Pass the data
|
|
|
|
XX_DMsg(DBG_SDI, ("ViewDocFile issued: %s,%s,%s,%s\n",
|
|
p3, p1, p2, szWindowID));
|
|
|
|
hReturn = DdeClientTransaction(NULL, 0, hConv, hszItem, CF_TEXT,
|
|
XTYP_POKE, DDE_TIMEOUT, NULL);
|
|
}
|
|
else
|
|
{
|
|
ERR_ReportError(NULL, SID_ERR_OUT_OF_MEMORY, NULL, NULL);
|
|
}
|
|
|
|
DdeDisconnect(hConv);
|
|
DdeFreeStringHandle(g_DdeInst, hszItem);
|
|
|
|
GTR_FREE(p1);
|
|
GTR_FREE(p2);
|
|
GTR_FREE(p3);
|
|
GTR_FREE(pTemp);
|
|
}
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszTopic);
|
|
DdeFreeStringHandle(g_DdeInst, hszService);
|
|
}
|
|
|
|
|
|
//*****************************************
|
|
// SDI_Issue_Result
|
|
//
|
|
// Issue results of OpenURL and ShowFile.
|
|
// For ShowFile, update the URL as well.
|
|
//*****************************************
|
|
|
|
void SDI_Issue_Result(long transID, long windowID, BOOL success)
|
|
{
|
|
DDENOTIFYSTRUCT *dns;
|
|
BOOL bFound = FALSE;
|
|
char szTemp[50];
|
|
HCONV hConv;
|
|
HSZ hszService, hszTopic, hszItem;
|
|
HDDEDATA hReturn;
|
|
struct Mwin *tw;
|
|
struct TRANSACTIONMAPSTRUCT *tms;
|
|
|
|
// Send the result of the last OpenURL to the application which issued OpenURL.
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if (dns->lTransID == transID)
|
|
break;
|
|
}
|
|
|
|
if (!dns)
|
|
return;
|
|
|
|
// Find the matching tw
|
|
|
|
tw = TW_FromTransactionID(transID);
|
|
if (!tw)
|
|
return;
|
|
|
|
if (!success)
|
|
{
|
|
// The specified URL load was a failure.
|
|
// Destroy the new window since the URL load failed
|
|
|
|
if (dns->bCreateNewWindow)
|
|
PostMessage(tw->hWndFrame, WM_CLOSE, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
// Update the URL if this is from ShowFile
|
|
|
|
if (strcmp(dns->szReturnTopic, "WWW_ShowFileResult") == 0)
|
|
{
|
|
GTR_FREE(tw->w3doc->szActualURL);
|
|
tw->w3doc->szActualURL = GTR_strdup(dns->pURL);
|
|
TBar_UpdateTBar(tw);
|
|
}
|
|
}
|
|
|
|
if (dns->szResultApp[0])
|
|
{
|
|
hszService = DdeCreateStringHandle(g_DdeInst, dns->szResultApp, CP_WINANSI);
|
|
hszTopic = DdeCreateStringHandle(g_DdeInst, dns->szReturnTopic, CP_WINANSI);
|
|
|
|
hConv = DdeConnect(g_DdeInst, hszService, hszTopic, NULL);
|
|
|
|
if (hConv)
|
|
{
|
|
switch(tw->lErrorOccurred)
|
|
{
|
|
case SDI_INVALID_URL:
|
|
case SDI_CANNOT_SAVE_FILE:
|
|
case SDI_INVALID_MIME:
|
|
sprintf(szTemp, "%ld,%ld", transID, tw->lErrorOccurred);
|
|
break;
|
|
|
|
default:
|
|
sprintf(szTemp, "%ld,%ld", transID, windowID);
|
|
break;
|
|
}
|
|
|
|
hszItem = CreateArgument(dns->szResultApp, szTemp);
|
|
|
|
hReturn = DdeClientTransaction(NULL, 0, hConv, hszItem, CF_TEXT,
|
|
XTYP_POKE, DDE_TIMEOUT, NULL);
|
|
|
|
DdeDisconnect(hConv);
|
|
DdeFreeStringHandle(g_DdeInst, hszItem);
|
|
}
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszService);
|
|
DdeFreeStringHandle(g_DdeInst, hszTopic);
|
|
}
|
|
|
|
RemoveDNS(dns);
|
|
|
|
tms = TMS_FromTransactionID(transID);
|
|
if (tms)
|
|
TMS_Remove(tms);
|
|
|
|
// Clear the tw structure since it gets reused
|
|
|
|
tw->transID = 0;
|
|
tw->lErrorOccurred = 0;
|
|
|
|
// Remove the tw if it's type is GWINDOWLESS
|
|
|
|
if (tw->wintype == GWINDOWLESS)
|
|
Plan_close(tw);
|
|
}
|
|
|
|
//*****************************************
|
|
// SDI_Issue_HTTPHeadResult
|
|
//
|
|
// Issue results of GetHTTPHead.
|
|
//*****************************************
|
|
|
|
void SDI_Issue_HTTPHeadResult(long transID, long windowID, BOOL success, char *pHeadData)
|
|
{
|
|
DDENOTIFYSTRUCT *dns;
|
|
BOOL bFound = FALSE;
|
|
char szTemp[50];
|
|
HCONV hConv;
|
|
HSZ hszService, hszTopic, hszItem;
|
|
HDDEDATA hReturn;
|
|
struct Mwin *tw;
|
|
|
|
// Send the result of the last OpenURL to the application which issued OpenURL.
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if (dns->lTransID == transID)
|
|
break;
|
|
}
|
|
|
|
if (!dns) // This should not happen
|
|
return;
|
|
|
|
// Find the matching tw
|
|
|
|
tw = TW_FromTransactionID(transID);
|
|
if (!tw)
|
|
return;
|
|
|
|
if (dns->szResultApp[0])
|
|
{
|
|
hszService = DdeCreateStringHandle(g_DdeInst, dns->szResultApp, CP_WINANSI);
|
|
hszTopic = DdeCreateStringHandle(g_DdeInst, dns->szReturnTopic, CP_WINANSI);
|
|
|
|
hConv = DdeConnect(g_DdeInst, hszService, hszTopic, NULL);
|
|
|
|
if (hConv)
|
|
{
|
|
sprintf(szTemp, "%ld,%ld", transID, windowID);
|
|
hszItem = CreateArgument(dns->szResultApp, szTemp);
|
|
|
|
hReturn = DdeClientTransaction(pHeadData, strlen(pHeadData), hConv, hszItem, CF_TEXT,
|
|
XTYP_POKE, DDE_TIMEOUT, NULL);
|
|
|
|
DdeDisconnect(hConv);
|
|
DdeFreeStringHandle(g_DdeInst, hszItem);
|
|
}
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszService);
|
|
DdeFreeStringHandle(g_DdeInst, hszTopic);
|
|
}
|
|
|
|
RemoveDNS(dns);
|
|
|
|
// Clear the tw structure since it gets reused
|
|
|
|
tw->transID = 0;
|
|
tw->lErrorOccurred = 0;
|
|
|
|
// Remove the tw if it's type is GWINDOWLESS (it ALWAYS should be, for this case)
|
|
|
|
if (tw->wintype == GWINDOWLESS)
|
|
Plan_close(tw);
|
|
}
|
|
|
|
//*****************************************
|
|
// SDI_Issue_URLEcho
|
|
//
|
|
// Issue URLEcho
|
|
//*****************************************
|
|
|
|
void SDI_Issue_URLEcho(struct Mwin *tw)
|
|
{
|
|
DDENOTIFYSTRUCT *dns;
|
|
BOOL bFound = FALSE;
|
|
HCONV hConv;
|
|
HSZ hszService, hszTopic, hszItem;
|
|
HDDEDATA hReturn;
|
|
char *p, *p1, *p2, *p3;
|
|
|
|
// Go through the list and issue URL echo to all registered apps
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if (_stricmp(dns->szReturnTopic, "WWW_URLEcho") == 0)
|
|
{
|
|
hszTopic = DdeCreateStringHandle(g_DdeInst, "WWW_URLEcho", CP_WINANSI);
|
|
hszService = DdeCreateStringHandle(g_DdeInst, dns->szResultApp, CP_WINANSI);
|
|
hConv = DdeConnect(g_DdeInst, hszService, hszTopic, NULL);
|
|
|
|
if (hConv)
|
|
{
|
|
p1 = MakeQuotedString(tw->w3doc->szActualURL);
|
|
p2 = MakeQuotedString(HTAtom_name(tw->mimeType));
|
|
p3 = MakeQuotedString(NULL);
|
|
|
|
p = GTR_MALLOC(strlen(p1) + strlen(p2) + strlen(p3) + 50);
|
|
sprintf(p, "%s,%s,%d,%s", p1, p2, tw->serialID, p3);
|
|
|
|
hszItem = CreateArgument(dns->szResultApp, p);
|
|
hReturn = DdeClientTransaction(NULL, 0, hConv, hszItem, CF_TEXT,
|
|
XTYP_POKE, DDE_TIMEOUT, NULL);
|
|
|
|
DdeDisconnect(hConv);
|
|
DdeFreeStringHandle(g_DdeInst, hszItem);
|
|
|
|
GTR_FREE(p3);
|
|
GTR_FREE(p2);
|
|
GTR_FREE(p1);
|
|
}
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszTopic);
|
|
DdeFreeStringHandle(g_DdeInst, hszService);
|
|
}
|
|
}
|
|
}
|
|
|
|
//*****************************************
|
|
// SDI_Issue_WindowClose
|
|
//
|
|
// Issue Window close
|
|
//*****************************************
|
|
|
|
void SDI_Issue_WindowClose(struct Mwin *tw)
|
|
{
|
|
DDENOTIFYSTRUCT *dns;
|
|
BOOL bFound = FALSE;
|
|
HCONV hConv;
|
|
HSZ hszService, hszTopic, hszItem;
|
|
HDDEDATA hReturn;
|
|
char szTemp[50];
|
|
|
|
// Go through the list and issue to all registered apps
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if ((dns->lWindowID == tw->serialID) &&
|
|
(_stricmp(dns->szReturnTopic, "WWW_WindowClose") == 0))
|
|
{
|
|
hszTopic = DdeCreateStringHandle(g_DdeInst, "WWW_WindowClose", CP_WINANSI);
|
|
hszService = DdeCreateStringHandle(g_DdeInst, dns->szResultApp, CP_WINANSI);
|
|
hConv = DdeConnect(g_DdeInst, hszService, hszTopic, NULL);
|
|
|
|
if (hConv)
|
|
{
|
|
sprintf(szTemp, "%ld,%d", dns->lWindowID, (int) wg.bShuttingDown);
|
|
hszItem = CreateArgument(dns->szResultApp, szTemp);
|
|
|
|
hReturn = DdeClientTransaction(NULL, 0, hConv, hszItem, CF_TEXT,
|
|
XTYP_POKE, DDE_TIMEOUT, NULL);
|
|
|
|
DdeDisconnect(hConv);
|
|
DdeFreeStringHandle(g_DdeInst, hszItem);
|
|
}
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszTopic);
|
|
DdeFreeStringHandle(g_DdeInst, hszService);
|
|
}
|
|
}
|
|
}
|
|
|
|
//*****************************************
|
|
// SDI_Issue_AppClose
|
|
//
|
|
// Issue app close
|
|
//*****************************************
|
|
|
|
void SDI_Issue_AppClose()
|
|
{
|
|
DDENOTIFYSTRUCT *dns;
|
|
BOOL bFound = FALSE;
|
|
HCONV hConv;
|
|
HSZ hszService, hszTopic;
|
|
HDDEDATA hReturn;
|
|
|
|
// Go through the list and issue to all registered apps
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if ((_stricmp(dns->szReturnTopic, "WWW_AppClose") == 0))
|
|
{
|
|
hszTopic = DdeCreateStringHandle(g_DdeInst, "WWW_AppClose", CP_WINANSI);
|
|
hszService = DdeCreateStringHandle(g_DdeInst, dns->szResultApp, CP_WINANSI);
|
|
|
|
hConv = DdeConnect(g_DdeInst, hszService, hszTopic, NULL);
|
|
|
|
if (hConv)
|
|
{
|
|
hReturn = DdeClientTransaction(NULL, 0, hConv, hszMosaic, CF_TEXT,
|
|
XTYP_POKE, DDE_TIMEOUT, NULL);
|
|
|
|
DdeDisconnect(hConv);
|
|
}
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszTopic);
|
|
DdeFreeStringHandle(g_DdeInst, hszService);
|
|
}
|
|
}
|
|
}
|
|
|
|
//*****************************************
|
|
// RegisterNow suite
|
|
//*****************************************
|
|
|
|
BOOL SDI_Issue_RegisterNow(struct Mwin *tw, char *pApplication)
|
|
{
|
|
HSZ hszApp, hszItem, hszTopic;
|
|
HCONV hConv;
|
|
char szBuffer[128];
|
|
BOOL bReturn;
|
|
long seconds;
|
|
HDDEDATA hResult;
|
|
|
|
// Tell the specified application to register within certain interval.
|
|
// Now issue RegisterNow and get the number of seconds required
|
|
|
|
sprintf(szBuffer, "\"MOSAIC\",%ld", TransactionID);
|
|
|
|
hszApp = DdeCreateStringHandle(g_DdeInst, pApplication, CP_WINANSI);
|
|
hszTopic = DdeCreateStringHandle(g_DdeInst, "WWW_RegisterNow", CP_WINANSI);
|
|
|
|
hszItem = CreateArgument(pApplication, szBuffer);
|
|
|
|
hConv = DdeConnect(g_DdeInst, hszApp, hszTopic, NULL);
|
|
if (hConv)
|
|
{
|
|
hResult = DdeClientTransaction(NULL, 0, hConv, hszItem, CF_TEXT, XTYP_REQUEST,
|
|
DDE_TIMEOUT, NULL);
|
|
|
|
if (!hResult)
|
|
bReturn = FALSE;
|
|
else
|
|
{
|
|
bReturn = TRUE;
|
|
|
|
// Get the requested number of seconds
|
|
|
|
DdeGetData(hResult, (LPBYTE) &seconds, sizeof(seconds), 0);
|
|
}
|
|
|
|
DdeDisconnect(hConv);
|
|
}
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszApp);
|
|
DdeFreeStringHandle(g_DdeInst, hszTopic);
|
|
DdeFreeStringHandle(g_DdeInst, hszItem);
|
|
|
|
if (bReturn)
|
|
{
|
|
// Start a timer for the duration of requested time
|
|
|
|
tw->transID = TransactionID;
|
|
SetTimer(wg.hWndHidden, TransactionID, seconds * 1000, NULL);
|
|
|
|
TransactionID++;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void DDE_Handle_RegisterDone(char *pItem)
|
|
{
|
|
long lTransID;
|
|
char *pTransID;
|
|
struct Mwin *tw;
|
|
|
|
pTransID = GetNextArgument(pItem, &lTransID, FALSE);
|
|
if (!pTransID)
|
|
return;
|
|
|
|
if (KillTimer(wg.hWndHidden, lTransID))
|
|
{
|
|
/* Existence of timer indicates that the transaction ID is valid */
|
|
|
|
tw = Mlist;
|
|
while (tw)
|
|
{
|
|
if (tw->transID == lTransID)
|
|
{
|
|
Async_UnblockByWindow(tw);
|
|
return;
|
|
}
|
|
|
|
tw = tw->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
//************************************************
|
|
// Utility functions
|
|
//************************************************
|
|
|
|
BOOL GTR_HasHelperRegistered(HTFormat format)
|
|
{
|
|
int i;
|
|
DDENOTIFYSTRUCT *dns;
|
|
BOOL result = FALSE;
|
|
struct Viewer_Info *pCurrent;
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if (dns->mime_type == format)
|
|
{
|
|
// See if it's still up
|
|
|
|
result = GTR_IsHelperReady(dns->szResultApp);
|
|
|
|
// If not up, it means that the helper died without
|
|
// unregistering. Clean up for the helper.
|
|
|
|
if (!result)
|
|
{
|
|
i = Hash_Find(gPrefs.pHashViewers,
|
|
HTAtom_name(format), NULL, (void **) &pCurrent);
|
|
|
|
if (i != -1)
|
|
{
|
|
if (pCurrent->bTemporaryStruct)
|
|
Hash_DeleteIndexedEntry(gPrefs.pHashViewers, i);
|
|
else
|
|
pCurrent->szCurrentViewerServiceName[0] = '\0';
|
|
}
|
|
|
|
RemoveDNS(dns);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL GTR_StartApplication(char *app)
|
|
{
|
|
return (ExecuteCommand(app) == 0);
|
|
}
|
|
|
|
BOOL GTR_IsHelperReady(char *app)
|
|
{
|
|
int index;
|
|
HSZ hszService, hszTopic;
|
|
HCONV hConv;
|
|
|
|
/* First check the hash to see if the server is up. */
|
|
|
|
index = Hash_Find(pServerHash, app, NULL, NULL);
|
|
if (index != -1)
|
|
return TRUE;
|
|
|
|
/* Now attempt to connect using some bogus topic - this hack
|
|
assumes that the helper app will only check the service name during
|
|
XTYP_CONNECT */
|
|
|
|
hszTopic = DdeCreateStringHandle(g_DdeInst, "1", CP_WINANSI);
|
|
hszService = DdeCreateStringHandle(g_DdeInst, app, CP_WINANSI);
|
|
|
|
hConv = DdeConnect(g_DdeInst, hszService, hszTopic, NULL);
|
|
if (hConv)
|
|
DdeDisconnect(hConv);
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszTopic);
|
|
DdeFreeStringHandle(g_DdeInst, hszService);
|
|
|
|
return (hConv != 0);
|
|
}
|
|
|
|
//************************************************
|
|
// Custom protocol handler
|
|
// When an app adds a new protocol, this function
|
|
// takes care of dispatching OpenURL
|
|
//************************************************
|
|
|
|
int DDE_Custom_Protocol_Handler(HTRequest *request, struct Mwin *tw)
|
|
{
|
|
int result;
|
|
long lWindowID;
|
|
HTList *cur;
|
|
char *pProtocol;
|
|
HTProtocol *p;
|
|
|
|
pProtocol = GTR_strdup(request->destination->szRequestedURL);
|
|
strtok(pProtocol, ":");
|
|
|
|
// Make sure the protocol exists
|
|
|
|
cur = protocols;
|
|
while ((p = (HTProtocol *) HTList_nextObject(cur)))
|
|
{
|
|
if (strcmp(p->name, pProtocol) == 0)
|
|
break;
|
|
}
|
|
|
|
GTR_FREE(pProtocol);
|
|
|
|
if (!p)
|
|
{
|
|
// Protocol not found. Return an error.
|
|
|
|
return -1;
|
|
}
|
|
|
|
lWindowID = tw->serialID;
|
|
|
|
result = SDI_Issue_OpenURL(request->destination->szRequestedURL, NULL, &lWindowID,
|
|
0, request->szPostData, request->szPostData ? "" : "application/x-www-form-urlencoded",
|
|
"MOSAIC", "MOSAIC");
|
|
|
|
return result;
|
|
}
|
|
|
|
int SDI_Issue_OpenURL(char *pURL, char *pFilespec, long *lWindowID, long lFlags,
|
|
char *pFormData, char *pMime, char *pProgressApp, char *pReturnApp)
|
|
{
|
|
char *p0, *p1, *p2, *p3, *p4, *p5;
|
|
int size = 0;
|
|
char szWindowID[50], szFlags[50];
|
|
char *pBuffer, *pProtocolFromURL;
|
|
DDENOTIFYSTRUCT *dns;
|
|
HDDEDATA hResult;
|
|
HSZ hszApp, hszItem, hszTopic;
|
|
HCONV hConv;
|
|
int ret = NO;
|
|
|
|
// Get the protocol from URL
|
|
|
|
pProtocolFromURL = GTR_MALLOC(strlen(pURL) + 1);
|
|
strcpy(pProtocolFromURL, pURL);
|
|
strtok(pProtocolFromURL, ":");
|
|
|
|
// Find the application name from the protocol name
|
|
|
|
for (dns = pDNS; dns; dns = dns->next)
|
|
{
|
|
if ((dns->pProtocol) &&
|
|
(strcmp(dns->pProtocol, pProtocolFromURL) == 0))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Compose the argument string for OpenURL and issue it to the protocol handler.
|
|
|
|
p0 = MakeQuotedString(pURL);
|
|
p1 = MakeQuotedString(pFilespec);
|
|
p2 = MakeQuotedString(pFormData);
|
|
p3 = MakeQuotedString(pMime);
|
|
p4 = MakeQuotedString(pProgressApp);
|
|
p5 = MakeQuotedString(pReturnApp);
|
|
|
|
sprintf(szWindowID, "%ld", *lWindowID);
|
|
sprintf(szFlags, "%ld", lFlags);
|
|
|
|
pBuffer = GTR_MALLOC(strlen(p0) + strlen(p1) + strlen(p2) + strlen(p3) + strlen(p4) + strlen(p5) +
|
|
strlen(szWindowID) + strlen(szFlags) + 10);
|
|
sprintf(pBuffer, "%s,%s,%s,%s,%s,%s,%s,%s", p0, p1, szWindowID, szFlags, p2, p3, p4, p5);
|
|
|
|
hszApp = DdeCreateStringHandle(g_DdeInst, dns->szResultApp, CP_WINANSI);
|
|
hszTopic = DdeCreateStringHandle(g_DdeInst, "WWW_OpenURL", CP_WINANSI);
|
|
hszItem = CreateArgument(dns->szResultApp, pBuffer);
|
|
|
|
hConv = DdeConnect(g_DdeInst, hszApp, hszTopic, NULL);
|
|
if (hConv)
|
|
{
|
|
hResult = DdeClientTransaction(NULL, 0, hConv, hszItem, CF_TEXT, XTYP_REQUEST,
|
|
DDE_TIMEOUT, NULL);
|
|
|
|
if (hResult)
|
|
{
|
|
DdeGetData(hResult, (LPBYTE) lWindowID, sizeof(*lWindowID), 0);
|
|
if (*lWindowID)
|
|
ret = 29999; // fake success
|
|
}
|
|
|
|
DdeDisconnect(hConv);
|
|
}
|
|
|
|
DdeFreeStringHandle(g_DdeInst, hszApp);
|
|
DdeFreeStringHandle(g_DdeInst, hszTopic);
|
|
DdeFreeStringHandle(g_DdeInst, hszItem);
|
|
|
|
GTR_FREE(pBuffer);
|
|
GTR_FREE(p0);
|
|
GTR_FREE(p1);
|
|
GTR_FREE(p2);
|
|
GTR_FREE(p3);
|
|
GTR_FREE(p4);
|
|
GTR_FREE(p5);
|
|
GTR_FREE(pProtocolFromURL);
|
|
|
|
return ret;
|
|
}
|
|
|
|
//************************************************
|
|
// Initialization and Termination functions
|
|
//************************************************
|
|
|
|
BOOL InitDDE(void)
|
|
{
|
|
DWORD flags;
|
|
|
|
flags = APPCLASS_STANDARD;
|
|
|
|
if (DdeInitialize((LPDWORD) &g_DdeInst, (PFNCALLBACK) DdeCallBack, flags, 0L))
|
|
return FALSE;
|
|
|
|
hszMosaic = DdeCreateStringHandle(g_DdeInst, "MOSAIC", CP_WINANSI);
|
|
hszReturn = DdeCreateStringHandle(g_DdeInst, "Return", CP_WINANSI);
|
|
|
|
if (!DdeNameService(g_DdeInst, hszMosaic, 0, DNS_REGISTER))
|
|
return FALSE;
|
|
|
|
// Create a hash table that contains all of our supported topics.
|
|
|
|
pTopicHash = Hash_Create();
|
|
|
|
Hash_Add(pTopicHash, "WWW_OpenURL", NULL, DDE_Handle_OpenURL);
|
|
Hash_Add(pTopicHash, "WWW_GetHTTPHead", NULL, DDE_Handle_GetHTTPHead);
|
|
Hash_Add(pTopicHash, "WWW_OpenURLResult", NULL, DDE_Handle_OpenURLResult);
|
|
Hash_Add(pTopicHash, "WWW_ShowFile", NULL, DDE_Handle_ShowFile);
|
|
Hash_Add(pTopicHash, "WWW_Activate", NULL, DDE_Handle_Activate);
|
|
Hash_Add(pTopicHash, "WWW_ListWindows", NULL, DDE_Handle_ListWindows);
|
|
Hash_Add(pTopicHash, "WWW_GetWindowInfo", NULL, DDE_Handle_GetWindowInfo);
|
|
Hash_Add(pTopicHash, "WWW_ParseAnchor", NULL, DDE_Handle_ParseAnchor);
|
|
Hash_Add(pTopicHash, "WWW_Exit", NULL, DDE_Handle_Exit);
|
|
Hash_Add(pTopicHash, "WWW_RegisterURLEcho", NULL, DDE_Handle_RegisterURLEcho);
|
|
Hash_Add(pTopicHash, "WWW_UnRegisterURLEcho", NULL, DDE_Handle_UnRegisterURLEcho);
|
|
Hash_Add(pTopicHash, "WWW_RegisterWindowClose", NULL, DDE_Handle_RegisterWindowClose);
|
|
Hash_Add(pTopicHash, "WWW_UnRegisterWindowClose", NULL, DDE_Handle_UnRegisterWindowClose);
|
|
Hash_Add(pTopicHash, "WWW_RegisterProtocol", NULL, DDE_Handle_RegisterProtocol);
|
|
Hash_Add(pTopicHash, "WWW_UnRegisterProtocol", NULL, DDE_Handle_UnRegisterProtocol);
|
|
Hash_Add(pTopicHash, "WWW_RegisterViewer", NULL, DDE_Handle_RegisterViewer);
|
|
Hash_Add(pTopicHash, "WWW_UnRegisterViewer", NULL, DDE_Handle_UnRegisterViewer);
|
|
Hash_Add(pTopicHash, "WWW_RegisterAppClose", NULL, DDE_Handle_RegisterAppClose);
|
|
Hash_Add(pTopicHash, "WWW_UnRegisterAppClose", NULL, DDE_Handle_UnRegisterAppClose);
|
|
Hash_Add(pTopicHash, "WWW_QueryVersion", NULL, DDE_Handle_QueryVersion);
|
|
Hash_Add(pTopicHash, "WWW_CancelTransaction", NULL, DDE_Handle_CancelTransaction);
|
|
Hash_Add(pTopicHash, "WWW_BeginProgress", NULL, DDE_Handle_BeginProgress);
|
|
Hash_Add(pTopicHash, "WWW_SetProgressRange", NULL, DDE_Handle_SetProgressRange);
|
|
Hash_Add(pTopicHash, "WWW_MakingProgress", NULL, DDE_Handle_MakingProgress);
|
|
Hash_Add(pTopicHash, "WWW_EndProgress", NULL, DDE_Handle_EndProgress);
|
|
Hash_Add(pTopicHash, "WWW_RegisterDone", NULL, DDE_Handle_RegisterDone);
|
|
|
|
// Create a server hash table
|
|
|
|
pServerHash = Hash_Create();
|
|
|
|
// Prepare the argument buffer
|
|
|
|
pArgumentBuffer = NULL;
|
|
pCurrentArgPos = NULL;
|
|
|
|
// Verity hack buffer
|
|
|
|
pFileContent = NULL;
|
|
|
|
// Version list
|
|
|
|
pVersionList = NULL;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void TerminateDDE(void)
|
|
{
|
|
DDENOTIFYSTRUCT *dns, *dnsnext;
|
|
struct VERSIONSTRUCT *pCur, *pNext;
|
|
|
|
DdeNameService(g_DdeInst, hszMosaic, 0, DNS_UNREGISTER);
|
|
|
|
if (hszMosaic)
|
|
DdeFreeStringHandle(g_DdeInst, hszMosaic);
|
|
if (hszReturn)
|
|
DdeFreeStringHandle(g_DdeInst, hszReturn);
|
|
|
|
Hash_Destroy(pTopicHash);
|
|
Hash_Destroy(pServerHash);
|
|
|
|
if (g_DdeInst)
|
|
DdeUninitialize(g_DdeInst);
|
|
|
|
if (pArgumentBuffer)
|
|
GTR_FREE(pArgumentBuffer);
|
|
if (pArgReturnBuffer)
|
|
GTR_FREE(pArgReturnBuffer);
|
|
|
|
dns = pDNS;
|
|
while (dns)
|
|
{
|
|
dnsnext = dns->next;
|
|
RemoveDNS(dns);
|
|
dns = dnsnext;
|
|
}
|
|
|
|
// Verity hack clean up
|
|
|
|
if (pFileContent)
|
|
GTR_FREE(pFileContent);
|
|
|
|
// Version list clean up
|
|
|
|
pCur = pVersionList;
|
|
while (pCur)
|
|
{
|
|
pNext = pCur->next;
|
|
GTR_FREE(pCur);
|
|
pCur = pNext;
|
|
}
|
|
}
|
|
|
|
#endif /* FEATURE_IAPI */
|
|
|