[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Implement this Harbour module: Harbour contribution module 'hbmzip' (ZIP file handling): contrib/hbmzip/tests/myzip.prg. Contains procedures: Main, ClipInit. This file provides utility functions

[Assistant]
#require "hbmzip"

#include "simpleio.ch"

REQUEST HB_CODEPAGE_UTF8EX

PROCEDURE Main( ... )

   LOCAL hZip, aDir, aFile, aWild, ;
      cZipName, cPath, cFileName, cExt, cWild, cPassword, cComment, ;
      tmp
   LOCAL lUnicode

   IF "--unicode" $ hb_CmdLine()
      hb_cdpSelect( "UTF8EX" )
      hb_SetTermCP( hb_cdpTerm() )
      Set( _SET_OSCODEPAGE, hb_cdpOS() )
      lUnicode := .T.
   ELSE
      lUnicode := .F.
   ENDIF

   aWild := { ... }
   IF Len( aWild ) < 2
      ? "Usage: myzip <ZipName> [ --pass <password> ] [ --unicode ] [ --comment <comment> ] <FilePattern1> [ <FilePattern2> ... ]"
      RETURN
   ENDIF

   hb_FNameSplit( aWild[ 1 ], @cPath, @cFileName, @cExt )
   IF Empty( cExt )
      cExt := ".zip"
   ENDIF
   cZipName := hb_FNameMerge( cPath, cFileName, cExt )

   hb_ADel( aWild, 1, .T. )

   FOR tmp := Len( aWild ) - 1 TO 1 STEP -1
      IF Lower( aWild[ tmp ] ) == "--pass"
         IF Empty( cPassword )
            cPassword := aWild[ tmp + 1 ]
         ENDIF
         aWild[ tmp ] := ""
         aWild[ tmp + 1 ] := ""
      ELSEIF Lower( aWild[ tmp ] ) == "--comment"
         IF Empty( cComment )
            cComment := aWild[ tmp + 1 ]
         ENDIF
         aWild[ tmp ] := ""
         aWild[ tmp + 1 ] := ""
      ELSEIF Lower( aWild[ tmp ] ) == "--unicode"

      ENDIF
   NEXT

   hZip := hb_zipOpen( cZipName )
   IF ! Empty( hZip )
      ? "Archive file:", cZipName
      FOR EACH cWild IN aWild
         IF ! Empty( cWild )
            hb_FNameSplit( cWild, @cPath, @cFileName, @cExt )
            aDir := hb_DirScan( cPath, cFileName + cExt )
            FOR EACH aFile IN aDir
               IF ! cPath + aFile[ 1 ] == cZipName
                  ? "Adding", cPath + aFile[ 1 ]
                  hb_zipStoreFile( hZip, cPath + aFile[ 1 ], cPath + aFile[ 1 ], cPassword,, lUnicode )
               ENDIF
            NEXT
         ENDIF
      NEXT
      hb_zipClose( hZip, cComment )
   ENDIF

   RETURN

INIT PROCEDURE ClipInit()

   IF "--unicode" $ hb_CmdLine()
      hb_cdpSelect( "UTF8EX" )
   ENDIF

   RETURN


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User]
Here is a Harbour (xBase/Clipper) implementation:

Harbour contribution module 'hbsqlit3' (SQLite3 database client library): contrib/hbsqlit3/tests/pack.prg. Contains procedures: Main. This file handles database operations

[Assistant]
#require "hbsqlit3"

PROCEDURE Main()

   LOCAL db := sqlite3_open_v2( "new.s3db", SQLITE_OPEN_READWRITE + SQLITE_OPEN_EXCLUSIVE )

   IF ! Empty( db )
      IF sqlite3_exec( db, "VACUUM" ) == SQLITE_OK
         ? "PACK - Done"

         sqlite3_sleep( 3000 )
      ENDIF
   ENDIF

   RETURN


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Implement this Harbour module: Harbour Runtime Library file: src/debug/dbgtinp.prg. Defines classes: HBDbInput. This file provides utility functions

[Assistant]
#pragma -b-

#define HB_CLS_NOTOBJECT
#include "hbclass.ch"

#include "inkey.ch"
#include "color.ch"
#include "setcurs.ch"

CREATE CLASS HBDbInput

   HIDDEN:

   VAR nRow    AS INTEGER
   VAR nCol    AS INTEGER
   VAR nWidth  AS INTEGER
   VAR nPos    AS INTEGER     INIT 1
   VAR nFirst  AS INTEGER     INIT 1
   VAR nSize   AS INTEGER
   VAR cValue  AS CHARACTER
   VAR acColor AS ARRAY

   EXPORTED:

   METHOD new( nRow, nCol, nWidth, cValue, cColor, nSize )
   METHOD applyKey( nKey )
   METHOD getValue()
   METHOD setValue( cValue )
   METHOD display()
   METHOD showCursor()
   METHOD newPos( nRow, nCol )
   METHOD setColor( cColor )

ENDCLASS

METHOD new( nRow, nCol, nWidth, cValue, cColor, nSize ) CLASS HBDbInput

   ::nRow   := nRow
   ::nCol   := nCol
   ::nWidth := nWidth
   ::nSize  := iif( HB_ISNUMERIC( nSize ), nSize, nWidth )
   ::cValue := PadR( cValue, ::nSize )

   ::setColor( cColor )

   RETURN Self

METHOD SetColor( cColor ) CLASS HBDbInput

   ::acColor := { hb_ColorIndex( cColor, CLR_STANDARD ), ;
                  hb_ColorIndex( cColor, CLR_ENHANCED ) }
   IF hb_ColorToN( ::acColor[ 2 ] ) == -1
      ::acColor[ 2 ] := ::acColor[ 1 ]
   ENDIF

   RETURN Self

METHOD newPos( nRow, nCol ) CLASS HBDbInput

   ::nRow := nRow
   ::nCol := nCol

   RETURN Self

METHOD getValue() CLASS HBDbInput
   RETURN ::cValue

METHOD setValue( cValue ) CLASS HBDbInput

   ::cValue := PadR( cValue, ::nSize )
   ::nPos := Min( ::nSize, Len( RTrim( ::cValue ) ) + 1 )

   RETURN Self

METHOD display() CLASS HBDbInput

   IF ::nPos < ::nFirst
      ::nFirst := ::nPos
   ELSEIF ::nPos - ::nFirst >= ::nWidth
      ::nFirst := ::nPos - ::nWidth + 1
   ENDIF
   hb_DispOutAt( ::nRow, ::nCol, SubStr( ::cValue, ::nFirst, ::nWidth ), ;
                 ::acColor[ 2 ] )

   RETURN Self

METHOD showCursor() CLASS HBDbInput

   SetPos( ::nRow, ::nCol + ::nPos - ::nFirst )
   SetCursor( iif( Set( _SET_INSERT ), SC_INSERT, SC_NORMAL ) )

   RETURN Self

METHOD applyKey( nKey ) CLASS HBDbInput

   LOCAL lUpdate := .T.

   SWITCH nKey
   CASE K_HOME
      ::nPos := 1
      EXIT
   CASE K_END
      ::nPos := Len( RTrim( ::cValue ) ) + 1
      IF ::nPos > ::nSize
         ::nPos := ::nSize
      ENDIF
      EXIT
   CASE K_LEFT
      IF ::nPos > 1
         ::nPos--
      ENDIF
      EXIT
   CASE K_RIGHT
      IF ::nPos < ::nSize
         ::nPos++
      ENDIF
      EXIT
   CASE K_DEL
      ::cValue := Stuff( ::cValue, ::nPos, 1, "" ) + " "
      EXIT
   CASE K_BS
      IF ::nPos > 1
         ::cValue := Stuff( ::cValue, --::nPos, 1, "" ) + " "
      ENDIF
      EXIT
   CASE K_CTRL_Y
   CASE K_CTRL_DEL
      ::cValue := Space( ::nSize )
      ::nPos := 1
      EXIT
   CASE K_INS
      Set( _SET_INSERT, ! Set( _SET_INSERT ) )
      EXIT
   OTHERWISE
      IF hb_keyChar( nKey ) == ""
         lUpdate := .F.
      ELSE
         IF Set( _SET_INSERT )
            ::cValue := Left( Stuff( ::cValue, ::nPos, 0, hb_keyChar( nKey ) ), ::nSize )
         ELSE
            ::cValue := Stuff( ::cValue, ::nPos, 1, hb_keyChar( nKey ) )
         ENDIF
         IF ::nPos < ::nSize
            ::nPos++
         ENDIF
      ENDIF
   ENDSWITCH

   IF lUpdate
      ::display()
   ENDIF

   RETURN Self


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Implement these Harbour functions: Harbour test program: tests/arrays.prg. Provides functions: Test, ReleaseTest. Contains procedures: Main. This test file exercises basic Harbour language features

[Assistant]
PROCEDURE Main()

   LOCAL a := { 100, 200, "Third" }
   LOCAL b := Array( 10000 )

   ? ValType( a )
   ? ValType( { "A" } )

   AAdd( a, "new element" )
   ? Len( a )

   ? a[ 1 ]
   ? a[ 2 ]
   ? a[ 3 ]
   ? a[ 4 ]

   ? ATail( a )

   a[ 3 ] := { "this", { "seems", "to", { "work", "so", "well" } } }
   ? a[ 3 ][ 2 ][ 3 ][ 1 ]

   a[ 3, 2 ][ 3, 1 ] := "Harbour power!"
   ? a[ 3, 2, 3, 1 ]

   ? ValType( b )
   ? Len( b )

   b[ 8000 ] := "Harbour"

   ? b[ 8000 ]

   ASize( b, 2000 )
   ? Len( b )

   b[ 1000 ] := 10
   Test( b[ 1000 ]++ )
   ? b[ 1000 ]

   b[ 1000 ] := 10
   Test( ++b[ 1000 ] )
   ? b[ 1000 ]

   b := { 1, { 2, { 4, 5 } } }
   Test( b[ 2 ][ 2 ][ 1 ]++ )
   ? b[ 2 ][ 2 ][ 1 ]

   b[ 2 ][ 2 ][ 1 ] := 2
   Test( ++b[ 2 ][ 2 ][ 1 ] )
   ? b[ 2 ][ 2 ][ 1 ]

   ReleaseTest()

   RETURN

FUNCTION Test( n )

   ? n

   RETURN NIL

FUNCTION ReleaseTest()

   LOCAL a := { 1, 2, 3 }

   HB_SYMBOL_UNUSED( a )

   RETURN NIL


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User]
Here is a Harbour (xBase/Clipper) implementation:

Harbour test program: tests/dates.prg. Contains procedures: Main, TestCentury. This test file exercises basic Harbour language features

[Assistant]
PROCEDURE Main()

   LOCAL dDate, dDate2, cMask, cDate

   ? "Testing Harbour dates management on", Date()

   TestCentury()

   ?
   ? "dDate := CToD( '02/04/1999' ) =>", dDate := CToD( "02/04/1999" )

   ? "ValType( dDate ) =", ValType( dDate )

   ? "Day( dDate ) =", Day( dDate )
   ? "Month( dDate ) =", Month( dDate )
   ? "Year( dDate ) =", Year( dDate )
   ?

   ? "dDate + 5 =", dDate2 := dDate + 5
   ? "dDate - 5 =", dDate - 5
   ?

   ? "dDate2 - dDate =", dDate2 - dDate

   ?
   ? dDate, DToS( dDate )

   ? "19990429", hb_SToD( "19990429" )

   ?
   Set( _SET_EPOCH, 1950 )
   cMask := "dd/mm/yyyy"
   cDate := "02/04/49"
   Set( _SET_DATEFORMAT, cMask )
   dDate := CToD( cDate )
   ? cDate, cMask, dDate, DToS( dDate ), DToC( dDate )

   ?
   cMask := "mm/dd/yyyy"
   Set( _SET_DATEFORMAT, cMask )
   dDate := CToD( cDate )
   ? cDate, cMask, dDate, DToS( dDate ), DToC( dDate )

   ?
   cMask := "yyyy/mm/dd"
   Set( _SET_DATEFORMAT, cMask )
   dDate := CToD( cDate )
   ? cDate, cMask, dDate, DToS( dDate ), DToC( dDate )
   ?
   ? "49/02/04", cMask, CToD( "49/02/04" )

   TestCentury()

   ?
   cMask := "yyyy/dd/mm"
   Set( _SET_DATEFORMAT, cMask )
   dDate := CToD( cDate )
   ? cDate, cMask, dDate, DToS( dDate ), DToC( dDate )
   ?
   ? "49/02/04", cMask, CToD( "49/02/04" )

   ?
   cMask := "ddd/mmm/yy"
   Set( _SET_DATEFORMAT, cMask )
   dDate := CToD( cDate )
   ? cDate, cMask, dDate, DToS( dDate ), DToC( dDate )

   RETURN

PROCEDURE TestCentury()

   ?
   ? __SetCentury()
   __SetCentury( "ON" )
   ?? __SetCentury()
   __SetCentury( "OFF" )
   ?? __SetCentury()
   __SetCentury( "GIBBERISH" )
   ?? __SetCentury()
   __SetCentury( .T. )
   ?? __SetCentury()
   __SetCentury( 5 )
   ?? __SetCentury()

   RETURN


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User]
Here is a Harbour (xBase/Clipper) implementation:

Harbour test program: tests/files.prg. Contains procedures: Main. This test file exercises basic Harbour language features

[Assistant]
#define NFILES   1000

#define WITH_DBFCDX

#ifdef WITH_ADS
#include "ads.ch"
REQUEST _ADS
#endif

PROCEDURE Main()

   LOCAL aCampos := { ;
      { "Codigo", "C",  6, 0 }, ;
      { "Nombre", "C", 35, 0 } }

   LOCAL n := 0, h := Array( NFILES )

#ifdef WITH_ADS

   rddRegister( "ADS", 1 )
   rddSetDefault( "ADS" )
   SET SERVER LOCAL
   SET FILETYPE TO CDX
   SET CHARTYPE TO OEM
   SET AXS LOCKING ON
   AdsRightsCheck( .F. )

#endif

   CLS
   AFill( h, 0 )
   DO WHILE n < NFILES
      n++
      @ 10, 0 SAY "Building files.... " + Str( n )
      dbCreate( "file" + hb_ntos( n ), aCampos )
      USE ( "file" + hb_ntos( n ) ) NEW

#ifdef WITH_ADS
      INDEX ON CODIGO TAG CODIGO TO ( "file" + hb_ntos( n ) )
#endif

      CLOSE DATA
   ENDDO

   n := 0

   DO WHILE n < NFILES
      n++
      @ 12, 0 SAY "Opening files.... " + Str( n )
      USE ( "file" + hb_ntos( n ) ) NEW

#ifdef WITH_ADS
      SET ORDER TO TAG CODIGO
#endif

   ENDDO

   CLOSE DATA

   n := 0

   DO WHILE n < NFILES
      n++
      @ 14, 0 SAY "Deleting files.... " + Str( n )
      hb_dbDrop( "file" + hb_ntos( n ) + ".dbf" )
   ENDDO

   RETURN


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Define Harbour macros and constants: Harbour contribution module 'hbtip' (Internet protocol utilities (FTP, HTTP, SMTP, POP3)): contrib/hbtip/thtml.prg. Defines classes: THtmlDocument, THtmlIterator. This file provides network protocol implementations

[Assistant]
#include "error.ch"
#include "hbclass.ch"
#include "thtml.ch"

#xtrans P_PARSER( <c> )       => { <c>, 0, Len( <c> ), 0 }
#xtrans :p_str                => \[ 1 ]
#xtrans :p_pos                => \[ 2 ]
#xtrans :p_len                => \[ 3 ]
#xtrans :p_end                => \[ 4 ]

#xtrans P_SEEK( <a>, <c> )    => ( <a>:p_end := <a>:p_pos, <a>:p_pos := hb_At( <c>, <a>:p_str, <a>:p_end + 1 ) )
#xtrans P_SEEKI( <a>, <c> )   => ( <a>:p_end := <a>:p_pos, <a>:p_pos := hb_AtI( <c>, <a>:p_str, <a>:p_end + 1 ) )
#xtrans P_PEEK( <a>, <c> )    => ( <a>:p_end := <a>:p_pos, hb_LeftEqI( SubStr( <a>:p_str, <a>:p_pos ), <c> ) )
#xtrans P_NEXT( <a> )         => ( <a>:p_end := <a>:p_pos, SubStr( <a>:p_str, ++<a>:p_pos, 1 ) )
#xtrans P_PREV( <a> )         => ( <a>:p_end := <a>:p_pos, SubStr( <a>:p_str, --<a>:p_pos, 1 ) )

#define S_DATA                1
#define S_NUM                 2
#define S_SIZE                3
#define S_STEP                4

#xtrans S_STACK()             => S_STACK( 64 )
#xtrans S_STACK( <n> )        => { Array( <n> ), 0, <n>, Max( 32, Int( <n> / 2 ) ) }
#xtrans S_GROW( <a> )         => ( iif( ++<a>\[S_NUM] > <a>\[S_SIZE], ASize( <a>\[S_DATA], ( <a>\[S_SIZE] += <a>\[S_STEP] ) ), <a> ) )
#xtrans S_SHRINK( <a> )       => ( iif( <a>\[S_NUM] > 0 .AND. --<a>\[S_NUM] \< <a>\[S_SIZE] - <a>\[S_STEP], ASize( <a>\[S_DATA], <a>\[S_SIZE] -= <a>\[S_STEP] ), <a> ) )
#xtrans S_COMPRESS( <a> )     => ( ASize( <a>\[S_DATA], <a>\[S_SIZE] := <a>\[S_NUM] ) )
#xtrans S_PUSH( <a>, <x> )    => ( S_GROW( <a> ), <a>\[S_DATA, <a>\[S_NUM]] := <x> )
#xtrans S_POP( <a>, @<x> )    => ( <x> := <a>\[S_DATA, <a>\[S_NUM]], <a>\[S_DATA, <a>\[S_NUM]] := NIL, S_SHRINK( <a> ) )
#xtrans S_POP( <a> )          => ( <a>\[S_DATA, <a>\[S_NUM]] := NIL, S_SHRINK( <a> ) )
#xtrans S_TOP( <a> )          => ( <a>\[S_DATA, <a>\[S_NUM]] )

THREAD STATIC t_aHA
THREAD STATIC t_hHT
THREAD STATIC t_cHtmlCP := ""
THREAD STATIC t_aHtmlUnicEntities
THREAD STATIC t_cHtmlUnicChars
#ifdef HB_LEGACY_LEVEL4
THREAD STATIC t_aHtmlAnsiEntities
THREAD STATIC t_cHtmlAnsiChars
#endif
THREAD STATIC t_lInit := .F.

#ifdef _DEBUG_
#xtranslate HIDDEN: => EXPORTED:
#endif

CREATE CLASS THtmlDocument MODULE FRIENDLY

   HIDDEN:
   VAR oIterator
   VAR nodes

   EXPORTED:
   VAR root    READONLY
   VAR head    READONLY
   VAR body    READONLY
   VAR changed INIT .T.

   METHOD new( cHtmlString )
   METHOD readFile( cFileName )
   METHOD writeFile( cFileName )

   METHOD collect()
   METHOD toString()
   METHOD getNode( cTagName )
   METHOD getNodes( cTagName )
   METHOD findFirst( cName, cAttrib, cValue, cData )
   METHOD findFirstRegex( cName, cAttrib, cValue, cData )
   METHOD findNext() INLINE ::oIterator:Next()

ENDCLASS

METHOD new( cHtmlString ) CLASS THtmlDocument

   LOCAL oSubNode, oErrNode, aHead, aBody, nMode := 0

   LOCAL cEmptyHtmlDoc := ;
      "<!DOCTYPE html>" + hb_eol() + ;
      "<html>" + hb_eol() + ;
      " <head>" + hb_eol() + ;
      " </head>" + hb_eol() + ;
      " <body>" + hb_eol() + ;
      " </body>" + hb_eol() + ;
      "</html>"

   IF ! HB_ISSTRING( cHtmlString )
      ::root := THtmlNode():new( cEmptyHtmlDoc )
   ELSEIF "<html" $ Lower( Left( cHtmlString, 4096 ) )
      ::root := THtmlNode():new( cHtmlString )
   ELSE
      ::root := THtmlNode():new( cEmptyHtmlDoc )
      nMode := 1
   ENDIF

   ::root:document := Self
   ::head := ::getNode( "head" )
   ::body := ::getNode( "body" )

   IF ::head == NIL .AND. ::body == NIL

      aHead := {}
      aBody := {}
      FOR EACH oSubNode IN ::root:htmlContent
         IF oSubNode:isType( CM_HEAD )
            AAdd( aHead, oSubNode )
         ELSE
            AAdd( aBody, oSubNode )
         ENDIF
      NEXT

      ::root    := THtmlNode():new( cEmptyHtmlDoc )
      ::root:document := Self
      ::changed := .T.
      ::head    := ::getNode( "head" )
      ::body    := ::getNode( "body" )

      FOR EACH oSubNode IN aHead
         IF oSubNode:isType( CM_HEAD )
            ::head:addNode( oSubNode )
         ELSE
            ::body:addNode( oSubNode )
         ENDIF
      NEXT

      FOR EACH oSubNode IN aBody
         IF Lower( oSubNode:htmlTagName ) $ "html,head,body"

            FOR EACH oErrNode IN oSubNode:htmlContent
               ::body:addNode( oErrNode )
            NEXT
         ELSE
            IF oSubNode:isType( CM_HEAD )
               oSubNode:delete()
               ::head:addNode( oSubNode )
            ELSE
               ::body:addNode( oSubNode )
            ENDIF
         ENDIF
      NEXT

   ELSEIF ::head == NIL
      ::head := ::body:insertBefore( THtmlNode():new( ::body, "head" ) )

   ELSEIF ::body == NIL
      ::head := ::head:insertAfter( THtmlNode():new( ::head, "body" ) )

   ENDIF

   IF nMode == 1
      FOR EACH oSubNode IN THtmlNode():new( cHtmlString ):htmlContent
         IF oSubNode:isType( CM_HEAD )
            ::head:addNode( oSubNode )
         ELSE
            ::body:addNode( oSubNode )
         ENDIF
      NEXT
   ENDIF

   RETURN Self

METHOD toString() CLASS THtmlDocument
   RETURN ::root:toString()

METHOD readFile( cFileName ) CLASS THtmlDocument

   IF hb_vfExists( cFileName )
      ::changed := .T.
      ::new( MemoRead( cFileName ) )

      RETURN .T.
   ENDIF

   RETURN .F.

METHOD writeFile( cFileName ) CLASS THtmlDocument

   LOCAL lSuccess := hb_MemoWrit( cFileName, ::toString() )

   IF lSuccess
      ::changed := .F.
   ENDIF

   RETURN lSuccess

METHOD collect() CLASS THtmlDocument

   IF ::changed
      ::nodes   := ::root:collect()
      ::changed := .F.
   ENDIF

   RETURN ::nodes

METHOD getNode( cTagName ) CLASS THtmlDocument

   LOCAL oNode

   IF ::changed
      ::collect()
   ENDIF

   FOR EACH oNode IN ::nodes
      IF Lower( oNode:htmlTagName ) == Lower( cTagName )
         RETURN oNode
      ENDIF
   NEXT

   RETURN NIL

METHOD getNodes( cTagName ) CLASS THtmlDocument

   LOCAL oNode, stack := S_STACK()

   IF ::changed
      ::collect()
   ENDIF

   FOR EACH oNode IN ::nodes
      IF Lower( oNode:htmlTagName ) == Lower( cTagName )
         S_PUSH( stack, oNode )
      ENDIF
   NEXT

   S_COMPRESS( stack )

   RETURN stack[ S_DATA ]

METHOD findFirst( cName, cAttrib, cValue, cData ) CLASS THtmlDocument

   ::oIterator := THtmlIteratorScan():New( Self )

   RETURN ::oIterator:Find( cName, cAttrib, cValue, cData )

METHOD findFirstRegex( cName, cAttrib, cValue, cData ) CLASS THtmlDocument

   ::oIterator := THtmlIteratorRegex():New( Self )

   RETURN ::oIterator:Find( cName, cAttrib, cValue, cData )

CREATE CLASS THtmlIterator MODULE FRIENDLY

   METHOD New( oHtml ) CONSTRUCTOR
   METHOD Next()
   METHOD Rewind()
   METHOD Find( cName, cAttribute, cValue, cData )
   METHOD GetNode()                 INLINE   ::oNode
   METHOD SetContext()
   METHOD Clone()

   HIDDEN:

   VAR cName
   VAR cAttribute
   VAR cValue
   VAR cData
   VAR oNode
   VAR oTop
   VAR aNodes
   VAR nCurrent
   VAR nLast

   METHOD MatchCriteria()

ENDCLASS

METHOD New( oHtml ) CLASS THtmlIterator

   IF oHtml:isDerivedFrom ( "THtmlDocument" )
      ::oNode := oHtml:root
      ::aNodes := oHtml:nodes
   ELSE
      ::oNode := oHtml
      ::aNodes := ::oNode:collect()
   ENDIF

   ::oTop     := ::oNode
   ::nCurrent := 1
   ::nLast    := Len( ::aNodes )

   RETURN Self

METHOD rewind() CLASS THtmlIterator

   ::oNode := ::oTop
   ::nCurrent := 0

   RETURN Self

METHOD Clone() CLASS THtmlIterator

   LOCAL oRet

   oRet            := THtmlIterator():New( ::oTop )
   oRet:cName      := ::cName
   oRet:cAttribute := ::cAttribute
   oRet:cValue     := ::cValue
   oRet:cData      := ::cData
   oRet:nCurrent   := 0
   oRet:nLast      := Len( ::aNodes )
   oRet:aNodes     := ::aNodes

   RETURN oRet

METHOD SetContext() CLASS THtmlIterator

   ::oTop          := ::oNode
   ::aNodes        := ::oNode:collect()
   ::nCurrent      := 0
   ::nLast         := Len( ::aNodes )

   RETURN Self


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Create Harbour OOP classes for the functionality described: Harbour contribution module 'hbtip' (Internet protocol utilities (FTP, HTTP, SMTP, POP3)): contrib/hbtip/popcli.prg. Defines classes: TIPClientPOP. This file provides network protocol implementations

[Assistant]
#include "hbclass.ch"

CREATE CLASS TIPClientPOP INHERIT TIPClient

   METHOD New( oUrl, xTrace, oCredentials )
   METHOD Open( cUrl )
   METHOD OpenDigest( cUrl )
   METHOD Close( lAutoQuit )
   METHOD Delete( nId )
   METHOD List()
   METHOD Noop()
   METHOD Retrieve( nId, nLen )
   METHOD Rset()
   METHOD Stat()
   METHOD Top( nMsgId )
   METHOD Quit()
   METHOD UIDL( nMsgId )
   METHOD countMail()
   METHOD GetOK()
   METHOD Read( nLen )
   METHOD retrieveAll( lDelete )

   METHOD getTop( nMsgId )
   METHOD getMessageRaw( nMsgId )
   METHOD getBody( nMsgId )
   METHOD getSubject( nMsgId )

ENDCLASS

METHOD New( oUrl, xTrace, oCredentials ) CLASS TIPClientPOP

   ::super:new( oUrl, iif( hb_defaultValue( xTrace, .F. ), "pop3", xTrace ), oCredentials )

   ::nDefaultPort := iif( ::oUrl:cProto == "pop3s" .OR. ::oUrl:cProto == "pops", 995, 110 )
   ::nConnTimeout := 10000

   RETURN Self

METHOD Open( cUrl ) CLASS TIPClientPOP

   IF ! ::super:Open( cUrl )
      RETURN .F.
   ENDIF

   IF Empty( ::oUrl:cUserid ) .OR. Empty( ::oUrl:cPassword )
      RETURN .F.
   ENDIF

   IF ::GetOk()
      ::inetSendAll( ::SocketCon, "USER " + ::oUrl:cUserid + ::cCRLF )
      IF ::GetOK()
         ::inetSendAll( ::SocketCon, "PASS " + ::oUrl:cPassword + ::cCRLF )
         IF ::GetOK()
            ::isOpen := .T.
            RETURN .T.
         ENDIF
      ENDIF
   ENDIF

   RETURN .F.

METHOD OpenDigest( cUrl ) CLASS TIPClientPOP

   LOCAL nPos, nPos2, cDigest

   IF ! ::super:Open( cUrl )
      RETURN .F.
   ENDIF

   IF Empty( ::oUrl:cUserid ) .OR. Empty( ::oUrl:cPassword )
      RETURN .F.
   ENDIF

   IF ::GetOk()
      IF ( nPos := At( "<", ::cReply ) ) > 0
         IF ( nPos2 := hb_At( ">", ::cReply, nPos + 1 ) ) > nPos
            cDigest := hb_MD5( SubStr( ::cReply, nPos, ( nPos2 - nPos ) + 1 ) + ::oUrl:cPassword )
            ::inetSendAll( ::SocketCon, "APOP " + ::oUrl:cUserid + " " + cDigest + ::cCRLF )
            IF ::GetOK()
               ::isOpen := .T.
               RETURN .T.
            ENDIF
         ENDIF
      ENDIF
   ENDIF

   RETURN .F.

METHOD Close( lAutoQuit ) CLASS TIPClientPOP

   ::InetTimeOut( ::SocketCon )

   IF hb_defaultValue( lAutoQuit, .T. )
      ::Quit()
   ENDIF

   RETURN ::super:Close()

METHOD Delete( nId ) CLASS TIPClientPOP

   ::inetSendAll( ::SocketCon, "DELE " + hb_ntos( Int( nId ) ) + ::cCRLF )

   RETURN ::GetOk()

METHOD List() CLASS TIPClientPOP

   LOCAL nPos
   LOCAL cStr, cRet

   ::inetSendAll( ::SocketCon, "LIST" + ::cCRLF )
   IF ! ::GetOk()
      RETURN NIL
   ENDIF

   cRet := ""
   DO WHILE ! cStr == "." .AND. ::inetErrorCode( ::SocketCon ) == 0
      cStr := ::inetRecvLine( ::SocketCon, @nPos, 256 )
      IF ! HB_ISSTRING( cStr ) .OR. cStr == "."
         ::bEof := .T.
      ELSE
         cRet += cStr + ::cCRLF
      ENDIF
   ENDDO

   IF ::inetErrorCode( ::SocketCon ) != 0
      RETURN NIL
   ENDIF

   RETURN cRet

METHOD Noop() CLASS TIPClientPOP

   ::inetSendAll( ::SocketCon, "NOOP" + ::cCRLF )

   RETURN ::GetOk()

METHOD Retrieve( nId, nLen ) CLASS TIPClientPOP

   LOCAL nPos
   LOCAL cRet, nRetLen, cBuffer, nRead
   LOCAL cEOM := ::cCRLF + "." + ::cCRLF

   IF ! ::bInitialized
      ::inetSendAll( ::SocketCon, "RETR " + hb_ntos( Int( nId ) ) + ::cCRLF )
      IF ! ::GetOk()
         ::bEof := .T.
         RETURN NIL
      ENDIF
      ::bInitialized := .T.
   ENDIF

   cRet := ""
   nRetLen := 0

   DO WHILE ::inetErrorCode( ::SocketCon ) == 0 .AND. ! ::bEof

      cBuffer := Space( 1024 )

      nRead := ::inetRecv( ::SocketCon, @cBuffer, hb_BLen( cBuffer ) )

      cRet += hb_BLeft( cBuffer, nRead )

      IF ( nPos := hb_BAt( cEOM, cRet, Max( nRetLen - hb_BLen( cEOM ), 1 ) ) ) > 0

         cRet := hb_BLeft( cRet, nPos + 1 )
         ::bEof := .T.

      ELSEIF HB_ISNUMERIC( nLen ) .AND. nLen < hb_BLen( cRet )
         EXIT
      ELSE
         nRetLen += nRead
      ENDIF
   ENDDO

   IF ::inetErrorCode( ::SocketCon ) != 0
      RETURN NIL
   ENDIF

   RETURN StrTran( cRet, ::cCRLF + "..", ::cCRLF + "." )

METHOD Rset() CLASS TIPClientPOP

   ::inetSendAll( ::SocketCon, "RSET" + ::cCRLF )

   RETURN ::GetOk()

METHOD Stat() CLASS TIPClientPOP

   LOCAL nRead

   ::inetSendAll( ::SocketCon, "STAT" + ::cCRLF )

   RETURN ::inetRecvLine( ::SocketCon, @nRead, 128 )

METHOD Top( nMsgId ) CLASS TIPClientPOP

   LOCAL nPos
   LOCAL cStr, cRet

   ::inetSendAll( ::SocketCon, "TOP " + hb_ntos( Int( nMsgId ) ) + " 0" + ::cCRLF )
   IF ! ::GetOk()
      RETURN NIL
   ENDIF

   cRet := ""
   DO WHILE ! cStr == "." .AND. ::inetErrorCode( ::SocketCon ) == 0
      cStr := ::inetRecvLine( ::SocketCon, @nPos, 512 )
      IF ! HB_ISSTRING( cStr ) .OR. cStr == "."
         ::bEof := .T.
      ELSE
         cRet += cStr + ::cCRLF
      ENDIF
   ENDDO

   IF ::inetErrorCode( ::SocketCon ) != 0
      RETURN NIL
   ENDIF

   RETURN cRet

METHOD Quit() CLASS TIPClientPOP

   ::inetSendAll( ::SocketCon, "QUIT" + ::cCRLF )

   RETURN ::GetOk()

METHOD UIDL( nMsgId ) CLASS TIPClientPOP

   LOCAL nPos
   LOCAL cStr, cRet

   IF HB_ISNUMERIC( nMsgId ) .AND. nMsgId >= 1
      ::inetSendAll( ::SocketCon, "UIDL " + hb_ntos( Int( nMsgId ) ) + ::cCRLF )
   ELSE
      ::inetSendAll( ::SocketCon, "UIDL" + ::cCRLF )
   ENDIF

   IF ! ::GetOk()
      RETURN NIL
   ENDIF

   IF Empty( nMsgId )
      cRet := ""
      DO WHILE ! cStr == "." .AND. ::inetErrorCode( ::SocketCon ) == 0
         cStr := ::inetRecvLine( ::SocketCon, @nPos, 256 )
         IF ! HB_ISSTRING( cStr ) .OR. cStr == "."
            ::bEof := .T.
         ELSE
            cRet += cStr + ::cCRLF
         ENDIF
      ENDDO
   ELSE

      RETURN SubStr( ::cReply, RAt( Space( 1 ), ::cReply ) + 1 )
   ENDIF

   IF ::inetErrorCode( ::SocketCon ) != 0
      RETURN NIL
   ENDIF

   RETURN cRet

METHOD countMail() CLASS TIPClientPop

   LOCAL cStat

   IF ::isOpen
      ::reset()
      cStat := ::Stat()
      IF HB_ISSTRING( cStat ) .AND. hb_LeftEq( cStat, "+OK" )
         RETURN Val( SubStr( cStat, 4, hb_At( " ", cStat, 5 ) - 4 ) )
      ENDIF
   ENDIF

   RETURN -1

METHOD GetOk() CLASS TIPClientPOP

   ::cReply := ::inetRecvLine( ::SocketCon,, 128 )

   RETURN ::inetErrorCode( ::SocketCon ) == 0 .AND. ;
      HB_ISSTRING( ::cReply ) .AND. hb_LeftEq( ::cReply, "+" )

METHOD Read( nLen ) CLASS TIPClientPOP

   IF Empty( ::oUrl:cFile )
      RETURN ::List()
   ELSEIF Val( ::oUrl:cFile ) < 0
      RETURN ::Delete( -Val( ::oUrl:cFile ) ) .AND. ::Quit()
   ENDIF

   RETURN ::Retrieve( Val( ::oUrl:cFile ), nLen )

METHOD retrieveAll( lDelete ) CLASS TIPClientPOP

   LOCAL aMails, oMail

   IF ::isOpen

      hb_default( @lDelete, .F. )

      FOR EACH oMail IN aMails := Array( ::countMail() )
         ::reset()

         oMail := TIPMail():new()
         oMail:fromString( ::retrieve( oMail:__enumIndex() ) )

         IF lDelete
            ::reset()
            ::delete( oMail:__enumIndex() )
         ENDIF
      NEXT
   ENDIF

   RETURN aMails

METHOD getTop( nMsgId ) CLASS TIPClientPOP

   LOCAL nPos, cStr, xRet

   ::inetSendAll( ::SocketCon, "TOP " + hb_ntos( Int( nMsgId ) ) + " 0" + ::cCRLF )
   IF ! ::GetOk()
      RETURN NIL
   ENDIF

   xRet := cStr := ""
   DO WHILE ! cStr == "." .AND. ::inetErrorCode( ::SocketCon ) == 0
      cStr := ::inetRecvLine( ::SocketCon, @nPos, 1024 )
      IF HB_ISSTRING( cStr ) .AND. ! cStr == "."
         xRet += cStr + ::cCRLF
      ENDIF
   ENDDO

   RETURN xRet

METHOD getMessageRaw( nMsgId ) CLASS TIPClientPOP

   LOCAL cLine, nBytes, xRet

   ::inetSendAll( ::SocketCon, "RETR " + hb_ntos( Int( nMsgId ) ) + ::cCRLF )
   IF ! ::GetOk()
      RETURN NIL
   ENDIF

   xRet := ""
   DO WHILE ::inetErrorCode( ::SocketCon ) == 0
      cLine := ::inetRecvLine( ::SocketCon, @nBytes, 8192 )
      IF nBytes <= 0 .OR. ! HB_ISSTRING( cLine ) .OR. cLine == "."
         EXIT
      ENDIF
      xRet += cLine + ::cCRLF
   ENDDO

   RETURN xRet


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User]
Write the following Harbour (xBase/Clipper) code:

Harbour contribution module 'hbtip' (Internet protocol utilities (FTP, HTTP, SMTP, POP3)): contrib/hbtip/mailassy.prg. Provides functions: hb_MailAssemble, tip_MailAssemble, s_TransCP. This file provides network protocol implementations

[Assistant]
#if defined( HB_LEGACY_LEVEL4 )
FUNCTION hb_MailAssemble( ... )
   RETURN tip_MailAssemble( ... )
#endif

FUNCTION tip_MailAssemble( ;
      cFrom, ;
      xTo, ;
      xCC, ;
      cBody, ;
      cSubject, ;
      aFiles, ;
      nPriority, ;
      lRead, ;
      cReplyTo, ;
      cCharset, ;
      cEncoding, ;
      lBodyHTML, ;
      bSMIME )

   LOCAL oMail
   LOCAL oAttach
   LOCAL aThisFile
   LOCAL cMimeType
   LOCAL cFile
   LOCAL cData
   LOCAL cContentType
   LOCAL nAttr

   LOCAL cCharsetCP
   LOCAL tmp

   IF Empty( cFrom ) .OR. ! HB_ISSTRING( cFrom )
      RETURN ""
   ENDIF
   IF Empty( xTo ) .OR. ( ! HB_ISSTRING( xTo ) .AND. ! HB_ISARRAY( xTo ) )
      RETURN ""
   ENDIF

   hb_default( @cBody, "" )
   hb_default( @cSubject, "" )
   hb_default( @aFiles, {} )
   nPriority := Int( hb_defaultValue( nPriority, 3 ) )
   hb_default( @lRead, .F. )
   hb_default( @cReplyTo, "" )
   hb_default( @cCharset, "UTF-8" )
   hb_default( @cEncoding, "quoted-printable" )
   hb_default( @lBodyHTML, .F. )

   IF Upper( cCharset ) == "UTF-8"
      cCharsetCP := "UTF8"
   ELSEIF hb_cdpExists( Lower( cCharset ) )
      cCharsetCP := hb_cdpUniID( Lower( cCharset ) )
   ENDIF

   cContentType := iif( lBodyHTML, "text/html", "text/plain" ) + "; charset=" + cCharset

   IF ! Right( cBody, 2 ) == Chr( 13 ) + Chr( 10 )
      cBody += Chr( 13 ) + Chr( 10 )
   ENDIF

   IF ! Empty( cCharsetCP )
      xTo := s_TransCP( xTo, cCharsetCP )
      xCC := s_TransCP( xCC, cCharsetCP )
      cFrom := s_TransCP( cFrom, cCharsetCP )
      cBody := s_TransCP( cBody, cCharsetCP )
      cSubject := s_TransCP( cSubject, cCharsetCP )
   ENDIF

   oMail := TIPMail():New()
   oMail:SetEncoder( cEncoding )
   oMail:SetCharset( cCharset )
   IF Empty( aFiles )
      oMail:hHeaders[ "Content-Type" ] := cContentType
      oMail:SetBody( cBody )
   ELSE
      oAttach := TIPMail():New()
      oAttach:SetEncoder( cEncoding )
      oAttach:SetCharset( cCharset )
      oAttach:hHeaders[ "Content-Type" ] := cContentType
      oAttach:SetBody( cBody )
      oMail:Attach( oAttach )

      FOR EACH aThisFile IN aFiles

         cMimeType := NIL
         nAttr := 0

         DO CASE
         CASE HB_ISSTRING( aThisFile )
            cFile := aThisFile
            cData := hb_MemoRead( cFile )
            hb_vfAttrGet( cFile, @nAttr )
         CASE HB_ISARRAY( aThisFile ) .AND. Len( aThisFile ) >= 2
            cFile := aThisFile[ 1 ]
            IF HB_ISSTRING( aThisFile[ 2 ] )
               cData := aThisFile[ 2 ]
               hb_default( @cFile, "unnamed" )
            ELSEIF HB_ISSTRING( cFile )
               cData := hb_MemoRead( cFile )
               hb_vfAttrGet( cFile, @nAttr )
            ELSE
               LOOP
            ENDIF
            IF Len( aThisFile ) >= 3 .AND. HB_ISSTRING( aThisFile[ 3 ] )
               cMimeType := aThisFile[ 3 ]
            ENDIF
         OTHERWISE
            LOOP
         ENDCASE

         IF cMimeType == NIL
            cMimeType := tip_FileNameMimeType( cFile, "application/octet-stream" )
         ENDIF
         cFile := s_TransCP( cFile, cCharsetCP )

         oAttach := TIPMail():New()
         oAttach:SetCharset( cCharset )
         oAttach:SetEncoder( iif( hb_LeftEq( cMimeType, "text/" ), cEncoding, "base64" ) )

         IF cMimeType == "text/html"
            cMimeType += "; charset=" + cCharset
            IF ! Right( cData, 2 ) == Chr( 13 ) + Chr( 10 )
               cData += Chr( 13 ) + Chr( 10 )
            ENDIF
         ENDIF

         cMimeType += "; name=" + '"' + hb_FNameNameExt( cFile ) + '"'
         IF ( nAttr := __tip_FAttrToUmask( nAttr ) ) != 0
            cMimeType += "; x-unix-mode=" + '"' + hb_NumToHex( nAttr, 4 ) + '"'
         ENDIF
         oAttach:hHeaders[ "Content-Type" ] := cMimeType

         oAttach:hHeaders[ "Content-Disposition" ] := "attachment; filename=" + '"' + hb_FNameNameExt( cFile ) + '"'
         oAttach:SetBody( cData )
         oMail:Attach( oAttach )
      NEXT
   ENDIF

   IF HB_ISEVALITEM( bSMIME ) .AND. ;
      HB_ISSTRING( tmp := Eval( bSMIME, oMail:ToString() ) )

      oMail := TIPMail():New()
      oMail:SetCharset( cCharset )
   ELSE
      tmp := NIL
   ENDIF

   oMail:SetHeader( cSubject, cFrom, xTo, xCC )
   oMail:hHeaders[ "Date" ] := tip_TimeStamp()
   IF ! Empty( cReplyTo )
      oMail:hHeaders[ "Reply-to" ] := cReplyTo
   ENDIF
   IF lRead
      oMail:hHeaders[ "Disposition-Notification-To" ] := tip_GetRawEmail( cFrom )
   ENDIF
   IF nPriority != 3
      oMail:hHeaders[ "X-Priority" ] := hb_ntos( nPriority )
   ENDIF

   RETURN iif( HB_ISSTRING( tmp ), oMail:HeadersToString() + tmp, oMail:ToString() )

STATIC FUNCTION s_TransCP( xData, cCP )

   LOCAL tmp

   IF ! Empty( cCP )
      DO CASE
      CASE HB_ISSTRING( xData )
         RETURN hb_Translate( xData,, cCP )
      CASE HB_ISARRAY( xData )
         FOR EACH tmp IN xData
            tmp := hb_Translate( tmp,, cCP )
         NEXT
      ENDCASE
   ENDIF

   RETURN xData


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Implement this Harbour module: Harbour header file: include/hbsxdef.ch. Defines 10 constants including: HB_SIX_DEF_CH_, EVENT_PREUSE, EVENT_POSTUSE, EVENT_UPDATE, EVENT_APPEND. Defines Harbour internal constants and macros

[Assistant]
#ifndef HB_SIX_DEF_CH_
#define HB_SIX_DEF_CH_

#define EVENT_PREUSE          1
#define EVENT_POSTUSE         2
#define EVENT_UPDATE          3
#define EVENT_APPEND          4
#define EVENT_DELETE          5
#define EVENT_RECALL          6
#define EVENT_PACK            7
#define EVENT_ZAP             8
#define EVENT_PUT             9
#define EVENT_GET             10
#define EVENT_PRECLOSE        11
#define EVENT_POSTCLOSE       12
#define EVENT_PREMEMOPACK     13
#define EVENT_POSTMEMOPACK    14

#define TRIGGER_ENABLE        1
#define TRIGGER_DISABLE       2
#define TRIGGER_REMOVE        3
#define TRIGGER_INSTALL       4
#define TRIGGER_PENDING       5

#define BLOB_FILECOMPRESS     1
#define BLOB_FILEENCRYPT      2

#endif


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User]
Here is a Harbour (xBase/Clipper) implementation:

Harbour contribution module 'hbnetio' (Network I/O operations): contrib/hbnetio/utils/hbnetio/_console.prg. Provides functions: hbnetiocon_GetHidden. Contains 5 procedures. This file provides network protocol implementations

[Assistant]
#include "color.ch"
#include "inkey.ch"
#include "setcurs.ch"

#include "hbgtinfo.ch"

PROCEDURE hbnetiocon_cmdUI( cIP, nPort, cPassword )

   LOCAL GetList := {}
   LOCAL hCommands
   LOCAL nSavedRow
   LOCAL nPos
   LOCAL aCommand
   LOCAL cCommand

   LOCAL bKeyDown
   LOCAL bKeyUp
   LOCAL bKeyIns
   LOCAL bKeyPaste
   LOCAL bKeyTab

   LOCAL aHistory, nHistIndex

   LOCAL lQuit

   LOCAL netclictrl := __hbshell_plugin()
   LOCAL netclictx
   LOCAL netcliID

   LOCAL hConIO := { ;
      "displine"  => {| c | hbnetiocon_ToConsole( c ) }, ;
      "gethidden" => {|| hbnetiocon_GetHidden() } }

   Set( _SET_CONFIRM, .F. )
   Set( _SET_SCOREBOARD, .F. )

   Set( _SET_DATEFORMAT, "yyyy-mm-dd" )
   Set( _SET_TIMEFORMAT, "hh:mm:ss" )

   SetCancel( .F. )

   netclictx := Eval( netclictrl[ "init" ], hConIO, { ;
      "--netio.addr=" + cIP + ":" + hb_ntos( nPort ), ;
      "--netio.pass=" + cPassword } )
   IF ! Empty( netclictx )
      netcliID := netclictrl[ "id" ]
   ENDIF

   hbnetiocon_ToConsole( "Type a command or '?' for help." )

   aHistory   := { "quit" }
   nHistIndex := Len( aHistory ) + 1

   hCommands  := { ;
      "?"    => { "", "Synonym for 'help'." , {|| ShowHelp( hCommands ), Eval( netclictrl[ "cmd" ], netclictx, "?" ) } }, ;
      "help" => { "", "Display this help."  , {|| ShowHelp( hCommands ), Eval( netclictrl[ "cmd" ], netclictx, "?" ) } }, ;
      "quit" => { "", "Exit console."       , {|| lQuit := .T. } } }

   lQuit := .F.

   DO WHILE ! lQuit

      cCommand := Space( 128 )

      QQOut( "$ " )
      nSavedRow := Row()

      @ nSavedRow, Col() GET cCommand PICTURE "@S" + hb_ntos( MaxCol() - Col() + 1 ) COLOR hb_ColorIndex( SetColor(), CLR_STANDARD ) + "," + hb_ColorIndex( SetColor(), CLR_STANDARD )

      SetCursor( iif( ReadInsert(), SC_INSERT, SC_NORMAL ) )

      bKeyIns   := SetKey( K_INS, ;
         {|| SetCursor( iif( ReadInsert( ! ReadInsert() ), ;
                          SC_NORMAL, SC_INSERT ) ) } )
      bKeyUp    := SetKey( K_UP, ;
         {|| iif( nHistIndex > 1, ;
                  cCommand := PadR( aHistory[ --nHistIndex ], Len( cCommand ) ), ), ;
                  ManageCursor( cCommand ) } )
      bKeyDown  := SetKey( K_DOWN, ;
         {|| cCommand := PadR( iif( nHistIndex < Len( aHistory ), ;
             aHistory[ ++nHistIndex ], ;
             ( nHistIndex := Len( aHistory ) + 1, "" ) ), Len( cCommand ) ), ;
                  ManageCursor( cCommand ) } )
      bKeyPaste := SetKey( K_ALT_V, {|| hb_gtInfo( HB_GTI_CLIPBOARDPASTE, .T. ) } )

      bKeyTab   := SetKey( K_TAB, {|| CompleteCmd( @cCommand, hCommands ) } )

      READ

      SetPos( nSavedRow, MaxCol() - 1 )

      SetKey( K_ALT_V, bKeyPaste )
      SetKey( K_DOWN,  bKeyDown  )
      SetKey( K_UP,    bKeyUp    )
      SetKey( K_INS,   bKeyIns   )
      SetKey( K_TAB,   bKeyTab   )

      QQOut( hb_eol() )

      cCommand := AllTrim( cCommand )

      IF Empty( cCommand )
         LOOP
      ENDIF

      IF Empty( aHistory ) .OR. ! ATail( aHistory ) == cCommand
         IF Len( aHistory ) < 64
            AAdd( aHistory, cCommand )
         ELSE
            ADel( aHistory, 1 )
            aHistory[ Len( aHistory ) ] := cCommand
         ENDIF
      ENDIF
      nHistIndex := Len( aHistory ) + 1

      aCommand := hb_ATokens( cCommand, " " )
      IF ! Empty( aCommand )
         IF ( nPos := hb_HPos( hCommands, Lower( aCommand[ 1 ] ) ) ) > 0
            Eval( hb_HValueAt( hCommands, nPos )[ 3 ], cCommand )
         ELSE
            IF Left( cCommand, Len( netcliID ) + 1 ) == netcliID + "."
               IF ! Eval( netclictrl[ "cmd" ], netclictx, SubStr( cCommand, Len( netcliID ) + 2 ) )
                  hbnetiocon_ToConsole( hb_StrFormat( "Error: Unrecognized command '%1$s'.", cCommand ) )
               ENDIF
            ELSE
               IF ! Eval( netclictrl[ "cmd" ], netclictx, cCommand )
                  hbnetiocon_ToConsole( hb_StrFormat( "Error: Unrecognized command '%1$s'.", cCommand ) )
               ENDIF
            ENDIF
         ENDIF
      ENDIF
   ENDDO

   Eval( netclictrl[ "exit" ], netclictx )

   RETURN

STATIC PROCEDURE ManageCursor( cCommand )

   hb_keyPut( K_HOME )
   IF ! Empty( cCommand )
      hb_keyPut( K_END )
   ENDIF

   RETURN

STATIC PROCEDURE CompleteCmd( cCommand, hCommands )

   LOCAL s := Lower( AllTrim( cCommand ) )
   LOCAL n

   IF Len( s ) > 1
      FOR EACH n IN hCommands
         IF s == Lower( Left( n:__enumKey(), Len( s ) ) )
            cCommand := PadR( n:__enumKey(), Len( cCommand ) )
            ManageCursor( cCommand )
            RETURN
         ENDIF
      NEXT
   ENDIF

   RETURN

STATIC PROCEDURE ShowHelp( hCommands )

   LOCAL aTexts := {}
   LOCAL n, c, m

   m := 8
   hb_HEval( hCommands, {| k, l | m := Max( m, Len( k + iif( Empty( l[ 1 ] ), "", " " + l[ 1 ] ) ) ) } )

   AAdd( aTexts, "Commands:" )

   FOR EACH n IN hCommands
      AAdd( aTexts, " " + PadR( n:__enumKey() + iif( Empty( n[ 1 ] ), "", " " + n[ 1 ] ), m ) + " - " + n[ 2 ] )
   NEXT
   AAdd( aTexts, "" )

   AAdd( aTexts, "Keyboard shortcuts:" )
   AAdd( aTexts, PadR( " <Up>", m )    + "  - Move up on historic list." )
   AAdd( aTexts, PadR( " <Down>", m )  + "  - Move down on historic list." )
   AAdd( aTexts, PadR( " <Tab>", m )   + "  - Complete command." )
   AAdd( aTexts, PadR( " <Alt+V>", m ) + "  - Paste from clipboard." )
   AAdd( aTexts, "" )

   c := 0
   m := MaxRow()

   FOR EACH n IN aTexts
      hbnetiocon_ToConsole( n )

      IF ++c == m
         c := 0
         QQOut( "Press any key to continue..." )
         Inkey( 0 )

         Scroll( Row(), 0, Row(), MaxCol() )
         SetPos( Row(), 0 )
      ENDIF
   NEXT

   RETURN

STATIC PROCEDURE hbnetiocon_ToConsole( cText )

   QQOut( cText + hb_eol() )

   RETURN

STATIC FUNCTION hbnetiocon_GetHidden()

   LOCAL GetList := {}
   LOCAL cPassword := Space( 128 )
   LOCAL nSavedRow
   LOCAL bKeyPaste

   QQOut( "Enter password: " )

   nSavedRow := Row()

   AAdd( GetList, hb_Get():New( Row(), Col(), {| v | iif( PCount() == 0, cPassword, cPassword := v ) }, "cPassword", "@S" + hb_ntos( MaxCol() - Col() + 1 ), hb_ColorIndex( SetColor(), CLR_STANDARD ) + "," + hb_ColorIndex( SetColor(), CLR_STANDARD ) ) )
   ATail( GetList ):hideInput( .T. )
   ATail( GetList ):postBlock := {|| ! Empty( cPassword ) }
   ATail( GetList ):display()

   SetCursor( iif( ReadInsert(), SC_INSERT, SC_NORMAL ) )
   bKeyPaste := SetKey( K_ALT_V, {|| hb_gtInfo( HB_GTI_CLIPBOARDPASTE, .T. ) } )

   READ

   SetPos( nSavedRow, MaxCol() - 1 )
   SetKey( K_ALT_V, bKeyPaste )

   QQOut( hb_eol() )

   RETURN AllTrim( cPassword )


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Generate Harbour code for: Harbour contribution module 'hbnf' (NanForum Toolkit - legacy Clipper compatibility functions): contrib/hbnf/pickday.prg. Provides functions: ft_PickDay. This file provides legacy compatibility functions

[Assistant]
FUNCTION ft_PickDay()

   LOCAL days := { "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", ;
      "FRIDAY", "SATURDAY" }
   LOCAL sel := 0
   LOCAL oldscrn := SaveScreen( 8, 35, 16, 45 ), oldcolor := SetColor( "+w/r" )

   hb_DispBox( 8, 35, 16, 45, hb_UTF8ToStrBox( "┌─┐│┘─└│ " ) )

   DO WHILE sel == 0
      sel := AChoice( 9, 36, 15, 44, days )
   ENDDO

   RestScreen( 8, 35, 16, 45, oldscrn )
   SetColor( oldcolor )

   RETURN days[ sel ]


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Generate Harbour code for: Harbour contribution module 'hbnf' (NanForum Toolkit - legacy Clipper compatibility functions): contrib/hbnf/eltime.prg. Provides functions: ft_ElTime. This file provides legacy compatibility functions

[Assistant]
FUNCTION ft_ElTime( cTIME1, cTIME2 )

   LOCAL  nDELSECS, nHRS, nMINS, nSECS, nSECS1, nSECS2

   nSECS1   := ( Val( SubStr( cTIME1, 1, 2 ) )
      Right( "00" + hb_ntos( nHRS ), 2 ) + ;
      ":" + ;
      Right( "00" + hb_ntos( nMINS ), 2 ) + ;
      ":" + ;
      Right( "00" + hb_ntos( nSECS ), 2 )


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Generate Harbour code for: Harbour contribution module 'xhb' (Extended Harbour functions): contrib/xhb/tcgi.prg. Defines classes: TCgi. Provides functions: ParseString, CgiParseVar. This file provides legacy compatibility functions

[Assistant]
#include "hbclass.ch"
#include "cgi.ch"

CREATE CLASS TCgi INHERIT THtml

   VAR nH
   VAR Server_Software
   VAR Server_Name
   VAR Gateway_Interface
   VAR Server_Protocol
   VAR Server_Port
   VAR Request_Method
   VAR Http_Accept
   VAR Http_User_agent
   VAR Http_Referer
   VAR Path_Info
   VAR Path_Translated
   VAR Script_Name
   VAR Query_String
   VAR Remote_Host
   VAR Remote_Addr
   VAR ipAddress
   VAR Remote_User
   VAR Auth_Type
   VAR Auth_User
   VAR Auth_Pass
   VAR Content_Type
   VAR Content_Length
   VAR Annotation_Server

   VAR aQueryFields INIT {}

   METHOD New( cInBuffer )
   METHOD Field( cQueryName )
   METHOD ToObject()

ENDCLASS

METHOD New( cInBuffer ) CLASS TCgi

   LOCAL i
   LOCAL aTemp
   LOCAL aVar

   ::nH := HtmlPageHandle()

   ::Server_Software   := GetEnv( "SERVER_SOFTWARE" )
   ::Server_Name       := GetEnv( "SERVER_NAME" )
   ::Gateway_Interface := GetEnv( "GATEWAY_INTERFACE" )
   ::Server_Protocol   := GetEnv( "SERVER_PROTOCOL" )
   ::Server_Port       := GetEnv( "SERVER_PORT" )
   ::Request_Method    := GetEnv( "REQUEST_METHOD" )
   ::Http_Accept       := GetEnv( "HTTP_ACCEPT" )
   ::Http_User_agent   := GetEnv( "HTTP_USER_AGENT" )
   ::Http_Referer      := GetEnv( "HTTP_REFERER" )
   ::Path_Info         := GetEnv( "PATH_INFO" )
   ::Path_Translated   := GetEnv( "PATH_TRANSLATED" )
   ::Script_Name       := GetEnv( "SCRIPT_NAME" )
   ::Query_String      := GetEnv( "QUERY_STRING" )
   ::Remote_Host       := GetEnv( "REMOTE_HOST" )
   ::Remote_Addr       := GetEnv( "REMOTE_ADDR" )
   ::ipAddress         := GetEnv( "REMOTE_ADDR" )
   ::Remote_User       := GetEnv( "REMOTE_USER" )
   ::Auth_Type         := GetEnv( "AUTH_TYPE" )
   ::Auth_User         := GetEnv( "AUTH_USER" )
   ::Auth_Pass         := GetEnv( "AUTH_PASS" )
   ::Content_Type      := GetEnv( "CONTENT_TYPE" )
   ::Content_Length    := GetEnv( "CONTENT_LENGTH" )
   ::Annotation_Server := GetEnv( "ANNOTATION_SERVER" )

   IF cInBuffer != NIL
      ::Query_String := RTrim( cInBuffer )
   ELSE
      IF "POST" $ Upper( ::Request_Method )
         ::Query_String := RTrim( FReadStr( STD_IN, Val( ::CONTENT_LENGTH ) ) )
      ENDIF
   ENDIF

   IF ! Empty( ::Query_String )

      ::aQueryFields := {}

      aTemp := hb_ATokens( ::Query_String, "&" )

      FOR i := 1 TO Len( aTemp )
         aVar := hb_ATokens( aTemp[ i ], "=" )
         IF Len( aVar ) == 2
            AAdd( ::aQueryFields, { aVar[ 1 ], HtmlDecodeUrl( aVar[ 2 ] ) } )
         ENDIF
      NEXT

   ENDIF

   RETURN ::ToObject()

METHOD ToObject() CLASS TCgi

   LOCAL i
   LOCAL nScope := 1
   LOCAL aDb
   LOCAL oNew

   STATIC s_n := 0

   aDb := HBClass():New( "NewCgi" + StrZero( ++s_n, 3 ), { "TCgi" } )

   FOR i := 1 TO Len( ::aQueryFields )

      IF ::aQueryFields[ i, 2 ] == NIL .OR. Empty( ::aQueryFields[ i, 2 ] )
         ::aQueryFields[ i, 2 ] := ""
      ENDIF

      adb:AddData( ::aQueryFields[ i, 1 ], ::aQueryFields[ i, 2 ], , nScope )
   NEXT

   adb:Create()
   oNew := adb:Instance()
   oNew:aQueryFields      := ::aQueryFields
   oNew:Server_Software   := ::Server_Software
   oNew:Server_Name       := ::Server_Name
   oNew:Gateway_Interface := ::Gateway_Interface
   oNew:Server_Protocol   := ::Server_Protocol
   oNew:Server_Port       := ::Server_Port
   oNew:Request_Method    := ::Request_Method
   oNew:Http_Accept       := ::Http_Accept
   oNew:Http_User_agent   := ::Http_User_agent
   oNew:Http_Referer      := ::Http_Referer
   oNew:Path_Info         := ::Path_Info
   oNew:Path_Translated   := ::Path_Translated
   oNew:Script_Name       := ::Script_Name
   oNew:Query_String      := ::Query_String
   oNew:Remote_Host       := ::Remote_Host
   oNew:Remote_Addr       := ::Remote_Addr
   oNew:ipAddress         := ::ipAddress
   oNew:Remote_User       := ::Remote_User
   oNew:Auth_Type         := ::Auth_Type
   oNew:Content_Type      := ::Content_Type
   oNew:Content_Length    := ::Content_Length
   oNew:Annotation_Server := ::Annotation_Server
   oNew:nH                := iif( HtmlPageHandle() == NIL, STD_OUT, HtmlPageHandle() )

   RETURN oNew

METHOD Field( cQueryName ) CLASS TCgi

   LOCAL cRet := ""
   LOCAL nRet

   __defaultNIL( @cQueryName, "" )

   nRet := AScan( ::aQueryFields, {| x | Upper( x[ 1 ] ) == Upper( cQueryName ) } )

   IF nRet > 0
      cRet := ::aQueryFields[ nRet, 2 ]
   ENDIF

   RETURN cRet

FUNCTION ParseString( cString, cDelim, nRet )

   LOCAL cBuf
   LOCAL aElem
   LOCAL nPosFim
   LOCAL nSize
   LOCAL i

   nSize := Len( cString ) - Len( StrTran( cString, cDelim ) ) + 1
   aElem := Array( nSize )

   cBuf := cString
   FOR i := 1 TO nSize
      nPosFim := At( cDelim, cBuf )

      IF nPosFim > 0
         aElem[ i ] := SubStr( cBuf, 1, nPosFim - 1 )
      ELSE
         aElem[ i ] := cBuf
      ENDIF

      cBuf := SubStr( cBuf, nPosFim + 1, Len( cBuf ) )

   NEXT

   RETURN aElem[ nRet ]

FUNCTION CgiParseVar( cEnvVar )

   cEnvVar := HtmlDecodeUrl( cEnvVar )

   IF "=" $ cEnvVar .AND. Len( cEnvVar ) > At( "=", cEnvVar )
      cEnvVar := AllTrim( SubStr( cEnvVar, At( "=", cEnvVar ) + 1 ) )
   ELSE
      cEnvVar := ""
   ENDIF

   RETURN cEnvVar


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Generate Harbour code for: Harbour contribution module 'hbct' (CA-Tools compatibility library): contrib/hbct/tests/wordone.prg. Contains procedures: Main. This file provides legacy compatibility functions

[Assistant]
#ifdef __HARBOUR__
#require "hbct"
#endif

PROCEDURE Main()

   ctinit()

   ? "Begin test of WordOne()"
   ?

   ? "Simple tests:"
   ? '  WordOne( "12ABAB12" )       == "12AB12" ? --> "' + WordOne( "12ABAB12" )       + '"'
   ? '  WordOne( "1AAAA2" )         == "1AAAA2" ? --> "' + WordOne( "1AAAA2" )         + '"'
   ? '  WordOne( "12", "1212ABAB" ) == "12ABAB" ? --> "' + WordOne( "12", "1212ABAB" ) + '"'
   ?

   ? "End test of WordOne()"
   ?

   ctexit()

   RETURN


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User]
Here is a Harbour (xBase/Clipper) implementation:

Harbour header file: extras/rddado/adordd.ch. Defines 10 constants including: _ADORDD_CH, adOpenForwardOnly, adOpenKeyset, adOpenDynamic, adOpenStatic. Declares 2 preprocessor commands. Defines Harbour internal constants and macros

[Assistant]
#ifndef _ADORDD_CH
#define _ADORDD_CH

#define adOpenForwardOnly               0
#define adOpenKeyset                    1
#define adOpenDynamic                   2
#define adOpenStatic                    3

#define adLockReadOnly                  1
#define adLockPessimistic               2
#define adLockOptimistic                3
#define adLockBatchOptimistic           4

#define adEmpty                         0
#define adTinyInt                       16
#define adSmallInt                      2
#define adInteger                       3
#define adBigInt                        20
#define adUnsignedTinyInt               17
#define adUnsignedSmallInt              18
#define adUnsignedInt                   19
#define adUnsignedBigInt                21
#define adSingle                        4
#define adDouble                        5
#define adCurrency                      6
#define adDecimal                       14
#define adNumeric                       131
#define adBoolean                       11
#define adError                         10
#define adUserDefined                   132
#define adVariant                       12
#define adIDispatch                     9
#define adIUnknown                      13
#define adGUID                          72
#define adDate                          7
#define adDBDate                        133
#define adDBTime                        134
#define adDBTimeStamp                   135
#define adBSTR                          8
#define adChar                          129
#define adVarChar                       200
#define adLongVarChar                   201
#define adWChar                         130
#define adVarWChar                      202
#define adLongVarWChar                  203
#define adBinary                        128
#define adVarBinary                     204
#define adLongVarBinary                 205
#define adChapter                       136
#define adFileTime                      64
#define adPropVariant                   138
#define adVarNumeric                    139
#define adArray

#define adRecDeleted                    4

#define adUseNone                       1
#define adUseServer                     2
#define adUseClient                     3
#define adUseClientBatch                3

#define adKeyForeign                    2

#define adStateClosed                   0
#define adStateOpen                     1
#define adStateConnecting               2
#define adStateExecuting                4
#define adStateFetching                 8

#define adSchemaProviderSpecific        -1
#define adSchemaAsserts                 0
#define adSchemaCatalogs                1
#define adSchemaCharacterSets           2
#define adSchemaCollations              3
#define adSchemaColumns                 4
#define adSchemaCheckConstraints        5
#define adSchemaConstraintColumnUsage   6
#define adSchemaConstraintTableUsage    7
#define adSchemaKeyColumnUsage          8
#define adSchemaReferentialContraints   9
#define adSchemaReferentialConstraints  9
#define adSchemaTableConstraints        10
#define adSchemaColumnsDomainUsage      11
#define adSchemaIndexes                 12
#define adSchemaColumnPrivileges        13
#define adSchemaTablePrivileges         14
#define adSchemaUsagePrivileges         15
#define adSchemaProcedures              16
#define adSchemaSchemata                17
#define adSchemaSQLLanguages            18
#define adSchemaStatistics              19
#define adSchemaTables                  20
#define adSchemaTranslations            21
#define adSchemaProviderTypes           22
#define adSchemaViews                   23
#define adSchemaViewColumnUsage         24
#define adSchemaViewTableUsage          25
#define adSchemaProcedureParameters     26
#define adSchemaForeignKeys             27
#define adSchemaPrimaryKeys             28
#define adSchemaProcedureColumns        29
#define adSchemaDBInfoKeywords          30
#define adSchemaDBInfoLiterals          31
#define adSchemaCubes                   32
#define adSchemaDimensions              33
#define adSchemaHierarchies             34
#define adSchemaLevels                  35
#define adSchemaMeasures                36
#define adSchemaProperties              37
#define adSchemaMembers                 38
#define adSchemaTrustees                39
#define adSchemaFunctions               40
#define adSchemaActions                 41
#define adSchemaCommands                42
#define adSchemaSets                    43

#define adAddNew                        0x1000400
#define adApproxPosition                0x0004000
#define adBookmark                      0x0002000
#define adDelete                        0x1000800
#define adFind                          0x0080000
#define adHoldRecords                   0x0000100
#define adIndex                         0x0100000
#define adMovePrevious                  0x0000200
#define adNotify                        0x0040000
#define adResync                        0x0020000
#define adSeek                          0x0200000
#define adUpdate                        0x1008000
#define adUpdateBatch                   0x0010000

#define adCmdUnspecified                -1
#define adCmdUnknown                    8
#define adCmdText                       1
#define adCmdTable                      2
#define adCmdStoredProc                 4
#define adCmdFile                       256
#define adCmdTableDirect                512

#command USE <(db)> [VIA <rdd>] [ALIAS <a>] [<nw: NEW>] ;
            [<ex: EXCLUSIVE>] [<sh: SHARED>] [<ro: READONLY>] ;
            [CODEPAGE <cp>] [INDEX <(index1)> [, <(indexN)>]] ;
            [ TABLE <cTable> ] ;
            [ <dbEngine: ACCESS, MYSQL, ORACLE, INFORMIX, SQL, FIREBIRD> ];
            [ FROM <cServer> ] ;
            [ QUERY <cQuery> ] ;
            [ USER <cUser> PASSWORD <cPassword> ]=> ;
         [ hb_adoSetTable( <cTable> ) ; ] ;
         [ hb_adoSetEngine( <(dbEngine)> ) ; ] ;
         [ hb_adoSetServer( <cServer> ) ; ] ;
         [ hb_adoSetQuery( <cQuery> ) ; ] ;
         [ hb_adoSetUser( <cUser> ); hb_adoSetPassword( <cPassword> ) ; ] ;
         dbUseArea( <.nw.>, <rdd>, <(db)>, <(a)>, ;
                    iif( <.sh.> .OR. <.ex.>, ! <.ex.>, NIL ), <.ro.> [, <cp>] ) ;
         [; dbSetIndex( <(index1)> )] ;
         [; dbSetIndex( <(indexN)> )]

#command LOCATE [FOR <for>] [WHILE <while>] [NEXT <next>] ;
                [RECORD <rec>] [<rest:REST>] [ALL] => ;
         [ hb_adoSetLocateFor( <(for)> ); ] ;
         __dbLocate( <{for}>, <{while}>, <next>, <rec>, <.rest.> )

#endif


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User]
Here is a Harbour (xBase/Clipper) implementation:

Harbour contribution module 'hbnf' (NanForum Toolkit - legacy Clipper compatibility functions): contrib/hbnf/tests/elapsed.prg. Contains procedures: Main. This file provides legacy compatibility functions

[Assistant]
#require "hbnf"

PROCEDURE Main()

   LOCAL dStart, dEnd, cTimeStart, cTimeEnd, n, aDataTest

   dStart := hb_SToD( "19901128" )
   dEnd   := hb_SToD( "19901130" )
   cTimeStart := "08:00:00"
   cTimeEnd   := "12:10:30"

   aDataTest := ft_Elapsed( dStart, dEnd, cTimeStart, cTimeEnd )
   FOR n := 1 TO 4
      ? aDataTest[ n, 1 ], Str( aDataTest[ n, 2 ], 12, 4 )
      ?? " "
      ?? iif( n == 1, "Days", iif( n == 2, "Hours", iif( n == 3, "Mins.", "Secs." ) ) )
   NEXT

   RETURN


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Generate Harbour code for: Harbour Runtime Library file: src/rtl/memoedit.prg. Defines classes: HBMemoEditor. Provides functions: MemoEdit. This file handles database operations

[Assistant]
#include "hbclass.ch"

#include "inkey.ch"
#include "memoedit.ch"
#include "setcurs.ch"
#include "hbgtinfo.ch"

CREATE CLASS HBMemoEditor INHERIT HBEditor

   VAR lCallKeyboardHook AS LOGICAL INIT .F.

   VAR xUserFunction

   METHOD MemoInit( xUserFunction )
   METHOD Edit()
   METHOD KeyboardHook( nKey )
   METHOD IdleHook()

   METHOD HandleUserKey( nKey, nUdfReturn )
   METHOD xDo( nStatus )

   METHOD MoveCursor( nKey )
   METHOD InsertState( lInsState )

   PROTECTED:

   METHOD UserFunctionIsValid()

ENDCLASS

METHOD UserFunctionIsValid() CLASS HBMemoEditor
#ifdef HB_CLP_STRICT
   RETURN HB_ISSTRING( ::xUserFunction )
#else
   RETURN HB_ISSTRING( ::xUserFunction ) .OR. HB_ISEVALITEM( ::xUserFunction )
#endif

METHOD MemoInit( xUserFunction ) CLASS HBMemoEditor

   LOCAL nUdfReturn

   ::xUserFunction := xUserFunction

   IF ::UserFunctionIsValid()

      DO WHILE .T.
         SWITCH nUdfReturn := ::xDo( ME_INIT )

         CASE K_INS
         CASE ME_TOGGLEWRAP
         CASE ME_TOGGLESCROLL

            ::HandleUserKey( , nUdfReturn )
            LOOP
         ENDSWITCH
         EXIT
      ENDDO
   ENDIF

   RETURN Self

METHOD Edit() CLASS HBMemoEditor

   LOCAL nKey, nKeyStd

   LOCAL hConfigurableKeys := { K_CTRL_Y =>, K_CTRL_T =>, K_CTRL_B =>, ;
                                K_CTRL_V =>, K_ALT_W =>, K_ESC => }
   LOCAL bKeyBlock

   IF ::lEditAllow .AND. ::UserFunctionIsValid()

      DO WHILE ! ::lExitEdit

         IF ( nKey := Inkey(, hb_bitOr( Set( _SET_EVENTMASK ), HB_INKEY_EXT ) ) ) == 0
            ::IdleHook()
            nKey := Inkey( 0, hb_bitOr( Set( _SET_EVENTMASK ), HB_INKEY_EXT ) )
         ENDIF
         nKeyStd := hb_keyStd( nKey )

         IF ( bKeyBlock := SetKey( nKeyStd ) ) != NIL
            Eval( bKeyBlock )
            LOOP
         ENDIF

         IF nKeyStd $ hConfigurableKeys
            ::HandleUserKey( nKey, ::xDo( iif( ::lDirty, ME_UNKEYX, ME_UNKEY ) ) )
         ELSE
            ::super:Edit( nKey )
         ENDIF
      ENDDO
   ELSE

      ::super:Edit()
   ENDIF

   RETURN Self

METHOD KeyboardHook( nKey ) CLASS HBMemoEditor

   LOCAL nYesNoKey
   LOCAL cBackScr
   LOCAL nRow
   LOCAL nCol

   IF ::UserFunctionIsValid() .AND. ! ::lCallKeyboardHook

      ::lCallKeyboardHook := .T.
      ::HandleUserKey( nKey, ::xDo( iif( ::lDirty, ME_UNKEYX, ME_UNKEY ) ) )
      ::lCallKeyboardHook := .F.

   ELSEIF hb_keyStd( nKey ) == K_ESC

      IF ::lDirty .AND. Set( _SET_SCOREBOARD )
         cBackScr := SaveScreen( 0, MaxCol() - 19, 0, MaxCol() )

         nRow := Row()
         nCol := Col()
         hb_DispOutAt( 0, MaxCol() - 19, "Abort Edit? (Y/N)" )
         SetPos( 0, MaxCol() - 2 )

         nYesNoKey := Inkey( 0 )

         RestScreen( 0, MaxCol() - 19, 0, MaxCol(), cBackScr )
         SetPos( nRow, nCol )

         IF Upper( hb_keyChar( nYesNoKey ) ) == "Y"
            hb_keySetLast( K_ESC )
            ::lSaved := .F.
            ::lExitEdit := .T.
         ENDIF
      ELSE
         ::lSaved := .F.
         ::lExitEdit := .T.
      ENDIF
   ENDIF

   RETURN Self

METHOD IdleHook() CLASS HBMemoEditor

   IF ::UserFunctionIsValid()
      ::xDo( ME_IDLE )
   ENDIF

   RETURN Self

METHOD HandleUserKey( nKey, nUdfReturn ) CLASS HBMemoEditor

   SWITCH nUdfReturn
   CASE ME_DEFAULT

      IF HB_ISNUMERIC( nKey )

         IF hb_keyStd( nKey ) == K_ESC
            ::lSaved := .F.
            ::lExitEdit := .T.
         ELSE
            ::super:Edit( nKey )
         ENDIF
      ELSE
         RETURN .F.
      ENDIF
      EXIT

   CASE ME_DATA
      IF HB_ISNUMERIC( nKey )

         IF HB_ULen( hb_keyChar( nKey ) ) > 0
            ::super:Edit( nKey )
         ENDIF
      ELSE
         RETURN .F.
      ENDIF
      EXIT

   CASE ME_TOGGLEWRAP
      ::lWordWrap := ! ::lWordWrap
      EXIT

   CASE ME_TOGGLESCROLL

      EXIT

   CASE ME_WORDRIGHT
      ::super:MoveCursor( K_CTRL_RIGHT )
      EXIT

   CASE ME_BOTTOMRIGHT
      ::super:MoveCursor( K_CTRL_END )
      EXIT

#ifndef HB_CLP_STRICT
   CASE ME_PASTE
      hb_gtInfo( HB_GTI_CLIPBOARDPASTE, .T. )
      EXIT
#endif

   CASE ME_IGNORE

      EXIT

   OTHERWISE

      IF ( nUdfReturn >= 1 .AND. nUdfReturn <= 31 ) .OR. nUdfReturn == K_ALT_W
         ::super:Edit( nUdfReturn )
      ELSE
         RETURN .F.
      ENDIF

   ENDSWITCH

   RETURN .T.

METHOD xDo( nStatus ) CLASS HBMemoEditor

   LOCAL nOldRow := ::Row()
   LOCAL nOldCol := ::Col()
   LOCAL nOldCur := SetCursor()

   LOCAL xResult := Do( ::xUserFunction, nStatus, ::nRow, ::nCol - 1 )

   SetPos( nOldRow, nOldCol )
   SetCursor( nOldCur )

   RETURN hb_defaultValue( xResult, ME_DEFAULT )

METHOD MoveCursor( nKey ) CLASS HBMemoEditor

   IF nKey == K_CTRL_W
      ::lSaved := .T.
      ::lExitEdit := .T.
      RETURN .F.
   ENDIF

   RETURN ::super:MoveCursor( nKey )

METHOD InsertState( lInsState ) CLASS HBMemoEditor

   IF HB_ISLOGICAL( lInsState ) .AND. ::lEditAllow
      Set( _SET_INSERT, lInsState )
      SetCursor( iif( lInsState, SC_INSERT, SC_NORMAL ) )
      IF Set( _SET_SCOREBOARD )
         hb_DispOutAt( 0, MaxCol() - 19, iif( lInsState, "<insert>", "        " ) )
      ENDIF
   ENDIF

   RETURN Self

FUNCTION MemoEdit( ;
   cString, ;
   nTop, ;
   nLeft, ;
   nBottom, ;
   nRight, ;
   lEditMode, ;
   xUserFunction, ;
   nLineLength, ;
   nTabSize, ;
   nTextBuffRow, ;
   nTextBuffColumn, ;
   nWindowRow, ;
   nWindowColumn )

   LOCAL oEd

   LOCAL nOldCursor

   hb_default( @nLeft           , 0 )
   hb_default( @nRight          , MaxCol() )
   hb_default( @nLineLength     , nRight - nLeft )
   hb_default( @nTextBuffColumn , 0 )
   hb_default( @nWindowColumn   , nTextBuffColumn )
   hb_default( @cString         , "" )

   oEd := HBMemoEditor():New( cString, ;
      hb_defaultValue( nTop, 0 ), ;
      nLeft, ;
      hb_defaultValue( nBottom, MaxRow() ), ;
      nRight, ;
      hb_defaultValue( lEditMode, .T. ), ;
      nLineLength, ;
      hb_defaultValue( nTabSize, 4 ), ;
      hb_defaultValue( nTextBuffRow, 1 ), ;
      nTextBuffColumn, ;
      hb_defaultValue( nWindowRow, 0 ), ;
      nWindowColumn )
   oEd:MemoInit( xUserFunction )
   oEd:display()

   IF ! HB_ISLOGICAL( xUserFunction )
      nOldCursor := SetCursor()
      oEd:InsertState( Set( _SET_INSERT ) )
      oEd:Edit()
      IF oEd:Saved()
         cString := oEd:GetText( .T. )
      ENDIF
      SetCursor( nOldCursor )
   ENDIF

   RETURN cString


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Implement these Harbour functions: Harbour contribution module 'hbssl' (OpenSSL wrapper for SSL/TLS encryption): contrib/hbssl/ssl_hbcon.prg. Provides functions: hb_SSL_new, hb_SSL_connect_socket, hb_SSL_connect_inet. This file implements security and encryption functions

[Assistant]
FUNCTION hb_SSL_new()

   STATIC s_onceControl

   hb_threadOnce( @s_onceControl, {|| SSL_init(), ;
                  RAND_seed( hb_randStr( 20 ) + hb_TToS( hb_DateTime() ) ) } )

   RETURN SSL_new( SSL_CTX_new() )

FUNCTION hb_SSL_connect_socket( pSocket, nTimeout, cInfo )

   LOCAL nErr
   LOCAL ssl

   ssl := hb_SSL_new()
   IF ! Empty( pSocket := hb_socketNewSSL_connect( @pSocket, ssl, nTimeout ) )
      cInfo := "SSL connected with " + SSL_get_cipher( ssl ) + " encryption."
      RETURN .T.
   ENDIF

   nErr := ERR_get_error()
   cInfo := hb_StrFormat( "SSL connection error [%d] %s", ;
                          nErr, ERR_error_string( nErr ) )
   RETURN .F.

FUNCTION hb_SSL_connect_inet( pInetSock, nTimeout, cInfo )

   LOCAL nResult, nErr
   LOCAL ssl

   ssl := hb_SSL_new()
   IF ( nResult := hb_inetSSL_CONNECT( pInetSock, ssl, nTimeout ) ) == 1
      cInfo := "SSL connected with " + SSL_get_cipher( ssl ) + " encryption."
      RETURN .T.
   ENDIF

   nErr := ERR_get_error()
   cInfo := hb_StrFormat( "SSL connection error [%d:%d] %s", ;
                          nResult, nErr, ERR_error_string( nErr ) )
   RETURN .F.


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Implement this Harbour module: Harbour contribution module 'hbwin' (Windows API wrapper functions): contrib/hbwin/tests/olesrv1.prg. Defines classes: OleNetioSrv. Contains procedures: DllMain. This file provides platform-specific functionality

[Assistant]
#define CLS_Name  "MyOleRPCServer"
#define CLS_ID    "{23245C3F-4487-404B-985F-E33886698D23}"

#include "hbclass.ch"

PROCEDURE DllMain()

   win_oleServerInit( CLS_ID, CLS_Name, {|| OleNetioSrv():new() }, .T. )

   RETURN

CREATE CLASS OleNetioSrv

   HIDDEN:

   VAR    pConn

   EXPORTED:

   METHOD Eval( cMethodName, ... )

ENDCLASS

METHOD Eval( cMethodName, ... ) CLASS OleNetioSrv

   LOCAL xRetVal, oErr

   BEGIN SEQUENCE WITH {| oErr | Break( oErr ) }
      SWITCH cMethodName
      CASE "CONNECT"
         xRetVal := ! Empty( ::pConn := netio_GetConnection( ... ) )
         EXIT
      CASE "DISCONNECT"
         ::pConn := NIL
         xRetVal := .T.
         EXIT
      CASE "PROCEXISTS"
         xRetVal := netio_ProcExists( ::pConn, ... )
         EXIT
      CASE "PROCEXEC"
         xRetVal := netio_ProcExec( ::pConn, ... )
         EXIT
      CASE "PROCEXECW"
         xRetVal := netio_ProcExecW( ::pConn, ... )
         EXIT
      CASE "FUNCEXEC"
         xRetVal := netio_FuncExec( ::pConn, ... )
         EXIT
      OTHERWISE

         xRetVal := netio_FuncExec( ::pConn, cMethodName, ... )
      ENDSWITCH
   RECOVER USING oErr
      xRetVal := oErr
   END SEQUENCE

   RETURN xRetVal

ANNOUNCE GT_SYS
REQUEST HB_GT_GUI_DEFAULT


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User]
Here is a Harbour (xBase/Clipper) implementation:

Harbour contribution module 'gtwvg' (): contrib/gtwvg/drawarea.prg. Defines classes: WvgDrawingArea. This file provides platform-specific functionality

[Assistant]
#include "hbclass.ch"
#include "inkey.ch"
#include "hbgtinfo.ch"

#include "hbgtwvg.ch"
#include "wvtwin.ch"
#include "wvgparts.ch"

CREATE CLASS WvgDrawingArea INHERIT WvgWindow

   VAR    caption                               INIT ""
   VAR    clipParent                            INIT .T.
   VAR    clipSiblings                          INIT .T.

   METHOD new( oParent, oOwner, aPos, aSize, aPresParams, lVisible )
   METHOD create( oParent, oOwner, aPos, aSize, aPresParams, lVisible )
   METHOD destroy()
   METHOD handleEvent( nMessage, aNM )

ENDCLASS

METHOD WvgDrawingArea:new( oParent, oOwner, aPos, aSize, aPresParams, lVisible )

   ::wvgWindow:new( oParent, oOwner, aPos, aSize, aPresParams, lVisible )

   ::style       := WS_CHILD
   ::exStyle     := 0
   ::className   := "DrawingArea"
   ::objType     := objTypeDA
   ::visible     := .T.

   RETURN Self

METHOD WvgDrawingArea:create( oParent, oOwner, aPos, aSize, aPresParams, lVisible )

   HB_SYMBOL_UNUSED( lVisible )

   ::wvgWindow:create( oParent, oOwner, aPos, aSize, aPresParams, .T. )

   ::oParent:addChild( Self )

   wvg_RegisterClass_ByName( ::className() )

   ::createControl()

   ::SetWindowProcCallback()
   ::show()

   RETURN Self

METHOD WvgDrawingArea:handleEvent( nMessage, aNM )

   DO CASE
   CASE nMessage == HB_GTE_RESIZED
      IF HB_ISBLOCK( ::sl_resize )
         Eval( ::sl_resize, , , Self )
      ENDIF
      AEval( ::aChildren, {| o | o:handleEvent( HB_GTE_RESIZED, { 0, 0, 0, 0, 0 } ) } )
      RETURN EVENT_HANDELLED

   CASE nMessage == HB_GTE_CTLCOLOR
      IF HB_ISNUMERIC( ::clr_FG )
         wvg_SetTextColor( aNM[ 1 ], ::clr_FG )
      ENDIF
      IF HB_ISNUMERIC( ::hBrushBG )
         wvg_SetBkMode( aNM[ 1 ], 1 )
         wvg_FillRect( aNM[ 1 ], { 0, 0, ::currentSize()[ 1 ], ::currentSize()[ 2 ] }, ::hBrushBG )
         RETURN EVENT_HANDELLED
      ENDIF

   ENDCASE

   RETURN EVENT_UNHANDELLED

METHOD PROCEDURE WvgDrawingArea:destroy()

   ::wvgWindow:destroy()

   RETURN


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User]
Write the following Harbour (xBase/Clipper) code:

Harbour test program: tests/rddtest/rddtst.prg. Provides 6 functions including: test_init, test_close, rdd_state, itm2str, rddtst_wr. Contains procedures: main, main, rdd_retval. This file handles database operations

[Assistant]
#ifndef N_LOOP
  #define N_LOOP 15
#endif

#ifndef EOL
  #define EOL chr( 13 ) + chr( 10 )
#endif

#command ? => outstd(EOL)
#command ? <xx,...> => outstd(<xx>, EOL)
#command ?? =>
#command ?? <xx,...> => outstd(<xx>)

#ifdef _TEST_CREATE_
  #command RDDTESTC <*x*> => <x>; rddtst_wr( #<x> )
  #command RDDTESTF <x> => rddtst_wr( #<x>, <x> )
  #command RDDTEST  <*x*> => RDDTESTC <x>
  #command RDDTEST  <x> => RDDTESTF <x>
#else
  #command RDDTESTC <s>, <*x*> => <x>; rddtst_tst( #<x>, <s> )
  #command RDDTESTF <r>, <s>, <x> => rddtst_tst( #<x>, <s>, <x>, <r> )

#endif
#define _DBNAME "_tst"

REQUEST DBFCDX
field FSTR, FNUM

#include "fileio.ch"

#ifdef _TEST_CREATE_
  static s_hMake := F_ERROR
#endif
static s_nTested := 0
static s_nErrors := 0

static aBadRetFunc:={ "DBSKIP", "DBGOTO", "DBDELETE", "DBRECALL", ;
                      "DBUNLOCK", "DBCOMMIT" }

#ifdef _TEST_SCOPE_
#include "ord.ch"
#include "dbinfo.ch"
#endif

#ifdef __HARBOUR__
#ifdef _TEST_ADS_
#include "ads.ch"
REQUEST ADS
init proc adstest_init()
rddRegister( "ADS", 1 )
AdsSetServerType( ADS_LOCAL_SERVER )

return
#endif
#endif

#ifdef _TEST_CREATE_
  procedure main( cOutFile, rdd )
  test_init( rdd, cOutFile )
  test_main()
  test_close()
  return
#else
  procedure main( rdd )
  test_init( rdd )
  test_main()
  test_close()
  return
#endif

static function test_init(rdd,cOutFile)
local n, cOut, aDb := { { "FSTR", "C", 10, 0 }, { "FNUM", "N", 10, 0 } }

if empty(rdd)
  #ifdef _TESTRDD
    rdd := _TESTRDD
  #else
    rdd := "DBFCDX"
  #endif
endif
rddSetDefault(rdd)
#ifdef _TEST_CREATE_
  if empty( cOutFile )
    ? "Syntax: <outfile.prg> [<rddname>]"
    quit
  elseif ( s_hMake := fcreate( cOutFile ) ) == F_ERROR
    ? "Cannot create file: ", cOutFile
    quit
  endif
  cOut:=""
  #ifdef _TEST_ADS_
    cOut += '#define _TEST_ADS_'+EOL
  #endif
  cOut +=;
        'REQUEST ' + rdd + EOL +;
        '#define _TESTRDD "' + rdd + '"' + EOL +;
        '#include "rddtst.prg"' + EOL +;
        EOL +;
        'FUNCTION test_main()' + EOL +;
        EOL
  if ! fwrite( s_hMake, cOut ) == len( cOut )
    ? "write error."
    quit
  endif
#endif

aeval( directory( "./" + _DBNAME + ".??x" ), {| x | ferase( x[ 1 ] ) } )
aeval( directory( "./TG_?.??x" ), {| x | ferase( x[ 1 ] ) } )
ferase( "./"+_DBNAME+".dbf" )
? "RDD: " + rdd
? "creating databse and index..."
dbcreate( _DBNAME, aDb )

return nil

static function test_close()
local cOut
#ifdef _TEST_CREATE_
  if s_hMake != F_ERROR
    cOut :=EOL +;
          'RETURN NIL' + EOL
    if ! fwrite( s_hMake, cOut ) == len( cOut )
      ? "write error."
      quit
    endif
    fclose( s_hMake )
  endif
#else
  ?
  ? "Number of tests: " + ltrim( str( s_nTested ) )
  ? "Number of errors: " + ltrim( str( s_nErrors ) )
#endif
dbclosearea()
aeval( directory( "./" + _DBNAME + ".??x" ), {| x | ferase( x[ 1 ] ) } )
aeval( directory( "./TG_?.??x" ), {| x | ferase( x[ 1 ] ) } )
ferase( "./" + _DBNAME + ".dbf" )
?
return nil

static procedure rdd_retval()
return

static function rdd_state()
return { recno(), bof(), eof(), found() }

static function itm2str( itm )
local cStr := "", i
if itm == NIL
  cStr += "NIL"
elseif valtype( itm ) == "C"
  cStr += '"' + strtran( itm, '"', '" + chr( 34 ) + "') + '"'
elseif valtype( itm ) == "N"
  cStr += ltrim( str( itm ) )
elseif valtype( itm ) == "L"
  cStr += iif( itm, ".T.", ".F." )
elseif valtype( itm ) == "D"
  cStr += "CTOD(" + DTOC( itm ) + ")"
elseif valtype( itm ) == "B"
  cStr += "{||" + itm2str( eval( itm ) ) + "}"
elseif valtype( itm ) == "A"
  cStr += "{"
  for i:=1 to len( itm )
    cStr += iif( i == 1, "", "," ) + itm2str( itm[ i ] )
  next
  cStr += "}"
endif
return cStr

#ifdef _TEST_CREATE_
  static function rddtst_wr( cAction, xRet )
  local aState, cOut

  if ascan( aBadRetFunc, {| x | upper( cAction ) = x + "(" } ) != 0
    xRet := NIL
  endif
  aState := rdd_state()
  if pcount() > 1
    cOut:="RDDTESTF " + itm2str( xRet ) + ", " + itm2str( aState ) + ", " + cAction + EOL
  else
    cOut:="RDDTESTC " + itm2str( aState ) + ", " + cAction + EOL
  endif
  if ! fwrite( s_hMake, cOut ) == len( cOut )
    ? "write error."
    quit
  endif
  return nil
#else

  static function rddtst_tst( cAction, aExState, xRet, xExRet )
  local aState, lOK := ( .T. ), s1, s2, i

  aState := rdd_state()
  if pcount() >= 4
    if ascan( aBadRetFunc, {| x | upper( cAction ) = x + "(" } ) != 0
      xRet := NIL
    endif
    if ! valtype( xRet ) == valtype( xExRet ) .or.;
       ! iif( valtype( xRet ) == "B", eval( xRet ) == eval( xExRet ), xRet == xExRet )
      lOK := ( .F. )
    endif
    s1 := itm2str( xRet )
    s2 := itm2str( xExRet )
    s1 := padr( s1, max( len( s1 ), len( s2 ) ) + 1 )
    s2 := padr( s2, len( s1 ) )
  else
    s1 := s2 := ""
  endif
  if ! empty( aExState ) .and. lOK
    for i := 1 to len( aExState )
      if ! valtype( aState[ i ] ) == valtype( aExState[ i ] ) .or. ! aState[ i ] == aExState[ i ]
        lOK := ( .F. )
        exit
      endif
    next
  endif
  ?
  ?? iif( lOK, "OK  ", "ERR " ) + cAction + " => " + s1 + itm2str( aState )
  if ! lOK
    ?
    ?? "    " + cAction + " => " + s2 + itm2str( aExState )
    s_nErrors++
  endif
  s_nTested++
  return nil
#endif


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Define Harbour macros and constants: Harbour contribution module 'hbct' (CA-Tools compatibility library): contrib/hbct/tests/charrlr.prg. Contains procedures: Main. This file provides legacy compatibility functions

[Assistant]
#ifdef __HARBOUR__
#require "hbct"
#else
#define hb_ntos( n ) LTrim( Str( n ) )
#define hb_BChar( n ) Chr( n )
#endif

PROCEDURE Main()

   LOCAL ni, cStr

   ctinit()

   ? "Begin test of CharRlr()"
   ?

   ? "Simple tests:"
   ? '  CharRlr( hb_BChar(  1 ) + hb_BChar(  2 ) + hb_BChar(   4 ) + hb_BChar( 8 ) + hb_BChar( 16 ) + hb_BChar( 32 ) + hb_BChar( 64 ) + hb_BChar( 128 ), 3 ) =='
   ? '           hb_BChar( 32 ) + hb_BChar( 64 ) + hb_BChar( 128 ) + hb_BChar( 1 ) + hb_BChar(  2 ) + hb_BChar(  4 ) + hb_BChar(  8 ) + hb_BChar(  16 ) ? -->'

   ? '           '
   cStr := CharRlr( hb_BChar( 1 ) + hb_BChar( 2 ) + hb_BChar( 4 ) + hb_BChar( 8 ) + hb_BChar( 16 ) + hb_BChar( 32 ) + hb_BChar( 64 ) + hb_BChar( 128 ), 3 )
   FOR ni := 1 TO Len( cStr )
      ?? "hb_BChar( " + hb_ntos( Asc( SubStr( cStr, ni, 1 ) ) ) + " )"
      IF ni < Len( cStr )
         ?? " + "
      ENDIF
   NEXT
   ?

   ? "End test of CharRlr()"
   ?

   ctexit()

   RETURN


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User]
Here is a Harbour (xBase/Clipper) implementation:

Harbour contribution module 'xhb' (Extended Harbour functions): contrib/xhb/dbgfx.prg. Provides functions: hb_ToOutDebugOnOff, hb_ToLogFileOnOff, hb_EmptyLogFileOnOff. Contains procedures: hb_ToOutDebug, hb_ToLogFile. This file provides legacy compatibility functions

[Assistant]
#include "fileio.ch"

STATIC s_lToOutDebug   := .T.
STATIC s_lToLogFile    := .T.
STATIC s_lEmptyLogFile := .T.

FUNCTION hb_ToOutDebugOnOff( lOnOff )

   LOCAL lOld := s_lToOutDebug

   IF HB_ISLOGICAL( lOnOff )
      s_lToOutDebug := lOnOff
   ENDIF

   RETURN lOld

PROCEDURE hb_ToOutDebug( ... )

   IF s_lToOutDebug
      hb_OutDebug( sprintf( ... ) )
   ENDIF

   RETURN

FUNCTION hb_ToLogFileOnOff( lOnOff )

   LOCAL lOld := s_lToLogFile

   IF HB_ISLOGICAL( lOnOff )
      s_lToLogFile := lOnOff
   ENDIF

   RETURN lOld

FUNCTION hb_EmptyLogFileOnOff( lOnOff )

   LOCAL lOld := s_lEmptyLogFile

   IF HB_ISLOGICAL( lOnOff )
      s_lEmptyLogFile := lOnOff
   ENDIF

   RETURN lOld

PROCEDURE hb_ToLogFile( cLogFile, ... )

   LOCAL nHandle

   IF ! s_lToLogFile
      RETURN
   ENDIF

   __defaultNIL( @cLogFile, "logfile.log" )

   IF cLogFile != NIL

      IF ! s_lEmptyLogFile .AND. hb_FileExists( cLogFile )
         nHandle := FOpen( cLogFile, FO_READWRITE + FO_SHARED )
      ELSE
         nHandle := FCreate( cLogFile )
         s_lEmptyLogFile := .F.

         IF FError() == 0 .AND. nHandle != F_ERROR
            FClose( nHandle )
            nHandle := FOpen( cLogFile, FO_READWRITE + FO_SHARED )
         ENDIF
      ENDIF

      IF nHandle != F_ERROR
         FSeek( nHandle, 0, FS_END )
         FWrite( nHandle, sprintf( ... ) )
         FWrite( nHandle, hb_eol() )
         FClose( nHandle )
      ENDIF
   ENDIF

   RETURN


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Write Harbour functions: ft_Pending. Harbour contribution module 'hbnf' (NanForum Toolkit - legacy Clipper compatibility functions): contrib/hbnf/pending.prg. Provides functions: ft_Pending. This file provides legacy compatibility functions

[Assistant]
FUNCTION ft_Pending( cMsg, nRow, nCol, nWait, cColor )

   THREAD STATIC t_nRow1 := 24
   THREAD STATIC t_nCol1 := 0
   THREAD STATIC t_nWait1 := 5
   THREAD STATIC t_cColor1 := "W+/R,X"

   THREAD STATIC t_nLast_Time := 0

   LOCAL nThis_Time

   IF cMsg != NIL

      t_nRow1   := iif( nRow != NIL, nRow, t_nRow1 )
      t_nCol1   := iif( nCol != NIL, nCol, t_nCol1 )
      t_nWait1  := iif( nWait != NIL, nWait, t_nWait1 )
      t_cColor1 := iif( cColor != NIL, cColor, t_cColor1 )

      nThis_Time := Seconds()

      IF t_nLast_Time == 0
         t_nLast_Time := nThis_Time - t_nWait1
      ENDIF

      IF ( nThis_Time - t_nLast_Time ) < 0.1
         t_nLast_Time := nThis_Time + t_nWait1
         Inkey( t_nWait1 )
      ELSE
         t_nLast_Time := nThis_Time
      ENDIF

      hb_Scroll( t_nRow1, 0, t_nRow1, 80 )

      hb_DispOutAt( t_nRow1, t_nCol1, cMsg, t_cColor1 )

   ENDIF

   RETURN NIL


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Implement these Harbour functions: Harbour contribution module 'xhb' (Extended Harbour functions): contrib/xhb/xcstr.prg. Provides 12 functions including: CStrToVal, StringToLiteral, ValToPrg, PrgExpToVal, ValToArray. This file provides legacy compatibility functions

[Assistant]
#include "error.ch"

#include "hbclass.ch"

#define CRLF Chr( 13 ) + Chr( 10 )

#xtranslate Throw( <oErr> ) => ( Eval( ErrorBlock(), <oErr> ), Break( <oErr> ) )

FUNCTION CStrToVal( cExp, cType )

   IF ! HB_ISSTRING( cExp )
      Throw( xhb_ErrorNew( "CSTR", 0, 3101, ProcName(), "Argument error", { cExp, cType } ) )
   ENDIF

   SWITCH cType
   CASE "C"
      RETURN cExp

   CASE "P"
      RETURN hb_HexToNum( cExp )

   CASE "D"
      IF IsDigit( SubStr( cExp, 3, 1 ) ) .AND. IsDigit( SubStr( cExp, 5, 1 ) )
         RETURN hb_SToD( cExp )
      ELSE
         RETURN CToD( cExp )
      ENDIF

   CASE "T"
      IF IsDigit( SubStr( cExp, 3, 1 ) ) .AND. ;
         IsDigit( SubStr( cExp, 5, 1 ) ) .AND. ;
         IsDigit( SubStr( cExp, 7, 1 ) )
         RETURN hb_SToT( cExp )
      ELSE
         RETURN hb_StrToTS( cExp )
      ENDIF

   CASE "L"
      RETURN SubStr( cExp, 1, 1 ) $ "TY" .OR. SubStr( cExp, 2, 1 ) $ "TY"

   CASE "N"
      RETURN Val( cExp )

   CASE "U"
      RETURN NIL

   OTHERWISE
      Throw( xhb_ErrorNew( "CSTRTOVAL", 0, 3101, ProcName(), "Argument error", { cExp, cType } ) )
   ENDSWITCH

   RETURN NIL

FUNCTION StringToLiteral( cString )

   LOCAL lDouble := .F.
   LOCAL lSingle := .F.

   IF hb_regexHas( "\n|\r", cString ) .OR. ;
      ( ( lDouble := '"' $ cString ) .AND. ;
        ( lSingle := "'" $ cString ) .AND. ;
      hb_regexHas( "\[|\]", cString ) )

      cString := StrTran( cString, '"', '\"' )
      cString := StrTran( cString, Chr( 10 ), "\n" )
      cString := StrTran( cString, Chr( 13 ), "\r" )

      RETURN 'E"' + cString + '"'
   ELSEIF ! lDouble
      RETURN '"' + cString + '"'
   ELSEIF ! lSingle
      RETURN "'" + cString + "'"
   ENDIF

   RETURN "[" + cString + "]"

FUNCTION ValToPrg( xVal, cName, nPad, hRefs )

   LOCAL aVar, cRet, cPad, cRef, pRef

   SWITCH ValType( xVal )
   CASE "C"
      RETURN StringToLiteral( xVal )

   CASE "D"
      RETURN "hb_SToD( '" + DToS( xVal ) + "' )"

   CASE "T"
      RETURN 't"' + hb_TSToStr( xVal, .T. ) + '"'

   CASE "L"
      RETURN iif( xVal, ".T.", ".F." )

   CASE "N"
      RETURN hb_ntos( xVal )

   CASE "A"
      pRef := __vmItemId( xVal )
      IF cName == NIL
         nPad := 0
         cName := "M->__ValToPrg_Array"
         hRefs := { => }
         cRet  := cName + " := "
      ELSEIF ! ( cRef := hb_HGetDef( hRefs, pRef ) ) == NIL
         RETURN cRef + " "
      ELSE
         cRet := ""
      ENDIF

      hRefs[ pRef ] := cName

      cRet  += "Array(" + hb_ntos( Len( xVal ) ) + ")" + CRLF

      nPad += 3
      cPad  := Space( nPad )

      FOR EACH aVar IN xVal
         cRef := cName + "[" + hb_ntos( aVar:__EnumIndex() ) + "]"
         cRet += cPad + cRef + " := " + ValToPrg( aVar, cRef, nPad, hRefs )
         IF ! Right( cRet, Len( CRLF ) ) == CRLF
            cRet += CRLF
         ENDIF
      NEXT

      nPad -= 3
      RETURN cRet

   CASE "H"
      pRef := __vmItemId( xVal )
      IF cName == NIL
         nPad := 0
         cName := "M->__ValToPrg_Hash"
         hRefs := { => }
         cRet  := cName + " := "
      ELSEIF ! ( cRef := hb_HGetDef( hRefs, pRef ) ) == NIL
         RETURN cRef + " "
      ELSE
         cRet := ""
      ENDIF

      hRefs[ pRef ] := cName

      cRet  += "{ => }" + CRLF

      nPad += 3
      cPad  := Space( nPad )

      FOR EACH aVar IN xVal
         cRef := cName + "[" + ValToPrg( aVar:__EnumKey() ) + "]"
         cRet += cPad + cRef + " := " + ValToPrg( aVar, cRef, nPad, hRefs )
         IF ! Right( cRet, Len( CRLF ) ) == CRLF
            cRet += CRLF
         ENDIF
      NEXT

      nPad -= 3
      RETURN cRet

   CASE "B"

      RETURN "{||  }"

   CASE "P"
      RETURN "0x" + hb_NumToHex( xVal )

   CASE "O"

      pRef := __vmItemId( xVal )
      IF cName == NIL
         cName := "M->__ValToPrg_Object"
         nPad := 0
         hRefs := { => }
         cRet  := cName + " := "
      ELSEIF ! ( cRef := hb_HGetDef( hRefs, pRef ) ) == NIL
         RETURN cRef + " "
      ELSE
         cRet := ""
      ENDIF

      hRefs[ pRef ] := cName

      cRet += xVal:ClassName + "():New()" + CRLF

      nPad += 3
      cPad := Space( nPad )

      FOR EACH aVar IN __objGetValueList( xVal )
         cRef := cName + ":" + aVar[ 1 ]
         cRet += cPad + cRef + " := " + ValToPrg( aVar[ 2 ], cRef, nPad, hRefs )
         IF ! Right( cRet, Len( CRLF ) ) == CRLF
            cRet += CRLF
         ENDIF
      NEXT

      nPad -= 3
      RETURN cRet

   OTHERWISE

      IF xVal == NIL
         cRet := "NIL"
      ELSE
         Throw( xhb_ErrorNew( "VALTOPRG", 0, 3103, ProcName(), "Unsupported type: " + ValType( xVal ), { xVal } ) )
      ENDIF
   ENDSWITCH

   RETURN cRet

FUNCTION PrgExpToVal( cExp )

   RETURN Eval( hb_macroBlock( cExp ) )

FUNCTION ValToArray( xVal )

   IF HB_ISARRAY( xVal )
      RETURN xVal
   ENDIF

   RETURN { xVal }

FUNCTION ValToBlock( xVal )

   IF HB_ISBLOCK( xVal )
      RETURN xVal
   ENDIF

   RETURN {|| xVal }

FUNCTION ValToCharacter( xVal )

   IF HB_ISSTRING( xVal )
      RETURN xVal
   ENDIF

   RETURN LTrim( CStr( xVal ) )

FUNCTION ValToDate( xVal )

   SWITCH ValType( xVal )
   CASE "A"
   CASE "H"
   CASE "L"
   CASE "O"
   CASE "U"
      EXIT

   CASE "B"
      RETURN ValToDate( Eval( xVal ) )

   CASE "C"
      RETURN iif( IsDigit( SubStr( xVal, 3, 1 ) ) .AND. ;
                  IsDigit( SubStr( xVal, 5, 1 ) ), hb_SToD( xVal ), ;
                                                   CToD( xVal ) )

   CASE "D"
      RETURN xVal

   CASE "T"
      RETURN hb_TToD( xVal )

   CASE "N"
      RETURN d"1900-01-01" + xVal

   CASE "P"
      RETURN d"1900-01-01" + hb_HexToNum( hb_NumToHex( xVal ) )

   OTHERWISE
      Throw( xhb_ErrorNew( "VALTODATE", 0, 3103, ProcName(), "Unsupported type", { xVal } ) )
   ENDSWITCH

   RETURN hb_SToD()

FUNCTION ValToTimeStamp( xVal )

   SWITCH ValType( xVal )
   CASE "A"
   CASE "H"
   CASE "L"
   CASE "O"
   CASE "U"
      EXIT

   CASE "B"
      RETURN ValToTimeStamp( Eval( xVal ) )

   CASE "C"
      RETURN iif( IsDigit( SubStr( xVal, 3, 1 ) ) .AND. ;
                  IsDigit( SubStr( xVal, 5, 1 ) ) .AND. ;
                  IsDigit( SubStr( xVal, 7, 1 ) ), hb_SToT( xVal ), ;
                                                   hb_StrToTS( xVal ) )

   CASE "D"
      RETURN hb_DToT( xVal )

   CASE "T"
      RETURN xVal

   CASE "N"
      RETURN t"1900-01-01" + xVal

   CASE "P"
      RETURN t"1900-01-01" + hb_HexToNum( hb_NumToHex( xVal ) )

   OTHERWISE
      Throw( xhb_ErrorNew( "VALTODATE", 0, 3103, ProcName(), "Unsupported type", { xVal } ) )
   ENDSWITCH

   RETURN hb_SToD()

FUNCTION ValToHash( xVal )

   IF HB_ISHASH( xVal )
      RETURN xVal
   ENDIF

   RETURN { ValToCharacter( xVal ) => xVal }

FUNCTION ValToLogical( xVal )

   SWITCH ValType( xVal )
   CASE "A"
   CASE "D"
   CASE "T"
   CASE "H"
   CASE "N"
   CASE "O"
   CASE "P"
      RETURN ! Empty( xVal )

   CASE "B"
      RETURN ValToLogical( Eval( xVal ) )

   CASE "C"
      IF Left( xVal, 1 ) == "." .AND. SubStr( xVal, 3, 1 ) == "." .AND. Upper( SubStr( xVal, 2, 1 ) ) $ "TFYN"
         RETURN Upper( SubStr( xVal, 2, 1 ) ) $ "TY"
      ELSEIF Len( xVal ) == 1 .AND. Upper( xVal ) $ "TFYN"
         RETURN Upper( xVal ) $ "TY"
      ELSE
         RETURN ! Empty( xVal )
      ENDIF
      EXIT

   CASE "L"
      RETURN xVal

   CASE "U"
      RETURN .F.

   OTHERWISE
      Throw( xhb_ErrorNew( "VALTOLOGICAL", 0, 3103, ProcName(), "Unsupported type", { xVal } ) )
   ENDSWITCH

   RETURN .F.

FUNCTION ValToNumber( xVal )

   SWITCH ValType( xVal )
   CASE "A"
   CASE "H"
      RETURN Len( xVal )

   CASE "B"
      RETURN ValToNumber( Eval( xVal ) )

   CASE "C"
      RETURN Val( xVal )

   CASE "D"
   CASE "T"
      RETURN xVal - 0d19000101

   CASE "L"
      RETURN iif( xVal, 1, 0 )

   CASE "O"
      RETURN xVal:hClass

   CASE "N"
      RETURN xVal

   CASE "P"
      RETURN xVal - 0

   CASE "U"
      RETURN 0

   OTHERWISE


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Generate Harbour code for: Harbour contribution module 'hbct' (CA-Tools compatibility library): contrib/hbct/tests/chareven.prg. Contains procedures: Main. This file provides legacy compatibility functions

[Assistant]
#ifdef __HARBOUR__
#require "hbct"
#endif

PROCEDURE Main()

   ctinit()

   ? "Begin test of CharEven()"
   ?

   ? "Simple tests:"
   ? '  CharEven( " 1 2 3 4 5" ) == "12345" ? --> "' + CharEven( " 1 2 3 4 5" ) + '"'
   ? '  CharEven( " 1 2 3 4 " )  == "1234"  ? --> "' + CharEven( " 1 2 3 4 " )  + '"'
   ? '  CharEven( " " )          == ""      ? --> "' + CharEven( " " )          + '"'

   ? "End test of CharEven()"
   ?

   ctexit()

   RETURN


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Generate Harbour code for: Harbour contribution module 'hbmisc' (Miscellaneous utility functions): contrib/hbmisc/tests/numtxtru.prg. Contains procedures: Main, Test. This file provides utility functions

[Assistant]
#require "hbmisc"

#include "inkey.ch"

REQUEST HB_CODEPAGE_UTF8EX

PROCEDURE Main()

   CLS

   hb_cdpSelect( "UTF8EX" )
   hb_SetTermCP( "UTF8EX" )

   ? "Press ESC to break"
   ? "Russian"
   Test( "ru" )
   ? "Ukrainian"
   Test( "uk" )
   ? "Belorussian"
   Test( "be" )

   RETURN

PROCEDURE Test( cLang )

   LOCAL nTemp

   FOR nTemp := 1 TO 1000000000
      OutStd( ;
         PadR( MnyToTxtRU( nTemp + ( nTemp % 100 ) * 0.01, cLang, , 3 ), 100 ) + " " + ;
         PadR( NumToTxtRU( nTemp, cLang, , .T. ), 100 ) + " " + ;
         PadR( DateToTxtRU( Date() + nTemp, cLang, .T. ), 50 ) + hb_eol() )
      IF nTemp % 1000 == 0
         ? nTemp
      ENDIF
      IF nTemp % 10000 == 0
         IF Inkey() == K_ESC
            EXIT
         ENDIF
      ENDIF
   NEXT

   RETURN


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Implement this Harbour module: Harbour contribution module 'hbtinymt' (Tiny Mersenne Twister PRNG): contrib/hbtinymt/tests/test64.prg. Contains procedures: Main, TestMatrix. This file provides utility functions

[Assistant]
#require "hbtinymt"

PROCEDURE Main()

   SET DECIMAL TO 0

   IF tinymt64_init( 0x123, 0x234, 0x345 )
      TestMatrix( "64-bit unsigned integers r, where 0 <= r < 2^64", {|| PadL( tinymt64_generate_uint64(), 22 ) } )
   ENDIF

   SET DECIMAL TO 22

   IF tinymt64_init_by_array( { 0x123, 0x234, 0x345 } )
      TestMatrix( "Double numbers r, where 0.0 <= r < 1.0", {|| PadL( tinymt64_generate_double(), 30 ) } )
      TestMatrix( "Double numbers r, where 0.0 <= r < 1.0", {|| PadL( tinymt64_generate_double01(), 30 ) } )
      TestMatrix( "Double numbers r, where 1.0 <= r < 2.0", {|| PadL( tinymt64_generate_double12(), 30 ) } )
      TestMatrix( "Double numbers r, where 0.0 < r <= 1.0", {|| PadL( tinymt64_generate_doubleOC(), 30 ) } )
      TestMatrix( "Double numbers r, where 0.0 < r <  1.0", {|| PadL( tinymt64_generate_doubleOO(), 30 ) } )
   ENDIF

   RETURN

STATIC PROCEDURE TestMatrix( cDescription, bBlock )

   LOCAL i, j

   ? cDescription
   FOR i := 1 TO 10
      FOR j := 1 TO 5
         ? Eval( bBlock )
      NEXT
      ?
   NEXT
   ?

   RETURN


[System] You are an expert Harbour (xBase/Clipper) programmer. Write clean, efficient code following Harbour conventions. Use proper Hungarian notation for variable names (c=character, n=numeric, l=logical, a=array, o=object, b=codeblock).

[User] Generate Harbour code for: Harbour test program: tests/parseini.prg. Contains procedures: Main. This test file tests specific function APIs

[Assistant]
PROCEDURE Main( cName )

   LOCAL hIni, aSect, cIni
   LOCAL cSection
   LOCAL cKey
   LOCAL nRow := 1

   SET COLOR TO w+/b
   CLS
   @ nRow++, 20 SAY "H A R B O U R - .ini file parser test"
   @ nRow++, 5 SAY "Call from command line using a .ini filename as the only parameter"
   nRow++

   IF Empty( cName )
      cName := "parseini.ini"
      @ nRow++, 5 SAY "Using default parseini.ini file"
   ENDIF

   hIni := hb_iniRead( cName )

   @ nRow, 0

   ? "Content of " + cName

   IF Empty( hIni )
      ? "Not a valid .ini file!"
   ELSE
      FOR EACH cSection IN hIni:Keys
         ?
         ? "Section [" + cSection + "]"
         aSect := hIni[ cSection ]

         FOR EACH cKey IN aSect:Keys
            ? cKey + " = " + aSect[ cKey ]
         NEXT
      NEXT
   ENDIF

   ?
   ? "Adding section 'Added', with key NEW = new"
   hIni[ "Added" ] := { => }
   hIni[ "Added" ][ "NEW" ] := "new"

   ? "Writing output to parseini_out.ini"
   IF hb_iniWrite( "parseini_out.ini", hIni, "#Generated file; don't touch", "#End of file" )
      ? "File written"
   ELSE
      ? "Can't write file"
   ENDIF
   ?
   ? "Press any key to next text."
   Inkey( 0 )

   nRow := 3
   @ nRow, 0 CLEAR
   ?
   ? "REPEATING TESTS WITHOUT AUTOMATIC MAIN SECTION"
   ?

   hIni := hb_iniRead( cName,;
                       ,;
                       , .F. )

   ? "Content of " + cName

   IF Empty( hIni )
      ? "Not a valid .ini file!"
   ELSE
      FOR EACH cSection IN hIni:Keys

         aSect := hIni[ cSection ]

         IF HB_ISHASH( aSect )

            ?
            ? "Section [" + cSection + "]"

            FOR EACH cKey IN aSect:Keys
               ? cKey + " = " + aSect[ cKey ]
            NEXT
         ELSE

            ? "TOPLEVEL option:", cSection + " = " + aSect
         ENDIF
      NEXT
   ENDIF

   ?
   ? "Adding section 'Added', with key NEW = new"
   hIni[ "Added" ] := { => }
   hIni[ "Added" ][ "NEW" ] := "new"

   ? "Writing output to parseini_out1.ini"
   IF hb_iniWrite( "parseini_out1.ini", hIni,;
                   "#Generated file without main auto section; don't touch", "#End of file",;
                   .F. )
      ? "File written"
   ELSE
      ? "Can't write file"
   ENDIF
   ?
   ? "Press any key to next text."
   Inkey( 0 )

   nRow := 3
   @ nRow, 0 CLEAR
   ?
   ? "WRITING INI TO A STRING"
   ?

   cIni := hb_iniWriteStr( hIni )

   ? "Content of hIni : "
   ?
   ? cIni
   ?
   ? "Press any key to next text."
   Inkey( 0 )

   nRow := 3
   @ nRow, 0 CLEAR
   ?
   ? "READING INI FILE FROM A STRING"
   ?

   hIni := hb_iniReadStr( cIni,;
            ,;
            , .F. )

   ? "Content: "

   IF Empty( hIni )
      ? "Not a valid .ini file!"
   ELSE
      FOR EACH cSection IN hIni:Keys

         aSect := hIni[ cSection ]

         IF HB_ISHASH( aSect )

            ?
            ? "Section [" + cSection + "]"

            FOR EACH cKey IN aSect:Keys
               ? cKey + " = " + aSect[ cKey ]
            NEXT
         ELSE

            ? "TOPLEVEL option:", cSection + " = " + aSect
         ENDIF
      NEXT
   ENDIF

   ?
   ? "Press any key to next text."
   Inkey( 0 )

   nRow := 3
   @ nRow, 0 CLEAR
   ?
   ? "WRITING INI FILE TO A STRING "
   ?

   cIni := hb_iniWriteStr( hb_iniRead( cName ) )

   ? "Content of " + cName
   ?
   ? cIni
   ?
   ? "Press any key to next text."
   Inkey( 0 )

   RETURN