Files
harbour-core/harbour/source/rtl/hbi18n1.c
Przemyslaw Czerpak c9731a76a7 2009-06-26 15:52 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/source/rdd/hsx/hsx.c
    * removed ( BYTE * ) casting

  * harbour/include/hbchksum.h
  * harbour/source/rtl/hbadler.c
  * harbour/source/rtl/hbcrc.c
  * harbour/source/rtl/hbmd5.c
    * use 'const char *' for passed memory buffers
         ULONG hb_adler32( ULONG adler, const char *buf, ULONG len );
         ULONG hb_crc16( ULONG crc, const char *buf, ULONG len );
         ULONG hb_crc32( ULONG crc, const char *buf, ULONG len );
         HB_ULONG hb_crc( HB_ULONG crc, const char * buf, ULONG len,
                          HB_ULONG poly );
         HB_ULONG hb_crcct( HB_ULONG crc, const char * buf, ULONG len,
                            HB_ULONG poly );
         void hb_md5( const char * ucData, ULONG ulLen, char * ucDigest );
         void hb_md5file( HB_FHANDLE hFile, char * ucDigest );

  * harbour/include/hbsxfunc.h
  * harbour/source/rdd/hbsix/sxcompr.c
  * harbour/source/rdd/hbsix/sxcrypt.c
    * use '[const] char *' for passed memory buffers in:
         void hb_sxEnCrypt( const char * pSrc, char * pDst,
                            const char * pKeyVal, ULONG ulLen );
         void hb_sxDeCrypt( const char * pSrc, char * pDst,
                            const char * pKeyVal, ULONG ulLen );
         BOOL hb_LZSSxDecompressMem( const char * pSrcBuf, ULONG ulSrcLen,
                                     char * pDstBuf, ULONG ulDstLen );
         BOOL hb_LZSSxCompressMem( const char * pSrcBuf, ULONG ulSrcLen,
                                   char * pDstBuf, ULONG ulDstLen,
                                   ULONG * pulSize );

  * harbour/include/hbapigt.h
  * harbour/include/hbgtcore.h
  * harbour/source/rtl/hbgtcore.c
  * harbour/source/rtl/mouse53.c
  * harbour/source/rtl/mouseapi.c
  * harbour/source/rtl/gtdos/gtdos.c
    * changed 'const BYTE *' to 'const char *' in MouseSaveState()
      and MouseRestoreState() GT methods and functions.

  * harbour/source/rtl/cdpapi.c
  * harbour/source/rtl/is.c
    * added ( char * ) casting as workaround for wrong in MSVC strchr()
      declaration.

  * harbour/include/hbrdddbf.h
  * harbour/source/rdd/dbf1.c
  * harbour/source/rtl/hbi18n1.c
  * harbour/contrib/xhb/hbcrypt.c
    * updated for above modifications
2009-06-26 13:53:41 +00:00

1069 lines
29 KiB
C

/*
* $Id$
*/
/*
* Harbour Project source code:
* I18N translation Harbour functions
*
* Copyright 2008 Przemyslaw Czerpak <druzus / at / priv.onet.pl>
* www - http://www.harbour-project.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
*
* As a special exception, the Harbour Project gives permission for
* additional uses of the text contained in its release of Harbour.
*
* The exception is that, if you link the Harbour libraries with other
* files to produce an executable, this does not by itself cause the
* resulting executable to be covered by the GNU General Public License.
* Your use of that executable is in no way restricted on account of
* linking the Harbour library code into it.
*
* This exception does not however invalidate any other reasons why
* the executable file might be covered by the GNU General Public License.
*
* This exception applies only to the code released by the Harbour
* Project under the name Harbour. If you copy code from other
* Harbour Project or Free Software Foundation releases into a copy of
* Harbour, as the General Public License permits, the exception does
* not apply to the code that you add in this way. To avoid misleading
* anyone as to the status of such modified files, you must delete
* this exception notice from them.
*
* If you write modifications of your own for Harbour, it is your choice
* whether to permit this exception to apply to your modifications.
* If you do not wish that, delete this exception notice.
*
*/
#define _HB_I18N_INTERNAL_
#include "hbapi.h"
#include "hbapiitm.h"
#include "hbapierr.h"
#include "hbapicdp.h"
#include "hbmath.h"
#include "hbvm.h"
#include "hbstack.h"
#include "hbthread.h"
#include "hbchksum.h"
/*
i18n hash table items:
"LANG" => <cLangID>
"BASE_LANG" => <cLangID>
"CODEPAGE" => <cCodePage>
"BASE_CODEPAGE" => <cCodePage>
"DESCRIPTION" => <cDescription>
"PLURAL_EXP" => <cPluralExp>
"BASE_PLURAL_EXP" => <cPluralExp>
"CONTEXT" => ;
{ "" => { <cMsg> => <cResult> | <aResult> } ; // default context
[, <cContext> => { <cMsg> => <cResult> | <aResult> } ] }
i18n file format:
00-03 signature { 193, 'H', 'B', 'L' }
04-07 size of serialized i18n hash table, 32 bits in little endian order
08-11 CRC32 of serialized i18n hash table
12-15 unused
16-47 description
48-63 unused
64-.. serialized i18n hash table
*/
#define HB_I18N_HEADER_SIZE 64
#define HB_I18N_SIG_OFFSET 0
#define HB_I18N_SIG_SIZE 4
#define HB_I18N_SIZE_OFFSET 4
#define HB_I18N_CRC_OFFSET 8
#define HB_I18N_TXT_OFFSET 16
#define HB_I18N_TXT_SIZE 32
#define HB_I18N_PLURAL_EN 1
#define HB_I18N_PLURAL_PL 2
#define HB_I18N_PLURAL_LT 3
typedef struct _HB_PLURAL_FORMS
{
const char * szLangID;
int iForm;
}
HB_PLURAL_FORMS, *PHB_PLURAL_FORMS;
static const HB_PLURAL_FORMS s_plural_forms[] =
{
{ "EN", HB_I18N_PLURAL_EN },
{ "PL", HB_I18N_PLURAL_PL },
{ "LT", HB_I18N_PLURAL_LT }
};
#define HB_PLURAL_FOMRS_COUNT ( sizeof( s_plural_forms ) / sizeof( HB_PLURAL_FORMS ) )
static const UCHAR s_signature[ 4 ] = { 193, 'H', 'B', 'L' };
typedef struct _HB_I18N_TRANS
{
HB_COUNTER iUsers;
PHB_CODEPAGE cdpage;
PHB_CODEPAGE base_cdpage;
PHB_ITEM table;
PHB_ITEM context_table;
PHB_ITEM default_context;
PHB_ITEM plural_block;
PHB_ITEM base_plural_block;
int plural_form;
int base_plural_form;
}
HB_I18N_TRANS, * PHB_I18N_TRANS;
static PHB_I18N_TRANS hb_i18n_table( void )
{
return ( PHB_I18N_TRANS ) hb_vmI18N();
}
static int hb_i18n_pluralformfind( const char * szLang )
{
int i;
for( i = 0; i < ( int ) HB_PLURAL_FOMRS_COUNT; ++i )
{
if( hb_stricmp( szLang, s_plural_forms[ i ].szLangID ) == 0 )
return s_plural_forms[ i ].iForm;
}
if( strlen( szLang ) > 2 )
{
for( i = 0; i < ( int ) HB_PLURAL_FOMRS_COUNT; ++i )
{
if( hb_strnicmp( szLang, s_plural_forms[ i ].szLangID, 2 ) == 0 )
return s_plural_forms[ i ].iForm;
}
}
return 0;
}
static const char * hb_i18n_pluralformid( int iForm )
{
int i;
for( i = 0; i < ( int ) HB_PLURAL_FOMRS_COUNT; ++i )
{
if( s_plural_forms[ i ].iForm == iForm )
return s_plural_forms[ i ].szLangID;
}
return NULL;
}
static long hb_i18n_pluralindex( int iForm, PHB_ITEM pNum )
{
double n = hb_numRound( hb_itemGetND( pNum ), 10 ), n10, n100;
switch( iForm )
{
case HB_I18N_PLURAL_PL:
n10 = fmod( n, 10.0 );
n100 = fmod( n, 100.0 );
return n == 1 ? 1 : ( n10 >= 2 && n10 <= 4 &&
( n100 < 10 || n100 >= 20 ) ? 2 : 3 );
case HB_I18N_PLURAL_LT:
n10 = fmod( n, 10.0 );
n100 = fmod( n, 100.0 );
return n100 >= 10 && n100 < 20 ? 2 : ( n10 == 1 ? 1 : 3 );
case HB_I18N_PLURAL_EN:
default:
return n == 1 ? 1 : 2;
}
}
static void hb_i18n_setitem( PHB_ITEM pHash, const char * szKey, const char * szValue )
{
PHB_ITEM pKey = hb_itemPutC( NULL, szKey );
PHB_ITEM pValue = hb_itemPutC( NULL, szValue );
hb_hashAdd( pHash, pKey, pValue );
hb_itemRelease( pKey );
hb_itemRelease( pValue );
}
static PHB_ITEM hb_i18n_pluralexp_compile( PHB_ITEM pExp )
{
ULONG ulLen = hb_itemGetCLen( pExp );
PHB_ITEM pBlock = NULL;
if( ulLen > 0 )
{
char * szMacro = ( char * ) hb_xgrab( ulLen + 6 );
const char * szType;
PHB_ITEM pMacro;
szMacro[ 0 ] = '{';
szMacro[ 1 ] = '|';
szMacro[ 2 ] = 'n';
szMacro[ 3 ] = '|';
memcpy( &szMacro[ 4 ], hb_itemGetCPtr( pExp ), ulLen );
szMacro[ 4 + ulLen ] = '}';
szMacro[ 5 + ulLen ] = '\0';
pMacro = hb_itemPutCLPtr( NULL, szMacro, ulLen );
szType = hb_macroGetType( pMacro );
if( *szType == 'B' )
{
hb_vmPush( pMacro );
hb_macroGetValue( hb_stackItemFromTop( -1 ), 0, 0 );
if( hb_vmRequestQuery() == 0 )
{
pExp = hb_stackItemFromTop( -1 );
if( HB_IS_BLOCK( pExp ) )
pBlock = hb_itemNew( pExp );
hb_stackPop();
}
}
hb_itemRelease( pMacro );
}
return pBlock;
}
static PHB_I18N_TRANS hb_i18n_new( void )
{
PHB_I18N_TRANS pI18N;
PHB_ITEM pKey;
pI18N = ( PHB_I18N_TRANS ) memset( hb_xgrab( sizeof( HB_I18N_TRANS ) ),
0, sizeof( HB_I18N_TRANS ) );
hb_atomic_set( &pI18N->iUsers, 1 );
pI18N->table = hb_hashNew( hb_itemNew( NULL ) );
pI18N->context_table = hb_hashNew( hb_itemNew( NULL ) );
pI18N->default_context = hb_hashNew( hb_itemNew( NULL ) );
pKey = hb_itemPutCConst( NULL, "CONTEXT" );
hb_hashAdd( pI18N->table, pKey, pI18N->context_table );
pKey = hb_itemPutC( pKey, NULL );
hb_hashAdd( pI18N->context_table, pKey, pI18N->default_context );
hb_itemRelease( pKey );
return pI18N;
}
/* HVM init */
void hb_i18n_init( void )
{
/* do nothing in this implementation */
}
/* HVM exit */
void hb_i18n_exit( void )
{
/* do nothing in this implementation */
}
/* make copy of i18n set for new thread */
void * hb_i18n_alloc( void * cargo )
{
if( cargo )
hb_atomic_inc( &( ( PHB_I18N_TRANS ) cargo )->iUsers );
return cargo;
}
/* release i18n set when thread is terminated */
void hb_i18n_release( void * cargo )
{
if( cargo )
{
PHB_I18N_TRANS pI18N = ( PHB_I18N_TRANS ) cargo;
if( hb_atomic_dec( &pI18N->iUsers ) )
{
if( pI18N->table )
hb_itemRelease( pI18N->table );
if( pI18N->context_table )
hb_itemRelease( pI18N->context_table );
if( pI18N->default_context )
hb_itemRelease( pI18N->default_context );
if( pI18N->base_plural_block )
hb_itemRelease( pI18N->base_plural_block );
if( pI18N->plural_block )
hb_itemRelease( pI18N->plural_block );
hb_xfree( pI18N );
}
}
}
static PHB_I18N_TRANS hb_i18n_initialize( PHB_ITEM pTable )
{
PHB_I18N_TRANS pI18N = NULL;
if( HB_IS_HASH( pTable ) )
{
PHB_ITEM pKey, pContext, pDefContext = NULL, pValue;
pKey = hb_itemPutCConst( NULL, "CONTEXT" );
pContext = hb_hashGetItemPtr( pTable, pKey, 0 );
if( pContext )
{
pKey = hb_itemPutC( pKey, NULL );
pDefContext = hb_hashGetItemPtr( pContext, pKey, 0 );
}
if( pContext && pDefContext )
{
pI18N = ( PHB_I18N_TRANS ) memset( hb_xgrab( sizeof( HB_I18N_TRANS ) ),
0, sizeof( HB_I18N_TRANS ) );
hb_atomic_set( &pI18N->iUsers, 1 );
pI18N->table = pTable;
pI18N->context_table = hb_itemNew( pContext );
pI18N->default_context = hb_itemNew( pDefContext );
pKey = hb_itemPutCConst( pKey, "BASE_CODEPAGE" );
pValue = hb_hashGetItemPtr( pTable, pKey, 0 );
if( pValue )
pI18N->base_cdpage = hb_cdpFind( hb_itemGetCPtr( pValue ) );
pKey = hb_itemPutCConst( pKey, "CODEPAGE" );
pValue = hb_hashGetItemPtr( pTable, pKey, 0 );
if( pValue )
pI18N->cdpage = hb_cdpFind( hb_itemGetCPtr( pValue ) );
pKey = hb_itemPutCConst( pKey, "BASE_LANG" );
pValue = hb_hashGetItemPtr( pTable, pKey, 0 );
if( pValue )
pI18N->base_plural_form = hb_i18n_pluralformfind( hb_itemGetCPtr( pValue ) );
pKey = hb_itemPutCConst( pKey, "LANG" );
pValue = hb_hashGetItemPtr( pTable, pKey, 0 );
if( pValue )
pI18N->plural_form = hb_i18n_pluralformfind( hb_itemGetCPtr( pValue ) );
pKey = hb_itemPutCConst( pKey, "BASE_PLURAL_EXP" );
pValue = hb_hashGetItemPtr( pTable, pKey, 0 );
if( pValue )
pI18N->base_plural_block = hb_i18n_pluralexp_compile( pValue );
pKey = hb_itemPutCConst( pKey, "PLURAL_EXP" );
pValue = hb_hashGetItemPtr( pTable, pKey, 0 );
if( pValue )
pI18N->plural_block = hb_i18n_pluralexp_compile( pValue );
}
hb_itemRelease( pKey );
}
return pI18N;
}
static PHB_ITEM hb_i18n_serialize( PHB_I18N_TRANS pI18N )
{
if( pI18N )
{
ULONG ulSize, ulCRC;
char * pBuffer = hb_itemSerialize( pI18N->table, FALSE, &ulSize );
char * pI18Nbuffer;
PHB_ITEM pKey, pValue;
ulCRC = hb_crc32( 0, pBuffer, ulSize );
pI18Nbuffer = ( char * ) memset( hb_xgrab( ulSize + HB_I18N_HEADER_SIZE + 1 ),
0, HB_I18N_HEADER_SIZE );
memcpy( pI18Nbuffer + HB_I18N_HEADER_SIZE, pBuffer, ulSize );
hb_xfree( pBuffer );
memcpy( pI18Nbuffer, s_signature, HB_I18N_SIG_SIZE );
HB_PUT_LE_UINT32( &pI18Nbuffer[ HB_I18N_SIZE_OFFSET ], ulSize );
HB_PUT_LE_UINT32( &pI18Nbuffer[ HB_I18N_CRC_OFFSET ], ulCRC );
pKey = hb_itemPutCConst( NULL, "DESCRIPTION" );
pValue = hb_hashGetItemPtr( pI18N->table, pKey, 0 );
if( pValue )
hb_strncpy( &pI18Nbuffer[ HB_I18N_TXT_OFFSET ],
hb_itemGetCPtr( pValue ), HB_I18N_TXT_SIZE );
return hb_itemPutCLPtr( pKey, pI18Nbuffer, ulSize + HB_I18N_HEADER_SIZE );
}
return NULL;
}
static BOOL hb_i18n_headercheck( const char * pBuffer, ULONG ulLen )
{
if( ulLen < HB_I18N_HEADER_SIZE )
return FALSE;
ulLen -= HB_I18N_HEADER_SIZE;
return memcmp( pBuffer, s_signature, HB_I18N_SIG_SIZE ) == 0 &&
( ulLen == 0 ||
( HB_GET_LE_UINT32( &pBuffer[ HB_I18N_SIZE_OFFSET ] ) == ulLen &&
HB_GET_LE_UINT32( &pBuffer[ HB_I18N_CRC_OFFSET ] ) ==
hb_crc32( 0, pBuffer + HB_I18N_HEADER_SIZE, ulLen ) ) );
}
static PHB_I18N_TRANS hb_i18n_deserialize( PHB_ITEM pItem )
{
PHB_I18N_TRANS pI18N = NULL;
if( pItem && HB_IS_STRING( pItem ) )
{
ULONG ulLen = hb_itemGetCLen( pItem );
const char * pBuffer = hb_itemGetCPtr( pItem );
if( ulLen > HB_I18N_HEADER_SIZE && hb_i18n_headercheck( pBuffer, ulLen ) )
{
PHB_ITEM pTable;
pBuffer += HB_I18N_HEADER_SIZE;
ulLen -= HB_I18N_HEADER_SIZE;
pTable = hb_itemDeserialize( &pBuffer, &ulLen );
if( pTable )
{
pI18N = hb_i18n_initialize( pTable );
if( !pI18N )
hb_itemRelease( pTable );
}
}
}
return pI18N;
}
static HB_GARBAGE_FUNC( hb_i18n_destructor )
{
PHB_I18N_TRANS * pI18NHolder = ( PHB_I18N_TRANS * ) Cargo;
if( *pI18NHolder )
{
hb_i18n_release( ( void * ) *pI18NHolder );
*pI18NHolder = NULL;
}
}
static PHB_I18N_TRANS hb_i18n_param( int * piParam, BOOL fActive )
{
PHB_I18N_TRANS * pI18NHolder = ( PHB_I18N_TRANS * ) hb_parptrGC( hb_i18n_destructor, *piParam );
if( pI18NHolder )
{
( *piParam )++;
return *pI18NHolder;
}
return fActive ? hb_i18n_table() : NULL;
}
static PHB_ITEM hb_i18n_newitem( PHB_I18N_TRANS pI18N )
{
PHB_I18N_TRANS * pI18NHolder;
PHB_ITEM pItem = hb_itemNew( NULL );
if( !pI18N )
pI18N = hb_i18n_new();
pI18NHolder = ( PHB_I18N_TRANS * )
hb_gcAlloc( sizeof( PHB_I18N_TRANS ), hb_i18n_destructor );
*pI18NHolder = pI18N;
return hb_itemPutPtrGC( pItem, pI18NHolder );
}
static BOOL hb_i18n_getpluralform( PHB_I18N_TRANS pI18N, PHB_ITEM pOldForm,
BOOL fBase )
{
BOOL fResult = FALSE;
if( pI18N )
{
if( pOldForm )
{
PHB_ITEM pBlock;
int iForm;
if( fBase )
{
pBlock = pI18N->base_plural_block;
iForm = pI18N->base_plural_form;
}
else
{
pBlock = pI18N->plural_block;
iForm = pI18N->plural_form;
}
if( pBlock )
hb_itemCopy( pOldForm, pBlock );
else if( iForm )
hb_itemPutC( pOldForm, hb_i18n_pluralformid( iForm ) );
else
hb_itemPutCConst( pOldForm, "EN" ); /* default is ENGLISH */
}
fResult = TRUE;
}
return fResult;
}
static BOOL hb_i18n_setpluralform( PHB_I18N_TRANS pI18N, PHB_ITEM pForm,
BOOL fBase )
{
BOOL fResult = FALSE;
if( pI18N && pForm )
{
if( HB_IS_BLOCK( pForm ) )
{
if( fBase )
{
if( pI18N->base_plural_block )
hb_itemCopy( pI18N->base_plural_block, pForm );
else
pI18N->base_plural_block = hb_itemNew( pForm );
}
else
{
if( pI18N->plural_block )
hb_itemCopy( pI18N->plural_block, pForm );
else
pI18N->plural_block = hb_itemNew( pForm );
}
fResult = TRUE;
}
else if( HB_IS_STRING( pForm ) )
{
int iForm = hb_i18n_pluralformfind( hb_itemGetCPtr( pForm ) );
if( iForm )
{
const char * szKey;
if( fBase )
{
if( pI18N->base_plural_block )
{
hb_itemRelease( pI18N->base_plural_block );
pI18N->base_plural_block = NULL;
}
pI18N->base_plural_form = iForm;
szKey = "BASE_LANG";
}
else
{
if( pI18N->plural_block )
{
hb_itemRelease( pI18N->plural_block );
pI18N->plural_block = NULL;
}
pI18N->plural_form = iForm;
szKey = "LANG";
}
hb_i18n_setitem( pI18N->table, szKey, hb_i18n_pluralformid( iForm ) );
fResult = TRUE;
}
}
}
return fResult;
}
static const char * hb_i18n_setcodepage( PHB_I18N_TRANS pI18N,
const char * szCdpID,
BOOL fBase, BOOL fTranslate )
{
const char * szOldCdpID = NULL, * szKey;
if( pI18N )
{
PHB_CODEPAGE cdp = szCdpID ? hb_cdpFind( szCdpID ) : NULL, cdpage;
cdpage = fBase ? pI18N->base_cdpage : pI18N->cdpage;
if( cdpage )
szOldCdpID = cdpage->id;
if( cdp && cdp != cdpage )
{
if( fTranslate && cdpage )
{
ULONG ulLen = hb_hashLen( pI18N->context_table ), ul;
for( ul = 1; ul <= ulLen; ++ul )
{
PHB_ITEM pContext = hb_hashGetValueAt( pI18N->context_table, ul );
ULONG ulCount = hb_hashLen( pContext ), ulLen, u;
char * szValue;
for( u = 1; u <= ulCount; ++u )
{
if( fBase )
{
if( hb_itemGetWriteCL( hb_hashGetKeyAt( pContext, u ),
&szValue, &ulLen ) )
{
hb_cdpnTranslate( szValue, cdpage, cdp, ulLen );
}
}
else
{
PHB_ITEM pResult = hb_hashGetValueAt( pContext, u );
if( HB_IS_STRING( pResult ) )
{
if( hb_itemGetWriteCL( pResult, &szValue, &ulLen ) )
hb_cdpnTranslate( szValue, cdpage, cdp, ulLen );
}
else if( HB_IS_ARRAY( pResult ) )
{
ULONG ulTrans = hb_arrayLen( pResult ), u2;
for( u2 = 1; u2 <= ulTrans; ++u2 )
{
if( hb_itemGetWriteCL( hb_arrayGetItemPtr( pResult, u2 ),
&szValue, &ulLen ) )
hb_cdpnTranslate( szValue, cdpage, cdp, ulLen );
}
}
}
}
if( fBase )
{
if( hb_itemGetWriteCL( hb_hashGetKeyAt( pI18N->context_table, u ),
&szValue, &ulLen ) )
{
hb_cdpnTranslate( szValue, cdpage, cdp, ulLen );
}
hb_hashSetFlags( pContext, HB_HASH_RESORT );
}
}
if( fBase )
hb_hashSetFlags( pI18N->context_table, HB_HASH_RESORT );
}
if( fBase )
{
pI18N->base_cdpage = cdp;
szKey = "BASE_CODEPAGE";
}
else
{
pI18N->cdpage = cdp;
szKey = "CODEPAGE";
}
hb_i18n_setitem( pI18N->table, szKey, szCdpID );
}
}
return szOldCdpID;
}
static const char * hb_i18n_description( PHB_I18N_TRANS pI18N, PHB_ITEM pItem )
{
if( pI18N )
{
PHB_ITEM pKey = hb_itemPutCConst( NULL, "DESCRIPTION" ), pValue;
pValue = hb_hashGetItemPtr( pI18N->table, pKey, 0 );
if( pItem )
{
if( HB_IS_STRING( pItem ) )
{
if( pValue )
hb_itemCopy( pValue, pItem );
else
{
hb_hashAdd( pI18N->table, pKey, pItem );
pValue = hb_hashGetItemPtr( pI18N->table, pKey, 0 );
}
}
}
hb_itemRelease( pKey );
return hb_itemGetCPtr( pValue );
}
return NULL;
}
static void hb_i18n_addtext( PHB_I18N_TRANS pI18N, PHB_ITEM pMsgID,
PHB_ITEM pTrans, PHB_ITEM pContext )
{
PHB_ITEM pTable = pContext ? hb_hashGetItemPtr( pI18N->context_table,
pContext, 0 ) : pI18N->default_context;
if( !pTable )
{
pTable = hb_hashNew( hb_itemNew( NULL ) );
hb_hashAdd( pTable, pMsgID, pTrans );
hb_hashAdd( pI18N->context_table, pContext, pTable );
hb_itemRelease( pTable );
}
else
hb_hashAdd( pTable, pMsgID, pTrans );
}
PHB_ITEM hb_i18n_gettext( PHB_ITEM pMsgID, PHB_ITEM pContext )
{
PHB_I18N_TRANS pI18N = hb_i18n_table();
PHB_CODEPAGE cdpage = NULL;
if( pI18N )
{
PHB_ITEM pTable = pContext && pI18N->context_table ?
hb_hashGetItemPtr( pI18N->context_table, pContext, 0 ) :
pI18N->default_context;
cdpage = pI18N->base_cdpage;
if( pTable )
{
pTable = hb_hashGetItemPtr( pTable, pMsgID, 0 );
if( pTable )
{
if( HB_IS_ARRAY( pTable ) )
pTable = hb_arrayGetItemPtr( pTable, 1 );
if( pTable && HB_IS_STRING( pTable ) )
{
pMsgID = pTable;
cdpage = pI18N->cdpage;
}
}
}
}
if( pMsgID )
{
if( HB_IS_STRING( pMsgID ) )
{
if( cdpage )
{
PHB_CODEPAGE cdp = hb_vmCDP();
if( cdp && cdp != cdpage )
{
char * szValue;
ULONG ulLen;
if( hb_itemGetWriteCL( pMsgID, &szValue, &ulLen ) )
{
hb_cdpnTranslate( szValue, cdpage, cdp, ulLen );
}
}
}
}
else
pMsgID = NULL;
}
return pMsgID;
}
PHB_ITEM hb_i18n_ngettext( PHB_ITEM pNum, PHB_ITEM pMsgID, PHB_ITEM pContext )
{
PHB_I18N_TRANS pI18N = hb_i18n_table();
PHB_CODEPAGE cdpage = NULL;
PHB_ITEM pBlock = NULL;
int iPluralForm = 0;
if( pI18N )
{
PHB_ITEM pTable = pContext && pI18N->context_table ?
hb_hashGetItemPtr( pI18N->context_table, pContext, 0 ) :
pI18N->default_context;
cdpage = pI18N->base_cdpage;
pBlock = pI18N->base_plural_block;
iPluralForm = pI18N->base_plural_form;
if( pTable )
{
PHB_ITEM pMsg = HB_IS_ARRAY( pMsgID ) ?
hb_arrayGetItemPtr( pMsgID, 1 ) : pMsgID;
pTable = pMsg && HB_IS_STRING( pMsg ) ?
hb_hashGetItemPtr( pTable, pMsg, 0 ) : NULL;
if( pTable )
{
if( HB_IS_STRING( pTable ) ||
( HB_IS_ARRAY( pTable ) &&
( hb_arrayGetType( pTable, 1 ) & HB_IT_STRING ) != 0 ) )
{
pMsgID = pTable;
cdpage = pI18N->cdpage;
pBlock = pI18N->plural_block;
iPluralForm = pI18N->plural_form;
}
}
}
}
if( HB_IS_ARRAY( pMsgID ) )
{
long lIndex;
if( !pNum )
lIndex = 1;
else if( pBlock )
{
hb_evalBlock1( pBlock, pNum );
lIndex = hb_parnl( -1 );
}
else
lIndex = hb_i18n_pluralindex( iPluralForm, pNum );
if( lIndex < 1 || ( lIndex != 1 &&
( hb_arrayGetType( pMsgID, lIndex ) & HB_IT_STRING ) == 0 ) )
lIndex = 1;
pMsgID = hb_arrayGetItemPtr( pMsgID, lIndex );
}
if( pMsgID )
{
if( HB_IS_STRING( pMsgID ) )
{
if( cdpage )
{
PHB_CODEPAGE cdp = hb_vmCDP();
if( cdp && cdp != cdpage )
{
char * szValue;
ULONG ulLen;
if( hb_itemGetWriteCL( pMsgID, &szValue, &ulLen ) )
{
hb_cdpnTranslate( szValue, cdpage, cdp, ulLen );
}
}
}
}
else
pMsgID = NULL;
}
return pMsgID;
}
/*
* base .prg i18n functions
*/
HB_FUNC( HB_I18N_GETTEXT )
{
PHB_ITEM pMsgID = hb_param( 1, HB_IT_STRING );
PHB_ITEM pContext = hb_param( 2, HB_IT_STRING );
if( pMsgID )
pMsgID = hb_i18n_gettext( pMsgID, pContext );
if( pMsgID && HB_IS_STRING( pMsgID ) )
hb_itemReturn( pMsgID );
else
hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
}
HB_FUNC( HB_I18N_NGETTEXT )
{
PHB_ITEM pNum = hb_param( 1, HB_IT_NUMERIC );
PHB_ITEM pMsgID = hb_param( 2, HB_IT_STRING | HB_IT_ARRAY );
PHB_ITEM pContext = hb_param( 3, HB_IT_STRING );
if( !pNum )
pMsgID = NULL;
else if( pMsgID )
pMsgID = hb_i18n_ngettext( pNum, pMsgID, pContext );
if( pMsgID && HB_IS_STRING( pMsgID ) )
hb_itemReturn( pMsgID );
else
hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
}
HB_FUNC( HB_I18N_GETTEXT_STRICT )
{
HB_FUNC_EXEC( HB_I18N_GETTEXT );
}
HB_FUNC( HB_I18N_NGETTEXT_STRICT )
{
HB_FUNC_EXEC( HB_I18N_NGETTEXT );
}
/*
* extended .prg i18n functions to create and manage translation tables
*/
HB_FUNC( HB_I18N_CREATE )
{
hb_itemReturnRelease( hb_i18n_newitem( NULL ) );
}
HB_FUNC( HB_I18N_CODEPAGE )
{
PHB_I18N_TRANS pI18N;
int iParam = 1;
pI18N = hb_i18n_param( &iParam, TRUE );
if( pI18N )
hb_retc( hb_i18n_setcodepage( pI18N, hb_parc( iParam ),
HB_ISLOG( iParam + 1 ) && hb_parl( iParam + 1 ),
HB_ISLOG( iParam + 2 ) && hb_parl( iParam + 2 ) ) );
else
hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
}
HB_FUNC( HB_I18N_PLURALFORM )
{
PHB_I18N_TRANS pI18N;
int iParam = 1;
pI18N = hb_i18n_param( &iParam, TRUE );
if( pI18N )
{
PHB_ITEM pOldForm = hb_itemNew( NULL );
PHB_ITEM pForm = hb_param( iParam, HB_IT_STRING | HB_IT_BLOCK );
BOOL fBase = HB_ISLOG( iParam + 1 ) && hb_parl( iParam + 1 );
if( hb_i18n_getpluralform( pI18N, pOldForm, fBase ) )
hb_itemReturn( pOldForm );
hb_itemRelease( pOldForm );
if( pForm )
hb_i18n_setpluralform( pI18N, pForm, fBase );
}
else
hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
}
HB_FUNC( HB_I18N_DESCRIPTION )
{
PHB_I18N_TRANS pI18N;
int iParam = 1;
pI18N = hb_i18n_param( &iParam, TRUE );
if( pI18N )
{
PHB_ITEM pNewDescript = hb_param( iParam, HB_IT_STRING );
hb_retc( hb_i18n_description( pI18N, NULL ) );
if( pNewDescript )
hb_i18n_description( pI18N, pNewDescript );
}
else
hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
}
HB_FUNC( HB_I18N_ADDTEXT )
{
PHB_I18N_TRANS pI18N;
int iParam = 1;
pI18N = hb_i18n_param( &iParam, FALSE );
if( pI18N )
{
PHB_ITEM pMsgID = hb_param( iParam, HB_IT_STRING );
PHB_ITEM pTrans = hb_param( iParam + 1, HB_IT_STRING | HB_IT_ARRAY );
PHB_ITEM pContext = hb_param( iParam + 2, HB_IT_STRING );
if( pMsgID && pTrans )
{
if( HB_IS_ARRAY( pTrans ) )
{
ULONG ulLen = hb_arrayLen( pTrans ), ul;
if( ulLen != 0 )
{
for( ul = 1; ul <= ulLen; ++ul )
{
if( !HB_IS_STRING( hb_arrayGetItemPtr( pTrans, ul ) ) )
{
pTrans = NULL;
break;
}
}
}
else
pTrans = NULL;
}
if( pTrans )
{
hb_i18n_addtext( pI18N, pMsgID, pTrans, pContext );
return;
}
}
}
hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
}
HB_FUNC( HB_I18N_SET )
{
if( hb_pcount() > 0 )
{
if( HB_ISNIL( 1 ) )
hb_vmSetI18N( NULL );
else
{
int iParam = 1;
PHB_I18N_TRANS pI18N = hb_i18n_param( &iParam, FALSE );
if( pI18N )
hb_vmSetI18N( hb_i18n_alloc( pI18N ) );
else
{
hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
return;
}
}
}
hb_retl( hb_i18n_table() != NULL );
}
HB_FUNC( HB_I18N_SAVETABLE )
{
PHB_I18N_TRANS pI18N;
int iParam = 1;
pI18N = hb_i18n_param( &iParam, TRUE );
if( pI18N )
hb_itemReturnRelease( hb_i18n_serialize( pI18N ) );
}
HB_FUNC( HB_I18N_RESTORETABLE )
{
PHB_ITEM pItem = hb_param( 1, HB_IT_STRING );
if( pItem )
{
PHB_I18N_TRANS pI18N = hb_i18n_deserialize( pItem );
if( pI18N )
hb_itemReturnRelease( hb_i18n_newitem( pI18N ) );
}
}
HB_FUNC( HB_I18N_HEADERSIZE )
{
hb_retni( HB_I18N_HEADER_SIZE );
}
HB_FUNC( HB_I18N_CHECK )
{
hb_retl( hb_i18n_headercheck( hb_parc( 1 ), hb_parclen( 1 ) ) );
}
/* unoffical function to access ineternal hash table used by i18n set */
HB_FUNC( __I18N_HASHTABLE )
{
PHB_I18N_TRANS pI18N;
PHB_ITEM pTable = hb_param( 1, HB_IT_HASH );
if( pTable )
{
pI18N = hb_i18n_initialize( hb_itemNew( pTable ) );
if( pI18N )
hb_itemReturnRelease( hb_i18n_newitem( pI18N ) );
else
hb_itemRelease( pTable );
}
else
{
int iParam = 1;
pI18N = hb_i18n_param( &iParam, TRUE );
if( pI18N )
hb_itemReturn( pI18N->table );
}
}