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( <cText>, .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 93d3a46d84 (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
This commit is contained in:
Przemysław Czerpak
2014-12-29 20:27:15 +01:00
parent 8eb8cf62a7
commit bcbd37990b
7 changed files with 185 additions and 148 deletions

View File

@@ -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( <cText>, .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

View File

@@ -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

View File

@@ -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 )
{

View File

@@ -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 )

View File

@@ -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() ), ;

View File

@@ -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

View File

@@ -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