Leaked source code of windows server 2003
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.

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