/* Include files required to compile */
#include "dmlb.ch"
#include "Gra.ch"
#include "Xbp.ch"
#include "font.ch"
#include "common.ch"
#include "AppEvent.ch"
#include "fileio.ch"
#include "Set.ch"
#include "Dll.ch"
#include "Appbrow.ch"
#include "class.ch"
#include "inkey.ch"
#include "Nls.ch"
#include "DelDbe.ch"
#include "SdfDbe.ch"
#include "Error.ch"
#include "DbStruct.ch"

*************************************************************************
*                                                                       *
* Function : XoExport(cFile, aFieldArray, bFor, bWhile, nNext,          *
*                      nRecord, lRest, cEngine, aDbeInfo, lStopOnError, *
*                       lAppend)                                        *
*                                                                       *
* Replacement for DbExport Routine which doesn't crash upon an error    *
*                                                                       *
*************************************************************************

FUNCTION XoExport(cFile, aFieldArray, bFor, bWhile, nNext, nRecord, lRest, cEngine, aDbeInfo, lStopOnError, lAppend)

  /* Local variable declaration */
  LOCAL nTargetArea, nSourceArea:=Select(), aInputStructure:=DbStruct(), aOutputStructure, aFieldPos:={}
  LOCAL cOrigEngine, i , cFieldTypes, aBadRecords:={}, cTargetTypes:="", nSourceRecno:=Recno()

  /* Default settings and general variables */
  DEFAULT aFieldArray to {}, cEngine to DbeSetDefault(), aDbeInfo to {}, lStopOnError to .t., lAppend to .f.
  cOrigEngine:=DbeSetDefault(upper(cEngine))

  /* Create Structure for New File */
  aOutputStructure:=iif(len(aFieldArray)==0,aInputStructure,{})
  for i:=1 to iif(len(aFieldArray)==0,len(aOutputStructure),len(aFieldArray))
    aadd(aFieldPos, FieldPos(iif(len(aFieldArray)==0,FieldName(i),aFieldArray[i])))
    if len(aFieldArray)!=0
      aadd(aOutputStructure, aInputStructure[ aFieldPos[i] ])
    endif
  next i

  /* Store and Reset Component Data Types */
  AEval(aDbeInfo, {|a| a[2]:=DbeInfo(COMPONENT_DATA, a[1], a[2]) })
  cFieldTypes:=DbeInfo(COMPONENT_DATA, DBE_DATATYPES)

  /* Remove Fields that are not supported by the Target Engine */
  for i:=1 to len(aOutputStructure)
    if at(aOutputStructure[i,2],cFieldTypes)=0
      aDel(aOutputStructure, i)
      aSize(aOutputStructure, len(aOutputStructure)-1)
      aDel(aFieldPos, i)
      aSize(aFieldPos, len(aFieldPos)-1)
      i--
    endif
  next i

  /* Create Field Types for creation of Delimited Text Files */
  if upper(cEngine)=="DELDBE"
    aEval(aOutputStructure,{|aElement|cTargetTypes+=aElement[DBS_TYPE]})
    DbeInfo(COMPONENT_DATA, DELDBE_FIELD_TYPES, cTargetTypes)
  elseif upper(cEngine)=="SDFCDX"
    DbeInfo(COMPONENT_DATA, SDFDBE_AUTOCREATION, .t.)
  endif

  /* Create the New Database */
  if lAppend==.f. .or. !fexists(cFile)
    DbCreate(cFile, aOutputStructure)
  endif
  DbUseArea(.t.,,cFile,,.f.)
  nTargetArea:=Select()

  /* Export Records */
  DbSelectArea(nSourceArea)
  DbEval({|| XoExportErrorTrap(aFieldPos, aBadRecords, lStopOnError, len(aOutputStructure), nSourceArea, nTargetArea, !(DbeInfo(COMPONENT_DATA, DBE_NAME) == "SDFDBE")) }, bFor, bWhile, nNext, nRecord, lRest)
  DbSelectArea(nTargetArea)

  /* Finish up */
  DbCloseArea()
  DbSelectArea(nSourceArea)
  DbGoto(nSourceRecno)
  AEval(aDbeInfo, {|a| a[2]:=DbeInfo(COMPONENT_DATA, a[1], a[2]) })
  DbeSetDefault(cOrigEngine)

return aBadRecords

* EOP: XoExport()


*************************************************************************
*                                                                       *
* Function : XoExportErrorTrap()                                        *
*                                                                       *
* Called from replacement Export routine to create Exported Records     *
*                                                                       *
*************************************************************************

FUNCTION XoExportErrorTrap(aFieldPos, aBadRecords, lStopOnError, nCount, nSource, nTarget, lSupportDel)

Local oError, bSaveErrorBlock

  /* Local variable declaration */
  LOCAL i, lDeleted:=Deleted(), aBuildRecord:={}

  /* Error Handling Loop */
  bSaveErrorBlock:=ErrorBlock({|oError| Break(oError)})
  begin sequence

    /* Create an Array of Field contents */
    for i:=1 to nCount
      aAdd(aBuildRecord,FieldGet(aFieldPos[i]))
    next i

    /* Add the New record to the Target File */
    DbSelectArea(nTarget)
    DbAppend()
    for i:=1 to nCount
      FieldPut(i, aBuildRecord[i])
    next i

    /* Maintain the Deleted flag in the Target File if SET DELETED is OFF */
    if lDeleted .AND. lSupportDel
      DbDelete()
    endif

  recover using oerror

    aadd(aBadRecords, (nSource)->(recno()))
    if lStopOnError
      DbGoBottom()
      DbSkip()
    endif

  endsequence
  ErrorBlock(bSaveErrorBlock)
  DbSelectArea(nSource)

return .t.

* EOP: XoExportErrorTrap()
