diff --git a/ChangeLog.txt b/ChangeLog.txt index c6bb88f327..0ea997c205 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -10,6 +10,52 @@ * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment */ +2015-10-02 16:45 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) + * include/hbapigt.h + * src/rtl/inkeyapi.c + + added new C function: + int hb_inkeyKeyExt( int iKey ); + It extracts function/edit key code value HB_KX_* from Harbour extended + key code. If passed keycode is not valid extended keycode which points + to function/edit key then 0 is returned. + + * include/harbour.hbx + * src/rtl/inkey.c + + added new PRG function hb_keyExt() - it's wrapper to hb_inkeyKeyExt() + + * include/harbour.hbx + * src/rtl/mlcfunc.c + ! restored original Cl*pper behavior in memo line functions, + test shows that inside MemoEdit() Cl*pper internally uses a little + bit different rules to format text then in memo line functions, + It's Cl*pper bug but hard to fix because any differences to Cl*pper + in this area cause that someone reports them as bug. So I decided + to leave original Cl*pper behavior for compatibility and add new + function which can be used in MemoEdit() and related code. + + added new memo line function: + hb_MLEval( , , [ =79 ], + [ =4 ], [ =.T. ], + [ ], [ @ ], [ @ ] ) -> + it formats texts using rules like in Cl*pper MemoEdit() not Cl*pper + memo lines functions. For each processed line is executed + with 2 parameters: and . It recognizes and accepts + any EOLs just like hb_ATokens( , .T. ) and strips or converts + soft CRs depending on word wrap mode. + + + * src/rtl/teditor.prg + * Use hb_MLEval() to format text + % minor optimization + + * src/rtl/memoedit.prg + * enabled Harbour extended key codes + * small optimization + ! fixed ME_BOTTOMRIGHT processing + ! fixed initial line size calculation + + * src/vm/thread.c + * removed dymmy code + 2015-09-30 11:18 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * src/vm/hvm.c ! added missing support for non MT builds in last commit diff --git a/include/harbour.hbx b/include/harbour.hbx index 872d5b60df..55e4ce8703 100644 --- a/include/harbour.hbx +++ b/include/harbour.hbx @@ -647,6 +647,7 @@ DYNAMIC hb_jsonEncode DYNAMIC hb_keyChar DYNAMIC hb_keyClear DYNAMIC hb_keyCode +DYNAMIC hb_keyExt DYNAMIC hb_keyIns DYNAMIC hb_keyLast DYNAMIC hb_keyMod @@ -692,6 +693,7 @@ DYNAMIC hb_MethodName DYNAMIC hb_MGetBounds DYNAMIC hb_MilliSeconds DYNAMIC hb_Minute +DYNAMIC hb_MLEval DYNAMIC hb_MMiddleDown DYNAMIC hb_mtvm DYNAMIC hb_mutexCreate diff --git a/include/hbapigt.h b/include/hbapigt.h index a5d1e03614..9ca88a67eb 100644 --- a/include/hbapigt.h +++ b/include/hbapigt.h @@ -314,6 +314,7 @@ extern HB_EXPORT void hb_inkeyExit( void ); /* reset inkey pool extern HB_EXPORT HB_SIZE hb_inkeyKeyString( int iKey, char * buffer, HB_SIZE nSize ); /* convert key value to string */ extern HB_EXPORT int hb_inkeyKeyStd( int iKey ); /* convert Harbour extended key code to cl*pper inkey code */ +extern HB_EXPORT int hb_inkeyKeyExt( int iKey ); /* extract function/edit key code value HB_KX_* from Harbour extended key code */ extern HB_EXPORT int hb_inkeyKeyMod( int iKey ); /* extract keyboard modifiers HB_KF_* from Harbour extended key code */ extern HB_EXPORT int hb_inkeyKeyVal( int iKey ); /* extract key/character code from Harbour extended key code */ diff --git a/src/rtl/inkey.c b/src/rtl/inkey.c index 82f7e9e080..f34288ac98 100644 --- a/src/rtl/inkey.c +++ b/src/rtl/inkey.c @@ -258,6 +258,11 @@ HB_FUNC( HB_KEYSTD ) hb_retni( hb_inkeyKeyStd( hb_parni( 1 ) ) ); } +HB_FUNC( HB_KEYEXT ) +{ + hb_retni( hb_inkeyKeyExt( hb_parni( 1 ) ) ); +} + HB_FUNC( HB_KEYMOD ) { hb_retni( hb_inkeyKeyMod( hb_parni( 1 ) ) ); diff --git a/src/rtl/inkeyapi.c b/src/rtl/inkeyapi.c index f7825dd02b..486737167a 100644 --- a/src/rtl/inkeyapi.c +++ b/src/rtl/inkeyapi.c @@ -508,3 +508,19 @@ int hb_inkeyKeyVal( int iKey ) return iValue; } + +int hb_inkeyKeyExt( int iKey ) +{ + int iValue = 0; + + HB_TRACE( HB_TR_DEBUG, ( "hb_inkeyKeyVal(%d)", iKey ) ); + + if( HB_INKEY_ISKEY( iKey ) ) + { + iValue = HB_INKEY_VALUE( iKey ); + if( iValue < 1 || iValue > ( int ) HB_SIZEOFARRAY( s_transKeyFun ) ) + iValue = 0; + } + + return iValue; +} diff --git a/src/rtl/memoedit.prg b/src/rtl/memoedit.prg index a10b9435bb..f732cdd77c 100644 --- a/src/rtl/memoedit.prg +++ b/src/rtl/memoedit.prg @@ -113,11 +113,12 @@ METHOD MemoInit( xUserFunction ) CLASS HBMemoEditor METHOD Edit() CLASS HBMemoEditor - LOCAL nKey + LOCAL nKey, nKeyStd // NOTE: K_ALT_W is not compatible with Cl*pper exit memo and save key, but I cannot discriminate // K_CTRL_W and K_CTRL_END from Harbour code. - LOCAL aConfigurableKeys := { K_CTRL_Y, K_CTRL_T, K_CTRL_B, K_CTRL_V, K_ALT_W, K_ESC } + LOCAL hConfigurableKeys := { K_CTRL_Y =>, K_CTRL_T =>, K_CTRL_B =>, ; + K_CTRL_V =>, K_ALT_W =>, K_ESC => } LOCAL bKeyBlock // If I have an user function I need to trap configurable keys and ask to @@ -128,18 +129,19 @@ METHOD Edit() CLASS HBMemoEditor // I need to test this condition here since I never block inside HBEditor:Edit() // if there is an user function - IF ( nKey := Inkey() ) == 0 + IF ( nKey := Inkey(, hb_bitOr( Set( _SET_EVENTMASK ), HB_INKEY_EXT ) ) ) == 0 ::IdleHook() - nKey := Inkey( 0 ) + nKey := Inkey( 0, hb_bitOr( Set( _SET_EVENTMASK ), HB_INKEY_EXT ) ) ENDIF + nKeyStd := hb_keyStd( nKey ) - IF ( bKeyBlock := SetKey( nKey ) ) != NIL + IF ( bKeyBlock := SetKey( nKeyStd ) ) != NIL Eval( bKeyBlock ) LOOP ENDIF // Is it a configurable key? - IF AScan( aConfigurableKeys, nKey ) > 0 + IF nKeyStd $ hConfigurableKeys ::HandleUserKey( nKey, ::xDo( iif( ::lDirty, ME_UNKEYX, ME_UNKEY ) ) ) ELSE ::super:Edit( nKey ) @@ -168,7 +170,7 @@ METHOD KeyboardHook( nKey ) CLASS HBMemoEditor ::HandleUserKey( nKey, ::xDo( iif( ::lDirty, ME_UNKEYX, ME_UNKEY ) ) ) ::lCallKeyboardHook := .F. - ELSEIF nKey == K_ESC + ELSEIF hb_keyStd( nKey ) == K_ESC IF ::lDirty .AND. Set( _SET_SCOREBOARD ) cBackScr := SaveScreen( 0, MaxCol() - 19, 0, MaxCol() ) @@ -214,13 +216,12 @@ METHOD HandleUserKey( nKey, nUdfReturn ) CLASS HBMemoEditor IF HB_ISNUMERIC( nKey ) // HBEditor is not able to handle keys with a value higher than 256, but I have to tell him // that user wants to save text - DO CASE - CASE nKey == K_ESC + IF hb_keyStd( nKey ) == K_ESC ::lSaved := .F. ::lExitEdit := .T. - CASE nKey <= 256 .OR. nKey == K_ALT_W .OR. HB_ULen( hb_keyChar( nKey ) ) > 0 + ELSE ::super:Edit( nKey ) - ENDCASE + ENDIF ELSE RETURN .F. ENDIF @@ -228,7 +229,8 @@ METHOD HandleUserKey( nKey, nUdfReturn ) CLASS HBMemoEditor CASE ME_DATA IF HB_ISNUMERIC( nKey ) - IF nKey <= 256 .OR. HB_ULen( hb_keyChar( nKey ) ) > 0 + /* TODO: convert nKey >=1 .and. nKey <= 31 to key value with unicode character */ + IF HB_ULen( hb_keyChar( nKey ) ) > 0 ::super:Edit( nKey ) ENDIF ELSE @@ -245,11 +247,11 @@ METHOD HandleUserKey( nKey, nUdfReturn ) CLASS HBMemoEditor EXIT CASE ME_WORDRIGHT - ::MoveCursor( K_CTRL_RIGHT ) + ::super:MoveCursor( K_CTRL_RIGHT ) EXIT CASE ME_BOTTOMRIGHT - ::MoveCursor( K_CTRL_END ) + ::super:MoveCursor( K_CTRL_END ) EXIT #ifndef HB_CLP_STRICT @@ -293,11 +295,10 @@ METHOD MoveCursor( nKey ) CLASS HBMemoEditor IF nKey == K_CTRL_W ::lSaved := .T. ::lExitEdit := .T. - ELSE - RETURN ::super:MoveCursor( nKey ) + RETURN .F. ENDIF - RETURN .F. + RETURN ::super:MoveCursor( nKey ) METHOD InsertState( lInsState ) CLASS HBMemoEditor @@ -334,7 +335,7 @@ FUNCTION MemoEdit( ; hb_default( @nLeft , 0 ) hb_default( @nRight , MaxCol() ) - hb_default( @nLineLength , nRight - nLeft + 1 ) + hb_default( @nLineLength , nRight - nLeft ) hb_default( @nTextBuffColumn , 0 ) hb_default( @nWindowColumn , nTextBuffColumn ) hb_default( @cString , "" ) diff --git a/src/rtl/mlcfunc.c b/src/rtl/mlcfunc.c index 50f531ce53..0bb2e10284 100644 --- a/src/rtl/mlcfunc.c +++ b/src/rtl/mlcfunc.c @@ -50,6 +50,7 @@ #include "hbapiitm.h" #include "hbapicdp.h" #include "hbset.h" +#include "hbvm.h" #define HB_EOL_BUFFER_SIZE 4 @@ -66,7 +67,6 @@ typedef struct HB_SIZE nLineLength; HB_SIZE nTabSize; HB_BOOL fWordWrap; - HB_BOOL fPos; int iEOLs; PHB_EOL_INFO pEOLs; PHB_CODEPAGE cdp; @@ -154,12 +154,11 @@ static HB_BOOL hb_mlInit( PHB_MLC_INFO pMLC, int iParAdd ) if( pMLC->pszString && nSize > 0 ) { pMLC->nOffset = pMLC->nMaxCol = pMLC->nMaxPos = pMLC->nCol = 0; - pMLC->fPos = HB_FALSE; pMLC->nLineLength = nSize; pMLC->nLen = hb_parclen( 1 ); - pMLC->nTabSize = hb_parnldef( 3 + iParAdd, 4 ); + pMLC->nTabSize = hb_parnsdef( 3 + iParAdd, 4 ); pMLC->fWordWrap = hb_parldef( 4 + iParAdd, 1 ); #ifdef HB_CLP_STRICT @@ -225,6 +224,8 @@ static HB_SIZE hb_mlGetLine( PHB_MLC_INFO pMLC ) { if( pMLC->nMaxCol && pMLC->nCol ) break; + if( pMLC->nOffset < pMLC->nMaxPos ) + nLastCol = pMLC->nCol; pMLC->nOffset += 2; if( ! pMLC->fWordWrap ) break; @@ -236,6 +237,8 @@ static HB_SIZE hb_mlGetLine( PHB_MLC_INFO pMLC ) i = hb_mlEol( pMLC ); if( i >= 0 ) { + if( pMLC->nOffset < pMLC->nMaxPos ) + nLastCol = pMLC->nCol; if( pMLC->nMaxCol == 0 ) pMLC->nOffset += pMLC->pEOLs[ i ].nLen; break; @@ -267,7 +270,7 @@ static HB_SIZE hb_mlGetLine( PHB_MLC_INFO pMLC ) { if( pMLC->fWordWrap ) { - if( pMLC->fPos && ( ch == ' ' || ch == HB_CHAR_HT ) ) + if( ch == ' ' || ch == HB_CHAR_HT ) break; else if( nBlankCol != 0 ) { @@ -281,7 +284,7 @@ static HB_SIZE hb_mlGetLine( PHB_MLC_INFO pMLC ) pMLC->nOffset = nLastPos; break; } - if( ch == ' ' || ch == HB_CHAR_HT ) + if( pMLC->nCol > 1 && ( ch == ' ' || ch == HB_CHAR_HT ) ) { nBlankCol = pMLC->nCol; nBlankPos = pMLC->nOffset; @@ -439,15 +442,19 @@ HB_FUNC( MLPOS ) { if( hb_mlInit( &MLC, 1 ) ) { - MLC.fPos = HB_TRUE; - - while( --nLine && hb_mlGetLine( &MLC ) ) - ; - nOffset = MLC.nOffset; - if( MLC.cdp ) - nOffset = hb_cdpTextLen( MLC.cdp, MLC.pszString, nOffset ); - if( MLC.nOffset < MLC.nLen ) - ++nOffset; + while( --nLine ) + { + if( ! hb_mlGetLine( &MLC ) ) + break; + } + if( nLine <= 1 ) + { + nOffset = MLC.nOffset; + if( MLC.cdp ) + nOffset = hb_cdpTextLen( MLC.cdp, MLC.pszString, nOffset ); + if( MLC.nOffset < MLC.nLen ) + ++nOffset; + } hb_mlExit( &MLC ); } } @@ -472,10 +479,11 @@ HB_FUNC( MLCTOPOS ) { if( MLC.nLineLength > 4 ) { - MLC.fPos = HB_TRUE; - - while( --nLine && hb_mlGetLine( &MLC ) ) - ; + while( --nLine ) + { + if( ! hb_mlGetLine( &MLC ) ) + break; + } if( nCol && nLine == 0 ) { MLC.nMaxCol = nCol; @@ -534,3 +542,165 @@ HB_FUNC( MPOSTOLC ) hb_storvns( nLine, -1, 1 ); hb_storvns( nCol, -1, 2 ); } + +/* hb_MLEval( , , [ =79 ], + * [ =4 ], [ =.T. ], + * [ ], [ @ ], [ @ ] ) -> + */ +HB_FUNC( HB_MLEVAL ) +{ + const char * pszString = hb_parc( 1 ); + PHB_ITEM pBlock = hb_param( 2, HB_IT_EVALITEM ); + HB_ISIZ nSize = hb_parnsdef( 3, 79 ); + HB_SIZE nRowPos = 0, nColPos = 0, nLines = 0; + + if( pszString && pBlock && nSize > 0 ) + { + HB_SIZE nOffset = 0; + HB_SIZE nLineLength = nSize; + HB_SIZE nLen = hb_parclen( 1 ); + HB_SIZE nTabSize = hb_parnsdef( 4, 4 ); + HB_SIZE nPos = hb_parns( 6 ) - 1; + HB_BOOL fWordWrap = hb_parldef( 5, 1 ); + PHB_CODEPAGE cdp = hb_vmCDP(); + PHB_ITEM pLineItem = NULL, pSoftItem = NULL; + HB_BOOL fSoftCR; + char * pszLine; + + if( ! HB_CDP_ISCHARIDX( cdp ) ) + cdp = NULL; + +#ifdef HB_CLP_STRICT + if( nLineLength > 254 ) + nLineLength = 79; +#else + if( nLineLength > 0xFFFF ) + nLineLength = 0xFFFF; +#endif + if( nTabSize >= nLineLength ) + nTabSize = nLineLength - 1; + if( nTabSize == 0 ) + nTabSize = 1; + + pszLine = ( char * ) hb_xgrab( nLineLength + 1 ); + + do + { + HB_SIZE nBlankCol = 0, nBlankPos = 0, nBlankDst = 0, nCol = 0, nDst = 0; + + fSoftCR = HB_FALSE; + ++nLines; + do + { + HB_SIZE nRepl; + HB_WCHAR ch; + + if( pszString[ nOffset ] == HB_CHAR_SOFT1 && + pszString[ nOffset + 1 ] == HB_CHAR_SOFT2 ) + { + nOffset += 2; + if( fWordWrap ) + continue; + break; + } + else if( pszString[ nOffset ] == HB_CHAR_CR ) + { + ++nOffset; + if( pszString[ nOffset ] == HB_CHAR_LF ) + ++nOffset; + break; + } + else if( pszString[ nOffset ] == HB_CHAR_LF ) + { + ++nOffset; + if( pszString[ nOffset ] == HB_CHAR_CR ) + ++nOffset; + break; + } + + if( cdp ) + { + if( ! HB_CDPCHAR_GET( cdp, pszString, nLen, &nOffset, &ch ) ) + continue; + if( ! HB_CDPCHAR_PUT( cdp, pszLine, nLineLength + 1, &nDst, ch ) ) + break; + } + else + ch = pszLine[ nDst++ ] = pszString[ nOffset++ ]; + + if( nRowPos == 0 && nOffset > nPos ) + { + nRowPos = nLines; + nColPos = nCol; + } + + if( ch == ' ' || ch == HB_CHAR_HT ) + { + nBlankPos = nOffset; + nBlankCol = nCol; + nBlankDst = nDst; + } + + nRepl = ch == HB_CHAR_HT ? nTabSize - ( nCol % nTabSize ) -1 : 0; + for( ;; ) + { + if( ++nCol >= nLineLength ) + { + if( fWordWrap && nBlankCol > 0 ) + { + nOffset = nBlankPos; + nCol = nBlankCol; + nDst = nBlankDst; + if( nOffset <= nPos ) + nRowPos = nColPos = 0; + } + fSoftCR = HB_TRUE; + break; + } + if( nRepl-- == 0 ) + break; + if( !cdp ) + pszLine[ nDst++ ] = ch; + else if( ! HB_CDPCHAR_PUT( cdp, pszLine, nLineLength + 1, &nDst, ch ) ) + break; + } + } + while( ! fSoftCR && nOffset < nLen ); + + if( nRowPos == 0 && nOffset >= nPos && ! fSoftCR ) + { + nRowPos = nLines; + nColPos = nCol; + } + + pLineItem = hb_itemPutCL( pLineItem, pszLine, nDst ); + pSoftItem = hb_itemPutL( pSoftItem, fSoftCR ); + hb_vmEvalBlockV( pBlock, 2, pLineItem, pSoftItem ); + } + while( nOffset < nLen && hb_vmRequestQuery() == 0 ); + + if( nRowPos == 0 && nOffset >= nPos ) + { + nRowPos = nLines + 1; + nColPos = 0; + } + + if( fSoftCR ) + { + pLineItem = hb_itemPutC( pLineItem, NULL ); + pSoftItem = hb_itemPutL( pSoftItem, HB_FALSE ); + hb_vmEvalBlockV( pBlock, 2, pLineItem, pSoftItem ); + } + + hb_itemRelease( pLineItem ); + hb_itemRelease( pSoftItem ); + hb_xfree( pszLine ); + } + + if( hb_vmRequestQuery() == 0 ) + { + hb_storns( nRowPos, 7 ); + hb_storns( nColPos, 8 ); + hb_retns( nLines ); + } +} diff --git a/src/rtl/teditor.prg b/src/rtl/teditor.prg index bfe8fc006e..c18bb07812 100644 --- a/src/rtl/teditor.prg +++ b/src/rtl/teditor.prg @@ -485,8 +485,8 @@ METHOD Edit( nPassedKey ) CLASS HBEditor hb_keyChar( nKey ) ) ) > 0 ::lDirty := .T. oLine := ::aText[ ::nRow ] - IF ::nCol > hb_ULen( oLine:cText ) + 1 - oLine:cText += Space( ::nCol - hb_ULen( oLine:cText ) - 1 ) + IF ( nPos := ::nCol - hb_ULen( oLine:cText ) - 1 ) > 0 + oLine:cText += Space( nPos ) ENDIF oLine:cText := hb_UStuff( oLine:cText, ::nCol, ; iif( Set( _SET_INSERT ), 0, 1 ), cKey ) @@ -644,27 +644,25 @@ METHOD IdleHook() CLASS HBEditor METHOD ReformParagraph() CLASS HBEditor LOCAL lNext := .T. - LOCAL cLine := "" - LOCAL nLine - LOCAL nLines - LOCAL aPos + LOCAL cText := "" + LOCAL nLine, nRow, nCol + nCol := Min( hb_ULen( ::aText[ ::nRow ]:cText ) + 1, ::nCol ) DO WHILE lNext .AND. ::nRow <= Len( ::aText ) - cLine += ::aText[ ::nRow ]:cText + cText += ::aText[ ::nRow ]:cText lNext := ::aText[ ::nRow ]:lSoftCR ::RemoveLine( ::nRow ) ENDDO - nLines := MLCount( cLine, ::nWordWrapCol + 1, ::nTabWidth ) - aPos := MPosToLC( cLine, ::nWordWrapCol + 1, ::nCol, ::nTabWidth ) - IF ::nRow + aPos[ 1 ] - 1 > ::LineCount + nLines - ++nLines - ENDIF - FOR nLine := 1 TO nLines - ::InsertLine( MemoLine( cLine, ::nWordWrapCol + 1, nLine, ::nTabWidth,,, .F. ), ; - nLine < nLines, ::nRow + nLine - 1 ) - NEXT - RETURN ::GoTo( ::nRow + aPos[ 1 ] - 1, aPos[ 2 ] + 1, _REFRESH_ALL ) + nLine := ::nRow + hb_MLEval( cText, {| cLine, lSoftCR | ::InsertLine( cLine, lSoftCR, nLine++ ) }, ; + ::nWordWrapCol + 1, ::nTabWidth,, nCol, @nRow, @nCol ) + IF nRow > 0 + ::nRow += nRow - 1 + ::nCol := nCol + 1 + ENDIF + + RETURN ::GoTo( ::nRow, ::nCol, _REFRESH_ALL ) // Changes insert state and insertion / overstrike mode of editor METHOD InsertState( lInsState ) CLASS HBEditor @@ -744,21 +742,11 @@ METHOD hitTest( nMRow, nMCol ) CLASS HBEditor STATIC FUNCTION Text2Array( cText, nWordWrapCol, nTabWidth ) LOCAL aArray := {} - LOCAL cLine - LOCAL nLines - LOCAL nLine - FOR EACH cLine IN hb_ATokens( cText, .T. ) - IF nWordWrapCol != NIL .AND. hb_ULen( cLine ) > nWordWrapCol - nLines := MLCount( cLine, nWordWrapCol + 1, nTabWidth ) - FOR nLine := 1 TO nLines - AAdd( aArray, HBTextLine():New( MemoLine( cLine, nWordWrapCol + 1, nLine, nTabWidth,,, .F. ), ; - nLine < nLines ) ) - NEXT - ELSE - AAdd( aArray, HBTextLine():New( cLine, .F. ) ) - ENDIF - NEXT + hb_MLEval( cText, {| cLine, lSoftCR | AAdd( aArray, HBTextLine():New( cLine, lSoftCR ) ) }, ; + iif( nWordWrapCol != NIL, nWordWrapCol + 1, 0xFFFF ), ; + nTabWidth, nWordWrapCol != NIL ) + IF Empty( aArray ) AAdd( aArray, HBTextLine():New() ) ENDIF diff --git a/src/vm/thread.c b/src/vm/thread.c index 720cd6416a..3fde9c5844 100644 --- a/src/vm/thread.c +++ b/src/vm/thread.c @@ -757,10 +757,6 @@ HB_BOOL hb_threadCondTimedWait( HB_COND_T * cond, HB_CRITICAL_T * mutex, HB_ULON return HB_COND_TIMEDWAIT( cond, mutex, ulMilliSec ) != 0; -#elif defined( HB_TASK_THREAD ) - - return HB_COND_WAIT( cond, mutex ) != 0; - #elif defined( HB_PTHREAD_API ) struct timespec ts;