/*---------------------------------------------------------------------------*\ | 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 created. | 29-Dec-92 port to NT, cleanup. | 19-Oct-93 unicode enhancements from a-dianeo. | \*---------------------------------------------------------------------------*/ #include #include #include #include #include #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 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 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 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 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 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 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 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 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 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; }