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.

1356 lines
41 KiB

  1. /************************************************************/
  2. /* Windows Write, Copyright 1985-1992 Microsoft Corporation */
  3. /************************************************************/
  4. #define NOGDICAPMASKS
  5. #define NOSYSMETRICS
  6. #define NOMENUS
  7. #define NOSOUND
  8. #define NOCOMM
  9. #define NOOPENFILE
  10. #define NORESOURCE
  11. #include <windows.h>
  12. #include "mw.h"
  13. #include "winddefs.h"
  14. #include "cmddefs.h"
  15. #include "wwdefs.h"
  16. #include "dispdefs.h"
  17. #include "docdefs.h"
  18. #include "debug.h"
  19. #if defined(OLE)
  20. #include "obj.h"
  21. #endif
  22. #ifdef PENWIN
  23. #define WM_PENWINFIRST 0x0380 // Remove when #define WIN31
  24. #include <penwin.h>
  25. int vcFakeMessage = 0;
  26. extern HCURSOR vhcPen; /* handle to pen cursor */
  27. extern int (FAR PASCAL *lpfnProcessWriting)(HWND, LPRC);
  28. extern VOID (FAR PASCAL *lpfnPostVirtualKeyEvent)(WORD, BOOL);
  29. extern VOID (FAR PASCAL *lpfnTPtoDP)(LPPOINT, int);
  30. extern BOOL (FAR PASCAL *lpfnCorrectWriting)(HWND, LPSTR, int, LPRC, DWORD, DWORD);
  31. extern BOOL (FAR PASCAL *lpfnSymbolToCharacter)(LPSYV, int, LPSTR, LPINT);
  32. VOID NEAR PASCAL PostCharacter(WORD wch);
  33. VOID NEAR PASCAL SendVirtKeyShift(WORD wVk, BYTE bFlags);
  34. VOID NEAR PASCAL SetSelection(HWND hWnd, LPPOINT lpPtFirst, LPPOINT lpPtLast, WORD wParam);
  35. int NEAR PASCAL WGetClipboardText(HWND hwndOwner, LPSTR lpsz, int cbSzSize);
  36. VOID NEAR PASCAL ClearAppQueue(VOID);
  37. #define VKB_SHIFT 0x01
  38. #define VKB_CTRL 0x02
  39. #define VKB_ALT 0x04
  40. #endif
  41. extern HWND vhWnd;
  42. extern HCURSOR vhcArrow;
  43. extern HCURSOR vhcIBeam;
  44. extern HCURSOR vhcBarCur;
  45. extern struct WWD rgwwd[];
  46. extern struct WWD *pwwdCur;
  47. extern HANDLE hMmwModInstance; /* handle to own module instance */
  48. extern int vfShiftKey;
  49. extern int vfCommandKey;
  50. extern int vfOptionKey;
  51. extern int vfDoubleClick;
  52. extern struct SEL selCur;
  53. extern long rgbBkgrnd;
  54. extern long rgbText;
  55. extern HBRUSH hbrBkgrnd;
  56. extern long ropErase;
  57. int vfCancelPictMove = FALSE;
  58. BOOL vfEraseWw = FALSE;
  59. long FAR PASCAL MdocWndProc(HWND, unsigned, WORD, LONG);
  60. void MdocCreate(HWND, LONG);
  61. void MdocSize(HWND, int, int, WORD);
  62. void MdocGetFocus(HWND, HWND);
  63. void MdocLoseFocus(HWND, HWND);
  64. void MdocMouse(HWND, unsigned, WORD, POINT);
  65. void MdocTimer(HWND, WORD);
  66. #if defined(JAPAN) & defined(DBCS_IME)
  67. #include <ime.h>
  68. extern BOOL bGetFocus;
  69. extern BOOL bImeFontEx;
  70. // for Non_PeekMessage mode in 'FImportantMsgPresent()'. [yutakan]
  71. BOOL bImeCnvOpen = FALSE;
  72. BOOL bSendFont = FALSE;
  73. BOOL GetIMEOpen(HWND);
  74. #endif
  75. #if defined(JAPAN) & defined(IME_HIDDEN) //IME3.1J
  76. //IR_UNDETERMINE
  77. extern typeCP selUncpFirst;
  78. extern typeCP selUncpLim;
  79. extern int vfImeHidden; /*ImeHidden Mode flag*/
  80. #endif
  81. #ifdef PENWIN
  82. // Helper routines to get events into system. Would be better (more efficient) if
  83. // could just call routines to set selection, copy, etc,
  84. // but this is the easiest way without touching any internals
  85. // Minics penwin internal routine, exception messages are posted instead
  86. // of sent since Write does a lot of peek ahead
  87. VOID NEAR PASCAL SetSelection(HWND hWnd,
  88. LPPOINT lpPtFirst, LPPOINT lpPtLast, WORD wParam)
  89. {
  90. static LONG lFirst = 0L;
  91. if (lpPtFirst)
  92. {
  93. (*lpfnTPtoDP)(lpPtFirst, 1);
  94. ScreenToClient(hWnd, lpPtFirst);
  95. }
  96. if (lpPtLast != NULL)
  97. {
  98. (*lpfnTPtoDP)(lpPtLast, 1);
  99. ScreenToClient(hWnd, lpPtLast);
  100. }
  101. if (lpPtFirst)
  102. {
  103. lFirst = MAKELONG(lpPtFirst->x, lpPtFirst->y);
  104. PostMessage(hWnd, WM_LBUTTONDOWN, wParam, lFirst);
  105. if (lpPtLast)
  106. {
  107. LONG lLast = MAKELONG(lpPtLast->x, lpPtLast->y);
  108. PostMessage(hWnd, WM_MOUSEMOVE, wParam, lLast);
  109. vcFakeMessage++;
  110. PostMessage(hWnd, WM_LBUTTONUP, wParam, lLast);
  111. }
  112. else
  113. {
  114. PostMessage(hWnd, WM_LBUTTONUP, wParam, lFirst);
  115. vcFakeMessage++;
  116. }
  117. }
  118. else // doubleclick
  119. {
  120. PostMessage(hWnd, WM_LBUTTONDBLCLK, wParam, lFirst);
  121. vcFakeMessage++;
  122. PostMessage(hWnd, WM_LBUTTONUP, wParam, lFirst);
  123. vcFakeMessage++;
  124. }
  125. }
  126. /*
  127. PURPOSE: Map a symbol value to a set of virtual keystrokes and then
  128. send the virtual keystrokes.
  129. TODO: Add real mapping of symbol values instead of assuming ANSI values
  130. Right now, this routine is worthless
  131. RETURN:
  132. GLOBALS:
  133. CONDITIONS: Kanji is not handled now, but could be.
  134. */
  135. VOID NEAR PASCAL PostCharacter(WORD wch)
  136. {
  137. int iVk = VkKeyScan(LOBYTE(wch));
  138. WORD wVk = (WORD)LOBYTE(iVk);
  139. char bFl = HIBYTE(iVk);
  140. if ((wVk != -1))
  141. SendVirtKeyShift(wVk, bFl);
  142. }
  143. /*--------------------------------------------------------------------------
  144. PURPOSE: Send an optionally shifted key sequence as system events
  145. RETURN: nothing
  146. GLOBALS:
  147. CONDITIONS: see flags in mspen.h
  148. */
  149. VOID NEAR PASCAL SendVirtKeyShift(WORD wVk, BYTE bFlags)
  150. {
  151. // send DOWN events:
  152. if (bFlags & VKB_SHIFT)
  153. (*lpfnPostVirtualKeyEvent)(VK_SHIFT, fFalse);
  154. if (bFlags & VKB_CTRL)
  155. (*lpfnPostVirtualKeyEvent)(VK_CONTROL, fFalse);
  156. if (bFlags & VKB_ALT)
  157. (*lpfnPostVirtualKeyEvent)(VK_MENU, fFalse);
  158. (*lpfnPostVirtualKeyEvent)(wVk, fFalse);
  159. // send UP events (in opposite order):
  160. (*lpfnPostVirtualKeyEvent)(wVk, fTrue);
  161. if (bFlags & VKB_ALT)
  162. (*lpfnPostVirtualKeyEvent)(VK_MENU, fTrue);
  163. if (bFlags & VKB_CTRL)
  164. (*lpfnPostVirtualKeyEvent)(VK_CONTROL, fTrue);
  165. if (bFlags & VKB_SHIFT)
  166. (*lpfnPostVirtualKeyEvent)(VK_SHIFT, fTrue);
  167. }
  168. /* Fill buffer with contents of clipboard
  169. */
  170. int NEAR PASCAL WGetClipboardText(HWND hwndOwner, LPSTR lpsz, int cbSzSize)
  171. {
  172. HANDLE hClip;
  173. int wLen = 0;
  174. OpenClipboard(hwndOwner);
  175. if (hClip = GetClipboardData(CF_TEXT))
  176. {
  177. LPSTR lpszClip = (LPSTR)GlobalLock(hClip);
  178. if (lpsz && cbSzSize > 0)
  179. {
  180. wLen = lstrlen(lpszClip);
  181. if (wLen > cbSzSize)
  182. lpszClip[cbSzSize-1] = 0;
  183. lstrcpy(lpsz, lpszClip);
  184. }
  185. GlobalUnlock(hClip);
  186. }
  187. #ifdef KKBUGFIX
  188. else
  189. *lpsz = '\0';
  190. #endif
  191. CloseClipboard();
  192. return wLen;
  193. }
  194. /*--------------------------------------------------------------------------
  195. PURPOSE: Dispatches any messages currently pending in our queue
  196. RETURN: nothing
  197. GLOBALS:
  198. CONDITIONS:
  199. */
  200. VOID NEAR PASCAL ClearAppQueue(VOID)
  201. {
  202. MSG msg;
  203. while (PeekMessage(&msg, (HWND)NULL, NULL, NULL, PM_REMOVE))
  204. {
  205. TranslateMessage(&msg);
  206. DispatchMessage(&msg);
  207. }
  208. }
  209. #endif
  210. static RECT rSaveInv;
  211. long FAR PASCAL MdocWndProc(hWnd, message, wParam, lParam)
  212. HWND hWnd;
  213. unsigned message;
  214. WORD wParam;
  215. LONG lParam;
  216. {
  217. extern int vfCloseFilesInDialog;
  218. extern BOOL fPrinting;
  219. long lReturn=0L;
  220. #ifdef PENWIN
  221. static cCharSent;
  222. #endif
  223. /* if IME Window mode is MCW_HIDDEN then IME don't send IR_OPENCONVERT.
  224. so I add this routine. */
  225. #ifdef PENWIN
  226. if (message < WM_CUT || message == WM_RCRESULT)
  227. #else
  228. if (message < WM_CUT )
  229. #endif
  230. {
  231. switch (message)
  232. {
  233. default:
  234. goto DefaultProc;
  235. /* For each of following mouse window messages, wParam contains
  236. ** bits indicating whether or not various virtual keys are down,
  237. ** and lParam is a POINT containing the mouse coordinates. The
  238. ** keydown bits of wParam are: MK_LBUTTON (set if Left Button is
  239. ** down); MK_RBUTTON (set if Right Button is down); MK_SHIFT (set
  240. ** if Shift Key is down); MK_ALTERNATE (set if Alt Key is down);
  241. ** and MK_CONTROL (set if Control Key is down). */
  242. case WM_LBUTTONDBLCLK:
  243. #ifdef PENWIN
  244. if (vcFakeMessage > 0)
  245. vcFakeMessage--;
  246. // fall through
  247. #endif
  248. case WM_LBUTTONUP:
  249. case WM_MOUSEMOVE:
  250. case WM_LBUTTONDOWN:
  251. MdocMouse(hWnd, message, wParam, MAKEPOINT(lParam));
  252. break;
  253. #ifdef PENWIN
  254. case WM_RCRESULT:
  255. {
  256. LPRCRESULT lpr = (LPRCRESULT)lParam;
  257. LPPOINT lpPntHot;
  258. LPPOINT lpPntHot2;
  259. if( (lpr->wResultsType&(RCRT_ALREADYPROCESSED|RCRT_NOSYMBOLMATCH))!=0 || lpr->lpsyv==NULL
  260. || lpr->cSyv == 0)
  261. return( FALSE );
  262. if (lpr->wResultsType&RCRT_GESTURE)
  263. {
  264. SYV syv = *(lpr->lpsyv);
  265. vcFakeMessage = 0;
  266. lpPntHot = lpr->syg.rgpntHotSpots;
  267. lpPntHot2 = lpr->syg.cHotSpot > 1 ? lpr->syg.rgpntHotSpots + 1: NULL;
  268. switch ( LOWORD(syv))
  269. {
  270. case LOWORD( SYV_EXTENDSELECT ):
  271. SetSelection(hWnd, lpPntHot, NULL, MK_SHIFT); // extend sel
  272. break;
  273. case LOWORD( SYV_CLEARWORD ): // dbl click & drag
  274. if (lpPntHot2)
  275. {
  276. SetSelection(hWnd, lpPntHot, NULL, 0);
  277. SetSelection(hWnd, NULL, NULL, 0); // dblclick selects word
  278. }
  279. SendVirtKeyShift(VK_DELETE, 0);
  280. break;
  281. case LOWORD( SYV_COPY):
  282. case LOWORD( SYV_CLEAR ):
  283. case LOWORD( SYV_CUT ):
  284. if ( selCur.cpFirst == selCur.cpLim && (lpr->wResultsType&RCRT_GESTURETRANSLATED)==0)
  285. {
  286. SetSelection(hWnd, lpPntHot, NULL, 0);
  287. if (syv != SYV_CLEAR)
  288. SetSelection(hWnd, NULL, NULL, 0); // dblclick
  289. }
  290. switch ( LOWORD(syv))
  291. {
  292. case LOWORD( SYV_COPY):
  293. SendVirtKeyShift(VK_INSERT, VKB_CTRL);
  294. break;
  295. case LOWORD( SYV_CLEAR ):
  296. SendVirtKeyShift(VK_DELETE, 0);
  297. break;
  298. case LOWORD( SYV_CUT ):
  299. SendVirtKeyShift(VK_DELETE, VKB_SHIFT);
  300. break;
  301. }
  302. break;
  303. case LOWORD( SYV_PASTE ):
  304. if ((lpr->wResultsType&RCRT_GESTURETRANSLATED)==0)
  305. SetSelection(hWnd, lpPntHot, NULL, 0);
  306. SendVirtKeyShift(VK_INSERT, VKB_SHIFT);
  307. break;
  308. case LOWORD( SYV_UNDO):
  309. SendVirtKeyShift(VK_BACK, VKB_ALT);
  310. break;
  311. case LOWORD(SYV_BACKSPACE):
  312. case LOWORD(SYV_SPACE):
  313. case LOWORD(SYV_RETURN):
  314. case LOWORD(SYV_TAB):
  315. SetSelection(hWnd, lpPntHot, NULL, 0);
  316. PostCharacter(LOWORD(*(lpr->lpsyv))&0x00ff);
  317. break;
  318. #if defined(KKBUGFIX) && !defined(KOREA)
  319. case LOWORD( SYV_CORRECT ):
  320. case LOWORD( SYV_KKCONVERT ):
  321. {
  322. WORD wLen;
  323. HANDLE hMem = NULL;
  324. LPSTR lpstr;
  325. LPSTR lpsz;
  326. BOOL fDoubleClickSent = fFalse;
  327. DWORD dwFlags = NULL;
  328. DWORD dwReserved = NULL;
  329. POINT pt;
  330. extern int vxpCursLine;
  331. extern int vypCursLine;
  332. #define cbCorrectMax 128
  333. // Strategy: If no selection, send in a double click to
  334. // select a word. Then copy selection to clipboard
  335. // read off of clipboard. Call CorrectWriting, and
  336. // but changed text in clipboard and then paste
  337. // from clipboard.
  338. if ( selCur.cpFirst == selCur.cpLim )
  339. {
  340. if (LOWORD(syv) == LOWORD(SYV_KKCONVERT))
  341. {
  342. SetSelection(hWnd, lpPntHot, lpPntHot2, 0);
  343. }
  344. else
  345. {
  346. // No selection so send double click
  347. SetSelection(hWnd, lpPntHot, NULL, 0); // set caret
  348. SetSelection(hWnd, NULL, NULL, 0); // dblclick
  349. }
  350. fDoubleClickSent = fTrue;
  351. ClearAppQueue();
  352. }
  353. SendMessage(hWnd, WM_COPY, 0, 0L);
  354. hMem = GlobalAlloc(GMEM_MOVEABLE, (DWORD)cbCorrectMax);
  355. if (hMem == NULL || (lpsz = (LPSTR)GlobalLock(hMem)) == NULL)
  356. return 1; // Just bag out for now: should add error message
  357. wLen = WGetClipboardText(hWnd, lpsz, cbCorrectMax);
  358. if (LOWORD(syv) == LOWORD(SYV_KKCONVERT) && wLen == 0)
  359. {
  360. beep();
  361. return 1;
  362. }
  363. if (IsClipboardFormatAvailable(CF_TEXT) || wLen == 0)
  364. {
  365. if (wLen < cbCorrectMax)
  366. {
  367. if (LOWORD(syv) == LOWORD(SYV_KKCONVERT))
  368. {
  369. dwFlags = CWR_KKCONVERT | CWR_SIMPLE;
  370. pt.x = vxpCursLine;
  371. pt.y = vypCursLine;
  372. ClientToScreen(hWnd, &pt);
  373. dwReserved = MAKELONG(pt.x, pt.y);
  374. }
  375. // Only bring up corrector if selection wasn't too big
  376. if ((*lpfnCorrectWriting)(hWnd, lpsz, cbCorrectMax, NULL, dwFlags, dwReserved))
  377. {
  378. if (*lpsz==0)
  379. {
  380. // User deleted all text in correction
  381. SendVirtKeyShift(VK_DELETE, 0);
  382. }
  383. else if (LOWORD(syv) == LOWORD(SYV_CORRECT))
  384. {
  385. GlobalUnlock(hMem);
  386. OpenClipboard(GetParent(hWnd)); // Use parent as
  387. // owner to circumvent write's short check
  388. // cuts if it is owner of clipboard
  389. EmptyClipboard();
  390. SetClipboardData(CF_TEXT, hMem);
  391. CloseClipboard();
  392. hMem = NULL;
  393. SendMessage(hWnd, WM_PASTE, 0, 0L);
  394. UpdateWindow(hWnd);
  395. }
  396. }
  397. else if (fDoubleClickSent)
  398. {
  399. // Need to clear bogus selection. Just send in a tap.
  400. SetSelection(hWnd, lpPntHot, NULL, 0);
  401. }
  402. }
  403. }
  404. if (hMem) // may never have been alloc'd if user canceled
  405. {
  406. GlobalUnlock(hMem);
  407. GlobalFree(hMem);
  408. }
  409. }
  410. break;
  411. #else // KKBUGFIX
  412. case LOWORD( SYV_CORRECT ):
  413. {
  414. WORD wLen;
  415. HANDLE hMem = NULL;
  416. LPSTR lpstr;
  417. LPSTR lpsz;
  418. BOOL fDoubleClickSent = fFalse;
  419. #define cbCorrectMax 128
  420. // Strategy: If no selection, send in a double click to
  421. // select a word. Then copy selection to clipboard
  422. // read off of clipboard. Call CorrectWriting, and
  423. // but changed text in clipboard and then paste
  424. // from clipboard.
  425. if ( selCur.cpFirst == selCur.cpLim )
  426. {
  427. // No selection so send double click
  428. SetSelection(hWnd, lpPntHot, NULL, 0); // set caret
  429. SetSelection(hWnd, NULL, NULL, 0); // dblclick
  430. fDoubleClickSent = fTrue;
  431. ClearAppQueue();
  432. }
  433. SendMessage(hWnd, WM_COPY, 0, 0L);
  434. if (IsClipboardFormatAvailable(CF_TEXT))
  435. {
  436. hMem = GlobalAlloc(GMEM_MOVEABLE, (DWORD)cbCorrectMax);
  437. if (hMem == NULL || (lpsz = (LPSTR)GlobalLock(hMem)) == NULL)
  438. return 1; // Just bag out for now: should add error message
  439. if (WGetClipboardText(hWnd, lpsz, cbCorrectMax) < cbCorrectMax)
  440. {
  441. // Only bring up corrector if selection wasn't too big
  442. if ((*lpfnCorrectWriting)(hWnd, lpsz, cbCorrectMax, NULL, 0, 0))
  443. {
  444. if (*lpsz==0)
  445. {
  446. // User deleted all text in correction
  447. SendVirtKeyShift(VK_DELETE, 0);
  448. }
  449. else
  450. {
  451. GlobalUnlock(hMem);
  452. OpenClipboard(GetParent(hWnd)); // Use parent as
  453. // owner to circumvent write's short check
  454. // cuts if it is owner of clipboard
  455. EmptyClipboard();
  456. SetClipboardData(CF_TEXT, hMem);
  457. CloseClipboard();
  458. hMem = NULL;
  459. SendMessage(hWnd, WM_PASTE, 0, 0L);
  460. UpdateWindow(hWnd);
  461. }
  462. }
  463. else if (fDoubleClickSent)
  464. {
  465. // Need to clear bogus selection. Just send in a tap.
  466. SetSelection(hWnd, lpPntHot, NULL, 0);
  467. }
  468. }
  469. if (hMem) // may never have been alloc'd if user canceled
  470. {
  471. GlobalUnlock(hMem);
  472. GlobalFree(hMem);
  473. }
  474. }
  475. }
  476. break;
  477. #endif // KKBUGFIX
  478. default:
  479. return( FALSE );
  480. }
  481. }
  482. else // Not a gesture,see if normal characters
  483. {
  484. #define cbTempBufferSize 128
  485. char rgch[cbTempBufferSize+2];
  486. int cb=0;
  487. int cbT;
  488. LPSTR lpstr = (LPSTR)lpr->lpsyv;
  489. typeCP cp=cp0;
  490. LPSYV lpsyv;
  491. LPSYV lpsyvEnd;
  492. extern int docScrap;
  493. extern int vfScrapIsPic;
  494. extern struct PAP *vppapNormal;
  495. extern struct CHP vchpNormal;
  496. vfScrapIsPic = fFalse;
  497. ClobberDoc( docScrap, docNil, cp0, cp0 );
  498. // Replace CR with LF's These are treated as EOLs
  499. // by CchReadLineExt. Then, before inserting
  500. // buffer, change all LFs to CR LFs as write expects
  501. // Will work for Kanji
  502. for (lpsyv=lpr->lpsyv, lpsyvEnd=&lpr->lpsyv[lpr->cSyv+1];
  503. lpsyv<lpsyvEnd; lpsyv++)
  504. {
  505. if (*lpsyv == SyvCharacterToSymbol(0xD))
  506. {
  507. *lpstr++ = 0xd;
  508. *lpstr++ = 0xa;
  509. cb+=2;
  510. }
  511. else
  512. {
  513. (*lpfnSymbolToCharacter)(lpsyv, 1, lpstr, &cbT);
  514. lpstr += cbT;
  515. cb += cbT;
  516. }
  517. }
  518. lpstr = (LPSTR)lpr->lpsyv;
  519. Assert(cb>0 && lpstr[cb-1] == 0);
  520. // This code is abstracted for FReadExtScrap where it copies
  521. // text from clipboard into the scrap document. We do similar.
  522. // copy result into scrap and then insert scrap with
  523. // no formating.
  524. while (cb > 0)
  525. {
  526. struct PAP *ppap=NULL;
  527. int fEol;
  528. unsigned cch=min(cb, cbTempBufferSize);
  529. if ((cch = CchReadLineExt((LPCH) lpstr, cch, rgch, &fEol))==0)
  530. /* Reached terminator */
  531. break;
  532. if (fEol)
  533. ppap = vppapNormal;
  534. InsertRgch(docScrap, cp, rgch, cch, &vchpNormal, ppap);
  535. cb -= cch;
  536. cp += (typeCP) cch;
  537. lpstr += cch;
  538. }
  539. CmdInsScrap(fTrue);
  540. }
  541. }
  542. return TRUE;
  543. #endif // PENWIN
  544. #if defined(OLE)
  545. case WM_DROPFILES:
  546. /* We got dropped on, so bring ourselves to the top */
  547. BringWindowToTop(hParentWw);
  548. ObjGetDrop(wParam,FALSE);
  549. break;
  550. #endif
  551. case WM_TIMER:
  552. /* Timer message. wParam contains the timer ID value */
  553. #if defined(JAPAN) & defined(DBCS_IME) //01/19/93
  554. if(bSendFont == TRUE) {
  555. SetImeFont(hWnd);
  556. bSendFont = FALSE;
  557. }
  558. if(bImeCnvOpen == TRUE) { //03/08/93 #4687 T-HIROYN
  559. if(FALSE == GetIMEOpen(hWnd))
  560. bImeCnvOpen = FALSE;
  561. }
  562. #endif
  563. MdocTimer(hWnd, wParam);
  564. break;
  565. case WM_CREATE:
  566. /* Window's being created; lParam contains lpParam field
  567. ** passed to CreateWindow */
  568. SetRectEmpty(&rSaveInv);
  569. MdocCreate(hWnd, lParam);
  570. #if defined(JAPAN) & defined(DBCS_IME) //IME3.1J
  571. bImeFontEx = FALSE;
  572. #if defined(IME_HIDDEN)
  573. vfImeHidden = 0;
  574. #endif
  575. if(TRUE == GetIMEVersioOk(hWnd)) {
  576. //IME_SETCONVERSIONFONTEX use OK ?
  577. if(TRUE == GetIMESupportFontEx(hWnd))
  578. bImeFontEx = TRUE;
  579. #if defined(IME_HIDDEN)
  580. vfImeHidden = 1;
  581. #endif
  582. }
  583. SetFocus(hWnd); //03/29/93 after TestWordCnv (INITMMW.C)
  584. // WM_SETFOCUS dose not come.
  585. #endif
  586. break;
  587. case WM_SIZE:
  588. /* Window's size is changing. lParam contains the height
  589. ** and width, in the low and high words, respectively.
  590. ** wParam contains SIZENORMAL for "normal" size changes,
  591. ** SIZEICONIC when the window is being made iconic, and
  592. ** SIZEFULLSCREEN when the window is being made full screen. */
  593. MdocSize(hWnd, LOWORD(lParam), HIWORD(lParam), wParam);
  594. break;
  595. case WM_PAINT:
  596. #if defined(OLE)
  597. if (nBlocking || fPrinting)
  598. // this'll reduce async problems
  599. {
  600. PAINTSTRUCT Paint;
  601. RECT rTmp=rSaveInv;
  602. BeginPaint(hWnd,&Paint);
  603. UnionRect(&rSaveInv,&rTmp,&Paint.rcPaint);
  604. EndPaint(hWnd,&Paint);
  605. break;
  606. }
  607. #endif
  608. /* Time for the window to draw itself. */
  609. UpdateInvalid();
  610. UpdateDisplay( FALSE );
  611. break;
  612. case WM_SETFOCUS:
  613. /* The window is getting the focus. wParam contains the window
  614. ** handle of the window that previously had the focus. */
  615. #if defined(JAPAN) & defined(DBCS_IME)
  616. // If we're getting input focus, we have to get current status of IME convert
  617. // window, and initialize 'bImeCnvOpen'. [yutakan:07/15/91]
  618. //
  619. #if 1 //#3221 01/25/93
  620. if(TRUE == GetIMEOpen(hWnd)) {
  621. bImeCnvOpen = TRUE;
  622. if (TRUE == SendIMEVKFLUSHKey(hWnd)) //Win3.1J t-hiroyn
  623. bImeCnvOpen = FALSE;
  624. } else
  625. bImeCnvOpen = FALSE;
  626. #else
  627. /* If err return, supporse IME is not enalble.*/
  628. if(TRUE == GetIMEOpen(hWnd)) {
  629. bImeCnvOpen = TRUE;
  630. } else
  631. bImeCnvOpen = FALSE;
  632. #endif
  633. bGetFocus = TRUE;
  634. //T-HIROYN add
  635. bImeFontEx = FALSE;
  636. if(TRUE == GetIMEVersioOk(hWnd)) {
  637. //IME_SETCONVERSIONFONTEX use OK ?
  638. if(TRUE == GetIMESupportFontEx(hWnd))
  639. bImeFontEx = TRUE;
  640. }
  641. #endif
  642. MdocGetFocus(hWnd, (HWND)wParam);
  643. break;
  644. case WM_KILLFOCUS:
  645. /* The window is losing the focus. wParam contains the window
  646. ** handle of the window about to get the focus, or NULL. */
  647. #if defined(JAPAN) & defined(DBCS_IME)
  648. /* If we're losing input focus, we have to clear OpenStatus of convertwindow,
  649. ** 'bImeCnvOpen'. [yutakan:07/15/91]
  650. */
  651. bImeCnvOpen = FALSE;
  652. bGetFocus = FALSE;
  653. #if defined(JAPAN) & defined(IME_HIDDEN) //IME3.1J
  654. //IME3.1J IR_UNDETERMINE
  655. if(selUncpFirst < selUncpLim) {
  656. UndetermineToDetermine(hWnd);
  657. }
  658. #endif
  659. SendIMEVKFLUSHKey(hWnd); //Win3.1J t-hiroyn
  660. #endif
  661. MdocLoseFocus(hWnd, (HWND)wParam);
  662. /* Since we might be moving/sizing a picture, set flag to
  663. ** cancel this. */
  664. vfCancelPictMove = TRUE;
  665. break;
  666. #if defined(JAPAN) & defined(DBCS_IME)
  667. case WM_IME_REPORT:
  668. /* if IME convert window has been opened,
  669. ** we're getting into Non PeekMessage
  670. ** Mode at 'FImportantMsgPresent()'
  671. */
  672. #if defined(JAPAN) & defined(IME_HIDDEN) //IME3.1J
  673. //IR_UNDETERMINE
  674. if(wParam == IR_UNDETERMINE) {
  675. LONG GetIRUndetermin(HWND, LPARAM); //clipbrd2.c
  676. return(GetIRUndetermin(hWnd, lParam));
  677. }
  678. #endif
  679. if(wParam == IR_IMESELECT) {
  680. bImeFontEx = FALSE;
  681. if(TRUE == GetIMEVersioOk(hWnd)) {
  682. //IME_SETCONVERSIONFONTEX use OK ?
  683. if(TRUE == GetIMESupportFontEx(hWnd))
  684. bImeFontEx = TRUE;
  685. }
  686. }
  687. if (wParam == IR_STRING) {
  688. #if 0 //t-hiroyn
  689. // Do nothing with IR_STRING // Yutakan
  690. break;
  691. /* put string from KKC to scrap */
  692. // PutImeString(hWnd, LOWORD(lParam)); // need more bug fix.
  693. // return 1L;
  694. #endif
  695. LONG GetIRString(HWND, LPARAM); //clipbrd2.c
  696. return(GetIRString(hWnd, lParam));
  697. }
  698. //IR_STRINGEX New Win3.1J
  699. if(wParam == IR_STRINGEX) {
  700. LONG GetIRStringEx(HWND, LPARAM); //clipbrd2.c
  701. return(GetIRStringEx(hWnd, lParam));
  702. }
  703. if(wParam == IR_OPENCONVERT || wParam == IR_CHANGECONVERT) {
  704. bImeCnvOpen = TRUE;
  705. //IME3.1J
  706. if(wParam == IR_OPENCONVERT) {
  707. SetImeFont(hWnd);
  708. bSendFont = TRUE; //01/19/93
  709. }
  710. }
  711. if(wParam == IR_CLOSECONVERT) {
  712. bImeCnvOpen = FALSE;
  713. }
  714. if (wParam == IR_STRINGSTART) {
  715. HANDLE hMem;
  716. LPSTR lpText;
  717. if (hMem = GlobalAlloc(GMEM_MOVEABLE, 512L)) {
  718. if (lpText = GlobalLock(hMem)) {
  719. if (EatString(hWnd, (LPSTR)lpText, 512)) {
  720. ForceImeBlock(hWnd, TRUE); //T-HIROYN 3.1J
  721. PutImeString( hWnd, hMem );
  722. CmdInsIRString(); //T-HIROYN 3.1J
  723. ForceImeBlock(hWnd, FALSE); //T-HIROYN 3.1J
  724. }
  725. GlobalUnlock(hMem);
  726. }
  727. GlobalFree(hMem);
  728. }
  729. }
  730. goto DefaultProc;
  731. #endif
  732. }
  733. }
  734. else if (message < WM_USER)
  735. { /* Clipboard messages */
  736. if (!FMdocClipboardMsg( message, wParam, lParam ))
  737. goto DefaultProc;
  738. }
  739. else
  740. { /* Private WRITE messages */
  741. switch (message)
  742. {
  743. default:
  744. goto DefaultProc;
  745. #if defined(OLE)
  746. case WM_WAITFORSERVER:
  747. {
  748. extern int vfDeactByOtherApp;
  749. if (!hwndWait && !vfDeactByOtherApp)
  750. {
  751. vbCancelOK = TRUE;
  752. ((LPOBJINFO)lParam)->fCanKillAsync = wParam;
  753. ((LPOBJINFO)lParam)->fCompleteAsync = TRUE;
  754. DialogBoxParam(hMmwModInstance, (LPSTR)"DTWAIT", hParentWw, lpfnWaitForObject, ((LPOBJINFO)lParam)->lpobject);
  755. }
  756. }
  757. break;
  758. case WM_OBJUPDATE:
  759. ObjObjectHasChanged(wParam,(LPOLEOBJECT)lParam);
  760. break;
  761. case WM_OBJERROR:
  762. ObjReleaseError(wParam);
  763. break;
  764. case WM_OBJBADLINK:
  765. ObjHandleBadLink(wParam,(LPOLEOBJECT)lParam);
  766. break;
  767. case WM_OBJDELETE:
  768. ObjDeleteObject((LPOBJINFO)lParam,wParam);
  769. break;
  770. #endif
  771. case wWndMsgDeleteFile:
  772. /* wParam is a global handle to the file to be deleted */
  773. /* Return code: TRUE - Ok to delete
  774. FALSE - don't delete */
  775. lReturn = (LONG)FDeleteFileMessage( wParam );
  776. break;
  777. case wWndMsgRenameFile:
  778. /* wParam is a global handle to the file being renamed */
  779. /* LOWORD( lParam ) is a global handle to the new name */
  780. /* No return code */
  781. RenameFileMessage( wParam, LOWORD( lParam ) );
  782. break;
  783. }
  784. }
  785. goto Ret;
  786. DefaultProc: /* All messages not processed come here. */
  787. lReturn = DefWindowProc(hWnd, message, wParam, lParam);
  788. Ret:
  789. if (vfCloseFilesInDialog)
  790. CloseEveryRfn( FALSE );
  791. return lReturn;
  792. }
  793. void MdocMouse(hWnd, message, wParam, pt)
  794. HWND hWnd;
  795. unsigned message;
  796. WORD wParam;
  797. POINT pt;
  798. {
  799. extern int vfFocus;
  800. extern int vfDownClick;
  801. extern int vfMouseExist;
  802. extern HCURSOR vhcHourGlass;
  803. extern int vfInLongOperation;
  804. MSG msg;
  805. #if defined(JAPAN) & defined(IME_HIDDEN) //IME3.1J
  806. //IR_UNDETERMINE
  807. if(message == WM_LBUTTONDOWN || message == WM_LBUTTONDBLCLK) {
  808. if(selUncpFirst < selUncpLim) {
  809. UndetermineToDetermine(hWnd);
  810. }
  811. }
  812. #endif
  813. if (vfInLongOperation)
  814. {
  815. SetCursor(vhcHourGlass);
  816. return;
  817. }
  818. if (message == WM_MOUSEMOVE)
  819. {
  820. if (vfMouseExist)
  821. {
  822. HCURSOR hc;
  823. /* All we do on move moves is set the cursor. */
  824. if (pt.y < wwdCurrentDoc.ypMin)
  825. {
  826. hc = vhcArrow;
  827. }
  828. else
  829. {
  830. #ifdef PENWIN
  831. hc = (pt.x > xpSelBar ) ? vhcPen : vhcBarCur;
  832. #else
  833. hc = (pt.x > xpSelBar) ? vhcIBeam : vhcBarCur;
  834. #endif
  835. }
  836. SetCursor( hc );
  837. }
  838. return;
  839. }
  840. /* Save the state of the shift keys. */
  841. vfShiftKey = wParam & MK_SHIFT;
  842. vfCommandKey = wParam & MK_CONTROL;
  843. /* high bit returned from GetKeyState is 1 when the key is down, else
  844. it is up, the low bit is 1 if it is toggled */
  845. PeekMessage(&msg, (HWND)NULL, NULL, NULL, PM_NOREMOVE);
  846. vfOptionKey = GetKeyState(VK_MENU) < 0 ? true : false;
  847. vfDoubleClick = (message == WM_LBUTTONDBLCLK);
  848. if (message == WM_LBUTTONUP)
  849. {
  850. /* Windows demands this */
  851. if (vfDownClick && !vfFocus)
  852. {
  853. SetFocus( hWnd );
  854. vfDownClick = FALSE;
  855. }
  856. }
  857. else
  858. {
  859. extern int vfGotoKeyMode;
  860. vfGotoKeyMode = FALSE;
  861. /* WM_LBUTTONDOWN or WM_LBUTTONDBLCLK */
  862. vfDownClick = TRUE;
  863. #ifdef PENWIN
  864. #ifdef KKBUGFIX
  865. if( lpfnProcessWriting == NULL ||
  866. vfDoubleClick ||
  867. pt.x < xpSelBar )
  868. //Normal mouse processing
  869. DoContentHit(pt);
  870. else
  871. {
  872. if ((*lpfnProcessWriting)( hWnd, NULL ) < 0)
  873. //Normal mouse processing
  874. DoContentHit(pt);
  875. else
  876. // During recognition, caret blinking rate is destroyed
  877. SetTimer( hWnd, tidCaret, GetCaretBlinkTime(), (FARPROC)NULL );
  878. }
  879. #else
  880. if( lpfnProcessWriting == NULL ||
  881. vfDoubleClick ||
  882. pt.x < xpSelBar ||
  883. (*lpfnProcessWriting)( hWnd, NULL ) < 0
  884. )
  885. //Normal mouse processing
  886. DoContentHit(pt);
  887. #endif
  888. #else
  889. DoContentHit(pt);
  890. #endif
  891. }
  892. #ifdef JAPAN
  893. if(bImeCnvOpen)
  894. SetImeFont(hWnd);
  895. #endif
  896. }
  897. void MdocTimer(hWnd, id)
  898. HWND hWnd;
  899. WORD id;
  900. {
  901. extern int vfSkipNextBlink;
  902. extern int vfInsertOn;
  903. extern int vfFocus;
  904. #if defined(OLE)
  905. ++nGarbageTime;
  906. #endif
  907. /* A timer event has occurred with ID id. Process it here. */
  908. Assert( id == tidCaret ); /* Caret blink is the only timer event we know */
  909. if ( ( vhWnd != hWnd ) || /* Document window is not current */
  910. ( !vfFocus ) || /* Don't have the focus */
  911. ( wwdCurrentDoc.fDirty) ) /* dl's are not up to date */
  912. return;
  913. if ( vfSkipNextBlink )
  914. { /* We have been warned not to blank the cursor this time around */
  915. vfSkipNextBlink = FALSE;
  916. if ( vfInsertOn )
  917. return;
  918. }
  919. #if defined(OLE)
  920. if (nGarbageTime > GARBAGETIME)
  921. ObjCollectGarbage();
  922. #endif
  923. if ( selCur.cpFirst == selCur.cpLim )
  924. {
  925. /* We must use ToggleSel instead of DrawInsertLine because the */
  926. /* insert cp might not be on the screen & ToggleSel can */
  927. /* figure this out */
  928. extern int vypCursLine;
  929. extern int vdypCursLine;
  930. /* The following condition may not be true if we get a timer message
  931. after a size message but before a paint message; ypMac will
  932. have been adjusted but dlMac does not get adjusted to reflect
  933. the change until UpdateDisplay is called. We have violated the
  934. Windows dictate that ALL size-related calculations must occur
  935. in the Size proc and we must compensate here */
  936. if ( vypCursLine - vdypCursLine < wwdCurrentDoc.ypMac )
  937. {
  938. ToggleSel( selCur.cpFirst, selCur.cpFirst, !vfInsertOn );
  939. vfSkipNextBlink = FALSE;
  940. }
  941. }
  942. }
  943. void CatchupInvalid(HWND hWnd)
  944. {
  945. if (!nBlocking && !IsRectEmpty(&rSaveInv))
  946. {
  947. InvalidateRect(hWnd,&rSaveInv,FALSE);
  948. SetRectEmpty(&rSaveInv);
  949. }
  950. }
  951. #if defined(JAPAN) & defined(DBCS_IME)
  952. /*
  953. ** We want to get 'IME ConvertWindow OpenStatus' but IME_GETOPEN
  954. ** subfunction.
  955. ** now does not support 'wCount' in IMESTRUCT (will support in future).
  956. ** So this function will always return FALSE since wCount is always 0
  957. ** as we set it before do SendIMEMessage(). [yutakan:07/16/91]
  958. */
  959. BOOL GetIMEOpen(HWND hwnd)
  960. {
  961. LPIMESTRUCT lpmem;
  962. HANDLE hIMEBlock;
  963. int wRet;
  964. /* Get comunication area with IME */
  965. hIMEBlock=GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_LOWER,
  966. (DWORD)sizeof(IMESTRUCT));
  967. if(!hIMEBlock) return FALSE;
  968. lpmem = (LPIMESTRUCT)GlobalLock(hIMEBlock);
  969. lpmem->fnc = IME_GETOPEN;
  970. lpmem->wCount = 0; //01/25/93
  971. GlobalUnlock(hIMEBlock);
  972. if(FALSE == (MySendIMEMessageEx(hwnd,MAKELONG(hIMEBlock,NULL)))){
  973. wRet = FALSE; /* Error */
  974. }
  975. else
  976. wRet = TRUE; /* Success */
  977. //01/25/93
  978. if (lpmem = (LPIMESTRUCT)GlobalLock(hIMEBlock)) {
  979. if(wRet == TRUE && lpmem->wCount == 0)
  980. wRet = FALSE; //ok
  981. GlobalUnlock(hIMEBlock);
  982. }
  983. GlobalFree(hIMEBlock);
  984. return wRet;
  985. }
  986. //T_HIROYN
  987. //SendIMEMessageEx New3.1J
  988. MySendIMEMessageEx(HWND hwnd, LPARAM lParam)
  989. {
  990. return(SendIMEMessageEx(hwnd, lParam));
  991. // return(SendIMEMessage(hwnd, lParam));
  992. }
  993. BOOL GetIMEVersioOk(HWND hwnd)
  994. {
  995. LPIMESTRUCT lpmem;
  996. WORD wVersion;
  997. int wRet = FALSE;
  998. /* comunication area with IME */
  999. HANDLE hImeStruct;
  1000. /* Get comunication area with IME */
  1001. hImeStruct = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
  1002. (DWORD)sizeof(IMESTRUCT));
  1003. if( !hImeStruct )
  1004. return FALSE;
  1005. if(lpmem = (LPIMESTRUCT)GlobalLock(hImeStruct)) {
  1006. lpmem->fnc = IME_GETIMECAPS;
  1007. lpmem->wParam = IME_GETVERSION;
  1008. GlobalUnlock(hImeStruct);
  1009. if(FALSE == (MySendIMEMessageEx(hwnd,MAKELONG(hImeStruct,NULL)))) {
  1010. goto retVercheck;
  1011. }
  1012. }
  1013. if(lpmem = (LPIMESTRUCT)GlobalLock(hImeStruct)) {
  1014. lpmem->fnc = IME_GETVERSION;
  1015. GlobalUnlock(hImeStruct);
  1016. wVersion = MySendIMEMessageEx(hwnd,MAKELONG(hImeStruct,NULL));
  1017. if(wVersion >= 0x0a03)
  1018. wRet = TRUE;
  1019. else
  1020. wRet = FALSE;
  1021. }
  1022. retVercheck:
  1023. GlobalFree(hImeStruct);
  1024. return wRet;
  1025. }
  1026. BOOL GetIMESupportFontEx(HWND hwnd)
  1027. {
  1028. LPIMESTRUCT lpmem;
  1029. int wRet = FALSE;
  1030. /* comunication area with IME */
  1031. HANDLE hImeStruct;
  1032. /* Get comunication area with IME */
  1033. hImeStruct = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
  1034. (DWORD)sizeof(IMESTRUCT));
  1035. if( !hImeStruct )
  1036. return FALSE;
  1037. if(lpmem = (LPIMESTRUCT)GlobalLock(hImeStruct)) {
  1038. lpmem->fnc = IME_GETIMECAPS;
  1039. lpmem->wParam = IME_SETCONVERSIONFONTEX;
  1040. GlobalUnlock(hImeStruct);
  1041. if(TRUE == (MySendIMEMessageEx(hwnd,MAKELONG(hImeStruct,NULL)))) {
  1042. wRet = TRUE;
  1043. }
  1044. }
  1045. GlobalFree(hImeStruct);
  1046. return wRet;
  1047. }
  1048. #if defined(JAPAN) & defined(IME_HIDDEN) //IME3.1J
  1049. BOOL GetIMEOpenMode(HWND hwnd)
  1050. {
  1051. LPIMESTRUCT lpmem;
  1052. int wRet = TRUE;
  1053. /* comunication area with IME */
  1054. extern HANDLE hImeMem;
  1055. if (lpmem = (LPIMESTRUCT)GlobalLock(hImeMem)) {
  1056. lpmem->fnc = IME_GETOPEN;
  1057. lpmem->wCount = 0;
  1058. GlobalUnlock(hImeMem);
  1059. if(0 == (MySendIMEMessageEx(hwnd,MAKELONG(hImeMem,NULL))))
  1060. wRet = FALSE; /* close ok */
  1061. else
  1062. wRet = TRUE; /* open ok ? */
  1063. }
  1064. if (lpmem = (LPIMESTRUCT)GlobalLock(hImeMem)) {
  1065. if(wRet == TRUE && lpmem->wCount == 0)
  1066. wRet = FALSE; //ok
  1067. GlobalUnlock(hImeMem);
  1068. }
  1069. return wRet;
  1070. }
  1071. #endif //IME_HIDDEN
  1072. /* routine to retrieve WM_CHAR from the message queue associated with hwnd.
  1073. * this is called by EatString.
  1074. */
  1075. WORD NEAR PASCAL EatOneCharacter(hwnd)
  1076. register HWND hwnd;
  1077. {
  1078. MSG msg;
  1079. register int i = 10;
  1080. while(!PeekMessage((LPMSG)&msg, hwnd, WM_CHAR, WM_CHAR, PM_REMOVE)) {
  1081. if (--i == 0)
  1082. return -1;
  1083. Yield();
  1084. }
  1085. return msg.wParam & 0xFF;
  1086. }
  1087. /* This routine is called when the MSWRITE_DOC class receives WM_IME_REPORT
  1088. * with IR_STRINGSTART message. The purpose of this function is to eat
  1089. * all strings between IR_STRINGSTART and IR_STRINGEND.
  1090. */
  1091. BOOL EatString(hwnd, lpSp, cchLen)
  1092. register HWND hwnd;
  1093. LPSTR lpSp;
  1094. WORD cchLen;
  1095. {
  1096. MSG msg;
  1097. int i = 10;
  1098. int w;
  1099. *lpSp = '\0';
  1100. if (cchLen < 4)
  1101. return NULL; // not enough
  1102. cchLen -= 2;
  1103. while(i--) {
  1104. while(PeekMessage((LPMSG)&msg, hwnd, NULL, NULL, PM_REMOVE)) {
  1105. i = 10;
  1106. switch(msg.message) {
  1107. case WM_CHAR:
  1108. *lpSp++ = (BYTE)msg.wParam;
  1109. cchLen--;
  1110. if (IsDBCSLeadByte((BYTE)msg.wParam)) {
  1111. if ((w = EatOneCharacter(hwnd)) == -1) {
  1112. /* Bad DBCS sequence - abort */
  1113. lpSp--;
  1114. goto WillBeDone;
  1115. }
  1116. *lpSp++ = (BYTE)w;
  1117. cchLen--;
  1118. }
  1119. if (cchLen <= 0)
  1120. goto WillBeDone; // buffer exhausted
  1121. break;
  1122. case WM_IME_REPORT:
  1123. if (msg.wParam == IR_STRINGEND) {
  1124. if (cchLen <= 0)
  1125. goto WillBeDone; // no more room to stuff
  1126. if ((w = EatOneCharacter(hwnd)) == -1)
  1127. goto WillBeDone;
  1128. *lpSp++ = (BYTE)w;
  1129. if (IsDBCSLeadByte((BYTE)w)) {
  1130. if ((w = EatOneCharacter(hwnd)) == -1) {
  1131. /* Bad DBCS sequence - abort */
  1132. lpSp--;
  1133. goto WillBeDone;
  1134. }
  1135. *lpSp++ = (BYTE)w;
  1136. }
  1137. goto WillBeDone;
  1138. }
  1139. /* Fall through */
  1140. default:
  1141. TranslateMessage(&msg);
  1142. DispatchMessage(&msg);
  1143. break;
  1144. }
  1145. }
  1146. }
  1147. /* We don't get WM_IME_REPORT + IR_STRINGEND
  1148. * But received string will be OK
  1149. */
  1150. WillBeDone:
  1151. *lpSp = '\0';
  1152. return TRUE;
  1153. }
  1154. #endif /* JAPAN */