by jhncon » Thu Dec 15, 2005 12:10 am
i have modified xFWH\..\TGet.prg and xHBR\..\strcase.c for supporting Big5 long time and seems OK, extracted code as following:
John M. S. Chiang
// ----- xFWH\..\TGet.prg
::lBig5 = If( !Empty(::oWnd), ::oWnd:lBig5, GetOEMCP()==950 ) // JMS
........................
METHOD KeyDown( nKey, nFlags ) CLASS TGet
......
case nKey == VK_RIGHT
nPos = ::oGet:Pos
if nPos >= Len(::oGet:Buffer) .or. ; // JMS
( ::lBig5 .and. nPos == Len(::oGet:Buffer)-1 .and. lBig5_1st( ::oGet:Buffer, nPos ) )
::GoNextGet() // JMS // ::oWnd:GoNextCtrl( ::hWnd, .t. ) // JMS
return 1
endif
if GetKeyState( VK_CONTROL )
::oGet:wordRight()
else
::oGet:right()
endif
if nPos <> ::oGet:Pos
while .t.
CallWindowProc( ::nOldProc, ::hWnd, WM_KEYDOWN, nKey, nFlags )
::GetSelPos( @nLo, @nHi )
if nHi + 1 >= ::oGet:Pos .or. ::lPassword .or. ;
nHi == nLastHi
EXIT
endif
nLastHi = nHi
end
::oGet:Pos = nHi + 1
::nPos = nHi + 1
endif
return 0
// Many thanks to HMP
...........
case nKey == VK_DELETE .or. nKey == VK_BACK
if nKey == VK_BACK .and. ::nPos == 0
::nPos := 1 // JMS necessary
::SetPos( ::nPos )
retu 0
endif
if ::lReadOnly
return 0
endif
if ::lDrag
return Super:KeyDown( nKey, nFlags )
endif
::GetSelPos( @nLo, @nHi )
// Deletes selection
if nHi != nLo
::GetDelSel( nLo, nHi )
if GetKeyState( VK_SHIFT )
CallWindowProc( ::nOldProc, ::hWnd, WM_KEYDOWN, nKey, nFlags )
endif
else
if !::lBig5 // JMS
if nKey == VK_DELETE
::oGet:Delete()
else
::oGet:BackSpace()
endif
else
if nKey == VK_DELETE // .and. !Empty(::oGet:Buffer) // revised from above 00-03-28 JMS
if lBig5_1st( ::oGet:Buffer,::nPos )
::oGet:Buffer := SubStr( ::oGet:Buffer, 1, ::nPos - 1 ) + ;
' ' + SubStr( ::oGet:Buffer, ::nPos + 2 )
::oGet:Delete()
endif
::oGet:Delete()
else
if ::nPos > 2 .and. lBig5_2nd( ::oGet:Buffer,::nPos-1 )
::oGet:Buffer := SubStr( ::oGet:Buffer, 1, ::nPos - 3 ) + ;
' ' + SubStr( ::oGet:Buffer, ::nPos )
::oGet:BackSpace()
endif
::oGet:BackSpace()
endif
endif
endif
::EditUpdate()
if ::bChange != nil
Eval( ::bChange, nKey, nFlags, Self )
endif
return 0
..............
//---------------------------------
METHOD KeyChar( nKey, nFlags ) CLASS TGet // KeyChar() runs before KeyDown()
// for ChineseBig5 1st(high_order) Chr( 161 - 254 ), 2nd(Low_order) Chr( 64 - 126, 161 - 254 )
local nHi, nLo, cStrike, lIns, nInsPos // JMS
local lAccept
local bKeyAction := SetKey( nKey )
local nDefButton, lChar := .t. // JMS
if ! Empty( ::cPicture ) .and. '@!' $ ::cPicture
nKey = Asc( Upper( Chr( nKey ) ) )
endif
if bKeyAction != nil .and. lAnd( nFlags, 16777216 ) // function Key
Eval( bKeyAction, ProcName( 4 ), ProcLine( 4 ), Self )
return 0 // Already processed, API do nothing
endif
if ::lReadOnly
if nKey == VK_ESCAPE
::oWnd:End()
endif
return 0
endif
do case
case nKey == VK_BACK // Already processed at KeyDown
If( ::nPos==0, ::SetPos( ::nPos := 1 ), ) // JMS necessary
return 0
case nKey == VK_ESCAPE // JMS to set VK_ESCAPE no Action
return 0 // but Escaped if not oGet lFocused
case nKey == VK_TAB .and. GetKeyState( VK_SHIFT )
::cStrIn := '' // JMS
::lChrHL := .f. // JMS
if ::bChange != nil
lAccept = Eval( ::bChange, nKey, nFlags, Self )
if ValType( lAccept ) == "L" .and. lAccept
if Upper( ::oWnd:ClassName() ) == "TCOMBOBOX"
::oWnd:oWnd:GoPrevCtrl( ::hWnd )
else
::GoPrevGet() // JMS // ::oWnd:GoPrevCtrl( ::hWnd, .t. ) // JMS
endif
endif
else
if Upper( ::oWnd:ClassName() ) == "TCOMBOBOX"
::oWnd:oWnd:GoPrevCtrl( ::hWnd )
else
::GoPrevGet() // JMS // ::oWnd:GoPrevCtrl( ::hWnd, .t. ) // JMS
endif
endif
return 0
case nKey == VK_TAB .or. nKey == VK_RETURN
::cStrIn := '' // JMS
::lChrHL := .f. // JMS
if ::bChange != nil
lAccept = Eval( ::bChange, nKey, nFlags, Self )
if ValType( lAccept ) == "L" .and. lAccept
::GoNextGet() // JMS // ::oWnd:GoNextCtrl( ::hWnd, .t. ) // JMS
endif
else
::GoNextGet() // JMS // ::oWnd:GoNextCtrl( ::hWnd, .t. ) // JMS
endif
#ifdef __HARBOUR__
// if nKey == VK_RETURN // Execute DEFPUSHBUTTON Action
// Super:KeyChar( nKey, nFlags ) // JMS deleted on 031020 to avoid reach PUSHBUTTON directly
// endif
#endif
return 0
case nKey >= 32 .and. nKey < 256
#ifdef __HARBOUR__
// <lk> deadkey+tab [or enter] previously pressed will cause a r/t error
if ::oGet:buffer == nil
return 0
endif
#endif
If ::oGet:Pos == nil // JMS
retu 0
endif
::cStrIn += ::oGet:Input(Chr(nKey)) // JMS :cStrIn was cut to end at same end postion of :buffer originally while input Big5 ...
::GetSelPos( @nLo, @nHi )
// Delete selection
if nHi != nLo
::lChrHL := .t. // JMS
if !( lIns := Set( _SET_INSERT ) )
Set( _SET_INSERT, .t. )
endif
*-----
::GetDelSel( nLo, nHi, @lChar ) // JMS
if !lChar
return 0
endif
::EditUpdate()
endif
if ::oGet:Type == "N" .and. Chr( nKey ) $ ".," // JMS
::oGet:ToDecPos()
elseif ::oGet:Type == "N" .and. !( Chr( nKey ) $ " -0123456789" )
return 0
else
// if ::bChange != nil // JMS, move behind for real action
// lAccept = Eval( ::bChange, nKey, nFlags, Self )
// if ValType( lAccept ) == "L" .and. ! lAccept
// return 0
// endif
// endif
if ::lBig5 .and. ::nPos == Len( ::oGet:Buffer ) .and. ( nKey >= 161 .and. nKey <= 254 ) // JMS possible Big5 1st(high_order) Chr( 161 - 254 ), but at End
if Len( ::cStrIn ) == 1 .or. ; // Big5_1st at end of effective ::cStrIn
( Len( ::cStrIn ) >= 3 .and. lBig5_2nd( ::cStrIn, Len(::cStrIn)-1 ) )
nKey := 32 // Space
endif
endif
if Set( _SET_INSERT ) .or. ::lChrHL // many thanks to HMP
if ::lBig5 .and. ::nPos < Len( ::oGet:Buffer )
if lBig5_2nd( ::oGet:Buffer,Len(::oGet:Buffer) )
::oGet:Buffer := Left( ::oGet:Buffer,Len(::oGet:Buffer)-2 ) + Space( 2 )
endif
endif
nInsPos := ::oGet:pos // JMS
::oGet:Insert( Chr( nKey ) )
if ::lChrHL .and. Len(::cStrIn) > 1
::oGet:pos := nInsPos // JMS for Selected condition, Big5 filled up in FistIn LastWrite
endif
else
cStrike := nil
if ::lBig5 .and. ::nPos < Len( ::oGet:Buffer )
if nKey >= 161 .and. nKey <= 254 // Could be 1st_Big5
if lBig5_1st( ::oGet:Buffer,::nPos+1 )
::oGet:Buffer := SubStr( ::oGet:Buffer, 1, ::nPos ) + ;
' ' + SubStr( ::oGet:Buffer, ::nPos + 3 )
endif
else
if lBig5_1st( ::oGet:Buffer,::nPos )
::oGet:Buffer := SubStr( ::oGet:Buffer, 1, ::nPos - 1 ) + ;
' ' + SubStr( ::oGet:Buffer, ::nPos + 2 )
cStrike := ' '
endif
endif
endif
::oGet:Overstrike( Chr(nKey) )
if cStrike != nil
::oGet:Overstrike( cStrike ) // JMS
::oGet:Pos -- // JMS
::nPos --
endif
endif
if ::lBig5 .and. ::nPos == Len( ::oGet:Buffer ) .and. lBig5_2nd( ::oGet:Buffer,::nPos )
::oGet:Pos -- // JMS
::nPos --
endif
if Len( ::cStrIn ) > 1 // to keep Caret width after Big5 Input
DestroyCaret()
If( Set( _SET_INSERT ), CreateCaret( ::hWnd, 0, 5, ::nGetChrHeight()-1 ),;
CreateCaret( ::hWnd, 0, 2, ::nGetChrHeight()-1 ) )
ShowCaret( ::hWnd )
endif
if ::bChange != nil
lAccept = Eval( ::bChange, nKey, nFlags, Self )
if ValType( lAccept ) == "L" .and. ! lAccept
return 0
endif
endif
endif
if ::oGet:Rejected
MsgBeep()
endif
::EditUpdate()
if ::oGet:TypeOut
if ! Set( _SET_CONFIRM )
::oWnd:nLastKey = VK_RETURN // VK_DOWN 17/10/95
::GoNextGet() // JMS // ::oWnd:GoNextCtrl( ::hWnd, .t. ) // JMS
::cStrIn := '' // JMS
::lChrHL := .f. // JMS
else
MsgBeep()
endif
endif
*-------
if nHi != nLo .and. !lIns // JMS
Set( _SET_INSERT, .f. )
if ::oGet:TypeOut
DestroyCaret()
CreateCaret( ::hWnd, 0, 2, ::nGetChrHeight()-1 ) // JMS
ShowCaret( ::hWnd )
endif
endif
otherwise
::cStrIn := '' // JMS
::lChrHL := .f. // JMS
return Super:KeyChar( nKey, nFlags )
endcase
return 0
//-------------------------------------------------------
// for ChineseBig5 1st(high_order) Chr( 161 - 254 ), 2nd(Low_order) Chr( 64 - 126, 161 - 254 )
BOOL ulBig5_2nd( unsigned char * aStr, int nPos, int nLen )
{
int nn ;
unsigned int nAsc1 ;
unsigned int nAsc2 ;
if( nLen < nPos )
return FALSE ;
else if( nPos == 1 )
return FALSE ;
else if( nPos == 2 )
{
nAsc1 = aStr[0] ;
nAsc2 = aStr[1] ;
if( ( nAsc1 >= 161 && nAsc1 <= 254 ) &&
( ( nAsc2 >= 64 && nAsc2 <= 126 ) || ( nAsc2 >= 161 && nAsc2 <= 254 ) ) )
return TRUE ;
else
return FALSE ;
}
else
{
nAsc1 = aStr[nPos-2] ;
nAsc2 = aStr[nPos-1] ;
if( ( nAsc2 < 64 || ( nAsc2 > 126 && nAsc2 < 161 ) || nAsc2 > 254 ) )
return FALSE ;
else if ( nAsc1 < 161 || nAsc1 > 254 )
return FALSE ;
else
{
for( nn = 1 ; nn < nPos; nn++ )
{
nAsc1 = aStr[nn-1] ;
nAsc2 = aStr[nn] ;
if( nAsc1 >= 161 && nAsc1 <= 254 )
{
if( ( nAsc2 >= 64 && nAsc2 <= 126 ) || ( nAsc2 >= 161 && nAsc2 <= 254 ) )
{
if( nn+1 == nPos )
return TRUE ;
else if( nn < nPos-1 )
nn ++ ;
}
}
};
if( nn >= nPos )
return FALSE ;
}
}
return FALSE ;
}
//-----------------------------------------------
HB_FUNC( LBIG5_1ST ) // lBig5_1st( cString, nPos )
{
unsigned char * aStr = (unsigned char * ) hb_parc( 1 ) ;
int nPos = hb_parni( 2 ) ;
int nLen = hb_parclen( 1 ) ;
unsigned int nAsc1 ;
if( nPos < nLen )
{
nAsc1 = aStr[nPos-1] ;
if( ( nAsc1 >= 161 && nAsc1 <= 254 ) && ulBig5_2nd( aStr, nPos+1, nLen ) )
hb_retl(TRUE);
else
hb_retl(FALSE);
}
else
hb_retl(FALSE);
}
//-----------------------------------------------
HB_FUNC( LBIG5_2ND ) // lBig5_2nd( cString, nPos )
{
hb_retl( ulBig5_2nd( (unsigned char * ) hb_parc( 1 ), hb_parni( 2 ), hb_parclen( 1 ) ) ) ;
}
//-----------------------------------------------
xHBR\..\rtl\strcase.c modified for Big5
// Big5 1st(high_order) Chr( 161 - 254 ), 2nd(Low_order) Chr( 64 - 126, 161 - 254 )
// JMS modified for trailer byte of lBig5 not influenced by Upper/Lower
/* converts szText to lower case. Does not create a new string! */
HB_EXPORT char * hb_strLower( char * szText, ULONG ulLen ) // JMS
{
ULONG i;
int nAsc1 ;
int nAsc2 ;
BOOL lBig5_1st = FALSE ;
BOOL lBig5_2nd = FALSE ;
HB_TRACE(HB_TR_DEBUG, ("hb_strLower(%s, %lu)", szText, ulLen));
if( GetOEMCP()==950 ) // lBig5
{ for( i = 0; i < ulLen; i++ )
{ if( szText[i] < 0 )
nAsc1 = 256+szText[i] ;
else
nAsc1 = szText[i] ;
if( i+1 < ulLen )
{ if( szText[i+1] < 0 )
nAsc2 = 256+szText[i+1] ;
else
nAsc2 = szText[i+1] ;
};
if( i == 0 )
{ if( i+1 < ulLen && ( nAsc1 >= 161 && nAsc1 <= 254 ) && ( ( nAsc2 >= 64 && nAsc2 <= 126 ) || ( nAsc2 >= 161 && nAsc2 <= 254 ) ) )
{ lBig5_1st = TRUE ; // Self
lBig5_2nd = FALSE ; // Self
};
}
else
{ if( lBig5_1st ) // former chr
{ lBig5_1st = FALSE ; // Self
lBig5_2nd = TRUE ; // Self
}
else
{ if( i+1 < ulLen && ( nAsc1 >= 161 && nAsc1 <= 254 ) && ( ( nAsc2 >= 64 && nAsc2 <= 126 ) || ( nAsc2 >= 161 && nAsc2 <= 254 ) ) )
{ lBig5_1st = TRUE ; // Self
lBig5_2nd = FALSE ; // Self
};
};
};
if( lBig5_2nd == FALSE )
szText[ i ] = tolower( szText[ i ] );
};
}
else
{
#ifndef HB_CDP_SUPPORT_OFF
if( hb_cdp_page->nChars )
for( i = 0; i < ulLen; i++ )
szText[ i ] = (char) hb_cdp_page->s_lower[szText[i]&255];
else
#endif
for( i = 0; i < ulLen; i++ )
szText[ i ] = tolower( (BYTE) szText[ i ] );
} // JMS
return szText;
}
HB_EXPORT char * hb_strLowerCopy( char * szText, ULONG ulLen )
{
char *szCopy = (char*) hb_xgrab( ulLen + 1 );
ULONG i;
HB_TRACE(HB_TR_DEBUG, ("hb_strLowerCopy(%s, %lu)", szText, ulLen));
#ifndef HB_CDP_SUPPORT_OFF
if( hb_cdp_page->nChars )
for( i = 0; i < ulLen; i++ )
szCopy[ i ] = (char) hb_cdp_page->s_lower[szText[i]&255];
else
#endif
for( i = 0; i < ulLen; i++ )
szCopy[ i ] = tolower( (BYTE) szText[ i ] );
szCopy[ i ] = '\0';
return szCopy;
}
HB_EXPORT char * hb_strUpperCopy( char * szText, ULONG ulLen )
{
char *szCopy = (char*) hb_xgrab( ulLen + 1 );
ULONG i;
HB_TRACE(HB_TR_DEBUG, ("hb_strUpperCopy(%s, %lu)", szText, ulLen));
#ifndef HB_CDP_SUPPORT_OFF
if( hb_cdp_page->nChars )
for( i = 0; i < ulLen; i++ )
szCopy[ i ] = (char) hb_cdp_page->s_upper[szText[i]&255];
else
#endif
for( i = 0; i < ulLen; i++ )
szCopy[ i ] = toupper( (BYTE) szText[ i ] );
szCopy[ i ] = '\0';
return szCopy;
}
/* converts szText to upper case. Does not create a new string! */
HB_EXPORT char * hb_strUpper( char * szText, ULONG ulLen ) // JMS
{
ULONG i;
int nAsc1 ;
int nAsc2 ;
BOOL lBig5_1st = FALSE ;
BOOL lBig5_2nd = FALSE ;
HB_TRACE(HB_TR_DEBUG, ("hb_strUpper(%s, %lu)", szText, ulLen));
if( GetOEMCP()==950 ) // lBig5
{ for( i = 0; i < ulLen; i++ )
{ if( szText[i] < 0 )
nAsc1 = 256+szText[i] ;
else
nAsc1 = szText[i] ;
if( i+1 < ulLen )
{ if( szText[i+1] < 0 )
nAsc2 = 256+szText[i+1] ;
else
nAsc2 = szText[i+1] ;
};
if( i == 0 )
{ if( i+1 < ulLen && ( nAsc1 >= 161 && nAsc1 <= 254 ) && ( ( nAsc2 >= 64 && nAsc2 <= 126 ) || ( nAsc2 >= 161 && nAsc2 <= 254 ) ) )
{ lBig5_1st = TRUE ; // Self
lBig5_2nd = FALSE ; // Self
};
}
else
{ if( lBig5_1st ) // former chr
{ lBig5_1st = FALSE ; // Self
lBig5_2nd = TRUE ; // Self
}
else
{ if( i+1 < ulLen && ( nAsc1 >= 161 && nAsc1 <= 254 ) && ( ( nAsc2 >= 64 && nAsc2 <= 126 ) || ( nAsc2 >= 161 && nAsc2 <= 254 ) ) )
{ lBig5_1st = TRUE ; // Self
lBig5_2nd = FALSE ; // Self
};
};
};
if( lBig5_2nd == FALSE )
szText[ i ] = toupper( szText[ i ] );
};
}
else
{
#ifndef HB_CDP_SUPPORT_OFF
if( hb_cdp_page->nChars )
for( i = 0; i < ulLen; i++ )
szText[ i ] = (char) hb_cdp_page->s_upper[szText[i]&255];
else
#endif
for( i = 0; i < ulLen; i++ )
szText[ i ] = toupper( (BYTE) szText[ i ] );
} // JMS
return szText;
}
//------------------------------
John M. S. Chiang