My Cantonese Input Method (version 20100717) Download
Data in DBF format (version 20100523) Download
Browse Data Online
*
* written by: Chang Man Wai, 2004
* useful sites: http://www.lexiconer.com/
*
* 06SEP2008 : close canton.dbf as soon as possible
* 04NOV2008 : prevent clearing the clipboard when hitting reset
* 30JAN2009 : show touched, use fixed width font in listbox
* 01FEB2009 : Double-click to email, add text1.interactivechange()
* 03APR009 : Change button "NewLine" to "History", add property buffer to class MyForm,
* pressing it would recall all outputed Chinese Big5 and then the buffer be cleared
* hitting cmdReset would also remember the history
* 13APR2009: Make cmdClip to remember history as well (like cmdReset)
* 10MAY2009: handle adnormal shutdown via "ON SHUTDOWN" and ReleaseType
* 24AUG2009: smarter buffer handling for cmdClip, cmdHistory and cmdReset
* 24SEP2009: show all possible keys text1 is empty
* 15OCT2009: bugfix for text1.valid() when handling blank key input
*
* Useful links:
* http://input.foruto.com/cie/cie_bd.htm
*
*
#Define K_F1 28
#Define K_ESC 27
#Define K_ENTER 13
parameters m.p1, m.p2
on shutdown do myquit
on error
set debug on
set help on
Set Escape Off
Set Talk Off
Set Notify Off
Set Safety Off
Set Exact On
Clear All
Close All
Clear
Public g_quit
Local oform
g_quit=.F.
#if .f.
*-- Turn off DDE error messages.
=ddesetoption( "SAFETY", .f.)
*-- Check to see if DDE service was already started.
achan = ddeinitiate( "pkf1", "System" )
IF achan # -1
*-- You'll probably want a more informative message.
WAIT WINDOW "Program already running."
ELSE
*-- If we got here, the service was not started, so start it.
=ddesetservice( "pkf1", "DEFINE" )
#endif
oform=Createobject("myform")
If Type("oform")="O"
Set Sysmenu To _Msm_edit
oform.Show()
Read Events
Endif
#if .f.
*-- At the end of the program, turn off the service, so we can get in
*-- next time.
=ddesetservice( "pkf1", "RELEASE" )
ENDIF
#endif
Set Sysmenu To Default
Set Safety On
Set Talk On
Set Notify On
Set Escape On
If g_quit
* clean temporary files for Vi$ta
Quit
Endif
Return
procedure myquit
local xx
on shutdown
on error *
close all
xx=sys(2023)+"*.tmp"
if g_quit
delete files &xx
endif
on error
quit
return
Define Class mytextbox As TextBox
FontSize=16
Format="!K"
lastvalue=""
IntegralHeight=.t.
Enddefine
Define Class mylabel As Label
AutoSize=.T.
Caption=""
FontName="Courier New"
FontSize=14
Enddefine
Define Class mycommandbutton As CommandButton
Height=25
Width=100
TabStop=.F.
Enddefine
Define Class myform As Form
Caption="CHANG's Cantonese Input Method"
KeyPreview=.T.
ShowWindow=2
AutoCenter=.T.
MaxButton=.f.
ShowTips=.t.
MaxButton=.f.
otoolbar=.F.
icon="chang.ico"
Width=400
Buffer=""
Add Object text1 As mytextbox With ;
top=8,Left=10,Height=29, Width=130, FontName="Courier New", Value=""
Add Object list1 As ListBox With ;
top=60,Left=10,Width=130,Height=177, ;
FontName="Courier New", FontSize=16, ;
rowsourcetype=6, ;
columncount=1, ;
columnlines=.f., ;
rowsource="matched.big5, kissed"
Add Object edit1 As EditBox With ;
top=60,Left=145,Width=250,Height=115,Format="!K", ;
FontSize=12, TabStop=.F., Value="", ;
ToolTipText="Enter a maths. equation here"
Add Object lblChangjei As mylabel With ;
top=15,Left=145
Add Object lblMatches As mylabel With ;
top=20,Left=290, Alignment=1
Add Object lblCalculate As mylabel With ;
top=43,Left=290,Alignment=1
Add Object lblCopyRight As Label With ;
top=212-35, Left=145, Width=200, FontSize=8, Caption="Powered by Visual Foxpro", ForeColor=rgb(255,128,128)
Add Object lblFreeware As Label With ;
top=212-35, Left=340, Width=200, FontSize=8, Caption="Freeware", ForeColor=rgb(255,0,0)
Add Object lblEmail As Label With ;
top=212-20, Left=145, Width=200, ;
ToolTipText="Double-click to email me", ;
FontSize=8, Caption="Email: toylet.toylet@gmail.com", ForeColor=rgb(255,128,128)
Add Object cmdClip As mycommandbutton With ;
top=212,Left=145, Width=75, Caption="\This.lastvalue
This.lastvalue=This.Value
thisform.lblCalculate.caption=""
If "?"$This.Value
m.thekey=Left(This.Value,At("?",This.Value)-1)
select 0
use data\canton noupdate
if used("matched")
use in matched
endif
Select Distinct thekey As big5, Space(1) As changjei, .F. As leaf , "" as kissed;
from canton ;
where thekey=m.thekey ;
into Cursor matched
use in canton
thisform.list1.columnCount=1
else
Select modified From remap ;
where original=This.Value ;
into Cursor t_dummy
If !Empty(t_dummy.modified)
This.Value=t_dummy.modified
Endif
Use In t_dummy
select 0
use data\canton noupdate alias canton
if used("matched")
use in matched
endif
Select big5, changjei,.T. As leaf, kissed_mask(touched) as kissed;
from canton ;
where thekey=This.Value ;
order by touched descending ;
into Cursor matched
use in canton
thisform.list1.columnCount=2
Endif
select matched
Thisform.list1.Requery()
Thisform.lblMatches.Caption=Alltrim(Str(Reccount("matched")))+" matches"
Thisform.list1.Value=1
endif
Return .T.
Function text1.interactivechange()
local m.xx
m.xx=alltrim(this.value)
select 0
use data\canton noupdate
Select distinct thekey As big5, Space(1) As changjei, .F. As leaf , "" as kissed;
from canton ;
where (left(thekey,len(m.xx))=m.xx or empty(m.xx)) ;
and !empty(thekey) ;
into Cursor matched
use in canton
with thisform.list1
.columncount=1
.requery()
.value=1
endwith
return .t.
Function edit1.valid()
local m.aa, m.errhand
if !empty(this.value)
m.aa=alltrim(this.value)
m.aa=strtran(m.aa,space(1),"")
m.aa=strtran(m.aa,chr(13),"")
m.aa=strtran(m.aa,chr(10),"")
m.errhand=on("error")
on error *
m.aa=eval(m.aa)
on error &errhand
if type("m.aa")="N"
if m.aa<>0
thisform.lblCalculate.caption=floatpnt(m.aa,15,4)
endif
else
thisform.lblCalculate.caption="Not an equation!!"
endif
thisform.cmdReset.enabled=.t.
endif
return .t.
Procedure list1.KeyPress
Lparameter nkeycode, nsac
Local m.thekey
If nkeycode=K_ENTER
* ENTER
If matched.leaf
* leaf node, no need to drill further
thisform.addone(matched.big5)
Thisform.edit1.Value=Thisform.edit1.Value+matched.big5
Thisform.lblChangjei.Caption=matched.changjei
thisform.cmdReset.enabled=.t.
Thisform.text1.SetFocus()
Nodefault
Else
* branch node, load the chinese characters of the branch
m.thekey=matched.big5
Thisform.text1.Value=m.thekey
Thisform.text1.lastvalue=m.thekey
select 0
use data\canton noupdate
if used("matched")
use in matched
endif
Select big5, changjei, .T. As leaf, kissed_mask(touched) as kissed ;
from canton ;
where thekey=m.thekey ;
order by touched descending ;
into Cursor matched
use in canton
Thisform.list1.Requery()
Thisform.lblMatches.Caption=Alltrim(Str(Reccount("matched")))+" matches"
Thisform.list1.Value=1
Endif
Endif
Endproc
Procedure cmdClip.Click
* copy to windows clipboard
if !empty(thisform.edit1.value)
_cliptext=thisform.edit1.value
thisform.buffer=thisform.buffer ;
+iif(empty(thisform.buffer),"",chr(13)+chr(10)) ;
+thisform.edit1.value
thisform.cmdHistory.enabled=.t.
Thisform.text1.SetFocus()
endif
Endproc
Procedure cmdHistory.Click
if !empty(thisform.buffer)
thisform.edit1.value=Thisform.buffer
thisform.buffer=""
thisform.cmdReset.enabled=.t.
this.enabled=!empty(thisform.buffer)
Thisform.text1.SetFocus()
endif
Endproc
Procedure cmdReset.Click
local m.lastline
if !empty(thisform.edit1.value)
if thisform.lastclip()<>thisform.edit1.value
thisform.buffer=thisform.buffer ;
+iif(empty(thisform.buffer),"",chr(13)+chr(10)) ;
+thisform.edit1.value
endif
Thisform.edit1.Value=""
thisform.cmdHistory.enabled=!empty(thisform.buffer)
this.enabled=.f.
Thisform.text1.SetFocus()
endif
Endproc
function lastclip
local m.xx
m.xx=mline(thisform.buffer,memlines(thisform.buffer))
return strtran(strtran(m.xx,chr(13),""),chr(10),"")
Procedure Load
If !File("data\canton.dbf")
If !Thisform.readcanton()
Return .F.
Endif
Endif
Create Cursor remap ( vowel c(5), original c(10), modified c(10) )
Thisform.makeremap()
Select 0
Use data\canton noupdate
Select distinct thekey As big5, Space(1) As changjei, .F. As leaf , "" as kissed;
from canton ;
where !empty(thekey) ;
into Cursor matched
use in canton
Endproc
Procedure Init
local m.xx, m.yy
select 0
use data\canton noupdate
count to m.xx for !empty(thekey)
with Thisform.lblCalculate
.Caption=Alltrim(Str(m.xx))+" words"+space(2)+Alltrim(Str(reccount("matched")))+" syllables"
endwith
use in canton
with Thisform.list1
.Value=1
endwith
Endproc
Procedure Activate
_Screen.Visible=.F.
Endproc
Procedure Unload
Use In matched
Use In remap
Endproc
Procedure KeyPress
Parameters nkeycode, nsac
If nkeycode=K_ESC
Thisform.QueryUnload()
Nodefault
Endif
Endproc
Procedure QueryUnload
Local frmQuit
Local loParam
if this.ReleaseType=2
g_quit=.t.
clear events
thisform.release()
nodefault
else
loParam=Createobject("MyParam")
frmQuit=Createobject("quitform",loParam)
frmQuit.Show()
Do Case
Case loParam.toquit=0
g_quit=.T.
Nodefault
Clear Events
Thisform.Release()
Case loParam.toquit=1
Nodefault
Case loParam.toquit=2
Clear Events
Endcase
endif
Endproc
Procedure Destroy
_Screen.Visible=.T.
Endproc
function addone
lparameter m.lcBig5
select 0
use data\canton shared
locate for big5=m.lcBig5
if found()
select canton
replace touched with touched+1
endif
use in canton
return .t.
Function readcanton
If File("canton.dbf")
? "CANTON.DBF already existed! Rename it."
Return .F.
Endif
Create Table canton ( thekey c(10), big5 c(2) )
Create Cursor temp ( Aline c(80) )
Append From canton.txt Type Sdf
Select temp
m.maxlen=0
Scan
If Recno() > 2
xx=At(" ",temp.Aline)
kk=Left(temp.Aline,xx)
If !Empty(m.kk)
If Len(m.kk) > m.maxlen
m.maxlen=Len(m.kk)
Endif
big5=Alltrim(Substr(temp.Aline,xx,xx+20))
Insert Into canton Values (kk, m.big5)
Endif
Endif
Endscan
? "max key length=",m.maxlen
? "word count=",Reccount("canton")
Close All
Return .T.
Procedure readoldcanton
Select 0
Use data\canton Shared
Select 0
Use ophrase Shared
Scan
Replace ophrase.Found With Space(1)
Select canton
Locate For big5=ophrase.Code
If Found()
Replace canton.canton With ophrase.Sound
Else
Insert Into canton ( ;
big5, canton ;
) Values ( ;
ophrase.Code, ophrase.Sound ;
)
Endif
Endscan
Use In canton
Use In ophrase
Endproc
Procedure readchangjei
Select 0
Use data\canton Shared
Create Cursor t_changjei ( ;
filler c(4),;
big5 c(2),;
radical c(3),;
stroke c(3),;
changjei c(10),;
found c(1);
)
Append From changjei.txt Delimited With Tab
Scan
Select canton
Locate For big5=t_changjei.big5
If Found()
Select canton
Replace changjei With t_changjei.changjei
Else
Insert Into canton ( ;
big5, changjei ;
) Values ( ;
t_changjei.big5,t_changjei.changjei ;
)
Endif
Endscan
Select t_changjei
Brow For Empty(t_changjei.Found)
Use In t_changjei
Use In canton
Endproc
Procedure makeremap
* missing: DEN, AI, TAG, TIM
Insert Into remap Values ( "IU", "DIU", "DEW" )
Insert Into remap Values ( "EONG", "CHEONG", "CHERN" )
Insert Into remap Values ( "EUNG", "CHEUNG", "CHERN" )
Insert Into remap Values ( "EUNG", "LEUNG", "LERN" )
Insert Into remap Values ( "EUNG", "HEUNG", "HERN" )
Insert Into remap Values ( "EUNG", "KEUNG", "KERN" )
Insert Into remap Values ( "EUNG", "SHEUNG","SHERN" )
Insert Into remap Values ( "EUNG", "TSEUNG","JUNK" )
Insert Into remap Values ( "ANG", "HANG", "HUNT" )
Insert Into remap Values ( "EAN", "DEAN", "DIN" )
Insert Into remap Values ( "O", "NGO", "ALL" )
Insert Into remap Values ( "O", "LO", "NO" ) && LOW, LAW
Insert Into remap Values ( "O", "SO", "SOUL" )
Insert Into remap Values ( "O", "KO", "GO" )
Insert Into remap Values ( "O", "HO", "HALL" )
Insert Into remap Values ( "O", "WO", "WALL" )
Insert Into remap Values ( "O", "MO", "MODE" )
Insert Into remap Values ( "IN", "LIN", "LEAN" )
Insert Into remap Values ( "IN", "NIN", "LEAN" )
Insert Into remap Values ( "IN", "LIN", "LEAN" )
Insert Into remap Values ( "IN", "HIN", "HINT" )
Insert Into remap Values ( "AN", "SAM", "SUM" )
Insert Into remap Values ( "AM", "KAM", "GUM" )
Insert Into remap Values ( "AM", "NAM", "LARM" )
Insert Into remap Values ( "AM", "LAM", "LUMP" ) && LUMP, LARM
Insert Into remap Values ( "AU", "LAU", "NULL" ) && NULL, LOUD
Insert Into remap Values ( "AU", "SAU", "SHOUT" )
Insert Into remap Values ( "AU", "GAU", "COW" )
Insert Into remap Values ( "AU", "KAU", "CULT" )
Insert Into remap Values ( "AU", "NGAU", "OUT" )
Insert Into remap Values ( "AU", "CHAU", "CHOW" )
Insert Into remap Values ( "AU", "SHAU", "SHOUT" )
Insert Into remap Values ( "AN", "KWAN", "GROUND" )
Insert Into remap Values ( "AN", "MAN", "MUNK" )
Insert Into remap Values ( "AN", "SAN", "SARM" ) && SARM, SAND
Insert Into remap Values ( "AN", "DAN", "DANT" ) && DEN, DANT, DOWN
Insert Into remap Values ( "ENG", "SENG", "SUNK" )
Insert Into remap Values ( "IN", "HIN", "HINT" )
Insert Into remap Values ( "IN", "MIN", "MEAN" )
Insert Into remap Values ( "IN", "NIN", "LEAN" )
Insert Into remap Values ( "IN", "MUN", "MOON" )
Insert Into remap Values ( "EE", "MEE", "MEAN" )
Insert Into remap Values ( "EE", "LEE", "LAY" )
Insert Into remap Values ( "ING", "CHING", "CHAIN" )
Insert Into remap Values ( "ING", "NING", "LINK" )
Insert Into remap Values ( "ING", "LING", "LINK" )
Insert Into remap Values ( "ING", "MING", "MAIN" )
Insert Into remap Values ( "ONG", "KWONG", "GONE" )
Insert Into remap Values ( "ONG", "TONG", "TOM" )
Insert Into remap Values ( "ONG", "KONG", "GONE" )
Insert Into remap Values ( "ON", "BON", "BOMB" )
Insert Into remap Values ( "ONG", "BONG", "BOMB" )
Insert Into remap Values ( "ONG", "WONG", "WARM" )
Insert Into remap Values ( "UN", "KWUN", "KOON" )
Insert Into remap Values ( "UN", "NUN", "LUNG" )
Insert Into remap Values ( "UK", "LUK", "LOOK" )
Insert Into remap Values ( "UK", "KUK", "COOK" )
Insert Into remap Values ( "UNG", "CHUNG", "JONE" ) && LUNG, LOAN
Insert Into remap Values ( "UNG", "SUNG", "ZONE" )
Insert Into remap Values ( "UNG", "KUNG", "CONE" )
Insert Into remap Values ( "UNG", "TUNG", "TONE" ) && TONE, DONT
Insert Into remap Values ( "UNG", "FUNG", "PHONE" )
Insert Into remap Values ( "OI", "OI", "OIL" )
Insert Into remap Values ( "OI", "LOI", "LOY" )
Insert Into remap Values ( "OI", "SOI", "SOIL" )
Insert Into remap Values ( "OI", "KOI", "COIL" )
Insert Into remap Values ( "OI", "TSOI", "CHOI" )
Insert Into remap Values ( "AAI", "AI", "EYE" )
Insert Into remap Values ( "AI", "AI", "EYE" )
Insert Into remap Values ( "AI", "KWAI", "QUITE" )
Insert Into remap Values ( "AI", "DAI", "DIE" )
Insert Into remap Values ( "AI", "TAI", "TIE" )
Insert Into remap Values ( "AI", "WAI", "RIGHT" )
Insert Into remap Values ( "AI", "LAI", "LIKE" ) && LIE, LIKE
Insert Into remap Values ( "AI", "SAI", "SITE" )
Insert Into remap Values ( "AI", "MAI", "MIND" )
Insert Into remap Values ( "AI", "KAI", "GUY" )
Insert Into remap Values ( "AI", "FAI", "FINE" )
Insert Into remap Values ( "AI", "HAI", "HIGH" )
Insert Into remap Values ( "SI", "SI", "SEE" )
Insert Into remap Values ( "LI", "LI", "LAY" )
Insert Into remap Values ( "A", "WA", "WAH" )
Insert Into remap Values ( "IU", "YIU", "YIELD" )
Insert Into remap Values ( "IU", "LIU", "NEW" )
Insert Into remap Values ( "IU", "SIU", "SILL" )
Insert Into remap Values ( "IU", "TIU", "TILL" )
Insert Into remap Values ( "IU", "KIU", "KILL" )
Insert Into remap Values ( "IU", "SHIU", "SILL" )
Insert Into remap Values ( "IU", "HIU", "HILL" )
Insert Into remap Values ( "IU", "GIU", "GILL" )
Insert Into remap Values ( "IU", "MIU", "MILL" )
Insert Into remap Values ( "IU", "CHIU", "CHEW" )
Insert Into remap Values ( "AO", "TAO", "THOUGH" )
Insert Into remap Values ( "AO", "DAO", "THOUGH" )
Insert Into remap Values ( "AO", "MAO", "MODE" )
Insert Into remap Values ( "A", "TA", "TAR" )
Insert Into remap Values ( "A", "KA", "CAR" )
Insert Into remap Values ( "A", "CHA", "CHAR" )
Insert Into remap Values ( "A", "SA", "CZAR" )
Insert Into remap Values ( "A", "KWA", "GRA" )
Insert Into remap Values ( "EI", "LEI", "LAY" )
Insert Into remap Values ( "EI", "SEI", "SAY" )
Insert Into remap Values ( "AK", "TAK", "DUCK" )
Insert Into remap Values ( "UE", "YUE", "YU" )
Insert Into remap Values ( "EH", "YEH", "YEAH" )
Insert Into remap Values ( "AAK", "AAK", "ARK" )
Insert Into remap Values ( "EUK", "LEUK", "LURK" )
Insert Into remap Values ( "IC", "LIC", "LEG" )
Insert Into remap Values ( "IC", "VIC", "WAKE" )
Endproc
Enddefine
Define Class quitform As Form
Caption="Quit"
Height=150
Width=200
AutoCenter=.T.
WindowType=1
ShowWindow=1
ControlBox=.F.
oQuit=.F.
Add Object btnYes As mycommandbutton With ;
top=10,Left=20,Caption="\ m.maxlen
m.maxlen=Len(Alltrim(thekey))
Endif
? Alltrim(thekey)
Select canton
Scan For thekey=t_thekey.thekey
?? Space(1)+Alltrim(canton.big5)
Endscan
Endscan
Use In t_thekey
Use In canton
Set Alternate Off
Set Alternate To
? "maximum length:",m.maxlen
Set Talk On
Set Safety On
Endproc
function floatpnt
parameter m.in_prce, m.in_wid, m.in_dec
*
* copied from WAE's PROCEDR2.PRG
*
* m.in_prce = the floating point value
* m.in_wid = the output width
* m.in_dec = the maximum precision of m.in_prce
*
* 25/09/01 - MMC, created. beware of the limits...
*
* you can use the following to re-test this function
* set decimal to 5
* for m.ii=0 to 7
* for m.jj=1 to 5
* m.vv=10**m.ii+1/10**m.jj
* ? m.ii, floatpnt(m.vv,7), floatpnt(-m.vv,7)
* endfor
* endfor
*
private m.prce, m.wid, m.dec
private M.ss, m.xx, o_dec
if m.in_wid-m.in_dec<2
* you need at least "0.", and "-" sign
return "I CANT"
endif
o_dec=set("decimal")
set decimal to m.in_dec
m.dec=m.in_dec
m.prce=abs(m.in_prce)
m.wid=m.in_wid
if m.in_prce<0
m.wid=m.wid-1
endif
if m.wid-m.dec<2
* "0." has 2 places at least
m.dec=m.dec-1
endif
m.ss=str(m.prce,15,m.dec)
if m.prce>10**(m.wid-1)
* the recursive call here is pretty useless. but...
m.ss=str(m.prce/1000,15)+"K"
else
* check the width of the part before decimal point
* trim the mantissa accordingly
if m.prce<=1
m.xx=m.dec
else
m.xx=m.wid-(int(log10(m.prce))+1)-1
if m.xx<=0
m.xx=0
endif
endif
m.ss=str(m.prce,15,m.xx)
endif
m.ss=alltrim(right(m.ss,m.wid))
if m.in_prce<0
m.ss="-"+m.ss
endif
* removing trailing decimal zero
if "."$m.ss
do while right(m.ss,1)="0"
m.ss=left(m.ss,len(m.ss)-1)
enddo
if right(m.ss,1)="."
m.ss=left(m.ss,len(m.ss)-1)
endif
if val(m.ss)=0
m.ss="0"
endif
endif
set decimal to &o_dec
return padl(m.ss,m.in_wid)
function kissed_mask
lparameter m.touched
local m.xx
if m.touched>9999
m.touched=9999
endif
if m.touched=0
m.xx=""
else
m.xx=str(m.touched,5)
endif
return padr(m.xx,6)
function mailto
local m.lcMail
DECLARE INTEGER ShellExecute ;
IN SHELL32.DLL ;
INTEGER nWinHandle,;
STRING cOperation,;
STRING cFileName,;
STRING cParameters,;
STRING cDirectory,;
INTEGER nShowWindow
m.lcMail = "mailto:toylet.toylet@gmail.com"+ ;
"?CC=&Subject= About Chang's Cantonese Input"+ ;
"&Body= "
ShellExecute(0,"open",m.lcMail,"","",1)
release dll
return .t.
FUNCTION FirstInstance(pMutex) && pMutex=Program name
#DEFINE ERROR_ALREADY_EXISTS 183
DECLARE INTEGER CreateMutex IN WIN32API INTEGER, INTEGER, STRING @
DECLARE INTEGER CloseHandle IN WIN32API INTEGER
DECLARE INTEGER GetLastError IN WIN32API
nExeHwnd=CreateMutex(0, 1, @pMutex)
IF GetLastError()=ERROR_ALREADY_EXISTS
CloseHandle(nExeHwnd)
RETURN .F.
ELSE
RETURN .T.
ENDIF
ENDFUNC