Ora ricerca prima la definizione della sorgente dati in ODBC, in caso negativo utilizza CodeBase (se esiste la variabile d'ambiente SPPROOT) per leggere il file. git-svn-id: svn://10.65.10.50/trunk@5146 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			610 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			610 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
#include "stdafx.h"
 | 
						|
 | 
						|
#include <fstream.h>
 | 
						|
#include <io.h>
 | 
						|
 | 
						|
#include "columnst.h"
 | 
						|
#include "sesa.h"
 | 
						|
 | 
						|
static CDatabase _db;
 | 
						|
static CString _strWorkDir;
 | 
						|
 | 
						|
#define S4DLL
 | 
						|
#include <d4all.h>
 | 
						|
 | 
						|
static CODE4 _codebase;
 | 
						|
static DATA4 *_dbdata;
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// SESA field info
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class SESA_Field : public CObject
 | 
						|
{ 
 | 
						|
  CString m_strName;
 | 
						|
  int m_nType;
 | 
						|
 | 
						|
  CString m_strValue;
 | 
						|
  CTime m_tValue;
 | 
						|
  double m_dValue;
 | 
						|
  BOOL m_bValue;
 | 
						|
 | 
						|
public:
 | 
						|
  const CString& Name() const { return m_strName; }
 | 
						|
  int Type() const { return m_nType; }
 | 
						|
  
 | 
						|
  CString& StrValue() { return m_strValue; }
 | 
						|
  CTime& TimeValue() { return m_tValue; }
 | 
						|
  double& DoubleValue() { return m_dValue; }
 | 
						|
  BOOL& BoolValue() { return m_bValue; }
 | 
						|
 | 
						|
  SESA_Field(LPCSTR strName, int nType);
 | 
						|
  virtual ~SESA_Field() { }
 | 
						|
};
 | 
						|
 | 
						|
SESA_Field::SESA_Field(LPCSTR strName, int nType)
 | 
						|
          : m_strName(strName), m_nType(nType), m_bValue(FALSE), m_dValue(0.0)
 | 
						|
{ }
 | 
						|
 | 
						|
class SESA_FieldList : public CObject
 | 
						|
{
 | 
						|
  CObList m_List;
 | 
						|
 | 
						|
public:
 | 
						|
  void Add(const CString& strField, int nType);
 | 
						|
  POSITION GetHeadPosition() const;
 | 
						|
  SESA_Field& GetNext(POSITION& rPosition);
 | 
						|
  SESA_Field& Find(const CString& strField);
 | 
						|
  void RemoveAll();
 | 
						|
  
 | 
						|
  int GetCount() const { return m_List.GetCount(); }
 | 
						|
  
 | 
						|
  virtual ~SESA_FieldList();
 | 
						|
};
 | 
						|
 | 
						|
void SESA_FieldList::Add(const CString& strName, int nType)
 | 
						|
{                   
 | 
						|
  SESA_Field* pField = new SESA_Field(strName, nType);
 | 
						|
  m_List.AddTail(pField);
 | 
						|
}
 | 
						|
 | 
						|
POSITION SESA_FieldList::GetHeadPosition() const
 | 
						|
{
 | 
						|
  return m_List.GetHeadPosition();
 | 
						|
}
 | 
						|
 | 
						|
SESA_Field& SESA_FieldList::GetNext(POSITION& rPosition)
 | 
						|
{
 | 
						|
  SESA_Field* pField = (SESA_Field*)m_List.GetNext(rPosition);
 | 
						|
  ASSERT(pField);
 | 
						|
  return *pField;
 | 
						|
}
 | 
						|
 | 
						|
SESA_Field& SESA_FieldList::Find(const CString& strName)
 | 
						|
{
 | 
						|
  for (POSITION pos = GetHeadPosition(); pos;)
 | 
						|
  {
 | 
						|
    SESA_Field& fld = GetNext(pos);
 | 
						|
    if (fld.Name() == strName)
 | 
						|
      return fld;
 | 
						|
  }    
 | 
						|
  return SESA_Field("", 0);
 | 
						|
}
 | 
						|
 | 
						|
void SESA_FieldList::RemoveAll()
 | 
						|
{
 | 
						|
  while (!m_List.IsEmpty())
 | 
						|
  {
 | 
						|
    CObject* pField = m_List.RemoveHead();
 | 
						|
    delete pField;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
SESA_FieldList::~SESA_FieldList()
 | 
						|
{
 | 
						|
  RemoveAll();
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// Sesa recordset
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class SESA_Recordset : public CRecordset
 | 
						|
{                               
 | 
						|
// DECLARE_DYNAMIC(SESA_Recordset)
 | 
						|
  SESA_FieldList m_FieldList;
 | 
						|
  CStringList m_DumpList;
 | 
						|
 | 
						|
protected:
 | 
						|
  virtual CString GetDefaultConnect();
 | 
						|
  virtual CString GetDefaultSQL();
 | 
						|
  virtual void DoFieldExchange(CFieldExchange* pFX);
 | 
						|
  
 | 
						|
public:                 
 | 
						|
  BOOL Open(LPCSTR strTable);
 | 
						|
 | 
						|
  void DumpHeader(ostream& out);
 | 
						|
  void ReadDumpList(const CString& strFile);
 | 
						|
  void DumpFields(ostream& out);
 | 
						|
  
 | 
						|
  SESA_Recordset(CDatabase* pDatabase);
 | 
						|
  virtual ~SESA_Recordset() { }
 | 
						|
};
 | 
						|
 | 
						|
//IMPLEMENT_DYNAMIC(SESA_Recordset, CRecordset)
 | 
						|
 | 
						|
CString SESA_Recordset::GetDefaultConnect()
 | 
						|
{
 | 
						|
  return "ODBC;";   // Copied from CATALOG sample application
 | 
						|
}
 | 
						|
 | 
						|
CString SESA_Recordset::GetDefaultSQL()
 | 
						|
{
 | 
						|
  ASSERT(FALSE);   // Copied from CATALOG sample application
 | 
						|
  return "!";
 | 
						|
}
 | 
						|
 | 
						|
BOOL SESA_Recordset::Open(LPCSTR strTable)
 | 
						|
{      
 | 
						|
  CColumns Cols(&_db);           
 | 
						|
  Cols.m_strTableNameParam = strTable;
 | 
						|
  BOOL ok = Cols.Open(CRecordset::forwardOnly, NULL, CRecordset::readOnly);
 | 
						|
  if (ok)
 | 
						|
  {
 | 
						|
    while (!Cols.IsEOF())
 | 
						|
    {
 | 
						|
      m_FieldList.Add(Cols.m_strColumnName, Cols.m_nDataType);
 | 
						|
      Cols.MoveNext();
 | 
						|
    }
 | 
						|
    RETCODE nRetCode;
 | 
						|
    AFX_SQL_SYNC(::SQLFreeStmt(Cols.m_hstmt, SQL_CLOSE));
 | 
						|
    
 | 
						|
    m_nFields = m_FieldList.GetCount();
 | 
						|
  }   
 | 
						|
  
 | 
						|
  if (ok)
 | 
						|
  {
 | 
						|
    ok = CRecordset::Open(CRecordset::snapshot, strTable, CRecordset::readOnly);
 | 
						|
    if (!ok) 
 | 
						|
    { 
 | 
						|
      CString msg;
 | 
						|
      msg = "Can't open table ";
 | 
						|
      msg += strTable;
 | 
						|
      AfxMessageBox(msg, MB_OK | MB_ICONEXCLAMATION);
 | 
						|
    }      
 | 
						|
  }  
 | 
						|
    
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
void SESA_Recordset::DoFieldExchange(CFieldExchange* pFX)
 | 
						|
{                                      
 | 
						|
  pFX->SetFieldType(CFieldExchange::outputColumn);
 | 
						|
  BOOL bLoad= pFX->m_nOperation == CFieldExchange::Fixup;
 | 
						|
  
 | 
						|
  int nField = 1;
 | 
						|
  for (POSITION pos = m_FieldList.GetHeadPosition(); pos; nField++)
 | 
						|
  {
 | 
						|
    SESA_Field& fld = m_FieldList.GetNext(pos);
 | 
						|
    CString& val = fld.StrValue();
 | 
						|
    switch(fld.Type())
 | 
						|
    {    
 | 
						|
    case SQL_BIT:
 | 
						|
      {
 | 
						|
        BOOL& b = fld.BoolValue();
 | 
						|
        RFX_Bool(pFX, fld.Name(), b); 
 | 
						|
        if (bLoad)
 | 
						|
        {        
 | 
						|
          if (b == FALSE || IsFieldFlagNull(nField, CFieldExchange::outputColumn))
 | 
						|
            val.Empty();
 | 
						|
          else
 | 
						|
            val = "X";
 | 
						|
        }
 | 
						|
      }  
 | 
						|
      break;     
 | 
						|
    case SQL_CHAR:
 | 
						|
    case SQL_NUMERIC:       
 | 
						|
      RFX_Text(pFX, fld.Name(), val); 
 | 
						|
      break;
 | 
						|
    case SQL_DATE:           
 | 
						|
      {
 | 
						|
        CTime& t = fld.TimeValue();
 | 
						|
        RFX_Date(pFX, fld.Name(), t); 
 | 
						|
        if (bLoad)
 | 
						|
        {       
 | 
						|
          TIMESTAMP_STRUCT* pts = (TIMESTAMP_STRUCT*)m_pvFieldProxy[nField];
 | 
						|
          if (pts->year == 0)               
 | 
						|
            val.Empty();  
 | 
						|
          else
 | 
						|
          {
 | 
						|
            char* buf = val.GetBuffer(16);
 | 
						|
            sprintf(buf, "%02d-%02d-%04d", pts->day, pts->month, pts->year);
 | 
						|
            val.ReleaseBuffer();
 | 
						|
          }  
 | 
						|
        }
 | 
						|
      }   
 | 
						|
      break;
 | 
						|
    case SQL_DOUBLE:        
 | 
						|
      {
 | 
						|
        double& d = fld.DoubleValue();
 | 
						|
        RFX_Double(pFX, fld.Name(), d); 
 | 
						|
        if (bLoad)
 | 
						|
        {     
 | 
						|
          if (d == 0.0 || IsFieldFlagNull(nField, CFieldExchange::outputColumn))
 | 
						|
          {
 | 
						|
            val.Empty();  
 | 
						|
          }
 | 
						|
          else
 | 
						|
          {
 | 
						|
            char* buf = val.GetBuffer(32);
 | 
						|
            sprintf(buf, "%.12lg", d);
 | 
						|
            val.ReleaseBuffer();
 | 
						|
          }  
 | 
						|
        }
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    default: 
 | 
						|
      ASSERT(0);
 | 
						|
      break;
 | 
						|
    }  
 | 
						|
  }  
 | 
						|
}
 | 
						|
 | 
						|
void SESA_Recordset::DumpHeader(ostream& out)
 | 
						|
{          
 | 
						|
  out << "[MAIN]" << endl 
 | 
						|
      << "TYPEFIELD=-1" << endl 
 | 
						|
      << "DECSEP=." << endl 
 | 
						|
      << "FIELDSEP=|" << endl
 | 
						|
      << endl;
 | 
						|
 | 
						|
  out << "[RECORD]" << endl;
 | 
						|
  int num = 0;
 | 
						|
  for (POSITION pos = m_FieldList.GetHeadPosition(); pos; num++)
 | 
						|
  {
 | 
						|
    const SESA_Field& fld = m_FieldList.GetNext(pos);
 | 
						|
    out << "NAME(" << num << ") = " << fld.Name() << endl
 | 
						|
        << endl;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void SESA_Recordset::ReadDumpList(const CString& strFile)
 | 
						|
{    
 | 
						|
  char szField[16];
 | 
						|
  char szName[16];
 | 
						|
  char szFile[32];
 | 
						|
  
 | 
						|
  // Mette .\ davanti al nome per cercare nella directory corrente,
 | 
						|
  // altrimenti lo cerca nella directory di Windows
 | 
						|
  sprintf(szFile, ".\\%s", strFile);      
 | 
						|
  
 | 
						|
  for (int num = 0; ; num++)
 | 
						|
  {                         
 | 
						|
    sprintf(szField, "NAME(%d)", num);
 | 
						|
    GetPrivateProfileString("RECORD", szField, "", szName, sizeof(szName), szFile);
 | 
						|
    if (*szName)
 | 
						|
      m_DumpList.AddTail(szName);
 | 
						|
    else
 | 
						|
      break;  
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void SESA_Recordset::DumpFields(ostream& out)
 | 
						|
{                              
 | 
						|
  if (m_DumpList.IsEmpty())
 | 
						|
  {
 | 
						|
    int num = 0;      
 | 
						|
    for (POSITION pos = m_FieldList.GetHeadPosition(); pos; num++)
 | 
						|
    {
 | 
						|
      SESA_Field& fld = m_FieldList.GetNext(pos);
 | 
						|
      if (num) out << '|';
 | 
						|
      out << fld.StrValue();
 | 
						|
    }         
 | 
						|
  }  
 | 
						|
  else
 | 
						|
  {
 | 
						|
    int num = 0;      
 | 
						|
    for (POSITION npos = m_DumpList.GetHeadPosition(); npos; num++)
 | 
						|
    {
 | 
						|
      CString& strName = m_DumpList.GetNext(npos);
 | 
						|
      SESA_Field& fld = m_FieldList.Find(strName);
 | 
						|
      if (num) out << '|';
 | 
						|
      out << fld.StrValue();
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  out << endl;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
SESA_Recordset::SESA_Recordset(CDatabase* pDatabase)
 | 
						|
              : CRecordset(pDatabase)
 | 
						|
{ }
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// SESA functions
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
inline BOOL is_space(char c) { return c >= '\t' && c <= ' '; }
 | 
						|
 | 
						|
static BOOL UpdateODBCIni(LPCSTR szEntry, LPCSTR szDefault, BOOL bForce = FALSE)
 | 
						|
{   
 | 
						|
  BOOL bWrite = bForce;
 | 
						|
  
 | 
						|
  if (!bForce)  
 | 
						|
  {
 | 
						|
    char szBuffer[80];
 | 
						|
    ::GetPrivateProfileString("SIGLAPP", szEntry, "", szBuffer, sizeof(szBuffer), "odbc.ini");
 | 
						|
    bWrite = *szBuffer == '\0';
 | 
						|
  }  
 | 
						|
  
 | 
						|
  if (bWrite)  
 | 
						|
    ::WritePrivateProfileString("SIGLAPP", szEntry, szDefault, "odbc.ini");
 | 
						|
  
 | 
						|
  return bWrite;
 | 
						|
}
 | 
						|
 | 
						|
BOOL SESA_OpenDatabase(const char* lpszDSN, const char* lpszConnect)
 | 
						|
{ 
 | 
						|
  if (lpszDSN == NULL || *lpszDSN == '\0')
 | 
						|
    lpszDSN = "SIGLAPP";
 | 
						|
  if (lpszConnect == NULL || *lpszConnect == '\0')
 | 
						|
    lpszConnect = "ODBC;";
 | 
						|
    
 | 
						|
  BOOL ok;
 | 
						|
  TRY
 | 
						|
  {
 | 
						|
  //                 DataSrc  Excl  ReadOnly  ConnectString  
 | 
						|
   ok = _db.Open(lpszDSN, FALSE, TRUE, lpszConnect);
 | 
						|
  }
 | 
						|
  CATCH_ALL(e)
 | 
						|
  {
 | 
						|
    ok = FALSE;
 | 
						|
  }
 | 
						|
  END_CATCH_ALL
 | 
						|
    
 | 
						|
  if (!ok)
 | 
						|
  {                                        
 | 
						|
    CString msg;
 | 
						|
    msg = "Can't connect to database ";
 | 
						|
    msg += lpszDSN;
 | 
						|
    msg += " using ";
 | 
						|
    msg += lpszConnect;
 | 
						|
    AfxMessageBox(msg, MB_OK | MB_ICONEXCLAMATION);
 | 
						|
  }
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
BOOL SESA_CloseDatabase()
 | 
						|
{
 | 
						|
  if (_db.IsOpen())
 | 
						|
    _db.Close();
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
BOOL SESA_DumpTableODBC(const char* lpszTableName)
 | 
						|
{ 
 | 
						|
  const BOOL bWasOpen = _db.IsOpen();
 | 
						|
  if (!bWasOpen)
 | 
						|
  {
 | 
						|
    BOOL bOk = SESA_OpenDatabase();
 | 
						|
    if (!bOk)
 | 
						|
      return FALSE;
 | 
						|
  }
 | 
						|
  
 | 
						|
  SESA_Recordset rs(&_db);             
 | 
						|
  BOOL ok = rs.Open(lpszTableName);
 | 
						|
  if (ok)
 | 
						|
  {  
 | 
						|
    CString strName = _strWorkDir;
 | 
						|
    strName += lpszTableName;
 | 
						|
    strName += ".ini";
 | 
						|
    
 | 
						|
    if (access(strName, 0x00) == 0)
 | 
						|
    {
 | 
						|
      rs.ReadDumpList(strName);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      ofstream out(strName);
 | 
						|
      rs.DumpHeader(out);
 | 
						|
    }
 | 
						|
    
 | 
						|
    strName = _strWorkDir;
 | 
						|
    strName += lpszTableName;
 | 
						|
    strName += ".txt";
 | 
						|
    ofstream out(strName);
 | 
						|
    while (!rs.IsEOF())
 | 
						|
    {
 | 
						|
      rs.DumpFields(out);
 | 
						|
      rs.MoveNext();
 | 
						|
    }
 | 
						|
    
 | 
						|
    RETCODE nRetCode;
 | 
						|
    AFX_SQL_SYNC(::SQLFreeStmt(rs.m_hstmt, SQL_CLOSE));
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    CString msg;
 | 
						|
    msg = "Can't open table ";
 | 
						|
    msg += lpszTableName;
 | 
						|
    AfxMessageBox(msg, MB_OK | MB_ICONEXCLAMATION);
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (!bWasOpen)
 | 
						|
    SESA_CloseDatabase();
 | 
						|
    
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
BOOL SESA_DumpTableCODEBASE(const char* SIGLAPP, const char* lpszTableName)
 | 
						|
{ 
 | 
						|
  BOOL ok;
 | 
						|
  CString filename;
 | 
						|
  CString msg;
 | 
						|
 | 
						|
  d4init(&_codebase);
 | 
						|
  _dbdata = NULL;
 | 
						|
  _codebase.read_lock=0;
 | 
						|
  _codebase.default_unique_error=e4unique;
 | 
						|
  _codebase.safety=0;
 | 
						|
  _codebase.lock_attempts=1;   
 | 
						|
  u4ncpy(_codebase.date_format,"CCYYMMDD",sizeof(_codebase.date_format));
 | 
						|
  
 | 
						|
  filename  = SIGLAPP;
 | 
						|
  if (filename.Right(1) != "\\" && filename.Right(1) != "/")
 | 
						|
    filename += "\\";
 | 
						|
  filename += lpszTableName;
 | 
						|
  _codebase.error_code=0;
 | 
						|
  _dbdata=d4open(&_codebase,(char*)(const char*)filename);
 | 
						|
  if (_dbdata != NULL)
 | 
						|
  {
 | 
						|
    CString strName = _strWorkDir;
 | 
						|
    CString fld_name,fld_val;
 | 
						|
    CStringArray field_list;
 | 
						|
    strName += lpszTableName;
 | 
						|
    strName += ".ini";
 | 
						|
    
 | 
						|
    if (access(strName, 0x00) == 0)
 | 
						|
    {
 | 
						|
      // Legge la lista dei campi dal .ini se esiste gia'
 | 
						|
      
 | 
						|
      char szField[16];
 | 
						|
      char szName[16];
 | 
						|
      char szFile[32];
 | 
						|
      
 | 
						|
      // Mette .\ davanti al nome per cercare nella directory corrente,
 | 
						|
      // altrimenti lo cerca nella directory di Windows
 | 
						|
      sprintf(szFile, ".\\%s", strName);      
 | 
						|
      
 | 
						|
      for (int num = 0; ; num++)
 | 
						|
      {                         
 | 
						|
        sprintf(szField, "NAME(%d)", num);
 | 
						|
        GetPrivateProfileString("RECORD", szField, "", szName, sizeof(szName), szFile);
 | 
						|
        if (*szName)
 | 
						|
          field_list.Add(szName);
 | 
						|
        else
 | 
						|
          break;  
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      // Scarica il tracciato dei campi
 | 
						|
      ofstream out(strName);
 | 
						|
      out << "[MAIN]" << endl 
 | 
						|
          << "TYPEFIELD=-1" << endl 
 | 
						|
          << "DECSEP=." << endl 
 | 
						|
          << "FIELDSEP=|" << endl
 | 
						|
          << endl;
 | 
						|
    
 | 
						|
      out << "[RECORD]" << endl;
 | 
						|
      FIELD4INFO *field_info = d4field_info(_dbdata);
 | 
						|
      if (field_info != NULL)
 | 
						|
      {
 | 
						|
        const int num_fields = d4num_fields(_dbdata);
 | 
						|
        for (int num=0; num < num_fields; num++)
 | 
						|
        {                                                
 | 
						|
          out << "NAME(" << num << ") = " << field_info[num].name << endl
 | 
						|
              << endl;
 | 
						|
          field_list.Add(field_info[num].name);
 | 
						|
        }
 | 
						|
        u4free(field_info);
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        msg = "Can't get file header.";
 | 
						|
        AfxMessageBox(msg, MB_OK | MB_ICONEXCLAMATION);
 | 
						|
        ok = FALSE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (ok)
 | 
						|
    {
 | 
						|
      strName = _strWorkDir;
 | 
						|
      strName += lpszTableName;
 | 
						|
      strName += ".txt";
 | 
						|
      ofstream out(strName);
 | 
						|
      d4top(_dbdata); // No tag is required
 | 
						|
      while (!d4eof(_dbdata) && ok)
 | 
						|
      {
 | 
						|
        if (!d4deleted(_dbdata)) // Dump only undeleted records
 | 
						|
        {
 | 
						|
          const int items = field_list.GetSize();
 | 
						|
          for (int num = 0; num < items && ok; num++)
 | 
						|
          {
 | 
						|
            fld_name = field_list.GetAt(num);
 | 
						|
            if (num) 
 | 
						|
              out << '|';
 | 
						|
            FIELD4* fldfld = d4field(_dbdata,(char*)(const char*)fld_name);
 | 
						|
            if (fldfld != NULL)
 | 
						|
            {
 | 
						|
              fld_val = f4str(fldfld);
 | 
						|
              char * v = fld_val.GetBuffer(80);
 | 
						|
              // Trims leading & trailing spaces
 | 
						|
              {
 | 
						|
                char* last = v;
 | 
						|
              
 | 
						|
                // Salta spazi iniziali
 | 
						|
                for (const char* s = v; *s && is_space(*s); s++);
 | 
						|
              
 | 
						|
                // Copia stringa
 | 
						|
                for(char* c = v; *s; s++)
 | 
						|
                {
 | 
						|
                  *c++ = *s;
 | 
						|
                  if (!is_space(*s)) last = c;
 | 
						|
                }
 | 
						|
                // Elimina spazi finali
 | 
						|
                *last = '\0';
 | 
						|
              }
 | 
						|
              out << v;
 | 
						|
              fld_val.ReleaseBuffer();
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
              msg = "Can't get field ";
 | 
						|
              msg += fld_val;
 | 
						|
              AfxMessageBox(msg, MB_OK | MB_ICONEXCLAMATION);
 | 
						|
              ok = FALSE;
 | 
						|
            }
 | 
						|
          }
 | 
						|
          out << endl;
 | 
						|
        }
 | 
						|
        d4skip(_dbdata,1L); // Skip next
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    d4close(_dbdata);
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    msg = "Can't open file ";
 | 
						|
    msg += filename;
 | 
						|
    AfxMessageBox(msg, MB_OK | MB_ICONEXCLAMATION);
 | 
						|
    ok = FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  d4init_undo(&_codebase);
 | 
						|
  
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
BOOL SESA_DumpTable(const char* lpszTableName)
 | 
						|
{ 
 | 
						|
  if (!SESA_DumpTableODBC(lpszTableName))
 | 
						|
  {
 | 
						|
    const char *SIGLAPP = getenv("SPPROOT");
 | 
						|
    return SIGLAPP ? SESA_DumpTableCODEBASE(SIGLAPP, lpszTableName) : FALSE;
 | 
						|
  }
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
BOOL SESA_WorkDir(const char* strDir)
 | 
						|
{ 
 | 
						|
  _strWorkDir = strDir;
 | 
						|
  _strWorkDir = _strWorkDir.SpanExcluding(" ");
 | 
						|
  const char& last = _strWorkDir[_strWorkDir.GetLength()-1];
 | 
						|
  if (last != '\\' && last != '/')
 | 
						|
    _strWorkDir += "\\";
 | 
						|
  return !_strWorkDir.IsEmpty();
 | 
						|
}
 |