/*++ Copyright (c) 1990-1998 Microsoft Corporation, All Rights Reserved Module Name: UICOMP.C ++*/ /**********************************************************************/ #include "windows.h" #include "immdev.h" #include "fakeime.h" /**********************************************************************/ /* */ /* CompStrWndProc() */ /* */ /* IME UI window procedure */ /* */ /**********************************************************************/ LRESULT CALLBACK CompStrWndProc( hWnd, message, wParam, lParam ) HWND hWnd; UINT message; WPARAM wParam; LPARAM lParam; { HWND hUIWnd; switch (message) { case WM_PAINT: PaintCompWindow( hWnd); break; case WM_SETCURSOR: case WM_MOUSEMOVE: case WM_LBUTTONUP: case WM_RBUTTONUP: DragUI(hWnd,message,wParam,lParam); if ((message == WM_SETCURSOR) && (HIWORD(lParam) != WM_LBUTTONDOWN) && (HIWORD(lParam) != WM_RBUTTONDOWN)) return DefWindowProc(hWnd,message,wParam,lParam); if ((message == WM_LBUTTONUP) || (message == WM_RBUTTONUP)) SetWindowLong(hWnd,FIGWL_MOUSE,0L); break; case WM_MOVE: hUIWnd = (HWND)GetWindowLongPtr(hWnd,FIGWL_SVRWND); if (IsWindow(hUIWnd)) SendMessage(hUIWnd,WM_UI_DEFCOMPMOVE,wParam,lParam); break; default: if (!MyIsIMEMessage(message)) return DefWindowProc(hWnd,message,wParam,lParam); break; } return 0; } /**********************************************************************/ /* */ /* CreateCompWindow() */ /* */ /**********************************************************************/ void PASCAL CreateCompWindow( HWND hUIWnd, LPUIEXTRA lpUIExtra,LPINPUTCONTEXT lpIMC ) { int i; RECT rc; lpUIExtra->dwCompStyle = lpIMC->cfCompForm.dwStyle; for (i=0; i < MAXCOMPWND ; i++) { if (!IsWindow(lpUIExtra->uiComp[i].hWnd)) { lpUIExtra->uiComp[i].hWnd = CreateWindowEx(0, (LPTSTR)szCompStrClassName,NULL, WS_COMPNODEFAULT, 0,0,1,1, hUIWnd,NULL,hInst,NULL); } lpUIExtra->uiComp[i].rc.left = 0; lpUIExtra->uiComp[i].rc.top = 0; lpUIExtra->uiComp[i].rc.right = 1; lpUIExtra->uiComp[i].rc.bottom = 1; SetWindowLongPtr(lpUIExtra->uiComp[i].hWnd,FIGWL_FONT,(LONG_PTR)lpUIExtra->hFont); SetWindowLongPtr(lpUIExtra->uiComp[i].hWnd,FIGWL_SVRWND,(LONG_PTR)hUIWnd); ShowWindow(lpUIExtra->uiComp[i].hWnd,SW_HIDE); lpUIExtra->uiComp[i].bShow = FALSE; } if (lpUIExtra->uiDefComp.pt.x == -1) { GetWindowRect(lpIMC->hWnd,&rc); lpUIExtra->uiDefComp.pt.x = rc.left; lpUIExtra->uiDefComp.pt.y = rc.bottom + 1; } if (!IsWindow(lpUIExtra->uiDefComp.hWnd)) { lpUIExtra->uiDefComp.hWnd = CreateWindowEx( WS_EX_WINDOWEDGE, (LPTSTR)szCompStrClassName,NULL, WS_COMPDEFAULT | WS_DLGFRAME, lpUIExtra->uiDefComp.pt.x, lpUIExtra->uiDefComp.pt.y, 1,1, hUIWnd,NULL,hInst,NULL); } //SetWindowLong(lpUIExtra->uiDefComp.hWnd,FIGWL_FONT,(DWORD)lpUIExtra->hFont); SetWindowLongPtr(lpUIExtra->uiDefComp.hWnd,FIGWL_SVRWND,(LONG_PTR)hUIWnd); ShowWindow(lpUIExtra->uiDefComp.hWnd,SW_HIDE); lpUIExtra->uiDefComp.bShow = FALSE; return; } /**********************************************************************/ /* */ /* NumCharInDX() */ /* */ /* Count how may the char can be arranged in DX. */ /* */ /**********************************************************************/ int PASCAL NumCharInDX(HDC hDC,LPMYSTR lp,int dx) { SIZE sz; int width = 0; int num = 0; int numT = 0; if (!*lp) return 0; while ((width < dx) && *(lp + numT)) { num = numT; #if defined(FAKEIMEM) || defined(UNICODE) numT++; GetTextExtentPointW(hDC,lp,numT,&sz); #else if (IsDBCSLeadByte(*(lp + numT))) numT += 2; else numT++; GetTextExtentPoint(hDC,lp,numT,&sz); #endif width = sz.cx; } if (width < dx) num = numT; return num; } /**********************************************************************/ /* */ /* NumCharInDY() */ /* */ /* Count how may the char can be arranged in DY. */ /* */ /**********************************************************************/ int PASCAL NumCharInDY(HDC hDC,LPMYSTR lp,int dy) { SIZE sz; int width = 0; int num; int numT = 0; if (!*lp) return 0; while ((width < dy) && *(lp + numT)) { num = numT; #if defined(FAKEIMEM) || defined(UNICODE) numT++; GetTextExtentPointW(hDC,lp,numT,&sz); #else if (IsDBCSLeadByte(*(lp + numT))) numT += 2; else numT++; GetTextExtentPoint(hDC,lp,numT,&sz); #endif width = sz.cy; } return num; } /**********************************************************************/ /* */ /* MoveCompWindow() */ /* */ /* Calc the position of composition windows and move them. */ /* */ /**********************************************************************/ void PASCAL MoveCompWindow( LPUIEXTRA lpUIExtra,LPINPUTCONTEXT lpIMC ) { HDC hDC; HFONT hFont = (HFONT)NULL; HFONT hOldFont = (HFONT)NULL; LPCOMPOSITIONSTRING lpCompStr; LPMYSTR lpstr; RECT rc; RECT oldrc; SIZE sz; int width; int height; int i; // // Save the composition form style into lpUIExtra. // lpUIExtra->dwCompStyle = lpIMC->cfCompForm.dwStyle; if (lpIMC->cfCompForm.dwStyle) // Style is not DEFAULT. { POINT ptSrc = lpIMC->cfCompForm.ptCurrentPos; RECT rcSrc; LPMYSTR lpt; int dx; int dy; int num; int curx; int cury; // // Lock the COMPOSITIONSTRING structure. // if (!(lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr))) return; // // If there is no composition string, don't display anything. // if ((lpCompStr->dwSize <= sizeof(COMPOSITIONSTRING)) || (lpCompStr->dwCompStrLen == 0)) { ImmUnlockIMCC(lpIMC->hCompStr); return; } // // Set the rectangle for the composition string. // if (lpIMC->cfCompForm.dwStyle & CFS_RECT) rcSrc = lpIMC->cfCompForm.rcArea; else GetClientRect(lpIMC->hWnd,(LPRECT)&rcSrc); ClientToScreen(lpIMC->hWnd, &ptSrc); ClientToScreen(lpIMC->hWnd, (LPPOINT)&rcSrc.left); ClientToScreen(lpIMC->hWnd, (LPPOINT)&rcSrc.right); // // Check the start position. // if (!PtInRect((LPRECT)&rcSrc,ptSrc)) { ImmUnlockIMCC(lpIMC->hCompStr); return; } // // Hide the default composition window. // if (IsWindow(lpUIExtra->uiDefComp.hWnd)) { ShowWindow(lpUIExtra->uiDefComp.hWnd,SW_HIDE); lpUIExtra->uiDefComp.bShow = FALSE; } lpt = lpstr = GETLPCOMPSTR(lpCompStr); #if defined(FAKEIMEM) || defined(UNICODE) num = 1; #else if (IsDBCSLeadByte(*lpt)) num = 2; else num = 1; #endif if (!lpUIExtra->bVertical) { dx = rcSrc.right - ptSrc.x; curx = ptSrc.x; cury = ptSrc.y; // // Set the composition string to each composition window. // The composition windows that are given the compostion string // will be moved and shown. // for (i = 0; i < MAXCOMPWND; i++) { if (IsWindow(lpUIExtra->uiComp[i].hWnd)) { hDC = GetDC(lpUIExtra->uiComp[i].hWnd); if (hFont = (HFONT)GetWindowLongPtr(lpUIExtra->uiComp[i].hWnd,FIGWL_FONT)) hOldFont = SelectObject(hDC,hFont); sz.cy = 0; oldrc = lpUIExtra->uiComp[i].rc; if (num = NumCharInDX(hDC,lpt,dx)) { #ifdef FAKEIMEM GetTextExtentPointW(hDC,lpt,num,&sz); #else GetTextExtentPoint(hDC,lpt,num,&sz); #endif lpUIExtra->uiComp[i].rc.left = curx; lpUIExtra->uiComp[i].rc.top = cury; lpUIExtra->uiComp[i].rc.right = sz.cx; lpUIExtra->uiComp[i].rc.bottom = sz.cy; SetWindowLong(lpUIExtra->uiComp[i].hWnd,FIGWL_COMPSTARTSTR, (DWORD) (lpt - lpstr)); SetWindowLong(lpUIExtra->uiComp[i].hWnd,FIGWL_COMPSTARTNUM, num); MoveWindow(lpUIExtra->uiComp[i].hWnd, curx,cury,sz.cx,sz.cy,TRUE); ShowWindow(lpUIExtra->uiComp[i].hWnd, SW_SHOWNOACTIVATE); lpUIExtra->uiComp[i].bShow = TRUE; lpt+=num; } else { lpUIExtra->uiComp[i].rc.left = 0; lpUIExtra->uiComp[i].rc.top = 0; lpUIExtra->uiComp[i].rc.right = 0; lpUIExtra->uiComp[i].rc.bottom = 0; SetWindowLong(lpUIExtra->uiComp[i].hWnd,FIGWL_COMPSTARTSTR, 0L); SetWindowLong(lpUIExtra->uiComp[i].hWnd,FIGWL_COMPSTARTNUM, 0L); ShowWindow(lpUIExtra->uiComp[i].hWnd, SW_HIDE); lpUIExtra->uiComp[i].bShow = FALSE; } InvalidateRect(lpUIExtra->uiComp[i].hWnd,NULL,FALSE); dx = rcSrc.right - rcSrc.left; curx = rcSrc.left; cury += sz.cy; if (hOldFont) SelectObject(hDC,hOldFont); ReleaseDC(lpUIExtra->uiComp[i].hWnd,hDC); } } } else // when it is vertical fonts. { dy = rcSrc.bottom - ptSrc.y; curx = ptSrc.x; cury = ptSrc.y; for (i = 0; i < MAXCOMPWND; i++) { if (IsWindow(lpUIExtra->uiComp[i].hWnd)) { hDC = GetDC(lpUIExtra->uiComp[i].hWnd); if (hFont = (HFONT)GetWindowLongPtr(lpUIExtra->uiComp[i].hWnd,FIGWL_FONT)) hOldFont = SelectObject(hDC,hFont); sz.cy = 0; if (num = NumCharInDY(hDC,lpt,dy)) { #ifdef FAKEIMEM GetTextExtentPointW(hDC,lpt,num,&sz); #else GetTextExtentPoint(hDC,lpt,num,&sz); #endif lpUIExtra->uiComp[i].rc.left = curx - sz.cy; lpUIExtra->uiComp[i].rc.top = cury; lpUIExtra->uiComp[i].rc.right = sz.cy; lpUIExtra->uiComp[i].rc.bottom = sz.cx; SetWindowLong(lpUIExtra->uiComp[i].hWnd,FIGWL_COMPSTARTSTR, (DWORD) (lpt - lpstr)); SetWindowLong(lpUIExtra->uiComp[i].hWnd,FIGWL_COMPSTARTNUM, num); MoveWindow(lpUIExtra->uiComp[i].hWnd, curx,cury,sz.cy,sz.cx,TRUE); ShowWindow(lpUIExtra->uiComp[i].hWnd, SW_SHOWNOACTIVATE); lpUIExtra->uiComp[i].bShow = TRUE; lpt+=num; } else { lpUIExtra->uiComp[i].rc.left = 0; lpUIExtra->uiComp[i].rc.top = 0; lpUIExtra->uiComp[i].rc.right = 0; lpUIExtra->uiComp[i].rc.bottom = 0; SetWindowLong(lpUIExtra->uiComp[i].hWnd,FIGWL_COMPSTARTSTR, 0L); SetWindowLong(lpUIExtra->uiComp[i].hWnd,FIGWL_COMPSTARTNUM, 0L); ShowWindow(lpUIExtra->uiComp[i].hWnd, SW_HIDE); lpUIExtra->uiComp[i].bShow = FALSE; } InvalidateRect(lpUIExtra->uiComp[i].hWnd,NULL,FALSE); dy = rcSrc.bottom - rcSrc.top; cury = rcSrc.top; curx -= sz.cy; if (hOldFont) SelectObject(hDC,hOldFont); ReleaseDC(lpUIExtra->uiComp[i].hWnd,hDC); } } } ImmUnlockIMCC(lpIMC->hCompStr); } else { // // When the style is DEFAULT, show the default composition window. // if (IsWindow(lpUIExtra->uiDefComp.hWnd)) { for (i = 0; i < MAXCOMPWND; i++) { if (IsWindow(lpUIExtra->uiComp[i].hWnd)) { ShowWindow(lpUIExtra->uiComp[i].hWnd,SW_HIDE); lpUIExtra->uiComp[i].bShow = FALSE; } } hDC = GetDC(lpUIExtra->uiDefComp.hWnd); if (lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr)) { if ((lpCompStr->dwSize > sizeof(COMPOSITIONSTRING)) && (lpCompStr->dwCompStrLen > 0)) { lpstr = GETLPCOMPSTR(lpCompStr); #ifdef FAKEIMEM GetTextExtentPointW(hDC,lpstr,lstrlenW(lpstr),&sz); #else GetTextExtentPoint(hDC,lpstr,lstrlen(lpstr),&sz); #endif width = sz.cx; height = sz.cy; } ImmUnlockIMCC(lpIMC->hCompStr); } ReleaseDC(lpUIExtra->uiDefComp.hWnd,hDC); GetWindowRect(lpUIExtra->uiDefComp.hWnd,&rc); lpUIExtra->uiDefComp.pt.x = rc.left; lpUIExtra->uiDefComp.pt.y = rc.top; MoveWindow(lpUIExtra->uiDefComp.hWnd, rc.left, rc.top, width+ 2 * GetSystemMetrics(SM_CXEDGE), height+ 2 * GetSystemMetrics(SM_CYEDGE), TRUE); ShowWindow(lpUIExtra->uiDefComp.hWnd, SW_SHOWNOACTIVATE); lpUIExtra->uiDefComp.bShow = TRUE; InvalidateRect(lpUIExtra->uiDefComp.hWnd,NULL,FALSE); } } } /**********************************************************************/ /* */ /* DrawTextOneLine(hDC, lpstr, lpattr, num) */ /* */ /**********************************************************************/ void PASCAL DrawTextOneLine( HWND hCompWnd, HDC hDC, LPMYSTR lpstr, LPBYTE lpattr, int num, BOOL fVert) { LPMYSTR lpStart = lpstr; LPMYSTR lpEnd = lpstr + num - 1; int x,y; RECT rc; if (num == 0) return; GetClientRect (hCompWnd,&rc); if (!fVert) { x = 0; y = 0; } else { x = rc.right; y = 0; } while (lpstr <= lpEnd) { int cnt = 0; BYTE bAttr = *lpattr; SIZE sz; while ((bAttr == *lpattr) || (cnt <= num)) { lpattr++; cnt++; } switch (bAttr) { case ATTR_INPUT: break; case ATTR_TARGET_CONVERTED: SetTextColor(hDC,RGB(127,127,127)); #ifdef FAKEIMEM if (!fVert) TextOutW(hDC,x + 1,y + 1,lpstr,cnt); else TextOutW(hDC,x - 1,y + 1,lpstr,cnt); #else if (!fVert) TextOut(hDC,x + 1,y + 1,lpstr,cnt); else TextOut(hDC,x - 1,y + 1,lpstr,cnt); #endif SetTextColor(hDC,RGB(0,0,0)); SetBkMode(hDC,TRANSPARENT); break; case ATTR_CONVERTED: SetTextColor(hDC,RGB(127,127,127)); #ifdef FAKEIMEM if (!fVert) TextOutW(hDC,x + 1,y + 1,lpstr,cnt); else TextOutW(hDC,x - 1,y + 1,lpstr,cnt); #else if (!fVert) TextOut(hDC,x + 1,y + 1,lpstr,cnt); else TextOut(hDC,x - 1,y + 1,lpstr,cnt); #endif SetTextColor(hDC,RGB(0,0,255)); SetBkMode(hDC,TRANSPARENT); break; case ATTR_TARGET_NOTCONVERTED: break; } #ifdef FAKEIMEM TextOutW(hDC,x,y,lpstr,cnt); GetTextExtentPointW(hDC,lpstr,cnt,&sz); #else TextOut(hDC,x,y,lpstr,cnt); GetTextExtentPoint(hDC,lpstr,cnt,&sz); #endif lpstr += cnt; if (!fVert) x += sz.cx; else y += sz.cx; } } /**********************************************************************/ /* */ /* PaintCompWindow(hCompWnd) */ /* */ /**********************************************************************/ void PASCAL PaintCompWindow( HWND hCompWnd) { PAINTSTRUCT ps; HIMC hIMC; LPINPUTCONTEXT lpIMC; LPCOMPOSITIONSTRING lpCompStr; HDC hDC; RECT rc; HFONT hFont = (HFONT)NULL; HFONT hOldFont = (HFONT)NULL; HWND hSvrWnd; hDC = BeginPaint(hCompWnd,&ps); if (hFont = (HFONT)GetWindowLongPtr(hCompWnd,FIGWL_FONT)) hOldFont = SelectObject(hDC,hFont); hSvrWnd = (HWND)GetWindowLongPtr(hCompWnd,FIGWL_SVRWND); if (hIMC = (HIMC)GetWindowLongPtr(hSvrWnd,IMMGWLP_IMC)) { lpIMC = ImmLockIMC(hIMC); if (lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr)) { if ((lpCompStr->dwSize > sizeof(COMPOSITIONSTRING)) && (lpCompStr->dwCompStrLen > 0)) { LPMYSTR lpstr; LPBYTE lpattr; LONG lstart; LONG num; BOOL fVert = FALSE; if (hFont) fVert = (lpIMC->lfFont.A.lfEscapement == 2700); lpstr = GETLPCOMPSTR(lpCompStr); lpattr = GETLPCOMPATTR(lpCompStr); SetBkMode(hDC,TRANSPARENT); if (lpIMC->cfCompForm.dwStyle) { HDC hPDC; hPDC = GetDC(GetParent(hCompWnd)); GetClientRect (hCompWnd,&rc); SetBkColor(hDC,GetBkColor(hPDC)); SetBkMode(hDC,OPAQUE); lstart = GetWindowLong(hCompWnd,FIGWL_COMPSTARTSTR); num = GetWindowLong(hCompWnd,FIGWL_COMPSTARTNUM); if (!num || ((lstart + num) > Mylstrlen(lpstr))) goto end_pcw; lpstr+=lstart; lpattr+=lstart; DrawTextOneLine(hCompWnd, hDC, lpstr, lpattr, num, fVert); ReleaseDC(GetParent(hCompWnd),hPDC); } else { num = Mylstrlen(lpstr); DrawTextOneLine(hCompWnd, hDC, lpstr, lpattr, num, fVert); } } end_pcw: ImmUnlockIMCC(lpIMC->hCompStr); } ImmUnlockIMC(hIMC); } if (hFont && hOldFont) SelectObject(hDC,hOldFont); EndPaint(hCompWnd,&ps); } /**********************************************************************/ /* */ /* HideCompWindow(lpUIExtra) */ /* */ /**********************************************************************/ void PASCAL HideCompWindow(LPUIEXTRA lpUIExtra) { int i; RECT rc; if (IsWindow(lpUIExtra->uiDefComp.hWnd)) { if (!lpUIExtra->dwCompStyle) GetWindowRect(lpUIExtra->uiDefComp.hWnd,(LPRECT)&rc); ShowWindow(lpUIExtra->uiDefComp.hWnd, SW_HIDE); lpUIExtra->uiDefComp.bShow = FALSE; } for (i=0;iuiComp[i].hWnd)) { ShowWindow(lpUIExtra->uiComp[i].hWnd, SW_HIDE); lpUIExtra->uiComp[i].bShow = FALSE; } } } /**********************************************************************/ /* */ /* SetFontCompWindow(lpUIExtra) */ /* */ /**********************************************************************/ void PASCAL SetFontCompWindow(LPUIEXTRA lpUIExtra) { int i; for (i=0;iuiComp[i].hWnd)) SetWindowLongPtr(lpUIExtra->uiComp[i].hWnd,FIGWL_FONT,(LONG_PTR)lpUIExtra->hFont); }