fileconf.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 2,084 行 · 第 1/5 页

CPP
2,084
字号
///////////////////////////////////////////////////////////////////////////////
// Name:        fileconf.cpp
// Purpose:     implementation of wxFileConfig derivation of wxConfig
// Author:      Vadim Zeitlin
// Modified by:
// Created:     07.04.98 (adapted from appconf.cpp)
// RCS-ID:      $Id: fileconf.cpp,v 1.137.2.2 2006/02/09 15:25:32 JS Exp $
// Copyright:   (c) 1997 Karsten Ball黡er   &  Vadim Zeitlin
//                       Ballueder@usa.net     <zeitlin@dptmaths.ens-cachan.fr>
// Licence:     wxWindows licence
///////////////////////////////////////////////////////////////////////////////

#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "fileconf.h"
#endif

// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------

#include  "wx/wxprec.h"

#ifdef    __BORLANDC__
  #pragma hdrstop
#endif  //__BORLANDC__

#if wxUSE_CONFIG && wxUSE_FILECONFIG

#ifndef   WX_PRECOMP
  #include  "wx/string.h"
  #include  "wx/intl.h"
#endif  //WX_PRECOMP

#include  "wx/app.h"
#include  "wx/dynarray.h"
#include  "wx/file.h"
#include  "wx/log.h"
#include  "wx/textfile.h"
#include  "wx/memtext.h"
#include  "wx/config.h"
#include  "wx/fileconf.h"
#include  "wx/filefn.h"

#if wxUSE_STREAMS
    #include  "wx/stream.h"
#endif // wxUSE_STREAMS

#include  "wx/utils.h"    // for wxGetHomeDir

#if defined(__WXMAC__)
  #include  "wx/mac/private.h"  // includes mac headers
  #include  "wx/filename.h"     // for MacSetTypeAndCreator
#endif

#if defined(__WXMSW__)
  #include "wx/msw/private.h"
#endif  //windows.h
#if defined(__WXPM__)
  #define INCL_DOS
  #include <os2.h>
#endif

#include  <stdlib.h>
#include  <ctype.h>

// ----------------------------------------------------------------------------
// macros
// ----------------------------------------------------------------------------
#define CONST_CAST ((wxFileConfig *)this)->

// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------

#ifndef MAX_PATH
  #define MAX_PATH 512
#endif

#define FILECONF_TRACE_MASK _T("fileconf")

// ----------------------------------------------------------------------------
// global functions declarations
// ----------------------------------------------------------------------------

// compare functions for sorting the arrays
static int LINKAGEMODE CompareEntries(wxFileConfigEntry *p1, wxFileConfigEntry *p2);
static int LINKAGEMODE CompareGroups(wxFileConfigGroup *p1, wxFileConfigGroup *p2);

// filter strings
static wxString FilterInValue(const wxString& str);
static wxString FilterOutValue(const wxString& str);

static wxString FilterInEntryName(const wxString& str);
static wxString FilterOutEntryName(const wxString& str);

// get the name to use in wxFileConfig ctor
static wxString GetAppName(const wxString& appname);

// ============================================================================
// private classes
// ============================================================================

// ----------------------------------------------------------------------------
// "template" array types
// ----------------------------------------------------------------------------

#ifdef WXMAKINGDLL_BASE
    WX_DEFINE_SORTED_USER_EXPORTED_ARRAY(wxFileConfigEntry *, ArrayEntries,
                                         WXDLLIMPEXP_BASE);
    WX_DEFINE_SORTED_USER_EXPORTED_ARRAY(wxFileConfigGroup *, ArrayGroups,
                                         WXDLLIMPEXP_BASE);
#else
    WX_DEFINE_SORTED_ARRAY(wxFileConfigEntry *, ArrayEntries);
    WX_DEFINE_SORTED_ARRAY(wxFileConfigGroup *, ArrayGroups);
#endif

// ----------------------------------------------------------------------------
// wxFileConfigLineList
// ----------------------------------------------------------------------------

// we store all lines of the local config file as a linked list in memory
class wxFileConfigLineList
{
public:
  void SetNext(wxFileConfigLineList *pNext)  { m_pNext = pNext; }
  void SetPrev(wxFileConfigLineList *pPrev)  { m_pPrev = pPrev; }

  // ctor
  wxFileConfigLineList(const wxString& str,
                       wxFileConfigLineList *pNext = NULL) : m_strLine(str)
    { SetNext(pNext); SetPrev(NULL); }

  // next/prev nodes in the linked list
  wxFileConfigLineList *Next() const { return m_pNext;  }
  wxFileConfigLineList *Prev() const { return m_pPrev;  }

  // get/change lines text
  void SetText(const wxString& str) { m_strLine = str;  }
  const wxString& Text() const { return m_strLine; }

private:
  wxString  m_strLine;                  // line contents
  wxFileConfigLineList *m_pNext,        // next node
                       *m_pPrev;        // previous one

    DECLARE_NO_COPY_CLASS(wxFileConfigLineList)
};

// ----------------------------------------------------------------------------
// wxFileConfigEntry: a name/value pair
// ----------------------------------------------------------------------------

class wxFileConfigEntry
{
private:
  wxFileConfigGroup *m_pParent; // group that contains us

  wxString      m_strName,      // entry name
                m_strValue;     //       value
  bool          m_bImmutable:1, // can be overriden locally?
                m_bHasValue:1;  // set after first call to SetValue()

  int           m_nLine;        // used if m_pLine == NULL only

  // pointer to our line in the linked list or NULL if it was found in global
  // file (which we don't modify)
  wxFileConfigLineList *m_pLine;

public:
  wxFileConfigEntry(wxFileConfigGroup *pParent,
                    const wxString& strName, int nLine);

  // simple accessors
  const wxString& Name()        const { return m_strName;    }
  const wxString& Value()       const { return m_strValue;   }
  wxFileConfigGroup *Group()    const { return m_pParent;    }
  bool            IsImmutable() const { return m_bImmutable; }
  bool            IsLocal()     const { return m_pLine != 0; }
  int             Line()        const { return m_nLine;      }
  wxFileConfigLineList *
                  GetLine()     const { return m_pLine;      }

  // modify entry attributes
  void SetValue(const wxString& strValue, bool bUser = true);
  void SetLine(wxFileConfigLineList *pLine);

    DECLARE_NO_COPY_CLASS(wxFileConfigEntry)
};

// ----------------------------------------------------------------------------
// wxFileConfigGroup: container of entries and other groups
// ----------------------------------------------------------------------------

class wxFileConfigGroup
{
private:
  wxFileConfig *m_pConfig;          // config object we belong to
  wxFileConfigGroup  *m_pParent;    // parent group (NULL for root group)
  ArrayEntries  m_aEntries;         // entries in this group
  ArrayGroups   m_aSubgroups;       // subgroups
  wxString      m_strName;          // group's name
  wxFileConfigLineList *m_pLine;    // pointer to our line in the linked list
  wxFileConfigEntry *m_pLastEntry;  // last entry/subgroup of this group in the
  wxFileConfigGroup *m_pLastGroup;  // local file (we insert new ones after it)

  // DeleteSubgroupByName helper
  bool DeleteSubgroup(wxFileConfigGroup *pGroup);

  // used by Rename()
  void UpdateGroupAndSubgroupsLines();

public:
  // ctor
  wxFileConfigGroup(wxFileConfigGroup *pParent, const wxString& strName, wxFileConfig *);

  // dtor deletes all entries and subgroups also
  ~wxFileConfigGroup();

  // simple accessors
  const wxString& Name()    const { return m_strName; }
  wxFileConfigGroup    *Parent()  const { return m_pParent; }
  wxFileConfig   *Config()  const { return m_pConfig; }

  const ArrayEntries& Entries() const { return m_aEntries;   }
  const ArrayGroups&  Groups()  const { return m_aSubgroups; }
  bool  IsEmpty() const { return Entries().IsEmpty() && Groups().IsEmpty(); }

  // find entry/subgroup (NULL if not found)
  wxFileConfigGroup *FindSubgroup(const wxChar *szName) const;
  wxFileConfigEntry *FindEntry   (const wxChar *szName) const;

  // delete entry/subgroup, return false if doesn't exist
  bool DeleteSubgroupByName(const wxChar *szName);
  bool DeleteEntry(const wxChar *szName);

  // create new entry/subgroup returning pointer to newly created element
  wxFileConfigGroup *AddSubgroup(const wxString& strName);
  wxFileConfigEntry *AddEntry   (const wxString& strName, int nLine = wxNOT_FOUND);

  void SetLine(wxFileConfigLineList *pLine);

  // rename: no checks are done to ensure that the name is unique!
  void Rename(const wxString& newName);

  //
  wxString GetFullName() const;

  // get the last line belonging to an entry/subgroup of this group
  wxFileConfigLineList *GetGroupLine();     // line which contains [group]
  wxFileConfigLineList *GetLastEntryLine(); // after which our subgroups start
  wxFileConfigLineList *GetLastGroupLine(); // after which the next group starts

  // called by entries/subgroups when they're created/deleted
  void SetLastEntry(wxFileConfigEntry *pEntry);
  void SetLastGroup(wxFileConfigGroup *pGroup)
    { m_pLastGroup = pGroup; }

  DECLARE_NO_COPY_CLASS(wxFileConfigGroup)
};

// ============================================================================
// implementation
// ============================================================================

// ----------------------------------------------------------------------------
// static functions
// ----------------------------------------------------------------------------
wxString wxFileConfig::GetGlobalDir()
{
  wxString strDir;

#ifdef __VMS__ // Note if __VMS is defined __UNIX is also defined
    strDir = wxT("sys$manager:");
#elif defined(__WXMAC__)
    strDir = wxMacFindFolder(  (short) kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder ) ;
#elif defined( __UNIX__ )
    strDir = wxT("/etc/");
#elif defined(__WXPM__)
    ULONG aulSysInfo[QSV_MAX] = {0};
    UINT drive;
    APIRET rc;

    rc = DosQuerySysInfo( 1L, QSV_MAX, (PVOID)aulSysInfo, sizeof(ULONG)*QSV_MAX);
    if (rc == 0)
    {
        drive = aulSysInfo[QSV_BOOT_DRIVE - 1];
        strDir.Printf(wxT("%c:\\OS2\\"), 'A'+drive-1);
    }
#elif defined(__WXSTUBS__)
    wxASSERT_MSG( false, wxT("TODO") ) ;
#elif defined(__DOS__)
    // There's no such thing as global cfg dir in MS-DOS, let's return
    // current directory (FIXME_MGL?)
    return wxT(".\\");
#elif defined(__WXWINCE__)
    strDir = wxT("\\Windows\\");
#else // Windows

    wxChar szWinDir[MAX_PATH];
    ::GetWindowsDirectory(szWinDir, MAX_PATH);

    strDir = szWinDir;
    strDir << wxT('\\');
#endif // Unix/Windows

    return strDir;
}

wxString wxFileConfig::GetLocalDir()
{
    wxString strDir;

#if defined(__WXMAC__) || defined(__DOS__)
    // no local dir concept on Mac OS 9 or MS-DOS
    return GetGlobalDir() ;
#else
    wxGetHomeDir(&strDir);

#ifdef  __UNIX__
#ifdef __VMS
    if (strDir.Last() != wxT(']'))
#endif
    if (strDir.Last() != wxT('/')) strDir << wxT('/');
#else
    if (strDir.Last() != wxT('\\')) strDir << wxT('\\');
#endif
#endif

    return strDir;
}

wxString wxFileConfig::GetGlobalFileName(const wxChar *szFile)
{
    wxString str = GetGlobalDir();
    str << szFile;

    if ( wxStrchr(szFile, wxT('.')) == NULL )
#if defined( __WXMAC__ )
        str << wxT(" Preferences") ;
#elif defined( __UNIX__ )
        str << wxT(".conf");
#else   // Windows
        str << wxT(".ini");
#endif  // UNIX/Win

    return str;
}

wxString wxFileConfig::GetLocalFileName(const wxChar *szFile)
{
#ifdef __VMS__
    // On VMS I saw the problem that the home directory was appended
    // twice for the configuration file. Does that also happen for
    // other platforms?
    wxString str = wxT( '.' );
#else
    wxString str = GetLocalDir();
#endif

#if defined( __UNIX__ ) && !defined( __VMS ) && !defined( __WXMAC__ )
    str << wxT('.');
#endif

    str << szFile;

#if defined(__WINDOWS__) || defined(__DOS__)
    if ( wxStrchr(szFile, wxT('.')) == NULL )
        str << wxT(".ini");
#endif

#ifdef __WXMAC__
    str << wxT(" Preferences") ;
#endif

    return str;
}

// ----------------------------------------------------------------------------
// ctor
// ----------------------------------------------------------------------------

void wxFileConfig::Init()
{
    m_pCurrentGroup =
    m_pRootGroup    = new wxFileConfigGroup(NULL, wxEmptyString, this);

    m_linesHead =
    m_linesTail = NULL;

    // It's not an error if (one of the) file(s) doesn't exist.

    // parse the global file
    if ( !m_strGlobalFile.empty() && wxFile::Exists(m_strGlobalFile) )
    {
        wxTextFile fileGlobal(m_strGlobalFile);

        if ( fileGlobal.Open(m_conv/*ignored in ANSI build*/) )
        {
            Parse(fileGlobal, false /* global */);
            SetRootPath();
        }
        else
        {
            wxLogWarning(_("can't open global configuration file '%s'."), m_strGlobalFile.c_str());
        }
    }

    // parse the local file
    if ( !m_strLocalFile.empty() && wxFile::Exists(m_strLocalFile) )
    {
        wxTextFile fileLocal(m_strLocalFile);
        if ( fileLocal.Open(m_conv/*ignored in ANSI build*/) )
        {
            Parse(fileLocal, true /* local */);
            SetRootPath();
        }
        else

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?