Source code of Windows XP (NT5)
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.

1057 lines
36 KiB

  1. /*---------------------------------------------------------------------------*\
  2. | DDE MODULE
  3. | This module contains the routines necessary for maintaining dde
  4. | conversations.
  5. |
  6. | FUNCTIONS
  7. | ---------
  8. | CreateCharData
  9. | CreatePasteData
  10. | SendFontToPartner
  11. |
  12. |
  13. | Copyright (c) Microsoft Corp., 1990-1993
  14. |
  15. | created: 01-Nov-91
  16. | history: 01-Nov-91 <clausgi> created.
  17. | 29-Dec-92 <chriswil> port to NT, cleanup.
  18. | 19-Oct-93 <chriswil> unicode enhancements from a-dianeo.
  19. |
  20. \*---------------------------------------------------------------------------*/
  21. #include <windows.h>
  22. #include <mmsystem.h>
  23. #include <ddeml.h>
  24. #include <commdlg.h>
  25. #include <commctrl.h>
  26. #include "winchat.h"
  27. #include "globals.h"
  28. // CP963
  29. BOOL TranslateMultiBytePosToWideCharPos( HWND hWnd, DWORD dwStart, DWORD dwEnd, LPDWORD lpdwStart, LPDWORD lpdwEnd )
  30. {
  31. INT nLine=0, wChars = 0, i, j, delta; // Just to make compiler happy, initialize wChars here.
  32. DWORD mCnt=0, mChars, offset, p_offset=0;
  33. HANDLE hText;
  34. PTCHAR pStartText;
  35. CHAR szBuff[800];
  36. LONG wStart, wEnd;
  37. *lpdwStart = 0;
  38. *lpdwEnd = 0;
  39. wStart = -1;
  40. wEnd = -1;
  41. hText = (HANDLE)SendMessage( hWnd, EM_GETHANDLE, 0, 0);
  42. if( !( hText ) )
  43. return( FALSE );
  44. pStartText = LocalLock( hText);
  45. if( !( pStartText ) )
  46. {
  47. LocalUnlock( hText );
  48. return( FALSE );
  49. }
  50. while(1)
  51. {
  52. INT flag = 0;
  53. offset = (DWORD)SendMessage( hWnd, EM_LINEINDEX, nLine++, 0 );
  54. if( offset > 0 ) { //0D0A
  55. delta = offset - (p_offset+wChars);
  56. if( delta ) mCnt += delta;
  57. p_offset = offset;
  58. } else if ( offset == 0) {
  59. *lpdwStart = dwStart;
  60. *lpdwEnd = dwEnd;
  61. LocalUnlock( hText );
  62. return( TRUE );
  63. } else {
  64. LocalUnlock( hText );
  65. return( FALSE );
  66. }
  67. wChars = (WORD)SendMessage( hWnd, EM_LINELENGTH, offset, 0 );
  68. mChars = WideCharToMultiByte( CP_ACP, 0, pStartText+offset,
  69. wChars, NULL, 0, NULL, NULL );
  70. if( (dwStart>=mCnt) && (dwStart<=mCnt+mChars)) flag |= 1;
  71. if((dwEnd>=mCnt) && (dwEnd<=mCnt+mChars)) flag |= 2;
  72. if( flag )
  73. {
  74. WideCharToMultiByte( CP_ACP, 0, pStartText+offset, wChars,
  75. szBuff, mChars, NULL, NULL );
  76. for(i=0,j=0; ; i++,j++ )
  77. {
  78. if( (flag&1) && (wStart==-1) )
  79. {
  80. if(dwStart <= (mCnt+i) )
  81. {
  82. wStart = offset+j;
  83. if( flag == 1 ) break;
  84. }
  85. }
  86. if( (flag&2) && (wEnd==-1) )
  87. {
  88. if(dwEnd <= (mCnt+i) )
  89. {
  90. wEnd = offset+j;
  91. if( flag == 2 ) break;
  92. }
  93. }
  94. if( (flag==3) && (wStart>-1) && (wEnd>-1) ) break;
  95. if( IsDBCSLeadByte(szBuff[i]) ) i++;
  96. }
  97. }
  98. if( (wStart>-1) && (wEnd>-1) ) break;
  99. mCnt += mChars;
  100. }
  101. *lpdwStart = (DWORD)wStart;
  102. *lpdwEnd = (DWORD)wEnd;
  103. LocalUnlock( hText );
  104. return( TRUE );
  105. }
  106. BOOL
  107. TranslateWideCharPosToMultiBytePos( HWND hWnd, DWORD dwStart, DWORD dwEnd, LPDWORD lpdwStart, LPDWORD lpdwEnd )
  108. {
  109. INT nLine=0, wChars = 0, i, j,delta; // Just to make compiler happy, initialize wChars here.
  110. DWORD mChars, mCnt=0, offset, p_offset=0;
  111. HANDLE hText;
  112. PTCHAR pStartText;
  113. CHAR szBuff[800];
  114. LONG mStart, mEnd;
  115. *lpdwStart = 0;
  116. *lpdwEnd = 0;
  117. mStart = -1;
  118. mEnd = -1;
  119. hText = (HANDLE)SendMessage( hWnd, EM_GETHANDLE, 0, 0);
  120. if( !( hText ) )
  121. return( FALSE );
  122. pStartText = LocalLock( hText);
  123. if( !( pStartText ) )
  124. {
  125. LocalUnlock( hText );
  126. return( FALSE );
  127. }
  128. while(1)
  129. {
  130. INT flag = 0;
  131. offset = (DWORD)SendMessage( hWnd, EM_LINEINDEX, nLine++, 0 );
  132. if( offset > 0 ) { //ODOA
  133. delta = offset - (p_offset+wChars);
  134. if( delta ) mCnt += delta;
  135. p_offset = offset;
  136. } else if ( offset == 0) {
  137. *lpdwStart = dwStart;
  138. *lpdwEnd = dwEnd;
  139. LocalUnlock( hText );
  140. return( TRUE );
  141. } else {
  142. LocalUnlock( hText );
  143. return( FALSE );
  144. }
  145. wChars = (WORD)SendMessage( hWnd, EM_LINELENGTH, offset, 0 );
  146. mChars = WideCharToMultiByte( CP_ACP, 0, pStartText+offset,
  147. wChars, NULL, 0, NULL, NULL );
  148. if( (dwStart>=offset) && (dwStart<=offset+wChars)) flag |= 1;
  149. if( (dwEnd>=offset) && (dwEnd<=offset+wChars) ) flag |= 2;
  150. if( flag )
  151. {
  152. WideCharToMultiByte( CP_ACP, 0, pStartText+offset, wChars,
  153. szBuff, mChars, NULL, NULL );
  154. for(i=0,j=0; ; i++, j++ )
  155. {
  156. if( (flag&1) && (mStart==-1) )
  157. {
  158. if(dwStart == (offset+i) )
  159. {
  160. mStart = mCnt+j;
  161. if( flag==1 ) break;
  162. }
  163. }
  164. if( (flag&2) && (mEnd==-1) )
  165. {
  166. if(dwEnd == (offset+i) )
  167. {
  168. mEnd = mCnt+j;
  169. if( flag == 2 ) break;
  170. }
  171. }
  172. if( (flag==3) && (mStart>-1) && (mEnd>-1) ) break;
  173. if( IsDBCSLeadByte(szBuff[j]) ) j++;
  174. }
  175. }
  176. if( (mStart>-1) && (mEnd>-1) ) break;
  177. mCnt += mChars;
  178. }
  179. *lpdwStart = (DWORD)mStart;
  180. *lpdwEnd = (DWORD)mEnd;
  181. LocalUnlock( hText );
  182. return( TRUE );
  183. }
  184. /*---------------------------------------------------------------------------*\
  185. | DDE CALLBACK PROCEDURE
  186. | This routine handles the events sent by DDEML.
  187. |
  188. | created: 11-Nov-91
  189. | history: 29-Dec-92 <chriswil> ported to NT.
  190. |
  191. \*---------------------------------------------------------------------------*/
  192. HDDEDATA CALLBACK DdeCallback(UINT wType, UINT wFmt, HCONV hConv, HSZ hszTopic, HSZ hszItem, HDDEDATA hData, DWORD lData1, DWORD lData2)
  193. {
  194. HDC hdc;
  195. HDDEDATA hRet;
  196. WPARAM wParam;
  197. LPARAM lParam;
  198. DWORD dwTemp1,dwTemp2;
  199. hRet = (HDDEDATA)0;
  200. switch(wType)
  201. {
  202. case XTYP_REGISTER:
  203. case XTYP_UNREGISTER:
  204. break;
  205. case XTYP_XACT_COMPLETE:
  206. if(lData1 == XactID)
  207. {
  208. if(hData != (HDDEDATA)0)
  209. {
  210. ChatState.fServerVerified = TRUE;
  211. }
  212. else
  213. {
  214. SetStatusWindowText(szNoConnect);
  215. ChatState.fConnectPending = FALSE;
  216. UpdateButtonStates();
  217. }
  218. }
  219. break;
  220. case XTYP_ADVDATA:
  221. case XTYP_POKE:
  222. if(ChatState.fConnected && (wFmt == cf_chatdata))
  223. {
  224. DdeGetData(hData,(LPBYTE)&ChatDataRcv,sizeof(ChatDataRcv),0L);
  225. // This is failing in some cases. Eventually, this should be in.
  226. //
  227. #ifndef DDEMLBUG
  228. if(DdeGetLastError(idInst) == DMLERR_NO_ERROR)
  229. #endif
  230. {
  231. switch(ChatDataRcv.type)
  232. {
  233. // FE specific:
  234. // We have a DBCS string selection.
  235. //
  236. case CHT_DBCS_STRING:
  237. {
  238. HANDLE hStrBuf;
  239. LPSTR lpStrBuf;
  240. hStrBuf = GlobalAlloc(GMEM_FIXED,ChatDataRcv.uval.cd_dbcs.size+1);
  241. if (hStrBuf)
  242. {
  243. lpStrBuf = GlobalLock(hStrBuf);
  244. if (lpStrBuf)
  245. {
  246. DdeGetData(hData,(BYTE *)lpStrBuf,ChatDataRcv.uval.cd_dbcs.size+1,XCHATSIZEA);
  247. #ifndef DDEMLBUG
  248. if (DdeGetLastError(idInst) == DMLERR_NO_ERROR)
  249. #endif
  250. {
  251. SendMessage(hwndRcv,EM_SETREADONLY,(WPARAM)FALSE,0L);
  252. #ifdef UNICODE
  253. {
  254. LPWSTR lpStrUnicode;
  255. ULONG cChars = strlen(lpStrBuf) + 1;
  256. //
  257. // Get text output position from DDE packet, and set it to EditControl.
  258. //
  259. // !!! BUG BUG BUG !!!
  260. //
  261. // If the sender is not Unicode Edit control. the position data might be
  262. // stored for MBCS string context.
  263. // in that case, we might draw the text at incorrect position.
  264. //
  265. // We have to convert to fit Unicode string.
  266. // wParam = SET_EM_SETSEL_WPARAM(LOWORD(
  267. //ChatDataRcv.uval.cd_dbcs.SelPos),HIWORD(ChatDataRcv.uval.cd_dbcs.SelPos));
  268. // lParam = SET_EM_SETSEL_LPARAM(LOWORD(
  269. //ChatDataRcv.uval.cd_dbcs.SelPos),HIWORD(ChatDataRcv.uval.cd_dbcs.SelPos));
  270. TranslateMultiBytePosToWideCharPos(
  271. hwndRcv,
  272. (DWORD)LOWORD(ChatDataRcv.uval.cd_dbcs.SelPos),
  273. (DWORD)HIWORD(ChatDataRcv.uval.cd_dbcs.SelPos),
  274. &dwTemp1,
  275. &dwTemp2 );
  276. // sign extend them
  277. wParam=(WPARAM)(INT_PTR)dwTemp1;
  278. lParam=(LPARAM)(INT_PTR)dwTemp2;
  279. SendMessage(hwndRcv, EM_SETSEL, wParam, lParam);
  280. //
  281. // Allocate temporary buffer for Nls conversion.
  282. //
  283. if((lpStrUnicode = LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT,
  284. cChars * 2)) == NULL )
  285. {
  286. break;
  287. }
  288. //
  289. // Convert MBCS to Unicode. because DDE packet contains MBCS string any time
  290. // for downlevel connectivity, But if we are compiled with -DUNICODE flag,
  291. // EditControl can only handled Unicode, just convert it.
  292. //
  293. MultiByteToWideChar(CP_ACP,0,
  294. lpStrBuf,cChars,
  295. lpStrUnicode,cChars * sizeof(WCHAR)
  296. );
  297. // Set string to EditControl.
  298. SendMessage(hwndRcv,EM_REPLACESEL,0,(LPARAM)lpStrUnicode);
  299. LocalFree(lpStrUnicode);
  300. }
  301. #else // !UNICODE
  302. wParam = SET_EM_SETSEL_WPARAM(LOWORD(ChatDataRcv.uval.cd_dbcs.SelPos),HIWORD(ChatDataRcv.uval.cd_dbcs.SelPos));
  303. lParam = SET_EM_SETSEL_LPARAM(LOWORD(ChatDataRcv.uval.cd_dbcs.SelPos),HIWORD(ChatDataRcv.uval.cd_dbcs.SelPos));
  304. SendMessage(hwndRcv,EM_SETSEL,wParam,lParam);
  305. SendMessage(hwndRcv,EM_REPLACESEL,0,(LPARAM)lpStrBuf);
  306. #endif // UNICODE
  307. SendMessage(hwndRcv,EM_SETREADONLY,(WPARAM)TRUE,0L);
  308. hRet = (HDDEDATA)TRUE;
  309. }
  310. GlobalUnlock(hStrBuf);
  311. }
  312. GlobalFree(hStrBuf);
  313. }
  314. }
  315. break;
  316. // This is a Unicode conversation, so mark the flag.
  317. //
  318. case CHT_UNICODE:
  319. ChatState.fUnicode = TRUE;
  320. hRet = (HDDEDATA)TRUE;
  321. break;
  322. // We got a character...stuff it into the control.
  323. //
  324. case CHT_CHAR:
  325. // In case user is tracking, so WM_CHAR is not tossed (thanks Dave)
  326. //
  327. SendMessage(hwndRcv,WM_LBUTTONUP,0,0L);
  328. SendMessage(hwndRcv,EM_SETREADONLY,(WPARAM)FALSE,0L);
  329. if (gfDbcsEnabled) {
  330. TranslateMultiBytePosToWideCharPos( hwndRcv,
  331. (DWORD)HIWORD(ChatDataRcv.uval.cd_dbcs.SelPos),
  332. (DWORD)LOWORD(ChatDataRcv.uval.cd_dbcs.SelPos),
  333. &dwTemp1, &dwTemp2 );
  334. // sign extend them
  335. wParam=(WPARAM)(INT_PTR)dwTemp1;
  336. lParam=(LPARAM)(INT_PTR)dwTemp2;
  337. } else {
  338. wParam = SET_EM_SETSEL_WPARAM(LOWORD(ChatDataRcv.uval.cd_char.SelPos),HIWORD(ChatDataRcv.uval.cd_char.SelPos));
  339. lParam = SET_EM_SETSEL_LPARAM(LOWORD(ChatDataRcv.uval.cd_char.SelPos),HIWORD(ChatDataRcv.uval.cd_char.SelPos));
  340. }
  341. SendMessage(hwndRcv,EM_SETSEL,wParam,lParam);
  342. SendMessage(hwndRcv,WM_CHAR,ChatDataRcv.uval.cd_char.Char,0L);
  343. SendMessage(hwndRcv,EM_SETREADONLY,TRUE,0L);
  344. hRet = (HDDEDATA)TRUE;
  345. break;
  346. // We have a paste selection.
  347. //
  348. case CHT_PASTEA:
  349. case CHT_PASTEW:
  350. {
  351. HANDLE hPasteBuf,hAnsiBuf;
  352. LPSTR lpPasteBuf,lpAnsiBuf;
  353. DWORD BufSize;
  354. BufSize = (ChatDataRcv.type == CHT_PASTEA ? ((ChatDataRcv.uval.cd_paste.size + 1) * sizeof(TCHAR)) : (ChatDataRcv.uval.cd_paste.size + sizeof(WCHAR)));
  355. hPasteBuf = GlobalAlloc(GMEM_FIXED,BufSize);
  356. if(hPasteBuf)
  357. {
  358. lpPasteBuf = GlobalLock(hPasteBuf);
  359. if(lpPasteBuf)
  360. {
  361. if(ChatDataRcv.type == CHT_PASTEA)
  362. {
  363. hAnsiBuf = GlobalAlloc(GMEM_FIXED,ChatDataRcv.uval.cd_paste.size+sizeof(WCHAR));
  364. if(hAnsiBuf)
  365. {
  366. lpAnsiBuf = GlobalLock(hAnsiBuf);
  367. if(lpAnsiBuf)
  368. {
  369. DdeGetData(hData,(BYTE *)lpAnsiBuf,ChatDataRcv.uval.cd_paste.size+sizeof(WCHAR),XCHATSIZEA);
  370. MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,lpAnsiBuf,ChatDataRcv.uval.cd_paste.size+sizeof(WCHAR),
  371. (LPWSTR)lpPasteBuf,ChatDataRcv.uval.cd_paste.size+1);
  372. GlobalUnlock(hAnsiBuf);
  373. }
  374. GlobalFree(hAnsiBuf);
  375. }
  376. }
  377. else
  378. DdeGetData(hData,(BYTE *)lpPasteBuf,ChatDataRcv.uval.cd_paste.size+sizeof(WCHAR),XCHATSIZEW);
  379. #ifndef DDEMLBUG
  380. if(DdeGetLastError(idInst) == DMLERR_NO_ERROR)
  381. #endif
  382. {
  383. SendMessage(hwndRcv,EM_SETREADONLY,(WPARAM)FALSE,0L);
  384. wParam = SET_EM_SETSEL_WPARAM(LOWORD(ChatDataRcv.uval.cd_char.SelPos),HIWORD(ChatDataRcv.uval.cd_char.SelPos));
  385. lParam = SET_EM_SETSEL_LPARAM(LOWORD(ChatDataRcv.uval.cd_char.SelPos),HIWORD(ChatDataRcv.uval.cd_char.SelPos));
  386. SendMessage(hwndRcv,EM_SETSEL,wParam,lParam);
  387. SendMessage(hwndRcv,EM_REPLACESEL,0,(LPARAM)lpPasteBuf);
  388. SendMessage(hwndRcv,EM_SETREADONLY,(WPARAM)TRUE,0L);
  389. hRet = (HDDEDATA)TRUE;
  390. }
  391. GlobalUnlock(hPasteBuf);
  392. }
  393. GlobalFree(hPasteBuf);
  394. }
  395. }
  396. break;
  397. // We got a font change. Create and stuff.
  398. //
  399. case CHT_FONTA:
  400. case CHT_FONTW:
  401. if(ChatDataRcv.type == CHT_FONTA)
  402. {
  403. CHATDATAA ChatDataA;
  404. memcpy(ChatDataA.uval.cd_win.lf.lfFaceName,ChatDataRcv.uval.cd_win.lf.lfFaceName,LF_XPACKFACESIZE + (sizeof(COLORREF) * 2));
  405. ChatDataRcv.uval.cd_win.cref = ChatDataA.uval.cd_win.cref;
  406. ChatDataRcv.uval.cd_win.brush = ChatDataA.uval.cd_win.brush;
  407. MultiByteToWideChar(CP_OEMCP,MB_PRECOMPOSED,ChatDataA.uval.cd_win.lf.lfFaceName,LF_XPACKFACESIZE,ChatDataRcv.uval.cd_win.lf.lfFaceName,LF_XPACKFACESIZE);
  408. }
  409. UnpackFont(&lfRcv,&ChatDataRcv.uval.cd_win.lf);
  410. hdc = GetDC(hwndApp);
  411. if(hdc)
  412. {
  413. RcvBrushColor = PartBrushColor = GetNearestColor(hdc,ChatDataRcv.uval.cd_win.brush);
  414. RcvColorref = GetNearestColor(hdc,ChatDataRcv.uval.cd_win.cref);
  415. ReleaseDC(hwndApp,hdc);
  416. }
  417. if(!ChatState.fUseOwnFont)
  418. {
  419. if(hEditRcvFont)
  420. DeleteObject(hEditRcvFont);
  421. hEditRcvFont = CreateFontIndirect(&lfRcv);
  422. DeleteObject(hEditRcvBrush);
  423. hEditRcvBrush = CreateSolidBrush(RcvBrushColor);
  424. if(hEditRcvFont)
  425. {
  426. SendMessage(hwndRcv,WM_SETFONT,(WPARAM)hEditRcvFont,1L);
  427. InvalidateRect(hwndRcv,NULL,TRUE);
  428. }
  429. }
  430. hRet = (HDDEDATA)TRUE;
  431. break;
  432. #ifdef PROTOCOL_NEGOTIATE
  433. case CHT_PROTOCOL:
  434. // Determine characteristics we have in common.
  435. //
  436. FlagIntersection(ChatDataRcv.uval.cd_protocol.pckt);
  437. // Return the flavor, if not already done.
  438. //
  439. if(!ChatState.fProtocolSent)
  440. AnnounceSupport();
  441. hRet = (HDDEDATA)TRUE;
  442. break;
  443. #endif
  444. default:
  445. break;
  446. }
  447. }
  448. }
  449. break;
  450. case XTYP_CONNECT:
  451. if(!ChatState.fConnected && !ChatState.fConnectPending && !ChatState.fInProcessOfDialing)
  452. {
  453. // allow connect only on the chat topic.
  454. //
  455. if(!DdeCmpStringHandles(hszTopic,hszChatTopic))
  456. hRet = (HDDEDATA)TRUE;
  457. }
  458. break;
  459. case XTYP_CONNECT_CONFIRM:
  460. ChatState.fConnectPending = TRUE;
  461. ChatState.fAllowAnswer = FALSE;
  462. ChatState.fIsServer = TRUE;
  463. ghConv = hConv;
  464. nConnectAttempt = 0;
  465. UpdateButtonStates();
  466. break;
  467. case XTYP_DISCONNECT:
  468. if(ChatState.fConnectPending || ChatState.fConnected)
  469. {
  470. if(ChatState.fConnected)
  471. wsprintf(szBuf,szHasTerminated,(LPTSTR)szConvPartner);
  472. else
  473. if(ChatState.fServerVerified)
  474. wsprintf(szBuf,szNoConnectionTo,(LPTSTR)szConvPartner);
  475. else
  476. lstrcpy(szBuf,szNoConnect);
  477. SetStatusWindowText(szBuf);
  478. ChatState.fConnectPending = FALSE;
  479. ChatState.fConnected = FALSE;
  480. ChatState.fIsServer = FALSE;
  481. ChatState.fUnicode = FALSE;
  482. #ifdef PROTOCOL_NEGOTIATE
  483. ChatState.fProtocolSent = FALSE;
  484. #endif
  485. // suspend text entry
  486. //
  487. UpdateButtonStates();
  488. SendMessage(hwndSnd,EM_SETREADONLY,TRUE,0L);
  489. SetWindowText(hwndApp,szAppName);
  490. // stop the ringing immediately
  491. //
  492. if(ChatState.fMMSound)
  493. sndPlaySound(NULL,SND_ASYNC);
  494. // cut the animation short
  495. //
  496. if(cAnimate)
  497. cAnimate = 1;
  498. }
  499. break;
  500. case XTYP_REQUEST:
  501. break;
  502. case XTYP_ADVREQ:
  503. if(ChatState.fIsServer && ChatState.fConnected)
  504. {
  505. switch(ChatData.type)
  506. {
  507. case CHT_DBCS_STRING:
  508. hRet = CreateDbcsStringData();
  509. break;
  510. case CHT_CHAR:
  511. case CHT_FONTA:
  512. case CHT_FONTW:
  513. case CHT_UNICODE:
  514. hRet = CreateCharData();
  515. break;
  516. case CHT_PASTEA:
  517. case CHT_PASTEW:
  518. hRet = CreatePasteData();
  519. break;
  520. #ifdef PROTOCOL_NEGOTIATE
  521. case CHT_PROTOCOL:
  522. hRet = CreateProtocolData();
  523. break;
  524. #endif
  525. default:
  526. break;
  527. }
  528. }
  529. break;
  530. case XTYP_ADVSTART:
  531. if(ChatState.fConnectPending)
  532. {
  533. // is this the connect confirm attempt?
  534. //
  535. if(!DdeCmpStringHandles(hszItem,hszConnectTest))
  536. return((HDDEDATA)TRUE);
  537. DdeQueryString(idInst,hszItem,szConvPartner,32L,0);
  538. wsprintf(szBuf,szIsCalling,(LPTSTR)szConvPartner);
  539. SetStatusWindowText(szBuf);
  540. // set window text on initial connect attempt
  541. //
  542. if(nConnectAttempt == 0)
  543. {
  544. wsprintf(szBuf,TEXT("%s - [%s]"),(LPTSTR)szAppName,(LPTSTR)szConvPartner);
  545. SetWindowText(hwndApp,szBuf);
  546. }
  547. if(ChatState.fAllowAnswer)
  548. {
  549. ChatState.fConnected = TRUE;
  550. ChatState.fConnectPending = FALSE;
  551. UpdateButtonStates();
  552. ClearEditControls();
  553. SendMessage(hwndSnd,EM_SETREADONLY,FALSE,0L);
  554. wsprintf(szBuf,szConnectedTo,(LPTSTR)szConvPartner);
  555. SetStatusWindowText(szBuf);
  556. if(hszConvPartner)
  557. DdeFreeStringHandle(idInst,hszConvPartner);
  558. hszConvPartner = DdeCreateStringHandle(idInst,szConvPartner,CP_WINUNICODE);
  559. // Indicate that it is a Unicode conversation.
  560. //
  561. PostMessage(hwndApp,WM_COMMAND,IDX_UNICODECONV,0L);
  562. // SendFontToPartner(); -- would like to do this - won't work
  563. // so we workaround it by posting the app window a message
  564. // to perform this function...
  565. //
  566. PostMessage(hwndApp,WM_COMMAND,IDX_DEFERFONTCHANGE,0L);
  567. #ifdef PROTOCOL_NEGOTIATE
  568. PostMessage(hwndApp,WM_COMMAND,IDX_DEFERPROTOCOL,0L);
  569. #endif
  570. hRet = (HDDEDATA)TRUE;
  571. }
  572. else
  573. if(!(nConnectAttempt++ % 6))
  574. {
  575. // Number of animation cycles == 24: ring remote.
  576. //
  577. cAnimate = 24;
  578. idTimer = SetTimer(hwndApp,(UINT_PTR)1,(UINT_PTR)55,NULL);
  579. FlashWindow(hwndApp,TRUE);
  580. DoRing(szWcRingIn);
  581. }
  582. }
  583. break;
  584. default:
  585. break;
  586. }
  587. return(hRet);
  588. }
  589. /*---------------------------------------------------------------------------*\
  590. | FE specific:
  591. | CREATE DBCS STRING TRANSACTION DATA
  592. | This routine creates a DDE object representing the DBCS string information.
  593. |
  594. | created: 07-Jul-93
  595. |
  596. \*---------------------------------------------------------------------------*/
  597. HDDEDATA CreateDbcsStringData(VOID)
  598. {
  599. HDDEDATA hTmp = (HDDEDATA)0;
  600. LPSTR lpDbcsMem;
  601. DWORD cbDbcs;
  602. hTmp = (HDDEDATA)0;
  603. lpDbcsMem = GlobalLock(ChatData.uval.cd_dbcs.hString);
  604. if(lpDbcsMem)
  605. {
  606. cbDbcs = (DWORD)GlobalSize(ChatData.uval.cd_dbcs.hString);
  607. ChatData.uval.cd_dbcs.size = (DWORD)cbDbcs;
  608. hTmp = DdeCreateDataHandle(idInst,NULL,sizeof(ChatData)+cbDbcs,0L,hszTextItem,cf_chatdata,0);
  609. if(hTmp)
  610. {
  611. DdeAddData(hTmp,(LPBYTE)&ChatData,sizeof(ChatData),0L);
  612. DdeAddData(hTmp,(BYTE *)lpDbcsMem,cbDbcs,XCHATSIZEA);
  613. }
  614. GlobalUnlock(ChatData.uval.cd_dbcs.hString);
  615. }
  616. GlobalFree(ChatData.uval.cd_dbcs.hString);
  617. return(hTmp);
  618. }
  619. /*---------------------------------------------------------------------------*\
  620. | CREATE CHARACTER TRANSACTION DATA
  621. | This routine creates a DDE object representing the charater information.
  622. |
  623. | created: 11-Nov-91
  624. | history: 29-Dec-92 <chriswil> ported to NT.
  625. |
  626. \*---------------------------------------------------------------------------*/
  627. HDDEDATA CreateCharData(VOID)
  628. {
  629. HANDLE hData;
  630. LPCHATDATA lpData;
  631. HDDEDATA hTmp;
  632. BOOL fDefCharUsed;
  633. hTmp = (HDDEDATA)0;
  634. hData = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE,sizeof(ChatData));
  635. if(hData)
  636. {
  637. lpData = (LPCHATDATA)GlobalLock(hData);
  638. if(lpData)
  639. {
  640. *lpData = ChatData;
  641. if(ChatData.type == CHT_FONTA)
  642. {
  643. lpData->uval.cd_win.cref = ((LPCHATDATAA)lpData)->uval.cd_win.cref;
  644. lpData->uval.cd_win.brush = ((LPCHATDATAA)lpData)->uval.cd_win.brush;
  645. }
  646. hTmp = DdeCreateDataHandle(idInst,(LPBYTE)lpData,sizeof(ChatData),0L,hszTextItem,cf_chatdata,0);
  647. GlobalUnlock(hData);
  648. }
  649. GlobalFree(hData);
  650. }
  651. return(hTmp);
  652. UNREFERENCED_PARAMETER(fDefCharUsed);
  653. }
  654. /*---------------------------------------------------------------------------*\
  655. | CREATE PASTE TRANSACTION DATA
  656. | This routine creates a DDE object representing the paste information.
  657. |
  658. | created: 11-Nov-91
  659. | history: 29-Dec-92 <chriswil> ported to NT.
  660. |
  661. \*---------------------------------------------------------------------------*/
  662. HDDEDATA CreatePasteData(VOID)
  663. {
  664. HDDEDATA hTmp,hRet;
  665. HANDLE hClipb;
  666. LPTSTR lpClipMem;
  667. DWORD cbClip;
  668. LPSTR lpBuf;
  669. DWORD dwBytes;
  670. hRet = (HDDEDATA)0;
  671. if(OpenClipboard(hwndSnd))
  672. {
  673. hClipb = GetClipboardData(CF_UNICODETEXT);
  674. if(hClipb)
  675. {
  676. lpClipMem = GlobalLock(hClipb);
  677. if(lpClipMem)
  678. {
  679. cbClip = (DWORD)GlobalSize(hClipb);
  680. ChatData.uval.cd_paste.size = cbClip;
  681. hTmp = DdeCreateDataHandle(idInst,NULL,(sizeof(ChatData)+cbClip),
  682. 0,hszTextItem,cf_chatdata,0);
  683. if(hTmp)
  684. {
  685. DdeAddData(hTmp,(LPBYTE)&ChatData,sizeof(ChatData),0L);
  686. if(ChatData.type == CHT_PASTEA)
  687. {
  688. dwBytes = WideCharToMultiByte(CP_ACP,0,lpClipMem,-1,NULL,0,NULL,NULL);
  689. ChatData.uval.cd_paste.size = dwBytes;
  690. lpBuf = LocalAlloc(LPTR,dwBytes);
  691. if(lpBuf)
  692. {
  693. WideCharToMultiByte(CP_ACP,0,lpClipMem,-1,lpBuf,dwBytes,NULL,NULL);
  694. DdeAddData(hTmp,(LPBYTE)lpBuf,dwBytes,XCHATSIZEA);
  695. hRet = hTmp;
  696. LocalFree(lpBuf);
  697. }
  698. }
  699. else
  700. {
  701. DdeAddData(hTmp,(LPBYTE)lpClipMem,cbClip,XCHATSIZEW);
  702. hRet = hTmp;
  703. }
  704. }
  705. GlobalUnlock(hClipb);
  706. }
  707. }
  708. CloseClipboard();
  709. }
  710. return(hRet);
  711. }
  712. #ifdef PROTOCOL_NEGOTIATE
  713. /*---------------------------------------------------------------------------*\
  714. | CREATE PROTOCOL TRANSACTION DATA
  715. | This routine creates a DDE object representing the protocol information.
  716. |
  717. | created: 11-Nov-91
  718. | history: 07-Apr-93 <chriswil> ported to NT.
  719. |
  720. \*---------------------------------------------------------------------------*/
  721. HDDEDATA CreateProtocolData(VOID)
  722. {
  723. HANDLE hData;
  724. LPCHATDATA lpData;
  725. HDDEDATA hTmp;
  726. hTmp = (HDDEDATA)0;
  727. hData = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE,sizeof(ChatData));
  728. if(hData)
  729. {
  730. lpData = (LPCHATDATA)GlobalLock(hData);
  731. if(lpData)
  732. {
  733. ChatData.type = CHT_PROTOCOL;
  734. ChatData.uval.cd_protocol.dwVer = CHT_VER;
  735. ChatData.uval.cd_protocol.pckt = GetCurrentPckt();
  736. *lpData = ChatData;
  737. hTmp = DdeCreateDataHandle(idInst,(LPBYTE)lpData,sizeof(ChatData),0L,hszTextItem,cf_chatdata,0);
  738. GlobalUnlock(hData);
  739. }
  740. GlobalFree(hData);
  741. }
  742. return(hTmp);
  743. }
  744. #endif
  745. #ifdef PROTOCOL_NEGOTIATE
  746. /*---------------------------------------------------------------------------*\
  747. | GET CURRENT PACKET
  748. | This routine returns the current packet capabilities of the system.
  749. |
  750. | created: 11-Nov-91
  751. | history: 07-Apr-93 <chriswil> ported to NT.
  752. |
  753. \*---------------------------------------------------------------------------*/
  754. PCKT GetCurrentPckt(VOID)
  755. {
  756. PCKT pckt;
  757. pckt = PCKT_TEXT;
  758. return(pckt);
  759. }
  760. #endif
  761. #ifdef PROTOCOL_NEGOTIATE
  762. /*---------------------------------------------------------------------------*\
  763. | FLAG INTERSECTION
  764. | This routine determines which packet types are supporte and flags the
  765. | appropriate ones.
  766. |
  767. | created: 11-Nov-91
  768. | history: 07-Apr-93 <chriswil> ported to NT.
  769. |
  770. \*---------------------------------------------------------------------------*/
  771. VOID FlagIntersection(PCKT pcktPartner)
  772. {
  773. PCKT pcktNet;
  774. pcktNet = GetCurrentPckt() & pcktPartner;
  775. return;
  776. }
  777. #endif
  778. /*---------------------------------------------------------------------------*\
  779. | SEND FONT TO PARTNER
  780. | This routine sends the font-information to the partner in this
  781. | conversation.
  782. |
  783. | created: 11-Nov-91
  784. | history: 29-Dec-92 <chriswil> ported to NT.
  785. |
  786. \*---------------------------------------------------------------------------*/
  787. VOID SendFontToPartner(VOID)
  788. {
  789. HDDEDATA hDdeData;
  790. PCHATDATAA pAChat;
  791. ChatData.type = (WORD)((ChatState.fUnicode ? CHT_FONTW : CHT_FONTA));
  792. PackFont(&ChatData.uval.cd_win.lf,&lfSnd);
  793. if(ChatData.type == CHT_FONTA)
  794. {
  795. pAChat = (PCHATDATAA)&ChatData;
  796. pAChat->uval.cd_win.cref = SndColorref;
  797. pAChat->uval.cd_win.brush = SndBrushColor;
  798. }
  799. else
  800. {
  801. ChatData.uval.cd_win.cref = SndColorref;
  802. ChatData.uval.cd_win.brush = SndBrushColor;
  803. }
  804. if(!ChatState.fIsServer)
  805. {
  806. hDdeData = DdeCreateDataHandle(idInst,(LPBYTE) &ChatData,sizeof(ChatData),0L,hszTextItem,cf_chatdata,0);
  807. if(hDdeData)
  808. DdeClientTransaction((LPBYTE)hDdeData,(DWORD)-1,ghConv,hszTextItem,cf_chatdata,XTYP_POKE,(DWORD)TIMEOUT_ASYNC,(LPDWORD)&StrXactID);
  809. }
  810. else
  811. DdePostAdvise(idInst,hszChatTopic,hszConvPartner);
  812. return;
  813. }
  814. /*---------------------------------------------------------------------------*\
  815. | UNPACK FONT
  816. | This routine unpacks the font stored in the packed transaction.
  817. |
  818. | created: 04-Feb-93
  819. | history: 04-Feb-93 <chriswil> created.
  820. |
  821. \*---------------------------------------------------------------------------*/
  822. VOID UnpackFont(LPLOGFONT lf, LPXPACKFONT lfPacked)
  823. {
  824. lf->lfHeight = (LONG)(short)lfPacked->lfHeight;
  825. lf->lfWidth = (LONG)(short)lfPacked->lfWidth;
  826. lf->lfEscapement = (LONG)(short)lfPacked->lfEscapement;
  827. lf->lfOrientation = (LONG)(short)lfPacked->lfOrientation;
  828. lf->lfWeight = (LONG)(short)lfPacked->lfWeight;
  829. lf->lfItalic = (BYTE)lfPacked->lfItalic;
  830. lf->lfUnderline = (BYTE)lfPacked->lfUnderline;
  831. lf->lfStrikeOut = (BYTE)lfPacked->lfStrikeOut;
  832. lf->lfCharSet = (BYTE)lfPacked->lfCharSet;
  833. lf->lfOutPrecision = (BYTE)lfPacked->lfOutPrecision;
  834. lf->lfClipPrecision = (BYTE)lfPacked->lfClipPrecision;
  835. lf->lfQuality = (BYTE)lfPacked->lfQuality;
  836. lf->lfPitchAndFamily = (BYTE)lfPacked->lfPitchAndFamily;
  837. lstrcpy(lf->lfFaceName,lfPacked->lfFaceName);
  838. return;
  839. }
  840. /*---------------------------------------------------------------------------*\
  841. | PACK FONT
  842. | This routine packs the font for transaction.
  843. |
  844. | created: 04-Feb-93
  845. | history: 04-Feb-93 <chriswil> created.
  846. |
  847. \*---------------------------------------------------------------------------*/
  848. VOID PackFont(LPXPACKFONT lfPacked, LPLOGFONT lf)
  849. {
  850. BOOL fDefCharUsed;
  851. lfPacked->lfHeight = (WORD)lf->lfHeight;
  852. lfPacked->lfWidth = (WORD)lf->lfWidth;
  853. lfPacked->lfEscapement = (WORD)lf->lfEscapement;
  854. lfPacked->lfOrientation = (WORD)lf->lfOrientation;
  855. lfPacked->lfWeight = (WORD)lf->lfWeight;
  856. lfPacked->lfItalic = (BYTE)lf->lfItalic;
  857. lfPacked->lfUnderline = (BYTE)lf->lfUnderline;
  858. lfPacked->lfStrikeOut = (BYTE)lf->lfStrikeOut;
  859. lfPacked->lfCharSet = (BYTE)lf->lfCharSet;
  860. lfPacked->lfOutPrecision = (BYTE)lf->lfOutPrecision;
  861. lfPacked->lfClipPrecision = (BYTE)lf->lfClipPrecision;
  862. lfPacked->lfQuality = (BYTE)lf->lfQuality;
  863. lfPacked->lfPitchAndFamily = (BYTE)lf->lfPitchAndFamily;
  864. if(ChatData.type == CHT_FONTA)
  865. WideCharToMultiByte(CP_OEMCP,0,lf->lfFaceName,LF_XPACKFACESIZE,(LPSTR)(lfPacked->lfFaceName),LF_XPACKFACESIZE,NULL,&fDefCharUsed);
  866. else
  867. lstrcpy(lfPacked->lfFaceName,lf->lfFaceName);
  868. return;
  869. }