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.

2328 lines
67 KiB

  1. /*---------------------------------------------------------------------------*\
  2. | WINCHAT APPLICATION MODULE
  3. | This is the main module file for the application. The application was
  4. | originally written by ClausGi for the Windows-For-WorkGroup product.
  5. | In the port to NT, all references to PEN-awareness and Protocol were
  6. | removed. Extensive cleanup and documenting was also added in the port.
  7. |
  8. | FUNCTIONS
  9. | ---------
  10. | myatol
  11. | UpdateButtonStates
  12. | appGetComputerName
  13. | AdjustEditWindows
  14. |
  15. |
  16. | Copyright (c) Microsoft Corp., 1990-1993
  17. |
  18. | created: 01-Nov-91
  19. | history: 01-Nov-91 <clausgi> created.
  20. | 29-Dec-92 <chriswil> port to NT, cleanup.
  21. | 19-Oct-93 <chriswil> unicode enhancements from a-dianeo.
  22. |
  23. \*---------------------------------------------------------------------------*/
  24. #include <windows.h>
  25. #include <mmsystem.h>
  26. #include <stdio.h>
  27. #include <ddeml.h>
  28. #include <commdlg.h>
  29. #include <commctrl.h>
  30. #include <shellapi.h>
  31. #include <nddeapi.h>
  32. #include <richedit.h>
  33. #include "winchat.h"
  34. #include "dialogs.h"
  35. #include "globals.h"
  36. #include "nddeagnt.h"
  37. #include <tchar.h>
  38. #include <imm.h>
  39. #include <htmlhelp.h>
  40. #define ASSERT(x)
  41. // This is used in the port to NT. Since NT doesn't haven a dialogbox for
  42. // this function, we'll use the lanman export.
  43. //
  44. #ifdef WIN32
  45. #define FOCUSDLG_DOMAINS_ONLY (1)
  46. #define FOCUSDLG_SERVERS_ONLY (2)
  47. #define FOCUSDLG_SERVERS_AND_DOMAINS (3)
  48. #define FOCUSDLG_BROWSE_LOGON_DOMAIN 0x00010000
  49. #define FOCUSDLG_BROWSE_WKSTA_DOMAIN 0x00020000
  50. #define FOCUSDLG_BROWSE_OTHER_DOMAINS 0x00040000
  51. #define FOCUSDLG_BROWSE_TRUSTING_DOMAINS 0x00080000
  52. #define FOCUSDLG_BROWSE_WORKGROUP_DOMAINS 0x00100000
  53. #define FOCUSDLG_BROWSE_LM2X_DOMAINS (FOCUSDLG_BROWSE_LOGON_DOMAIN | FOCUSDLG_BROWSE_WKSTA_DOMAIN | FOCUSDLG_BROWSE_OTHER_DOMAINS)
  54. #define FOCUSDLG_BROWSE_ALL_DOMAINS (FOCUSDLG_BROWSE_LOCAL_DOMAINS | FOCUSDLG_BROWSE_WORKGROUP_DOMAINS)
  55. #define FOCUSDLG_BROWSE_LOCAL_DOMAINS (FOCUSDLG_BROWSE_LM2X_DOMAINS | FOCUSDLG_BROWSE_TRUSTING_DOMAINS)
  56. #define MY_LOGONTYPE (FOCUSDLG_BROWSE_ALL_DOMAINS | FOCUSDLG_SERVERS_ONLY)
  57. UINT APIENTRY I_SystemFocusDialog(HWND,UINT,LPWSTR,UINT,PBOOL,LPWSTR,DWORD);
  58. #endif
  59. BOOL TranslateWideCharPosToMultiBytePos(HWND,DWORD,DWORD,LPDWORD,LPDWORD);
  60. /*---------------------------------------------------------------------------*\
  61. | WINDOWS MAIN
  62. | This is the main event-processing loop for the application.
  63. |
  64. | created: 11-Nov-91
  65. | history: 29-Dec-92 <chriswil> ported to NT.
  66. |
  67. \*---------------------------------------------------------------------------*/
  68. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  69. {
  70. MSG msg;
  71. msg.wParam = 0;
  72. if(InitApplication(hInstance))
  73. {
  74. if(InitInstance(hInstance,nCmdShow))
  75. {
  76. while(GetMessage(&msg,NULL,0,0))
  77. {
  78. if(!TranslateAccelerator(hwndApp,hAccel,&msg))
  79. {
  80. TranslateMessage(&msg);
  81. DispatchMessage(&msg);
  82. }
  83. }
  84. if(hszConvPartner)
  85. DdeFreeStringHandle(idInst,hszConvPartner);
  86. DdeFreeStringHandle(idInst,hszChatTopic);
  87. DdeFreeStringHandle(idInst,hszChatShare);
  88. DdeFreeStringHandle(idInst,hszLocalName );
  89. DdeFreeStringHandle(idInst,hszTextItem);
  90. DdeFreeStringHandle(idInst,hszConnectTest);
  91. DdeUninitialize(idInst);
  92. EndIniMapping();
  93. }
  94. }
  95. return((int)msg.wParam);
  96. }
  97. #ifdef WIN16
  98. #pragma alloc_text ( _INIT, InitApplication )
  99. #endif
  100. /*---------------------------------------------------------------------------*\
  101. | INITIALIZE APPLICATION
  102. | This routine registers the application with user.
  103. |
  104. | created: 11-Nov-91
  105. | history: 29-Dec-92 <chriswil> ported to NT.
  106. |
  107. \*---------------------------------------------------------------------------*/
  108. BOOL FAR InitApplication(HINSTANCE hInstance)
  109. {
  110. WNDCLASS wc;
  111. wc.style = 0;
  112. wc.lpfnWndProc = MainWndProc;
  113. wc.cbClsExtra = 0;
  114. wc.cbWndExtra = 0;
  115. wc.hInstance = hInstance;
  116. wc.hIcon = LoadIcon(hInstance, TEXT("PHONE1"));
  117. wc.hCursor = LoadCursor(NULL,IDC_ARROW);
  118. wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
  119. wc.lpszMenuName = szWinChatMenu;
  120. wc.lpszClassName = szWinChatClass;
  121. return(RegisterClass(&wc));
  122. }
  123. #define IMMMODULENAME L"IMM32.DLL"
  124. #define PATHDLM L'\\'
  125. #define IMMMODULENAMELEN ((sizeof PATHDLM + sizeof IMMMODULENAME) / sizeof(WCHAR))
  126. VOID GetImmFileName(PWSTR wszImmFile)
  127. {
  128. UINT i = GetSystemDirectoryW(wszImmFile, MAX_PATH);
  129. if (i > 0 && i < MAX_PATH - IMMMODULENAMELEN) {
  130. wszImmFile += i;
  131. if (wszImmFile[-1] != PATHDLM) {
  132. *wszImmFile++ = PATHDLM;
  133. }
  134. }
  135. wcscpy(wszImmFile, IMMMODULENAME);
  136. }
  137. /*---------------------------------------------------------------------------*\
  138. | IsTSRemoteSession
  139. |
  140. | Input: None
  141. | Output: BOOL - TRUE if in a Terminal Server remote session (SessionId != 0)
  142. | FALSE - if error OR not in a TS rermote session
  143. | Function: To determine whether we are running in a TS remote session or not.
  144. |
  145. \*---------------------------------------------------------------------------*/
  146. BOOL IsTSRemoteSession()
  147. {
  148. BOOL bRetVal;
  149. DWORD dwSessionID;
  150. HINSTANCE hInst;
  151. FARPROC lpfnProcessIdToSessionId;
  152. //assume failure
  153. bRetVal = FALSE;
  154. // load library and get proc address
  155. hInst=LoadLibrary(TEXT("kernel32.dll"));
  156. if (hInst)
  157. {
  158. lpfnProcessIdToSessionId = GetProcAddress(hInst,"ProcessIdToSessionId");
  159. if (lpfnProcessIdToSessionId )
  160. {
  161. if (lpfnProcessIdToSessionId(GetCurrentProcessId(),&dwSessionID))
  162. {
  163. if(dwSessionID!=0)
  164. {
  165. bRetVal = TRUE;
  166. }
  167. }
  168. }
  169. // free the library
  170. FreeLibrary(hInst);
  171. }
  172. return bRetVal;
  173. }
  174. #ifdef WIN16
  175. #pragma alloc_text ( _INIT, InitInstance )
  176. #endif
  177. /*---------------------------------------------------------------------------*\
  178. | INITIALIZE APPLICATION INTSTANCE
  179. | This routine initializes instance information.
  180. |
  181. | created: 11-Nov-91
  182. | history: 29-Dec-92 <chriswil> ported to NT.
  183. |
  184. \*---------------------------------------------------------------------------*/
  185. BOOL FAR InitInstance(HINSTANCE hInstance, int nCmdShow)
  186. {
  187. HWND hwnd;
  188. HMENU hMenu;
  189. HINSTANCE hmodNetDriver;
  190. int cAppQueue;
  191. BOOL bRet;
  192. hInst = hInstance;
  193. //
  194. // get DBCS flag
  195. //
  196. gfDbcsEnabled = GetSystemMetrics(SM_DBCSENABLED);
  197. if (GetSystemMetrics(SM_IMMENABLED)) {
  198. //
  199. // if IME is enabled, get real API addresses
  200. //
  201. WCHAR wszImmFile[MAX_PATH];
  202. HINSTANCE hInstImm32;
  203. GetImmFileName(wszImmFile);
  204. hInstImm32 = GetModuleHandle(wszImmFile);
  205. if (hInstImm32) {
  206. pfnImmGetContext = (PVOID)GetProcAddress(hInstImm32, "ImmGetContext");
  207. ASSERT(pfnImmGetContext);
  208. pfnImmReleaseContext = (PVOID)GetProcAddress(hInstImm32, "ImmReleaseContext");
  209. ASSERT(pfnImmReleaseContext);
  210. pfnImmGetCompositionStringW = (PVOID)GetProcAddress(hInstImm32, "ImmGetCompositionStringW");
  211. ASSERT(pfnImmGetCompositionStringW);
  212. }
  213. }
  214. // increase our app queue for better performance...
  215. //
  216. for(cAppQueue=128; !SETMESSAGEQUEUE(cAppQueue); cAppQueue >>= 1);
  217. //
  218. //
  219. bRet = FALSE;
  220. if(cAppQueue >= 8)
  221. {
  222. bRet = TRUE;
  223. cxIcon = GetSystemMetrics(SM_CXICON);
  224. cyIcon = GetSystemMetrics(SM_CYICON);
  225. hAccel = LoadAccelerators(hInstance,MAKEINTRESOURCE(IDACCELERATORS));
  226. LoadIntlStrings();
  227. StartIniMapping();
  228. InitFontFromIni();
  229. // check if it's a Terminal Server remote session
  230. if (IsTSRemoteSession())
  231. {
  232. TCHAR szTSNotSupported[SZBUFSIZ];
  233. LoadString(hInst, IDS_TSNOTSUPPORTED, szTSNotSupported, SZBUFSIZ);
  234. MessageBeep(MB_ICONSTOP);
  235. MessageBox(NULL, szTSNotSupported, szAppName, MB_OK | MB_ICONSTOP);
  236. return(FALSE);
  237. }
  238. // get our machine name and map to correct character set.
  239. //
  240. if(!appGetComputerName(szLocalName))
  241. {
  242. MessageBeep(MB_ICONSTOP);
  243. MessageBox(NULL,szSysErr,szAppName,MB_OK | MB_ICONSTOP);
  244. return(FALSE);
  245. }
  246. // initialize DDEML.
  247. //
  248. if(DdeInitialize(&idInst,(PFNCALLBACK)MakeProcInstance((FARPROC)DdeCallback,hInst),APPCLASS_STANDARD,0L))
  249. {
  250. MessageBeep(MB_ICONSTOP);
  251. MessageBox(NULL,szSysErr,szAppName,MB_OK | MB_ICONSTOP);
  252. return(FALSE);
  253. }
  254. ChatState.fMinimized = (nCmdShow == SW_MINIMIZE) ? TRUE : FALSE;
  255. ChatState.fMMSound = waveOutGetNumDevs();
  256. ChatState.fSound = GetPrivateProfileInt(szPref,szSnd ,1,szIni);
  257. ChatState.fToolBar = GetPrivateProfileInt(szPref,szTool ,1,szIni);
  258. ChatState.fStatusBar = GetPrivateProfileInt(szPref,szStat ,1,szIni);
  259. ChatState.fTopMost = GetPrivateProfileInt(szPref,szTop ,0,szIni);
  260. ChatState.fSideBySide = GetPrivateProfileInt(szPref,szSbS ,0,szIni);
  261. ChatState.fUseOwnFont = GetPrivateProfileInt(szPref,szUseOF,0,szIni);
  262. hszLocalName = DdeCreateStringHandle(idInst,szLocalName ,0);
  263. hszChatTopic = DdeCreateStringHandle(idInst,szChatTopic ,0);
  264. hszChatShare = DdeCreateStringHandle(idInst,szChatShare ,0);
  265. hszServiceName = DdeCreateStringHandle(idInst,szServiceName,0);
  266. hszConnectTest = DdeCreateStringHandle(idInst,szConnectTest,0);
  267. hszTextItem = DdeCreateStringHandle(idInst,szChatText ,0);
  268. if(!hszLocalName || !hszChatTopic || !hszServiceName || !hszTextItem || !hszChatShare)
  269. {
  270. MessageBeep(MB_ICONSTOP);
  271. MessageBox(NULL,szSysErr,szAppName,MB_OK | MB_ICONSTOP);
  272. return(FALSE);
  273. }
  274. DdeNameService(idInst,hszServiceName,(HSZ)0,DNS_REGISTER);
  275. if(DdeGetLastError(idInst) != DMLERR_NO_ERROR)
  276. {
  277. MessageBeep(MB_ICONSTOP);
  278. MessageBox (NULL,szSysErr,szAppName,MB_OK | MB_ICONSTOP);
  279. return(FALSE);
  280. }
  281. cf_chatdata = RegisterClipboardFormat(TEXT("Chat Data"));
  282. if(!(cf_chatdata))
  283. {
  284. MessageBeep(MB_ICONSTOP);
  285. MessageBox(NULL,szSysErr,szAppName,MB_OK | MB_ICONSTOP);
  286. return(FALSE);
  287. }
  288. // get winnet extension browse dialog entry point
  289. //
  290. WNetServerBrowseDialog = NULL;
  291. hmodNetDriver = WNETGETCAPS(0xFFFF);
  292. if(hmodNetDriver != NULL)
  293. WNetServerBrowseDialog = (WNETCALL)GetProcAddress(hmodNetDriver,(LPSTR)146);
  294. // create main window
  295. hwnd = CreateWindow(
  296. szWinChatClass,
  297. szAppName,
  298. WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  299. CW_USEDEFAULT,
  300. CW_USEDEFAULT,
  301. CW_USEDEFAULT,
  302. CW_USEDEFAULT,
  303. NULL,
  304. NULL,
  305. hInstance,
  306. NULL
  307. );
  308. if(!hwnd)
  309. {
  310. MessageBeep(MB_ICONSTOP);
  311. MessageBox(NULL,szSysErr,szAppName,MB_OK | MB_ICONSTOP);
  312. return(FALSE);
  313. }
  314. hwndApp = hwnd; // save global
  315. // font choice struct init
  316. //
  317. chf.lStructSize = sizeof(CHOOSEFONT);
  318. chf.lpLogFont = &lfSnd;
  319. chf.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_INITTOLOGFONTSTRUCT;
  320. chf.rgbColors = GetSysColor(COLOR_WINDOWTEXT);
  321. chf.lCustData = 0L;
  322. chf.lpfnHook = NULL;
  323. chf.lpTemplateName = NULL;
  324. chf.hInstance = NULL;
  325. chf.lpszStyle = NULL;
  326. chf.nFontType = SCREEN_FONTTYPE;
  327. chf.nSizeMin = 0;
  328. chf.nSizeMax = 0;
  329. // color choice init
  330. //
  331. chc.lStructSize = sizeof(CHOOSECOLOR);
  332. chc.hwndOwner = hwndApp;
  333. chc.hInstance = hInst;
  334. chc.lpCustColors = (LPDWORD)CustColors;
  335. chc.Flags = CC_RGBINIT | CC_PREVENTFULLOPEN;
  336. chc.lCustData = 0;
  337. chc.lpfnHook = NULL;
  338. chc.lpTemplateName = NULL;
  339. // window placement...
  340. //
  341. if(ReadWindowPlacement(&Wpl))
  342. {
  343. // override these - CODEWORK don't need to save
  344. // them to .ini, but will mis-parse old .ini files
  345. // if change is made.
  346. //
  347. Wpl.showCmd = nCmdShow;
  348. Wpl.ptMaxPosition.x = -1;
  349. Wpl.ptMaxPosition.y = -1;
  350. Wpl.flags = 0;
  351. SetWindowPlacement(hwnd,&Wpl);
  352. UpdateWindow(hwnd);
  353. }
  354. else
  355. ShowWindow(hwnd,nCmdShow);
  356. //
  357. //
  358. hMenu = GetSystemMenu(hwnd,FALSE);
  359. AppendMenu(hMenu,MF_SEPARATOR,0,NULL);
  360. if(ChatState.fTopMost)
  361. AppendMenu(hMenu,MF_ENABLED | MF_CHECKED | MF_STRING,IDM_TOPMOST,szAlwaysOnTop);
  362. else
  363. AppendMenu(hMenu,MF_ENABLED | MF_UNCHECKED | MF_STRING,IDM_TOPMOST,szAlwaysOnTop);
  364. // Set topmost style...
  365. //
  366. SetWindowPos(hwndApp,ChatState.fTopMost ? HWND_TOPMOST : HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  367. UpdateButtonStates();
  368. #if !defined(_WIN64)
  369. {
  370. static NDDESHAREINFO nddeShareInfo = {
  371. 1, // revision
  372. szChatShare,
  373. SHARE_TYPE_STATIC,
  374. TEXT("WinChat|Chat\0\0"),
  375. TRUE, // shared
  376. FALSE, // not a service
  377. TRUE, // can be started
  378. SW_SHOWNORMAL,
  379. {0,0}, // mod id
  380. 0, // no item list
  381. TEXT("")
  382. };
  383. TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 3] = TEXT("\\\\");
  384. DWORD cbName = MAX_COMPUTERNAME_LENGTH + 1;
  385. //
  386. // Make sure NetDDE DSDM has trusted shares set up properly for us.
  387. // This fix allows us to work with floating profiles.
  388. //
  389. START_NETDDE_SERVICES(hwnd);
  390. GetComputerName(&szComputerName[2],&cbName);
  391. NDdeShareAdd(szComputerName,2,NULL,(LPBYTE)&nddeShareInfo,sizeof(NDDESHAREINFO));
  392. NDdeSetTrustedShare(szComputerName, szChatShare,
  393. NDDE_TRUST_SHARE_START | NDDE_TRUST_SHARE_INIT);
  394. }
  395. #endif
  396. }
  397. return(bRet);
  398. }
  399. /*---------------------------------------------------------------------------*\
  400. | MAIN WINDOW PROC
  401. | This is the main event-handler for the application.
  402. |
  403. | created: 11-Nov-91
  404. | history: 29-Dec-92 <chriswil> ported to NT.
  405. |
  406. \*---------------------------------------------------------------------------*/
  407. LRESULT CALLBACK MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  408. {
  409. LRESULT lResult;
  410. lResult = 0l;
  411. switch(message)
  412. {
  413. case WM_CREATE:
  414. appWMCreateProc(hwnd);
  415. break;
  416. case WM_WININICHANGE:
  417. appWMWinIniChangeProc(hwnd);
  418. break;
  419. case WM_ERASEBKGND:
  420. if((lResult = (LRESULT)appWMEraseBkGndProc(hwnd)) == 0)
  421. lResult = DefWindowProc(hwnd,message,wParam,lParam);
  422. break;
  423. case WM_SETFOCUS:
  424. appWMSetFocusProc(hwnd);
  425. break;
  426. case WM_MENUSELECT:
  427. appWMMenuSelectProc(hwnd,wParam,lParam);
  428. break;
  429. case WM_TIMER:
  430. appWMTimerProc(hwnd);
  431. break;
  432. case WM_PAINT:
  433. appWMPaintProc(hwnd);
  434. break;
  435. case WM_QUERYDRAGICON:
  436. lResult = (LRESULT)(LPVOID)appWMQueryDragIconProc(hwnd);
  437. break;
  438. case WM_SIZE:
  439. appWMSizeProc(hwnd,wParam,lParam);
  440. break;
  441. case WM_INITMENU:
  442. appWMInitMenuProc((HMENU)wParam);
  443. break;
  444. case WM_SYSCOMMAND:
  445. if(!appWMSysCommandProc(hwnd,wParam,lParam))
  446. lResult = DefWindowProc(hwnd,message,wParam,lParam);
  447. break;
  448. case WM_COMMAND:
  449. if(!appWMCommandProc(hwnd,wParam,lParam))
  450. lResult = DefWindowProc(hwnd,message,wParam,lParam);
  451. break;
  452. case WM_NOTIFY:
  453. {
  454. LPTOOLTIPTEXT lpTTT = (LPTOOLTIPTEXT) lParam;
  455. if (lpTTT->hdr.code == TTN_NEEDTEXT) {
  456. LoadString (hInst, (UINT)(MH_BASE + lpTTT->hdr.idFrom), lpTTT->szText, 80);
  457. return TRUE;
  458. }
  459. }
  460. break;
  461. #ifdef WIN32
  462. case WM_CTLCOLOREDIT:
  463. case WM_CTLCOLORSTATIC:
  464. #else
  465. case WM_CTLCOLOR:
  466. #endif
  467. if((lResult = (LRESULT)(LPVOID)appWMCtlColorProc(hwnd,wParam,lParam)) == 0l)
  468. lResult = DefWindowProc(hwnd,message,wParam,lParam);
  469. break;
  470. case WM_DESTROY:
  471. appWMDestroyProc(hwnd);
  472. break;
  473. case WM_CLOSE:
  474. WinHelp(hwnd,(LPTSTR)szHelpFile,HELP_QUIT,0L);
  475. // Fall through for final close.
  476. //
  477. default:
  478. lResult = DefWindowProc(hwnd,message,wParam,lParam);
  479. break;
  480. }
  481. return(lResult);
  482. }
  483. /*---------------------------------------------------------------------------*\
  484. | EDIT-HOOK PROCEDURE
  485. | This is the main event-handler for the edit-control hook.
  486. |
  487. | created: 11-Nov-91
  488. | history: 29-Dec-92 <chriswil> ported to NT.
  489. |
  490. \*---------------------------------------------------------------------------*/
  491. LRESULT CALLBACK EditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  492. {
  493. WPARAM wSet;
  494. LPARAM lSet;
  495. GETTEXTLENGTHEX gettextlengthex;
  496. LRESULT lResult;
  497. LPTSTR lpszText;
  498. HANDLE hText;
  499. INT count;
  500. LPTSTR lpszStartSel;
  501. DWORD dwTemp1;
  502. DWORD dwTemp2;
  503. switch(msg) {
  504. case WM_IME_COMPOSITION:
  505. {
  506. LPWSTR lpStrParam;
  507. LPSTR lpStrTmp;
  508. HANDLE hTmp;
  509. if (lParam & GCS_RESULTSTR)
  510. {
  511. HIMC hImc;
  512. ULONG cCharsMbcs, cChars;
  513. //
  514. // Get input context of hwnd
  515. //
  516. if ((hImc = pfnImmGetContext(hwnd)) == 0)
  517. break;
  518. //
  519. //ImmGetComposition returns the size of buffer needed in byte
  520. //
  521. cCharsMbcs = pfnImmGetCompositionStringW(hImc,GCS_RESULTSTR, NULL , 0);
  522. if(!(cCharsMbcs))
  523. {
  524. pfnImmReleaseContext(hwnd, hImc);
  525. break;
  526. }
  527. lpStrParam = (LPWSTR)GlobalAlloc(GPTR,//HEAP_ZERO_MEMORY,
  528. cCharsMbcs + sizeof(WCHAR));
  529. if (lpStrParam==NULL)
  530. {
  531. pfnImmReleaseContext(hwnd, hImc);
  532. break;
  533. }
  534. pfnImmGetCompositionStringW(hImc, GCS_RESULTSTR, lpStrParam,
  535. cCharsMbcs);
  536. //
  537. // Compute character count including NULL char.
  538. //
  539. cChars = wcslen(lpStrParam) + 1;
  540. //
  541. // Set ChatData packet
  542. //
  543. ChatData.type = CHT_DBCS_STRING;
  544. //
  545. // Get current cursor position
  546. //
  547. // !!! BUG BUG BUG !!!
  548. //
  549. // This position data is only nice for Unicode Edit control.
  550. // is the partner has not Unicode Edit control. the string
  551. // will be truncated.
  552. //
  553. SendMessage(hwndSnd,EM_GETSEL,(WPARAM)&dwTemp1,(LPARAM)&dwTemp2);
  554. ChatData.uval.cd_dbcs.SelPos = MAKELONG((WORD)dwTemp1, (WORD)dwTemp2 );
  555. if (gfDbcsEnabled) {
  556. //
  557. // since text is passed as multi byte character string,
  558. // position fixup is needed if DBCS is enabled
  559. //
  560. DWORD dwStart, dwEnd;
  561. TranslateWideCharPosToMultiBytePos( hwndSnd,
  562. (DWORD)LOWORD(ChatData.uval.cd_dbcs.SelPos),
  563. (DWORD)HIWORD(ChatData.uval.cd_dbcs.SelPos),
  564. &dwStart, &dwEnd );
  565. ChatData.uval.cd_dbcs.SelPos
  566. = MAKELONG((WORD)dwStart, (WORD)dwEnd );
  567. }
  568. //
  569. // Allocate string buffer for DDE.
  570. //
  571. if((hTmp = GlobalAlloc( GMEM_ZEROINIT |
  572. GMEM_MOVEABLE |
  573. GMEM_DDESHARE ,
  574. (DWORD)cCharsMbcs)) == NULL)
  575. {
  576. pfnImmReleaseContext(hwnd, hImc);
  577. GlobalFree(lpStrParam);
  578. break;
  579. }
  580. lpStrTmp = GlobalLock(hTmp);
  581. //
  582. // Store MBCS string into DDE buffer.
  583. //
  584. // In CHT_DBCS_STRING context, we should send mbcs string
  585. // for downlevel connectivity.
  586. //
  587. WideCharToMultiByte(CP_ACP,0,lpStrParam,cChars/* + 1*/,
  588. lpStrTmp ,cCharsMbcs/* + 1*/,
  589. NULL,NULL);
  590. //
  591. // Keep the buffer handle in to DDE message packet.
  592. //
  593. GlobalUnlock(hTmp);
  594. ChatData.uval.cd_dbcs.hString = hTmp;
  595. //
  596. // Now, we have a packet to send server/client, just send it.
  597. //
  598. wSet = SET_EN_NOTIFY_WPARAM(ID_EDITSND,EN_DBCS_STRING,hwnd);
  599. lSet = SET_EN_NOTIFY_LPARAM(ID_EDITSND,EN_DBCS_STRING,hwnd);
  600. SendMessage(hwndApp,WM_COMMAND,wSet,lSet);
  601. //
  602. // if we have still a connection to server/client. repaint text.
  603. //
  604. if(ChatState.fConnected)
  605. SendMessage(hwndSnd,EM_REPLACESEL,0,(LPARAM)lpStrParam);
  606. pfnImmReleaseContext(hwnd, hImc);
  607. GlobalFree(lpStrParam);
  608. return(TRUE);
  609. }
  610. break;
  611. }
  612. #if 0 // FE: obsolete. leave it here only FYI
  613. case WM_IME_REPORT:
  614. {
  615. LPTSTR lpStrParam,lpStrTmp;
  616. HANDLE hTmp;
  617. if(wParam == IR_STRING)
  618. {
  619. if(lpStrParam = GlobalLock((HANDLE)lParam))
  620. {
  621. if(hTmp = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE,(DWORD)(lstrlen(lpStrParam) + 1)))
  622. {
  623. ChatData.type = CHT_DBCS_STRING;
  624. ChatData.uval.cd_dbcs.SelPos = SendMessage(hwndSnd,EM_GETSEL,0,0L);
  625. lpStrTmp = GlobalLock(hTmp);
  626. lstrcpy(lpStrTmp, lpStrParam);
  627. GlobalUnlock(hTmp);
  628. ChatData.uval.cd_dbcs.hString = hTmp;
  629. wSet = SET_EN_NOTIFY_WPARAM(ID_EDITSND,EN_DBCS_STRING,hwnd);
  630. lSet = SET_EN_NOTIFY_LPARAM(ID_EDITSND,EN_DBCS_STRING,hwnd);
  631. SendMessage(hwndApp,WM_COMMAND,wSet,lSet);
  632. if(ChatState.fConnected)
  633. SendMessage(hwndSnd,EM_REPLACESEL,0,(LPARAM)lpStrParam);
  634. GlobalUnlock((HANDLE)lParam);
  635. return(TRUE);
  636. }
  637. else
  638. {
  639. GlobalUnlock((HANDLE)lParam);
  640. break;
  641. }
  642. }
  643. }
  644. break;
  645. }
  646. #endif // FE: obsolete
  647. case WM_KEYDOWN:
  648. if (wParam == VK_DELETE) {
  649. DWORD dwLastError;
  650. ChatData.type = CHT_CHAR;
  651. SendMessage(hwndSnd,EM_GETSEL,(WPARAM)&dwTemp1,(LPARAM)&dwTemp2);
  652. ChatData.uval.cd_dbcs.SelPos = MAKELONG((WORD)dwTemp1, (WORD)dwTemp2 );
  653. lResult=SendMessage(hwndSnd,WM_GETTEXTLENGTH,0,0);
  654. // if we are trying to delete at the end of the line then ignore it
  655. if(lResult<=LOWORD(ChatData.uval.cd_char.SelPos)) break;
  656. if (LOWORD(ChatData.uval.cd_char.SelPos) == HIWORD(ChatData.uval.cd_char.SelPos)) {
  657. // get handle to the text
  658. hText = (HANDLE)SendMessage( hwndSnd, EM_GETHANDLE, 0, 0);
  659. if( !(hText) )
  660. break;
  661. lpszText = LocalLock( hText);
  662. if( !(lpszText))
  663. {
  664. LocalUnlock(hText);
  665. break;
  666. }
  667. lpszStartSel=lpszText;
  668. for(count=0;count<LOWORD(ChatData.uval.cd_char.SelPos);count++)
  669. {
  670. lpszStartSel=CharNext(lpszStartSel);
  671. if(lpszStartSel[0] == TEXT('\0')) break; // if at the end then break since something is mesed
  672. }
  673. if(lpszStartSel[0] != TEXT('\0') && lpszStartSel[0] == TEXT('\r'))
  674. {
  675. if(lpszStartSel[1] != TEXT('\0') && lpszStartSel[1] == TEXT('\n'))
  676. {
  677. ChatData.uval.cd_char.SelPos=MAKELONG(LOWORD(ChatData.uval.cd_char.SelPos),
  678. HIWORD(ChatData.uval.cd_char.SelPos)+2);
  679. }
  680. else
  681. {
  682. ChatData.uval.cd_char.SelPos=MAKELONG(LOWORD(ChatData.uval.cd_char.SelPos)+1,
  683. HIWORD(ChatData.uval.cd_char.SelPos)+1);
  684. }
  685. }
  686. else
  687. {
  688. ChatData.uval.cd_char.SelPos=MAKELONG(LOWORD(ChatData.uval.cd_char.SelPos)+1,
  689. HIWORD(ChatData.uval.cd_char.SelPos)+1);
  690. }
  691. LocalUnlock( hText );
  692. }
  693. if (gfDbcsEnabled) {
  694. DWORD dwStart, dwEnd;
  695. TranslateWideCharPosToMultiBytePos( hwndSnd,
  696. (DWORD)LOWORD(ChatData.uval.cd_dbcs.SelPos),
  697. (DWORD)HIWORD(ChatData.uval.cd_dbcs.SelPos),
  698. &dwStart, &dwEnd );
  699. ChatData.uval.cd_dbcs.SelPos
  700. = MAKELONG((WORD)dwStart, (WORD)dwEnd);
  701. }
  702. ChatData.uval.cd_char.Char = VK_BACK;
  703. wSet = SET_EN_NOTIFY_WPARAM(ID_EDITSND,EN_CHAR,hwnd);
  704. lSet = SET_EN_NOTIFY_LPARAM(ID_EDITSND,EN_CHAR,hwnd);
  705. SendMessage(hwndApp,WM_COMMAND,(WPARAM)wSet,(LPARAM)lSet);
  706. }
  707. break;
  708. case WM_CHAR:
  709. if(wParam != CTRL_V)
  710. {
  711. ChatData.type = CHT_CHAR;
  712. SendMessage(hwndSnd,EM_GETSEL,(WPARAM)&dwTemp1,(LPARAM)&dwTemp2);
  713. ChatData.uval.cd_dbcs.SelPos = MAKELONG((WORD)dwTemp1, (WORD)dwTemp2 );
  714. if (gfDbcsEnabled) {
  715. DWORD dwStart, dwEnd;
  716. TranslateWideCharPosToMultiBytePos( hwndSnd,
  717. (DWORD)LOWORD(ChatData.uval.cd_dbcs.SelPos),
  718. (DWORD)HIWORD(ChatData.uval.cd_dbcs.SelPos),
  719. &dwStart, &dwEnd );
  720. ChatData.uval.cd_dbcs.SelPos
  721. = MAKELONG((WORD)dwStart, (WORD)dwEnd);
  722. }
  723. ChatData.uval.cd_char.Char = (WORD)wParam;
  724. wSet = SET_EN_NOTIFY_WPARAM(ID_EDITSND,EN_CHAR,hwnd);
  725. lSet = SET_EN_NOTIFY_LPARAM(ID_EDITSND,EN_CHAR,hwnd);
  726. SendMessage(hwndApp,WM_COMMAND,wSet,lSet);
  727. }
  728. break;
  729. case WM_PASTE:
  730. ChatData.type = (WORD)(ChatState.fUnicode ? CHT_PASTEW : CHT_PASTEA);
  731. SendMessage(hwndSnd,EM_GETSEL,(WPARAM)&dwTemp1,(LPARAM)&dwTemp2);
  732. ChatData.uval.cd_paste.SelPos = MAKELONG(dwTemp1,dwTemp2);
  733. wSet = SET_EN_NOTIFY_WPARAM(ID_EDITSND,EN_PASTE,hwnd);
  734. lSet = SET_EN_NOTIFY_LPARAM(ID_EDITSND,EN_PASTE,hwnd);
  735. SendMessage(hwndApp,WM_COMMAND,wSet,lSet);
  736. break;
  737. }
  738. return(CallWindowProc(lpfnOldEditProc,hwnd,msg,wParam,lParam));
  739. }
  740. /*---------------------------------------------------------------------------*\
  741. | APPLICATION CREATE PROCEDURE
  742. | This is the main event-handler for the WM_CREATE event.
  743. |
  744. | created: 11-Nov-91
  745. | history: 29-Dec-92 <chriswil> ported to NT.
  746. |
  747. \*---------------------------------------------------------------------------*/
  748. VOID appWMCreateProc(HWND hwnd)
  749. {
  750. HDC hdc;
  751. TCHAR buf[16] = {0};
  752. RECT rc;
  753. // read from ini
  754. //
  755. wsprintf(buf,TEXT("%ld"),GetSysColor(COLOR_WINDOW));
  756. GetPrivateProfileString(szPref,szBkgnd,buf,szBuf,SZBUFSIZ,szIni);
  757. SndBrushColor = myatol(szBuf);
  758. // just in case display driver changed, set the send-color.
  759. //
  760. hdc = GetDC (hwnd);
  761. if(hdc)
  762. {
  763. SndBrushColor = GetNearestColor(hdc,SndBrushColor);
  764. ReleaseDC(hwnd,hdc);
  765. }
  766. if(ChatState.fUseOwnFont)
  767. {
  768. RcvBrushColor = SndBrushColor;
  769. RcvColorref = SndColorref;
  770. }
  771. else
  772. RcvBrushColor = GetSysColor ( COLOR_WINDOW );
  773. ChatState.fConnected = FALSE;
  774. ChatState.fConnectPending = FALSE;
  775. ChatState.fIsServer = FALSE;
  776. ChatState.fServerVerified = TRUE;
  777. ChatState.fInProcessOfDialing = FALSE;
  778. ChatState.fUnicode = FALSE;
  779. CreateTools(hwnd);
  780. CreateChildWindows(hwnd);
  781. UpdateButtonStates();
  782. // determine height of toolbar window and save...
  783. //
  784. GetClientRect(hwndToolbar, &rc);
  785. dyButtonBar = rc.bottom - rc.top;
  786. // determine height of statusbar window and save...
  787. GetClientRect(hwndStatus, &rc);
  788. dyStatus = rc.bottom - rc.top;
  789. // stuff our local font into one or both edit controls
  790. //
  791. hEditSndFont = CreateFontIndirect((LPLOGFONT)&lfSnd);
  792. if(hEditSndFont)
  793. {
  794. SendMessage(hwndSnd,WM_SETFONT,(WPARAM)hEditSndFont,1L);
  795. if(ChatState.fUseOwnFont)
  796. SendMessage(hwndRcv,WM_SETFONT,(WPARAM)hEditSndFont,1L);
  797. }
  798. hwndActiveEdit = hwndSnd;
  799. return;
  800. }
  801. /*---------------------------------------------------------------------------*\
  802. | APPLICATION WININICHANGE PROCEDURE
  803. | This is the main event-handler for the WM_WININICHANGE event.
  804. |
  805. | created: 11-Nov-91
  806. | history: 29-Dec-92 <chriswil> ported to NT.
  807. |
  808. \*---------------------------------------------------------------------------*/
  809. VOID appWMWinIniChangeProc(HWND hwnd)
  810. {
  811. if(hEditSndFont)
  812. {
  813. DeleteObject(hEditSndFont);
  814. hEditSndFont = CreateFontIndirect((LPLOGFONT)&lfSnd);
  815. if(hEditSndFont)
  816. SendMessage(hwndSnd,WM_SETFONT,(WPARAM)hEditSndFont,1L);
  817. }
  818. if(hEditRcvFont)
  819. {
  820. DeleteObject(hEditRcvFont);
  821. hEditRcvFont = CreateFontIndirect((LPLOGFONT)&lfRcv);
  822. }
  823. if(ChatState.fUseOwnFont && hEditSndFont)
  824. SendMessage(hwndRcv,WM_SETFONT,(WPARAM)hEditSndFont,1L);
  825. else
  826. {
  827. if(hEditRcvFont)
  828. SendMessage(hwndRcv,WM_SETFONT,(WPARAM)hEditRcvFont,1L);
  829. }
  830. return;
  831. }
  832. /*---------------------------------------------------------------------------*\
  833. | APPLICATION ERASEBKGND PROCEDURE
  834. | This is the main event-handler for the WM_ERASEBKBND event.
  835. |
  836. | created: 11-Nov-91
  837. | history: 29-Dec-92 <chriswil> ported to NT.
  838. |
  839. \*---------------------------------------------------------------------------*/
  840. BOOL appWMEraseBkGndProc(HWND hwnd)
  841. {
  842. BOOL bErase;
  843. bErase = IsIconic(hwnd) ? TRUE : FALSE;
  844. return(bErase);
  845. }
  846. /*---------------------------------------------------------------------------*\
  847. | APPLICATION SETFOCUS PROCEDURE
  848. | This is the main event-handler for the WM_SETFOCUS event.
  849. |
  850. | created: 11-Nov-91
  851. | history: 29-Dec-92 <chriswil> ported to NT.
  852. |
  853. \*---------------------------------------------------------------------------*/
  854. VOID appWMSetFocusProc(HWND hwnd)
  855. {
  856. SetFocus(hwndActiveEdit);
  857. return;
  858. }
  859. /*---------------------------------------------------------------------------*\
  860. | APPLICATION CTLCOLOR PROCEDURE
  861. | This is the main event-handler for the WM_CTLCOLOR event.
  862. |
  863. | created: 11-Nov-91
  864. | history: 29-Dec-92 <chriswil> ported to NT.
  865. |
  866. \*---------------------------------------------------------------------------*/
  867. HBRUSH appWMCtlColorProc(HWND hwnd, WPARAM wParam, LPARAM lParam)
  868. {
  869. HDC hDC;
  870. HWND hWndCtl;
  871. HBRUSH hBrush;
  872. hBrush = NULL;
  873. hDC = GET_WM_CTLCOLOREDIT_HDC(wParam,lParam);
  874. hWndCtl = GET_WM_CTLCOLOREDIT_HWND(wParam,lParam);
  875. if(hWndCtl == hwndSnd)
  876. {
  877. SetTextColor(hDC,SndColorref);
  878. SetBkColor(hDC,SndBrushColor);
  879. hBrush = hEditSndBrush;
  880. }
  881. else
  882. if(hWndCtl == hwndRcv)
  883. {
  884. if(ChatState.fUseOwnFont)
  885. {
  886. SetTextColor(hDC,SndColorref);
  887. SetBkColor(hDC,SndBrushColor);
  888. }
  889. else
  890. {
  891. SetTextColor(hDC,RcvColorref);
  892. SetBkColor(hDC,RcvBrushColor);
  893. }
  894. hBrush = hEditRcvBrush;
  895. }
  896. return(hBrush);
  897. }
  898. /*---------------------------------------------------------------------------*\
  899. | APPLICATION SELECTMENU PROCEDURE
  900. | This is the main event-handler for the WM_MENUSELECT event.
  901. |
  902. | created: 11-Nov-91
  903. | history: 29-Dec-92 <chriswil> ported to NT.
  904. |
  905. \*---------------------------------------------------------------------------*/
  906. VOID appWMMenuSelectProc(HWND hwnd, WPARAM wParam, LPARAM lParam)
  907. {
  908. if(wParam == IDM_TOPMOST)
  909. {
  910. if(LoadString(hInst,MH_BASE+IDM_TOPMOST,szBuf,SZBUFSIZ))
  911. SendMessage(hwndStatus,SB_SETTEXT,SBT_NOBORDERS|255,(LPARAM)(LPSTR)szBuf);
  912. }
  913. MenuHelp((WORD)WM_MENUSELECT,wParam,lParam,GetMenu(hwnd),hInst,hwndStatus,(LPUINT)nIDs);
  914. return;
  915. }
  916. /*---------------------------------------------------------------------------*\
  917. | APPLICATION PAINT PROCEDURE
  918. | This is the main event-handler for the WM_PAINT event.
  919. |
  920. | created: 11-Nov-91
  921. | history: 29-Dec-92 <chriswil> ported to NT.
  922. |
  923. \*---------------------------------------------------------------------------*/
  924. VOID appWMPaintProc(HWND hwnd)
  925. {
  926. HDC hdc;
  927. PAINTSTRUCT ps;
  928. RECT rc;
  929. hdc = BeginPaint(hwnd,&ps);
  930. if(hdc)
  931. {
  932. if(IsIconic(hwnd))
  933. {
  934. //
  935. //
  936. DefWindowProc(hwnd,WM_ICONERASEBKGND,(WPARAM)ps.hdc,0L);
  937. BitBlt(hMemDC,0,0,cxIcon,cyIcon,hdc,0,0,SRCCOPY);
  938. DrawIcon(hdc,0,0,hPhones[0]);
  939. // make 2 more copies.
  940. //
  941. BitBlt(hMemDC,cxIcon ,0,cxIcon,cyIcon,hMemDC,0,0,SRCCOPY);
  942. BitBlt(hMemDC,2*cxIcon,0,cxIcon,cyIcon,hMemDC,0,0,SRCCOPY);
  943. // draw phones into them.
  944. //
  945. DrawIcon(hMemDC,0 ,0,hPhones[0]);
  946. DrawIcon(hMemDC,cxIcon ,0,hPhones[1]);
  947. DrawIcon(hMemDC,2*cxIcon,0,hPhones[2]);
  948. }
  949. else
  950. {
  951. #if BRD > 2
  952. rc = SndRc;
  953. rc.top--;
  954. rc.left--;
  955. DrawShadowRect(hdc,&rc);
  956. rc = RcvRc;
  957. rc.top--;
  958. rc.left--;
  959. DrawShadowRect(hdc,&rc);
  960. #endif
  961. }
  962. EndPaint ( hwnd, &ps );
  963. }
  964. return;
  965. }
  966. /*---------------------------------------------------------------------------*\
  967. | APPLICATION TIMER PROCEDURE
  968. | This is the main event-handler for the WM_TIMER event.
  969. |
  970. | created: 11-Nov-91
  971. | history: 29-Dec-92 <chriswil> ported to NT.
  972. |
  973. \*---------------------------------------------------------------------------*/
  974. VOID appWMTimerProc(HWND hwnd)
  975. {
  976. HDC hdc;
  977. DWORD dummy;
  978. // Animate the phone icon.
  979. //
  980. if(cAnimate)
  981. {
  982. if(--cAnimate == 0)
  983. {
  984. KillTimer(hwnd,idTimer);
  985. FlashWindow(hwnd,FALSE);
  986. }
  987. if(IsIconic(hwnd))
  988. {
  989. hdc = GetDC(hwndApp);
  990. if(hdc)
  991. {
  992. BitBlt(hdc,0,0,cxIcon,cyIcon,hMemDC,ASeq[cAnimate % 4] * cxIcon,0,SRCCOPY);
  993. ReleaseDC(hwndApp,hdc);
  994. }
  995. }
  996. return;
  997. }
  998. // We must be ringing...
  999. //
  1000. if(!ChatState.fConnectPending)
  1001. {
  1002. KillTimer(hwnd,idTimer);
  1003. return;
  1004. }
  1005. // has the existence of the server been verified (by completion
  1006. // of the async advstart xact)?
  1007. //
  1008. if(!ChatState.fServerVerified)
  1009. {
  1010. return;
  1011. }
  1012. // don't want to lose this...
  1013. //
  1014. DdeKeepStringHandle(idInst,hszLocalName);
  1015. if(DdeClientTransaction(NULL,0L,ghConv,hszLocalName,cf_chatdata,XTYP_ADVSTART,(DWORD)3000L,(LPDWORD)&dummy) == (HDDEDATA)TRUE)
  1016. {
  1017. ChatState.fConnected = TRUE;
  1018. ChatState.fConnectPending = FALSE;
  1019. UpdateButtonStates();
  1020. KILLSOUND;
  1021. SendFontToPartner();
  1022. wsprintf(szBuf,szConnectedTo,(LPSTR)szConvPartner);
  1023. SetStatusWindowText(szBuf);
  1024. wsprintf(szBuf,TEXT("%s - [%s]"),(LPTSTR)szAppName,(LPTSTR)szConvPartner);
  1025. SetWindowText(hwnd,szBuf);
  1026. // allow text entry...
  1027. //
  1028. SendMessage(hwndSnd,EM_SETREADONLY,(WPARAM)FALSE,0L);
  1029. KillTimer(hwnd,idTimer);
  1030. AnnounceSupport();
  1031. }
  1032. else
  1033. {
  1034. // The other party has not answered yet... ring every 6 seconds.
  1035. // Ring local,
  1036. //
  1037. if(!(nConnectAttempt++ % 6))
  1038. DoRing(szWcRingOut);
  1039. }
  1040. return;
  1041. }
  1042. /*---------------------------------------------------------------------------*\
  1043. | APPLICATION QUERYDRAGICON PROCEDURE
  1044. | This is the main event-handler for the WM_QUERYDRAGICON event.
  1045. |
  1046. | created: 11-Nov-91
  1047. | history: 29-Dec-92 <chriswil> ported to NT.
  1048. |
  1049. \*---------------------------------------------------------------------------*/
  1050. HICON appWMQueryDragIconProc(HWND hwnd)
  1051. {
  1052. HICON hIcon;
  1053. hIcon = hPhones[0];
  1054. return(hIcon);
  1055. }
  1056. /*---------------------------------------------------------------------------*\
  1057. | APPLICATION SIZE PROCEDURE
  1058. | This is the main event-handler for the WM_SIZE event.
  1059. |
  1060. | created: 11-Nov-91
  1061. | history: 29-Dec-92 <chriswil> ported to NT.
  1062. |
  1063. \*---------------------------------------------------------------------------*/
  1064. VOID appWMSizeProc(HWND hwnd, WPARAM wParam, LPARAM lParam)
  1065. {
  1066. if(ChatState.fMinimized && ChatState.fConnectPending && ChatState.fIsServer)
  1067. {
  1068. ChatState.fAllowAnswer = TRUE;
  1069. SetStatusWindowText(szConnecting);
  1070. // stop the ringing immediately.
  1071. //
  1072. KILLSOUND;
  1073. if(ChatState.fMMSound)
  1074. sndPlaySound(NULL,SND_ASYNC);
  1075. // cut the animation short.
  1076. //
  1077. if(cAnimate)
  1078. cAnimate = 1;
  1079. }
  1080. //
  1081. //
  1082. InvalidateRect(hwnd,NULL,TRUE);
  1083. SendMessage(hwndToolbar,WM_SIZE,0,0L);
  1084. SendMessage(hwndStatus ,WM_SIZE,0,0L);
  1085. AdjustEditWindows();
  1086. ChatState.fMinimized = (wParam == SIZE_MINIMIZED) ? TRUE : FALSE;
  1087. return;
  1088. }
  1089. /*---------------------------------------------------------------------------*\
  1090. | APPLICATION INITMENU PROCEDURE
  1091. | This is the main event-handler for the WM_INITMENU event.
  1092. |
  1093. | created: 11-Nov-91
  1094. | history: 29-Dec-92 <chriswil> ported to NT.
  1095. |
  1096. \*---------------------------------------------------------------------------*/
  1097. VOID appWMInitMenuProc(HMENU hmenu)
  1098. {
  1099. UINT status;
  1100. LONG l;
  1101. TCHAR szTest[] = TEXT(" ");
  1102. DWORD dwTemp1,dwTemp2;
  1103. SendMessage(hwndActiveEdit,EM_GETSEL,(LPARAM)&dwTemp1,(WPARAM)&dwTemp2);
  1104. l = MAKELONG(dwTemp1,dwTemp2);
  1105. if(HIWORD(l) != LOWORD(l))
  1106. status = MF_ENABLED;
  1107. else
  1108. status = MF_GRAYED;
  1109. EnableMenuItem(hmenu,IDM_EDITCUT ,(hwndActiveEdit == hwndSnd && ChatState.fConnected) ? status : MF_GRAYED);
  1110. EnableMenuItem(hmenu,IDM_EDITCOPY,status);
  1111. status = MF_GRAYED;
  1112. if(hwndActiveEdit == hwndSnd && ChatState.fConnected && IsClipboardFormatAvailable(CF_TEXT))
  1113. {
  1114. status = MF_ENABLED;
  1115. }
  1116. EnableMenuItem(hmenu,IDM_EDITPASTE,status);
  1117. // select all enabled if control non-empty.
  1118. //
  1119. status = MF_GRAYED;
  1120. if(SendMessage(hwndActiveEdit,WM_GETTEXT,2,(LPARAM)szTest))
  1121. status = MF_ENABLED;
  1122. EnableMenuItem(hmenu,IDM_EDITSELECT,status);
  1123. // can we dial, answer and hangup.
  1124. //
  1125. EnableMenuItem(hmenu,IDM_DIAL ,(!ChatState.fConnected && !ChatState.fConnectPending) ? MF_ENABLED : MF_GRAYED);
  1126. EnableMenuItem(hmenu,IDM_ANSWER,(ChatState.fConnectPending && ChatState.fIsServer) ? MF_ENABLED : MF_GRAYED);
  1127. EnableMenuItem(hmenu,IDM_HANGUP,(ChatState.fConnected || ChatState.fConnectPending) ? MF_ENABLED : MF_GRAYED);
  1128. // Is toolbar, statusbar and sound allowed?
  1129. //
  1130. CheckMenuItem(hmenu,IDM_SOUND ,(ChatState.fSound) ? MF_CHECKED : MF_UNCHECKED);
  1131. CheckMenuItem(hmenu,IDM_TOOLBAR ,(ChatState.fToolBar) ? MF_CHECKED : MF_UNCHECKED);
  1132. CheckMenuItem(hmenu,IDM_STATUSBAR,(ChatState.fStatusBar) ? MF_CHECKED : MF_UNCHECKED);
  1133. return;
  1134. }
  1135. /*---------------------------------------------------------------------------*\
  1136. | APPLICATION SYSCOMMAND PROCEDURE
  1137. | This is the main event-handler for the WM_SYSCOMMAND event.
  1138. |
  1139. | created: 11-Nov-91
  1140. | history: 29-Dec-92 <chriswil> ported to NT.
  1141. |
  1142. \*---------------------------------------------------------------------------*/
  1143. LRESULT appWMSysCommandProc(HWND hwnd, WPARAM wParam, LPARAM lParam)
  1144. {
  1145. LRESULT lResult;
  1146. HMENU hmenu;
  1147. lResult = 0l;
  1148. switch(wParam)
  1149. {
  1150. case IDM_TOPMOST:
  1151. ChatState.fTopMost = ChatState.fTopMost ? FALSE : TRUE;
  1152. hmenu = GetSystemMenu(hwnd,FALSE);
  1153. if(hmenu)
  1154. CheckMenuItem(hmenu,IDM_TOPMOST,(ChatState.fTopMost) ? MF_CHECKED : MF_UNCHECKED);
  1155. SetWindowPos(hwnd,ChatState.fTopMost ? HWND_TOPMOST : HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  1156. break;
  1157. }
  1158. return(lResult);
  1159. }
  1160. /*---------------------------------------------------------------------------*\
  1161. | APPLICATION COMMAND PROCEDURE
  1162. | This is the main event-handler for the WM_COMMAND event.
  1163. |
  1164. | created: 11-Nov-91
  1165. | history: 29-Dec-92 <chriswil> ported to NT.
  1166. |
  1167. \*---------------------------------------------------------------------------*/
  1168. BOOL appWMCommandProc(HWND hwnd, WPARAM wParam, LPARAM lParam)
  1169. {
  1170. HDC hdc;
  1171. int tmp;
  1172. UINT uNotify;
  1173. DWORD dummy;
  1174. DWORD dwBufSize;
  1175. HDDEDATA hDdeData;
  1176. BOOL bHandled,bOK,bOKPressed=FALSE;
  1177. WPARAM wSelStart;
  1178. LPARAM lSelEnd;
  1179. bHandled = TRUE;
  1180. switch(LOWORD(wParam))
  1181. {
  1182. case ID_EDITRCV:
  1183. uNotify = GET_EN_SETFOCUS_NOTIFY(wParam,lParam);
  1184. switch(uNotify)
  1185. {
  1186. case EN_SETFOCUS:
  1187. hwndActiveEdit = hwndRcv;
  1188. break;
  1189. // If the control is out of space, honk.
  1190. //
  1191. case EN_ERRSPACE:
  1192. MessageBeep(0);
  1193. break;
  1194. }
  1195. break;
  1196. case ID_EDITSND:
  1197. uNotify = GET_EN_SETFOCUS_NOTIFY(wParam,lParam);
  1198. switch(uNotify)
  1199. {
  1200. // This string came from the edit-hook
  1201. // procedure.
  1202. //
  1203. case EN_DBCS_STRING:
  1204. if(ChatState.fConnected)
  1205. {
  1206. if(!ChatState.fIsServer)
  1207. {
  1208. hDdeData = CreateDbcsStringData();
  1209. if(hDdeData)
  1210. DdeClientTransaction((LPBYTE)hDdeData,(DWORD)-1,ghConv,hszTextItem,cf_chatdata,XTYP_POKE,(DWORD)TIMEOUT_ASYNC,(LPDWORD)&dummy);
  1211. }
  1212. else
  1213. {
  1214. hszConvPartner = DdeCreateStringHandle(idInst,szConvPartner,0);
  1215. DdePostAdvise(idInst,hszChatTopic,hszConvPartner);
  1216. }
  1217. }
  1218. break;
  1219. // This character came from the edit-hook
  1220. // procedure.
  1221. //
  1222. case EN_CHAR:
  1223. if(ChatState.fConnected)
  1224. {
  1225. if(!ChatState.fIsServer)
  1226. {
  1227. hDdeData = CreateCharData();
  1228. if(hDdeData)
  1229. DdeClientTransaction((LPBYTE)hDdeData,(DWORD)-1,ghConv,hszTextItem,cf_chatdata,XTYP_POKE,(DWORD)TIMEOUT_ASYNC,(LPDWORD)&dummy);
  1230. }
  1231. else
  1232. {
  1233. hszConvPartner = DdeCreateStringHandle(idInst,szConvPartner,0);
  1234. DdePostAdvise(idInst,hszChatTopic,hszConvPartner);
  1235. }
  1236. }
  1237. break;
  1238. case EN_PASTE:
  1239. if(ChatState.fConnected)
  1240. {
  1241. if(!ChatState.fIsServer)
  1242. {
  1243. if(IsClipboardFormatAvailable(CF_UNICODETEXT))
  1244. {
  1245. hDdeData = CreatePasteData();
  1246. if(hDdeData)
  1247. DdeClientTransaction((LPBYTE)hDdeData,(DWORD)-1,ghConv,hszTextItem,cf_chatdata,XTYP_POKE,(DWORD)TIMEOUT_ASYNC,(LPDWORD)&StrXactID);
  1248. }
  1249. }
  1250. else
  1251. {
  1252. hszConvPartner = DdeCreateStringHandle(idInst,szConvPartner,0);
  1253. DdePostAdvise(idInst,hszChatTopic,hszConvPartner);
  1254. }
  1255. }
  1256. break;
  1257. case EN_SETFOCUS:
  1258. hwndActiveEdit = hwndSnd;
  1259. break;
  1260. case EN_ERRSPACE:
  1261. // If the control is out of space, honk.
  1262. //
  1263. MessageBeep(0);
  1264. break;
  1265. }
  1266. break;
  1267. case IDC_TOOLBAR:
  1268. MenuHelp(WM_COMMAND,wParam,lParam,GetMenu(hwnd),hInst,hwndStatus,(LPUINT)nIDs);
  1269. break;
  1270. case IDM_EXIT:
  1271. SendMessage(hwnd,WM_CLOSE,0,0L);
  1272. break;
  1273. case IDM_TOOLBAR:
  1274. if(ChatState.fToolBar)
  1275. {
  1276. ChatState.fToolBar = FALSE;
  1277. ShowWindow(hwndToolbar,SW_HIDE);
  1278. InvalidateRect(hwnd,NULL,TRUE);
  1279. AdjustEditWindows();
  1280. }
  1281. else
  1282. {
  1283. ChatState.fToolBar = TRUE;
  1284. InvalidateRect(hwnd,NULL,TRUE);
  1285. AdjustEditWindows();
  1286. ShowWindow(hwndToolbar,SW_SHOW);
  1287. }
  1288. break;
  1289. case IDM_STATUSBAR:
  1290. if(ChatState.fStatusBar)
  1291. {
  1292. ChatState.fStatusBar = FALSE;
  1293. ShowWindow(hwndStatus,SW_HIDE);
  1294. InvalidateRect(hwnd,NULL,TRUE);
  1295. AdjustEditWindows();
  1296. }
  1297. else
  1298. {
  1299. ChatState.fStatusBar = TRUE;
  1300. InvalidateRect(hwnd,NULL,TRUE);
  1301. AdjustEditWindows();
  1302. ShowWindow(hwndStatus,SW_SHOW);
  1303. }
  1304. break;
  1305. case IDM_SWITCHWIN:
  1306. if(hwndActiveEdit == hwndSnd)
  1307. SetFocus(hwndActiveEdit = hwndRcv);
  1308. else
  1309. SetFocus(hwndActiveEdit = hwndSnd);
  1310. break;
  1311. case IDM_SOUND:
  1312. ChatState.fSound = ChatState.fSound ? FALSE : TRUE;
  1313. break;
  1314. case IDM_COLOR:
  1315. SetFocus(hwndActiveEdit);
  1316. chc.rgbResult = SndBrushColor;
  1317. tmp = ChooseColor((LPCHOOSECOLOR)&chc);
  1318. if(tmp)
  1319. {
  1320. hdc = GetDC(hwnd);
  1321. if(hdc)
  1322. {
  1323. // must map to solid color (edit-control limitation).
  1324. //
  1325. SndBrushColor = GetNearestColor(hdc,chc.rgbResult);
  1326. ReleaseDC(hwnd,hdc);
  1327. }
  1328. DeleteObject(hEditSndBrush);
  1329. hEditSndBrush = CreateSolidBrush(SndBrushColor);
  1330. InvalidateRect(hwndSnd,NULL,TRUE);
  1331. SaveBkGndToIni();
  1332. if(ChatState.fUseOwnFont)
  1333. {
  1334. RcvBrushColor = SndBrushColor;
  1335. DeleteObject(hEditRcvBrush);
  1336. hEditRcvBrush = CreateSolidBrush(RcvBrushColor);
  1337. InvalidateRect(hwndRcv, NULL, TRUE);
  1338. }
  1339. if(ChatState.fConnected)
  1340. SendFontToPartner();
  1341. }
  1342. break;
  1343. case IDM_FONT:
  1344. SetFocus(hwndActiveEdit);
  1345. chf.hwndOwner = hwndSnd;
  1346. chf.rgbColors = SndColorref;
  1347. tmp = ChooseFont((LPCHOOSEFONT)&chf);
  1348. if(tmp)
  1349. {
  1350. if(hEditSndFont)
  1351. DeleteObject(hEditSndFont);
  1352. hEditSndFont = CreateFontIndirect((LPLOGFONT)&lfSnd);
  1353. if(hEditSndFont)
  1354. {
  1355. SndColorref = chf.rgbColors;
  1356. SaveFontToIni();
  1357. SendMessage(hwndSnd,WM_SETFONT,(WPARAM)hEditSndFont,1L);
  1358. if(ChatState.fUseOwnFont)
  1359. {
  1360. SendMessage(hwndRcv,WM_SETFONT,(WPARAM)hEditSndFont,1L);
  1361. RcvColorref = SndColorref;
  1362. }
  1363. // notify partner of the change
  1364. //
  1365. if(ChatState.fConnected)
  1366. SendFontToPartner();
  1367. }
  1368. }
  1369. break;
  1370. case IDM_DIAL:
  1371. if(ChatState.fConnected)
  1372. {
  1373. SetStatusWindowText(szAlreadyConnect);
  1374. break;
  1375. }
  1376. if(ChatState.fConnectPending)
  1377. {
  1378. SetStatusWindowText ( szAbandonFirst);
  1379. break;
  1380. }
  1381. dwBufSize = SZBUFSIZ;
  1382. WNETGETUSER((LPTSTR)NULL,(LPTSTR)szBuf,&dwBufSize);
  1383. if(GetLastError() == ERROR_NO_NETWORK)
  1384. {
  1385. if(MessageBox(hwnd,szNoNet,TEXT("Chat"),MB_YESNO | MB_ICONQUESTION) == IDNO)
  1386. break;
  1387. }
  1388. ChatState.fInProcessOfDialing = TRUE;
  1389. if(WNetServerBrowseDialog == NULL || (*WNetServerBrowseDialog)(hwnd,TEXT("MRU_Chat"),szBuf,SZBUFSIZ,0L) == WN_NOT_SUPPORTED)
  1390. {
  1391. #if WIN32
  1392. bOKPressed = FALSE;
  1393. *szBuf = TEXT('\0');
  1394. lstrcpy(szHelp, TEXT("winchat.hlp"));
  1395. I_SystemFocusDialog(hwnd,MY_LOGONTYPE,(LPWSTR)szBuf,SZBUFSIZ,&bOKPressed,(LPWSTR)szHelp,IDH_SELECTCOMPUTER);
  1396. if(bOKPressed)
  1397. {
  1398. bOK = TRUE;
  1399. lstrcpy(szConvPartner,szBuf);
  1400. }
  1401. #else
  1402. dlgDisplayBox(hInst,hwnd,(LPSTR)MAKEINTRESOURCE(IDD_CONNECT),dlgConnectProc,0l);
  1403. #endif
  1404. }
  1405. SetFocus(hwndActiveEdit);
  1406. if(*szBuf && bOKPressed)
  1407. {
  1408. CharUpper(szBuf);
  1409. if((lstrlen(szBuf) > 2) && (szBuf[0] == TEXT('\\')) && (szBuf[1] == TEXT('\\')))
  1410. lstrcpy(szConvPartner,szBuf+2);
  1411. else
  1412. lstrcpy(szConvPartner,szBuf);
  1413. ClearEditControls();
  1414. wsprintf(szBuf,szDialing,(LPSTR)szConvPartner);
  1415. SetStatusWindowText(szBuf);
  1416. #if TESTLOCAL
  1417. wsprintf(szBuf,TEXT("%s"),(LPTSTR)szServiceName);
  1418. hszConnect = DdeCreateStringHandle(idInst,szBuf,0);
  1419. ghConv = DdeConnect(idInst,hszConnect,hszChatTopic,NULL);
  1420. #else
  1421. wsprintf(szBuf,TEXT("\\\\%s\\NDDE$"),(LPTSTR)szConvPartner);
  1422. hszConnect = DdeCreateStringHandle(idInst,szBuf,0);
  1423. ghConv = DdeConnect(idInst,hszConnect,hszChatShare,NULL);
  1424. #endif
  1425. if(ghConv == (HCONV)0)
  1426. {
  1427. SetStatusWindowText(szNoConnect);
  1428. DdeFreeStringHandle(idInst,hszConnect);
  1429. ChatState.fInProcessOfDialing = FALSE;
  1430. break;
  1431. }
  1432. ChatState.fConnectPending = TRUE;
  1433. UpdateButtonStates();
  1434. // set up server verify async xaction.
  1435. //
  1436. ChatState.fServerVerified = FALSE;
  1437. DdeKeepStringHandle(idInst,hszConnectTest);
  1438. DdeClientTransaction(NULL,0L,ghConv,hszConnectTest,cf_chatdata,XTYP_ADVSTART,(DWORD)TIMEOUT_ASYNC,(LPDWORD)&XactID);
  1439. // Indicate that this is a Unicode conversation.
  1440. //
  1441. ChatData.type = CHT_UNICODE;
  1442. hDdeData = CreateCharData ();
  1443. if(hDdeData)
  1444. DdeClientTransaction((LPBYTE)hDdeData,(DWORD)-1,ghConv,hszTextItem,cf_chatdata,XTYP_POKE,(DWORD)TIMEOUT_ASYNC,(LPDWORD)&dummy);
  1445. // set ring timer...
  1446. // connect attempts every second - will be divided by
  1447. // 6 for actual phone rings. This is done to speed the
  1448. // connection process
  1449. // want first message immediately...
  1450. //
  1451. idTimer = SetTimer(hwnd,1,1000,NULL);
  1452. PostMessage(hwnd,WM_TIMER,1,0L);
  1453. nConnectAttempt = 0;
  1454. }
  1455. ChatState.fInProcessOfDialing = FALSE;
  1456. DdeFreeStringHandle(idInst,hszConnect);
  1457. break;
  1458. case IDM_ANSWER:
  1459. if(ChatState.fConnectPending)
  1460. {
  1461. if(!ChatState.fIsServer)
  1462. {
  1463. SetStatusWindowText(szYouCaller);
  1464. break;
  1465. }
  1466. else
  1467. {
  1468. // allow the connection.
  1469. //
  1470. ChatState.fAllowAnswer = TRUE;
  1471. SetStatusWindowText(szConnecting);
  1472. // stop the ringing immediately.
  1473. //
  1474. if(ChatState.fMMSound)
  1475. sndPlaySound(NULL,SND_ASYNC);
  1476. // cut the animation short.
  1477. //
  1478. if(cAnimate)
  1479. cAnimate = 1;
  1480. }
  1481. }
  1482. break;
  1483. case IDM_HANGUP:
  1484. if(!ChatState.fConnected && !ChatState.fConnectPending)
  1485. {
  1486. break;
  1487. }
  1488. if(ChatState.fConnectPending && !ChatState.fConnected)
  1489. {
  1490. SetStatusWindowText(szConnectAbandon);
  1491. }
  1492. else
  1493. {
  1494. SetStatusWindowText(szHangingUp);
  1495. }
  1496. KILLSOUND;
  1497. DdeDisconnect(ghConv);
  1498. ChatState.fConnectPending = FALSE;
  1499. ChatState.fConnected = FALSE;
  1500. ChatState.fIsServer = FALSE;
  1501. ChatState.fUnicode = FALSE;
  1502. #ifdef PROTOCOL_NEGOTIATE
  1503. ChatState.fProtocolSent = FALSE;
  1504. #endif
  1505. // suspend text entry.
  1506. //
  1507. UpdateButtonStates();
  1508. SendMessage(hwndSnd,EM_SETREADONLY,TRUE,0L);
  1509. SetWindowText(hwndApp,szAppName);
  1510. break;
  1511. case IDX_UNICODECONV:
  1512. ChatData.type = CHT_UNICODE;
  1513. hszConvPartner = DdeCreateStringHandle(idInst,szConvPartner,0);
  1514. DdePostAdvise(idInst,hszChatTopic,hszConvPartner);
  1515. break;
  1516. case IDX_DEFERFONTCHANGE:
  1517. SendFontToPartner();
  1518. break;
  1519. #ifdef PROTOCOL_NEGOTIATE
  1520. case IDX_DEFERPROTOCOL:
  1521. AnnounceSupport();
  1522. break;
  1523. #endif
  1524. case IDM_CONTENTS:
  1525. HtmlHelpA(GetDesktopWindow(),"winchat.chm",HH_DISPLAY_TOPIC,0L);
  1526. break;
  1527. case IDM_ABOUT:
  1528. ShellAbout(hwndSnd,szAppName,szNull,hPhones[0]);
  1529. SetFocus(hwndActiveEdit);
  1530. break;
  1531. case IDM_PREFERENCES:
  1532. DialogBoxParam(hInst,(LPTSTR)MAKEINTRESOURCE(IDD_PREFERENCES),hwnd,dlgPreferencesProc,(LPARAM)0);
  1533. break;
  1534. case IDM_EDITCOPY:
  1535. SendMessage(hwndActiveEdit,WM_COPY,0,0L);
  1536. break;
  1537. case IDM_EDITPASTE:
  1538. SendMessage(hwndActiveEdit,WM_PASTE,0,0L);
  1539. break;
  1540. case IDM_EDITCUT:
  1541. SendMessage(hwndActiveEdit,WM_CUT,0,0L);
  1542. break;
  1543. case IDM_EDITSELECT:
  1544. wSelStart = SET_EM_SETSEL_WPARAM(0,-1);
  1545. lSelEnd = SET_EM_SETSEL_LPARAM(0,-1);
  1546. SendMessage(hwndActiveEdit,EM_SETSEL,wSelStart,lSelEnd);
  1547. break;
  1548. case IDM_EDITUNDO:
  1549. SendMessage(hwndActiveEdit,EM_UNDO,0,0L);
  1550. break;
  1551. default:
  1552. bHandled = FALSE;
  1553. break;
  1554. }
  1555. return(bHandled);
  1556. }
  1557. /*---------------------------------------------------------------------------*\
  1558. | APPLICATION DESTROY PROCEDURE
  1559. | This is the main event-handler for the WM_DESTROY event.
  1560. |
  1561. | created: 11-Nov-91
  1562. | history: 29-Dec-92 <chriswil> ported to NT.
  1563. |
  1564. \*---------------------------------------------------------------------------*/
  1565. VOID appWMDestroyProc(HWND hwnd)
  1566. {
  1567. // Abandon transaction if in progress. Force hangup
  1568. // of conversation.
  1569. //
  1570. if(!ChatState.fServerVerified)
  1571. DdeAbandonTransaction(idInst,ghConv,XactID);
  1572. SendMessage(hwnd,WM_COMMAND,IDM_HANGUP,0L);
  1573. // Destroy resources allocated on behalf of app.
  1574. //
  1575. KILLSOUND;
  1576. DeleteTools(hwnd);
  1577. // Save the state information.
  1578. //
  1579. Wpl.length = sizeof(Wpl);
  1580. if(GetWindowPlacement(hwnd,&Wpl))
  1581. SaveWindowPlacement(&Wpl);
  1582. wsprintf(szBuf, TEXT("%d"), (UINT)ChatState.fSound);
  1583. WritePrivateProfileString(szPref, szSnd, szBuf, szIni);
  1584. wsprintf(szBuf, TEXT("%d"), (UINT)ChatState.fToolBar);
  1585. WritePrivateProfileString(szPref, szTool, szBuf, szIni);
  1586. wsprintf(szBuf, TEXT("%d"), (UINT)ChatState.fStatusBar);
  1587. WritePrivateProfileString(szPref, szStat, szBuf, szIni);
  1588. wsprintf(szBuf, TEXT("%d"), (UINT)ChatState.fTopMost);
  1589. WritePrivateProfileString(szPref, szTop, szBuf, szIni);
  1590. wsprintf(szBuf, TEXT("%d"), (UINT)ChatState.fSideBySide);
  1591. WritePrivateProfileString(szPref, szSbS, szBuf, szIni);
  1592. wsprintf(szBuf, TEXT("%d"), (UINT)ChatState.fUseOwnFont);
  1593. WritePrivateProfileString(szPref, szUseOF, szBuf, szIni);
  1594. PostQuitMessage(0);
  1595. return;
  1596. }
  1597. /*---------------------------------------------------------------------------*\
  1598. | ASCII TO LONG
  1599. | This routine converts an ascii string to long.
  1600. |
  1601. | created: 11-Nov-91
  1602. | history: 29-Dec-92 <chriswil> ported to NT.
  1603. |
  1604. \*---------------------------------------------------------------------------*/
  1605. LONG FAR myatol(LPTSTR s)
  1606. {
  1607. LONG ret = 0L;
  1608. while(*s) ret = ret * 10 + (*s++ - TEXT('0'));
  1609. return(ret);
  1610. }
  1611. /*---------------------------------------------------------------------------*\
  1612. | UPDATE BUTTON STATES
  1613. | This routine updates the menu/toolbar buttons.
  1614. |
  1615. | created: 11-Nov-91
  1616. | history: 29-Dec-92 <chriswil> ported to NT.
  1617. |
  1618. \*---------------------------------------------------------------------------*/
  1619. VOID FAR UpdateButtonStates(VOID)
  1620. {
  1621. BOOL DialState = FALSE;
  1622. BOOL AnswerState = FALSE;
  1623. BOOL HangUpState = FALSE;
  1624. if(ChatState.fConnected)
  1625. HangUpState = TRUE;
  1626. else
  1627. if(ChatState.fConnectPending)
  1628. {
  1629. if(!ChatState.fIsServer)
  1630. HangUpState = TRUE;
  1631. else
  1632. AnswerState = TRUE;
  1633. }
  1634. else
  1635. DialState = TRUE;
  1636. SendMessage(hwndToolbar,TB_ENABLEBUTTON,IDM_DIAL ,DialState);
  1637. SendMessage(hwndToolbar,TB_ENABLEBUTTON,IDM_ANSWER,AnswerState);
  1638. SendMessage(hwndToolbar,TB_ENABLEBUTTON,IDM_HANGUP,HangUpState);
  1639. return;
  1640. }
  1641. /*---------------------------------------------------------------------------*\
  1642. | GET COMPUTER NAME
  1643. | This routine returns the computer name of the machine.
  1644. |
  1645. | created: 31-Dec-92
  1646. | history: 31-Dec-92 <chriswil> created.
  1647. |
  1648. \*---------------------------------------------------------------------------*/
  1649. BOOL FAR appGetComputerName(LPTSTR lpszName)
  1650. {
  1651. BOOL bGet;
  1652. DWORD dwSize;
  1653. #ifdef WIN32
  1654. dwSize = MAX_COMPUTERNAME_LENGTH+1;
  1655. bGet = GetComputerName(lpszName,&dwSize);
  1656. #else
  1657. bGet = TRUE;
  1658. dwSize = 0l;
  1659. if(GetPrivateProfileString(szVredir,szComputerName,szNull,lpszName,UNCNLEN,szSysIni))
  1660. OemToAnsi(lpszName,lpszName);
  1661. #endif
  1662. return(bGet);
  1663. }
  1664. /*---------------------------------------------------------------------------*\
  1665. | ADJUST EDIT WINDOWS
  1666. | This routine sizes the edit-controls.
  1667. |
  1668. | created: 11-Nov-91
  1669. | history: 29-Dec-92 <chriswil> ported to NT.
  1670. |
  1671. \*---------------------------------------------------------------------------*/
  1672. VOID FAR AdjustEditWindows(VOID)
  1673. {
  1674. int tmpsplit;
  1675. RECT rc;
  1676. GetClientRect(hwndApp,&rc);
  1677. rc.top += ChatState.fToolBar ? dyButtonBar + BRD : BRD;
  1678. rc.bottom -= ChatState.fStatusBar ? dyStatus + BRD : BRD;
  1679. if(!ChatState.fSideBySide)
  1680. {
  1681. tmpsplit = rc.top + (rc.bottom - rc.top) / 2;
  1682. SndRc.left = RcvRc.left = rc.left - 1 + BRD;
  1683. SndRc.right = RcvRc.right = rc.right + 1 - BRD;
  1684. SndRc.top = rc.top;
  1685. SndRc.bottom = tmpsplit;
  1686. RcvRc.top = tmpsplit + BRD;
  1687. RcvRc.bottom = rc.bottom;
  1688. }
  1689. else
  1690. {
  1691. tmpsplit = rc.left + (rc.right - rc.left) / 2;
  1692. SndRc.left = rc.left - 1 + BRD;
  1693. SndRc.right = tmpsplit - BRD / 2;
  1694. RcvRc.left = tmpsplit + BRD / 2;
  1695. RcvRc.right = rc.right + 1 - BRD;
  1696. SndRc.top = RcvRc.top = rc.top;
  1697. SndRc.bottom = RcvRc.bottom = rc.bottom;
  1698. }
  1699. MoveWindow(hwndSnd,SndRc.left,SndRc.top,SndRc.right-SndRc.left,SndRc.bottom-SndRc.top,TRUE);
  1700. MoveWindow(hwndRcv,RcvRc.left,RcvRc.top,RcvRc.right-RcvRc.left,RcvRc.bottom-RcvRc.top,TRUE);
  1701. return;
  1702. }
  1703. /*---------------------------------------------------------------------------*\
  1704. | CLEAR EDIT CONTROLS
  1705. | This routine clears the send/receive edit controls.
  1706. |
  1707. | created: 11-Nov-91
  1708. | history: 29-Dec-92 <chriswil> ported to NT.
  1709. |
  1710. \*---------------------------------------------------------------------------*/
  1711. VOID ClearEditControls(VOID)
  1712. {
  1713. SendMessage(hwndSnd,EM_SETREADONLY,FALSE,0L);
  1714. SendMessage(hwndSnd,WM_SETTEXT ,0 ,(LPARAM)(LPSTR)szNull);
  1715. SendMessage(hwndSnd,EM_SETREADONLY,TRUE ,0L);
  1716. SendMessage(hwndRcv,EM_SETREADONLY,FALSE,0L);
  1717. SendMessage(hwndRcv,WM_SETTEXT ,0 ,(LPARAM)(LPSTR)szNull);
  1718. SendMessage(hwndRcv,EM_SETREADONLY,TRUE ,0L);
  1719. return;
  1720. }
  1721. /*---------------------------------------------------------------------------*\
  1722. | DO RING
  1723. | This routine performs the phone ringing.
  1724. |
  1725. | created: 11-Nov-91
  1726. | history: 29-Dec-92 <chriswil> ported to NT.
  1727. |
  1728. \*---------------------------------------------------------------------------*/
  1729. VOID DoRing(LPCTSTR sound)
  1730. {
  1731. if(ChatState.fSound)
  1732. {
  1733. if(ChatState.fMMSound)
  1734. sndPlaySound(sound,SND_ASYNC);
  1735. else
  1736. MessageBeep(0);
  1737. }
  1738. return;
  1739. }
  1740. /*---------------------------------------------------------------------------*\
  1741. | DRAW SHADOW RECT
  1742. | This routine draws a shadow outline.
  1743. |
  1744. | created: 11-Nov-91
  1745. | history: 29-Dec-92 <chriswil> ported to NT.
  1746. |
  1747. \*---------------------------------------------------------------------------*/
  1748. VOID DrawShadowRect(HDC hdc, LPRECT rc)
  1749. {
  1750. HPEN hSavePen = SelectObject(hdc,hShadowPen);
  1751. MoveToEx(hdc,rc->left,rc->bottom,NULL);
  1752. LineTo(hdc,rc->left,rc->top );
  1753. LineTo(hdc,rc->right,rc->top );
  1754. SelectObject(hdc,hHilitePen);
  1755. LineTo(hdc,rc->right,rc->bottom);
  1756. LineTo(hdc,rc->left-1,rc->bottom);
  1757. SelectObject(hdc,hSavePen);
  1758. return;
  1759. }
  1760. #ifdef PROTOCOL_NEGOTIATE
  1761. /*---------------------------------------------------------------------------*\
  1762. | ANNOUNCE SUPPORT
  1763. | This routine announces to the partner what we support.
  1764. |
  1765. | created: 11-Nov-91
  1766. | history: 29-Dec-92 <chriswil> ported to NT.
  1767. |
  1768. \*---------------------------------------------------------------------------*/
  1769. VOID AnnounceSupport(VOID)
  1770. {
  1771. HDDEDATA hDdeData;
  1772. DWORD dummy;
  1773. if(ChatState.fConnected)
  1774. {
  1775. ChatData.type = CHT_PROTOCOL;
  1776. if(!ChatState.fIsServer)
  1777. {
  1778. hDdeData = CreateProtocolData();
  1779. if(hDdeData)
  1780. DdeClientTransaction((LPBYTE)hDdeData,(DWORD)-1L,ghConv,hszTextItem,cf_chatdata,XTYP_POKE,(DWORD)TIMEOUT_ASYNC,(LPDWORD)&dummy);
  1781. }
  1782. else
  1783. {
  1784. hszConvPartner = DdeCreateStringHandle(idInst,szConvPartner,0);
  1785. if(hszConvPartner)
  1786. DdePostAdvise(idInst,hszChatTopic,hszConvPartner);
  1787. }
  1788. ChatState.fProtocolSent = TRUE;
  1789. }
  1790. return;
  1791. }
  1792. #endif
  1793. /*---------------------------------------------------------------------------*\
  1794. | START INI-FILE MAPPING
  1795. | This routines sets the private-profile settings to go to the registry on\
  1796. | a per-user basis.
  1797. |
  1798. |
  1799. \*---------------------------------------------------------------------------*/
  1800. VOID StartIniMapping(VOID)
  1801. {
  1802. HKEY hKey1,hKey2,hKey3,hKeySnd;
  1803. DWORD dwDisp,dwSize;
  1804. if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,szIniSection,0,NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&hKey1,&dwDisp) == ERROR_SUCCESS)
  1805. {
  1806. if(dwDisp == REG_CREATED_NEW_KEY)
  1807. {
  1808. RegSetValueEx(hKey1,TEXT("Preferences"),0,REG_SZ,(LPBYTE)szIniKey1,ByteCountOf(lstrlen(szIniKey1)+1));
  1809. RegSetValueEx(hKey1,TEXT("Font") ,0,REG_SZ,(LPBYTE)szIniKey2,ByteCountOf(lstrlen(szIniKey2)+1));
  1810. }
  1811. if(RegCreateKeyEx(HKEY_CURRENT_USER,TEXT("Software\\Microsoft\\Winchat"),0,NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&hKey1,&dwDisp) == ERROR_SUCCESS)
  1812. {
  1813. if(dwDisp == REG_CREATED_NEW_KEY)
  1814. {
  1815. RegCreateKeyEx(HKEY_CURRENT_USER,TEXT("Software\\Microsoft\\Winchat\\Preferences"),0,NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&hKey2,&dwDisp);
  1816. RegCreateKeyEx(HKEY_CURRENT_USER,TEXT("Software\\Microsoft\\Winchat\\Font") ,0,NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&hKey3,&dwDisp);
  1817. RegCloseKey(hKey2);
  1818. RegCloseKey(hKey3);
  1819. }
  1820. }
  1821. RegCloseKey(hKey1);
  1822. }
  1823. // The sndPlaySound() first looks in the registry for the wav-files. The
  1824. // NT version doesn't have these here at setup, so Winchat will write out
  1825. // the defaults when the strings don't exist. This will allow uses to change
  1826. // sounds for ringing-in and ringing-out.
  1827. //
  1828. if(RegOpenKeyEx(HKEY_CURRENT_USER,TEXT("Control Panel\\Sounds"),0,KEY_WRITE | KEY_QUERY_VALUE,&hKeySnd) == ERROR_SUCCESS)
  1829. {
  1830. dwSize = 0;
  1831. dwDisp = REG_SZ;
  1832. if(RegQueryValueEx(hKeySnd,TEXT("RingIn"),NULL,&dwDisp,NULL,&dwSize) != ERROR_SUCCESS)
  1833. {
  1834. if(dwSize == 0)
  1835. {
  1836. // Set the wav-file values. Add (1) extra count to account for the null
  1837. // terminator.
  1838. //
  1839. RegSetValueEx(hKeySnd,TEXT("RingIn") ,0,REG_SZ,(LPBYTE)szIniRingIn ,ByteCountOf(lstrlen(szIniRingIn)+1));
  1840. RegSetValueEx(hKeySnd,TEXT("RingOut"),0,REG_SZ,(LPBYTE)szIniRingOut,ByteCountOf(lstrlen(szIniRingOut)+1));
  1841. }
  1842. }
  1843. RegCloseKey(hKeySnd);
  1844. }
  1845. return;
  1846. }
  1847. /*---------------------------------------------------------------------------*\
  1848. | END INI-FILE MAPPING
  1849. | This routines ends the ini-file mapping. It doesn't do anything at this
  1850. | point, but I've kept it in for some reason.
  1851. |
  1852. |
  1853. \*---------------------------------------------------------------------------*/
  1854. VOID EndIniMapping(VOID)
  1855. {
  1856. return;
  1857. }