Subject:
A IME demo program
From:
"Zhang Hongbiao" ####@####.####
Date:
16 Feb 2005 03:35:29 +0000
Message-Id: <BAY18-DAV10752D4A9C06636AF2FA31BE6C0@phx.gbl>
I'd like to present a IME demo program, maybe you can call it in this way.
It's quite a simple application.
'cause I wrote a request before to seek some information of input method
in Microwindows.
I found less information finally.
So I wrote a demo program to demonstrate the feasibilities of introducing
a input method to Microwindows.
I think it may do help to some guys who are working on that direction.
It employes a event-block-and-process-and-redispatch mechanism.
Whenever you press a digit button, it blocks the event and translate to a '9'
button event and redispathc it. Maybe you can revise it to make it work better.
You should write a makefile for it and compile it in Linux.
p.s. Jack is my English name.
Enjoy using it! ^__^
Jack
Email: ####@####.####
2005/2/16
Below is the source code of the demo program :
-------------------------------------------------
/*******************************************************************************
IMEDemo.c - General description about this file.
REVISION HISTORY
Date EngineerName Updation/Reason
---------- ------------ -------------------
2004-12-15 Jack File creation.
*******************************************************************************/
/*==============================================================================
INCLUDE FILES FOR MODULE
==============================================================================*/
/* $include */
#define MWINCLUDECOLORS
#include "windows.h"
#include "wintern.h" /* for MwSetDesktopWallpaper*/
#include "device.h"
#include "stdio.h"
#include "string.h"
#include "assert.h"
#include "nano-X.h"
/* begin: added by Jack, 2004-12-15 */
/* */
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <time.h>
#include <sched.h>
#include <semaphore.h>
/* end : added by Jack, 2004-12-15 */
/*==============================================================================
EXTERNAL DATA AND FUNCTIONS REFRENCE DECLARATIONS
==============================================================================*/
/* $extern */
/*==============================================================================
LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE
==============================================================================*/
/* $macro */
/* $enum */
/* $global variable definition */
/* $global function declaration */
/* $local variable definition */
static HWND hTheEDWnd;
static char l_strEDClass[] = "EDClass";
static char l_strEDName[] = "ED";
static HWND hTheIMEWnd;
static char l_strIMEClass[] = "IMEClass";
static char l_strIMEName[] = "IME";
#define MAX_BUF_LEN 32
static char l_aEDBuf[MAX_BUF_LEN +1];
static int l_iEDBufLen;
static char l_aIMEBuf[MAX_BUF_LEN +1];
static int l_iIMEBufLen;
static MSG l_stMsg;
static BOOL l_bIMEStart = FALSE;
#define PTHREAD_STACK_MIN 4096
static char ime_thread_stack[PTHREAD_STACK_MIN*2];
static pthread_t ime_thread;
/* For safe condition variable usage, must use a boolean predicate and */
/* a mutex with the condition. */
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
sem_t sem;
/* $local function declaration */
static LRESULT CALLBACK
EDProc(HWND hwnd, UINT uMsg, WPARAM wp, LPARAM lp);
static LRESULT CALLBACK
IMEProc(HWND hwnd, UINT uMsg, WPARAM wp, LPARAM lp);
static int
ime_main();
/*==============================================================================
FUNCTION IMPLEMENTIONS
==============================================================================*/
/* $global function implemention */
/* local function implemention */
static BOOL
EDRegisterClass()
{
WNDCLASS wndclass;
/* Register Main Window */
wndclass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = (WNDPROC)EDProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = 0;
wndclass.hIcon = 0;
wndclass.hCursor = 0;
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = l_strEDClass;
RegisterClass(&wndclass);
return TRUE;
}
static BOOL
EDCreateWindow()
{
RECT stRc;
GetWindowRect(GetDesktopWindow(), &stRc);
/* Create APP main window */
hTheEDWnd =CreateWindowEx(0L,
l_strEDClass,
l_strEDName,
WS_VISIBLE|WS_OVERLAPPEDWINDOW,
20,
20,
128,
160,
NULL,
NULL,
NULL,
NULL);
if (!hTheEDWnd)
{
return FALSE;
}
return TRUE;
}
static BOOL
EDInit()
{
/* Register app class */
if (!EDRegisterClass())
{
printf("EDRegisterClass FAIL!!!\n");
return FALSE;
}
/* Create app window */
if(!EDCreateWindow())
{
printf("EDCreateWindow FAIL!!!\n");
return FALSE;
}
return TRUE;
}
static BOOL
IMERegisterClass()
{
WNDCLASS wndclass;
/* Register Main Window */
wndclass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = (WNDPROC)IMEProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = 0;
wndclass.hIcon = 0;
wndclass.hCursor = 0;
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = l_strIMEClass;
RegisterClass(&wndclass);
return TRUE;
}
static BOOL
IMECreateWindow()
{
RECT stRc;
GetWindowRect(GetDesktopWindow(), &stRc);
/* Create APP main window */
hTheIMEWnd =CreateWindowEx(0L,
l_strIMEClass,
l_strIMEName,
WS_VISIBLE|WS_BORDER,
160,
20,
128,
32,
NULL,
NULL,
NULL,
NULL);
if (!hTheIMEWnd)
{
return FALSE;
}
return TRUE;
}
static BOOL
IMEInit()
{
/* Register app class */
if(!IMERegisterClass())
{
printf("IMERegisterClass FAIL!!!\n");
return FALSE;
}
/* Create app window */
if(!IMECreateWindow())
{
printf("IMECreateWindow FAIL!!!\n");
return FALSE;
}
return TRUE;
}
int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nShowCmd)
{
MSG msg;
/* Perform application initialization */
if (!EDInit())
{
printf("EDInit FAIL!!!\n");
return FALSE;
}
if (!IMEInit())
{
printf("IMEInit FAIL!!!\n");
return FALSE;
}
SetFocus(hTheEDWnd);
sem_init(&sem, 0, 0);
/* Enter message loop */
while (GetMessage(&msg,NULL,0,0))
{
if(l_bIMEStart)
{
printf("msg.message = 0x%x\n", msg.message);
if(msg.message == WM_CHAR)
{
pthread_mutex_lock(&mutex);
l_stMsg = msg;
printf("pthread_cond_signal\n");
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
printf("sem_wait\n");
sem_wait(&sem);
msg = l_stMsg;
}
}
//else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}
static void *
ime_thread_entry( void *arg)
{
struct sched_param param;
int policy;
int rc;
rc = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
if(rc)
{
printf("ime_thread_entry: pthread_setcancelstate FAIL(%d)!!!\n", rc);
}
rc = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
if(rc)
{
printf("ime_thread_entry: pthread_setcanceltype FAIL(%d)!!!\n", rc);
}
printf("ime_thread_entry: Thread start..\n");
#if 0 /* Jack 2004-12-15 : */
while(1)
{
sleep(1);
pthread_testcancel();
printf("ime_thread_entry: Thread rolls once\n");
}
#else /* !0 */
ime_main();
#endif /* 0 Jack 2004-12-15 */
printf("Unexpectedly got out of loop!\n");
l_bIMEStart = FALSE;
pthread_exit( 0 );
}
static int
StartIME()
{
pthread_attr_t attr;
int policy;
int rc;
pthread_attr_init( &attr );
pthread_attr_setstack(&attr, (void *)ime_thread_stack, sizeof(ime_thread_stack));
printf("Create thread\n");
if(pthread_create(&ime_thread, &attr, ime_thread_entry, (void*)0x1234))
{
printf("pthread_create FAIL!!!\n");
}
else
{
l_bIMEStart = TRUE;
}
return 0;
}
static int
StopIME()
{
printf("pthread_cancel\n");
if(pthread_cancel(ime_thread))
{
printf("pthread_cancel FAIL!~!!\n");
}
else
{
sem_post(&sem);
sem_init(&sem, 0, 0);
l_bIMEStart = FALSE;
}
return 0;
}
static void DrawIME(HWND hwnd)
{
HDC hdc;
RECT rect;
GetClientRect(hwnd, &rect);
hdc = GetDC(hwnd);
FillRect(hdc, &rect, GetStockObject(WHITE_BRUSH));
DrawText(hdc, l_aIMEBuf, l_iIMEBufLen, &rect, DT_TOP|DT_LEFT);
ReleaseDC(hwnd, hdc);
}
static LRESULT CALLBACK
IMEProc(HWND hwnd, UINT uMsg, WPARAM wp, LPARAM lp)
{
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
switch (uMsg)
{
case WM_PAINT:
//hdc=BeginPaint(hwnd,&ps);
//GetClientRect(hwnd,&rect);
//FillRect(hdc, &rect, GetStockObject(WHITE_BRUSH));
//EndPaint(hwnd,&ps);
break;
case WM_COMMAND:
break;
case WM_CHAR:
break;
case WM_DESTROY:
//PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd,uMsg,wp,lp);
}
return (0);
}
static LRESULT CALLBACK
EDProc(HWND hwnd, UINT uMsg, WPARAM wp, LPARAM lp)
{
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
switch (uMsg)
{
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
GetClientRect(hwnd,&rect);
FillRect(hdc, &rect, GetStockObject(WHITE_BRUSH));
DrawText(hdc, l_aEDBuf, l_iEDBufLen, &rect, DT_TOP|DT_LEFT);
EndPaint(hwnd,&ps);
break;
case WM_COMMAND:
break;
case WM_CHAR:
switch(wp)
{
case VK_NUMPAD0:
case VK_NUMPAD1:
case VK_NUMPAD2:
case VK_NUMPAD3:
case VK_NUMPAD4:
case VK_NUMPAD5:
case VK_NUMPAD6:
case VK_NUMPAD7:
case VK_NUMPAD8:
case VK_NUMPAD9:
if(l_iEDBufLen == MAX_BUF_LEN)
{
break;
}
l_aEDBuf[l_iEDBufLen++]= (wp-VK_NUMPAD0)+'0';
GetClientRect(hwnd, &rect);
InvalidateRect(hwnd, &rect, TRUE);
break;
case VK_F1:
l_iEDBufLen = 0;
l_aEDBuf[0]='\0';
GetClientRect(hwnd, &rect);
InvalidateRect(hwnd, &rect, TRUE);
break;
case VK_F12:
if(l_bIMEStart)
{
StopIME();
}
else
{
StartIME();
}
break;
}
break;
case WM_DESTROY:
//PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd,uMsg,wp,lp);
}
return (0);
}
static int
ime_sendback(int c)
{
return 0;
}
static int
ime_main()
{
MSG msg;
for(;;)
{
pthread_mutex_lock(&mutex);
printf("pthread_cond_wait\n");
pthread_cond_wait(&cond, &mutex);
printf("pthread_cond_wait got unlocked\n");
msg = l_stMsg;
switch(msg.message)
{
case WM_CHAR:
switch(msg.wParam)
{
case VK_NUMPAD0:
case VK_NUMPAD1:
case VK_NUMPAD2:
case VK_NUMPAD3:
case VK_NUMPAD4:
case VK_NUMPAD5:
case VK_NUMPAD6:
case VK_NUMPAD7:
case VK_NUMPAD8:
case VK_NUMPAD9:
l_iIMEBufLen = 1;
l_aIMEBuf[0]= (msg.wParam - VK_NUMPAD0)+'0';
DrawIME(hTheIMEWnd);
msg.wParam = VK_NUMPAD9;
break;
}
break;
}
l_stMsg = msg;
pthread_mutex_unlock(&mutex);
printf("sem_post\n");
sem_post(&sem);
}
return 0;
}