Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » U++ Library support » U++ Libraries and TheIDE: i18n, Unicode and Internationalization » Japanese IME test code
Japanese IME test code [message #15099] Mon, 31 March 2008 09:58 Go to next message
mobilehunter is currently offline  mobilehunter
Messages: 87
Registered: November 2006
Member
Hope Mirek and other can check these code
case WM_IME_STARTCOMPOSITION:
	{
		HWND hwnd =GetHWND();
		POINT pt;
		GetCaretPos(&pt);// I don't know the properway to get this in UPP way.
		HIMC hIMC = ImmGetContext(hwnd);
		COMPOSITIONFORM cf;
		
/*These lines up to us to make ime font match to current font, or just the font size.
		FontInfo fi = Draw::GetStdFont().Info();
		LOGFONT lf;
		HFONT hfont = fi.GetHFONT(); //i'm sorry to add this function manually to Draw.h, since i don't know how to get HFONT 
		GetObject(hfont, sizeof(LOGFONT), &lf);
		ImmSetCompositionFont(hIMC, &lf);
			
		cf.dwStyle = CFS_POINT;
		cf.ptCurrentPos.x = pt.x;
		cf.ptCurrentPos.y = pt.y;
		ImmSetCompositionWindow(hIMC, &cf);
		ImmReleaseContext(hwnd, hIMC);
	}
break;


Above code will make IME window position start at current caret position.

Please fix above codes, since i don't have deep understanding of UPP codes.

Test with GUI17a sample and UWord

[Updated on: Mon, 31 March 2008 10:00]

Report message to a moderator

Re: Japanese IME test code [message #15163 is a reply to message #15099] Sun, 06 April 2008 08:14 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
mobilehunter wrote on Mon, 31 March 2008 03:58

Hope Mirek and other can check these code
case WM_IME_STARTCOMPOSITION:
	{
		HWND hwnd =GetHWND();
		POINT pt;
		GetCaretPos(&pt);// I don't know the properway to get this in UPP way.
		HIMC hIMC = ImmGetContext(hwnd);
		COMPOSITIONFORM cf;
		
/*These lines up to us to make ime font match to current font, or just the font size.
		FontInfo fi = Draw::GetStdFont().Info();
		LOGFONT lf;
		HFONT hfont = fi.GetHFONT(); //i'm sorry to add this function manually to Draw.h, since i don't know how to get HFONT 
		GetObject(hfont, sizeof(LOGFONT), &lf);
		ImmSetCompositionFont(hIMC, &lf);
			
		cf.dwStyle = CFS_POINT;
		cf.ptCurrentPos.x = pt.x;
		cf.ptCurrentPos.y = pt.y;
		ImmSetCompositionWindow(hIMC, &cf);
		ImmReleaseContext(hwnd, hIMC);
	}
break;


Above code will make IME window position start at current caret position.

Please fix above codes, since i don't have deep understanding of UPP codes.

Test with GUI17a sample and UWord


Looks OK to me, but I cannot check it Smile

If this gets approval from any other CJK user, I will paste it in gladly Smile

Mirek
Re: Japanese IME test code [message #15170 is a reply to message #15163] Mon, 07 April 2008 03:10 Go to previous messageGo to next message
mobilehunter is currently offline  mobilehunter
Messages: 87
Registered: November 2006
Member
Hi Mirek,
Thanks for the reply.

I change the code for displaying the IME window to controls such as RichEdit and EditField, since as my understanding those controls know their font and caret position better. And add a virtual function DisplayIMEWindow() to those controls.

So the implementation inside Win32Proc.cpp:
case WM_IME_STARTCOMPOSITION:
{
  Ctrl*f=GetFocusChild();
  if(f)
     f->DisplayIMEWindow();
}
break;


And below are the implementation inside EditField control
void EditField::DisplayIMEWindow()
{
	HWND hwnd =this->GetParent()->GetHWND();
	POINT pt;
	FontInfo fi = font.Info();
	
	GetCaretPos(&pt);
	HIMC hIMC = ImmGetContext(hwnd);
	COMPOSITIONFORM cf;
	
	LOGFONT lf;
	HFONT hfont = fi.GetHFONT();
	GetObject(hfont, sizeof(LOGFONT), &lf);
	ImmSetCompositionFont(hIMC, &lf);
		
	cf.dwStyle = CFS_POINT;
	cf.ptCurrentPos.x = pt.x;
	cf.ptCurrentPos.y = pt.y;
	ImmSetCompositionWindow(hIMC, &cf);
	ImmReleaseContext(hwnd, hIMC);
}


And below inside RichEdit control (kbd.cpp):
void RichEdit::DisplayIMEWindow()
{
	HWND hwnd = this->GetParent()->GetHWND();
	POINT pt;
	FontInfo fi = formatinfo.Info();
	
	GetCaretPos(&pt);
	HIMC hIMC = ImmGetContext(hwnd);
	COMPOSITIONFORM cf;
	LOGFONT lf;
	
	HFONT hfont = fi.GetHFONT();
	::GetObject(hfont, sizeof(LOGFONT), &lf);
	ImmSetCompositionFont(hIMC, &lf);
		
	cf.dwStyle = CFS_POINT;
	cf.ptCurrentPos.x = pt.x;
	cf.ptCurrentPos.y = pt.y;
	ImmSetCompositionWindow(hIMC, &cf);
	ImmReleaseContext(hwnd, hIMC);
}


I still have problem with the font size for IME window.
And have problem debugging the codes. The IDE will hang if i press F10 key after a break point.
Re: Japanese IME test code [message #15220 is a reply to message #15170] Thu, 10 April 2008 05:27 Go to previous messageGo to next message
mobilehunter is currently offline  mobilehunter
Messages: 87
Registered: November 2006
Member
Another update for RichEdit control, to make the font size of IME window follows RichEdit's font size.
void RichEdit::DisplayIMEWindow()
{
  HWND hwnd = this->GetParent()->GetHWND();
  POINT pt;
  COMPOSITIONFORM cf;
  LOGFONT lf;
  HIMC hIMC = ImmGetContext(hwnd);
  GetCaretPos(&pt);	
	
  int zoomHeight = GetZoom() * tabs(formatinfo.GetHeight());
  ImmGetCompositionFont(hIMC,&lf);
  lf.lfHeight = -zoomHeight;
  ImmSetCompositionFont(hIMC, &lf);

  cf.dwStyle = CFS_POINT;
  cf.ptCurrentPos.x = pt.x;
  cf.ptCurrentPos.y = pt.y;
	
  ImmSetCompositionWindow(hIMC, &cf);
  ImmReleaseContext(hwnd, hIMC);
}


And for EditField.
void EditField::DisplayIMEWindow()
{
	HWND hwnd = this->GetParent()->GetHWND();
	POINT pt;
	COMPOSITIONFORM cf;
	LOGFONT lf;
	HIMC hIMC = ImmGetContext(hwnd);
	GetCaretPos(&pt);	
	Size sz = GetSize();
	int yy = GetTy();
	
	ImmGetCompositionFont(hIMC,&lf);
	lf.lfHeight = font.Info().GetHeight()+yy;
	ImmSetCompositionFont(hIMC, &lf);

	cf.dwStyle = CFS_POINT;
	cf.ptCurrentPos.x = pt.x;
	cf.ptCurrentPos.y = pt.y-yy;
	
	ImmSetCompositionWindow(hIMC, &cf);
	ImmReleaseContext(hwnd, hIMC);
}

[Updated on: Thu, 10 April 2008 05:59]

Report message to a moderator

Re: Japanese IME test code [message #15290 is a reply to message #15220] Tue, 15 April 2008 21:17 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
I am afraid this new spin is not quite as good.

IMO, if you want more correct font, you should rather add some means to get it form the widget, something like "virtual Font GetIMEFont()" method.

Also, suggested implementation are in Win32. At least, they should be #ifdefed in Win32.

Mirek
Re: Japanese IME test code [message #15400 is a reply to message #15290] Mon, 21 April 2008 06:33 Go to previous messageGo to next message
mobilehunter is currently offline  mobilehunter
Messages: 87
Registered: November 2006
Member
Changed the codes.
All the functions declared as virtual
RichEdit control:
#ifdef PLATFORM_WIN32
Font RichEdit::GetIMEFont()
{
  Font imeFont(formatinfo);
  int zoomHeight = GetZoom() * tabs(formatinfo.GetHeight());
	
  imeFont.Height(zoomHeight);
  return imeFont;
}

void RichEdit::DisplayIMEWindow()
{	
  HWND hwnd = this->GetParent()->GetHWND();
  POINT pt;
  COMPOSITIONFORM cf;
  LOGFONT lf;
  GetCaretPos(&pt);	
  Font imeFont = GetIMEFont();
	
  cf.dwStyle = CFS_POINT;
  cf.ptCurrentPos.x = pt.x;
  cf.ptCurrentPos.y = pt.y;

  HIMC hIMC = ImmGetContext(hwnd);	
  ImmGetCompositionFont(hIMC,&lf);
  lf.lfHeight = -imeFont.GetHeight();
  ImmSetCompositionFont(hIMC, &lf);
  ImmSetCompositionWindow(hIMC, &cf);
  ImmReleaseContext(hwnd, hIMC);
}
#endif PLATFORM_WIN32


And for editfield control:
#ifdef PLATFORM_WIN32
Font EditField::GetIMEFont()
{
  Font imeFont(font);
  imeFont.Height(font.Info().GetHeight());
  return imeFont;
}

void EditField::DisplayIMEWindow()
{
  HWND hwnd = this->GetParent()->GetHWND();
  POINT pt;
  COMPOSITIONFORM cf;
  LOGFONT lf;
  GetCaretPos(&pt);	
  int yy = GetTy();
  Font imeFont = GetIMEFont();

  cf.dwStyle = CFS_POINT;
  cf.ptCurrentPos.x = pt.x;
  cf.ptCurrentPos.y = pt.y-yy;//to make the ime window to appear inside editfield

  HIMC hIMC = ImmGetContext(hwnd);		
  ImmGetCompositionFont(hIMC,&lf);
  lf.lfHeight = -(imeFont.GetHeight());
  ImmSetCompositionFont(hIMC, &lf);
  ImmSetCompositionWindow(hIMC, &cf);
  ImmReleaseContext(hwnd, hIMC);
}
#endif

[Updated on: Mon, 21 April 2008 06:34]

Report message to a moderator

Re: Japanese IME test code [message #15417 is a reply to message #15400] Wed, 23 April 2008 10:02 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Ah, sorry, looks like I was not specific enough Wink

DisplayIMEWindow are now the same, are not they? So with GetIMEFont, we can gladly move them into CtrlCore and not be bothered reimplementing it for each individual class.

In the same time, we can implement base Ctrl::GetIMEFont to return StdFont and get this working well for all widgets.

What do you think?

Mirek
Re: Japanese IME test code [message #15462 is a reply to message #15417] Fri, 25 April 2008 07:15 Go to previous messageGo to next message
mobilehunter is currently offline  mobilehunter
Messages: 87
Registered: November 2006
Member
luzr wrote on Wed, 23 April 2008 17:02

Ah, sorry, looks like I was not specific enough Wink

DisplayIMEWindow are now the same, are not they? So with GetIMEFont, we can gladly move them into CtrlCore and not be bothered reimplementing it for each individual class.

In the same time, we can implement base Ctrl::GetIMEFont to return StdFont and get this working well for all widgets.

What do you think?

Mirek

DisplayIMEWindow are almost the same, the differences are at font height and coordinate of IME window.

The font height of IME window should follow the font height of it's parent, also should fit nicely inside the parent.

That's why i implemented at RichEdit and EditField ctrl, since i don't know how to get current font height of each control, and to layout nicely in generic way.

Moving to CtrlCore would be the best.
Re: Japanese IME test code [message #15492 is a reply to message #15462] Sat, 26 April 2008 10:26 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
mobilehunter wrote on Fri, 25 April 2008 01:15


That's why i implemented at RichEdit and EditField ctrl, since i don't know how to get current font height of each control, and to layout nicely in generic way.



Well, but if you would introduce

virtual void GetIMEFont();

int Ctrl interface (returning StdFont as default implementation), you could move

void DisplayIMEWindow()

into Ctrl too, placing IME window at caret position, or maybe adding another

virtual Point GetIMEPosition()

returning caret position as default.

In any case, implementing GetIMEFont/GetIMEPosition seems to be more simple (and often OK with default implementation) that implementing DisplayIMEWindow.

Anything I am missing?

Mirek
Re: Japanese IME test code [message #15493 is a reply to message #15492] Sat, 26 April 2008 10:27 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
P.S.: And it solves "#ifdef PLATFORM_WIN32" issue as well...

Mirek
Re: Japanese IME test code [message #15497 is a reply to message #15492] Sat, 26 April 2008 14:13 Go to previous messageGo to next message
mobilehunter is currently offline  mobilehunter
Messages: 87
Registered: November 2006
Member
luzr wrote on Sat, 26 April 2008 17:26



In any case, implementing GetIMEFont/GetIMEPosition seems to be more simple (and often OK with default implementation) that implementing DisplayIMEWindow.

Anything I am missing?

Mirek



No:). I think it's better.
If i'm not wrong, the implementation of invoking IME window will be reside at Win32Proc.cpp or X11Proc.cpp.
Re: Japanese IME test code [message #15498 is a reply to message #15497] Sat, 26 April 2008 15:00 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Will you implement and test it? (I am a little bit short of IME here Smile

Mirek
Re: Japanese IME test code [message #15499 is a reply to message #15498] Sat, 26 April 2008 15:35 Go to previous messageGo to next message
mobilehunter is currently offline  mobilehunter
Messages: 87
Registered: November 2006
Member
luzr wrote on Sat, 26 April 2008 22:00

Will you implement and test it? (I am a little bit short of IME here Smile

Mirek

Sure. I will try at monday.
I don't have windows machine for development at home now.
Re: Japanese IME test code [message #15506 is a reply to message #15099] Sun, 27 April 2008 04:05 Go to previous messageGo to next message
mobilehunter is currently offline  mobilehunter
Messages: 87
Registered: November 2006
Member
Here are new implementation.
Tested against EditCtrl only.

at CtrlCore.h:
virtual Font   GetIMEFont();
virtual Point  GetIMEPoint();


at Ctrl.cpp:
//default implementation
Font Ctrl::GetIMEFont()
{
	return StdFont();
}

Point Ctrl::GetIMEPoint()
{
	POINT pt;
	GetCaretPos(&pt);//still not upp-wise :)
	
	return Point(pt);
}


at win32proc.cpp:
case WM_IME_STARTCOMPOSITION:
{
	Ctrl*f=GetFocusChild();
		
	HWND hwnd =GetHWND();
	Point imePt = f->GetIMEPoint();
	Font imeFont = f->GetIMEFont();

	COMPOSITIONFORM cf;
	cf.dwStyle = CFS_POINT;
	cf.ptCurrentPos.x = imePt.x;
	cf.ptCurrentPos.y = imePt.y;
		
	LOGFONT lf;
	HIMC hIMC = ImmGetContext(hwnd);
		
	ImmGetCompositionFont(hIMC,&lf);
	lf.lfHeight = -imeFont.Info().GetHeight();
	ImmSetCompositionFont(hIMC, &lf);	
		
	ImmSetCompositionWindow(hIMC, &cf);
	ImmReleaseContext(hwnd, hIMC);
}
break;
Re: Japanese IME test code [message #15585 is a reply to message #15506] Tue, 29 April 2008 18:56 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Should not GetIMEPoint be rather in view coordinates?

(I suppose you have screen coordinates here).

Mirek
Re: Japanese IME test code [message #15649 is a reply to message #15585] Fri, 02 May 2008 07:39 Go to previous messageGo to next message
mobilehunter is currently offline  mobilehunter
Messages: 87
Registered: November 2006
Member
luzr wrote on Wed, 30 April 2008 01:56

Should not GetIMEPoint be rather in view coordinates?

(I suppose you have screen coordinates here).

Mirek


GetCaret() will return relative coordinate from containing window.
Re: Japanese IME test code [message #15731 is a reply to message #15649] Tue, 06 May 2008 19:49 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
mobilehunter wrote on Fri, 02 May 2008 01:39

luzr wrote on Wed, 30 April 2008 01:56

Should not GetIMEPoint be rather in view coordinates?

(I suppose you have screen coordinates here).

Mirek


GetCaret() will return relative coordinate from containing window.


Which is not the same as view of child widget...

(I could fix the code, but I cannot test it.)

Mirek
Re: Japanese IME test code [message #15745 is a reply to message #15731] Tue, 06 May 2008 22:21 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
I guess this might be helpful here:


Rect Ctrl::GetCaret() const
{
	return RectC(caretx, carety, caretcx, caretcy);
}



Mirek
Re: Japanese IME test code [message #15810 is a reply to message #15745] Thu, 08 May 2008 08:04 Go to previous messageGo to next message
mobilehunter is currently offline  mobilehunter
Messages: 87
Registered: November 2006
Member
I change my codes to support "on-the-spot" mode of IME for Windows, i also tried playing with XIM for linux, tested againt SCIM (this will come later sometime:)).

I still have problem with caret, and many behaviours not supported.

For this mode i tested with EditField control (i have to modify it's Paint function).

Here are my codes:
At CtrlCore.h
//Added for CJK
public:
	virtual bool ImeIsInPreEditMode() { return imeIsInPreEditMode;}
	virtual Font   ImePreEditFont();
	virtual Point  ImePreEditStartPoint();
	virtual void ImePreEditSetText(const WString & text);
	virtual int ImePreEditGetTextCx(const wchar *txt, int n, bool password, Font fnt);
	virtual void ImePreEditStart();
	virtual void ImePreEditEnd();
	virtual void ImePreEditSyncCaret();
	virtual int ImePreEditPaint(Draw &w,int fcy, Color ink, Color paper, Font fnt);
private:
	Font imeFont;
	bool imeIsInPreEditMode;
	Point imePreEditPoint;
	int imePreEditCursor;
	WString imePreEditString;
	//End of CJK


At Ctrl.cpp
//Added for CJK
Font Ctrl::ImePreEditFont()
{
	return StdFont();
}

Point Ctrl::ImePreEditStartPoint()
{
	return Point(caretx,carety);
}

void Ctrl::ImePreEditSetText(const WString& text)
{
	imePreEditString = text;
	Refresh();
}

void Ctrl::ImePreEditSyncCaret()
{
	int x = ImePreEditGetTextCx(imePreEditString,imePreEditCursor,false,imeFont);
	FontInfo fi = imeFont.Info();
	int ty = (GetSize().cy + 1 - fi.GetHeight()) / 2;
	
	caretx=imePreEditPoint.x + x + 2 - fi.GetRightSpace('o') + fi.GetLeftSpace('o');
	carety=ty;
	caretcx=1;
	caretcy=min(GetSize().cy - 2 * ty, fi.GetHeight());
}

int Ctrl::ImePreEditGetTextCx(const wchar *txt, int n, bool password, Font fnt)
{
	FontInfo fi = fnt.Info();
	if(password)
		return n * fi['*'];
	const wchar *s = txt;
	int x = 0;
	while(n--)
		x += fi[*s++];
	return x;
}

void Ctrl::ImePreEditStart()
{
	imePreEditPoint = ImePreEditStartPoint();
	imeIsInPreEditMode = true;
	imePreEditCursor=0;
	imePreEditString="";
	imeFont = ImePreEditFont();
}

void Ctrl::ImePreEditEnd()
{
	imeIsInPreEditMode = true;
	imePreEditCursor=0;
	imePreEditString="";
	Refresh();
}

int Ctrl::ImePreEditPaint(Draw &w,int fcy, Color ink, Color paper, Font fnt)
{
	int n=imePreEditString.GetLength();
	if(n < 0) return 0;
	const wchar * imtxt=imePreEditString;
	int cx = ImePreEditGetTextCx(imePreEditString,n,false,imeFont);
	w.DrawRect(imePreEditPoint.x, 0, cx, fcy, paper);
	w.DrawText(imePreEditPoint.x, 0, imtxt, fnt, ink, n);
	//draw feedback
	w.DrawLine(imePreEditPoint.x,fcy,imePreEditPoint.x+cx,fcy,1);
	return cx;
}
//End of CJK


At Win32Proc.cpp
case WM_IME_STARTCOMPOSITION:
		{
			Ctrl*f=GetFocusChild();	
			f->ImePreEditStart();		
			
			CANDIDATEFORM cf;
			cf.dwStyle = CFS_CANDIDATEPOS;
			cf.ptCurrentPos.x = f->imePreEditPoint.x;
			cf.ptCurrentPos.y = f->imePreEditPoint.y;
		
			HIMC hIMC = ImmGetContext(hwnd);		
			ImmSetCandidateWindow(hIMC, &cf);
			ImmReleaseContext(hwnd, hIMC);

			return 0L;
		}
	case WM_IME_ENDCOMPOSITION:
		{
			Ctrl*f=GetFocusChild();
			f->ImePreEditEnd();
			return 0L;
		}
	case WM_IME_COMPOSITION:
		{
			Ctrl*f=GetFocusChild();
			
			if(lParam & GCS_COMPSTR)
			{
		        HWND hWnd =GetHWND();
		        HIMC hIMC = ImmGetContext(hwnd);
		
		        long dwSize = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0);

				wchar temp[1024];
				wchar attribute[10];
											
				if(lParam & GCS_COMPATTR)
				{
					int attrLen=ImmGetCompositionStringW(hIMC, GCS_COMPATTR, NULL, 0);
					ImmGetCompositionStringW(hIMC, GCS_COMPATTR, attribute, attrLen);
					LOGHEXDUMP(attribute,attrLen);
				}
				
		        ImmGetCompositionStringW(hIMC, GCS_COMPSTR, temp, dwSize);
		        if(lParam & GCS_CURSORPOS)
				{	
					int cursor = ImmGetCompositionString(hIMC, GCS_CURSORPOS, NULL, 0);
					DUMP(cursor);
					if(attribute[0] != ATTR_TARGET_CONVERTED)		
			        	f->imePreEditCursor = cursor/2;
				}
		        ImmReleaseContext(hWnd, hIMC);
		        f->ImePreEditSetText(WString(temp,dwSize/2));
		        if(attribute[0] != ATTR_TARGET_CONVERTED)
		        {
		        	f->ImePreEditSyncCaret();  
		        	SyncCaret();      
		        }
		        return 0L;
			}			
			break;
		}


And at EditField.cpp
if(GetSelection(l, h)) {
			Paints(w, x, fcy, txt, ink, paper, l, password, font);
			Paints(w, x, fcy, txt, enabled ? st->selectedtext : paper,
			                       enabled ? st->selected : ink, h - l, password, font);
			Paints(w, x, fcy, txt, ink, paper, text.GetLength() - h, password, font);
		}
		else
		{
			if(!ImeIsInPreEditMode())
				Paints(w, x, fcy, txt, ink, paper, text.GetLength(), password, font);
			else
			{	
				Paints(w, x, fcy, txt, ink, paper, cursor, password, font);  
			    x+=ImePreEditPaint(w,fcy,ink,paper,font);
			    Paints(w, x, fcy, txt, ink, paper,text.GetLength() - cursor , password, font);  
			}
		}
Re: Japanese IME test code [message #15811 is a reply to message #15810] Thu, 08 May 2008 09:52 Go to previous messageGo to previous message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
mobilehunter wrote on Thu, 08 May 2008 02:04

I change my codes to support "on-the-spot" mode of IME for Windows, i also tried playing with XIM for linux, tested againt SCIM (this will come later sometime:)).

I still have problem with caret, and many behaviours not supported.

For this mode i tested with EditField control (i have to modify it's Paint function).

Here are my codes:
At CtrlCore.h
//Added for CJK
public:
	virtual bool ImeIsInPreEditMode() { return imeIsInPreEditMode;}
	virtual Font   ImePreEditFont();
	virtual Point  ImePreEditStartPoint();
	virtual void ImePreEditSetText(const WString & text);
	virtual int ImePreEditGetTextCx(const wchar *txt, int n, bool password, Font fnt);
	virtual void ImePreEditStart();
	virtual void ImePreEditEnd();
	virtual void ImePreEditSyncCaret();
	virtual int ImePreEditPaint(Draw &w,int fcy, Color ink, Color paper, Font fnt);
private:
	Font imeFont;
	bool imeIsInPreEditMode;
	Point imePreEditPoint;
	int imePreEditCursor;
	WString imePreEditString;
	//End of CJK


At Ctrl.cpp
//Added for CJK
Font Ctrl::ImePreEditFont()
{
	return StdFont();
}

Point Ctrl::ImePreEditStartPoint()
{
	return Point(caretx,carety);
}

void Ctrl::ImePreEditSetText(const WString& text)
{
	imePreEditString = text;
	Refresh();
}

void Ctrl::ImePreEditSyncCaret()
{
	int x = ImePreEditGetTextCx(imePreEditString,imePreEditCursor,false,imeFont);
	FontInfo fi = imeFont.Info();
	int ty = (GetSize().cy + 1 - fi.GetHeight()) / 2;
	
	caretx=imePreEditPoint.x + x + 2 - fi.GetRightSpace('o') + fi.GetLeftSpace('o');
	carety=ty;
	caretcx=1;
	caretcy=min(GetSize().cy - 2 * ty, fi.GetHeight());
}

int Ctrl::ImePreEditGetTextCx(const wchar *txt, int n, bool password, Font fnt)
{
	FontInfo fi = fnt.Info();
	if(password)
		return n * fi['*'];
	const wchar *s = txt;
	int x = 0;
	while(n--)
		x += fi[*s++];
	return x;
}

void Ctrl::ImePreEditStart()
{
	imePreEditPoint = ImePreEditStartPoint();
	imeIsInPreEditMode = true;
	imePreEditCursor=0;
	imePreEditString="";
	imeFont = ImePreEditFont();
}

void Ctrl::ImePreEditEnd()
{
	imeIsInPreEditMode = true;
	imePreEditCursor=0;
	imePreEditString="";
	Refresh();
}

int Ctrl::ImePreEditPaint(Draw &w,int fcy, Color ink, Color paper, Font fnt)
{
	int n=imePreEditString.GetLength();
	if(n < 0) return 0;
	const wchar * imtxt=imePreEditString;
	int cx = ImePreEditGetTextCx(imePreEditString,n,false,imeFont);
	w.DrawRect(imePreEditPoint.x, 0, cx, fcy, paper);
	w.DrawText(imePreEditPoint.x, 0, imtxt, fnt, ink, n);
	//draw feedback
	w.DrawLine(imePreEditPoint.x,fcy,imePreEditPoint.x+cx,fcy,1);
	return cx;
}
//End of CJK


At Win32Proc.cpp
case WM_IME_STARTCOMPOSITION:
		{
			Ctrl*f=GetFocusChild();	
			f->ImePreEditStart();		
			
			CANDIDATEFORM cf;
			cf.dwStyle = CFS_CANDIDATEPOS;
			cf.ptCurrentPos.x = f->imePreEditPoint.x;
			cf.ptCurrentPos.y = f->imePreEditPoint.y;
		
			HIMC hIMC = ImmGetContext(hwnd);		
			ImmSetCandidateWindow(hIMC, &cf);
			ImmReleaseContext(hwnd, hIMC);

			return 0L;
		}
	case WM_IME_ENDCOMPOSITION:
		{
			Ctrl*f=GetFocusChild();
			f->ImePreEditEnd();
			return 0L;
		}
	case WM_IME_COMPOSITION:
		{
			Ctrl*f=GetFocusChild();
			
			if(lParam & GCS_COMPSTR)
			{
		        HWND hWnd =GetHWND();
		        HIMC hIMC = ImmGetContext(hwnd);
		
		        long dwSize = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0);

				wchar temp[1024];
				wchar attribute[10];
											
				if(lParam & GCS_COMPATTR)
				{
					int attrLen=ImmGetCompositionStringW(hIMC, GCS_COMPATTR, NULL, 0);
					ImmGetCompositionStringW(hIMC, GCS_COMPATTR, attribute, attrLen);
					LOGHEXDUMP(attribute,attrLen);
				}
				
		        ImmGetCompositionStringW(hIMC, GCS_COMPSTR, temp, dwSize);
		        if(lParam & GCS_CURSORPOS)
				{	
					int cursor = ImmGetCompositionString(hIMC, GCS_CURSORPOS, NULL, 0);
					DUMP(cursor);
					if(attribute[0] != ATTR_TARGET_CONVERTED)		
			        	f->imePreEditCursor = cursor/2;
				}
		        ImmReleaseContext(hWnd, hIMC);
		        f->ImePreEditSetText(WString(temp,dwSize/2));
		        if(attribute[0] != ATTR_TARGET_CONVERTED)
		        {
		        	f->ImePreEditSyncCaret();  
		        	SyncCaret();      
		        }
		        return 0L;
			}			
			break;
		}


And at EditField.cpp
if(GetSelection(l, h)) {
			Paints(w, x, fcy, txt, ink, paper, l, password, font);
			Paints(w, x, fcy, txt, enabled ? st->selectedtext : paper,
			                       enabled ? st->selected : ink, h - l, password, font);
			Paints(w, x, fcy, txt, ink, paper, text.GetLength() - h, password, font);
		}
		else
		{
			if(!ImeIsInPreEditMode())
				Paints(w, x, fcy, txt, ink, paper, text.GetLength(), password, font);
			else
			{	
				Paints(w, x, fcy, txt, ink, paper, cursor, password, font);  
			    x+=ImePreEditPaint(w,fcy,ink,paper,font);
			    Paints(w, x, fcy, txt, ink, paper,text.GetLength() - cursor , password, font);  
			}
		}



Uh, what is "on-the-spot" mode?

The number of new virtual functions is staggering....

BTW, for now I would like to add the mode from previous posts, where we were ok with just

virtual Font GetIMEFont();
virtual Point GetIMEPoint();

The only thing I am missing there is change so that GetIMEPoint returns view-relative Point, not top window relative.

Mirek
Previous Topic: How to retrieve current language?
Next Topic: CJK characters can be higlighted as keywords
Goto Forum:
  


Current Time: Thu Mar 28 14:41:39 CET 2024

Total time taken to generate the page: 0.01502 seconds