/************************************************************/ /* Windows Write, Copyright 1985-1992 Microsoft Corporation */ /************************************************************/ #define NOGDICAPMASKS #define NOSYSMETRICS #define NOMENUS #define NOSOUND #define NOCOMM #define NOOPENFILE #define NORESOURCE #include #include "mw.h" #include "winddefs.h" #include "cmddefs.h" #include "wwdefs.h" #include "dispdefs.h" #include "docdefs.h" #include "debug.h" #if defined(OLE) #include "obj.h" #endif #ifdef PENWIN #define WM_PENWINFIRST 0x0380 // Remove when #define WIN31 #include int vcFakeMessage = 0; extern HCURSOR vhcPen; /* handle to pen cursor */ extern int (FAR PASCAL *lpfnProcessWriting)(HWND, LPRC); extern VOID (FAR PASCAL *lpfnPostVirtualKeyEvent)(WORD, BOOL); extern VOID (FAR PASCAL *lpfnTPtoDP)(LPPOINT, int); extern BOOL (FAR PASCAL *lpfnCorrectWriting)(HWND, LPSTR, int, LPRC, DWORD, DWORD); extern BOOL (FAR PASCAL *lpfnSymbolToCharacter)(LPSYV, int, LPSTR, LPINT); VOID NEAR PASCAL PostCharacter(WORD wch); VOID NEAR PASCAL SendVirtKeyShift(WORD wVk, BYTE bFlags); VOID NEAR PASCAL SetSelection(HWND hWnd, LPPOINT lpPtFirst, LPPOINT lpPtLast, WORD wParam); int NEAR PASCAL WGetClipboardText(HWND hwndOwner, LPSTR lpsz, int cbSzSize); VOID NEAR PASCAL ClearAppQueue(VOID); #define VKB_SHIFT 0x01 #define VKB_CTRL 0x02 #define VKB_ALT 0x04 #endif extern HWND vhWnd; extern HCURSOR vhcArrow; extern HCURSOR vhcIBeam; extern HCURSOR vhcBarCur; extern struct WWD rgwwd[]; extern struct WWD *pwwdCur; extern HANDLE hMmwModInstance; /* handle to own module instance */ extern int vfShiftKey; extern int vfCommandKey; extern int vfOptionKey; extern int vfDoubleClick; extern struct SEL selCur; extern long rgbBkgrnd; extern long rgbText; extern HBRUSH hbrBkgrnd; extern long ropErase; int vfCancelPictMove = FALSE; BOOL vfEraseWw = FALSE; long FAR PASCAL MdocWndProc(HWND, unsigned, WORD, LONG); void MdocCreate(HWND, LONG); void MdocSize(HWND, int, int, WORD); void MdocGetFocus(HWND, HWND); void MdocLoseFocus(HWND, HWND); void MdocMouse(HWND, unsigned, WORD, POINT); void MdocTimer(HWND, WORD); #if defined(JAPAN) & defined(DBCS_IME) #include extern BOOL bGetFocus; // for Non_PeekMessage mode in 'FImportantMsgPresent()'. [yutakan] BOOL bImeCnvOpen; BOOL GetIMEOpen(HWND, BOOL *); #endif #ifdef PENWIN // Helper routines to get events into system. Would be better (more efficient) if // could just call routines to set selection, copy, etc, // but this is the easiest way without touching any internals // Minics penwin internal routine, exception messages are posted instead // of sent since Write does a lot of peek ahead VOID NEAR PASCAL SetSelection(HWND hWnd, LPPOINT lpPtFirst, LPPOINT lpPtLast, WORD wParam) { static LONG lFirst = 0L; if (lpPtFirst) { (*lpfnTPtoDP)(lpPtFirst, 1); ScreenToClient(hWnd, lpPtFirst); } if (lpPtLast != NULL) { (*lpfnTPtoDP)(lpPtLast, 1); ScreenToClient(hWnd, lpPtLast); } if (lpPtFirst) { lFirst = MAKELONG(lpPtFirst->x, lpPtFirst->y); PostMessage(hWnd, WM_LBUTTONDOWN, wParam, lFirst); if (lpPtLast) { LONG lLast = MAKELONG(lpPtLast->x, lpPtLast->y); PostMessage(hWnd, WM_MOUSEMOVE, wParam, lLast); vcFakeMessage++; PostMessage(hWnd, WM_LBUTTONUP, wParam, lLast); } else { PostMessage(hWnd, WM_LBUTTONUP, wParam, lFirst); vcFakeMessage++; } } else // doubleclick { PostMessage(hWnd, WM_LBUTTONDBLCLK, wParam, lFirst); vcFakeMessage++; PostMessage(hWnd, WM_LBUTTONUP, wParam, lFirst); vcFakeMessage++; } } /* PURPOSE: Map a symbol value to a set of virtual keystrokes and then send the virtual keystrokes. TODO: Add real mapping of symbol values instead of assuming ANSI values Right now, this routine is worthless RETURN: GLOBALS: CONDITIONS: Kanji is not handled now, but could be. */ VOID NEAR PASCAL PostCharacter(WORD wch) { int iVk = VkKeyScan(LOBYTE(wch)); WORD wVk = (WORD)LOBYTE(iVk); char bFl = HIBYTE(iVk); if ((wVk != -1)) SendVirtKeyShift(wVk, bFl); } /*-------------------------------------------------------------------------- PURPOSE: Send an optionally shifted key sequence as system events RETURN: nothing GLOBALS: CONDITIONS: see flags in mspen.h */ VOID NEAR PASCAL SendVirtKeyShift(WORD wVk, BYTE bFlags) { // send DOWN events: if (bFlags & VKB_SHIFT) (*lpfnPostVirtualKeyEvent)(VK_SHIFT, fFalse); if (bFlags & VKB_CTRL) (*lpfnPostVirtualKeyEvent)(VK_CONTROL, fFalse); if (bFlags & VKB_ALT) (*lpfnPostVirtualKeyEvent)(VK_MENU, fFalse); (*lpfnPostVirtualKeyEvent)(wVk, fFalse); // send UP events (in opposite order): (*lpfnPostVirtualKeyEvent)(wVk, fTrue); if (bFlags & VKB_ALT) (*lpfnPostVirtualKeyEvent)(VK_MENU, fTrue); if (bFlags & VKB_CTRL) (*lpfnPostVirtualKeyEvent)(VK_CONTROL, fTrue); if (bFlags & VKB_SHIFT) (*lpfnPostVirtualKeyEvent)(VK_SHIFT, fTrue); } /* Fill buffer with contents of clipboard */ int NEAR PASCAL WGetClipboardText(HWND hwndOwner, LPSTR lpsz, int cbSzSize) { HANDLE hClip; int wLen = 0; OpenClipboard(hwndOwner); if (hClip = GetClipboardData(CF_TEXT)) { LPSTR lpszClip = (LPSTR)GlobalLock(hClip); if (lpsz && cbSzSize > 0) { wLen = lstrlen(lpszClip); if (wLen > cbSzSize) lpszClip[cbSzSize-1] = 0; lstrcpy(lpsz, lpszClip); } GlobalUnlock(hClip); } CloseClipboard(); return wLen; } /*-------------------------------------------------------------------------- PURPOSE: Dispatches any messages currently pending in our queue RETURN: nothing GLOBALS: CONDITIONS: */ VOID NEAR PASCAL ClearAppQueue(VOID) { MSG msg; while (PeekMessage(&msg, (HWND)NULL, NULL, NULL, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } #endif static RECT rSaveInv; long FAR PASCAL MdocWndProc(hWnd, message, wParam, lParam) HWND hWnd; unsigned message; WORD wParam; LONG lParam; { extern int vfCloseFilesInDialog; extern BOOL fPrinting; long lReturn=0L; #ifdef PENWIN static cCharSent; #endif #ifdef PENWIN if (message < WM_CUT || message == WM_RCRESULT) #else if (message < WM_CUT ) #endif { switch (message) { default: goto DefaultProc; /* For each of following mouse window messages, wParam contains ** bits indicating whether or not various virtual keys are down, ** and lParam is a POINT containing the mouse coordinates. The ** keydown bits of wParam are: MK_LBUTTON (set if Left Button is ** down); MK_RBUTTON (set if Right Button is down); MK_SHIFT (set ** if Shift Key is down); MK_ALTERNATE (set if Alt Key is down); ** and MK_CONTROL (set if Control Key is down). */ case WM_LBUTTONDBLCLK: #ifdef PENWIN if (vcFakeMessage > 0) vcFakeMessage--; // fall through #endif case WM_LBUTTONUP: case WM_MOUSEMOVE: case WM_LBUTTONDOWN: MdocMouse(hWnd, message, wParam, MAKEPOINT(lParam)); break; #ifdef PENWIN case WM_RCRESULT: { LPRCRESULT lpr = (LPRCRESULT)lParam; LPPOINT lpPntHot; LPPOINT lpPntHot2; if( (lpr->wResultsType&(RCRT_ALREADYPROCESSED|RCRT_NOSYMBOLMATCH))!=0 || lpr->lpsyv==NULL || lpr->cSyv == 0) return( FALSE ); if (lpr->wResultsType&RCRT_GESTURE) { SYV syv = *(lpr->lpsyv); vcFakeMessage = 0; lpPntHot = lpr->syg.rgpntHotSpots; lpPntHot2 = lpr->syg.cHotSpot > 1 ? lpr->syg.rgpntHotSpots + 1: NULL; switch ( LOWORD(syv)) { case LOWORD( SYV_EXTENDSELECT ): SetSelection(hWnd, lpPntHot, NULL, MK_SHIFT); // extend sel break; case LOWORD( SYV_CLEARWORD ): // dbl click & drag if (lpPntHot2) { SetSelection(hWnd, lpPntHot, NULL, 0); SetSelection(hWnd, NULL, NULL, 0); // dblclick selects word } SendVirtKeyShift(VK_DELETE, 0); break; case LOWORD( SYV_COPY): case LOWORD( SYV_CLEAR ): case LOWORD( SYV_CUT ): if ( selCur.cpFirst == selCur.cpLim && (lpr->wResultsType&RCRT_GESTURETRANSLATED)==0) { SetSelection(hWnd, lpPntHot, NULL, 0); if (syv != SYV_CLEAR) SetSelection(hWnd, NULL, NULL, 0); // dblclick } switch ( LOWORD(syv)) { case LOWORD( SYV_COPY): SendVirtKeyShift(VK_INSERT, VKB_CTRL); break; case LOWORD( SYV_CLEAR ): SendVirtKeyShift(VK_DELETE, 0); break; case LOWORD( SYV_CUT ): SendVirtKeyShift(VK_DELETE, VKB_SHIFT); break; } break; case LOWORD( SYV_PASTE ): if ((lpr->wResultsType&RCRT_GESTURETRANSLATED)==0) SetSelection(hWnd, lpPntHot, NULL, 0); SendVirtKeyShift(VK_INSERT, VKB_SHIFT); break; case LOWORD( SYV_UNDO): SendVirtKeyShift(VK_BACK, VKB_ALT); break; case LOWORD(SYV_BACKSPACE): case LOWORD(SYV_SPACE): case LOWORD(SYV_RETURN): case LOWORD(SYV_TAB): SetSelection(hWnd, lpPntHot, NULL, 0); PostCharacter(LOWORD(*(lpr->lpsyv))&0x00ff); break; case LOWORD( SYV_CORRECT ): { WORD wLen; HANDLE hMem = NULL; LPSTR lpstr; LPSTR lpsz; BOOL fDoubleClickSent = fFalse; #define cbCorrectMax 128 // Strategy: If no selection, send in a double click to // select a word. Then copy selection to clipboard // read off of clipboard. Call CorrectWriting, and // but changed text in clipboard and then paste // from clipboard. if ( selCur.cpFirst == selCur.cpLim ) { // No selection so send double click SetSelection(hWnd, lpPntHot, NULL, 0); // set caret SetSelection(hWnd, NULL, NULL, 0); // dblclick fDoubleClickSent = fTrue; ClearAppQueue(); } SendMessage(hWnd, WM_COPY, 0, 0L); if (IsClipboardFormatAvailable(CF_TEXT)) { hMem = GlobalAlloc(GMEM_MOVEABLE, (DWORD)cbCorrectMax); if (hMem == NULL || (lpsz = (LPSTR)GlobalLock(hMem)) == NULL) return 1; // Just bag out for now: should add error message if (WGetClipboardText(hWnd, lpsz, cbCorrectMax) < cbCorrectMax) { // Only bring up corrector if selection wasn't too big if ((*lpfnCorrectWriting)(hWnd, lpsz, cbCorrectMax, NULL, 0, 0)) { if (*lpsz==0) { // User deleted all text in correction SendVirtKeyShift(VK_DELETE, 0); } else { GlobalUnlock(hMem); OpenClipboard(GetParent(hWnd)); // Use parent as // owner to circumvent write's short check // cuts if it is owner of clipboard EmptyClipboard(); SetClipboardData(CF_TEXT, hMem); CloseClipboard(); hMem = NULL; SendMessage(hWnd, WM_PASTE, 0, 0L); UpdateWindow(hWnd); } } else if (fDoubleClickSent) { // Need to clear bogus selection. Just send in a tap. SetSelection(hWnd, lpPntHot, NULL, 0); } } if (hMem) // may never have been alloc'd if user canceled { GlobalUnlock(hMem); GlobalFree(hMem); } } } break; default: return( FALSE ); } } else // Not a gesture,see if normal characters { #define cbTempBufferSize 128 char rgch[cbTempBufferSize+2]; int cb=0; int cbT; LPSTR lpstr = (LPSTR)lpr->lpsyv; typeCP cp=cp0; LPSYV lpsyv; LPSYV lpsyvEnd; extern int docScrap; extern int vfScrapIsPic; extern struct PAP *vppapNormal; extern struct CHP vchpNormal; vfScrapIsPic = fFalse; ClobberDoc( docScrap, docNil, cp0, cp0 ); // Replace CR with LF's These are treated as EOLs // by CchReadLineExt. Then, before inserting // buffer, change all LFs to CR LFs as write expects // Will work for Kanji for (lpsyv=lpr->lpsyv, lpsyvEnd=&lpr->lpsyv[lpr->cSyv+1]; lpsyvlpsyv; Assert(cb>0 && lpstr[cb-1] == 0); // This code is abstracted for FReadExtScrap where it copies // text from clipboard into the scrap document. We do similar. // copy result into scrap and then insert scrap with // no formating. while (cb > 0) { struct PAP *ppap=NULL; int fEol; unsigned cch=min(cb, cbTempBufferSize); if ((cch = CchReadLineExt((LPCH) lpstr, cch, rgch, &fEol))==0) /* Reached terminator */ break; if (fEol) ppap = vppapNormal; InsertRgch(docScrap, cp, rgch, cch, &vchpNormal, ppap); cb -= cch; cp += (typeCP) cch; lpstr += cch; } CmdInsScrap(fTrue); } } return TRUE; #endif // PENWIN #if defined(OLE) case WM_DROPFILES: /* We got dropped on, so bring ourselves to the top */ BringWindowToTop(hParentWw); ObjGetDrop(wParam,FALSE); break; #endif case WM_TIMER: /* Timer message. wParam contains the timer ID value */ MdocTimer(hWnd, wParam); break; case WM_CREATE: /* Window's being created; lParam contains lpParam field ** passed to CreateWindow */ SetRectEmpty(&rSaveInv); MdocCreate(hWnd, lParam); break; case WM_SIZE: /* Window's size is changing. lParam contains the height ** and width, in the low and high words, respectively. ** wParam contains SIZENORMAL for "normal" size changes, ** SIZEICONIC when the window is being made iconic, and ** SIZEFULLSCREEN when the window is being made full screen. */ MdocSize(hWnd, LOWORD(lParam), HIWORD(lParam), wParam); break; case WM_PAINT: #if defined(OLE) if (nBlocking || fPrinting) // this'll reduce async problems { PAINTSTRUCT Paint; RECT rTmp=rSaveInv; BeginPaint(hWnd,&Paint); UnionRect(&rSaveInv,&rTmp,&Paint.rcPaint); EndPaint(hWnd,&Paint); break; } #endif /* Time for the window to draw itself. */ UpdateInvalid(); UpdateDisplay( FALSE ); break; case WM_SETFOCUS: /* The window is getting the focus. wParam contains the window ** handle of the window that previously had the focus. */ #if defined(JAPAN) & defined(DBCS_IME) // If we're getting input focus, we have to get current status of IME convert // window, and initialize 'bImeCnvOpen'. [yutakan:07/15/91] // if(!GetIMEOpen(hWnd,&bImeCnvOpen)) /* If err return, supporse IME is not enalble. */ bImeCnvOpen = FALSE; bGetFocus = TRUE; #endif MdocGetFocus(hWnd, (HWND)wParam); break; case WM_KILLFOCUS: /* The window is losing the focus. wParam contains the window ** handle of the window about to get the focus, or NULL. */ #if defined(JAPAN) & defined(DBCS_IME) /* If we're losing input focus, we have to clear OpenStatus of convertwindow, ** 'bImeCnvOpen'. [yutakan:07/15/91] */ bImeCnvOpen = FALSE; bGetFocus = FALSE; #endif MdocLoseFocus(hWnd, (HWND)wParam); /* Since we might be moving/sizing a picture, set flag to ** cancel this. */ vfCancelPictMove = TRUE; break; #if defined(JAPAN) & defined(DBCS_IME) case WM_IME_REPORT: /* if IME convert window has been opened, ** we're getting into Non PeekMessage ** Mode at 'FImportantMsgPresent()' */ if(wParam == IR_OPENCONVERT || wParam == IR_CHANGECONVERT) bImeCnvOpen = TRUE; else if(wParam == IR_CLOSECONVERT) bImeCnvOpen = FALSE; if (wParam == IR_STRING) { // Do nothing with IR_STRING // Yutakan break; /* put string from KKC to scrap */ // PutImeString(hWnd, LOWORD(lParam)); // need more bug fix. // return 1L; } if (wParam == IR_STRINGSTART) { HANDLE hMem; LPSTR lpText; if (hMem = GlobalAlloc(GMEM_MOVEABLE, 512L)) { if (lpText = GlobalLock(hMem)) { if (EatString(hWnd, (LPSTR)lpText, 512)) { PutImeString( hWnd, hMem ); } GlobalUnlock(hMem); } GlobalFree(hMem); } } goto DefaultProc; #endif } } else if (message < WM_USER) { /* Clipboard messages */ if (!FMdocClipboardMsg( message, wParam, lParam )) goto DefaultProc; } else { /* Private WRITE messages */ switch (message) { default: goto DefaultProc; #if defined(OLE) case WM_WAITFORSERVER: { extern int vfDeactByOtherApp; if (!hwndWait && !vfDeactByOtherApp) { vbCancelOK = TRUE; ((LPOBJINFO)lParam)->fCanKillAsync = wParam; ((LPOBJINFO)lParam)->fCompleteAsync = TRUE; DialogBoxParam(hMmwModInstance, (LPSTR)"DTWAIT", hParentWw, lpfnWaitForObject, ((LPOBJINFO)lParam)->lpobject); } } break; case WM_OBJUPDATE: ObjObjectHasChanged(wParam,(LPOLEOBJECT)lParam); break; case WM_OBJERROR: ObjReleaseError(wParam); break; case WM_OBJBADLINK: ObjHandleBadLink(wParam,(LPOLEOBJECT)lParam); break; case WM_OBJDELETE: ObjDeleteObject((LPOBJINFO)lParam,wParam); break; #endif case wWndMsgDeleteFile: /* wParam is a global handle to the file to be deleted */ /* Return code: TRUE - Ok to delete FALSE - don't delete */ lReturn = (LONG)FDeleteFileMessage( wParam ); break; case wWndMsgRenameFile: /* wParam is a global handle to the file being renamed */ /* LOWORD( lParam ) is a global handle to the new name */ /* No return code */ RenameFileMessage( wParam, LOWORD( lParam ) ); break; } } goto Ret; DefaultProc: /* All messages not processed come here. */ lReturn = DefWindowProc(hWnd, message, wParam, lParam); Ret: if (vfCloseFilesInDialog) CloseEveryRfn( FALSE ); return lReturn; } void MdocMouse(hWnd, message, wParam, pt) HWND hWnd; unsigned message; WORD wParam; POINT pt; { extern int vfFocus; extern int vfDownClick; extern int vfMouseExist; extern HCURSOR vhcHourGlass; extern int vfInLongOperation; MSG msg; if (vfInLongOperation) { SetCursor(vhcHourGlass); return; } if (message == WM_MOUSEMOVE) { if (vfMouseExist) { HCURSOR hc; /* All we do on move moves is set the cursor. */ if (pt.y < wwdCurrentDoc.ypMin) { hc = vhcArrow; } else { #ifdef PENWIN hc = (pt.x > xpSelBar ) ? vhcPen : vhcBarCur; #else hc = (pt.x > xpSelBar) ? vhcIBeam : vhcBarCur; #endif } SetCursor( hc ); } return; } /* Save the state of the shift keys. */ vfShiftKey = wParam & MK_SHIFT; vfCommandKey = wParam & MK_CONTROL; /* high bit returned from GetKeyState is 1 when the key is down, else it is up, the low bit is 1 if it is toggled */ PeekMessage(&msg, (HWND)NULL, NULL, NULL, PM_NOREMOVE); vfOptionKey = GetKeyState(VK_MENU) < 0 ? true : false; vfDoubleClick = (message == WM_LBUTTONDBLCLK); if (message == WM_LBUTTONUP) { /* Windows demands this */ if (vfDownClick && !vfFocus) { SetFocus( hWnd ); vfDownClick = FALSE; } } else { extern int vfGotoKeyMode; vfGotoKeyMode = FALSE; /* WM_LBUTTONDOWN or WM_LBUTTONDBLCLK */ vfDownClick = TRUE; #ifdef PENWIN if( lpfnProcessWriting == NULL || vfDoubleClick || pt.x < xpSelBar || (*lpfnProcessWriting)( hWnd, NULL ) < 0 ) //Normal mouse processing DoContentHit(pt); #else DoContentHit(pt); #endif } } void MdocTimer(hWnd, id) HWND hWnd; WORD id; { extern int vfSkipNextBlink; extern int vfInsertOn; extern int vfFocus; #if defined(OLE) ++nGarbageTime; #endif /* A timer event has occurred with ID id. Process it here. */ Assert( id == tidCaret ); /* Caret blink is the only timer event we know */ if ( ( vhWnd != hWnd ) || /* Document window is not current */ ( !vfFocus ) || /* Don't have the focus */ ( wwdCurrentDoc.fDirty) ) /* dl's are not up to date */ return; if ( vfSkipNextBlink ) { /* We have been warned not to blank the cursor this time around */ vfSkipNextBlink = FALSE; if ( vfInsertOn ) return; } #if defined(OLE) if (nGarbageTime > GARBAGETIME) ObjCollectGarbage(); #endif if ( selCur.cpFirst == selCur.cpLim ) { /* We must use ToggleSel instead of DrawInsertLine because the */ /* insert cp might not be on the screen & ToggleSel can */ /* figure this out */ extern int vypCursLine; extern int vdypCursLine; /* The following condition may not be true if we get a timer message after a size message but before a paint message; ypMac will have been adjusted but dlMac does not get adjusted to reflect the change until UpdateDisplay is called. We have violated the Windows dictate that ALL size-related calculations must occur in the Size proc and we must compensate here */ if ( vypCursLine - vdypCursLine < wwdCurrentDoc.ypMac ) { ToggleSel( selCur.cpFirst, selCur.cpFirst, !vfInsertOn ); vfSkipNextBlink = FALSE; } } } void CatchupInvalid(HWND hWnd) { if (!nBlocking && !IsRectEmpty(&rSaveInv)) { InvalidateRect(hWnd,&rSaveInv,FALSE); SetRectEmpty(&rSaveInv); } } #if defined(JAPAN) & defined(DBCS_IME) /* ** We want to get 'IME ConvertWindow OpenStatus' but IME_GETOPEN ** subfunction. ** now does not support 'wCount' in IMESTRUCT (will support in future). ** So this function will always return FALSE since wCount is always 0 ** as we set it before do SendIMEMessage(). [yutakan:07/16/91] */ BOOL GetIMEOpen(HWND hwnd, BOOL *pFlag) { LPIMESTRUCT lpmem; HANDLE hIMEBlock; int wRet; /* Get comunication area with IME */ hIMEBlock=GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_LOWER, (DWORD)sizeof(IMESTRUCT)); if(!hIMEBlock) return FALSE; lpmem = (LPIMESTRUCT)GlobalLock(hIMEBlock); lpmem->fnc = IME_GETOPEN; lpmem->wCount = 0; GlobalUnlock(hIMEBlock); if(!SendIMEMessage(hwnd,MAKELONG(hIMEBlock,NULL))){ wRet = FALSE; /* Error */ } else wRet = TRUE; /* Success */ lpmem = (LPIMESTRUCT)GlobalLock(hIMEBlock); *pFlag = lpmem->wParam && lpmem->wCount; GlobalUnlock(hIMEBlock); GlobalFree(hIMEBlock); return wRet; } /* routine to retrieve WM_CHAR from the message queue associated with hwnd. * this is called by EatString. */ WORD NEAR PASCAL EatOneCharacter(hwnd) register HWND hwnd; { MSG msg; register int i = 10; while(!PeekMessage((LPMSG)&msg, hwnd, WM_CHAR, WM_CHAR, PM_REMOVE)) { if (--i == 0) return -1; Yield(); } return msg.wParam & 0xFF; } /* This routine is called when the MSWRITE_DOC class receives WM_IME_REPORT * with IR_STRINGSTART message. The purpose of this function is to eat * all strings between IR_STRINGSTART and IR_STRINGEND. */ BOOL EatString(hwnd, lpSp, cchLen) register HWND hwnd; LPSTR lpSp; WORD cchLen; { MSG msg; int i = 10; int w; *lpSp = '\0'; if (cchLen < 4) return NULL; // not enough cchLen -= 2; while(i--) { while(PeekMessage((LPMSG)&msg, hwnd, NULL, NULL, PM_REMOVE)) { i = 10; switch(msg.message) { case WM_CHAR: *lpSp++ = (BYTE)msg.wParam; cchLen--; if (IsDBCSLeadByte((BYTE)msg.wParam)) { if ((w = EatOneCharacter(hwnd)) == -1) { /* Bad DBCS sequence - abort */ lpSp--; goto WillBeDone; } *lpSp++ = (BYTE)w; cchLen--; } if (cchLen <= 0) goto WillBeDone; // buffer exhausted break; case WM_IME_REPORT: if (msg.wParam == IR_STRINGEND) { if (cchLen <= 0) goto WillBeDone; // no more room to stuff if ((w = EatOneCharacter(hwnd)) == -1) goto WillBeDone; *lpSp++ = (BYTE)w; if (IsDBCSLeadByte((BYTE)w)) { if ((w = EatOneCharacter(hwnd)) == -1) { /* Bad DBCS sequence - abort */ lpSp--; goto WillBeDone; } *lpSp++ = (BYTE)w; } goto WillBeDone; } /* Fall through */ default: TranslateMessage(&msg); DispatchMessage(&msg); break; } } } /* We don't get WM_IME_REPORT + IR_STRINGEND * But received string will be OK */ WillBeDone: *lpSp = '\0'; return TRUE; } #endif /* JAPAN */