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
192b8dbf
Commit
192b8dbf
authored
Apr 21, 2013
by
Ken Thomases
Committed by
Alexandre Julliard
Apr 22, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winemac: Implement an IME that uses the OS X input methods.
Developed with Aric Stewart.
parent
72be2327
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
1875 additions
and
2 deletions
+1875
-2
Makefile.in
dlls/winemac.drv/Makefile.in
+2
-1
cocoa_app.h
dlls/winemac.drv/cocoa_app.h
+2
-0
cocoa_app.m
dlls/winemac.drv/cocoa_app.m
+49
-0
cocoa_event.m
dlls/winemac.drv/cocoa_event.m
+4
-0
cocoa_window.h
dlls/winemac.drv/cocoa_window.h
+3
-0
cocoa_window.m
dlls/winemac.drv/cocoa_window.m
+199
-1
event.c
dlls/winemac.drv/event.c
+10
-0
ime.c
dlls/winemac.drv/ime.c
+1511
-0
keyboard.c
dlls/winemac.drv/keyboard.c
+47
-0
macdrv.h
dlls/winemac.drv/macdrv.h
+15
-0
macdrv_cocoa.h
dlls/winemac.drv/macdrv_cocoa.h
+14
-0
macdrv_main.c
dlls/winemac.drv/macdrv_main.c
+1
-0
winemac.drv.spec
dlls/winemac.drv/winemac.drv.spec
+18
-0
No files found.
dlls/winemac.drv/Makefile.in
View file @
192b8dbf
MODULE
=
winemac.drv
IMPORTS
=
uuid user32 gdi32 advapi32
DELAYIMPORTS
=
ole32 shell32
DELAYIMPORTS
=
ole32 shell32
imm32
EXTRALIBS
=
-framework
AppKit
-framework
Carbon
-framework
Security
-framework
OpenGL
-framework
IOKit
C_SRCS
=
\
...
...
@@ -10,6 +10,7 @@ C_SRCS = \
event.c
\
gdi.c
\
image.c
\
ime.c
\
keyboard.c
\
macdrv_main.c
\
mouse.c
\
...
...
dlls/winemac.drv/cocoa_app.h
View file @
192b8dbf
...
...
@@ -52,6 +52,8 @@ enum {
CGEventSourceKeyboardType
keyboardType
;
NSEvent
*
lastFlagsChanged
;
BOOL
inputSourceIsInputMethod
;
BOOL
inputSourceIsInputMethodValid
;
CGFloat
primaryScreenHeight
;
BOOL
primaryScreenHeightValid
;
...
...
dlls/winemac.drv/cocoa_app.m
View file @
192b8dbf
...
...
@@ -81,6 +81,7 @@ int macdrv_err_on;
@property
(
copy
,
nonatomic
)
NSArray
*
cursorFrames
;
@property
(
retain
,
nonatomic
)
NSTimer
*
cursorTimer
;
@property
(
retain
,
nonatomic
)
NSImage
*
applicationIcon
;
@property
(
readonly
,
nonatomic
)
BOOL
inputSourceIsInputMethod
;
-
(
void
)
setupObservations
;
-
(
void
)
applicationDidBecomeActive
:(
NSNotification
*
)
notification
;
...
...
@@ -96,6 +97,19 @@ int macdrv_err_on;
@synthesize
orderedWineWindows
,
applicationIcon
;
@synthesize
cursorFrames
,
cursorTimer
;
+
(
void
)
initialize
{
if
(
self
==
[
WineApplicationController
class
])
{
NSDictionary
*
defaults
=
[
NSDictionary
dictionaryWithObjectsAndKeys
:
@""
,
@"NSQuotedKeystrokeBinding"
,
@""
,
@"NSRepeatCountBinding"
,
[
NSNumber
numberWithBool
:
NO
],
@"ApplePressAndHoldEnabled"
,
nil
];
[[
NSUserDefaults
standardUserDefaults
]
registerDefaults
:
defaults
];
}
}
+
(
WineApplicationController
*
)
sharedController
{
static
WineApplicationController
*
sharedController
;
...
...
@@ -323,6 +337,8 @@ int macdrv_err_on;
{
TISInputSourceRef
inputSource
;
inputSourceIsInputMethodValid
=
FALSE
;
inputSource
=
TISCopyCurrentKeyboardLayoutInputSource
();
if
(
inputSource
)
{
...
...
@@ -1227,6 +1243,25 @@ int macdrv_err_on;
[
NSTextInputContext
self
];
}
-
(
BOOL
)
inputSourceIsInputMethod
{
if
(
!
inputSourceIsInputMethodValid
)
{
TISInputSourceRef
inputSource
=
TISCopyCurrentKeyboardInputSource
();
if
(
inputSource
)
{
CFStringRef
type
=
TISGetInputSourceProperty
(
inputSource
,
kTISPropertyInputSourceType
);
inputSourceIsInputMethod
=
!
CFEqual
(
type
,
kTISTypeKeyboardLayout
);
CFRelease
(
inputSource
);
}
else
inputSourceIsInputMethod
=
FALSE
;
inputSourceIsInputMethodValid
=
TRUE
;
}
return
inputSourceIsInputMethod
;
}
/*
* ---------- NSApplicationDelegate methods ----------
...
...
@@ -1646,3 +1681,17 @@ void macdrv_quit_reply(int reply)
[
NSApp
replyToApplicationShouldTerminate
:
reply
];
});
}
/***********************************************************************
* macdrv_using_input_method
*/
int
macdrv_using_input_method
(
void
)
{
__block
BOOL
ret
;
OnMainThread
(
^
{
ret
=
[[
WineApplicationController
sharedController
]
inputSourceIsInputMethod
];
});
return
ret
;
}
dlls/winemac.drv/cocoa_event.m
View file @
192b8dbf
...
...
@@ -453,6 +453,10 @@ void macdrv_release_event(macdrv_event *event)
switch
(
event
->
type
)
{
case
IM_SET_TEXT
:
if
(
event
->
im_set_text
.
text
)
CFRelease
(
event
->
im_set_text
.
text
);
break
;
case
KEYBOARD_CHANGED
:
CFRelease
(
event
->
keyboard_changed
.
uchr
);
break
;
...
...
dlls/winemac.drv/cocoa_window.h
View file @
192b8dbf
...
...
@@ -54,6 +54,9 @@
NSTimer
*
liveResizeDisplayTimer
;
void
*
imeData
;
BOOL
commandDone
;
BOOL
causing_becomeKeyWindow
;
BOOL
ignore_windowMiniaturize
;
BOOL
ignore_windowDeminiaturize
;
...
...
dlls/winemac.drv/cocoa_window.m
View file @
192b8dbf
...
...
@@ -118,10 +118,13 @@ static inline void fix_generic_modifiers_by_device(NSUInteger* modifiers)
}
@interface
WineContentView
:
NSView
@interface
WineContentView
:
NSView
<
NSTextInputClient
>
{
NSMutableArray
*
glContexts
;
NSMutableArray
*
pendingGlContexts
;
NSMutableAttributedString
*
markedText
;
NSRange
markedTextSelection
;
}
-
(
void
)
addGLContext
:
(
WineOpenGLContext
*
)
context
;
...
...
@@ -154,6 +157,9 @@ static inline void fix_generic_modifiers_by_device(NSUInteger* modifiers)
@property
(
readwrite
,
nonatomic
)
NSInteger
levelWhenActive
;
@property
(
assign
,
nonatomic
)
void
*
imeData
;
@property
(
nonatomic
)
BOOL
commandDone
;
@end
...
...
@@ -161,6 +167,7 @@ static inline void fix_generic_modifiers_by_device(NSUInteger* modifiers)
-
(
void
)
dealloc
{
[
markedText
release
];
[
glContexts
release
];
[
pendingGlContexts
release
];
[
super
dealloc
];
...
...
@@ -289,6 +296,147 @@ static inline void fix_generic_modifiers_by_device(NSUInteger* modifiers)
return
YES
;
}
-
(
BOOL
)
acceptsFirstResponder
{
return
[[
self
window
]
contentView
]
==
self
;
}
-
(
void
)
completeText
:
(
NSString
*
)
text
{
macdrv_event
*
event
;
WineWindow
*
window
=
(
WineWindow
*
)[
self
window
];
event
=
macdrv_create_event
(
IM_SET_TEXT
,
window
);
event
->
im_set_text
.
data
=
[
window
imeData
];
event
->
im_set_text
.
text
=
(
CFStringRef
)[
text
copy
];
event
->
im_set_text
.
complete
=
TRUE
;
[[
window
queue
]
postEvent
:
event
];
macdrv_release_event
(
event
);
[
markedText
deleteCharactersInRange
:
NSMakeRange
(
0
,
[
markedText
length
])];
markedTextSelection
=
NSMakeRange
(
0
,
0
);
[[
self
inputContext
]
discardMarkedText
];
}
/*
* ---------- NSTextInputClient methods ----------
*/
-
(
NSTextInputContext
*
)
inputContext
{
if
(
!
markedText
)
markedText
=
[[
NSMutableAttributedString
alloc
]
init
];
return
[
super
inputContext
];
}
-
(
void
)
insertText
:
(
id
)
string
replacementRange
:
(
NSRange
)
replacementRange
{
if
([
string
isKindOfClass
:[
NSAttributedString
class
]])
string
=
[
string
string
];
if
([
string
isKindOfClass
:[
NSString
class
]])
[
self
completeText
:
string
];
}
-
(
void
)
doCommandBySelector
:
(
SEL
)
aSelector
{
[(
WineWindow
*
)[
self
window
]
setCommandDone
:
TRUE
];
}
-
(
void
)
setMarkedText
:
(
id
)
string
selectedRange
:
(
NSRange
)
selectedRange
replacementRange
:
(
NSRange
)
replacementRange
{
if
([
string
isKindOfClass
:[
NSAttributedString
class
]])
string
=
[
string
string
];
if
([
string
isKindOfClass
:[
NSString
class
]])
{
macdrv_event
*
event
;
WineWindow
*
window
=
(
WineWindow
*
)[
self
window
];
if
(
replacementRange
.
location
==
NSNotFound
)
replacementRange
=
NSMakeRange
(
0
,
[
markedText
length
]);
[
markedText
replaceCharactersInRange
:
replacementRange
withString
:
string
];
markedTextSelection
=
selectedRange
;
markedTextSelection
.
location
+=
replacementRange
.
location
;
event
=
macdrv_create_event
(
IM_SET_TEXT
,
window
);
event
->
im_set_text
.
data
=
[
window
imeData
];
event
->
im_set_text
.
text
=
(
CFStringRef
)[[
markedText
string
]
copy
];
event
->
im_set_text
.
complete
=
FALSE
;
[[
window
queue
]
postEvent
:
event
];
macdrv_release_event
(
event
);
event
=
macdrv_create_event
(
IM_SET_CURSOR_POS
,
window
);
event
->
im_set_cursor_pos
.
data
=
[
window
imeData
];
event
->
im_set_cursor_pos
.
pos
=
markedTextSelection
.
location
;
[[
window
queue
]
postEvent
:
event
];
macdrv_release_event
(
event
);
}
}
-
(
void
)
unmarkText
{
[
self
completeText
:
nil
];
}
-
(
NSRange
)
selectedRange
{
return
markedTextSelection
;
}
-
(
NSRange
)
markedRange
{
NSRange
range
=
NSMakeRange
(
0
,
[
markedText
length
]);
if
(
!
range
.
length
)
range
.
location
=
NSNotFound
;
return
range
;
}
-
(
BOOL
)
hasMarkedText
{
return
[
markedText
length
]
>
0
;
}
-
(
NSAttributedString
*
)
attributedSubstringForProposedRange
:
(
NSRange
)
aRange
actualRange
:
(
NSRangePointer
)
actualRange
{
if
(
aRange
.
location
>=
[
markedText
length
])
return
nil
;
aRange
=
NSIntersectionRange
(
aRange
,
NSMakeRange
(
0
,
[
markedText
length
]));
if
(
actualRange
)
*
actualRange
=
aRange
;
return
[
markedText
attributedSubstringFromRange
:
aRange
];
}
-
(
NSArray
*
)
validAttributesForMarkedText
{
return
[
NSArray
array
];
}
-
(
NSRect
)
firstRectForCharacterRange
:
(
NSRange
)
aRange
actualRange
:
(
NSRangePointer
)
actualRange
{
aRange
=
NSIntersectionRange
(
aRange
,
NSMakeRange
(
0
,
[
markedText
length
]));
if
(
actualRange
)
*
actualRange
=
aRange
;
return
NSMakeRect
(
100
,
100
,
aRange
.
length
?
1
:
0
,
12
);
}
-
(
NSUInteger
)
characterIndexForPoint
:
(
NSPoint
)
aPoint
{
return
NSNotFound
;
}
-
(
NSInteger
)
windowLevel
{
return
[[
self
window
]
level
];
}
@end
...
...
@@ -300,6 +448,7 @@ static inline void fix_generic_modifiers_by_device(NSUInteger* modifiers)
@synthesize
colorKeyed
,
colorKeyRed
,
colorKeyGreen
,
colorKeyBlue
;
@synthesize
usePerPixelAlpha
;
@synthesize
levelWhenActive
;
@synthesize
imeData
,
commandDone
;
+
(
WineWindow
*
)
createWindowWithFeatures
:(
const
struct
macdrv_window_features
*
)
wf
windowFrame
:(
NSRect
)
window_frame
...
...
@@ -356,6 +505,7 @@ static inline void fix_generic_modifiers_by_device(NSUInteger* modifiers)
[
contentView
addTrackingArea
:
trackingArea
];
[
window
setContentView
:
contentView
];
[
window
setInitialFirstResponder
:
contentView
];
return
window
;
}
...
...
@@ -1844,3 +1994,51 @@ uint32_t macdrv_window_background_color(void)
return
result
;
}
/***********************************************************************
* macdrv_send_text_input_event
*/
int
macdrv_send_text_input_event
(
int
pressed
,
unsigned
int
flags
,
int
repeat
,
int
keyc
,
void
*
data
)
{
__block
BOOL
ret
;
OnMainThread
(
^
{
WineWindow
*
window
=
(
WineWindow
*
)[
NSApp
keyWindow
];
if
(
!
[
window
isKindOfClass
:[
WineWindow
class
]])
{
window
=
(
WineWindow
*
)[
NSApp
mainWindow
];
if
(
!
[
window
isKindOfClass
:[
WineWindow
class
]]
&&
[[
NSApp
orderedWineWindows
]
count
])
{
window
=
[[
NSApp
orderedWineWindows
]
objectAtIndex
:
0
];
if
(
!
[
window
isKindOfClass
:[
WineWindow
class
]])
window
=
nil
;
}
}
if
(
window
)
{
NSUInteger
localFlags
=
flags
;
CGEventRef
c
;
NSEvent
*
event
;
window
.
imeData
=
data
;
fix_device_modifiers_by_generic
(
&
localFlags
);
// An NSEvent created with +keyEventWithType:... is internally marked
// as synthetic and doesn't get sent through input methods. But one
// created from a CGEvent doesn't have that problem.
c
=
CGEventCreateKeyboardEvent
(
NULL
,
keyc
,
pressed
);
CGEventSetFlags
(
c
,
localFlags
);
CGEventSetIntegerValueField
(
c
,
kCGKeyboardEventAutorepeat
,
repeat
);
event
=
[
NSEvent
eventWithCGEvent
:
c
];
CFRelease
(
c
);
window
.
commandDone
=
FALSE
;
ret
=
[[[
window
contentView
]
inputContext
]
handleEvent
:
event
]
&&
!
window
.
commandDone
;
}
else
ret
=
FALSE
;
});
return
ret
;
}
dlls/winemac.drv/event.c
View file @
192b8dbf
...
...
@@ -35,6 +35,8 @@ static const char *dbgstr_event(int type)
"APP_DEACTIVATED"
,
"APP_QUIT_REQUESTED"
,
"DISPLAYS_CHANGED"
,
"IM_SET_CURSOR_POS"
,
"IM_SET_TEXT"
,
"KEY_PRESS"
,
"KEY_RELEASE"
,
"KEYBOARD_CHANGED"
,
...
...
@@ -90,6 +92,8 @@ static macdrv_event_mask get_event_mask(DWORD mask)
event_mask
|=
event_mask_for_type
(
APP_DEACTIVATED
);
event_mask
|=
event_mask_for_type
(
APP_QUIT_REQUESTED
);
event_mask
|=
event_mask_for_type
(
DISPLAYS_CHANGED
);
event_mask
|=
event_mask_for_type
(
IM_SET_CURSOR_POS
);
event_mask
|=
event_mask_for_type
(
IM_SET_TEXT
);
event_mask
|=
event_mask_for_type
(
STATUS_ITEM_CLICKED
);
event_mask
|=
event_mask_for_type
(
WINDOW_CLOSE_REQUESTED
);
event_mask
|=
event_mask_for_type
(
WINDOW_DID_MINIMIZE
);
...
...
@@ -173,6 +177,12 @@ void macdrv_handle_event(const macdrv_event *event)
case
DISPLAYS_CHANGED
:
macdrv_displays_changed
(
event
);
break
;
case
IM_SET_CURSOR_POS
:
macdrv_im_set_cursor_pos
(
event
);
break
;
case
IM_SET_TEXT
:
macdrv_im_set_text
(
event
);
break
;
case
KEY_PRESS
:
case
KEY_RELEASE
:
macdrv_key_event
(
hwnd
,
event
);
...
...
dlls/winemac.drv/ime.c
0 → 100644
View file @
192b8dbf
/*
* The IME for interfacing with Mac input methods
*
* Copyright 2008, 2013 CodeWeavers, Aric Stewart
* Copyright 2013 Ken Thomases for CodeWeavers Inc.
*
* 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.
*/
#include "config.h"
#include <stdarg.h>
#include "macdrv.h"
#include "winuser.h"
#include "imm.h"
#include "ddk/imm.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
imm
);
#define FROM_MACDRV ((HIMC)0xcafe1337)
typedef
struct
_IMEPRIVATE
{
BOOL
bInComposition
;
BOOL
bInternalState
;
HFONT
textfont
;
HWND
hwndDefault
;
UINT
repeat
;
}
IMEPRIVATE
,
*
LPIMEPRIVATE
;
typedef
struct
_tagTRANSMSG
{
UINT
message
;
WPARAM
wParam
;
LPARAM
lParam
;
}
TRANSMSG
,
*
LPTRANSMSG
;
static
const
WCHAR
UI_CLASS_NAME
[]
=
{
'W'
,
'i'
,
'n'
,
'e'
,
' '
,
'M'
,
'a'
,
'c'
,
' '
,
'I'
,
'M'
,
'E'
,
0
};
static
HIMC
*
hSelectedFrom
=
NULL
;
static
INT
hSelectedCount
=
0
;
/* 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
HIMC
RealIMC
(
HIMC
hIMC
)
{
if
(
hIMC
==
FROM_MACDRV
)
{
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
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
=
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
,
LPCWSTR
compstr
,
DWORD
len
,
DWORD
*
flags
)
{
/* 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
(
compstr
==
NULL
&&
len
!=
0
)
{
ERR
(
"compstr is NULL however we have a len! Please report
\n
"
);
len
=
0
;
}
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
;
new_one
->
dwCursorPos
=
lpcs
->
dwCursorPos
;
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
);
}
else
{
new_one
->
dwCursorPos
=
len
;
*
flags
|=
GCS_CURSORPOS
;
}
/* 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
));
}
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
(
resultstr
==
NULL
&&
len
!=
0
)
{
ERR
(
"resultstr is NULL however we have a len! Please report
\n
"
);
len
=
0
;
}
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
=
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
;
DWORD
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
=
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
GenerateMessageToTransKey
(
LPDWORD
lpTransBuf
,
UINT
*
uNumTranMsgs
,
UINT
msg
,
WPARAM
wParam
,
LPARAM
lParam
)
{
LPTRANSMSG
ptr
;
if
(
*
uNumTranMsgs
+
1
>=
(
UINT
)
*
lpTransBuf
)
return
FALSE
;
ptr
=
(
LPTRANSMSG
)(
lpTransBuf
+
1
+
*
uNumTranMsgs
*
3
);
ptr
->
message
=
msg
;
ptr
->
wParam
=
wParam
;
ptr
->
lParam
=
lParam
;
(
*
uNumTranMsgs
)
++
;
return
TRUE
;
}
static
BOOL
IME_RemoveFromSelected
(
HIMC
hIMC
)
{
int
i
;
for
(
i
=
0
;
i
<
hSelectedCount
;
i
++
)
{
if
(
hSelectedFrom
[
i
]
==
hIMC
)
{
if
(
i
<
hSelectedCount
-
1
)
memmove
(
&
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
;
}
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
);
}
BOOL
WINAPI
ImeInquire
(
LPIMEINFO
lpIMEInfo
,
LPWSTR
lpszUIClass
,
LPCWSTR
lpszOption
)
{
TRACE
(
"
\n
"
);
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 */
/* FIXME: Can we? */
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
)
{
TRACE
(
"%x %p
\n
"
,
uSubFunc
,
lpData
);
return
0
;
}
BOOL
WINAPI
ImeProcessKey
(
HIMC
hIMC
,
UINT
vKey
,
LPARAM
lKeyData
,
CONST
LPBYTE
lpbKeyState
)
{
LPINPUTCONTEXT
lpIMC
;
BOOL
inIME
;
TRACE
(
"hIMC %p vKey 0x%04x lKeyData 0x%08lx lpbKeyState %p
\n
"
,
hIMC
,
vKey
,
lKeyData
,
lpbKeyState
);
switch
(
vKey
)
{
case
VK_SHIFT
:
case
VK_CONTROL
:
case
VK_CAPITAL
:
case
VK_MENU
:
return
FALSE
;
}
inIME
=
macdrv_using_input_method
();
lpIMC
=
LockRealIMC
(
hIMC
);
if
(
lpIMC
)
{
LPIMEPRIVATE
myPrivate
;
myPrivate
=
ImmLockIMCC
(
lpIMC
->
hPrivate
);
if
(
inIME
&&
!
myPrivate
->
bInternalState
)
ImmSetOpenStatus
(
RealIMC
(
FROM_MACDRV
),
TRUE
);
else
if
(
!
inIME
&&
myPrivate
->
bInternalState
)
{
ShowWindow
(
myPrivate
->
hwndDefault
,
SW_HIDE
);
ImmDestroyIMCC
(
lpIMC
->
hCompStr
);
lpIMC
->
hCompStr
=
ImeCreateBlankCompStr
();
ImmSetOpenStatus
(
RealIMC
(
FROM_MACDRV
),
FALSE
);
}
myPrivate
->
repeat
=
(
lKeyData
>>
30
)
&
0x1
;
myPrivate
->
bInternalState
=
inIME
;
ImmUnlockIMCC
(
lpIMC
->
hPrivate
);
}
UnlockRealIMC
(
hIMC
);
return
inIME
;
}
BOOL
WINAPI
ImeSelect
(
HIMC
hIMC
,
BOOL
fSelect
)
{
LPINPUTCONTEXT
lpIMC
;
TRACE
(
"%p %s
\n
"
,
hIMC
,
fSelect
?
"TRUE"
:
"FALSE"
);
if
(
hIMC
==
FROM_MACDRV
)
{
ERR
(
"ImeSelect should never be called from Cocoa
\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
=
ImmLockIMCC
(
lpIMC
->
hPrivate
);
myPrivate
->
bInComposition
=
FALSE
;
myPrivate
->
bInternalState
=
FALSE
;
myPrivate
->
textfont
=
NULL
;
myPrivate
->
hwndDefault
=
NULL
;
myPrivate
->
repeat
=
0
;
ImmUnlockIMCC
(
lpIMC
->
hPrivate
);
UnlockRealIMC
(
hIMC
);
}
return
TRUE
;
}
BOOL
WINAPI
ImeSetActiveContext
(
HIMC
hIMC
,
BOOL
fFlag
)
{
FIXME
(
"(%p, %x): stub
\n
"
,
hIMC
,
fFlag
);
return
TRUE
;
}
UINT
WINAPI
ImeToAsciiEx
(
UINT
uVKey
,
UINT
uScanCode
,
CONST
LPBYTE
lpbKeyState
,
LPDWORD
lpdwTransKey
,
UINT
fuState
,
HIMC
hIMC
)
{
UINT
vkey
;
LPINPUTCONTEXT
lpIMC
;
LPIMEPRIVATE
myPrivate
;
HWND
hwndDefault
;
UINT
repeat
;
INT
rc
;
TRACE
(
"uVKey 0x%04x uScanCode 0x%04x fuState %u hIMC %p
\n
"
,
uVKey
,
uScanCode
,
fuState
,
hIMC
);
vkey
=
LOWORD
(
uVKey
);
if
(
vkey
==
VK_KANA
||
vkey
==
VK_KANJI
||
vkey
==
VK_MENU
)
{
TRACE
(
"Skipping metakey
\n
"
);
return
0
;
}
lpIMC
=
LockRealIMC
(
hIMC
);
myPrivate
=
ImmLockIMCC
(
lpIMC
->
hPrivate
);
if
(
!
myPrivate
->
bInternalState
)
{
ImmUnlockIMCC
(
lpIMC
->
hPrivate
);
UnlockRealIMC
(
hIMC
);
return
0
;
}
repeat
=
myPrivate
->
repeat
;
hwndDefault
=
myPrivate
->
hwndDefault
;
ImmUnlockIMCC
(
lpIMC
->
hPrivate
);
UnlockRealIMC
(
hIMC
);
TRACE
(
"Processing Mac 0x%04x
\n
"
,
vkey
);
rc
=
macdrv_process_text_input
(
uVKey
,
uScanCode
,
repeat
,
lpbKeyState
,
hIMC
);
if
(
!
rc
)
{
UINT
msgs
=
0
;
UINT
msg
=
(
uScanCode
&
0x8000
)
?
WM_KEYUP
:
WM_KEYDOWN
;
/* KeyStroke not processed by the IME
* so we need to rebuild the KeyDown message and pass it on to WINE
*/
if
(
!
GenerateMessageToTransKey
(
lpdwTransKey
,
&
msgs
,
msg
,
vkey
,
MAKELONG
(
0x0001
,
uScanCode
)))
GenerateIMEMessage
(
hIMC
,
msg
,
vkey
,
MAKELONG
(
0x0001
,
uScanCode
));
return
msgs
;
}
else
UpdateDataInDefaultIMEWindow
(
hIMC
,
hwndDefault
,
FALSE
);
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
:
switch
(
dwValue
)
{
case
IMC_SETCOMPOSITIONWINDOW
:
FIXME
(
"NI_CONTEXTUPDATED: IMC_SETCOMPOSITIONWINDOW
\n
"
);
break
;
case
IMC_SETCONVERSIONMODE
:
FIXME
(
"NI_CONTEXTUPDATED: IMC_SETCONVERSIONMODE
\n
"
);
break
;
case
IMC_SETSENTENCEMODE
:
FIXME
(
"NI_CONTEXTUPDATED: IMC_SETSENTENCEMODE
\n
"
);
break
;
case
IMC_SETCANDIDATEPOS
:
FIXME
(
"NI_CONTEXTUPDATED: IMC_SETCANDIDATEPOS
\n
"
);
break
;
case
IMC_SETCOMPOSITIONFONT
:
{
LPIMEPRIVATE
myPrivate
;
TRACE
(
"NI_CONTEXTUPDATED: IMC_SETCOMPOSITIONFONT
\n
"
);
myPrivate
=
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
(
"NI_CONTEXTUPDATED: IMC_SETOPENSTATUS
\n
"
);
myPrivate
=
ImmLockIMCC
(
lpIMC
->
hPrivate
);
if
(
lpIMC
->
fOpen
!=
myPrivate
->
bInternalState
&&
myPrivate
->
bInComposition
)
{
if
(
lpIMC
->
fOpen
==
FALSE
)
{
GenerateIMEMessage
(
hIMC
,
WM_IME_ENDCOMPOSITION
,
0
,
0
);
myPrivate
->
bInComposition
=
FALSE
;
}
else
{
GenerateIMEMessage
(
hIMC
,
WM_IME_STARTCOMPOSITION
,
0
,
0
);
GenerateIMEMessage
(
hIMC
,
WM_IME_COMPOSITION
,
0
,
0
);
}
}
myPrivate
->
bInternalState
=
lpIMC
->
fOpen
;
bRet
=
TRUE
;
}
break
;
default:
FIXME
(
"NI_CONTEXTUPDATED: Unknown
\n
"
);
break
;
}
break
;
case
NI_COMPOSITIONSTR
:
switch
(
dwIndex
)
{
case
CPS_COMPLETE
:
{
HIMCC
newCompStr
;
DWORD
cplen
=
0
;
LPWSTR
cpstr
;
LPCOMPOSITIONSTRING
cs
=
NULL
;
LPBYTE
cdata
=
NULL
;
LPIMEPRIVATE
myPrivate
;
TRACE
(
"NI_COMPOSITIONSTR: 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
];
DWORD
flags
=
GCS_COMPSTR
;
newCompStr
=
updateResultStr
(
lpIMC
->
hCompStr
,
cpstr
,
cplen
);
ImmDestroyIMCC
(
lpIMC
->
hCompStr
);
lpIMC
->
hCompStr
=
newCompStr
;
newCompStr
=
updateCompStr
(
lpIMC
->
hCompStr
,
NULL
,
0
,
&
flags
);
ImmDestroyIMCC
(
lpIMC
->
hCompStr
);
lpIMC
->
hCompStr
=
newCompStr
;
GenerateIMEMessage
(
hIMC
,
WM_IME_COMPOSITION
,
0
,
flags
);
GenerateIMEMessage
(
hIMC
,
WM_IME_COMPOSITION
,
param
,
GCS_RESULTSTR
|
GCS_RESULTCLAUSE
);
}
GenerateIMEMessage
(
hIMC
,
WM_IME_ENDCOMPOSITION
,
0
,
0
);
myPrivate
=
ImmLockIMCC
(
lpIMC
->
hPrivate
);
myPrivate
->
bInComposition
=
FALSE
;
ImmUnlockIMCC
(
lpIMC
->
hPrivate
);
bRet
=
TRUE
;
}
break
;
case
CPS_CONVERT
:
FIXME
(
"NI_COMPOSITIONSTR: CPS_CONVERT
\n
"
);
break
;
case
CPS_REVERT
:
FIXME
(
"NI_COMPOSITIONSTR: CPS_REVERT
\n
"
);
break
;
case
CPS_CANCEL
:
{
LPIMEPRIVATE
myPrivate
;
TRACE
(
"NI_COMPOSITIONSTR: CPS_CANCEL
\n
"
);
if
(
lpIMC
->
hCompStr
)
ImmDestroyIMCC
(
lpIMC
->
hCompStr
);
lpIMC
->
hCompStr
=
ImeCreateBlankCompStr
();
myPrivate
=
ImmLockIMCC
(
lpIMC
->
hPrivate
);
if
(
myPrivate
->
bInComposition
)
{
GenerateIMEMessage
(
hIMC
,
WM_IME_ENDCOMPOSITION
,
0
,
0
);
myPrivate
->
bInComposition
=
FALSE
;
}
ImmUnlockIMCC
(
lpIMC
->
hPrivate
);
bRet
=
TRUE
;
}
break
;
default:
FIXME
(
"NI_COMPOSITIONSTR: 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
);
/*
* Explanation:
* this sets the composition string in the imm32.dll level
* of the composition buffer.
* TODO: set the Cocoa window's marked text string and tell text input context
*/
if
(
lpRead
&&
dwReadLen
)
FIXME
(
"Reading string unimplemented
\n
"
);
lpIMC
=
LockRealIMC
(
hIMC
);
if
(
lpIMC
==
NULL
)
return
FALSE
;
myPrivate
=
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
,
(
LPCWSTR
)
lpComp
,
dwCompLen
/
sizeof
(
WCHAR
),
&
flags
);
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
,
&
flags
);
ImmDestroyIMCC
(
lpIMC
->
hCompStr
);
lpIMC
->
hCompStr
=
newCompStr
;
}
}
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
;
}
static
void
IME_SetCursorPos
(
void
*
hIMC
,
DWORD
pos
)
{
LPINPUTCONTEXT
lpIMC
;
LPCOMPOSITIONSTRING
compstr
;
if
(
!
hSelectedFrom
)
return
;
lpIMC
=
LockRealIMC
(
hIMC
);
if
(
!
lpIMC
)
return
;
compstr
=
ImmLockIMCC
(
lpIMC
->
hCompStr
);
if
(
!
compstr
)
{
UnlockRealIMC
(
hIMC
);
return
;
}
compstr
->
dwCursorPos
=
pos
;
ImmUnlockIMCC
(
lpIMC
->
hCompStr
);
UnlockRealIMC
(
hIMC
);
GenerateIMEMessage
(
FROM_MACDRV
,
WM_IME_COMPOSITION
,
pos
,
GCS_CURSORPOS
);
return
;
}
static
void
IME_SetCompositionString
(
void
*
hIMC
,
LPCVOID
lpComp
,
DWORD
dwCompLen
)
{
ImeSetCompositionString
(
hIMC
,
SCS_SETSTR
,
lpComp
,
dwCompLen
,
NULL
,
0
);
}
static
void
IME_NotifyComplete
(
void
*
hIMC
)
{
NotifyIME
(
hIMC
,
NI_COMPOSITIONSTR
,
CPS_COMPLETE
,
0
);
}
/*****
* 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
=
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 because 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
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
)
GetWindowLongPtrW
(
hwnd
,
IMMGWL_IMC
);
if
(
!
hIMC
)
hIMC
=
RealIMC
(
FROM_MACDRV
);
/* 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
=
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
;
}
/* Interfaces to other parts of the Mac driver */
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_PTR
);
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"
);
}
/***********************************************************************
* macdrv_im_set_cursor_pos
*/
void
macdrv_im_set_cursor_pos
(
const
macdrv_event
*
event
)
{
HWND
hwnd
=
macdrv_get_window_hwnd
(
event
->
window
);
void
*
himc
=
event
->
im_set_cursor_pos
.
data
;
TRACE
(
"win %p/%p himc %p pos %u
\n
"
,
hwnd
,
event
->
window
,
himc
,
event
->
im_set_cursor_pos
.
pos
);
if
(
!
himc
)
himc
=
RealIMC
(
FROM_MACDRV
);
IME_SetCursorPos
(
himc
,
event
->
im_set_cursor_pos
.
pos
);
}
/***********************************************************************
* macdrv_im_set_text
*/
void
macdrv_im_set_text
(
const
macdrv_event
*
event
)
{
HWND
hwnd
=
macdrv_get_window_hwnd
(
event
->
window
);
void
*
himc
=
event
->
im_set_text
.
data
;
TRACE
(
"win %p/%p himc %p text %s complete %u
\n
"
,
hwnd
,
event
->
window
,
himc
,
debugstr_cf
(
event
->
im_set_text
.
text
),
event
->
im_set_text
.
complete
);
if
(
!
himc
)
himc
=
RealIMC
(
FROM_MACDRV
);
if
(
event
->
im_set_text
.
text
)
{
CFIndex
length
=
CFStringGetLength
(
event
->
im_set_text
.
text
);
const
UniChar
*
chars
=
CFStringGetCharactersPtr
(
event
->
im_set_text
.
text
);
UniChar
*
buffer
=
NULL
;
if
(
!
chars
)
{
buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
length
*
sizeof
(
*
buffer
));
CFStringGetCharacters
(
event
->
im_set_text
.
text
,
CFRangeMake
(
0
,
length
),
buffer
);
chars
=
buffer
;
}
if
(
himc
)
IME_SetCompositionString
(
himc
,
chars
,
length
*
sizeof
(
*
chars
));
else
{
INPUT
input
;
CFIndex
i
;
input
.
type
=
INPUT_KEYBOARD
;
input
.
ki
.
wVk
=
0
;
input
.
ki
.
time
=
0
;
input
.
ki
.
dwExtraInfo
=
0
;
for
(
i
=
0
;
i
<
length
;
i
++
)
{
input
.
ki
.
wScan
=
chars
[
i
];
input
.
ki
.
dwFlags
=
KEYEVENTF_UNICODE
;
__wine_send_input
(
hwnd
,
&
input
);
input
.
ki
.
dwFlags
=
KEYEVENTF_UNICODE
|
KEYEVENTF_KEYUP
;
__wine_send_input
(
hwnd
,
&
input
);
}
}
HeapFree
(
GetProcessHeap
(),
0
,
buffer
);
}
if
(
event
->
im_set_text
.
complete
)
IME_NotifyComplete
(
himc
);
}
dlls/winemac.drv/keyboard.c
View file @
192b8dbf
...
...
@@ -889,6 +889,53 @@ static BOOL match_keyboard_layout(HKL hkl)
/***********************************************************************
* macdrv_process_text_input
*/
BOOL
macdrv_process_text_input
(
UINT
vkey
,
UINT
scan
,
UINT
repeat
,
const
BYTE
*
key_state
,
void
*
himc
)
{
struct
macdrv_thread_data
*
thread_data
=
macdrv_thread_data
();
unsigned
int
flags
;
int
keyc
;
BOOL
ret
=
FALSE
;
TRACE
(
"vkey 0x%04x scan 0x%04x repeat %u himc %p
\n
"
,
vkey
,
scan
,
repeat
,
himc
);
flags
=
thread_data
->
last_modifiers
;
if
(
key_state
[
VK_SHIFT
]
&
0x80
)
flags
|=
NX_SHIFTMASK
;
else
flags
&=
~
(
NX_SHIFTMASK
|
NX_DEVICELSHIFTKEYMASK
|
NX_DEVICERSHIFTKEYMASK
);
if
(
key_state
[
VK_CAPITAL
]
&
0x01
)
flags
|=
NX_ALPHASHIFTMASK
;
else
flags
&=
~
NX_ALPHASHIFTMASK
;
if
(
key_state
[
VK_CONTROL
]
&
0x80
)
flags
|=
NX_CONTROLMASK
;
else
flags
&=
~
(
NX_CONTROLMASK
|
NX_DEVICELCTLKEYMASK
|
NX_DEVICERCTLKEYMASK
);
if
(
key_state
[
VK_MENU
]
&
0x80
)
flags
|=
NX_COMMANDMASK
;
else
flags
&=
~
(
NX_COMMANDMASK
|
NX_DEVICELCMDKEYMASK
|
NX_DEVICERCMDKEYMASK
);
/* Find the Mac keycode corresponding to the scan code */
for
(
keyc
=
0
;
keyc
<
sizeof
(
thread_data
->
keyc2vkey
)
/
sizeof
(
thread_data
->
keyc2vkey
[
0
]);
keyc
++
)
if
(
thread_data
->
keyc2vkey
[
keyc
]
==
vkey
)
break
;
if
(
keyc
>=
sizeof
(
thread_data
->
keyc2vkey
)
/
sizeof
(
thread_data
->
keyc2vkey
[
0
]))
goto
done
;
TRACE
(
"flags 0x%08x keyc 0x%04x
\n
"
,
flags
,
keyc
);
ret
=
macdrv_send_text_input_event
(((
scan
&
0x8000
)
==
0
),
flags
,
repeat
,
keyc
,
himc
);
done:
TRACE
(
" -> %s
\n
"
,
ret
?
"TRUE"
:
"FALSE"
);
return
ret
;
}
/***********************************************************************
* ActivateKeyboardLayout (MACDRV.@)
*/
HKL
CDECL
macdrv_ActivateKeyboardLayout
(
HKL
hkl
,
UINT
flags
)
...
...
dlls/winemac.drv/macdrv.h
View file @
192b8dbf
...
...
@@ -64,6 +64,8 @@ static inline const char *wine_dbgstr_cgrect(CGRect cgrect)
CGRectGetMaxX
(
cgrect
),
CGRectGetMaxY
(
cgrect
));
}
extern
const
char
*
debugstr_cf
(
CFTypeRef
t
)
DECLSPEC_HIDDEN
;
/**************************************************************************
* Mac GDI driver
...
...
@@ -188,4 +190,17 @@ extern CFArrayRef create_app_icon_images(void) DECLSPEC_HIDDEN;
extern
void
macdrv_status_item_clicked
(
const
macdrv_event
*
event
)
DECLSPEC_HIDDEN
;
/**************************************************************************
* Mac IME driver
*/
extern
void
IME_RegisterClasses
(
HINSTANCE
hImeInst
)
DECLSPEC_HIDDEN
;
extern
BOOL
macdrv_process_text_input
(
UINT
vkey
,
UINT
scan
,
UINT
repeat
,
const
BYTE
*
key_state
,
void
*
himc
)
DECLSPEC_HIDDEN
;
extern
void
macdrv_im_set_cursor_pos
(
const
macdrv_event
*
event
)
DECLSPEC_HIDDEN
;
extern
void
macdrv_im_set_text
(
const
macdrv_event
*
event
)
DECLSPEC_HIDDEN
;
#endif
/* __WINE_MACDRV_H */
dlls/winemac.drv/macdrv_cocoa.h
View file @
192b8dbf
...
...
@@ -135,6 +135,7 @@ extern void macdrv_window_rejected_focus(const struct macdrv_event *event) DECLS
extern
void
macdrv_beep
(
void
)
DECLSPEC_HIDDEN
;
extern
void
macdrv_set_application_icon
(
CFArrayRef
images
)
DECLSPEC_HIDDEN
;
extern
void
macdrv_quit_reply
(
int
reply
)
DECLSPEC_HIDDEN
;
extern
int
macdrv_using_input_method
(
void
)
DECLSPEC_HIDDEN
;
/* cursor */
...
...
@@ -156,6 +157,8 @@ enum {
APP_DEACTIVATED
,
APP_QUIT_REQUESTED
,
DISPLAYS_CHANGED
,
IM_SET_CURSOR_POS
,
IM_SET_TEXT
,
KEY_PRESS
,
KEY_RELEASE
,
KEYBOARD_CHANGED
,
...
...
@@ -196,6 +199,15 @@ typedef struct macdrv_event {
int
activating
;
}
displays_changed
;
struct
{
void
*
data
;
unsigned
int
pos
;
}
im_set_cursor_pos
;
struct
{
void
*
data
;
CFStringRef
text
;
/* new text or NULL if just completing existing text */
unsigned
int
complete
;
/* is completing text? */
}
im_set_text
;
struct
{
CGKeyCode
keycode
;
CGEventFlags
modifiers
;
unsigned
long
time_ms
;
...
...
@@ -348,6 +360,8 @@ extern void macdrv_set_view_window_and_frame(macdrv_view v, macdrv_window w, CGR
extern
void
macdrv_add_view_opengl_context
(
macdrv_view
v
,
macdrv_opengl_context
c
)
DECLSPEC_HIDDEN
;
extern
void
macdrv_remove_view_opengl_context
(
macdrv_view
v
,
macdrv_opengl_context
c
)
DECLSPEC_HIDDEN
;
extern
uint32_t
macdrv_window_background_color
(
void
)
DECLSPEC_HIDDEN
;
extern
int
macdrv_send_text_input_event
(
int
pressed
,
unsigned
int
flags
,
int
repeat
,
int
keyc
,
void
*
data
)
DECLSPEC_HIDDEN
;
/* keyboard */
...
...
dlls/winemac.drv/macdrv_main.c
View file @
192b8dbf
...
...
@@ -206,6 +206,7 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)
switch
(
reason
)
{
case
DLL_PROCESS_ATTACH
:
IME_RegisterClasses
(
hinst
);
ret
=
process_attach
();
break
;
case
DLL_THREAD_DETACH
:
...
...
dlls/winemac.drv/winemac.drv.spec
View file @
192b8dbf
...
...
@@ -49,3 +49,21 @@
# System tray
@ cdecl wine_notify_icon(long ptr)
# IME
@ stdcall ImeConfigure(long long long ptr)
@ stdcall ImeConversionList(long wstr ptr long long)
@ stdcall ImeDestroy(long)
@ stdcall ImeEnumRegisterWord(ptr wstr long wstr ptr)
@ stdcall ImeEscape(long long ptr)
@ stdcall ImeGetImeMenuItems(long long long ptr ptr long)
@ stdcall ImeGetRegisterWordStyle(wstr long wstr)
@ stdcall ImeInquire(ptr wstr wstr)
@ stdcall ImeProcessKey(long long long ptr)
@ stdcall ImeRegisterWord(wstr long wstr)
@ stdcall ImeSelect(long long)
@ stdcall ImeSetActiveContext(long long)
@ stdcall ImeSetCompositionString(long long ptr long ptr long)
@ stdcall ImeToAsciiEx(long long ptr ptr long long)
@ stdcall ImeUnregisterWord(wstr long wstr)
@ stdcall NotifyIME(long long long long)
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