2008-03-05 19:10 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/contrib/hbct/screen2.c
! fixed possible vary bad bug (memory buffer overflow) in SCREENSTR()
* harbour/source/rtl/hbffind.c
! fixed possible GPF in some *nixes
* harbour/source/vm/classes.c
! do not execute the same destructor inherited from different parent
classes more then once
* harbour/source/rtl/transfrm.c
! fixed bug with '9' used as stop condition of function pattern
this character cannot be stripped, f.e.:
? transform( "abc", "@_99*" )
! fixed bug with '*' or '$' used with @), f.e.:
? transform( -12345, "@) $999999" )
! fixed replacing '.' with ',' when @E is used without picture part, f.e.:
? transform( 123.45, "@E" )
! fixed ',' conversions
? transform( 12.34,"@E ab,cd.ef9,9.99,.--" )
! fixed bug with picture starting with ".", f.e.:
? transform( 0.3456, ".999" )
! fixed "@(" and "@)" conversions, f.e.:
? transform( -12345, "@) 1999*999" )
! fixed late oveflow detection in "@(" and "@)", f.e.:
? transtest( -12345, "@( 6798^999" )
! fixed "@E" conversion for dates to keep user delimiters set in
_SET_DATEFORMAT, f.e.:
set( _SET_DATEFORMAT, "mm:dd:yyyy" ); ? transform( date(), "@E" )
set( _SET_DATEFORMAT, "yyyy<mm>dd" ); ? transform( date(), "@E" )
Please note that Harbour is not strictly Clipper compatible here
because it respects _SET_DATEFORMAT set by user.
! fixed 64bit integer conversion by eliminating conversion to
'double' f.e.:
? transform( 1234567890123456789, "99999999999999999999" )
? transform( -1234567890123456789, "99999999999999999999" )
! some other fixes, see regression test transtst.prg
% speed improvement in numeric conversions
+ harbour/tests/transtst.prg
+ added regression test for transform function
* harbour/utils/hbtest/rt_trans.prg
* disabled transform() tests for "@E" and result smaller then 5 bytes
CA-Cl*pper do not check result size and always exchanges
bytes 1-2 with bytes 4-5 for @E conversion. It's buffer overflow
bug and I do not want to replicate it inside our transform
implementation. It also causes that the results for for strings
smaller then 5 bytes behaves randomly.
In fact precise tests can show that it's not random behavior
but CA-Cl*pper uses static buffer for result and when current one
is smaller then 5 bytes then first two bytes are replaced with
4-5 bytes from previous result which was length enough, f.e.:
? transform( "0123456789", "" )
? transform( "AB", "@E" )
? transform( "ab", "@E" )
Replicating exact CA-Cl*pper behavior it's trivial (it will be enough
to use static buffer two and not check the size of current result) but
IMHO it's bug.
* harbour/source/rtl/round.c
* added strictly Clipper compatible code covered by HB_C52_STRICT
and comment about possible difference in Harbour.
* harbour/include/hbgtinfo.ch
* harbour/source/rtl/hbgtcore.c
* harbour/source/rtl/gtxwc/gtxwc.c
* harbour/source/rtl/gtsln/gtsln.c
* harbour/source/rtl/gttrm/gttrm.c
* harbour/source/rtl/gtwvt/gtwvt.c
+ added HB_GTI_ISUNICODE - it returns logical value with information
about Unicode mode in active GT driver - it's necessary for proper
CP initialization in some GTDs which can work in both mode depending
on client side settings
* harbour/source/rtl/gttrm/gttrm.c
* improved UTF-8 detection
* added automatic PuTTY detection
* improved PuTTY and some xterm key handling
* added some missing RXVT keys
This commit is contained in:
@@ -8,6 +8,88 @@
|
||||
2002-12-01 13:30 UTC+0100 Foo Bar <foo.bar@foobar.org>
|
||||
*/
|
||||
|
||||
2008-03-05 19:10 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
|
||||
* harbour/contrib/hbct/screen2.c
|
||||
! fixed possible vary bad bug (memory buffer overflow) in SCREENSTR()
|
||||
|
||||
* harbour/source/rtl/hbffind.c
|
||||
! fixed possible GPF in some *nixes
|
||||
|
||||
* harbour/source/vm/classes.c
|
||||
! do not execute the same destructor inherited from different parent
|
||||
classes more then once
|
||||
|
||||
* harbour/source/rtl/transfrm.c
|
||||
! fixed bug with '9' used as stop condition of function pattern
|
||||
this character cannot be stripped, f.e.:
|
||||
? transform( "abc", "@_99*" )
|
||||
! fixed bug with '*' or '$' used with @), f.e.:
|
||||
? transform( -12345, "@) $999999" )
|
||||
! fixed replacing '.' with ',' when @E is used without picture part, f.e.:
|
||||
? transform( 123.45, "@E" )
|
||||
! fixed ',' conversions
|
||||
? transform( 12.34,"@E ab,cd.ef9,9.99,.--" )
|
||||
! fixed bug with picture starting with ".", f.e.:
|
||||
? transform( 0.3456, ".999" )
|
||||
! fixed "@(" and "@)" conversions, f.e.:
|
||||
? transform( -12345, "@) 1999*999" )
|
||||
! fixed late oveflow detection in "@(" and "@)", f.e.:
|
||||
? transtest( -12345, "@( 6798^999" )
|
||||
! fixed "@E" conversion for dates to keep user delimiters set in
|
||||
_SET_DATEFORMAT, f.e.:
|
||||
set( _SET_DATEFORMAT, "mm:dd:yyyy" ); ? transform( date(), "@E" )
|
||||
set( _SET_DATEFORMAT, "yyyy<mm>dd" ); ? transform( date(), "@E" )
|
||||
Please note that Harbour is not strictly Clipper compatible here
|
||||
because it respects _SET_DATEFORMAT set by user.
|
||||
! fixed 64bit integer conversion by eliminating conversion to
|
||||
'double' f.e.:
|
||||
? transform( 1234567890123456789, "99999999999999999999" )
|
||||
? transform( -1234567890123456789, "99999999999999999999" )
|
||||
! some other fixes, see regression test transtst.prg
|
||||
% speed improvement in numeric conversions
|
||||
|
||||
+ harbour/tests/transtst.prg
|
||||
+ added regression test for transform function
|
||||
|
||||
* harbour/utils/hbtest/rt_trans.prg
|
||||
* disabled transform() tests for "@E" and result smaller then 5 bytes
|
||||
CA-Cl*pper do not check result size and always exchanges
|
||||
bytes 1-2 with bytes 4-5 for @E conversion. It's buffer overflow
|
||||
bug and I do not want to replicate it inside our transform
|
||||
implementation. It also causes that the results for for strings
|
||||
smaller then 5 bytes behaves randomly.
|
||||
In fact precise tests can show that it's not random behavior
|
||||
but CA-Cl*pper uses static buffer for result and when current one
|
||||
is smaller then 5 bytes then first two bytes are replaced with
|
||||
4-5 bytes from previous result which was length enough, f.e.:
|
||||
? transform( "0123456789", "" )
|
||||
? transform( "AB", "@E" )
|
||||
? transform( "ab", "@E" )
|
||||
Replicating exact CA-Cl*pper behavior it's trivial (it will be enough
|
||||
to use static buffer two and not check the size of current result) but
|
||||
IMHO it's bug.
|
||||
|
||||
* harbour/source/rtl/round.c
|
||||
* added strictly Clipper compatible code covered by HB_C52_STRICT
|
||||
and comment about possible difference in Harbour.
|
||||
|
||||
* harbour/include/hbgtinfo.ch
|
||||
* harbour/source/rtl/hbgtcore.c
|
||||
* harbour/source/rtl/gtxwc/gtxwc.c
|
||||
* harbour/source/rtl/gtsln/gtsln.c
|
||||
* harbour/source/rtl/gttrm/gttrm.c
|
||||
* harbour/source/rtl/gtwvt/gtwvt.c
|
||||
+ added HB_GTI_ISUNICODE - it returns logical value with information
|
||||
about Unicode mode in active GT driver - it's necessary for proper
|
||||
CP initialization in some GTDs which can work in both mode depending
|
||||
on client side settings
|
||||
|
||||
* harbour/source/rtl/gttrm/gttrm.c
|
||||
* improved UTF-8 detection
|
||||
* added automatic PuTTY detection
|
||||
* improved PuTTY and some xterm key handling
|
||||
* added some missing RXVT keys
|
||||
|
||||
2008-02-25 00:08 UTC-0600 Teo Fonrouge (teo/at/windtelsoft/dot/com)
|
||||
* make_vc.mak
|
||||
! Fixed small typo
|
||||
|
||||
@@ -344,9 +344,9 @@ HB_FUNC( SCREENSTR )
|
||||
*szText++ = ( char ) usChar;
|
||||
*szText++ = ( char ) bColor;
|
||||
}
|
||||
while( ++sC <= sMaxCol && --ulCount );
|
||||
while( --ulCount && ++sC <= sMaxCol );
|
||||
}
|
||||
while( ++sRow <= sMaxRow && ulCount );
|
||||
while( ulCount && ++sRow <= sMaxRow );
|
||||
|
||||
hb_retclen_buffer( pBuffer, ulSize );
|
||||
}
|
||||
|
||||
@@ -116,6 +116,8 @@
|
||||
#define HB_GTI_ADDKEYMAP 45 /* add key escape sequences */
|
||||
#define HB_GTI_DELKEYMAP 46 /* del key escape sequences */
|
||||
|
||||
#define HB_GTI_ISUNICODE 47 /* is Unicode input/output enabled? */
|
||||
|
||||
/* Font weights */
|
||||
#define HB_GTI_FONTW_THIN 1
|
||||
#define HB_GTI_FONTW_NORMAL 2
|
||||
@@ -192,6 +194,7 @@
|
||||
#define GTI_NEWWIN HB_GTI_NEWWIN
|
||||
#define GTI_ADDKEYMAP HB_GTI_ADDKEYMAP
|
||||
#define GTI_DELKEYMAP HB_GTI_DELKEYMAP
|
||||
#define GTI_ISUNICODE HB_GTI_ISUNICODE
|
||||
|
||||
/* Font weights */
|
||||
#define GTI_FONTW_THIN HB_GTI_FONTW_THIN
|
||||
|
||||
@@ -906,6 +906,10 @@ static BOOL hb_gt_sln_Info( PHB_GT pGT, int iType, PHB_GT_INFO pInfo )
|
||||
pInfo->pResult = hb_itemPutL( pInfo->pResult, TRUE );
|
||||
break;
|
||||
|
||||
case HB_GTI_ISUNICODE:
|
||||
pInfo->pResult = hb_itemPutL( pInfo->pResult, hb_sln_Is_Unicode );
|
||||
break;
|
||||
|
||||
case HB_GTI_ESCDELAY:
|
||||
pInfo->pResult = hb_itemPutNI( pInfo->pResult, hb_sln_escDelay );
|
||||
if( hb_itemType( pInfo->pNewVal ) & HB_IT_NUMERIC )
|
||||
|
||||
@@ -119,6 +119,7 @@ static HB_GT_FUNCS SuperTable;
|
||||
#define TERM_ANSI 1
|
||||
#define TERM_LINUX 2
|
||||
#define TERM_XTERM 3
|
||||
#define TERM_PUTTY 4
|
||||
|
||||
#define NO_STDKEYS 96
|
||||
#define NO_EXTDKEYS 30
|
||||
@@ -336,6 +337,7 @@ typedef struct _HB_GTTRM
|
||||
BYTE * pOutBuf;
|
||||
|
||||
int terminal_type;
|
||||
int terminal_ext;
|
||||
|
||||
#if defined( OS_UNIX_COMPATIBLE )
|
||||
struct termios saved_TIO, curr_TIO;
|
||||
@@ -374,7 +376,7 @@ typedef struct _HB_GTTRM
|
||||
void (* Init) ( HB_GTTRM_PTR );
|
||||
void (* Exit) ( HB_GTTRM_PTR );
|
||||
void (* SetTermMode) ( HB_GTTRM_PTR, int );
|
||||
BOOL (* GetCursorPos) ( HB_GTTRM_PTR, int *, int * );
|
||||
BOOL (* GetCursorPos) ( HB_GTTRM_PTR, int *, int *, const char * );
|
||||
void (* SetCursorPos) ( HB_GTTRM_PTR, int , int );
|
||||
void (* SetCursorStyle) ( HB_GTTRM_PTR, int );
|
||||
void (* SetAttributes) ( HB_GTTRM_PTR, int );
|
||||
@@ -1717,9 +1719,10 @@ static void hb_gt_trm_AnsiSetTermMode( PHB_GTTRM pTerm, int iAM )
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL hb_gt_trm_AnsiGetCursorPos( PHB_GTTRM pTerm, int * iRow, int * iCol )
|
||||
static BOOL hb_gt_trm_AnsiGetCursorPos( PHB_GTTRM pTerm, int * iRow, int * iCol,
|
||||
const char * szPost )
|
||||
{
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_gt_trm_AnsiGetCursorPos(%p,%p,%p)", pTerm, iRow, iCol));
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_gt_trm_AnsiGetCursorPos(%p,%p,%p,%p)", pTerm, iRow, iCol, szPost));
|
||||
|
||||
if( pTerm->fPosAnswer )
|
||||
{
|
||||
@@ -1727,6 +1730,8 @@ static BOOL hb_gt_trm_AnsiGetCursorPos( PHB_GTTRM pTerm, int * iRow, int * iCol
|
||||
int i, n, y, x;
|
||||
|
||||
hb_gt_trm_termOut( pTerm, ( BYTE * ) "\x1B[6n", 4 );
|
||||
if( szPost )
|
||||
hb_gt_trm_termOut( pTerm, ( BYTE * ) szPost, strlen( szPost ) );
|
||||
hb_gt_trm_termFlush( pTerm );
|
||||
|
||||
*iRow = *iCol = -1;
|
||||
@@ -1751,7 +1756,15 @@ static BOOL hb_gt_trm_AnsiGetCursorPos( PHB_GTTRM pTerm, int * iRow, int * iCol
|
||||
if( n == 0 )
|
||||
{
|
||||
while( i > 0 && rdbuf[0] != '\033' )
|
||||
memmove( rdbuf, rdbuf + 1, i-- );
|
||||
{
|
||||
if( szPost && i >= 5 && hb_strnicmp( rdbuf, "PuTTY", 5 ) == 0 )
|
||||
{
|
||||
pTerm->terminal_ext |= TERM_PUTTY;
|
||||
memmove( rdbuf, rdbuf + 5, i -= 5 );
|
||||
}
|
||||
else
|
||||
memmove( rdbuf, rdbuf + 1, i-- );
|
||||
}
|
||||
}
|
||||
n += i;
|
||||
if( n >= 6 )
|
||||
@@ -2042,11 +2055,8 @@ static BOOL hb_trm_isUTF8( PHB_GTTRM pTerm )
|
||||
int iRow = 0, iCol = 0;
|
||||
BOOL fSize;
|
||||
|
||||
hb_gt_trm_termOut( pTerm, ( BYTE * ) "\r\303\255", 3 );
|
||||
hb_gt_trm_termFlush( pTerm );
|
||||
fSize = pTerm->GetCursorPos( pTerm, &iRow, &iCol );
|
||||
hb_gt_trm_termOut( pTerm, ( BYTE * ) "\r \r", 4 );
|
||||
hb_gt_trm_termFlush( pTerm );
|
||||
hb_gt_trm_termOut( pTerm, ( BYTE * ) "\005\r\303\255", 4 );
|
||||
fSize = pTerm->GetCursorPos( pTerm, &iRow, &iCol, "\r \r" );
|
||||
pTerm->iCol = 0;
|
||||
if( fSize )
|
||||
return iCol == 1;
|
||||
@@ -2324,6 +2334,13 @@ static void init_keys( PHB_GTTRM pTerm )
|
||||
|
||||
{ 0, NULL } };
|
||||
|
||||
static const keySeq rxvtKeySeq[] = {
|
||||
|
||||
{ EXKEY_HOME, "\033[H" },
|
||||
{ EXKEY_END, "\033Ow" },
|
||||
|
||||
{ 0, NULL } };
|
||||
|
||||
static const keySeq xtermModKeySeq[] = {
|
||||
|
||||
{ EXKEY_F1 |KEY_CTRLMASK, "\033O5P" },
|
||||
@@ -2401,6 +2418,8 @@ static void init_keys( PHB_GTTRM pTerm )
|
||||
{ EXKEY_PGUP |KEY_CTRLMASK|KEY_ALTMASK, "\033[5;2~" },
|
||||
{ EXKEY_PGDN |KEY_CTRLMASK|KEY_ALTMASK, "\033[6;2~" },
|
||||
|
||||
{ EXKEY_BS |KEY_ALTMASK, "\033\010" },
|
||||
|
||||
{ 0, NULL } };
|
||||
|
||||
static const keySeq xtermFnKeySeq[] = {
|
||||
@@ -2459,6 +2478,8 @@ static void init_keys( PHB_GTTRM pTerm )
|
||||
/* Konsole */
|
||||
{ EXKEY_ENTER |KEY_CTRLMASK|KEY_ALTMASK, "\033OM" },
|
||||
|
||||
{ EXKEY_END, "\033Ow" }, /* rxvt */
|
||||
|
||||
/* gnome-terminal */
|
||||
{ EXKEY_END, "\033OF" }, /* kend */
|
||||
{ EXKEY_HOME, "\033OH" }, /* khome */
|
||||
@@ -2623,6 +2644,8 @@ static void init_keys( PHB_GTTRM pTerm )
|
||||
addKeyTab( pTerm, xtermFnKeySeq );
|
||||
addKeyTab( pTerm, xtermModKeySeq );
|
||||
addKeyTab( pTerm, puttyKeySeq );
|
||||
/* if( pTerm->terminal_ext & TERM_PUTTY ) for PuTTY */
|
||||
addKeyTab( pTerm, rxvtKeySeq );
|
||||
}
|
||||
else if( pTerm->terminal_type == TERM_ANSI )
|
||||
{
|
||||
@@ -2716,7 +2739,7 @@ static void hb_gt_trm_SetTerm( PHB_GTTRM pTerm )
|
||||
{
|
||||
static const char * szAcsc = "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~";
|
||||
static const char * szExtAcsc = "+\020,\021-\030.\0310\333`\004a\261f\370g\361h\260i\316j\331k\277l\332m\300n\305o~p\304q\304r\304s_t\303u\264v\301w\302x\263y\363z\362{\343|\330}\234~\376";
|
||||
char * szTerm;
|
||||
const char * szTerm;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_gt_trm_SetTerm(%p)", pTerm));
|
||||
|
||||
@@ -2756,7 +2779,8 @@ static void hb_gt_trm_SetTerm( PHB_GTTRM pTerm )
|
||||
pTerm->szAcsc = szExtAcsc;
|
||||
pTerm->terminal_type = TERM_LINUX;
|
||||
}
|
||||
else if( strstr( szTerm, "xterm" ) != NULL ||
|
||||
else if( ( pTerm->terminal_ext & TERM_PUTTY ) ||
|
||||
strstr( szTerm, "xterm" ) != NULL ||
|
||||
strncmp( szTerm, "rxvt", 4 ) == 0 ||
|
||||
strcmp( szTerm, "putty" ) == 0 ||
|
||||
strncmp( szTerm, "screen", 6 ) == 0 )
|
||||
@@ -2892,15 +2916,15 @@ static void hb_gt_trm_Init( PHB_GT pGT, FHANDLE hFilenoStdin, FHANDLE hFilenoStd
|
||||
HB_GTSELF_SETFLAG( pGT, HB_GTI_COMPATBUFFER, FALSE );
|
||||
HB_GTSELF_SETFLAG( pGT, HB_GTI_STDOUTCON, pTerm->fStdoutTTY );
|
||||
HB_GTSELF_SETFLAG( pGT, HB_GTI_STDERRCON, pTerm->fStderrTTY );
|
||||
HB_GTSELF_SETBLINK( pGT, TRUE );
|
||||
|
||||
pTerm->Init( pTerm );
|
||||
pTerm->SetTermMode( pTerm, 0 );
|
||||
if( pTerm->GetCursorPos( pTerm, &pTerm->iRow, &pTerm->iCol ) )
|
||||
if( pTerm->GetCursorPos( pTerm, &pTerm->iRow, &pTerm->iCol, NULL ) )
|
||||
HB_GTSELF_SETPOS( pGT, pTerm->iRow, pTerm->iCol );
|
||||
pTerm->fUTF8 = hb_trm_isUTF8( pTerm );
|
||||
hb_gt_trm_SetKeyTrans( pTerm, NULL, NULL );
|
||||
hb_gt_trm_SetDispTrans( pTerm, NULL, NULL, 0 );
|
||||
HB_GTSELF_SETBLINK( pGT, TRUE );
|
||||
if( pTerm->fOutTTY )
|
||||
HB_GTSELF_SEMICOLD( pGT );
|
||||
}
|
||||
@@ -3085,9 +3109,9 @@ static char * hb_gt_trm_Version( PHB_GT pGT, int iType )
|
||||
HB_SYMBOL_UNUSED( pGT );
|
||||
|
||||
if( iType == 0 )
|
||||
return HB_GT_DRVNAME( HB_GT_NAME );
|
||||
return ( char * ) HB_GT_DRVNAME( HB_GT_NAME );
|
||||
|
||||
return "Harbour terminal driver";
|
||||
return ( char * ) "Harbour terminal driver";
|
||||
}
|
||||
|
||||
static BOOL hb_gt_trm_Suspend( PHB_GT pGT )
|
||||
@@ -3182,10 +3206,28 @@ static void hb_gt_trm_SetBlink( PHB_GT pGT, BOOL fBlink )
|
||||
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_trm_SetBlink(%p,%d)", pGT, ( int ) fBlink ) );
|
||||
|
||||
pTerm = HB_GTTRM_GET( pGT );
|
||||
if( fBlink )
|
||||
|
||||
#if 0
|
||||
/* This is not portable extension - temporary disabled */
|
||||
if( pTerm->terminal_ext & TERM_PUTTY )
|
||||
{
|
||||
static const char * szBlinkOff = "\033[=0E"; /* disable blinking, highlight bkg */
|
||||
static const char * szBlinkOn = "\033[=1E"; /* enable blinking */
|
||||
|
||||
const char * szBlink = fBlink ? szBlinkOn : szBlinkOff;
|
||||
|
||||
pTerm->iAttrMask |= 0x0080;
|
||||
hb_gt_trm_termOut( pTerm, ( BYTE * ) szBlink, strlen( szBlink ) );
|
||||
hb_gt_trm_termFlush( pTerm );
|
||||
}
|
||||
else
|
||||
pTerm->iAttrMask &= ~0x0080;
|
||||
#endif
|
||||
{
|
||||
if( fBlink )
|
||||
pTerm->iAttrMask |= 0x0080;
|
||||
else
|
||||
pTerm->iAttrMask &= ~0x0080;
|
||||
}
|
||||
|
||||
HB_GTSUPER_SETBLINK( pGT, fBlink );
|
||||
}
|
||||
@@ -3380,6 +3422,10 @@ static BOOL hb_gt_trm_Info( PHB_GT pGT, int iType, PHB_GT_INFO pInfo )
|
||||
pInfo->pResult = hb_itemPutL( pInfo->pResult, TRUE );
|
||||
break;
|
||||
|
||||
case HB_GTI_ISUNICODE:
|
||||
pInfo->pResult = hb_itemPutL( pInfo->pResult, pTerm->fUTF8 );
|
||||
break;
|
||||
|
||||
case HB_GTI_ESCDELAY:
|
||||
pInfo->pResult = hb_itemPutNI( pInfo->pResult, pTerm->esc_delay );
|
||||
if( hb_itemType( pInfo->pNewVal ) & HB_IT_NUMERIC )
|
||||
@@ -3441,7 +3487,7 @@ static BOOL hb_gt_FuncInit( PHB_GT_FUNCS pFuncTable )
|
||||
|
||||
/* ********************************************************************** */
|
||||
|
||||
static const HB_GT_INIT gtInit = { HB_GT_DRVNAME( HB_GT_NAME ),
|
||||
static const HB_GT_INIT gtInit = { ( char * ) HB_GT_DRVNAME( HB_GT_NAME ),
|
||||
hb_gt_FuncInit,
|
||||
HB_GTSUPER,
|
||||
HB_GTID_PTR };
|
||||
|
||||
@@ -1486,6 +1486,14 @@ static BOOL hb_gt_wvt_Info( PHB_GT pGT, int iType, PHB_GT_INFO pInfo )
|
||||
pInfo->pResult = hb_itemPutL( pInfo->pResult, TRUE );
|
||||
break;
|
||||
|
||||
case HB_GTI_ISUNICODE:
|
||||
#if defined(UNICODE)
|
||||
pInfo->pResult = hb_itemPutL( pInfo->pResult, TRUE );
|
||||
#else
|
||||
pInfo->pResult = hb_itemPutL( pInfo->pResult, FALSE );
|
||||
#endif
|
||||
break;
|
||||
|
||||
case HB_GTI_INPUTFD:
|
||||
pInfo->pResult = hb_itemPutNInt( pInfo->pResult,
|
||||
( UINT_PTR ) GetStdHandle( STD_INPUT_HANDLE ) );
|
||||
|
||||
@@ -3678,6 +3678,10 @@ static BOOL hb_gt_xwc_Info( PHB_GT pGT, int iType, PHB_GT_INFO pInfo )
|
||||
pInfo->pResult = hb_itemPutL( pInfo->pResult, wnd->dpy != NULL );
|
||||
break;
|
||||
|
||||
case HB_GTI_ISUNICODE:
|
||||
pInfo->pResult = hb_itemPutL( pInfo->pResult, TRUE );
|
||||
break;
|
||||
|
||||
case HB_GTI_INPUTFD:
|
||||
pInfo->pResult = hb_itemPutNI( pInfo->pResult, ConnectionNumber( wnd->dpy ) );
|
||||
break;
|
||||
|
||||
@@ -724,6 +724,8 @@ static BOOL hb_fsFindNextLow( PHB_FFIND ffind )
|
||||
#else
|
||||
|
||||
{
|
||||
int TODO; /* TODO: for given platform */
|
||||
|
||||
/* HB_SYMBOL_UNUSED( ffind ); */
|
||||
|
||||
HB_SYMBOL_UNUSED( nYear );
|
||||
@@ -763,14 +765,16 @@ static BOOL hb_fsFindNextLow( PHB_FFIND ffind )
|
||||
|
||||
HB_EXPORT PHB_FFIND hb_fsFindFirst( const char * pszFileMask, USHORT attrmask )
|
||||
{
|
||||
PHB_FFIND ffind = ( PHB_FFIND ) hb_xgrab( sizeof( HB_FFIND ) );
|
||||
PHB_FFIND ffind;
|
||||
|
||||
ffind = ( PHB_FFIND ) hb_xgrab( sizeof( HB_FFIND ) );
|
||||
memset( ffind, 0, sizeof( HB_FFIND ) );
|
||||
|
||||
/* Allocate platform dependent file find info storage */
|
||||
|
||||
ffind->info = ( void * ) hb_xgrab( sizeof( HB_FFIND_INFO ) );
|
||||
memset( ffind->info, 0, sizeof( HB_FFIND_INFO ) );
|
||||
|
||||
/* Store search parameters */
|
||||
|
||||
ffind->pszFileMask = pszFileMask;
|
||||
ffind->attrmask = attrmask;
|
||||
ffind->bFirst = TRUE;
|
||||
@@ -849,6 +853,7 @@ HB_EXPORT void hb_fsFindClose( PHB_FFIND ffind )
|
||||
|
||||
#elif defined(HB_OS_UNIX)
|
||||
|
||||
if( info->dir != NULL )
|
||||
{
|
||||
closedir( info->dir );
|
||||
}
|
||||
@@ -857,6 +862,7 @@ HB_EXPORT void hb_fsFindClose( PHB_FFIND ffind )
|
||||
|
||||
{
|
||||
/* Intentionally do nothing */
|
||||
int TODO; /* TODO: for given platform */
|
||||
|
||||
HB_SYMBOL_UNUSED( info );
|
||||
}
|
||||
|
||||
@@ -1424,6 +1424,7 @@ static BOOL hb_gt_def_Info( PHB_GT pGT, int iType, PHB_GT_INFO pInfo )
|
||||
case HB_GTI_KBDSUPPORT:
|
||||
case HB_GTI_ISCTWIN:
|
||||
case HB_GTI_ISMULTIWIN:
|
||||
case HB_GTI_ISUNICODE:
|
||||
pInfo->pResult = hb_itemPutL( pInfo->pResult, FALSE );
|
||||
break;
|
||||
|
||||
|
||||
@@ -98,10 +98,18 @@ HB_FUNC( ROUND )
|
||||
{
|
||||
int iDec = hb_parni( 2 );
|
||||
|
||||
#ifdef HB_C52_STRICT
|
||||
/* In CA-Cl*pper ROUND() always returns double item, what in some
|
||||
* applications may be important due to different formatting rules
|
||||
* when SET FIXED is ON [druzus]
|
||||
*/
|
||||
hb_retndlen( hb_numRound( hb_itemGetND( pNumber ), iDec ), 0, HB_MAX( iDec, 0 ) );
|
||||
#else
|
||||
if( iDec == 0 && HB_IS_NUMINT( pNumber ) )
|
||||
hb_itemReturn( pNumber );
|
||||
else
|
||||
hb_retnlen( hb_numRound( hb_itemGetND( pNumber ), iDec ), 0, HB_MAX( iDec, 0 ) );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
hb_errRT_BASE_SubstR( EG_ARG, 1094, NULL, "ROUND", HB_ERR_ARGS_BASEPARAMS );
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
@@ -82,9 +82,8 @@
|
||||
#define PF_BRITISH 0x0100 /* @E */
|
||||
#define PF_EXCHANG 0x0100 /* @E. Also means exchange . and , */
|
||||
#define PF_EMPTY 0x0200 /* @Z */
|
||||
#define PF_NUMDATE 0x0400 /* Internal flag. Ignore decimal dot */
|
||||
#define PF_WIDTH 0x0800 /* @S */
|
||||
#define PF_PARNEGWOS 0x1000 /* @) Similar to PF_PARNEG but without leading spaces */
|
||||
#define PF_WIDTH 0x0400 /* @S */
|
||||
#define PF_PARNEGWOS 0x0800 /* @) Similar to PF_PARNEG but without leading spaces */
|
||||
|
||||
HB_FUNC( TRANSFORM )
|
||||
{
|
||||
@@ -95,6 +94,7 @@ HB_FUNC( TRANSFORM )
|
||||
|
||||
if( pPic && hb_itemGetCLen( pPic ) > 0 )
|
||||
{
|
||||
char szPicDate[ 11 ];
|
||||
char * szPic = hb_itemGetCPtr( pPic );
|
||||
ULONG ulPicLen = hb_itemGetCLen( pPic );
|
||||
USHORT uiPicFlags; /* Function flags */
|
||||
@@ -105,7 +105,7 @@ HB_FUNC( TRANSFORM )
|
||||
char * szResult;
|
||||
ULONG ulResultPos;
|
||||
|
||||
double dValue = 0;
|
||||
ULONG ulOffset = 0;
|
||||
|
||||
/* ======================================================= */
|
||||
/* Analyze picture functions */
|
||||
@@ -132,9 +132,8 @@ HB_FUNC( TRANSFORM )
|
||||
switch( hb_charUpper( *szPic ) )
|
||||
{
|
||||
case HB_CHAR_HT:
|
||||
case '9':
|
||||
case ' ':
|
||||
bDone = TRUE; /* End of function string */
|
||||
bDone = TRUE; /* End of function string */
|
||||
break;
|
||||
case '!':
|
||||
uiPicFlags |= PF_UPPER;
|
||||
@@ -147,7 +146,7 @@ HB_FUNC( TRANSFORM )
|
||||
break;
|
||||
case 'L':
|
||||
case '0':
|
||||
uiPicFlags |= PF_PADL;
|
||||
uiPicFlags |= PF_PADL; /* FoxPro/XPP extension */
|
||||
byParamL = '0';
|
||||
break;
|
||||
case 'B':
|
||||
@@ -158,7 +157,6 @@ HB_FUNC( TRANSFORM )
|
||||
break;
|
||||
case 'D':
|
||||
uiPicFlags |= PF_DATE;
|
||||
uiPicFlags |= PF_NUMDATE;
|
||||
break;
|
||||
case 'E':
|
||||
uiPicFlags |= PF_BRITISH;
|
||||
@@ -168,16 +166,13 @@ HB_FUNC( TRANSFORM )
|
||||
break;
|
||||
case 'S':
|
||||
uiPicFlags |= PF_WIDTH;
|
||||
|
||||
ulParamS = 0;
|
||||
while( ulPicLen > 1 && *( szPic + 1 ) >= '0' && *( szPic + 1 ) <= '9' )
|
||||
{
|
||||
szPic++;
|
||||
ulPicLen--;
|
||||
|
||||
ulParamS = ( ulParamS * 10 ) + ( ( ULONG ) ( *szPic - '0' ) );
|
||||
}
|
||||
|
||||
break;
|
||||
case 'X':
|
||||
uiPicFlags |= PF_DEBIT;
|
||||
@@ -201,22 +196,19 @@ HB_FUNC( TRANSFORM )
|
||||
char * szExp = hb_itemGetCPtr( pValue );
|
||||
ULONG ulExpLen = hb_itemGetCLen( pValue );
|
||||
ULONG ulExpPos = 0;
|
||||
|
||||
char szPicDate[ 11 ];
|
||||
BOOL bAnyPic = FALSE;
|
||||
BOOL bFound = FALSE;
|
||||
|
||||
/* Grab enough */
|
||||
|
||||
/* Support date function for strings */
|
||||
if( ( uiPicFlags & PF_DATE ) ||
|
||||
( ( uiPicFlags & PF_BRITISH ) && ( uiPicFlags & PF_REMAIN ) ) )
|
||||
if( uiPicFlags & ( PF_DATE | PF_BRITISH ) )
|
||||
{
|
||||
hb_dateFormat( "XXXXXXXX", szPicDate, hb_set.HB_SET_DATEFORMAT );
|
||||
|
||||
szPic = szPicDate;
|
||||
ulPicLen = strlen( szPicDate );
|
||||
}
|
||||
|
||||
szResult = ( char * ) hb_xgrab( ulExpLen + ulPicLen + 1 );
|
||||
ulResultPos = 0;
|
||||
|
||||
@@ -365,17 +357,32 @@ HB_FUNC( TRANSFORM )
|
||||
szResult[ ulResultPos++ ] = ' ';
|
||||
}
|
||||
|
||||
if( ( ( uiPicFlags & PF_DATE ) && ( uiPicFlags & PF_BRITISH ) ) ||
|
||||
( ( uiPicFlags & PF_BRITISH ) && ( uiPicFlags & PF_REMAIN ) ) )
|
||||
if( uiPicFlags & PF_BRITISH )
|
||||
{
|
||||
szPicDate[ 0 ] = szResult[ 3 ];
|
||||
szPicDate[ 1 ] = szResult[ 4 ];
|
||||
|
||||
szResult[ 3 ] = szResult[ 0 ];
|
||||
szResult[ 4 ] = szResult[ 1 ];
|
||||
|
||||
szResult[ 0 ] = szPicDate[ 0 ];
|
||||
szResult[ 1 ] = szPicDate[ 1 ];
|
||||
/* CA-Cl*pper do not check result size and always exchanges
|
||||
* bytes 1-2 with bytes 4-5. It's buffer overflow bug and I do
|
||||
* not want to replicate it. It also causes that the results of
|
||||
* @E conversion used for strings smaller then 5 bytes behaves
|
||||
* randomly.
|
||||
* In fact precise tests can show that it's not random behavior
|
||||
* but CA-Cl*pper uses static buffer for result and when current
|
||||
* one is smaller then 5 bytes then first two bytes are exchanged
|
||||
* with 4-5 bytes from previous result which was length enough,
|
||||
* f.e.:
|
||||
* ? transform( "0123456789", "" )
|
||||
* ? transform( "AB", "@E" )
|
||||
* ? transform( "ab", "@E" )
|
||||
* [druzus]
|
||||
*/
|
||||
if( ulResultPos >= 5 )
|
||||
{
|
||||
szPicDate[ 0 ] = szResult[ 0 ];
|
||||
szPicDate[ 1 ] = szResult[ 1 ];
|
||||
szResult[ 0 ] = szResult[ 3 ];
|
||||
szResult[ 1 ] = szResult[ 4 ];
|
||||
szResult[ 3 ] = szPicDate[ 0 ];
|
||||
szResult[ 4 ] = szPicDate[ 1 ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,292 +392,250 @@ HB_FUNC( TRANSFORM )
|
||||
|
||||
else if( HB_IS_NUMERIC( pValue ) )
|
||||
{
|
||||
double dPush;
|
||||
|
||||
int iOrigWidth;
|
||||
int iOrigDec;
|
||||
int iWidth; /* Width of string */
|
||||
int iDec; /* Number of decimals */
|
||||
int iCount;
|
||||
ULONG i;
|
||||
ULONG ulBufSize;
|
||||
int iCount = 0;
|
||||
|
||||
char * szStr;
|
||||
char cPic;
|
||||
char szPicDate[ 11 ];
|
||||
PHB_ITEM pNumber = NULL;
|
||||
|
||||
PHB_ITEM pNumber;
|
||||
PHB_ITEM pWidth;
|
||||
PHB_ITEM pDec;
|
||||
|
||||
BOOL bFound = FALSE;
|
||||
BOOL bInit = FALSE;
|
||||
BOOL bPDec = FALSE;
|
||||
|
||||
dValue = hb_itemGetND( pValue );
|
||||
hb_itemGetNLen( pValue, &iOrigWidth, &iOrigDec );
|
||||
double dValue = hb_itemGetND( pValue );
|
||||
|
||||
/* Support date function for numbers */
|
||||
if( uiPicFlags & PF_DATE )
|
||||
{
|
||||
hb_dateFormat( "99999999", szPicDate,
|
||||
hb_set.HB_SET_DATEFORMAT );
|
||||
|
||||
hb_dateFormat( "99999999", szPicDate, hb_set.HB_SET_DATEFORMAT );
|
||||
szPic = szPicDate;
|
||||
ulPicLen = strlen( szPicDate );
|
||||
}
|
||||
|
||||
/* TODO: maybe replace this 16 with something else */
|
||||
ulBufSize = ulPicLen + (ULONG) iOrigWidth + (ULONG) iOrigDec + 16;
|
||||
szResult = ( char * ) hb_xgrab( ulBufSize ); /* Grab enough */
|
||||
*szResult = '\0';
|
||||
|
||||
for( i = 0; i < ulPicLen && !bFound; i++ ) /* Count number in front */
|
||||
for( i = iWidth = iDec = 0; i < ulPicLen; i++ )
|
||||
{
|
||||
if( szPic[ i ] == '.' )
|
||||
/* bFound = !( uiPicFlags & PF_NUMDATE ); / * Exit when numeric */
|
||||
bFound = TRUE;
|
||||
{
|
||||
while( ++i < ulPicLen )
|
||||
{
|
||||
if( szPic[ i ] == '9' || szPic[ i ] == '#' ||
|
||||
szPic[ i ] == '$' || szPic[ i ] == '*' )
|
||||
{
|
||||
iWidth++;
|
||||
iDec++;
|
||||
}
|
||||
}
|
||||
if( iDec )
|
||||
iWidth++;
|
||||
break;
|
||||
}
|
||||
else if( szPic[ i ] == '9' || szPic[ i ] == '#' ||
|
||||
szPic[ i ] == '$' || szPic[ i ] == '*' )
|
||||
iCount++;
|
||||
iWidth++;
|
||||
}
|
||||
iWidth = iCount;
|
||||
|
||||
if( bFound ) /* Did we find a dot */
|
||||
{
|
||||
iDec = 0;
|
||||
if( i < ulPicLen )
|
||||
{ /* if not 9999. */
|
||||
iWidth++; /* Also adjust iWidth */
|
||||
}
|
||||
for( ; i < ulPicLen; i++ )
|
||||
{
|
||||
if( szPic[ i ] == '9' ||
|
||||
szPic[ i ] == '#' ||
|
||||
szPic[ i ] == '$' ||
|
||||
szPic[ i ] == '*' )
|
||||
{
|
||||
iWidth++;
|
||||
iDec++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
iDec = 0;
|
||||
|
||||
if( ( uiPicFlags & ( PF_DEBIT + PF_PARNEG + PF_PARNEGWOS ) ) && dValue < 0 )
|
||||
dPush = -dValue; /* Always push absolute val */
|
||||
else
|
||||
dPush = dValue;
|
||||
|
||||
/* Don't empty the result if the number is not zero */
|
||||
if( dPush != 0 && ( uiPicFlags & PF_EMPTY ) )
|
||||
uiPicFlags &= ~PF_EMPTY;
|
||||
|
||||
iCount = 0;
|
||||
if( iWidth == 0 ) /* Width calculated ?? */
|
||||
{
|
||||
iWidth = iOrigWidth; /* Push original width */
|
||||
iDec = iOrigDec; /* Push original decimals */
|
||||
hb_itemGetNLen( pValue, &iWidth, &iDec );
|
||||
if( hb_set.HB_SET_FIXED )
|
||||
{
|
||||
if( HB_IS_NUMINT( pValue ) )
|
||||
iWidth += 2 + ( hb_set.HB_SET_DECIMALS << 1 );
|
||||
else
|
||||
iDec = hb_set.HB_SET_DECIMALS;
|
||||
}
|
||||
if( iDec )
|
||||
iWidth += iDec + 1;
|
||||
}
|
||||
else if( iDec > 0 && iWidth - iDec == 1 )
|
||||
{
|
||||
iCount = 1;
|
||||
iWidth++;
|
||||
}
|
||||
|
||||
pNumber = hb_itemPutNDLen( NULL, dPush, -1, iDec );
|
||||
pWidth = hb_itemPutNI( NULL, iWidth + ( ( ulPicLen || iDec == 0 ) ? 0 : ( iDec + 1 ) ) );
|
||||
pDec = hb_itemPutNI( NULL, iDec );
|
||||
|
||||
szStr = hb_itemStr( pNumber, pWidth, pDec );
|
||||
|
||||
hb_itemRelease( pNumber );
|
||||
hb_itemRelease( pWidth );
|
||||
hb_itemRelease( pDec );
|
||||
|
||||
if( szStr )
|
||||
if( ( uiPicFlags & ( PF_DEBIT | PF_PARNEG | PF_PARNEGWOS ) ) && dValue < 0 )
|
||||
{
|
||||
iCount = 0;
|
||||
|
||||
/* Pad with padding char */
|
||||
if( uiPicFlags & PF_PADL )
|
||||
{
|
||||
for( i = 0; szStr[ i ] == ' ' && i < ( ULONG ) iWidth; i++ )
|
||||
szStr[ i ] = byParamL;
|
||||
}
|
||||
|
||||
if( ulPicLen )
|
||||
for( i = 0; i < ulPicLen; i++ )
|
||||
{
|
||||
cPic = szPic[ i ];
|
||||
|
||||
if( !bInit && ( cPic == '9' || cPic == '#' || cPic == '$' || cPic == '*' ) )
|
||||
bInit = TRUE;
|
||||
|
||||
if( cPic == '9' || cPic == '#' )
|
||||
{
|
||||
if( iCount < iWidth )
|
||||
szResult[ i ] = szStr[ iCount++ ]; /* Just copy */
|
||||
else
|
||||
szResult[ i ] = ' ';
|
||||
}
|
||||
else if( cPic == '.' && bInit )
|
||||
{
|
||||
bPDec = TRUE;
|
||||
|
||||
if( uiPicFlags & PF_EXCHANG ) /* Exchange . and , */
|
||||
{
|
||||
szResult[ i ] = ',';
|
||||
iCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( uiPicFlags & PF_NUMDATE || bPDec ) /* Dot in date */
|
||||
{
|
||||
szResult[ i ] = cPic;
|
||||
iCount++;
|
||||
}
|
||||
else /* Dot in number */
|
||||
{
|
||||
szResult[ i ] = szStr[ iCount++ ];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( cPic == '$' || cPic == '*' )
|
||||
{
|
||||
if( szStr[ iCount ] == ' ' )
|
||||
{
|
||||
szResult[ i ] = cPic;
|
||||
iCount++;
|
||||
}
|
||||
else
|
||||
szResult[ i ] = szStr[ iCount++ ];
|
||||
}
|
||||
else if( cPic == ',' && bInit ) /* Comma */
|
||||
{
|
||||
if( iCount && isdigit( ( int ) szStr[ iCount - 1 ] ) )
|
||||
{ /* May we place it */
|
||||
if( uiPicFlags & PF_EXCHANG )
|
||||
szResult[ i ] = '.';
|
||||
else
|
||||
szResult[ i ] = ',';
|
||||
}
|
||||
else
|
||||
{
|
||||
if( i && szResult[ i - 1 ] == '*' )
|
||||
szResult[ i ] = '*';
|
||||
else
|
||||
szResult[ i ] = ' ';
|
||||
|
||||
if ( i && szResult[ i - 1 ] == '-' )
|
||||
{
|
||||
szResult[ i -1 ] = ' ';
|
||||
szResult[ i ] = '-';
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
szResult[ i ] = cPic;
|
||||
}
|
||||
/* Always convert absolute val */
|
||||
if( HB_IS_NUMINT( pValue ) ) /* workaround for 64bit integer conversion */
|
||||
pNumber = hb_itemPutNInt( NULL, - hb_itemGetNInt( pValue ) );
|
||||
else
|
||||
pNumber = hb_itemPutND( NULL, -dValue );
|
||||
pValue = pNumber;
|
||||
}
|
||||
|
||||
if( dValue != 0 )
|
||||
/* Don't empty the result if the number is not zero */
|
||||
uiPicFlags &= ~PF_EMPTY;
|
||||
|
||||
/* allocate 4 additional bytes for possible ") CR" or ") DB" suffix */
|
||||
szResult = ( char * ) hb_xgrab( iWidth + 5 );
|
||||
hb_itemStrBuf( szResult, pValue, iWidth, iDec );
|
||||
if( pNumber )
|
||||
hb_itemRelease( pNumber );
|
||||
|
||||
if( iCount )
|
||||
{
|
||||
iWidth--;
|
||||
if( *szResult != '0' )
|
||||
{
|
||||
hb_strncpy( szResult, szStr, ulBufSize - 1 );
|
||||
i = strlen( szResult );
|
||||
memset( szResult + 1, '*', iWidth );
|
||||
*szResult = '.';
|
||||
}
|
||||
else
|
||||
memmove( szResult, szResult + 1, iWidth );
|
||||
szResult[ iWidth ] = '\0';
|
||||
}
|
||||
|
||||
if( ( uiPicFlags & PF_PARNEG ) && dValue < 0 && !( uiPicFlags & PF_PARNEGWOS ) )
|
||||
/* This is a behavior of Clipper,
|
||||
if exist PF_PARNEG and PF_PARNEGWOS,
|
||||
PR_PARNEGWOS prevails. */
|
||||
/* Pad with padding char */
|
||||
if( uiPicFlags & PF_PADL )
|
||||
{
|
||||
for( i = 0; szResult[ i ] == ' '; i++ )
|
||||
szResult[ i ] = byParamL;
|
||||
|
||||
/* please test it with FoxPro and xbase++ to check
|
||||
* if they made the same [druzus]
|
||||
*/
|
||||
if( i && szResult[ i ] == '-' )
|
||||
{
|
||||
for( iCount = 0; ( ULONG ) iCount < i; iCount++ )
|
||||
/* Permit to detect overflow when picture init with mask */
|
||||
szResult[ 0 ] = '-';
|
||||
szResult[ i ] = byParamL;
|
||||
}
|
||||
}
|
||||
|
||||
if( ulPicLen == 0 )
|
||||
{
|
||||
if( uiPicFlags & PF_EXCHANG )
|
||||
{
|
||||
for( i = 0; i < ( ULONG ) iWidth; ++i )
|
||||
{
|
||||
if( isdigit( ( int ) szResult[ iCount ] ) &&
|
||||
!( szResult[ iCount ] == '0' ) && /* if not PF_PADL */
|
||||
( iCount == 0 ||
|
||||
!isdigit( ( int ) szPic[ iCount ] ) ) ) /* if not mask symbol */
|
||||
/* Overflow */
|
||||
if( szResult[ i ] == '.' )
|
||||
{
|
||||
for( iCount++; ( ULONG ) iCount < i; iCount++ )
|
||||
{
|
||||
if( isdigit( ( int ) szResult[ iCount ] ) )
|
||||
szResult[ iCount ] = '*';
|
||||
}
|
||||
szResult[ i ] = ',';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
i = iWidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
char * szStr = szResult;
|
||||
|
||||
/* allocate 4 additional bytes for possible ") CR" or ") DB" suffix */
|
||||
szResult = ( char * ) hb_xgrab( ulPicLen + 5 );
|
||||
|
||||
for( i = iCount = 0; i < ulPicLen; i++ )
|
||||
{
|
||||
cPic = szPic[ i ];
|
||||
if( cPic == '9' || cPic == '#' )
|
||||
{
|
||||
szResult[ i ] = iCount < iWidth ? szStr[ iCount++ ] : ' ';
|
||||
}
|
||||
else if( cPic == '$' || cPic == '*' )
|
||||
{
|
||||
if( iCount < iWidth )
|
||||
{
|
||||
szResult[ i ] = szStr[ iCount ] == ' ' ? cPic : szStr[ iCount ];
|
||||
iCount++;
|
||||
}
|
||||
else
|
||||
szResult[ i ] = ' ';
|
||||
}
|
||||
else if( cPic == '.' && iCount < iWidth )
|
||||
{
|
||||
szResult[ i ] = ( uiPicFlags & PF_EXCHANG ) ? ',' : '.';
|
||||
iCount++;
|
||||
}
|
||||
else if( cPic == ',' && i && iCount < iWidth )
|
||||
{
|
||||
if( isdigit( ( UCHAR ) szResult[ i - 1 ] ) )
|
||||
szResult[ i ] = ( uiPicFlags & PF_EXCHANG ) ? '.' : ',';
|
||||
else
|
||||
{
|
||||
if( !isdigit( ( int ) szResult[ iCount ] ) ||
|
||||
( szResult[ iCount ] == '0' && !isdigit( ( int ) szPic[ iCount ] ) ) )
|
||||
break;
|
||||
szResult[ i ] = szResult[ i - 1 ];
|
||||
if( szResult[ i - 1 ] == '-' )
|
||||
{
|
||||
szResult[ i - 1 ] = i > 1 && szResult[ i - 2 ] != '$' ?
|
||||
szResult[ i - 2 ] : ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
szResult[ i ] = cPic;
|
||||
}
|
||||
hb_xfree( szStr );
|
||||
}
|
||||
|
||||
if( dValue < 0 )
|
||||
{
|
||||
/* PF_PARNEGWOS has higher priority then PF_PARNEG */
|
||||
if( ( uiPicFlags & PF_PARNEGWOS ) )
|
||||
{
|
||||
iCount = 0;
|
||||
if( ulPicLen && i > 1 )
|
||||
{
|
||||
if( *szPic == *szResult && ( *szPic == '*' || *szPic == '$' ) &&
|
||||
szResult[ 1 ] == ' ' )
|
||||
++iCount;
|
||||
}
|
||||
while( ( ULONG ) iCount + 1 < i && szResult[ iCount + 1 ] == ' ' )
|
||||
++iCount;
|
||||
|
||||
#ifndef HB_C52_STRICT
|
||||
/* This is not Clipper compatible */
|
||||
if( szResult[ iCount ] >= '1' && szResult[ iCount ] <= '9' &&
|
||||
( ulPicLen == 0 || szPic[ iCount ] == '9' ||
|
||||
szPic[ iCount ] != szResult[ iCount ] ) )
|
||||
{
|
||||
szResult[ iCount ] = '(';
|
||||
for( ++iCount; ( ULONG ) iCount < i; iCount++ )
|
||||
{
|
||||
if( szResult[ iCount ] >= '0' && szResult[ iCount ] <= '9' &&
|
||||
( ulPicLen == 0 || szPic[ iCount ] == '9' ||
|
||||
szPic[ iCount ] != szResult[ iCount ] ) )
|
||||
szResult[ iCount ] = '*';
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
szResult[ iCount ] = '(';
|
||||
szResult[ i++ ] = ')';
|
||||
}
|
||||
else if( ( uiPicFlags & PF_PARNEG ) )
|
||||
{
|
||||
#ifndef HB_C52_STRICT
|
||||
/* This is not Clipper compatible */
|
||||
if( *szResult >= '1' && *szResult <= '9' &&
|
||||
( ulPicLen == 0 || *szPic == '9' || *szPic != *szResult ) )
|
||||
{
|
||||
for( iCount = 1; ( ULONG ) iCount < i; iCount++ )
|
||||
{
|
||||
if( szResult[ iCount ] >= '0' && szResult[ iCount ] <= '9' &&
|
||||
( ulPicLen == 0 || szPic[ iCount ] == '9' ||
|
||||
szPic[ iCount ] != szResult[ iCount ] ) )
|
||||
szResult[ iCount ] = '*';
|
||||
}
|
||||
}
|
||||
#endif
|
||||
*szResult = '(';
|
||||
szResult[ i++ ] = ')';
|
||||
ulOffset = 1;
|
||||
}
|
||||
|
||||
if( ( uiPicFlags & PF_PARNEGWOS ) && dValue < 0 )
|
||||
{
|
||||
for( iCount = 0; ( ULONG ) iCount < i; iCount++ )
|
||||
/* Permit to detect overflow when picture init with mask */
|
||||
{
|
||||
if( isdigit( ( int ) szResult[ iCount ] ) &&
|
||||
!( szResult[ iCount ] == '0' ) && /* if not PF_PADL */
|
||||
( iCount == 0 ||
|
||||
!isdigit( ( int ) szPic[ iCount ] ) ) ) /* if not mask symbol */
|
||||
/* Overflow */
|
||||
{
|
||||
for( iCount++; ( ULONG ) iCount < i; iCount++ )
|
||||
{
|
||||
if( isdigit( ( int ) szResult[ iCount ] ) )
|
||||
szResult[ iCount ] = '*';
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !isdigit( ( int ) szResult[ iCount ] ) ||
|
||||
( szResult[ iCount ] == '0' && !isdigit( ( int ) szPic[ iCount ] ) ) )
|
||||
{
|
||||
for( ; ( ULONG ) iCount < i; iCount++ )
|
||||
{
|
||||
if( szResult[ iCount ] != ' ' )
|
||||
{
|
||||
if( iCount > 0 )
|
||||
szResult[ iCount - 1 ] = '(';
|
||||
else
|
||||
*szResult = '(';
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
szResult[ i++ ] = ')';
|
||||
}
|
||||
|
||||
if( ( uiPicFlags & PF_CREDIT ) && dValue >= 0 )
|
||||
{
|
||||
szResult[ i++ ] = ' ';
|
||||
szResult[ i++ ] = 'C';
|
||||
szResult[ i++ ] = 'R';
|
||||
}
|
||||
|
||||
if( ( uiPicFlags & PF_DEBIT ) && dValue < 0 )
|
||||
if( ( uiPicFlags & PF_DEBIT ) )
|
||||
{
|
||||
szResult[ i++ ] = ' ';
|
||||
szResult[ i++ ] = 'D';
|
||||
szResult[ i++ ] = 'B';
|
||||
}
|
||||
|
||||
ulResultPos = i;
|
||||
szResult[ i ] = '\0';
|
||||
|
||||
hb_xfree( szStr );
|
||||
}
|
||||
else
|
||||
else if( ( uiPicFlags & PF_CREDIT ) && dValue > 0 )
|
||||
{
|
||||
ulResultPos = 0;
|
||||
szResult[ i++ ] = ' ';
|
||||
szResult[ i++ ] = 'C';
|
||||
szResult[ i++ ] = 'R';
|
||||
}
|
||||
|
||||
ulResultPos = i;
|
||||
szResult[ i ] = '\0';
|
||||
}
|
||||
|
||||
/* ======================================================= */
|
||||
@@ -679,27 +644,86 @@ HB_FUNC( TRANSFORM )
|
||||
|
||||
else if( HB_IS_DATE( pValue ) )
|
||||
{
|
||||
char szPicDate[ 11 ];
|
||||
char szDate[ 9 ];
|
||||
|
||||
char * szDateFormat;
|
||||
char szNewFormat[ 11 ];
|
||||
UINT nFor;
|
||||
|
||||
szResult = ( char * ) hb_xgrab( 13 );
|
||||
szDateFormat = hb_set.HB_SET_DATEFORMAT;
|
||||
|
||||
hb_dateFormat( hb_itemGetDS( pValue, szDate ), szResult,
|
||||
( uiPicFlags & PF_BRITISH ) ?
|
||||
( hb_set.hb_set_century ? "DD/MM/YYYY" : "DD/MM/YY" ) :
|
||||
hb_set.HB_SET_DATEFORMAT );
|
||||
#ifndef HB_C52_STRICT
|
||||
if( uiPicFlags & PF_BRITISH )
|
||||
{
|
||||
/* When @E is used CA-Cl*pper do not update date format
|
||||
* pattern but wrongly moves 4-th and 5-th bytes of
|
||||
* formatted date to the beginning (see below). It causes
|
||||
* that date formats formats different then MM?DD?YY[YY]
|
||||
* are wrongly translated. The code below is not CA-Cl*pper
|
||||
* compatible but it tries to respect user date format
|
||||
* [druzus]
|
||||
*/
|
||||
const char * szBritish = hb_set.hb_set_century ?
|
||||
"DDMMYYYY" : "DDMMYY";
|
||||
char cLast = 'x';
|
||||
|
||||
for( nFor = 0; nFor < 10; nFor++ )
|
||||
{
|
||||
if( *szBritish == cLast )
|
||||
{
|
||||
szNewFormat[ nFor ] = cLast;
|
||||
szBritish++;
|
||||
}
|
||||
else if( ! *szDateFormat )
|
||||
break;
|
||||
else if( *szBritish &&
|
||||
( *szDateFormat == 'Y' || *szDateFormat == 'y' ||
|
||||
*szDateFormat == 'D' || *szDateFormat == 'd' ||
|
||||
*szDateFormat == 'M' || *szDateFormat == 'm' ) )
|
||||
{
|
||||
szNewFormat[ nFor ] = cLast = *szBritish++;
|
||||
do
|
||||
szDateFormat++;
|
||||
while( szDateFormat[ -1 ] == szDateFormat[ 0 ] );
|
||||
}
|
||||
else
|
||||
szNewFormat[ nFor ] = *szDateFormat++;
|
||||
}
|
||||
szNewFormat[ nFor ] = '\0';
|
||||
szDateFormat = szNewFormat;
|
||||
}
|
||||
#endif
|
||||
|
||||
hb_dateFormat( hb_itemGetDS( pValue, szDate ), szResult, szDateFormat );
|
||||
ulResultPos = strlen( szResult );
|
||||
|
||||
#ifdef HB_C52_STRICT
|
||||
if( uiPicFlags & PF_BRITISH )
|
||||
{
|
||||
/* replicated wrong Clipper behavior, see note above.
|
||||
* It's not exact CA-Cl*pper behavior because it does
|
||||
* not check for size of results and can extract data
|
||||
* from static memory buffer used in previous conversions
|
||||
* (see my note for @E in string conversion above)
|
||||
* but this is buffer overflow and I do not plan to
|
||||
* replicated it too [druzus]
|
||||
*/
|
||||
if( ulResultPos >= 5 )
|
||||
{
|
||||
szNewFormat[ 0 ] = szResult[ 0 ];
|
||||
szNewFormat[ 1 ] = szResult[ 1 ];
|
||||
szResult[ 0 ] = szResult[ 3 ];
|
||||
szResult[ 1 ] = szResult[ 4 ];
|
||||
szResult[ 3 ] = szNewFormat[ 0 ];
|
||||
szResult[ 4 ] = szNewFormat[ 1 ];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if( uiPicFlags & PF_REMAIN )
|
||||
{
|
||||
hb_dateFormat( "99999999", szPicDate,
|
||||
( uiPicFlags & PF_BRITISH ) ?
|
||||
( hb_set.hb_set_century ? "DD/MM/YYYY" : "DD/MM/YY" ) :
|
||||
hb_set.HB_SET_DATEFORMAT );
|
||||
|
||||
/* Here we also respect the date format modified for @E [druzus]
|
||||
*/
|
||||
hb_dateFormat( "99999999", szPicDate, szDateFormat );
|
||||
ulPicLen = strlen( szPicDate );
|
||||
|
||||
for( nFor = 0; nFor < ulPicLen; nFor++ )
|
||||
@@ -712,7 +736,6 @@ HB_FUNC( TRANSFORM )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ======================================================= */
|
||||
@@ -723,16 +746,20 @@ HB_FUNC( TRANSFORM )
|
||||
{
|
||||
BOOL bDone = FALSE;
|
||||
BOOL bExit = FALSE;
|
||||
|
||||
char cPic;
|
||||
|
||||
ulResultPos = 0;
|
||||
if( uiPicFlags & ( PF_DATE | PF_BRITISH ) )
|
||||
{
|
||||
hb_dateFormat( "99999999", szPicDate, hb_set.HB_SET_DATEFORMAT );
|
||||
szPic = szPicDate;
|
||||
ulPicLen = strlen( szPicDate );
|
||||
}
|
||||
|
||||
ulResultPos = 0;
|
||||
szResult = ( char * ) hb_xgrab( ulPicLen + 2 );
|
||||
|
||||
for( ; ( ulPicLen || !bDone ) && !bExit ; ulResultPos++, szPic++, ulPicLen-- )
|
||||
{
|
||||
|
||||
if( ulPicLen )
|
||||
cPic = *szPic;
|
||||
else
|
||||
@@ -779,7 +806,6 @@ HB_FUNC( TRANSFORM )
|
||||
if( !( uiPicFlags & PF_REMAIN ) )
|
||||
bExit = TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ======================================================= */
|
||||
@@ -793,26 +819,24 @@ HB_FUNC( TRANSFORM )
|
||||
|
||||
if( ! bError )
|
||||
{
|
||||
/* Trim left and pad with spaces */
|
||||
if( uiPicFlags & PF_LEFT )
|
||||
if( uiPicFlags & PF_EMPTY )
|
||||
memset( szResult, ' ', ulResultPos );
|
||||
else if( uiPicFlags & PF_LEFT )
|
||||
{
|
||||
|
||||
ULONG ulFirstChar = ( ( ( uiPicFlags & PF_PARNEG ) && dValue < 0 && !( uiPicFlags & PF_PARNEGWOS ) ) ? 1: 0 );
|
||||
/* Trim left and pad with spaces */
|
||||
ULONG ulFirstChar = ulOffset;
|
||||
|
||||
while( ulFirstChar < ulResultPos && szResult[ ulFirstChar ] == ' ' )
|
||||
ulFirstChar++;
|
||||
|
||||
if( ulFirstChar < ulResultPos )
|
||||
if( ulFirstChar > ulOffset && ulFirstChar < ulResultPos )
|
||||
{
|
||||
memmove( szResult + ( ( ( uiPicFlags & PF_PARNEG ) && dValue < 0 && !( uiPicFlags & PF_PARNEGWOS ) ) ? 1: 0 ), szResult + ulFirstChar, ulResultPos - ulFirstChar );
|
||||
memset( szResult + ulResultPos - ulFirstChar + ( ( ( uiPicFlags & PF_PARNEG ) && dValue < 0 && !( uiPicFlags & PF_PARNEGWOS ) ) ? 1: 0 ), ' ', ulFirstChar );
|
||||
memmove( szResult + ulOffset, szResult + ulFirstChar, ulResultPos - ulFirstChar );
|
||||
memset( szResult + ulOffset + ulResultPos - ulFirstChar, ' ', ulFirstChar - ulOffset );
|
||||
}
|
||||
}
|
||||
|
||||
if( uiPicFlags & PF_EMPTY )
|
||||
memset( szResult, ' ', ulResultPos );
|
||||
|
||||
hb_retclen_buffer( szResult, ( uiPicFlags & PF_WIDTH && ulResultPos > ulParamS && ulParamS > 0 ) ? ulParamS : ulResultPos );
|
||||
hb_retclen_buffer( szResult, ( ulParamS && ulResultPos > ulParamS ) ? ulParamS : ulResultPos );
|
||||
}
|
||||
}
|
||||
else if( pPic || ISNIL( 2 ) ) /* Picture is an empty string or NIL */
|
||||
@@ -823,25 +847,18 @@ HB_FUNC( TRANSFORM )
|
||||
}
|
||||
else if( HB_IS_NUMERIC( pValue ) )
|
||||
{
|
||||
int iWidth = 10, iDec;
|
||||
char * szStr;
|
||||
|
||||
if( !HB_IS_DOUBLE( pValue ) && hb_set.HB_SET_FIXED )
|
||||
if( HB_IS_NUMINT( pValue ) && hb_set.HB_SET_FIXED )
|
||||
{
|
||||
int iWidth, iDec;
|
||||
hb_itemGetNLen( pValue, &iWidth, &iDec );
|
||||
if( iWidth < 10 )
|
||||
{
|
||||
PHB_ITEM pWidth = hb_itemPutNI( NULL, 2 + iWidth +
|
||||
( hb_set.HB_SET_DECIMALS << 1 ) );
|
||||
szStr = hb_itemStr( pValue, pWidth, NULL );
|
||||
hb_itemRelease( pWidth );
|
||||
if( szStr )
|
||||
hb_retc_buffer( szStr );
|
||||
else
|
||||
hb_retc( NULL );
|
||||
}
|
||||
iWidth += 2 + ( hb_set.HB_SET_DECIMALS << 1 );
|
||||
szStr = hb_xgrab( iWidth + 1 );
|
||||
hb_itemStrBuf( szStr, pValue, iWidth, iDec );
|
||||
hb_retclen_buffer( szStr, iWidth );
|
||||
}
|
||||
if( iWidth >= 10 )
|
||||
else
|
||||
{
|
||||
ULONG ulLen;
|
||||
BOOL bFreeReq;
|
||||
|
||||
@@ -2041,11 +2041,20 @@ static void hb_objSupperDestructorCall( PHB_ITEM pObject, PCLASS pClass )
|
||||
{
|
||||
if( pbClasses[ uiClass ] == 1 )
|
||||
{
|
||||
hb_vmPushSymbol( &s___msgDestructor );
|
||||
hb_clsMakeSuperObject( hb_stackAllocItem(), pObject, uiClass );
|
||||
hb_vmSend( 0 );
|
||||
if( hb_vmRequestQuery() != 0 )
|
||||
break;
|
||||
PMETHOD pDestructor = hb_clsFindMsg( &s_pClasses[ uiClass ],
|
||||
s___msgDestructor.pDynSym );
|
||||
if( pDestructor )
|
||||
{
|
||||
if( pbClasses[ pDestructor->uiSprClass ] == 1 )
|
||||
{
|
||||
hb_vmPushSymbol( &s___msgDestructor );
|
||||
hb_clsMakeSuperObject( hb_stackAllocItem(), pObject, uiClass );
|
||||
hb_vmSend( 0 );
|
||||
if( hb_vmRequestQuery() != 0 )
|
||||
break;
|
||||
pbClasses[ pDestructor->uiSprClass ] |= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
307
harbour/tests/transtst.prg
Normal file
307
harbour/tests/transtst.prg
Normal file
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Harbour Project source code:
|
||||
* test code for TRANSFORM() function
|
||||
*
|
||||
* Copyright 2008 Przemyslaw Czerpak <druzus / at / priv.onet.pl>
|
||||
* www - http://www.harbour-project.org
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
static s_stop := .f.
|
||||
|
||||
proc main()
|
||||
test()
|
||||
return
|
||||
|
||||
function transtest( xVal, cPict, cExpect )
|
||||
local cResult := transform( xVal, cPict )
|
||||
if !cResult == cExpect
|
||||
s_stop := .t.
|
||||
endif
|
||||
return iif( cResult == cExpect, "[OK] ", "[ERROR] ["+cExpect+"] => ") + ;
|
||||
"[" + cResult + "]"
|
||||
|
||||
proc stop()
|
||||
if s_stop
|
||||
? repl("*",50)
|
||||
inkey(0)
|
||||
s_stop := .f.
|
||||
endif
|
||||
return
|
||||
|
||||
proc test()
|
||||
local dt
|
||||
? transtest( "abcd", "@9!*", "ABCD" )
|
||||
? transtest( "abcd", "@_9!*", "ABCD" )
|
||||
? transtest( "abcd", "@_9"+chr(9)+"9!9", "aBc" )
|
||||
? transtest( "abcd", "@!!!", "ABCD" )
|
||||
? transtest( "abcd", "@9", "abcd" )
|
||||
?
|
||||
? transtest( 134.24, "99,999.99", " 134.24" )
|
||||
? transtest( 134.24, "@E 99,999.99", " 134,24" )
|
||||
? transtest( -134.24,"@E 99,999.99", " -134,24" )
|
||||
? transtest( 134.24, "@E99,999.99", " 134,24" )
|
||||
? transtest( -134.24, "@E99,999.99", " -134,24" )
|
||||
?
|
||||
? transtest(-7, "@X 9999", " 7 DB")
|
||||
? transtest(stod("19920509"), "@E", "09/05/92")
|
||||
? transtest(val("3.10"),"@X", "3.10")
|
||||
? transtest(0.80,".9999", ".8000" )
|
||||
? transtest(-0.80, ".9999", ".****" )
|
||||
? transtest(12345.123, "@X99", " 12345.123")
|
||||
? transtest(-12345.123, "@X99", " 12345.123 DB" )
|
||||
? transtest( 123456.78, "@E", " 123456,78")
|
||||
? transtest(0,"@C 9.99", "0.00")
|
||||
stop()
|
||||
#ifdef __HARBOUR__
|
||||
dt:=stod("19871231")
|
||||
set date format to "MM:DD:YYYY"
|
||||
? transtest( dt, "@E", "31:12:1987" )
|
||||
set date format to "DD:MM:YYYY"
|
||||
? transtest( dt, "@E", "31:12:1987")
|
||||
set date format to "YYYY:MM:DD"
|
||||
? transtest( dt, "@E", "31:12:1987")
|
||||
set date format to "YYYY:DD:MM"
|
||||
? transtest( dt, "@E", "31:12:1987")
|
||||
set date format to "YY:MM:DD"
|
||||
? transtest( dt, "@E", "31:12:87")
|
||||
set date format to "MM:DD:YY"
|
||||
? transtest( dt, "@E", "31:12:87")
|
||||
set date format to "DD:MM:YY"
|
||||
? transtest( dt, "@E", "31:12:87")
|
||||
set date format to "<YY:DD.MM>"
|
||||
? transtest( dt, "@E", "<31:12.87>")
|
||||
set date format to "|YY|MM|DD|"
|
||||
? transtest( dt, "@E", "|31|12|87|")
|
||||
set date format to "MM<DD>YY"
|
||||
? transtest( dt, "@E", "31<12>87")
|
||||
stop()
|
||||
#endif
|
||||
|
||||
? transtest( -5, "@(Z $###,##9.99", "( 5.00)" )
|
||||
? transtest( -10, "@)Z $###,##9.99", "$ (10.00)" )
|
||||
? transtest( -20, "@Z $###,##9.99", "$ -20.00" )
|
||||
? transtest(100,"9999.", " 100.")
|
||||
? transtest(1.1,"@B!99.99", "1.1 ")
|
||||
? transtest(12.345,"@R 99/99", " /12")
|
||||
? transtest( "1234567890", "@9", "1234567890")
|
||||
? transtest( 1234567890, "@9", " 1234567890")
|
||||
? transtest( 1234, "9 999", "1 234" )
|
||||
? transtest( 123.123456, "999.99.99.99", "123.12.45. " )
|
||||
? transtest( 123.123456, "$$$.$$.$$.$$", "123.12.45. " )
|
||||
? transtest( 123.123456, "***.**.**.**", "123.12.45. " )
|
||||
? transtest( 99999, "9.999", "*.***" )
|
||||
? transtest( 99, "*.***", "*.***" )
|
||||
? transtest( 12345, "9999.", "****." )
|
||||
stop()
|
||||
? transtest(-12345.00, "@(", "( 12345.00)")
|
||||
? transtest(-12345.00, "@)", " (12345.00)")
|
||||
? transtest(-123456789.00, "@(", "(123456789.00)")
|
||||
? transtest(-123456789.00, "@)", "(123456789.00)")
|
||||
? transtest(-1234567890, "@(", "( 1234567890)")
|
||||
? transtest(-1234567890, "@)", " (1234567890)")
|
||||
? transtest(-12345, "@( [999999]", "( 12345])")
|
||||
? transtest(-12345, "@) [999999]", "[(12345])")
|
||||
? transtest(-12345, "@( $999999", "( 12345)")
|
||||
? transtest(-12345, "@) $999999", "$(12345)")
|
||||
? transtest(-12345, "@( #999999", "( 12345)")
|
||||
? transtest(-12345, "@) #999999", " (12345)")
|
||||
? transtest(-12345, "@( $99999", "(12345)")
|
||||
? transtest(-12345, "@) $99999", "(12345)")
|
||||
? transtest(-12345, "@( #99999", "(12345)")
|
||||
? transtest(-12345, "@) #99999", "(12345)")
|
||||
? transtest(-12345, "@( 6798^999", "(7*8^***)")
|
||||
? transtest(-12345, "@( 9798^9999", "(718^2345)")
|
||||
stop()
|
||||
?
|
||||
tofix()
|
||||
return
|
||||
|
||||
proc tofix()
|
||||
? transtest( 134.24, "@E99,999.99", " 134,24" )
|
||||
? transtest( -134.24, "@E99,999.99", " -134,24" )
|
||||
? transtest(0.80,".9999", ".8000")
|
||||
? transtest(-0.80,".9999", ".****")
|
||||
? transtest(12345.123, "@X99", " 12345.123")
|
||||
? transtest(-12345.123, "@X99", " 12345.123 DB")
|
||||
? transtest( 123456.78, "@E", " 123456,78")
|
||||
? transtest(0,"@C 9.99", "0.00")
|
||||
? transtest(1.1,"@B!99.99", "1.1 ")
|
||||
? transtest(-12345, "@) [999999]", "[(12345])")
|
||||
? transtest(-12345, "@) $999999", "$(12345)")
|
||||
? transtest(-12345, "@) *999999", "*(12345)")
|
||||
? transtest(-12345, "@) #999999", " (12345)")
|
||||
? transtest(-12345, "@) *9$9*999]", "*($12345])")
|
||||
? transtest(-12345, "@) *999*999]", "* (12345])")
|
||||
? transtest(-12345, "@) 0999*999]", "0 (12345])")
|
||||
? transtest(-12345, "@) 1999*999]", "1 (12345])")
|
||||
? transtest(-12345, "@) *[99*999]", "([ 12345])")
|
||||
? transtest(-12345, "@) *****999]", "(**12345])")
|
||||
? transtest(-12345, "@) *1***999]", "(1*12345])")
|
||||
? transtest(-12345, "@) * 999999]", "* (12345])")
|
||||
? transtest( -5, "@(Z $###,##9.99", "( 5.00)" )
|
||||
? transtest( -10, "@)Z $###,##9.99", "$ (10.00)" )
|
||||
? transtest( -5, "@(Z $999,999.99", "( 5.00)" )
|
||||
? transtest( -10, "@)Z $999,999.99", "$ (10.00)" )
|
||||
? transtest( -5, "@(Z 999,999.99", "( 5.00)" )
|
||||
? transtest( -10, "@)Z 999,999.99", " (10.00)" )
|
||||
? transtest( -20, "@Z $###,##9.99", "$ -20.00" )
|
||||
? transtest(0.1,".9", ".1")
|
||||
? transtest(0.0,".9", ".0")
|
||||
? transtest(1,".9", ".*")
|
||||
? transtest(.456,".9", ".5")
|
||||
? transtest(123,"99.-", "**.-")
|
||||
stop()
|
||||
? transtest(-123.45,"999,999.99", " -123.45")
|
||||
? transtest(-123456.78,"999,999,999.99", " -123,456.78")
|
||||
? transtest(-123456.78,"$$$,$$$,$$$.$$", "$$ -123,456.78")
|
||||
? transtest(-123456.78,"***,***,***.**", "***-123,456.78")
|
||||
? transtest(123456.78,"@E 888,$$$,$$$.$$", "888.123.456,78")
|
||||
? transtest(123456.78,"@E 888x,$$$,$$$.$$", "888xx123.456,78")
|
||||
? transtest(123456.78,"@E 888x,,$$$,$$$.$$", "888xxx123.456,78")
|
||||
? transtest(123456.78,"@E 8,88x,,$$$,$$$.$$", "8.88xxx123.456,78")
|
||||
? transtest(123456.78,"@E 8,88x,,$$$,,$$$.$$", "8.88xxx123..456,78")
|
||||
? transtest(123456.78,"@E 8,88x,,$$$,,$$$.$$77,7", "8.88xxx123..456,7877,7")
|
||||
? transtest(123456,"@E 8,88x,,$$$,,$$$77,7", "8.88xxx123..45677,7")
|
||||
? transtest(123456,"@E -,999,999", " -123.456")
|
||||
? transtest(12345,"@E -,999,999", " - 12.345")
|
||||
? transtest(12345,"@E -,|999,999", " -| 12.345")
|
||||
? transtest(12345,"@E ^-,|999,999", "^^-| 12.345")
|
||||
? transtest(12345,"@E 1-,|999,999", "11-| 12.345")
|
||||
? transtest(12345,"@E |--,|999,999", "|---| 12.345")
|
||||
stop()
|
||||
? transtest(12.34,"@E 99'99", " '12")
|
||||
? transtest(12.34,"99,99,11", " 12,11")
|
||||
? transtest(12.34,"@E 99,99,11", " 12,11")
|
||||
? transtest(12.34,"@E 99,", "12,")
|
||||
? transtest(12.34,"@E 9,9", "1.2")
|
||||
? transtest(12.34,"@E ab,cd.ef9,9.99,.--", "abbcd,ef***,* ,.--")
|
||||
? transtest(12.34,"@E ab,cd,ef9,9.99,.--", "abbcddef1.2,34,.--")
|
||||
? transtest(12.34,"@E ,ab,cd,ef9,9.99,.--", ",abbcddef1.2,34,.--")
|
||||
? transtest(12.34,"@E ,,,,99,.99,.--", ",,,,12.,34,.--")
|
||||
? transtest(124.4,"@E ,,,,9,9.99,.--", ",,,,***,**,.--")
|
||||
? transtest( 1.2,"@E ,,,,*,*.**,.--", ",,,,**1,20,.--")
|
||||
? transtest(12.34,"@E ,,,,*,*.**,.--", ",,,,1.2,34,.--")
|
||||
? transtest(12.34,"@E ,,,,*,*.**,.--,--", ",,,,1.2,34,.--,--")
|
||||
? transtest(12.34,"@E ,,,,*,*,.,**", ",,,,1.2.,,34")
|
||||
? transtest(12.34,",,,,*,*,.,**", ",,,,1,2,..34")
|
||||
? transtest(12.34,",,,,*,*,.,*|,*", ",,,,1,2,..3||4")
|
||||
? transtest(12.34,",,,,*,*,.,*,*", ",,,,1,2,..3,4")
|
||||
? transtest(123.345678912,"@E 999.99.99,99.99.", "123,34,67.89, .")
|
||||
#ifdef __HARBOUR__
|
||||
? transtest( 1234567890123456789, "99999999999999999999", " 1234567890123456789" )
|
||||
? transtest( -1234567890123456789, "99999999999999999999", "-1234567890123456789" )
|
||||
#else
|
||||
? transtest( 1234567890123456789, "99999999999999999999", " 1234567890123457000" )
|
||||
? transtest( -1234567890123456789, "99999999999999999999", "-1234567890123457000" )
|
||||
#endif
|
||||
stop()
|
||||
set(_SET_DATEFORMAT,"YYYY/MM/DD")
|
||||
? transtest(12345678,"@D", "1234/56/78")
|
||||
set(_SET_DATEFORMAT,"YYYY.MM.DD")
|
||||
? transtest(1234.56789,"@D", "1234.56.9 ")
|
||||
set(_SET_DATEFORMAT,"YYYY.MM:DD")
|
||||
? transtest(1234.56789,"@D", "1234.56:79")
|
||||
? transtest(123.345678912,"@D ", " 123.34:57")
|
||||
set(_SET_DATEFORMAT,"MM-DD-YYYY")
|
||||
? transtest(.t.,"@RE <|,yY#lL,|>", "99-99-9999T")
|
||||
? transtest(.f.,"@RE <|,yY#lL,|>", "99-99-9999F")
|
||||
? transtest(.t.,"@RD <|,yY#lL,|>", "99-99-9999T")
|
||||
? transtest(.f.,"@RD <|,yY#lL,|>", "99-99-9999F")
|
||||
? transtest(.f.,"@DE <|,yY#lL,|>", "9")
|
||||
? transtest("abcdefghij","@S15! <XXXXXXXX>", "<BCDEFGHI>")
|
||||
? transtest("abcdefghij","@S0! <XXXXXXXX>", "<BCDEFGHI>")
|
||||
? transtest("abcdefghij","@S5! <XXXXXXXX>", "<BCDE")
|
||||
stop()
|
||||
set fixed on
|
||||
? transtest( 1234, , " 1234" )
|
||||
? transtest( 1234, "" , " 1234" )
|
||||
? transtest( 1234, "@" , " 1234" )
|
||||
? transtest( 1234, "@!", " 1234" )
|
||||
? transtest( -1234, , " -1234" )
|
||||
? transtest( -1234, "@" , " -1234" )
|
||||
#ifdef HB_C52_STRICT
|
||||
? transtest( round(123,0), , " 123.00" )
|
||||
? transtest( round(123,0), "@!", " 123.00" )
|
||||
? transtest( round(123.0,0), , " 123.00" )
|
||||
? transtest( round(123.0,0),"@!", " 123.00" )
|
||||
#endif
|
||||
stop()
|
||||
? transtest( 1234.567, , " 1234.57" )
|
||||
? transtest( 1234.567, "", " 1234.57" )
|
||||
? transtest( 1234.567, "@" , " 1234.57" )
|
||||
? transtest( 1234.567, "@!", " 1234.57" )
|
||||
? transtest( -1234.567, , " -1234.57" )
|
||||
? transtest( -1234.567, "@", " -1234.57" )
|
||||
? transtest( val("-1.0"), , "-1.00" )
|
||||
? transtest( val("-1.0"), "@", "-1.00" )
|
||||
? transtest( val("-123"), , " -123" )
|
||||
? transtest( val("-123"), "@", " -123" )
|
||||
? transtest( 0, , " 0" )
|
||||
? transtest( 0.0, , " 0.00" )
|
||||
? transtest( val("1"), , " 1" )
|
||||
? transtest( val("12"), , " 12" )
|
||||
? transtest( val("123"), , " 123" )
|
||||
? transtest( val("1234"), , " 1234" )
|
||||
stop()
|
||||
set decimal to 3
|
||||
? transtest( 0.0, , " 0.000" )
|
||||
? transtest( val("1"), , " 1" )
|
||||
? transtest( val("12"), , " 12" )
|
||||
? transtest( val("123"), , " 123" )
|
||||
? transtest( val("1234"), , " 1234" )
|
||||
set decimal to 4
|
||||
? transtest( 0.0, , " 0.0000" )
|
||||
? transtest( val("1"), , " 1" )
|
||||
? transtest( val("12"), , " 12" )
|
||||
? transtest( val("123"), , " 123" )
|
||||
? transtest( val("1234"), , " 1234" )
|
||||
set fixed off
|
||||
stop()
|
||||
? transtest( -1234, , " -1234" )
|
||||
? transtest( -1234, "@B", "-1234 " )
|
||||
? transtest( -1234, "@(", "( 1234)" )
|
||||
? transtest( -1234, "@)", " (1234)" )
|
||||
? transtest( -1234, "@B)", "(1234) " )
|
||||
? transtest( -1234, "@B(", "(1234) " )
|
||||
? transtest( "( 12)", "@B(", "( 12)" )
|
||||
? transtest( "( 12)", "@B)", "( 12)" )
|
||||
? transtest( " 12", "@B(", "12 " )
|
||||
? transtest( " 12", "@B)", "12 " )
|
||||
#ifdef __HARBOUR__
|
||||
? transtest( 1234, "@L", "0000001234" )
|
||||
? transtest( 1234, "@0", "0000001234" )
|
||||
? transtest( 1234, "@L(", "0000001234" )
|
||||
? transtest( 1234, "@0)", "0000001234" )
|
||||
? transtest( -1234, "@L(", "(000001234)" )
|
||||
? transtest( -1234, "@0)", "(000001234)" )
|
||||
/* please test it with FoxPro and xbase++ to check if they give the same result */
|
||||
? transtest( -1234, "@L", "-000001234" )
|
||||
? transtest( -1234, "@0", "-000001234" )
|
||||
#endif
|
||||
/* FlagShip extensions */
|
||||
? transtest( -1234, "@Z", " -1234" )
|
||||
? transtest( 1234, "@Z", " 1234" )
|
||||
? transtest( -1234, "@F", " -1234" )
|
||||
? transtest( 1234, "@F", " 1234" )
|
||||
? transtest( -1234, "@T", " -1234" )
|
||||
? transtest( 1234, "@T", " 1234" )
|
||||
|
||||
? transtest( 123456789.12, "@,39 999,999,999.99", "123,456,789.12" )
|
||||
? transtest( 123456789.12, "@,39 999,999,999.99", "123,456,789.12" )
|
||||
? transtest( 123.456, "@R 9 9 9.9", "1 2 3.5" )
|
||||
stop()
|
||||
return
|
||||
|
||||
#ifndef __HARBOUR__
|
||||
func stod(s)
|
||||
local cDf:=set(_SET_DATEFORMAT,"YYYY/MM/DD"), dt
|
||||
dt:=ctod(stuff(stuff(s,7,0,"/"),5,0,"/"))
|
||||
set(_SET_DATEFORMAT,cDf)
|
||||
return dt
|
||||
#endif
|
||||
@@ -197,7 +197,7 @@ FUNCTION Main_TRANS()
|
||||
TEST_LINE( Transform( HB_SToD("19101112") , "9#-9#/##" ) , "1910.11.12" )
|
||||
TEST_LINE( Transform( HB_SToD("19920101") , "" ) , "1992.01.01" )
|
||||
TEST_LINE( Transform( HB_SToD("19920101") , "DO THIS " ) , "1992.01.01" )
|
||||
TEST_LINE( Transform( HB_SToD("19920102") , "@E" ) , "02/01/1992" ) /* Bug in CA-Cl*pper, it returns: "2.91901.02" */
|
||||
TEST_LINE( Transform( HB_SToD("19920102") , "@E" ) , "02.01.1992" ) /* Bug in CA-Cl*pper, it returns: "2.91901.02" */
|
||||
TEST_LINE( Transform( 1234 , "@D 9999" ) , "1234.00.0 " )
|
||||
TEST_LINE( Transform( 1234 , "@BD 9999" ) , "1234.00.0 " )
|
||||
|
||||
@@ -216,7 +216,7 @@ FUNCTION Main_TRANS()
|
||||
TEST_LINE( Transform( HB_SToD("19101112") , "9#-9#/##" ) , "10.11.12" )
|
||||
TEST_LINE( Transform( HB_SToD("19920101") , "" ) , "92.01.01" )
|
||||
TEST_LINE( Transform( HB_SToD("19920101") , "DO THIS " ) , "92.01.01" )
|
||||
TEST_LINE( Transform( HB_SToD("19920102") , "@E" ) , "02/01/92" ) /* Bug in CA-Cl*pper, it returns: "01.92.02" */
|
||||
TEST_LINE( Transform( HB_SToD("19920102") , "@E" ) , "02.01.92" ) /* Bug in CA-Cl*pper, it returns: "01.92.02" */
|
||||
TEST_LINE( Transform( 1234 , "@D 9999" ) , "**.**.* " )
|
||||
TEST_LINE( Transform( 1234 , "@BD 9999" ) , "**.**.* " )
|
||||
|
||||
@@ -411,6 +411,21 @@ FUNCTION Main_TRANS()
|
||||
TEST_LINE( Transform("ABCDEFG", "@DB" ) , "AB.DE.G" )
|
||||
TEST_LINE( Transform(" CDEFG", "@DB" ) , ".DE.G " )
|
||||
TEST_LINE( Transform("ABCDEFG", "@DBZ" ) , " " )
|
||||
#ifdef __CLIPPER__
|
||||
/* CA-Cl*pper do not check result size and always exchanges
|
||||
* bytes 1-2 with bytes 4-5 for @E conversion. It's buffer overflow
|
||||
* bug and I do not want to replicate it inside our transform
|
||||
* implementation. It also causes that the results for for strings
|
||||
* smaller then 5 bytes behaves randomly.
|
||||
* In fact precise tests can show that it's not random behavior
|
||||
* but CA-Cl*pper uses static buffer for result and when current one
|
||||
* is smaller then 5 bytes then at 1-st two bytes are replaced with
|
||||
* 4-5 bytes from previous result which was length enough, f.e.:
|
||||
* ? transform( "0123456789", "" )
|
||||
* ? transform( "AB", "@E" )
|
||||
* ? transform( "ab", "@E" )
|
||||
* [druzus]
|
||||
*/
|
||||
TEST_LINE( Transform(".", "@E" ) , " " )
|
||||
TEST_LINE( Transform(",", "@E" ) , "." )
|
||||
TEST_LINE( Transform("..", "@E" ) , ","+Chr(0)+"" )
|
||||
@@ -423,6 +438,7 @@ FUNCTION Main_TRANS()
|
||||
TEST_LINE( Transform("JKL", "@ER ," ) , "L .JK. " )
|
||||
TEST_LINE( Transform("OPI", "@ER" ) , "I .OP. " )
|
||||
TEST_LINE( Transform("JKL", "@ER" ) , "L .JK. " )
|
||||
#endif
|
||||
TEST_LINE( Transform(CTOD(""), "@DB") , ". . " )
|
||||
TEST_LINE( Transform(CTOD(""), "@DBR uiuijk") , ".. . . " )
|
||||
TEST_LINE( Transform(100, "@B $99999") , "$ 100" )
|
||||
|
||||
Reference in New Issue
Block a user