Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
6dca48fe
Commit
6dca48fe
authored
Apr 02, 2008
by
Aric Stewart
Committed by
Alexandre Julliard
Apr 07, 2008
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winex11: Add IME functionality to winex11drv.
All XIM interaction will soon pass through this functionality instead of directly to imm32.
parent
d03f4d2a
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
1463 additions
and
1 deletion
+1463
-1
Makefile.in
dlls/winex11.drv/Makefile.in
+2
-1
ime.c
dlls/winex11.drv/ime.c
+1425
-0
winex11.drv.spec
dlls/winex11.drv/winex11.drv.spec
+18
-0
x11drv.h
dlls/winex11.drv/x11drv.h
+14
-0
x11drv_main.c
dlls/winex11.drv/x11drv_main.c
+2
-0
xim.c
dlls/winex11.drv/xim.c
+2
-0
No files found.
dlls/winex11.drv/Makefile.in
View file @
6dca48fe
...
...
@@ -3,7 +3,7 @@ TOPOBJDIR = ../..
SRCDIR
=
@srcdir@
VPATH
=
@srcdir@
MODULE
=
winex11.drv
IMPORTS
=
user32 gdi32 advapi32 kernel32 ntdll
IMPORTS
=
user32 gdi32 advapi32
imm32
kernel32 ntdll
EXTRAINCL
=
@X_CFLAGS@
EXTRALIBS
=
@X_LIBS@ @X_PRE_LIBS@ @XLIB@ @X_EXTRA_LIBS@
...
...
@@ -21,6 +21,7 @@ C_SRCS = \
dib_src_swap.c
\
event.c
\
graphics.c
\
ime.c
\
init.c
\
keyboard.c
\
mouse.c
\
...
...
dlls/winex11.drv/ime.c
0 → 100644
View file @
6dca48fe
/*
* The IME for interfacing with XIM
*
* Copyright 2008 CodeWeavers, Aric Stewart
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/*
* Notes:
* The normal flow for IMM/IME Processing is as follows.
* 1) The Keyboard Driver generates key messages which are first passed to
* the IMM and then to IME via ImeProcessKey. If the IME returns 0 then
* it does not want the key and the keyboard driver then generates the
* WM_KEYUP/WM_KEYDOWN messages. However if the IME is going to process the
* key it returns non-zero.
* 2) If the IME is going to process the key then the IMM calls ImeToAsciiEx to
* process the key. the IME modifies the HIMC structure to reflect the
* current state and generates any messages it needs the IMM to process.
* 3) IMM checks the messages and send them to the application in question. From
* here the IMM level deals with if the application is IME aware or not.
*
* This flow does not work well for the X11 driver and XIM.
* (It works fine for Mac)
* As such we will have to reroute step 1. Instead the x11drv driver will
* generate an XIM events and call directly into this IME implimenetaion.
* As such we will have to use the alternative ImmGenerateMessage path to be
* generate the messages that we want the IMM layer to send to the application.
*/
#include "config.h"
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "wine/debug.h"
#include "imm.h"
#include "ddk/imm.h"
#include "winnls.h"
#include "x11drv.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
imm
);
#define FROM_X11 ((HIMC)0xcafe1337)
typedef
struct
_IMEPRIVATE
{
BOOL
bInComposition
;
BOOL
bInternalState
;
HFONT
textfont
;
HWND
hwndDefault
;
}
IMEPRIVATE
,
*
LPIMEPRIVATE
;
typedef
struct
_tagTRANSMSG
{
UINT
message
;
WPARAM
wParam
;
LPARAM
lParam
;
}
TRANSMSG
,
*
LPTRANSMSG
;
static
const
WCHAR
UI_CLASS_NAME
[]
=
{
'W'
,
'i'
,
'n'
,
'e'
,
'X'
,
'1'
,
'1'
,
'I'
,
'M'
,
'E'
,
0
};
static
HIMC
*
hSelectedFrom
=
NULL
;
static
INT
hSelectedCount
=
0
;
static
BOOL
hXIMPresent
=
FALSE
;
/* MSIME messages */
static
UINT
WM_MSIME_SERVICE
;
static
UINT
WM_MSIME_RECONVERTOPTIONS
;
static
UINT
WM_MSIME_MOUSE
;
static
UINT
WM_MSIME_RECONVERTREQUEST
;
static
UINT
WM_MSIME_RECONVERT
;
static
UINT
WM_MSIME_QUERYPOSITION
;
static
UINT
WM_MSIME_DOCUMENTFEED
;
static
LRESULT
WINAPI
IME_WindowProc
(
HWND
hwnd
,
UINT
uMsg
,
WPARAM
wParam
,
LPARAM
lParam
);
static
void
UpdateDataInDefaultIMEWindow
(
HIMC
hHIMC
,
HWND
hwnd
,
BOOL
showable
);
static
HIMC
RealIMC
(
HIMC
hIMC
)
{
if
(
hIMC
==
FROM_X11
)
{
INT
i
;
HWND
wnd
=
GetFocus
();
HIMC
winHimc
=
ImmGetContext
(
wnd
);
for
(
i
=
0
;
i
<
hSelectedCount
;
i
++
)
if
(
winHimc
==
hSelectedFrom
[
i
])
return
winHimc
;
return
NULL
;
}
else
return
hIMC
;
}
static
LPINPUTCONTEXT
LockRealIMC
(
HIMC
hIMC
)
{
HIMC
real_imc
=
RealIMC
(
hIMC
);
if
(
real_imc
)
return
(
LPINPUTCONTEXT
)
ImmLockIMC
(
real_imc
);
else
return
NULL
;
}
static
BOOL
UnlockRealIMC
(
HIMC
hIMC
)
{
HIMC
real_imc
=
RealIMC
(
hIMC
);
if
(
real_imc
)
return
ImmUnlockIMC
(
real_imc
);
else
return
FALSE
;
}
static
HIMCC
ImeCreateBlankCompStr
(
void
)
{
HIMCC
rc
;
LPCOMPOSITIONSTRING
ptr
;
rc
=
ImmCreateIMCC
(
sizeof
(
COMPOSITIONSTRING
));
ptr
=
(
LPCOMPOSITIONSTRING
)
ImmLockIMCC
(
rc
);
memset
(
ptr
,
0
,
sizeof
(
COMPOSITIONSTRING
));
ptr
->
dwSize
=
sizeof
(
COMPOSITIONSTRING
);
ImmUnlockIMCC
(
rc
);
return
rc
;
}
static
int
updateField
(
DWORD
origLen
,
DWORD
origOffset
,
DWORD
currentOffset
,
LPBYTE
target
,
LPBYTE
source
,
DWORD
*
lenParam
,
DWORD
*
offsetParam
,
BOOL
wchars
)
{
if
(
origLen
>
0
&&
origOffset
>
0
)
{
int
truelen
=
origLen
;
if
(
wchars
)
truelen
*=
sizeof
(
WCHAR
);
memcpy
(
&
target
[
currentOffset
],
&
source
[
origOffset
],
truelen
);
*
lenParam
=
origLen
;
*
offsetParam
=
currentOffset
;
currentOffset
+=
truelen
;
}
return
currentOffset
;
}
static
HIMCC
updateCompStr
(
HIMCC
old
,
LPWSTR
compstr
,
DWORD
len
)
{
/* we need to make sure the CompStr, CompClaus and CompAttr fields are all
* set and correct */
int
needed_size
;
HIMCC
rc
;
LPBYTE
newdata
=
NULL
;
LPBYTE
olddata
=
NULL
;
LPCOMPOSITIONSTRING
new_one
;
LPCOMPOSITIONSTRING
lpcs
=
NULL
;
INT
current_offset
=
0
;
TRACE
(
"%s, %i
\n
"
,
debugstr_wn
(
compstr
,
len
),
len
);
if
(
old
==
NULL
&&
compstr
==
NULL
&&
len
==
0
)
return
NULL
;
if
(
old
!=
NULL
)
{
olddata
=
ImmLockIMCC
(
old
);
lpcs
=
(
LPCOMPOSITIONSTRING
)
olddata
;
}
needed_size
=
sizeof
(
COMPOSITIONSTRING
)
+
len
*
sizeof
(
WCHAR
)
+
len
+
sizeof
(
DWORD
)
*
2
;
if
(
lpcs
!=
NULL
)
{
needed_size
+=
lpcs
->
dwCompReadAttrLen
;
needed_size
+=
lpcs
->
dwCompReadClauseLen
;
needed_size
+=
lpcs
->
dwCompReadStrLen
*
sizeof
(
DWORD
);
needed_size
+=
lpcs
->
dwResultReadClauseLen
;
needed_size
+=
lpcs
->
dwResultReadStrLen
*
sizeof
(
DWORD
);
needed_size
+=
lpcs
->
dwResultClauseLen
;
needed_size
+=
lpcs
->
dwResultStrLen
*
sizeof
(
DWORD
);
needed_size
+=
lpcs
->
dwPrivateSize
;
}
rc
=
ImmCreateIMCC
(
needed_size
);
newdata
=
ImmLockIMCC
(
rc
);
new_one
=
(
LPCOMPOSITIONSTRING
)
newdata
;
new_one
->
dwSize
=
needed_size
;
current_offset
=
sizeof
(
COMPOSITIONSTRING
);
if
(
lpcs
!=
NULL
)
{
current_offset
=
updateField
(
lpcs
->
dwCompReadAttrLen
,
lpcs
->
dwCompReadAttrOffset
,
current_offset
,
newdata
,
olddata
,
&
new_one
->
dwCompReadAttrLen
,
&
new_one
->
dwCompReadAttrOffset
,
FALSE
);
current_offset
=
updateField
(
lpcs
->
dwCompReadClauseLen
,
lpcs
->
dwCompReadClauseOffset
,
current_offset
,
newdata
,
olddata
,
&
new_one
->
dwCompReadClauseLen
,
&
new_one
->
dwCompReadClauseOffset
,
FALSE
);
current_offset
=
updateField
(
lpcs
->
dwCompReadStrLen
,
lpcs
->
dwCompReadStrOffset
,
current_offset
,
newdata
,
olddata
,
&
new_one
->
dwCompReadStrLen
,
&
new_one
->
dwCompReadStrOffset
,
TRUE
);
/* new CompAttr, CompClause, CompStr, dwCursorPos */
new_one
->
dwDeltaStart
=
0
;
current_offset
=
updateField
(
lpcs
->
dwResultReadClauseLen
,
lpcs
->
dwResultReadClauseOffset
,
current_offset
,
newdata
,
olddata
,
&
new_one
->
dwResultReadClauseLen
,
&
new_one
->
dwResultReadClauseOffset
,
FALSE
);
current_offset
=
updateField
(
lpcs
->
dwResultReadStrLen
,
lpcs
->
dwResultReadStrOffset
,
current_offset
,
newdata
,
olddata
,
&
new_one
->
dwResultReadStrLen
,
&
new_one
->
dwResultReadStrOffset
,
TRUE
);
current_offset
=
updateField
(
lpcs
->
dwResultClauseLen
,
lpcs
->
dwResultClauseOffset
,
current_offset
,
newdata
,
olddata
,
&
new_one
->
dwResultClauseLen
,
&
new_one
->
dwResultClauseOffset
,
FALSE
);
current_offset
=
updateField
(
lpcs
->
dwResultStrLen
,
lpcs
->
dwResultStrOffset
,
current_offset
,
newdata
,
olddata
,
&
new_one
->
dwResultStrLen
,
&
new_one
->
dwResultStrOffset
,
TRUE
);
current_offset
=
updateField
(
lpcs
->
dwPrivateSize
,
lpcs
->
dwPrivateOffset
,
current_offset
,
newdata
,
olddata
,
&
new_one
->
dwPrivateSize
,
&
new_one
->
dwPrivateOffset
,
FALSE
);
}
/* set new data */
/* CompAttr */
new_one
->
dwCompAttrLen
=
len
;
if
(
len
>
0
)
{
new_one
->
dwCompAttrOffset
=
current_offset
;
memset
(
&
newdata
[
current_offset
],
ATTR_INPUT
,
len
);
current_offset
+=
len
;
}
/* CompClause */
if
(
len
>
0
)
{
new_one
->
dwCompClauseLen
=
sizeof
(
DWORD
)
*
2
;
new_one
->
dwCompClauseOffset
=
current_offset
;
*
(
DWORD
*
)(
&
newdata
[
current_offset
])
=
0
;
current_offset
+=
sizeof
(
DWORD
);
*
(
DWORD
*
)(
&
newdata
[
current_offset
])
=
len
;
current_offset
+=
sizeof
(
DWORD
);
}
/* CompStr */
new_one
->
dwCompStrLen
=
len
;
if
(
len
>
0
)
{
new_one
->
dwCompStrOffset
=
current_offset
;
memcpy
(
&
newdata
[
current_offset
],
compstr
,
len
*
sizeof
(
WCHAR
));
}
/* CursorPos */
new_one
->
dwCursorPos
=
len
;
ImmUnlockIMCC
(
rc
);
if
(
lpcs
)
ImmUnlockIMCC
(
old
);
return
rc
;
}
static
HIMCC
updateResultStr
(
HIMCC
old
,
LPWSTR
resultstr
,
DWORD
len
)
{
/* we need to make sure the ResultStr and ResultClause fields are all
* set and correct */
int
needed_size
;
HIMCC
rc
;
LPBYTE
newdata
=
NULL
;
LPBYTE
olddata
=
NULL
;
LPCOMPOSITIONSTRING
new_one
;
LPCOMPOSITIONSTRING
lpcs
=
NULL
;
INT
current_offset
=
0
;
TRACE
(
"%s, %i
\n
"
,
debugstr_wn
(
resultstr
,
len
),
len
);
if
(
old
==
NULL
&&
resultstr
==
NULL
&&
len
==
0
)
return
NULL
;
if
(
old
!=
NULL
)
{
olddata
=
ImmLockIMCC
(
old
);
lpcs
=
(
LPCOMPOSITIONSTRING
)
olddata
;
}
needed_size
=
sizeof
(
COMPOSITIONSTRING
)
+
len
*
sizeof
(
WCHAR
)
+
sizeof
(
DWORD
)
*
2
;
if
(
lpcs
!=
NULL
)
{
needed_size
+=
lpcs
->
dwCompReadAttrLen
;
needed_size
+=
lpcs
->
dwCompReadClauseLen
;
needed_size
+=
lpcs
->
dwCompReadStrLen
*
sizeof
(
DWORD
);
needed_size
+=
lpcs
->
dwCompAttrLen
;
needed_size
+=
lpcs
->
dwCompClauseLen
;
needed_size
+=
lpcs
->
dwCompStrLen
*
sizeof
(
DWORD
);
needed_size
+=
lpcs
->
dwResultReadClauseLen
;
needed_size
+=
lpcs
->
dwResultReadStrLen
*
sizeof
(
DWORD
);
needed_size
+=
lpcs
->
dwPrivateSize
;
}
rc
=
ImmCreateIMCC
(
needed_size
);
newdata
=
ImmLockIMCC
(
rc
);
new_one
=
(
LPCOMPOSITIONSTRING
)
newdata
;
new_one
->
dwSize
=
needed_size
;
current_offset
=
sizeof
(
COMPOSITIONSTRING
);
if
(
lpcs
!=
NULL
)
{
current_offset
=
updateField
(
lpcs
->
dwCompReadAttrLen
,
lpcs
->
dwCompReadAttrOffset
,
current_offset
,
newdata
,
olddata
,
&
new_one
->
dwCompReadAttrLen
,
&
new_one
->
dwCompReadAttrOffset
,
FALSE
);
current_offset
=
updateField
(
lpcs
->
dwCompReadClauseLen
,
lpcs
->
dwCompReadClauseOffset
,
current_offset
,
newdata
,
olddata
,
&
new_one
->
dwCompReadClauseLen
,
&
new_one
->
dwCompReadClauseOffset
,
FALSE
);
current_offset
=
updateField
(
lpcs
->
dwCompReadStrLen
,
lpcs
->
dwCompReadStrOffset
,
current_offset
,
newdata
,
olddata
,
&
new_one
->
dwCompReadStrLen
,
&
new_one
->
dwCompReadStrOffset
,
TRUE
);
current_offset
=
updateField
(
lpcs
->
dwCompAttrLen
,
lpcs
->
dwCompAttrOffset
,
current_offset
,
newdata
,
olddata
,
&
new_one
->
dwCompAttrLen
,
&
new_one
->
dwCompAttrOffset
,
FALSE
);
current_offset
=
updateField
(
lpcs
->
dwCompClauseLen
,
lpcs
->
dwCompClauseOffset
,
current_offset
,
newdata
,
olddata
,
&
new_one
->
dwCompClauseLen
,
&
new_one
->
dwCompClauseOffset
,
FALSE
);
current_offset
=
updateField
(
lpcs
->
dwCompStrLen
,
lpcs
->
dwCompStrOffset
,
current_offset
,
newdata
,
olddata
,
&
new_one
->
dwCompStrLen
,
&
new_one
->
dwCompStrOffset
,
TRUE
);
new_one
->
dwCursorPos
=
lpcs
->
dwCursorPos
;
new_one
->
dwDeltaStart
=
0
;
current_offset
=
updateField
(
lpcs
->
dwResultReadClauseLen
,
lpcs
->
dwResultReadClauseOffset
,
current_offset
,
newdata
,
olddata
,
&
new_one
->
dwResultReadClauseLen
,
&
new_one
->
dwResultReadClauseOffset
,
FALSE
);
current_offset
=
updateField
(
lpcs
->
dwResultReadStrLen
,
lpcs
->
dwResultReadStrOffset
,
current_offset
,
newdata
,
olddata
,
&
new_one
->
dwResultReadStrLen
,
&
new_one
->
dwResultReadStrOffset
,
TRUE
);
/* new ResultClause , ResultStr */
current_offset
=
updateField
(
lpcs
->
dwPrivateSize
,
lpcs
->
dwPrivateOffset
,
current_offset
,
newdata
,
olddata
,
&
new_one
->
dwPrivateSize
,
&
new_one
->
dwPrivateOffset
,
FALSE
);
}
/* set new data */
/* ResultClause */
if
(
len
>
0
)
{
new_one
->
dwResultClauseLen
=
sizeof
(
DWORD
)
*
2
;
new_one
->
dwResultClauseOffset
=
current_offset
;
*
(
DWORD
*
)(
&
newdata
[
current_offset
])
=
0
;
current_offset
+=
sizeof
(
DWORD
);
*
(
DWORD
*
)(
&
newdata
[
current_offset
])
=
len
;
current_offset
+=
sizeof
(
DWORD
);
}
/* ResultStr */
new_one
->
dwResultStrLen
=
len
;
if
(
len
>
0
)
{
new_one
->
dwResultStrOffset
=
current_offset
;
memcpy
(
&
newdata
[
current_offset
],
resultstr
,
len
*
sizeof
(
WCHAR
));
}
ImmUnlockIMCC
(
rc
);
if
(
lpcs
)
ImmUnlockIMCC
(
old
);
return
rc
;
}
static
void
GenerateIMEMessage
(
HIMC
hIMC
,
UINT
msg
,
WPARAM
wParam
,
LPARAM
lParam
)
{
LPINPUTCONTEXT
lpIMC
;
LPTRANSMSG
lpTransMsg
;
lpIMC
=
LockRealIMC
(
hIMC
);
if
(
lpIMC
==
NULL
)
return
;
lpIMC
->
hMsgBuf
=
ImmReSizeIMCC
(
lpIMC
->
hMsgBuf
,
(
lpIMC
->
dwNumMsgBuf
+
1
)
*
sizeof
(
TRANSMSG
));
if
(
!
lpIMC
->
hMsgBuf
)
return
;
lpTransMsg
=
(
LPTRANSMSG
)
ImmLockIMCC
(
lpIMC
->
hMsgBuf
);
if
(
!
lpTransMsg
)
return
;
lpTransMsg
+=
lpIMC
->
dwNumMsgBuf
;
lpTransMsg
->
message
=
msg
;
lpTransMsg
->
wParam
=
wParam
;
lpTransMsg
->
lParam
=
lParam
;
ImmUnlockIMCC
(
lpIMC
->
hMsgBuf
);
lpIMC
->
dwNumMsgBuf
++
;
ImmGenerateMessage
(
RealIMC
(
hIMC
));
UnlockRealIMC
(
hIMC
);
}
static
void
GenerateIMECHARMessages
(
HIMC
hIMC
,
LPWSTR
String
,
DWORD
length
)
{
LPINPUTCONTEXT
lpIMC
;
LPTRANSMSG
lpTransMsg
;
INT
i
;
if
(
length
<=
0
)
return
;
lpIMC
=
LockRealIMC
(
hIMC
);
if
(
lpIMC
==
NULL
)
return
;
lpIMC
->
hMsgBuf
=
ImmReSizeIMCC
(
lpIMC
->
hMsgBuf
,
(
lpIMC
->
dwNumMsgBuf
+
length
)
*
sizeof
(
TRANSMSG
));
if
(
!
lpIMC
->
hMsgBuf
)
return
;
lpTransMsg
=
(
LPTRANSMSG
)
ImmLockIMCC
(
lpIMC
->
hMsgBuf
);
if
(
!
lpTransMsg
)
return
;
lpTransMsg
+=
lpIMC
->
dwNumMsgBuf
;
for
(
i
=
0
;
i
<
length
;
i
++
)
{
lpTransMsg
->
message
=
WM_IME_CHAR
;
lpTransMsg
->
wParam
=
String
[
i
];
lpTransMsg
->
lParam
=
1
;
lpTransMsg
++
;
}
ImmUnlockIMCC
(
lpIMC
->
hMsgBuf
);
lpIMC
->
dwNumMsgBuf
+=
length
;
ImmGenerateMessage
(
RealIMC
(
hIMC
));
UnlockRealIMC
(
hIMC
);
}
static
BOOL
IME_RemoveFromSelected
(
HIMC
hIMC
)
{
int
i
;
for
(
i
=
0
;
i
<
hSelectedCount
;
i
++
)
if
(
hSelectedFrom
[
i
]
==
hIMC
)
{
if
(
i
<
hSelectedCount
-
1
)
memcpy
(
&
hSelectedFrom
[
i
],
&
hSelectedFrom
[
i
+
1
],
(
hSelectedCount
-
i
-
1
)
*
sizeof
(
HIMC
));
hSelectedCount
--
;
return
TRUE
;
}
return
FALSE
;
}
static
void
IME_AddToSelected
(
HIMC
hIMC
)
{
hSelectedCount
++
;
if
(
hSelectedFrom
)
hSelectedFrom
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
hSelectedFrom
,
hSelectedCount
*
sizeof
(
HIMC
));
else
hSelectedFrom
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
HIMC
));
hSelectedFrom
[
hSelectedCount
-
1
]
=
hIMC
;
}
BOOL
WINAPI
ImeInquire
(
LPIMEINFO
lpIMEInfo
,
LPWSTR
lpszUIClass
,
LPCWSTR
lpszOption
)
{
TRACE
(
"
\n
"
);
if
(
!
hXIMPresent
)
{
ERR
(
"No XIM in the back end
\n
"
);
return
FALSE
;
}
lpIMEInfo
->
dwPrivateDataSize
=
sizeof
(
IMEPRIVATE
);
lpIMEInfo
->
fdwProperty
=
IME_PROP_UNICODE
|
IME_PROP_AT_CARET
;
lpIMEInfo
->
fdwConversionCaps
=
IME_CMODE_NATIVE
;
lpIMEInfo
->
fdwSentenceCaps
=
IME_SMODE_AUTOMATIC
;
lpIMEInfo
->
fdwUICaps
=
UI_CAP_2700
;
/* Tell App we cannot accept ImeSetCompositionString calls */
lpIMEInfo
->
fdwSCSCaps
=
0
;
lpIMEInfo
->
fdwSelectCaps
=
SELECT_CAP_CONVERSION
;
lstrcpyW
(
lpszUIClass
,
UI_CLASS_NAME
);
return
TRUE
;
}
BOOL
WINAPI
ImeConfigure
(
HKL
hKL
,
HWND
hWnd
,
DWORD
dwMode
,
LPVOID
lpData
)
{
FIXME
(
"(%p, %p, %d, %p): stub
\n
"
,
hKL
,
hWnd
,
dwMode
,
lpData
);
SetLastError
(
ERROR_CALL_NOT_IMPLEMENTED
);
return
FALSE
;
}
DWORD
WINAPI
ImeConversionList
(
HIMC
hIMC
,
LPCWSTR
lpSource
,
LPCANDIDATELIST
lpCandList
,
DWORD
dwBufLen
,
UINT
uFlag
)
{
FIXME
(
"(%p, %s, %p, %d, %d): stub
\n
"
,
hIMC
,
debugstr_w
(
lpSource
),
lpCandList
,
dwBufLen
,
uFlag
);
SetLastError
(
ERROR_CALL_NOT_IMPLEMENTED
);
return
0
;
}
BOOL
WINAPI
ImeDestroy
(
UINT
uForce
)
{
TRACE
(
"
\n
"
);
HeapFree
(
GetProcessHeap
(),
0
,
hSelectedFrom
);
hSelectedFrom
=
NULL
;
hSelectedCount
=
0
;
return
TRUE
;
}
LRESULT
WINAPI
ImeEscape
(
HIMC
hIMC
,
UINT
uSubFunc
,
LPVOID
lpData
)
{
FIXME
(
"(%p, %d, %p): stub
\n
"
,
hIMC
,
uSubFunc
,
lpData
);
SetLastError
(
ERROR_CALL_NOT_IMPLEMENTED
);
return
0
;
}
BOOL
WINAPI
ImeProcessKey
(
HIMC
hIMC
,
UINT
vKey
,
LPARAM
lKeyData
,
CONST
LPBYTE
lpbKeyState
)
{
/* See the comment at the head of this file */
TRACE
(
"We do no processing via this route
\n
"
);
return
FALSE
;
}
BOOL
WINAPI
ImeSelect
(
HIMC
hIMC
,
BOOL
fSelect
)
{
LPINPUTCONTEXT
lpIMC
;
TRACE
(
"%p %s
\n
"
,
hIMC
,(
fSelect
)
?
"TRUE"
:
"FALSE"
);
if
(
hIMC
==
FROM_X11
)
{
ERR
(
"ImeSelect should never be called from X11
\n
"
);
return
FALSE
;
}
if
(
!
hXIMPresent
)
{
ERR
(
"No XIM in the back end
\n
"
);
return
FALSE
;
}
if
(
!
hIMC
)
return
TRUE
;
/* not selected */
if
(
!
fSelect
)
return
IME_RemoveFromSelected
(
hIMC
);
IME_AddToSelected
(
hIMC
);
/* Initialize our structures */
lpIMC
=
LockRealIMC
(
hIMC
);
if
(
lpIMC
!=
NULL
)
{
LPIMEPRIVATE
myPrivate
;
myPrivate
=
(
LPIMEPRIVATE
)
ImmLockIMCC
(
lpIMC
->
hPrivate
);
myPrivate
->
bInComposition
=
FALSE
;
myPrivate
->
bInternalState
=
FALSE
;
myPrivate
->
textfont
=
NULL
;
myPrivate
->
hwndDefault
=
NULL
;
ImmUnlockIMCC
(
lpIMC
->
hPrivate
);
UnlockRealIMC
(
hIMC
);
}
return
TRUE
;
}
BOOL
WINAPI
ImeSetActiveContext
(
HIMC
hIMC
,
BOOL
fFlag
)
{
FIXME
(
"Stub"
);
return
TRUE
;
}
UINT
WINAPI
ImeToAsciiEx
(
UINT
uVKey
,
UINT
uScanCode
,
CONST
LPBYTE
lpbKeyState
,
LPDWORD
lpdwTransKey
,
UINT
fuState
,
HIMC
hIMC
)
{
/* See the comment at the head of this file */
TRACE
(
"We do no processing via this route
\n
"
);
return
0
;
}
BOOL
WINAPI
NotifyIME
(
HIMC
hIMC
,
DWORD
dwAction
,
DWORD
dwIndex
,
DWORD
dwValue
)
{
BOOL
bRet
=
FALSE
;
LPINPUTCONTEXT
lpIMC
;
TRACE
(
"%p %i %i %i
\n
"
,
hIMC
,
dwAction
,
dwIndex
,
dwValue
);
lpIMC
=
LockRealIMC
(
hIMC
);
if
(
lpIMC
==
NULL
)
return
FALSE
;
switch
(
dwAction
)
{
case
NI_OPENCANDIDATE
:
FIXME
(
"NI_OPENCANDIDATE
\n
"
);
break
;
case
NI_CLOSECANDIDATE
:
FIXME
(
"NI_CLOSECANDIDATE
\n
"
);
break
;
case
NI_SELECTCANDIDATESTR
:
FIXME
(
"NI_SELECTCANDIDATESTR
\n
"
);
break
;
case
NI_CHANGECANDIDATELIST
:
FIXME
(
"NI_CHANGECANDIDATELIST
\n
"
);
break
;
case
NI_SETCANDIDATE_PAGESTART
:
FIXME
(
"NI_SETCANDIDATE_PAGESTART
\n
"
);
break
;
case
NI_SETCANDIDATE_PAGESIZE
:
FIXME
(
"NI_SETCANDIDATE_PAGESIZE
\n
"
);
break
;
case
NI_CONTEXTUPDATED
:
FIXME
(
"NI_CONTEXTUPDATED:"
);
switch
(
dwValue
)
{
case
IMC_SETCOMPOSITIONWINDOW
:
FIXME
(
"IMC_SETCOMPOSITIONWINDOW
\n
"
);
break
;
case
IMC_SETCONVERSIONMODE
:
FIXME
(
"IMC_SETCONVERSIONMODE
\n
"
);
break
;
case
IMC_SETSENTENCEMODE
:
FIXME
(
"IMC_SETSENTENCEMODE
\n
"
);
break
;
case
IMC_SETCANDIDATEPOS
:
FIXME
(
"IMC_SETCANDIDATEPOS
\n
"
);
break
;
case
IMC_SETCOMPOSITIONFONT
:
{
LPIMEPRIVATE
myPrivate
;
TRACE
(
"IMC_SETCOMPOSITIONFONT
\n
"
);
myPrivate
=
(
LPIMEPRIVATE
)
ImmLockIMCC
(
lpIMC
->
hPrivate
);
if
(
myPrivate
->
textfont
)
{
DeleteObject
(
myPrivate
->
textfont
);
myPrivate
->
textfont
=
NULL
;
}
myPrivate
->
textfont
=
CreateFontIndirectW
(
&
lpIMC
->
lfFont
.
W
);
ImmUnlockIMCC
(
lpIMC
->
hPrivate
);
}
break
;
case
IMC_SETOPENSTATUS
:
{
LPIMEPRIVATE
myPrivate
;
TRACE
(
"IMC_SETOPENSTATUS
\n
"
);
myPrivate
=
(
LPIMEPRIVATE
)
ImmLockIMCC
(
lpIMC
->
hPrivate
);
if
(
lpIMC
->
fOpen
!=
myPrivate
->
bInternalState
)
{
if
(
lpIMC
->
fOpen
==
FALSE
)
{
X11DRV_ForceXIMReset
(
lpIMC
->
hWnd
);
GenerateIMEMessage
(
hIMC
,
WM_IME_ENDCOMPOSITION
,
0
,
0
);
}
else
GenerateIMEMessage
(
hIMC
,
WM_IME_STARTCOMPOSITION
,
0
,
0
);
}
bRet
=
TRUE
;
}
break
;
default:
FIXME
(
"Unknown
\n
"
);
break
;
}
break
;
case
NI_COMPOSITIONSTR
:
TRACE
(
"NI_COMPOSITIONSTR:"
);
switch
(
dwIndex
)
{
case
CPS_COMPLETE
:
{
HIMCC
newCompStr
;
DWORD
cplen
=
0
;
LPWSTR
cpstr
;
LPCOMPOSITIONSTRING
cs
=
NULL
;
LPBYTE
cdata
=
NULL
;
LPIMEPRIVATE
myPrivate
;
TRACE
(
"CPS_COMPLETE
\n
"
);
/* clear existing result */
newCompStr
=
updateResultStr
(
lpIMC
->
hCompStr
,
NULL
,
0
);
ImmDestroyIMCC
(
lpIMC
->
hCompStr
);
lpIMC
->
hCompStr
=
newCompStr
;
if
(
lpIMC
->
hCompStr
)
{
cdata
=
ImmLockIMCC
(
lpIMC
->
hCompStr
);
cs
=
(
LPCOMPOSITIONSTRING
)
cdata
;
cplen
=
cs
->
dwCompStrLen
;
cpstr
=
(
LPWSTR
)
&
(
cdata
[
cs
->
dwCompStrOffset
]);
ImmUnlockIMCC
(
lpIMC
->
hCompStr
);
}
if
(
cplen
>
0
)
{
WCHAR
param
=
cpstr
[
0
];
newCompStr
=
updateResultStr
(
lpIMC
->
hCompStr
,
cpstr
,
cplen
);
ImmDestroyIMCC
(
lpIMC
->
hCompStr
);
lpIMC
->
hCompStr
=
newCompStr
;
newCompStr
=
updateCompStr
(
lpIMC
->
hCompStr
,
NULL
,
0
);
ImmDestroyIMCC
(
lpIMC
->
hCompStr
);
lpIMC
->
hCompStr
=
newCompStr
;
GenerateIMEMessage
(
hIMC
,
WM_IME_COMPOSITION
,
0
,
GCS_COMPSTR
);
GenerateIMEMessage
(
hIMC
,
WM_IME_COMPOSITION
,
param
,
GCS_RESULTSTR
|
GCS_RESULTCLAUSE
);
}
GenerateIMEMessage
(
hIMC
,
WM_IME_ENDCOMPOSITION
,
0
,
0
);
myPrivate
=
(
LPIMEPRIVATE
)
ImmLockIMCC
(
lpIMC
->
hPrivate
);
myPrivate
->
bInComposition
=
FALSE
;
ImmUnlockIMCC
(
lpIMC
->
hPrivate
);
bRet
=
TRUE
;
}
break
;
case
CPS_CONVERT
:
FIXME
(
"CPS_CONVERT
\n
"
);
break
;
case
CPS_REVERT
:
FIXME
(
"CPS_REVERT
\n
"
);
break
;
case
CPS_CANCEL
:
{
BOOL
send
;
LPCOMPOSITIONSTRING
lpCompStr
;
TRACE
(
"CPS_CANCEL
\n
"
);
X11DRV_ForceXIMReset
(
lpIMC
->
hWnd
);
lpCompStr
=
ImmLockIMCC
(
lpIMC
->
hCompStr
);
send
=
(
lpCompStr
->
dwCompStrLen
!=
0
);
ImmUnlockIMCC
(
lpIMC
->
hCompStr
);
if
(
send
)
{
HIMCC
newCompStr
;
newCompStr
=
updateCompStr
(
lpIMC
->
hCompStr
,
NULL
,
0
);
ImmDestroyIMCC
(
lpIMC
->
hCompStr
);
lpIMC
->
hCompStr
=
newCompStr
;
GenerateIMEMessage
(
hIMC
,
WM_IME_COMPOSITION
,
0
,
GCS_COMPSTR
);
}
bRet
=
TRUE
;
}
break
;
default:
FIXME
(
"Unknown
\n
"
);
break
;
}
break
;
default:
FIXME
(
"Unknown Message
\n
"
);
break
;
}
UnlockRealIMC
(
hIMC
);
return
bRet
;
}
BOOL
WINAPI
ImeRegisterWord
(
LPCWSTR
lpszReading
,
DWORD
dwStyle
,
LPCWSTR
lpszRegister
)
{
FIXME
(
"(%s, %d, %s): stub
\n
"
,
debugstr_w
(
lpszReading
),
dwStyle
,
debugstr_w
(
lpszRegister
));
SetLastError
(
ERROR_CALL_NOT_IMPLEMENTED
);
return
FALSE
;
}
BOOL
WINAPI
ImeUnregisterWord
(
LPCWSTR
lpszReading
,
DWORD
dwStyle
,
LPCWSTR
lpszUnregister
)
{
FIXME
(
"(%s, %d, %s): stub
\n
"
,
debugstr_w
(
lpszReading
),
dwStyle
,
debugstr_w
(
lpszUnregister
));
SetLastError
(
ERROR_CALL_NOT_IMPLEMENTED
);
return
FALSE
;
}
UINT
WINAPI
ImeGetRegisterWordStyle
(
UINT
nItem
,
LPSTYLEBUFW
lpStyleBuf
)
{
FIXME
(
"(%d, %p): stub
\n
"
,
nItem
,
lpStyleBuf
);
SetLastError
(
ERROR_CALL_NOT_IMPLEMENTED
);
return
0
;
}
UINT
WINAPI
ImeEnumRegisterWord
(
REGISTERWORDENUMPROCW
lpfnEnumProc
,
LPCWSTR
lpszReading
,
DWORD
dwStyle
,
LPCWSTR
lpszRegister
,
LPVOID
lpData
)
{
FIXME
(
"(%p, %s, %d, %s, %p): stub
\n
"
,
lpfnEnumProc
,
debugstr_w
(
lpszReading
),
dwStyle
,
debugstr_w
(
lpszRegister
),
lpData
);
SetLastError
(
ERROR_CALL_NOT_IMPLEMENTED
);
return
0
;
}
BOOL
WINAPI
ImeSetCompositionString
(
HIMC
hIMC
,
DWORD
dwIndex
,
LPCVOID
lpComp
,
DWORD
dwCompLen
,
LPCVOID
lpRead
,
DWORD
dwReadLen
)
{
LPINPUTCONTEXT
lpIMC
;
DWORD
flags
=
0
;
WCHAR
wParam
=
0
;
LPIMEPRIVATE
myPrivate
;
TRACE
(
"(%p, %d, %p, %d, %p, %d):
\n
"
,
hIMC
,
dwIndex
,
lpComp
,
dwCompLen
,
lpRead
,
dwReadLen
);
if
(
hIMC
!=
FROM_X11
)
FIXME
(
"PROBLEM: This only sets the wine level string
\n
"
);
/*
* Explanation:
* this sets the composition string in the imm32.dll level
* of the composition buffer. we cannot manipulate the xim level
* buffer, which means that once the xim level buffer changes again
* any call to this function from the application will be lost
*/
if
(
lpRead
&&
dwReadLen
)
FIXME
(
"Reading string unimplemented
\n
"
);
lpIMC
=
LockRealIMC
(
hIMC
);
if
(
lpIMC
==
NULL
)
return
FALSE
;
myPrivate
=
(
LPIMEPRIVATE
)
ImmLockIMCC
(
lpIMC
->
hPrivate
);
if
(
dwIndex
==
SCS_SETSTR
)
{
HIMCC
newCompStr
;
if
(
!
myPrivate
->
bInComposition
)
{
GenerateIMEMessage
(
hIMC
,
WM_IME_STARTCOMPOSITION
,
0
,
0
);
myPrivate
->
bInComposition
=
TRUE
;
}
flags
=
GCS_COMPSTR
;
if
(
dwCompLen
&&
lpComp
)
{
newCompStr
=
updateCompStr
(
lpIMC
->
hCompStr
,
(
LPWSTR
)
lpComp
,
dwCompLen
/
sizeof
(
WCHAR
));
ImmDestroyIMCC
(
lpIMC
->
hCompStr
);
lpIMC
->
hCompStr
=
newCompStr
;
wParam
=
((
const
WCHAR
*
)
lpComp
)[
0
];
flags
|=
GCS_COMPCLAUSE
|
GCS_COMPATTR
|
GCS_DELTASTART
;
}
else
{
newCompStr
=
updateCompStr
(
lpIMC
->
hCompStr
,
NULL
,
0
);
ImmDestroyIMCC
(
lpIMC
->
hCompStr
);
lpIMC
->
hCompStr
=
newCompStr
;
}
}
UpdateDataInDefaultIMEWindow
(
hIMC
,
myPrivate
->
hwndDefault
,
FALSE
);
GenerateIMEMessage
(
hIMC
,
WM_IME_COMPOSITION
,
wParam
,
flags
);
ImmUnlockIMCC
(
lpIMC
->
hPrivate
);
UnlockRealIMC
(
hIMC
);
return
TRUE
;
}
DWORD
WINAPI
ImeGetImeMenuItems
(
HIMC
hIMC
,
DWORD
dwFlags
,
DWORD
dwType
,
LPIMEMENUITEMINFOW
lpImeParentMenu
,
LPIMEMENUITEMINFOW
lpImeMenu
,
DWORD
dwSize
)
{
FIXME
(
"(%p, %x %x %p %p %x): stub
\n
"
,
hIMC
,
dwFlags
,
dwType
,
lpImeParentMenu
,
lpImeMenu
,
dwSize
);
SetLastError
(
ERROR_CALL_NOT_IMPLEMENTED
);
return
0
;
}
/* Interfaces to XIM and other parts of winex11drv */
void
IME_RegisterClasses
(
HINSTANCE
hImeInst
)
{
WNDCLASSW
wndClass
;
ZeroMemory
(
&
wndClass
,
sizeof
(
WNDCLASSW
));
wndClass
.
style
=
CS_GLOBALCLASS
|
CS_IME
|
CS_HREDRAW
|
CS_VREDRAW
;
wndClass
.
lpfnWndProc
=
(
WNDPROC
)
IME_WindowProc
;
wndClass
.
cbClsExtra
=
0
;
wndClass
.
cbWndExtra
=
2
*
sizeof
(
LONG
);
wndClass
.
hInstance
=
hImeInst
;
wndClass
.
hCursor
=
LoadCursorW
(
NULL
,
(
LPWSTR
)
IDC_ARROW
);
wndClass
.
hIcon
=
LoadIconW
(
NULL
,
(
LPWSTR
)
IDI_APPLICATION
);
wndClass
.
hbrBackground
=
(
HBRUSH
)(
COLOR_WINDOW
+
1
);
wndClass
.
lpszMenuName
=
0
;
wndClass
.
lpszClassName
=
UI_CLASS_NAME
;
RegisterClassW
(
&
wndClass
);
WM_MSIME_SERVICE
=
RegisterWindowMessageA
(
"MSIMEService"
);
WM_MSIME_RECONVERTOPTIONS
=
RegisterWindowMessageA
(
"MSIMEReconvertOptions"
);
WM_MSIME_MOUSE
=
RegisterWindowMessageA
(
"MSIMEMouseOperation"
);
WM_MSIME_RECONVERTREQUEST
=
RegisterWindowMessageA
(
"MSIMEReconvertRequest"
);
WM_MSIME_RECONVERT
=
RegisterWindowMessageA
(
"MSIMEReconvert"
);
WM_MSIME_QUERYPOSITION
=
RegisterWindowMessageA
(
"MSIMEQueryPosition"
);
WM_MSIME_DOCUMENTFEED
=
RegisterWindowMessageA
(
"MSIMEDocumentFeed"
);
}
void
IME_UnregisterClasses
(
HINSTANCE
hImeInst
)
{
UnregisterClassW
(
UI_CLASS_NAME
,
hImeInst
);
}
void
IME_SetOpenStatus
(
BOOL
fOpen
)
{
LPINPUTCONTEXT
lpIMC
;
LPIMEPRIVATE
myPrivate
;
lpIMC
=
LockRealIMC
(
FROM_X11
);
if
(
lpIMC
==
NULL
)
return
;
myPrivate
=
(
LPIMEPRIVATE
)
ImmLockIMCC
(
lpIMC
->
hPrivate
);
if
(
myPrivate
->
bInternalState
&&
fOpen
==
FALSE
)
{
ShowWindow
(
myPrivate
->
hwndDefault
,
SW_HIDE
);
ImmDestroyIMCC
(
lpIMC
->
hCompStr
);
lpIMC
->
hCompStr
=
ImeCreateBlankCompStr
();
}
myPrivate
->
bInternalState
=
fOpen
;
ImmUnlockIMCC
(
lpIMC
->
hPrivate
);
UnlockRealIMC
(
FROM_X11
);
ImmSetOpenStatus
(
RealIMC
(
FROM_X11
),
fOpen
);
}
void
IME_XIMPresent
(
BOOL
present
)
{
hXIMPresent
=
present
;
}
LRESULT
IME_SendMessageToSelectedHWND
(
UINT
msg
,
WPARAM
wParam
,
LPARAM
lParam
)
{
LPINPUTCONTEXT
lpIMC
;
LRESULT
rc
=
0
;
if
(
!
hSelectedFrom
)
return
rc
;
lpIMC
=
LockRealIMC
(
FROM_X11
);
if
(
lpIMC
)
rc
=
SendMessageW
(
lpIMC
->
hWnd
,
msg
,
wParam
,
lParam
);
UnlockRealIMC
(
FROM_X11
);
return
rc
;
}
INT
IME_GetCursorPos
()
{
LPINPUTCONTEXT
lpIMC
;
INT
rc
=
0
;
LPCOMPOSITIONSTRING
compstr
;
if
(
!
hSelectedFrom
)
return
rc
;
lpIMC
=
LockRealIMC
(
FROM_X11
);
if
(
lpIMC
)
{
compstr
=
(
LPCOMPOSITIONSTRING
)
ImmLockIMCC
(
lpIMC
->
hCompStr
);
rc
=
compstr
->
dwCursorPos
;
ImmUnlockIMCC
(
lpIMC
->
hCompStr
);
}
UnlockRealIMC
(
FROM_X11
);
return
rc
;
}
void
IME_UpdateAssociation
(
HWND
focus
)
{
ImmGetContext
(
focus
);
if
(
!
focus
||
!
hSelectedFrom
)
return
;
ImmAssociateContext
(
focus
,
RealIMC
(
FROM_X11
));
}
BOOL
IME_SetCompositionString
(
DWORD
dwIndex
,
LPCVOID
lpComp
,
DWORD
dwCompLen
,
LPCVOID
lpRead
,
DWORD
dwReadLen
)
{
return
ImeSetCompositionString
(
FROM_X11
,
dwIndex
,
lpComp
,
dwCompLen
,
lpRead
,
dwReadLen
);
}
BOOL
IME_NotifyIME
(
DWORD
dwAction
,
DWORD
dwIndex
,
DWORD
dwValue
)
{
return
NotifyIME
(
FROM_X11
,
dwAction
,
dwIndex
,
dwValue
);
}
/*****
* Internal functions to help with IME window management
*/
static
void
PaintDefaultIMEWnd
(
HIMC
hIMC
,
HWND
hwnd
)
{
PAINTSTRUCT
ps
;
RECT
rect
;
HDC
hdc
;
LPCOMPOSITIONSTRING
compstr
;
LPBYTE
compdata
=
NULL
;
HMONITOR
monitor
;
MONITORINFO
mon_info
;
INT
offX
=
0
,
offY
=
0
;
LPINPUTCONTEXT
lpIMC
;
lpIMC
=
LockRealIMC
(
hIMC
);
if
(
lpIMC
==
NULL
)
return
;
hdc
=
BeginPaint
(
hwnd
,
&
ps
);
GetClientRect
(
hwnd
,
&
rect
);
FillRect
(
hdc
,
&
rect
,
(
HBRUSH
)(
COLOR_WINDOW
+
1
));
compdata
=
ImmLockIMCC
(
lpIMC
->
hCompStr
);
compstr
=
(
LPCOMPOSITIONSTRING
)
compdata
;
if
(
compstr
->
dwCompStrLen
&&
compstr
->
dwCompStrOffset
)
{
SIZE
size
;
POINT
pt
;
HFONT
oldfont
=
NULL
;
LPWSTR
CompString
;
LPIMEPRIVATE
myPrivate
;
CompString
=
(
LPWSTR
)(
compdata
+
compstr
->
dwCompStrOffset
);
myPrivate
=
(
LPIMEPRIVATE
)
ImmLockIMCC
(
lpIMC
->
hPrivate
);
if
(
myPrivate
->
textfont
)
oldfont
=
SelectObject
(
hdc
,
myPrivate
->
textfont
);
ImmUnlockIMCC
(
lpIMC
->
hPrivate
);
GetTextExtentPoint32W
(
hdc
,
CompString
,
compstr
->
dwCompStrLen
,
&
size
);
pt
.
x
=
size
.
cx
;
pt
.
y
=
size
.
cy
;
LPtoDP
(
hdc
,
&
pt
,
1
);
/*
* How this works based on tests on windows:
* CFS_POINT: then we start our window at the point and grow it as large
* as it needs to be for the string.
* CFS_RECT: we still use the ptCurrentPos as a starting point and our
* window is only as large as we need for the string, but we do not
* grow such that our window exceeds the given rect. Wrapping if
* needed and possible. If our ptCurrentPos is outside of our rect
* then no window is displayed.
* CFS_FORCE_POSITION: appears to behave just like CFS_POINT
* maybe becase the default MSIME does not do any IME adjusting.
*/
if
(
lpIMC
->
cfCompForm
.
dwStyle
!=
CFS_DEFAULT
)
{
POINT
cpt
=
lpIMC
->
cfCompForm
.
ptCurrentPos
;
ClientToScreen
(
lpIMC
->
hWnd
,
&
cpt
);
rect
.
left
=
cpt
.
x
;
rect
.
top
=
cpt
.
y
;
rect
.
right
=
rect
.
left
+
pt
.
x
;
rect
.
bottom
=
rect
.
top
+
pt
.
y
;
monitor
=
MonitorFromPoint
(
cpt
,
MONITOR_DEFAULTTOPRIMARY
);
}
else
/* CFS_DEFAULT */
{
/* Windows places the default IME window in the bottom left */
HWND
target
=
lpIMC
->
hWnd
;
if
(
!
target
)
target
=
GetFocus
();
GetWindowRect
(
target
,
&
rect
);
rect
.
top
=
rect
.
bottom
;
rect
.
right
=
rect
.
left
+
pt
.
x
+
20
;
rect
.
bottom
=
rect
.
top
+
pt
.
y
+
20
;
offX
=
offY
=
10
;
monitor
=
MonitorFromWindow
(
target
,
MONITOR_DEFAULTTOPRIMARY
);
}
if
(
lpIMC
->
cfCompForm
.
dwStyle
==
CFS_RECT
)
{
RECT
client
;
client
=
lpIMC
->
cfCompForm
.
rcArea
;
MapWindowPoints
(
lpIMC
->
hWnd
,
0
,
(
POINT
*
)
&
client
,
2
);
IntersectRect
(
&
rect
,
&
rect
,
&
client
);
/* TODO: Wrap the input if needed */
}
if
(
lpIMC
->
cfCompForm
.
dwStyle
==
CFS_DEFAULT
)
{
/* make sure we are on the desktop */
mon_info
.
cbSize
=
sizeof
(
mon_info
);
GetMonitorInfoW
(
monitor
,
&
mon_info
);
if
(
rect
.
bottom
>
mon_info
.
rcWork
.
bottom
)
{
int
shift
=
rect
.
bottom
-
mon_info
.
rcWork
.
bottom
;
rect
.
top
-=
shift
;
rect
.
bottom
-=
shift
;
}
if
(
rect
.
left
<
0
)
{
rect
.
right
-=
rect
.
left
;
rect
.
left
=
0
;
}
if
(
rect
.
right
>
mon_info
.
rcWork
.
right
)
{
int
shift
=
rect
.
right
-
mon_info
.
rcWork
.
right
;
rect
.
left
-=
shift
;
rect
.
right
-=
shift
;
}
}
SetWindowPos
(
hwnd
,
HWND_TOPMOST
,
rect
.
left
,
rect
.
top
,
rect
.
right
-
rect
.
left
,
rect
.
bottom
-
rect
.
top
,
SWP_NOACTIVATE
);
TextOutW
(
hdc
,
offX
,
offY
,
CompString
,
compstr
->
dwCompStrLen
);
if
(
oldfont
)
SelectObject
(
hdc
,
oldfont
);
}
ImmUnlockIMCC
(
lpIMC
->
hCompStr
);
EndPaint
(
hwnd
,
&
ps
);
UnlockRealIMC
(
hIMC
);
}
static
void
UpdateDataInDefaultIMEWindow
(
HIMC
hIMC
,
HWND
hwnd
,
BOOL
showable
)
{
LPCOMPOSITIONSTRING
compstr
;
LPINPUTCONTEXT
lpIMC
;
lpIMC
=
LockRealIMC
(
hIMC
);
if
(
lpIMC
==
NULL
)
return
;
if
(
lpIMC
->
hCompStr
)
compstr
=
ImmLockIMCC
(
lpIMC
->
hCompStr
);
else
compstr
=
NULL
;
if
(
compstr
==
NULL
||
compstr
->
dwCompStrLen
==
0
)
ShowWindow
(
hwnd
,
SW_HIDE
);
else
if
(
showable
)
ShowWindow
(
hwnd
,
SW_SHOWNOACTIVATE
);
RedrawWindow
(
hwnd
,
NULL
,
NULL
,
RDW_ERASENOW
|
RDW_INVALIDATE
);
if
(
compstr
!=
NULL
)
ImmUnlockIMCC
(
lpIMC
->
hCompStr
);
UnlockRealIMC
(
hIMC
);
}
static
void
DefaultIMEComposition
(
HIMC
hIMC
,
HWND
hwnd
,
LPARAM
lParam
)
{
TRACE
(
"IME message WM_IME_COMPOSITION 0x%lx
\n
"
,
lParam
);
if
(
lParam
&
GCS_RESULTSTR
)
{
LPCOMPOSITIONSTRING
compstr
;
LPBYTE
compdata
;
LPWSTR
ResultStr
;
HIMCC
newCompStr
;
LPINPUTCONTEXT
lpIMC
;
lpIMC
=
LockRealIMC
(
hIMC
);
if
(
lpIMC
==
NULL
)
return
;
TRACE
(
"Posting result as IME_CHAR
\n
"
);
compdata
=
ImmLockIMCC
(
lpIMC
->
hCompStr
);
compstr
=
(
LPCOMPOSITIONSTRING
)
compdata
;
ResultStr
=
(
LPWSTR
)(
compdata
+
compstr
->
dwResultStrOffset
);
GenerateIMECHARMessages
(
hIMC
,
ResultStr
,
compstr
->
dwResultStrLen
);
ImmUnlockIMCC
(
lpIMC
->
hCompStr
);
/* clear the buffer */
newCompStr
=
updateResultStr
(
lpIMC
->
hCompStr
,
NULL
,
0
);
ImmDestroyIMCC
(
lpIMC
->
hCompStr
);
lpIMC
->
hCompStr
=
newCompStr
;
UnlockRealIMC
(
hIMC
);
}
else
UpdateDataInDefaultIMEWindow
(
hIMC
,
hwnd
,
TRUE
);
}
static
void
DefaultIMEStartComposition
(
HIMC
hIMC
,
HWND
hwnd
)
{
LPINPUTCONTEXT
lpIMC
;
lpIMC
=
LockRealIMC
(
hIMC
);
if
(
lpIMC
==
NULL
)
return
;
TRACE
(
"IME message WM_IME_STARTCOMPOSITION
\n
"
);
lpIMC
->
hWnd
=
GetFocus
();
ShowWindow
(
hwnd
,
SW_SHOWNOACTIVATE
);
UnlockRealIMC
(
hIMC
);
}
static
LRESULT
ImeHandleNotify
(
HIMC
hIMC
,
HWND
hwnd
,
UINT
msg
,
WPARAM
wParam
,
LPARAM
lParam
)
{
switch
(
wParam
)
{
case
IMN_OPENSTATUSWINDOW
:
FIXME
(
"WM_IME_NOTIFY:IMN_OPENSTATUSWINDOW
\n
"
);
break
;
case
IMN_CLOSESTATUSWINDOW
:
FIXME
(
"WM_IME_NOTIFY:IMN_CLOSESTATUSWINDOW
\n
"
);
break
;
case
IMN_OPENCANDIDATE
:
FIXME
(
"WM_IME_NOTIFY:IMN_OPENCANDIDATE
\n
"
);
break
;
case
IMN_CHANGECANDIDATE
:
FIXME
(
"WM_IME_NOTIFY:IMN_CHANGECANDIDATE
\n
"
);
break
;
case
IMN_CLOSECANDIDATE
:
FIXME
(
"WM_IME_NOTIFY:IMN_CLOSECANDIDATE
\n
"
);
break
;
case
IMN_SETCONVERSIONMODE
:
FIXME
(
"WM_IME_NOTIFY:IMN_SETCONVERSIONMODE
\n
"
);
break
;
case
IMN_SETSENTENCEMODE
:
FIXME
(
"WM_IME_NOTIFY:IMN_SETSENTENCEMODE
\n
"
);
break
;
case
IMN_SETOPENSTATUS
:
FIXME
(
"WM_IME_NOTIFY:IMN_SETOPENSTATUS
\n
"
);
break
;
case
IMN_SETCANDIDATEPOS
:
FIXME
(
"WM_IME_NOTIFY:IMN_SETCANDIDATEPOS
\n
"
);
break
;
case
IMN_SETCOMPOSITIONFONT
:
FIXME
(
"WM_IME_NOTIFY:IMN_SETCOMPOSITIONFONT
\n
"
);
break
;
case
IMN_SETCOMPOSITIONWINDOW
:
FIXME
(
"WM_IME_NOTIFY:IMN_SETCOMPOSITIONWINDOW
\n
"
);
break
;
case
IMN_GUIDELINE
:
FIXME
(
"WM_IME_NOTIFY:IMN_GUIDELINE
\n
"
);
break
;
case
IMN_SETSTATUSWINDOWPOS
:
FIXME
(
"WM_IME_NOTIFY:IMN_SETSTATUSWINDOWPOS
\n
"
);
break
;
default:
FIXME
(
"WM_IME_NOTIFY:<Unknown 0x%lx>
\n
"
,
wParam
);
break
;
}
return
0
;
}
static
LRESULT
WINAPI
IME_WindowProc
(
HWND
hwnd
,
UINT
msg
,
WPARAM
wParam
,
LPARAM
lParam
)
{
LRESULT
rc
=
0
;
HIMC
hIMC
;
TRACE
(
"Incoming Message 0x%x (0x%08lx, 0x%08lx)
\n
"
,
msg
,
wParam
,
lParam
);
/*
* Each UI window contains the current Input Context.
* This Input Context can be obtained by calling GetWindowLong
* with IMMGWL_IMC when the UI window receives a WM_IME_xxx message.
* The UI window can refer to this Input Context and handles the
* messages.
*/
hIMC
=
(
HIMC
)
GetWindowLongW
(
hwnd
,
IMMGWL_IMC
);
if
(
!
hIMC
)
hIMC
=
RealIMC
(
FROM_X11
);
/* if we have no hIMC there are many messages we cannot process */
if
(
hIMC
==
NULL
)
{
switch
(
msg
)
{
case
WM_IME_STARTCOMPOSITION
:
case
WM_IME_ENDCOMPOSITION
:
case
WM_IME_COMPOSITION
:
case
WM_IME_NOTIFY
:
case
WM_IME_CONTROL
:
case
WM_IME_COMPOSITIONFULL
:
case
WM_IME_SELECT
:
case
WM_IME_CHAR
:
return
0L
;
default:
break
;
}
}
switch
(
msg
)
{
case
WM_CREATE
:
{
LPIMEPRIVATE
myPrivate
;
LPINPUTCONTEXT
lpIMC
;
SetWindowTextA
(
hwnd
,
"Wine Ime Active"
);
lpIMC
=
LockRealIMC
(
hIMC
);
if
(
lpIMC
)
{
myPrivate
=
(
LPIMEPRIVATE
)
ImmLockIMCC
(
lpIMC
->
hPrivate
);
myPrivate
->
hwndDefault
=
hwnd
;
ImmUnlockIMCC
(
lpIMC
->
hPrivate
);
}
UnlockRealIMC
(
hIMC
);
return
TRUE
;
}
case
WM_PAINT
:
PaintDefaultIMEWnd
(
hIMC
,
hwnd
);
return
FALSE
;
case
WM_NCCREATE
:
return
TRUE
;
case
WM_SETFOCUS
:
if
(
wParam
)
SetFocus
((
HWND
)
wParam
);
else
FIXME
(
"Received focus, should never have focus
\n
"
);
break
;
case
WM_IME_COMPOSITION
:
DefaultIMEComposition
(
hIMC
,
hwnd
,
lParam
);
break
;
case
WM_IME_STARTCOMPOSITION
:
DefaultIMEStartComposition
(
hIMC
,
hwnd
);
break
;
case
WM_IME_ENDCOMPOSITION
:
TRACE
(
"IME message %s, 0x%lx, 0x%lx
\n
"
,
"WM_IME_ENDCOMPOSITION"
,
wParam
,
lParam
);
ShowWindow
(
hwnd
,
SW_HIDE
);
break
;
case
WM_IME_SELECT
:
TRACE
(
"IME message %s, 0x%lx, 0x%lx
\n
"
,
"WM_IME_SELECT"
,
wParam
,
lParam
);
break
;
case
WM_IME_CONTROL
:
TRACE
(
"IME message %s, 0x%lx, 0x%lx
\n
"
,
"WM_IME_CONTROL"
,
wParam
,
lParam
);
rc
=
1
;
break
;
case
WM_IME_NOTIFY
:
rc
=
ImeHandleNotify
(
hIMC
,
hwnd
,
msg
,
wParam
,
lParam
);
break
;
default:
TRACE
(
"Non-standard message 0x%x
\n
"
,
msg
);
}
/* check the MSIME messages */
if
(
msg
==
WM_MSIME_SERVICE
)
{
TRACE
(
"IME message %s, 0x%lx, 0x%lx
\n
"
,
"WM_MSIME_SERVICE"
,
wParam
,
lParam
);
rc
=
FALSE
;
}
else
if
(
msg
==
WM_MSIME_RECONVERTOPTIONS
)
{
TRACE
(
"IME message %s, 0x%lx, 0x%lx
\n
"
,
"WM_MSIME_RECONVERTOPTIONS"
,
wParam
,
lParam
);
}
else
if
(
msg
==
WM_MSIME_MOUSE
)
{
TRACE
(
"IME message %s, 0x%lx, 0x%lx
\n
"
,
"WM_MSIME_MOUSE"
,
wParam
,
lParam
);
}
else
if
(
msg
==
WM_MSIME_RECONVERTREQUEST
)
{
TRACE
(
"IME message %s, 0x%lx, 0x%lx
\n
"
,
"WM_MSIME_RECONVERTREQUEST"
,
wParam
,
lParam
);
}
else
if
(
msg
==
WM_MSIME_RECONVERT
)
{
TRACE
(
"IME message %s, 0x%lx, 0x%lx
\n
"
,
"WM_MSIME_RECONVERT"
,
wParam
,
lParam
);
}
else
if
(
msg
==
WM_MSIME_QUERYPOSITION
)
{
TRACE
(
"IME message %s, 0x%lx, 0x%lx
\n
"
,
"WM_MSIME_QUERYPOSITION"
,
wParam
,
lParam
);
}
else
if
(
msg
==
WM_MSIME_DOCUMENTFEED
)
{
TRACE
(
"IME message %s, 0x%lx, 0x%lx
\n
"
,
"WM_MSIME_DOCUMENTFEED"
,
wParam
,
lParam
);
}
/* DefWndProc if not an IME message */
if
(
!
rc
&&
!
((
msg
>=
WM_IME_STARTCOMPOSITION
&&
msg
<=
WM_IME_KEYLAST
)
||
(
msg
>=
WM_IME_SETCONTEXT
&&
msg
<=
WM_IME_KEYUP
)))
rc
=
DefWindowProcW
(
hwnd
,
msg
,
wParam
,
lParam
);
return
rc
;
}
dlls/winex11.drv/winex11.drv.spec
View file @
6dca48fe
...
...
@@ -145,3 +145,21 @@
@ cdecl wglShareLists(long long) X11DRV_wglShareLists
@ cdecl wglUseFontBitmapsA(ptr long long long) X11DRV_wglUseFontBitmapsA
@ cdecl wglUseFontBitmapsW(ptr long long long) X11DRV_wglUseFontBitmapsW
#IME Interface
@ stdcall ImeInquire(ptr wstr wstr)
@ stdcall ImeConfigure(long long long ptr)
@ stdcall ImeDestroy(long)
@ stdcall ImeEscape(long long ptr)
@ stdcall ImeSelect(long long)
@ stdcall ImeSetActiveContext(long long)
@ stdcall ImeToAsciiEx(long long ptr ptr long long)
@ stdcall NotifyIME(long long long long)
@ stdcall ImeRegisterWord(wstr long wstr)
@ stdcall ImeUnregisterWord(wstr long wstr)
@ stdcall ImeEnumRegisterWord(ptr wstr long wstr ptr)
@ stdcall ImeSetCompositionString(long long ptr long ptr long)
@ stdcall ImeConversionList(long wstr ptr long long)
@ stdcall ImeProcessKey(long long long ptr)
@ stdcall ImeGetRegisterWordStyle(wstr long wstr)
@ stdcall ImeGetImeMenuItems(long long long ptr ptr long)
dlls/winex11.drv/x11drv.h
View file @
6dca48fe
...
...
@@ -277,6 +277,20 @@ extern BOOL destroy_glxpixmap(Display *display, XID glxpixmap);
extern
XIC
X11DRV_CreateIC
(
XIM
xim
,
Display
*
display
,
Window
win
);
extern
XIM
X11DRV_SetupXIM
(
Display
*
display
,
const
char
*
input_style
);
extern
void
X11DRV_XIMLookupChars
(
const
char
*
str
,
DWORD
count
);
extern
void
X11DRV_ForceXIMReset
(
HWND
hwnd
);
/* IME support */
extern
void
IME_RegisterClasses
(
HINSTANCE
hImeInst
);
extern
void
IME_UnregisterClasses
(
HINSTANCE
hImeInst
);
extern
void
IME_SetOpenStatus
(
BOOL
fOpen
);
extern
void
IME_XIMPresent
(
BOOL
present
);
extern
LRESULT
IME_SendMessageToSelectedHWND
(
UINT
msg
,
WPARAM
wParam
,
LPARAM
lParam
);
extern
INT
IME_GetCursorPos
();
extern
void
IME_UpdateAssociation
(
HWND
focus
);
extern
BOOL
IME_SetCompositionString
(
DWORD
dwIndex
,
LPCVOID
lpComp
,
DWORD
dwCompLen
,
LPCVOID
lpRead
,
DWORD
dwReadLen
);
extern
BOOL
IME_NotifyIME
(
DWORD
dwAction
,
DWORD
dwIndex
,
DWORD
dwValue
);
extern
void
X11DRV_XDND_EnterEvent
(
HWND
hWnd
,
XClientMessageEvent
*
event
);
extern
void
X11DRV_XDND_PositionEvent
(
HWND
hWnd
,
XClientMessageEvent
*
event
);
...
...
dlls/winex11.drv/x11drv_main.c
View file @
6dca48fe
...
...
@@ -672,12 +672,14 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
{
case
DLL_PROCESS_ATTACH
:
ret
=
process_attach
();
IME_RegisterClasses
(
hinst
);
break
;
case
DLL_THREAD_DETACH
:
thread_detach
();
break
;
case
DLL_PROCESS_DETACH
:
process_detach
();
IME_UnregisterClasses
(
hinst
);
break
;
}
return
ret
;
...
...
dlls/winex11.drv/xim.c
View file @
6dca48fe
...
...
@@ -500,6 +500,8 @@ XIM X11DRV_SetupXIM(Display *display, const char *input_style)
}
wine_tsx11_unlock
();
IME_XIMPresent
(
TRUE
);
IME_UpdateAssociation
(
NULL
);
if
(
!
hImmDll
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment