windows-nt/Source/XPSP1/NT/shell/osshell/accesory/winchat/dde.c
2020-09-26 16:20:57 +08:00

1058 lines
36 KiB
C

/*---------------------------------------------------------------------------*\
| DDE MODULE
| This module contains the routines necessary for maintaining dde
| conversations.
|
| FUNCTIONS
| ---------
| CreateCharData
| CreatePasteData
| SendFontToPartner
|
|
| Copyright (c) Microsoft Corp., 1990-1993
|
| created: 01-Nov-91
| history: 01-Nov-91 <clausgi> created.
| 29-Dec-92 <chriswil> port to NT, cleanup.
| 19-Oct-93 <chriswil> unicode enhancements from a-dianeo.
|
\*---------------------------------------------------------------------------*/
#include <windows.h>
#include <mmsystem.h>
#include <ddeml.h>
#include <commdlg.h>
#include <commctrl.h>
#include "winchat.h"
#include "globals.h"
// CP963
BOOL TranslateMultiBytePosToWideCharPos( HWND hWnd, DWORD dwStart, DWORD dwEnd, LPDWORD lpdwStart, LPDWORD lpdwEnd )
{
INT nLine=0, wChars = 0, i, j, delta; // Just to make compiler happy, initialize wChars here.
DWORD mCnt=0, mChars, offset, p_offset=0;
HANDLE hText;
PTCHAR pStartText;
CHAR szBuff[800];
LONG wStart, wEnd;
*lpdwStart = 0;
*lpdwEnd = 0;
wStart = -1;
wEnd = -1;
hText = (HANDLE)SendMessage( hWnd, EM_GETHANDLE, 0, 0);
if( !( hText ) )
return( FALSE );
pStartText = LocalLock( hText);
if( !( pStartText ) )
{
LocalUnlock( hText );
return( FALSE );
}
while(1)
{
INT flag = 0;
offset = (DWORD)SendMessage( hWnd, EM_LINEINDEX, nLine++, 0 );
if( offset > 0 ) { //0D0A
delta = offset - (p_offset+wChars);
if( delta ) mCnt += delta;
p_offset = offset;
} else if ( offset == 0) {
*lpdwStart = dwStart;
*lpdwEnd = dwEnd;
LocalUnlock( hText );
return( TRUE );
} else {
LocalUnlock( hText );
return( FALSE );
}
wChars = (WORD)SendMessage( hWnd, EM_LINELENGTH, offset, 0 );
mChars = WideCharToMultiByte( CP_ACP, 0, pStartText+offset,
wChars, NULL, 0, NULL, NULL );
if( (dwStart>=mCnt) && (dwStart<=mCnt+mChars)) flag |= 1;
if((dwEnd>=mCnt) && (dwEnd<=mCnt+mChars)) flag |= 2;
if( flag )
{
WideCharToMultiByte( CP_ACP, 0, pStartText+offset, wChars,
szBuff, mChars, NULL, NULL );
for(i=0,j=0; ; i++,j++ )
{
if( (flag&1) && (wStart==-1) )
{
if(dwStart <= (mCnt+i) )
{
wStart = offset+j;
if( flag == 1 ) break;
}
}
if( (flag&2) && (wEnd==-1) )
{
if(dwEnd <= (mCnt+i) )
{
wEnd = offset+j;
if( flag == 2 ) break;
}
}
if( (flag==3) && (wStart>-1) && (wEnd>-1) ) break;
if( IsDBCSLeadByte(szBuff[i]) ) i++;
}
}
if( (wStart>-1) && (wEnd>-1) ) break;
mCnt += mChars;
}
*lpdwStart = (DWORD)wStart;
*lpdwEnd = (DWORD)wEnd;
LocalUnlock( hText );
return( TRUE );
}
BOOL
TranslateWideCharPosToMultiBytePos( HWND hWnd, DWORD dwStart, DWORD dwEnd, LPDWORD lpdwStart, LPDWORD lpdwEnd )
{
INT nLine=0, wChars = 0, i, j,delta; // Just to make compiler happy, initialize wChars here.
DWORD mChars, mCnt=0, offset, p_offset=0;
HANDLE hText;
PTCHAR pStartText;
CHAR szBuff[800];
LONG mStart, mEnd;
*lpdwStart = 0;
*lpdwEnd = 0;
mStart = -1;
mEnd = -1;
hText = (HANDLE)SendMessage( hWnd, EM_GETHANDLE, 0, 0);
if( !( hText ) )
return( FALSE );
pStartText = LocalLock( hText);
if( !( pStartText ) )
{
LocalUnlock( hText );
return( FALSE );
}
while(1)
{
INT flag = 0;
offset = (DWORD)SendMessage( hWnd, EM_LINEINDEX, nLine++, 0 );
if( offset > 0 ) { //ODOA
delta = offset - (p_offset+wChars);
if( delta ) mCnt += delta;
p_offset = offset;
} else if ( offset == 0) {
*lpdwStart = dwStart;
*lpdwEnd = dwEnd;
LocalUnlock( hText );
return( TRUE );
} else {
LocalUnlock( hText );
return( FALSE );
}
wChars = (WORD)SendMessage( hWnd, EM_LINELENGTH, offset, 0 );
mChars = WideCharToMultiByte( CP_ACP, 0, pStartText+offset,
wChars, NULL, 0, NULL, NULL );
if( (dwStart>=offset) && (dwStart<=offset+wChars)) flag |= 1;
if( (dwEnd>=offset) && (dwEnd<=offset+wChars) ) flag |= 2;
if( flag )
{
WideCharToMultiByte( CP_ACP, 0, pStartText+offset, wChars,
szBuff, mChars, NULL, NULL );
for(i=0,j=0; ; i++, j++ )
{
if( (flag&1) && (mStart==-1) )
{
if(dwStart == (offset+i) )
{
mStart = mCnt+j;
if( flag==1 ) break;
}
}
if( (flag&2) && (mEnd==-1) )
{
if(dwEnd == (offset+i) )
{
mEnd = mCnt+j;
if( flag == 2 ) break;
}
}
if( (flag==3) && (mStart>-1) && (mEnd>-1) ) break;
if( IsDBCSLeadByte(szBuff[j]) ) j++;
}
}
if( (mStart>-1) && (mEnd>-1) ) break;
mCnt += mChars;
}
*lpdwStart = (DWORD)mStart;
*lpdwEnd = (DWORD)mEnd;
LocalUnlock( hText );
return( TRUE );
}
/*---------------------------------------------------------------------------*\
| DDE CALLBACK PROCEDURE
| This routine handles the events sent by DDEML.
|
| created: 11-Nov-91
| history: 29-Dec-92 <chriswil> ported to NT.
|
\*---------------------------------------------------------------------------*/
HDDEDATA CALLBACK DdeCallback(UINT wType, UINT wFmt, HCONV hConv, HSZ hszTopic, HSZ hszItem, HDDEDATA hData, DWORD lData1, DWORD lData2)
{
HDC hdc;
HDDEDATA hRet;
WPARAM wParam;
LPARAM lParam;
DWORD dwTemp1,dwTemp2;
hRet = (HDDEDATA)0;
switch(wType)
{
case XTYP_REGISTER:
case XTYP_UNREGISTER:
break;
case XTYP_XACT_COMPLETE:
if(lData1 == XactID)
{
if(hData != (HDDEDATA)0)
{
ChatState.fServerVerified = TRUE;
}
else
{
SetStatusWindowText(szNoConnect);
ChatState.fConnectPending = FALSE;
UpdateButtonStates();
}
}
break;
case XTYP_ADVDATA:
case XTYP_POKE:
if(ChatState.fConnected && (wFmt == cf_chatdata))
{
DdeGetData(hData,(LPBYTE)&ChatDataRcv,sizeof(ChatDataRcv),0L);
// This is failing in some cases. Eventually, this should be in.
//
#ifndef DDEMLBUG
if(DdeGetLastError(idInst) == DMLERR_NO_ERROR)
#endif
{
switch(ChatDataRcv.type)
{
// FE specific:
// We have a DBCS string selection.
//
case CHT_DBCS_STRING:
{
HANDLE hStrBuf;
LPSTR lpStrBuf;
hStrBuf = GlobalAlloc(GMEM_FIXED,ChatDataRcv.uval.cd_dbcs.size+1);
if (hStrBuf)
{
lpStrBuf = GlobalLock(hStrBuf);
if (lpStrBuf)
{
DdeGetData(hData,(BYTE *)lpStrBuf,ChatDataRcv.uval.cd_dbcs.size+1,XCHATSIZEA);
#ifndef DDEMLBUG
if (DdeGetLastError(idInst) == DMLERR_NO_ERROR)
#endif
{
SendMessage(hwndRcv,EM_SETREADONLY,(WPARAM)FALSE,0L);
#ifdef UNICODE
{
LPWSTR lpStrUnicode;
ULONG cChars = strlen(lpStrBuf) + 1;
//
// Get text output position from DDE packet, and set it to EditControl.
//
// !!! BUG BUG BUG !!!
//
// If the sender is not Unicode Edit control. the position data might be
// stored for MBCS string context.
// in that case, we might draw the text at incorrect position.
//
// We have to convert to fit Unicode string.
// wParam = SET_EM_SETSEL_WPARAM(LOWORD(
//ChatDataRcv.uval.cd_dbcs.SelPos),HIWORD(ChatDataRcv.uval.cd_dbcs.SelPos));
// lParam = SET_EM_SETSEL_LPARAM(LOWORD(
//ChatDataRcv.uval.cd_dbcs.SelPos),HIWORD(ChatDataRcv.uval.cd_dbcs.SelPos));
TranslateMultiBytePosToWideCharPos(
hwndRcv,
(DWORD)LOWORD(ChatDataRcv.uval.cd_dbcs.SelPos),
(DWORD)HIWORD(ChatDataRcv.uval.cd_dbcs.SelPos),
&dwTemp1,
&dwTemp2 );
// sign extend them
wParam=(WPARAM)(INT_PTR)dwTemp1;
lParam=(LPARAM)(INT_PTR)dwTemp2;
SendMessage(hwndRcv, EM_SETSEL, wParam, lParam);
//
// Allocate temporary buffer for Nls conversion.
//
if((lpStrUnicode = LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT,
cChars * 2)) == NULL )
{
break;
}
//
// Convert MBCS to Unicode. because DDE packet contains MBCS string any time
// for downlevel connectivity, But if we are compiled with -DUNICODE flag,
// EditControl can only handled Unicode, just convert it.
//
MultiByteToWideChar(CP_ACP,0,
lpStrBuf,cChars,
lpStrUnicode,cChars * sizeof(WCHAR)
);
// Set string to EditControl.
SendMessage(hwndRcv,EM_REPLACESEL,0,(LPARAM)lpStrUnicode);
LocalFree(lpStrUnicode);
}
#else // !UNICODE
wParam = SET_EM_SETSEL_WPARAM(LOWORD(ChatDataRcv.uval.cd_dbcs.SelPos),HIWORD(ChatDataRcv.uval.cd_dbcs.SelPos));
lParam = SET_EM_SETSEL_LPARAM(LOWORD(ChatDataRcv.uval.cd_dbcs.SelPos),HIWORD(ChatDataRcv.uval.cd_dbcs.SelPos));
SendMessage(hwndRcv,EM_SETSEL,wParam,lParam);
SendMessage(hwndRcv,EM_REPLACESEL,0,(LPARAM)lpStrBuf);
#endif // UNICODE
SendMessage(hwndRcv,EM_SETREADONLY,(WPARAM)TRUE,0L);
hRet = (HDDEDATA)TRUE;
}
GlobalUnlock(hStrBuf);
}
GlobalFree(hStrBuf);
}
}
break;
// This is a Unicode conversation, so mark the flag.
//
case CHT_UNICODE:
ChatState.fUnicode = TRUE;
hRet = (HDDEDATA)TRUE;
break;
// We got a character...stuff it into the control.
//
case CHT_CHAR:
// In case user is tracking, so WM_CHAR is not tossed (thanks Dave)
//
SendMessage(hwndRcv,WM_LBUTTONUP,0,0L);
SendMessage(hwndRcv,EM_SETREADONLY,(WPARAM)FALSE,0L);
if (gfDbcsEnabled) {
TranslateMultiBytePosToWideCharPos( hwndRcv,
(DWORD)HIWORD(ChatDataRcv.uval.cd_dbcs.SelPos),
(DWORD)LOWORD(ChatDataRcv.uval.cd_dbcs.SelPos),
&dwTemp1, &dwTemp2 );
// sign extend them
wParam=(WPARAM)(INT_PTR)dwTemp1;
lParam=(LPARAM)(INT_PTR)dwTemp2;
} else {
wParam = SET_EM_SETSEL_WPARAM(LOWORD(ChatDataRcv.uval.cd_char.SelPos),HIWORD(ChatDataRcv.uval.cd_char.SelPos));
lParam = SET_EM_SETSEL_LPARAM(LOWORD(ChatDataRcv.uval.cd_char.SelPos),HIWORD(ChatDataRcv.uval.cd_char.SelPos));
}
SendMessage(hwndRcv,EM_SETSEL,wParam,lParam);
SendMessage(hwndRcv,WM_CHAR,ChatDataRcv.uval.cd_char.Char,0L);
SendMessage(hwndRcv,EM_SETREADONLY,TRUE,0L);
hRet = (HDDEDATA)TRUE;
break;
// We have a paste selection.
//
case CHT_PASTEA:
case CHT_PASTEW:
{
HANDLE hPasteBuf,hAnsiBuf;
LPSTR lpPasteBuf,lpAnsiBuf;
DWORD BufSize;
BufSize = (ChatDataRcv.type == CHT_PASTEA ? ((ChatDataRcv.uval.cd_paste.size + 1) * sizeof(TCHAR)) : (ChatDataRcv.uval.cd_paste.size + sizeof(WCHAR)));
hPasteBuf = GlobalAlloc(GMEM_FIXED,BufSize);
if(hPasteBuf)
{
lpPasteBuf = GlobalLock(hPasteBuf);
if(lpPasteBuf)
{
if(ChatDataRcv.type == CHT_PASTEA)
{
hAnsiBuf = GlobalAlloc(GMEM_FIXED,ChatDataRcv.uval.cd_paste.size+sizeof(WCHAR));
if(hAnsiBuf)
{
lpAnsiBuf = GlobalLock(hAnsiBuf);
if(lpAnsiBuf)
{
DdeGetData(hData,(BYTE *)lpAnsiBuf,ChatDataRcv.uval.cd_paste.size+sizeof(WCHAR),XCHATSIZEA);
MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,lpAnsiBuf,ChatDataRcv.uval.cd_paste.size+sizeof(WCHAR),
(LPWSTR)lpPasteBuf,ChatDataRcv.uval.cd_paste.size+1);
GlobalUnlock(hAnsiBuf);
}
GlobalFree(hAnsiBuf);
}
}
else
DdeGetData(hData,(BYTE *)lpPasteBuf,ChatDataRcv.uval.cd_paste.size+sizeof(WCHAR),XCHATSIZEW);
#ifndef DDEMLBUG
if(DdeGetLastError(idInst) == DMLERR_NO_ERROR)
#endif
{
SendMessage(hwndRcv,EM_SETREADONLY,(WPARAM)FALSE,0L);
wParam = SET_EM_SETSEL_WPARAM(LOWORD(ChatDataRcv.uval.cd_char.SelPos),HIWORD(ChatDataRcv.uval.cd_char.SelPos));
lParam = SET_EM_SETSEL_LPARAM(LOWORD(ChatDataRcv.uval.cd_char.SelPos),HIWORD(ChatDataRcv.uval.cd_char.SelPos));
SendMessage(hwndRcv,EM_SETSEL,wParam,lParam);
SendMessage(hwndRcv,EM_REPLACESEL,0,(LPARAM)lpPasteBuf);
SendMessage(hwndRcv,EM_SETREADONLY,(WPARAM)TRUE,0L);
hRet = (HDDEDATA)TRUE;
}
GlobalUnlock(hPasteBuf);
}
GlobalFree(hPasteBuf);
}
}
break;
// We got a font change. Create and stuff.
//
case CHT_FONTA:
case CHT_FONTW:
if(ChatDataRcv.type == CHT_FONTA)
{
CHATDATAA ChatDataA;
memcpy(ChatDataA.uval.cd_win.lf.lfFaceName,ChatDataRcv.uval.cd_win.lf.lfFaceName,LF_XPACKFACESIZE + (sizeof(COLORREF) * 2));
ChatDataRcv.uval.cd_win.cref = ChatDataA.uval.cd_win.cref;
ChatDataRcv.uval.cd_win.brush = ChatDataA.uval.cd_win.brush;
MultiByteToWideChar(CP_OEMCP,MB_PRECOMPOSED,ChatDataA.uval.cd_win.lf.lfFaceName,LF_XPACKFACESIZE,ChatDataRcv.uval.cd_win.lf.lfFaceName,LF_XPACKFACESIZE);
}
UnpackFont(&lfRcv,&ChatDataRcv.uval.cd_win.lf);
hdc = GetDC(hwndApp);
if(hdc)
{
RcvBrushColor = PartBrushColor = GetNearestColor(hdc,ChatDataRcv.uval.cd_win.brush);
RcvColorref = GetNearestColor(hdc,ChatDataRcv.uval.cd_win.cref);
ReleaseDC(hwndApp,hdc);
}
if(!ChatState.fUseOwnFont)
{
if(hEditRcvFont)
DeleteObject(hEditRcvFont);
hEditRcvFont = CreateFontIndirect(&lfRcv);
DeleteObject(hEditRcvBrush);
hEditRcvBrush = CreateSolidBrush(RcvBrushColor);
if(hEditRcvFont)
{
SendMessage(hwndRcv,WM_SETFONT,(WPARAM)hEditRcvFont,1L);
InvalidateRect(hwndRcv,NULL,TRUE);
}
}
hRet = (HDDEDATA)TRUE;
break;
#ifdef PROTOCOL_NEGOTIATE
case CHT_PROTOCOL:
// Determine characteristics we have in common.
//
FlagIntersection(ChatDataRcv.uval.cd_protocol.pckt);
// Return the flavor, if not already done.
//
if(!ChatState.fProtocolSent)
AnnounceSupport();
hRet = (HDDEDATA)TRUE;
break;
#endif
default:
break;
}
}
}
break;
case XTYP_CONNECT:
if(!ChatState.fConnected && !ChatState.fConnectPending && !ChatState.fInProcessOfDialing)
{
// allow connect only on the chat topic.
//
if(!DdeCmpStringHandles(hszTopic,hszChatTopic))
hRet = (HDDEDATA)TRUE;
}
break;
case XTYP_CONNECT_CONFIRM:
ChatState.fConnectPending = TRUE;
ChatState.fAllowAnswer = FALSE;
ChatState.fIsServer = TRUE;
ghConv = hConv;
nConnectAttempt = 0;
UpdateButtonStates();
break;
case XTYP_DISCONNECT:
if(ChatState.fConnectPending || ChatState.fConnected)
{
if(ChatState.fConnected)
wsprintf(szBuf,szHasTerminated,(LPTSTR)szConvPartner);
else
if(ChatState.fServerVerified)
wsprintf(szBuf,szNoConnectionTo,(LPTSTR)szConvPartner);
else
lstrcpy(szBuf,szNoConnect);
SetStatusWindowText(szBuf);
ChatState.fConnectPending = FALSE;
ChatState.fConnected = FALSE;
ChatState.fIsServer = FALSE;
ChatState.fUnicode = FALSE;
#ifdef PROTOCOL_NEGOTIATE
ChatState.fProtocolSent = FALSE;
#endif
// suspend text entry
//
UpdateButtonStates();
SendMessage(hwndSnd,EM_SETREADONLY,TRUE,0L);
SetWindowText(hwndApp,szAppName);
// stop the ringing immediately
//
if(ChatState.fMMSound)
sndPlaySound(NULL,SND_ASYNC);
// cut the animation short
//
if(cAnimate)
cAnimate = 1;
}
break;
case XTYP_REQUEST:
break;
case XTYP_ADVREQ:
if(ChatState.fIsServer && ChatState.fConnected)
{
switch(ChatData.type)
{
case CHT_DBCS_STRING:
hRet = CreateDbcsStringData();
break;
case CHT_CHAR:
case CHT_FONTA:
case CHT_FONTW:
case CHT_UNICODE:
hRet = CreateCharData();
break;
case CHT_PASTEA:
case CHT_PASTEW:
hRet = CreatePasteData();
break;
#ifdef PROTOCOL_NEGOTIATE
case CHT_PROTOCOL:
hRet = CreateProtocolData();
break;
#endif
default:
break;
}
}
break;
case XTYP_ADVSTART:
if(ChatState.fConnectPending)
{
// is this the connect confirm attempt?
//
if(!DdeCmpStringHandles(hszItem,hszConnectTest))
return((HDDEDATA)TRUE);
DdeQueryString(idInst,hszItem,szConvPartner,32L,0);
wsprintf(szBuf,szIsCalling,(LPTSTR)szConvPartner);
SetStatusWindowText(szBuf);
// set window text on initial connect attempt
//
if(nConnectAttempt == 0)
{
wsprintf(szBuf,TEXT("%s - [%s]"),(LPTSTR)szAppName,(LPTSTR)szConvPartner);
SetWindowText(hwndApp,szBuf);
}
if(ChatState.fAllowAnswer)
{
ChatState.fConnected = TRUE;
ChatState.fConnectPending = FALSE;
UpdateButtonStates();
ClearEditControls();
SendMessage(hwndSnd,EM_SETREADONLY,FALSE,0L);
wsprintf(szBuf,szConnectedTo,(LPTSTR)szConvPartner);
SetStatusWindowText(szBuf);
if(hszConvPartner)
DdeFreeStringHandle(idInst,hszConvPartner);
hszConvPartner = DdeCreateStringHandle(idInst,szConvPartner,CP_WINUNICODE);
// Indicate that it is a Unicode conversation.
//
PostMessage(hwndApp,WM_COMMAND,IDX_UNICODECONV,0L);
// SendFontToPartner(); -- would like to do this - won't work
// so we workaround it by posting the app window a message
// to perform this function...
//
PostMessage(hwndApp,WM_COMMAND,IDX_DEFERFONTCHANGE,0L);
#ifdef PROTOCOL_NEGOTIATE
PostMessage(hwndApp,WM_COMMAND,IDX_DEFERPROTOCOL,0L);
#endif
hRet = (HDDEDATA)TRUE;
}
else
if(!(nConnectAttempt++ % 6))
{
// Number of animation cycles == 24: ring remote.
//
cAnimate = 24;
idTimer = SetTimer(hwndApp,(UINT_PTR)1,(UINT_PTR)55,NULL);
FlashWindow(hwndApp,TRUE);
DoRing(szWcRingIn);
}
}
break;
default:
break;
}
return(hRet);
}
/*---------------------------------------------------------------------------*\
| FE specific:
| CREATE DBCS STRING TRANSACTION DATA
| This routine creates a DDE object representing the DBCS string information.
|
| created: 07-Jul-93
|
\*---------------------------------------------------------------------------*/
HDDEDATA CreateDbcsStringData(VOID)
{
HDDEDATA hTmp = (HDDEDATA)0;
LPSTR lpDbcsMem;
DWORD cbDbcs;
hTmp = (HDDEDATA)0;
lpDbcsMem = GlobalLock(ChatData.uval.cd_dbcs.hString);
if(lpDbcsMem)
{
cbDbcs = (DWORD)GlobalSize(ChatData.uval.cd_dbcs.hString);
ChatData.uval.cd_dbcs.size = (DWORD)cbDbcs;
hTmp = DdeCreateDataHandle(idInst,NULL,sizeof(ChatData)+cbDbcs,0L,hszTextItem,cf_chatdata,0);
if(hTmp)
{
DdeAddData(hTmp,(LPBYTE)&ChatData,sizeof(ChatData),0L);
DdeAddData(hTmp,(BYTE *)lpDbcsMem,cbDbcs,XCHATSIZEA);
}
GlobalUnlock(ChatData.uval.cd_dbcs.hString);
}
GlobalFree(ChatData.uval.cd_dbcs.hString);
return(hTmp);
}
/*---------------------------------------------------------------------------*\
| CREATE CHARACTER TRANSACTION DATA
| This routine creates a DDE object representing the charater information.
|
| created: 11-Nov-91
| history: 29-Dec-92 <chriswil> ported to NT.
|
\*---------------------------------------------------------------------------*/
HDDEDATA CreateCharData(VOID)
{
HANDLE hData;
LPCHATDATA lpData;
HDDEDATA hTmp;
BOOL fDefCharUsed;
hTmp = (HDDEDATA)0;
hData = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE,sizeof(ChatData));
if(hData)
{
lpData = (LPCHATDATA)GlobalLock(hData);
if(lpData)
{
*lpData = ChatData;
if(ChatData.type == CHT_FONTA)
{
lpData->uval.cd_win.cref = ((LPCHATDATAA)lpData)->uval.cd_win.cref;
lpData->uval.cd_win.brush = ((LPCHATDATAA)lpData)->uval.cd_win.brush;
}
hTmp = DdeCreateDataHandle(idInst,(LPBYTE)lpData,sizeof(ChatData),0L,hszTextItem,cf_chatdata,0);
GlobalUnlock(hData);
}
GlobalFree(hData);
}
return(hTmp);
UNREFERENCED_PARAMETER(fDefCharUsed);
}
/*---------------------------------------------------------------------------*\
| CREATE PASTE TRANSACTION DATA
| This routine creates a DDE object representing the paste information.
|
| created: 11-Nov-91
| history: 29-Dec-92 <chriswil> ported to NT.
|
\*---------------------------------------------------------------------------*/
HDDEDATA CreatePasteData(VOID)
{
HDDEDATA hTmp,hRet;
HANDLE hClipb;
LPTSTR lpClipMem;
DWORD cbClip;
LPSTR lpBuf;
DWORD dwBytes;
hRet = (HDDEDATA)0;
if(OpenClipboard(hwndSnd))
{
hClipb = GetClipboardData(CF_UNICODETEXT);
if(hClipb)
{
lpClipMem = GlobalLock(hClipb);
if(lpClipMem)
{
cbClip = (DWORD)GlobalSize(hClipb);
ChatData.uval.cd_paste.size = cbClip;
hTmp = DdeCreateDataHandle(idInst,NULL,(sizeof(ChatData)+cbClip),
0,hszTextItem,cf_chatdata,0);
if(hTmp)
{
DdeAddData(hTmp,(LPBYTE)&ChatData,sizeof(ChatData),0L);
if(ChatData.type == CHT_PASTEA)
{
dwBytes = WideCharToMultiByte(CP_ACP,0,lpClipMem,-1,NULL,0,NULL,NULL);
ChatData.uval.cd_paste.size = dwBytes;
lpBuf = LocalAlloc(LPTR,dwBytes);
if(lpBuf)
{
WideCharToMultiByte(CP_ACP,0,lpClipMem,-1,lpBuf,dwBytes,NULL,NULL);
DdeAddData(hTmp,(LPBYTE)lpBuf,dwBytes,XCHATSIZEA);
hRet = hTmp;
LocalFree(lpBuf);
}
}
else
{
DdeAddData(hTmp,(LPBYTE)lpClipMem,cbClip,XCHATSIZEW);
hRet = hTmp;
}
}
GlobalUnlock(hClipb);
}
}
CloseClipboard();
}
return(hRet);
}
#ifdef PROTOCOL_NEGOTIATE
/*---------------------------------------------------------------------------*\
| CREATE PROTOCOL TRANSACTION DATA
| This routine creates a DDE object representing the protocol information.
|
| created: 11-Nov-91
| history: 07-Apr-93 <chriswil> ported to NT.
|
\*---------------------------------------------------------------------------*/
HDDEDATA CreateProtocolData(VOID)
{
HANDLE hData;
LPCHATDATA lpData;
HDDEDATA hTmp;
hTmp = (HDDEDATA)0;
hData = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE,sizeof(ChatData));
if(hData)
{
lpData = (LPCHATDATA)GlobalLock(hData);
if(lpData)
{
ChatData.type = CHT_PROTOCOL;
ChatData.uval.cd_protocol.dwVer = CHT_VER;
ChatData.uval.cd_protocol.pckt = GetCurrentPckt();
*lpData = ChatData;
hTmp = DdeCreateDataHandle(idInst,(LPBYTE)lpData,sizeof(ChatData),0L,hszTextItem,cf_chatdata,0);
GlobalUnlock(hData);
}
GlobalFree(hData);
}
return(hTmp);
}
#endif
#ifdef PROTOCOL_NEGOTIATE
/*---------------------------------------------------------------------------*\
| GET CURRENT PACKET
| This routine returns the current packet capabilities of the system.
|
| created: 11-Nov-91
| history: 07-Apr-93 <chriswil> ported to NT.
|
\*---------------------------------------------------------------------------*/
PCKT GetCurrentPckt(VOID)
{
PCKT pckt;
pckt = PCKT_TEXT;
return(pckt);
}
#endif
#ifdef PROTOCOL_NEGOTIATE
/*---------------------------------------------------------------------------*\
| FLAG INTERSECTION
| This routine determines which packet types are supporte and flags the
| appropriate ones.
|
| created: 11-Nov-91
| history: 07-Apr-93 <chriswil> ported to NT.
|
\*---------------------------------------------------------------------------*/
VOID FlagIntersection(PCKT pcktPartner)
{
PCKT pcktNet;
pcktNet = GetCurrentPckt() & pcktPartner;
return;
}
#endif
/*---------------------------------------------------------------------------*\
| SEND FONT TO PARTNER
| This routine sends the font-information to the partner in this
| conversation.
|
| created: 11-Nov-91
| history: 29-Dec-92 <chriswil> ported to NT.
|
\*---------------------------------------------------------------------------*/
VOID SendFontToPartner(VOID)
{
HDDEDATA hDdeData;
PCHATDATAA pAChat;
ChatData.type = (WORD)((ChatState.fUnicode ? CHT_FONTW : CHT_FONTA));
PackFont(&ChatData.uval.cd_win.lf,&lfSnd);
if(ChatData.type == CHT_FONTA)
{
pAChat = (PCHATDATAA)&ChatData;
pAChat->uval.cd_win.cref = SndColorref;
pAChat->uval.cd_win.brush = SndBrushColor;
}
else
{
ChatData.uval.cd_win.cref = SndColorref;
ChatData.uval.cd_win.brush = SndBrushColor;
}
if(!ChatState.fIsServer)
{
hDdeData = DdeCreateDataHandle(idInst,(LPBYTE) &ChatData,sizeof(ChatData),0L,hszTextItem,cf_chatdata,0);
if(hDdeData)
DdeClientTransaction((LPBYTE)hDdeData,(DWORD)-1,ghConv,hszTextItem,cf_chatdata,XTYP_POKE,(DWORD)TIMEOUT_ASYNC,(LPDWORD)&StrXactID);
}
else
DdePostAdvise(idInst,hszChatTopic,hszConvPartner);
return;
}
/*---------------------------------------------------------------------------*\
| UNPACK FONT
| This routine unpacks the font stored in the packed transaction.
|
| created: 04-Feb-93
| history: 04-Feb-93 <chriswil> created.
|
\*---------------------------------------------------------------------------*/
VOID UnpackFont(LPLOGFONT lf, LPXPACKFONT lfPacked)
{
lf->lfHeight = (LONG)(short)lfPacked->lfHeight;
lf->lfWidth = (LONG)(short)lfPacked->lfWidth;
lf->lfEscapement = (LONG)(short)lfPacked->lfEscapement;
lf->lfOrientation = (LONG)(short)lfPacked->lfOrientation;
lf->lfWeight = (LONG)(short)lfPacked->lfWeight;
lf->lfItalic = (BYTE)lfPacked->lfItalic;
lf->lfUnderline = (BYTE)lfPacked->lfUnderline;
lf->lfStrikeOut = (BYTE)lfPacked->lfStrikeOut;
lf->lfCharSet = (BYTE)lfPacked->lfCharSet;
lf->lfOutPrecision = (BYTE)lfPacked->lfOutPrecision;
lf->lfClipPrecision = (BYTE)lfPacked->lfClipPrecision;
lf->lfQuality = (BYTE)lfPacked->lfQuality;
lf->lfPitchAndFamily = (BYTE)lfPacked->lfPitchAndFamily;
lstrcpy(lf->lfFaceName,lfPacked->lfFaceName);
return;
}
/*---------------------------------------------------------------------------*\
| PACK FONT
| This routine packs the font for transaction.
|
| created: 04-Feb-93
| history: 04-Feb-93 <chriswil> created.
|
\*---------------------------------------------------------------------------*/
VOID PackFont(LPXPACKFONT lfPacked, LPLOGFONT lf)
{
BOOL fDefCharUsed;
lfPacked->lfHeight = (WORD)lf->lfHeight;
lfPacked->lfWidth = (WORD)lf->lfWidth;
lfPacked->lfEscapement = (WORD)lf->lfEscapement;
lfPacked->lfOrientation = (WORD)lf->lfOrientation;
lfPacked->lfWeight = (WORD)lf->lfWeight;
lfPacked->lfItalic = (BYTE)lf->lfItalic;
lfPacked->lfUnderline = (BYTE)lf->lfUnderline;
lfPacked->lfStrikeOut = (BYTE)lf->lfStrikeOut;
lfPacked->lfCharSet = (BYTE)lf->lfCharSet;
lfPacked->lfOutPrecision = (BYTE)lf->lfOutPrecision;
lfPacked->lfClipPrecision = (BYTE)lf->lfClipPrecision;
lfPacked->lfQuality = (BYTE)lf->lfQuality;
lfPacked->lfPitchAndFamily = (BYTE)lf->lfPitchAndFamily;
if(ChatData.type == CHT_FONTA)
WideCharToMultiByte(CP_OEMCP,0,lf->lfFaceName,LF_XPACKFACESIZE,(LPSTR)(lfPacked->lfFaceName),LF_XPACKFACESIZE,NULL,&fDefCharUsed);
else
lstrcpy(lfPacked->lfFaceName,lf->lfFaceName);
return;
}