diff --git a/ChangeLog.txt b/ChangeLog.txt index 52714db69b..b9fd0465bb 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -10,6 +10,36 @@ * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment */ +2014-12-29 20:27 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) + * include/hbznet.h + * src/rtl/hbinet.c + * src/rtl/hbinetz.c + * moved HB_INET_ERR_* macros to header file + + added error and errorStr functions to hb_inet*() socket read/write + wrappers + ! call close function of hb_inet*() socket read/write wrappers before + closing the socket + + added hb_znetInetFD() C function + + * src/rtl/teditor.prg + ! use hb_ATokens( , .T. ) and MemoLine() to divide text into lines + to improve performance and fix TABs decoding + + * src/rtl/memoedit.prg + * src/rtl/teditor.prg + * applied recent fixes and cleanups from Viktor's branch. + + * src/rtl/tgetlist.prg + * applied recent fixes from Viktor's branch: + ; (2014-12-19 01:00 UTC+0100 Viktor Szakats) + ! HBGetList():GUIApplyKey(): fixed bug introduced with UNICODE + support in 93d3a46d843daaf6d08149d83fa5203ff910c484 (upstream). + That patch had an undocumented workaround for the problem inside + ListBox():findText(), which was not Cl*pper compatible, so + it was later removed in 6f8508ff54a3955822b36bf4a65a2775a11bab23. + This patch hopefully fixes the root cause. + Reported here: https://groups.google.com/d/msg/harbour-devel/7Cpax5TdHnY/n5XfXX8N9vMJ + 2014-12-15 15:48 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * src/rtl/hbtoken.c * cleaner version of recent hb_tokenPtr() fix which works correctly diff --git a/include/hbznet.h b/include/hbznet.h index 78b9ae7075..6f0d215c88 100644 --- a/include/hbznet.h +++ b/include/hbznet.h @@ -53,6 +53,12 @@ HB_EXTERN_BEGIN +#define HB_INET_ERR_OK 0 +#define HB_INET_ERR_TIMEOUT ( -1 ) +#define HB_INET_ERR_CLOSEDCONN ( -2 ) +#define HB_INET_ERR_BUFFOVERRUN ( -3 ) +#define HB_INET_ERR_CLOSEDSOCKET ( -4 ) + #if defined( _HB_ZNET_INTERNAL_ ) struct _HB_ZNETSTREAM; typedef struct _HB_ZNETSTREAM * PHB_ZNETSTREAM; @@ -60,10 +66,12 @@ HB_EXTERN_BEGIN typedef void * PHB_ZNETSTREAM; #endif -typedef long ( * HB_INET_SFUNC ) ( PHB_ZNETSTREAM, HB_SOCKET, const void *, long, HB_MAXINT, long * ); -typedef long ( * HB_INET_RFUNC ) ( PHB_ZNETSTREAM, HB_SOCKET, void *, long, HB_MAXINT ); -typedef long ( * HB_INET_FFUNC ) ( PHB_ZNETSTREAM, HB_SOCKET, HB_MAXINT ); -typedef void ( * HB_INET_CFUNC ) ( PHB_ZNETSTREAM ); +typedef long ( * HB_INET_RDFUNC ) ( PHB_ZNETSTREAM, HB_SOCKET, void *, long, HB_MAXINT ); +typedef long ( * HB_INET_WRFUNC ) ( PHB_ZNETSTREAM, HB_SOCKET, const void *, long, HB_MAXINT, long * ); +typedef long ( * HB_INET_FLFUNC ) ( PHB_ZNETSTREAM, HB_SOCKET, HB_MAXINT ); +typedef void ( * HB_INET_CLFUNC ) ( PHB_ZNETSTREAM ); +typedef int ( * HB_INET_ERFUNC ) ( PHB_ZNETSTREAM ); +typedef const char * ( * HB_INET_ESFUNC ) ( PHB_ZNETSTREAM, int ); extern HB_EXPORT PHB_ZNETSTREAM hb_znetOpen( int level, int strategy ); extern HB_EXPORT void hb_znetEncryptKey( PHB_ZNETSTREAM pStream, const void * keydata, int keylen ); @@ -73,11 +81,14 @@ extern HB_EXPORT long hb_znetRead( PHB_ZNETSTREAM pStream, HB_SOCKET sd, void extern HB_EXPORT long hb_znetFlush( PHB_ZNETSTREAM pStream, HB_SOCKET sd, HB_MAXINT timeout ); extern HB_EXPORT long hb_znetWrite( PHB_ZNETSTREAM pStream, HB_SOCKET sd, const void * buffer, long len, HB_MAXINT timeout, long * plast ); +extern HB_EXPORT HB_SOCKET hb_znetInetFD( PHB_ITEM pItem, HB_BOOL fError ); extern HB_EXPORT HB_BOOL hb_znetInetInitialize( PHB_ITEM, PHB_ZNETSTREAM, - HB_INET_RFUNC, - HB_INET_SFUNC, - HB_INET_FFUNC, - HB_INET_CFUNC ); + HB_INET_RDFUNC, + HB_INET_WRFUNC, + HB_INET_FLFUNC, + HB_INET_CLFUNC, + HB_INET_ERFUNC, + HB_INET_ESFUNC ); HB_EXTERN_END diff --git a/src/rtl/hbinet.c b/src/rtl/hbinet.c index 50a4ae65f3..2e9a3f2956 100644 --- a/src/rtl/hbinet.c +++ b/src/rtl/hbinet.c @@ -64,12 +64,6 @@ #include "hbthread.h" #include "hbznet.h" -#define HB_INET_ERR_OK 0 -#define HB_INET_ERR_TIMEOUT ( -1 ) -#define HB_INET_ERR_CLOSEDCONN ( -2 ) -#define HB_INET_ERR_BUFFOVERRUN ( -3 ) -#define HB_INET_ERR_CLOSEDSOCKET ( -4 ) - typedef struct { HB_SOCKET sd; @@ -85,10 +79,12 @@ typedef struct int iTimeLimit; PHB_ITEM pPeriodicBlock; PHB_ZNETSTREAM stream; - HB_INET_RFUNC recvFunc; - HB_INET_SFUNC sendFunc; - HB_INET_FFUNC flushFunc; - HB_INET_CFUNC cleanFunc; + HB_INET_RDFUNC recvFunc; + HB_INET_WRFUNC sendFunc; + HB_INET_FLFUNC flushFunc; + HB_INET_CLFUNC cleanFunc; + HB_INET_ERFUNC errorFunc; + HB_INET_ESFUNC errstrFunc; } HB_SOCKET_STRUCT, * PHB_SOCKET_STRUCT; #define HB_INET_BUFFER_LEN 1500 @@ -143,20 +139,29 @@ static HB_BOOL hb_inetIsOpen( PHB_SOCKET_STRUCT socket ) return HB_TRUE; } -static int hb_inetCloseSocket( PHB_SOCKET_STRUCT socket ) +static int s_inetGetError( PHB_SOCKET_STRUCT socket ) { - int ret = hb_socketClose( socket->sd ); + int iError; - socket->sd = HB_NO_SOCKET; - socket->inbuffer = 0; - return ret; + if( socket->errorFunc ) + iError = socket->errorFunc( socket->stream ); + else + { + iError = hb_socketGetError(); + if( iError == HB_SOCKET_ERR_TIMEOUT ) + iError = HB_INET_ERR_TIMEOUT; + } + return iError; +} + +static HB_BOOL s_inetIsTimeout( PHB_SOCKET_STRUCT socket ) +{ + return s_inetGetError( socket ) == HB_SOCKET_ERR_TIMEOUT; } static void hb_inetGetError( PHB_SOCKET_STRUCT socket ) { - socket->iError = hb_socketGetError(); - if( socket->iError == HB_SOCKET_ERR_TIMEOUT ) - socket->iError = HB_INET_ERR_TIMEOUT; + socket->iError = s_inetGetError( socket ); } static void hb_inetCloseStream( PHB_SOCKET_STRUCT socket ) @@ -171,15 +176,30 @@ static void hb_inetCloseStream( PHB_SOCKET_STRUCT socket ) socket->stream = NULL; } +static int hb_inetCloseSocket( PHB_SOCKET_STRUCT socket, HB_BOOL fShutDown ) +{ + int ret; + + hb_inetCloseStream( socket ); + + if( fShutDown ) + hb_socketShutdown( socket->sd, HB_SOCKET_SHUT_RDWR ); + + ret = hb_socketClose( socket->sd ); + + socket->sd = HB_NO_SOCKET; + socket->inbuffer = 0; + return ret; +} + static HB_GARBAGE_FUNC( hb_inetSocketFinalize ) { PHB_SOCKET_STRUCT socket = ( PHB_SOCKET_STRUCT ) Cargo; if( socket->sd != HB_NO_SOCKET ) - { - hb_socketShutdown( socket->sd, HB_SOCKET_SHUT_RDWR ); - hb_inetCloseSocket( socket ); - } + hb_inetCloseSocket( socket, HB_TRUE ); + else + hb_inetCloseStream( socket ); if( socket->pPeriodicBlock ) { @@ -196,7 +216,6 @@ static HB_GARBAGE_FUNC( hb_inetSocketFinalize ) hb_xfree( socket->buffer ); socket->buffer = NULL; } - hb_inetCloseStream( socket ); } static HB_GARBAGE_FUNC( hb_inetSocketMark ) @@ -231,11 +250,25 @@ static void hb_inetAutoInit( void ) } } +HB_SOCKET hb_znetInetFD( PHB_ITEM pItem, HB_BOOL fError ) +{ + PHB_SOCKET_STRUCT socket = ( PHB_SOCKET_STRUCT ) hb_itemGetPtrGC( pItem, &s_gcInetFuncs ); + + if( socket ) + return socket->sd; + else if( fError ) + hb_inetErrRT(); + + return HB_NO_SOCKET; +} + HB_BOOL hb_znetInetInitialize( PHB_ITEM pItem, PHB_ZNETSTREAM pStream, - HB_INET_RFUNC recvFunc, - HB_INET_SFUNC sendFunc, - HB_INET_FFUNC flushFunc, - HB_INET_CFUNC cleanFunc ) + HB_INET_RDFUNC recvFunc, + HB_INET_WRFUNC sendFunc, + HB_INET_FLFUNC flushFunc, + HB_INET_CLFUNC cleanFunc, + HB_INET_ERFUNC errorFunc, + HB_INET_ESFUNC errstrFunc ) { PHB_SOCKET_STRUCT socket = ( PHB_SOCKET_STRUCT ) hb_itemGetPtrGC( pItem, &s_gcInetFuncs ); @@ -247,6 +280,8 @@ HB_BOOL hb_znetInetInitialize( PHB_ITEM pItem, PHB_ZNETSTREAM pStream, socket->sendFunc = sendFunc; socket->flushFunc = flushFunc; socket->cleanFunc = cleanFunc; + socket->errorFunc = errorFunc; + socket->errstrFunc = errstrFunc; socket->stream = pStream; return HB_TRUE; } @@ -300,8 +335,7 @@ HB_FUNC( HB_INETCLOSE ) { if( socket->sd != HB_NO_SOCKET ) { - hb_socketShutdown( socket->sd, HB_SOCKET_SHUT_RDWR ); - hb_retni( hb_inetCloseSocket( socket ) ); + hb_retni( hb_inetCloseSocket( socket, HB_TRUE ) ); #ifdef HB_INET_LINUX_INTERRUPT kill( 0, HB_INET_LINUX_INTERRUPT ); #endif @@ -388,7 +422,10 @@ HB_FUNC( HB_INETERRORDESC ) case HB_INET_ERR_CLOSEDSOCKET : hb_retc_const( "Closed socket" ); return; case HB_INET_ERR_BUFFOVERRUN : hb_retc_const( "Buffer overrun" ); return; default: - hb_retc( hb_socketErrorStr( socket->iError ) ); + if( socket->errstrFunc ) + hb_retc( socket->errstrFunc( socket->stream, socket->iError ) ); + else + hb_retc( hb_socketErrorStr( socket->iError ) ); } } else @@ -706,7 +743,7 @@ static void s_inetRecvInternal( int iMode ) if( iMode == 0 ) /* Called from hb_inetRecv()? */ break; } - else if( iLen == -1 && hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT ) + else if( iLen == -1 && s_inetIsTimeout( socket ) ) { /* timed out; let's see if we have to run a cb routine */ iTimeElapsed += socket->iTimeout; @@ -794,7 +831,7 @@ static void s_inetRecvPattern( const char * const * patterns, int * patternsizes } iLen = s_inetRecv( socket, &cChar, 1, HB_TRUE, socket->iTimeout ); - if( iLen == -1 && hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT ) + if( iLen == -1 && s_inetIsTimeout( socket ) ) { iLen = -2; /* this signals timeout */ iTimeElapsed += socket->iTimeout; @@ -1030,7 +1067,7 @@ static void s_inetSendInternal( HB_BOOL lAll ) if( socket->flushFunc && ( lLastSnd > 0 || ( lLastSnd == -1 && socket->iTimeout >= 0 && socket->iTimeout < 10000 && - hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT ) ) ) + s_inetIsTimeout( socket ) ) ) ) { /* TODO: safe information about unflushed data and try to call flush before entering receive wait sate */ @@ -1138,7 +1175,7 @@ HB_FUNC( HB_INETSERVER ) if( ! socket ) HB_SOCKET_INIT( socket, pSocket ); else if( socket->sd != HB_NO_SOCKET ) - hb_inetCloseSocket( socket ); + hb_inetCloseSocket( socket, HB_FALSE ); socket->sd = hb_socketOpen( HB_SOCKET_PF_INET, HB_SOCKET_PT_STREAM, 0 ); if( socket->sd == HB_NO_SOCKET ) hb_inetGetError( socket ); @@ -1155,7 +1192,7 @@ HB_FUNC( HB_INETSERVER ) hb_socketListen( socket->sd, iListen ) != 0 ) { hb_inetGetError( socket ); - hb_inetCloseSocket( socket ); + hb_inetCloseSocket( socket, HB_FALSE ); } else socket->iError = HB_INET_ERR_OK; @@ -1219,7 +1256,7 @@ static void hb_inetConnectInternal( HB_BOOL fResolve ) if( ! socket ) HB_SOCKET_INIT( socket, pSocket ); else if( socket->sd != HB_NO_SOCKET ) - hb_inetCloseSocket( socket ); + hb_inetCloseSocket( socket, HB_FALSE ); if( fResolve ) szHost = szAddr = hb_socketResolveAddr( szHost, HB_SOCKET_AF_INET ); @@ -1310,7 +1347,7 @@ HB_FUNC( HB_INETDGRAMBIND ) s_inetBind( socket, socket->remote, socket->remotelen ) != 0 ) { hb_inetGetError( socket ); - hb_inetCloseSocket( socket ); + hb_inetCloseSocket( socket, HB_FALSE ); } else if( hb_pcount() >= 4 ) { diff --git a/src/rtl/hbinetz.c b/src/rtl/hbinetz.c index c2d3e6354b..92b1a20639 100644 --- a/src/rtl/hbinetz.c +++ b/src/rtl/hbinetz.c @@ -61,14 +61,14 @@ HB_FUNC( HB_INETCOMPRESS ) iStrategy = hb_parnidef( 3, HB_ZLIB_STRATEGY_DEFAULT ); if( iLevel == HB_ZLIB_COMPRESSION_DISABLE ) - hb_znetInetInitialize( pItem, NULL, NULL, NULL, NULL, NULL ); + hb_znetInetInitialize( pItem, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); else { PHB_ZNETSTREAM pStream = hb_znetOpen( iLevel, iStrategy ); if( pStream == NULL ) pItem = NULL; /* to force RTE */ if( hb_znetInetInitialize( pItem, pStream, hb_znetRead, hb_znetWrite, - hb_znetFlush, hb_znetClose ) ) + hb_znetFlush, hb_znetClose, NULL, NULL ) ) { int keylen = ( int ) hb_parclen( 4 ); if( keylen ) diff --git a/src/rtl/memoedit.prg b/src/rtl/memoedit.prg index 29ffba9a5b..5af83ae82a 100644 --- a/src/rtl/memoedit.prg +++ b/src/rtl/memoedit.prg @@ -133,9 +133,7 @@ METHOD Edit() CLASS HBMemoEditor // Is it a configurable key? IF AScan( aConfigurableKeys, nKey ) > 0 - IF ::HandleUserKey( nKey, ::xDo( iif( ::lDirty, ME_UNKEYX, ME_UNKEY ) ) ) - - ENDIF + ::HandleUserKey( nKey, ::xDo( iif( ::lDirty, ME_UNKEYX, ME_UNKEY ) ) ) ELSE ::super:Edit( nKey ) ENDIF @@ -201,8 +199,8 @@ METHOD IdleHook() CLASS HBMemoEditor METHOD HandleUserKey( nKey, nUdfReturn ) CLASS HBMemoEditor - DO CASE - CASE nUdfReturn == ME_DEFAULT + SWITCH nUdfReturn + CASE ME_DEFAULT // I won't reach this point during ME_INIT since ME_DEFAULT ends initialization phase of MemoEdit() @@ -219,8 +217,9 @@ METHOD HandleUserKey( nKey, nUdfReturn ) CLASS HBMemoEditor ELSE RETURN .F. ENDIF + EXIT - CASE nUdfReturn == ME_DATA + CASE ME_DATA IF HB_ISNUMERIC( nKey ) IF nKey <= 256 ::super:Edit( nKey ) @@ -228,25 +227,35 @@ METHOD HandleUserKey( nKey, nUdfReturn ) CLASS HBMemoEditor ELSE RETURN .F. ENDIF + EXIT - CASE nUdfReturn == ME_TOGGLEWRAP + CASE ME_TOGGLEWRAP ::lWordWrap := ! ::lWordWrap + EXIT - CASE nUdfReturn == ME_TOGGLESCROLL + CASE ME_TOGGLESCROLL // TODO: HBEditor does not support vertical scrolling of text inside window without moving cursor position + EXIT - CASE nUdfReturn == ME_WORDRIGHT + CASE ME_WORDRIGHT ::MoveCursor( K_CTRL_RIGHT ) + EXIT - CASE nUdfReturn == ME_BOTTOMRIGHT + CASE ME_BOTTOMRIGHT ::MoveCursor( K_CTRL_END ) + EXIT #ifndef HB_CLP_STRICT - CASE nUdfReturn == ME_PASTE /* Xbase++ compatibility */ + CASE ME_PASTE /* Xbase++ compatibility */ hb_gtInfo( HB_GTI_CLIPBOARDPASTE ) + EXIT #endif - CASE nUdfReturn != ME_IGNORE + CASE ME_IGNORE + /* do nothing */ + EXIT + + OTHERWISE // TOFIX: Not CA-Cl*pper compatible, see teditor.prg IF HB_ISNUMERIC( nKey ) .AND. ( ( nKey >= 1 .AND. nKey <= 31 ) .OR. nKey == K_ALT_W ) @@ -255,7 +264,7 @@ METHOD HandleUserKey( nKey, nUdfReturn ) CLASS HBMemoEditor RETURN .F. ENDIF - ENDCASE + ENDSWITCH RETURN .T. @@ -313,8 +322,7 @@ FUNCTION MemoEdit( ; hb_default( @nWindowColumn , nTextBuffColumn ) hb_default( @cString , "" ) - /* Original MemoEdit() converts tabs into spaces */ - oEd := HBMemoEditor():New( StrTran( cString, Chr( 9 ), Space( 1 ) ), ; + oEd := HBMemoEditor():New( cString, ; hb_defaultValue( nTop, 0 ), ; nLeft, ; hb_defaultValue( nBottom, MaxRow() ), ; diff --git a/src/rtl/teditor.prg b/src/rtl/teditor.prg index 33f3b8dba5..17ff050f6f 100644 --- a/src/rtl/teditor.prg +++ b/src/rtl/teditor.prg @@ -139,7 +139,7 @@ CREATE CLASS HBEditor VAR nNumCols AS NUMERIC INIT 1 // How many columns / rows can be displayed inside editor window VAR nNumRows AS NUMERIC INIT 1 - VAR nTabWidth AS NUMERIC INIT 8 // Size of Tab chars + VAR nTabWidth AS NUMERIC INIT 4 // Size of Tab chars VAR lEditAllow AS LOGICAL INIT .T. // Are changes to text allowed? VAR lSaved AS LOGICAL INIT .F. // True if user exited editor with K_CTRL_W VAR lWordWrap AS LOGICAL INIT .F. // True if word wrapping is active @@ -209,7 +209,7 @@ METHOD LoadFile( cFileName ) CLASS HBEditor cString := "" ENDIF - ::aText := Text2Array( cString, iif( ::lWordWrap, ::nNumCols, ) ) + ::aText := Text2Array( cString, iif( ::lWordWrap, ::nNumCols, ), ::nTabWidth ) ::naTextLen := Len( ::aText ) IF ::naTextLen == 0 @@ -224,7 +224,7 @@ METHOD LoadFile( cFileName ) CLASS HBEditor METHOD LoadText( cString ) CLASS HBEditor - ::aText := Text2Array( cString, iif( ::lWordWrap, ::nNumCols, ) ) + ::aText := Text2Array( cString, iif( ::lWordWrap, ::nNumCols, ), ::nTabWidth ) ::naTextLen := Len( ::aText ) IF ::naTextLen == 0 @@ -373,23 +373,14 @@ METHOD SplitLine( nRow ) CLASS HBEditor DO WHILE !( SubStr( cLine, --nFirstSpace, 1 ) == " " ) .AND. nFirstSpace > 1 ENDDO - // If there is a space before beginning of line split there - IF nFirstSpace > 1 - cSplitLine := Left( cLine, nFirstSpace ) - ELSE - // else split at current cursor position - cSplitLine := Left( cLine, ::nCol - 1 ) - ENDIF - - ::InsertLine( cSplitLine, .T., nStartRow++ ) - + ::InsertLine( cSplitLine := ; + Left( cLine, iif( nFirstSpace > 1, nFirstSpace, ::nCol - 1 ) ), .T., nStartRow++ ) ELSE // remainder of line - cSplitLine := cLine - ::InsertLine( cSplitLine, .F., nStartRow++ ) + ::InsertLine( cSplitLine := cLine, .F., nStartRow++ ) ENDIF - cLine := Right( cLine, Len( cLine ) - Len( cSplitLine ) ) + cLine := SubStr( cLine, Len( cSplitLine ) + 1 ) ENDDO IF lMoveToNextLine @@ -772,13 +763,15 @@ METHOD Edit( nPassedKey ) CLASS HBEditor ::RefreshLine() CASE nKey == K_BS - ::lDirty := .T. - // delete previous character - ::aText[ ::nRow ]:cText := Stuff( ::aText[ ::nRow ]:cText, --::nCol, 1, "" ) - // correct column position for next call to MoveCursor() - ::nCol++ - ::MoveCursor( K_LEFT ) - ::RefreshLine() + IF ::nCol > 1 + ::lDirty := .T. + // delete previous character + ::aText[ ::nRow ]:cText := Stuff( ::aText[ ::nRow ]:cText, --::nCol, 1, "" ) + // correct column position for next call to MoveCursor() + ::nCol++ + ::MoveCursor( K_LEFT ) + ::RefreshLine() + ENDIF CASE nKey == K_CTRL_Y ::lDirty := .T. @@ -1003,7 +996,7 @@ METHOD New( cString, nTop, nLeft, nBottom, nRight, lEditMode, nLineLength, nTabS nLineLength := NIL ENDIF - ::aText := Text2Array( hb_defaultValue( cString, "" ), nLineLength ) + ::aText := Text2Array( hb_defaultValue( cString, "" ), nLineLength, ::nTabWidth ) ::naTextLen := Len( ::aText ) IF ::naTextLen == 0 @@ -1038,7 +1031,7 @@ METHOD New( cString, nTop, nLeft, nBottom, nRight, lEditMode, nLineLength, nTabS ::nFirstRow := Max( 1, nTextRow - nWndRow ) ::nFirstCol := nTextCol - nWndCol + 1 - IF ::nFirstCol < 1 + IF ::nFirstCol < 1 nTextCol -= ::nFirstCol - 1 ::nFirstCol := 1 ENDIF @@ -1051,8 +1044,8 @@ METHOD New( cString, nTop, nLeft, nBottom, nRight, lEditMode, nLineLength, nTabS ::nFirstRow := ::naTextLen ENDIF - IF ( ::nFirstRow + nWndRow ) > ::naTextLen - DO WHILE ( ::nFirstRow + ( --nWndRow ) ) > ::naTextLen + IF ::nFirstRow + nWndRow > ::naTextLen + DO WHILE ::nFirstRow + --nWndRow > ::naTextLen ENDDO ENDIF @@ -1066,71 +1059,25 @@ METHOD New( cString, nTop, nLeft, nBottom, nRight, lEditMode, nLineLength, nTabS /* -------------------------------------------- */ -// Returns EOL char (be it either CR or LF or both) -STATIC FUNCTION WhichEOL( cString ) - - LOCAL nCRPos := At( Chr( 13 ), cString ) - LOCAL nLFPos := At( Chr( 10 ), cString ) - - IF nCRPos > 0 .AND. nLFPos == 0 - RETURN Chr( 13 ) - ELSEIF nCRPos == 0 .AND. nLFPos > 0 - RETURN Chr( 10 ) - ELSEIF nCRPos > 0 .AND. nLFPos == nCRPos + 1 - RETURN Chr( 13 ) + Chr( 10 ) - ENDIF - - RETURN hb_eol() - // Converts a string to an array of strings splitting input string at EOL boundaries -STATIC FUNCTION Text2Array( cString, nWordWrapCol ) +STATIC FUNCTION Text2Array( cString, nWordWrapCol, nTabWidth ) LOCAL aArray := {} - LOCAL cEOL := WhichEOL( cString ) - LOCAL nEOLLen := Len( cEOL ) - LOCAL nRetLen := 0 - LOCAL ncSLen := Len( cString ) - LOCAL nTokPos := 0 - LOCAL cLine - LOCAL nFirstSpace - LOCAL cSplitLine + LOCAL nLines + LOCAL nLine - DO WHILE nRetLen < ncSLen - - cLine := hb_tokenPtr( @cString, @nTokPos, cEOL ) - - nRetLen += Len( cLine ) + nEOLLen + FOR EACH cLine IN hb_ATokens( cString, .T. ) IF nWordWrapCol != NIL .AND. Len( cLine ) > nWordWrapCol - - DO WHILE ! Empty( cLine ) - - // Split line at nWordWrapCol boundary - IF Len( cLine ) > nWordWrapCol - - nFirstSpace := nWordWrapCol - DO WHILE !( SubStr( cLine, --nFirstSpace, 1 ) == " " ) .AND. nFirstSpace > 1 - ENDDO - - IF nFirstSpace > 1 - cSplitLine := Left( cLine, nFirstSpace ) - ELSE - cSplitLine := Left( cLine, nWordWrapCol ) - ENDIF - - AAdd( aArray, HBTextLine():New( cSplitLine, .T. ) ) - ELSE - // remainder of line is shorter than split point - cSplitLine := cLine - AAdd( aArray, HBTextLine():New( cSplitLine, .F. ) ) - ENDIF - - cLine := Right( cLine, Len( cLine ) - Len( cSplitLine ) ) - ENDDO + nLines := MLCount( cLine, nWordWrapCol, nTabWidth ) + FOR nLine := 1 TO nLines + AAdd( aArray, HBTextLine():New( MemoLine( cLine, nWordWrapCol, nLine, nTabWidth ), ; + nLine < nLines ) ) + NEXT ELSE AAdd( aArray, HBTextLine():New( cLine, .F. ) ) ENDIF - ENDDO + NEXT RETURN aArray diff --git a/src/rtl/tgetlist.prg b/src/rtl/tgetlist.prg index 24b5bfa49e..37ead20898 100644 --- a/src/rtl/tgetlist.prg +++ b/src/rtl/tgetlist.prg @@ -915,6 +915,7 @@ METHOD GUIReader( oGet, oMenu, aMsg ) CLASS HBGetList oGet:varPut( oGUI:value ) EXIT ENDIF + /* fall through */ OTHERWISE oGet:varPut( oGUI:buffer ) ENDSWITCH @@ -942,6 +943,7 @@ METHOD GUIApplyKey( oGet, oGUI, nKey, oMenu, aMsg ) CLASS HBGetList LOCAL nMRow LOCAL nMCol LOCAL nButton + LOCAL cKey // Check for SET KEY first IF ( bKeyBlock := SetKey( nKey ) ) != NIL @@ -1011,7 +1013,8 @@ METHOD GUIApplyKey( oGet, oGUI, nKey, oMenu, aMsg ) CLASS HBGetList nKey := 0 ENDIF - ELSEIF ( nButton := oGUI:FindText( hb_keyChar( nKey ), oGUI:Value + 1, .F., .F. ) ) != 0 + ELSEIF !( ( cKey := hb_keyChar( nKey ) ) == "" ) .AND. ; + ( nButton := oGUI:FindText( cKey, oGUI:Value + 1, .F., .F. ) ) != 0 oGUI:Select( nButton ) ENDIF @@ -1189,6 +1192,7 @@ METHOD GUIPostValidate( oGet, oGUI, aMsg ) CLASS HBGetList xNewValue := oGUI:value EXIT ENDIF + /* fall through */ OTHERWISE xNewValue := oGUI:buffer ENDSWITCH @@ -1210,7 +1214,7 @@ METHOD GUIPostValidate( oGet, oGUI, aMsg ) CLASS HBGetList SetPos( oGet:row, oGet:col ) ::ShowScoreBoard() - IF ! ( oGUI:ClassName() == "TBROWSE" ) + IF !( oGUI:ClassName() == "TBROWSE" ) oGUI:Select( oGet:varGet() ) ENDIF @@ -1219,7 +1223,7 @@ METHOD GUIPostValidate( oGet, oGUI, aMsg ) CLASS HBGetList __GetListLast( Self ) IF ::lKillRead - oGet:exitState := GE_ESCAPE // Provokes ReadModal() exit + oGet:exitState := GE_ESCAPE // Provokes ReadModal() exit lValid := .T. ENDIF