//----------------------------------------------------------------------------
// ObjectWindow - OWL NExt
// Copyright 1999. Yura Bidus.
// All Rights reserved.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
//
//  OVERVIEW
//  ~~~~~~~~
//  Syntax coloring hex editor.
//----------------------------------------------------------------------------
#if !defined(COOL_HEXEDIT_H)
#define COOL_HEXEDIT_H
 
 
#include <owl/docview.h>
#include <owl/doctpl.h>
#include <owl/scroller.h>
#include <owl/opensave.h>
#include <owl/dialog.h>
#include <owl/combobox.h>
 
#include <coolprj/defs.h>
#include <coolprj/cooledit.h>
 
#if !defined(COOL_NODRAGDROP)
#include <coolprj/dragdrop.h>
#endif
 
/////////////////////////////////////////////////////////////////////////////
// THexEdit window
 
enum {
  //  Base colors
  HEXINDEX_WHITESPACE,
  HEXINDEX_ADDRESS,
  HEXINDEX_DIGITS,
  HEXINDEX_ASCII,
  HEXINDEX_SELECTION,
 
  HEXINDEX_LAST,
};
 
 
 
////////////////////////////////////
// class THexBuffer
// ~~~~~ ~~~~~~~~~~
//
//{{GENERIC = THexBuffer}}
class _COOLCLASS THexBuffer {
  public:
    typedef TCoolTextBuffer::TSyntaxDescr TSyntaxDescr;
    enum TBufferFlags {
      bfReadOnly      = 0x00000001L,
      bfModified      = 0x00010000L,
      bfCreateBackup  = 0x00020000L,
    };
 
  public:
    THexBuffer();
    virtual ~THexBuffer();
 
    //  'Dirty' flag
    void SetDirty(bool dirty = true);
    bool IsDirty() const;
    bool IsReadOnly() const;
    void EnableReadOnly(bool enable);
 
    // syntax colorArray
    void SetSyntaxDescr(int index, const TSyntaxDescr& node);
    TSyntaxDescr& GetSyntaxDescr(int index) const;
    bool SyntaxDescrExist() const;
    static TSyntaxDescr* GetDefSyntaxDescr(int index);
    void BuildDefSyntaxDescr();
    void SetSyntaxArray(TSyntaxDescr* array);
    // save and restore all format and font information
    void SaveSyntaxDescr(owl::TConfigFile& file);
    void RestoreSyntaxDescr(owl::TConfigFile& file);
 
    void GetFont(LOGFONT& lf) const;
    void SetFont(const LOGFONT& lf);
 
    virtual bool Load(LPCTSTR filename) = 0;
    virtual bool Save(LPCTSTR filename, bool clearDirty = true) = 0;
    virtual void Clear() = 0;
    virtual owl::uint GetDataSize() = 0;
    virtual owl::uint GetBuffer(owl::uint index, owl::uint8* buffer, owl::uint size) = 0;
    virtual owl::uint32 Search(const TEditPos& searchRange, owl::uint8* text, owl::uint len,
                          bool up = false);
 
  protected_data:
    owl::uint32        Flags;
    TSyntaxDescr* SyntaxArray;// size == COLORINDEX_LAST
    LOGFONT       BaseFont;
 
  private:
    // Hidden to prevent accidental copying or assignment
    //
    THexBuffer(const THexBuffer&);
    THexBuffer& operator=(const THexBuffer&);
}; 
 
//{{THexBuffer = THexFileBuffer}}
class _COOLCLASS THexFileBuffer: public THexBuffer {
  typedef THexBuffer Inherited;
  public:
    THexFileBuffer();
    ~THexFileBuffer();
 
    bool Load(owl::TFile& file);
    bool Save(owl::TFile& file, bool clearDirty = true);
 
    virtual bool Load(LPCTSTR filename);
    virtual bool Save(LPCTSTR filename, bool clearDirty = true);
    virtual void Clear();
    virtual owl::uint GetDataSize();
    virtual owl::uint GetBuffer(owl::uint index, owl::uint8* buffer, owl::uint size);
//  virtual owl::uint32 Search(const TEditPos& searchRange, owl::uint8* text, owl::uint len,
//                      bool up = false);
 
  protected_data:
    owl::uint8*        BinaryData;
    owl::uint          DataSize;
};
 
inline void THexBuffer::SetDirty(bool dirty)
  { dirty ? Flags |=bfModified : Flags &=~bfModified; }
inline bool THexBuffer::IsDirty() const
  { return (Flags&bfModified)!=0;    }
inline bool THexBuffer::IsReadOnly() const
  {  return (Flags&bfReadOnly)!=0;  }
inline void THexBuffer::EnableReadOnly(bool enable)
  {  enable ? Flags |= bfReadOnly : Flags &= ~bfReadOnly;  }
inline THexBuffer::TSyntaxDescr& THexBuffer::GetSyntaxDescr(int index) const
  {  return SyntaxArray[index];}
inline bool THexBuffer::SyntaxDescrExist() const
  {  return SyntaxArray != 0; }
inline owl::uint THexFileBuffer::GetDataSize()
  { return DataSize; }
 
 
//-----------------------------------------------------------------------------
// class THexViewWnd
// ~~~~~ ~~~~~~~~~~~~
//
//{{TControl = THexViewWnd}}
class _COOLCLASS THexViewWnd: public owl::TControl {
  typedef owl::TControl Inherited;
  public:
    enum TFindFlags {
      ffNone        = 0x0000,
      ffMatchCase   = 0x0001,
      ffWholeWord   = 0x0002,
      ffDirectionUp = 0x0004,
      ffWholeDoc    = 0x0008,
 
      ffFindNext    = 0x0010,
      ffReplace     = 0x0020,
      ffReplaceAll  = 0x0040,
      ffDlgTerm     = 0x0080,
      ffSEChanged   = 0x0100,
      ffMaskFlags   = ffFindNext|ffReplace|ffReplaceAll|ffDlgTerm|ffSEChanged,
    };
    enum TPosType{
      ptNone=-1, ptAddress, psDigit, psAscii,
    };
    enum TSelType{
      stStreamSelection, stLineSelection,
    };
 
    struct TTextSelection {
      public:
        TTextSelection(THexViewWnd* parent):Parent(parent){}
        virtual ~TTextSelection(){}
        virtual TSelType  GetType() = 0;
        virtual bool      HasSelection(int line) = 0;
        virtual bool      GetSelection(int line, int& startChar, int& endChar) = 0;
        virtual bool      IsEmpty();
        virtual TEditPos  GetStart() = 0;
        virtual TEditPos  GetEnd() = 0;
        virtual void      Extend(const TEditPos& pos) = 0;
        virtual bool      Copy(std::ostream& os) = 0;
                bool      Copy();
 
      protected:
        THexViewWnd* GetParent();
        UINT  GetFormat();
        bool  TextToClipboard(owl::TClipboard& cb, owl::uint8* text, int len);
        THexBuffer* GetBuffer();
      private:
        THexViewWnd* Parent;
    };
    struct TLineSelection: public TTextSelection {
      private:
        typedef TTextSelection Inherited;
      public:
        TLineSelection(THexViewWnd* parent, int start, int end);
        virtual TSelType GetType();
        virtual bool      HasSelection(int line);
        virtual bool      GetSelection(int line, int& startChar, int& endChar);
        virtual TEditPos  GetStart();
        virtual TEditPos  GetEnd();
        virtual void      Extend(const TEditPos& point);
        virtual bool      Copy(std::ostream& os);
 
      protected:
        int Start;
        int End;
    };
    struct TStreamSelection: public TTextSelection {
      private:
        typedef TTextSelection Inherited;
      public:
        TStreamSelection(THexViewWnd* parent, const TEditRange& range);
        virtual TSelType GetType();
        virtual bool      HasSelection(int line);
        virtual bool      GetSelection(int line, int& startChar, int& endChar);
        virtual TEditPos  GetStart();
        virtual TEditPos  GetEnd();
        virtual void      Extend(const TEditPos& point);
        virtual bool      Copy(std::ostream& os);
      protected:
        TEditRange Range;
    };
    enum THexTxtFlags{
      cfFocused           = 0x000001,
      cfHasCaret          = 0x000002,
      cfAddress           = 0x000004,
      cfDigit             = 0x000008,
      cfAscii             = 0x000010,
      cfSelMargin         = 0x000020,
      cfShowInactiveSel   = 0x000040,
      cfCursorHidden      = 0x000080,
      cfMouseDown         = 0x000100,
      cfNoUseCaret        = 0x000200,
      cfShowWideAddr      = 0x000400,
      cfSecondDigit        = 0x000800,
#if !defined(COOL_NODRAGDROP)
      cfNoDragDrop        = 0x010000,
      cfDragPending       = 0x020000,
      cfDraggingText      = 0x040000,
      cfDropPosVisible    = 0x080000,
#endif
    };
#if !defined(COOL_NODRAGDROP)
    class _COOLCLASS THexDragDropProxy: public TDragDropProxy{
      public:
        THexDragDropProxy():TDragDropProxy(0){}
    };
    friend class THexDragDropProxy;
#endif
 
  public:
    THexViewWnd(owl::TWindow* parent,int id,LPCTSTR title,int x, int y,
                int w, int h, owl::TModule* module = 0);
    ~THexViewWnd();
 
  public:
    owl::TColor  GetTxColor(int index) const;
    owl::TColor  GetBkColor(int index) const;
    THexBuffer::TSyntaxDescr& GetSyntaxDescr(int index) const;
    bool    IsUnderline(int index) const;
    bool    IsItalic(int index) const;
    bool    IsBold(int index) const;
    void    GetFont(LOGFONT& lf) const;
    void    SetFont(const LOGFONT &lf);
    int     GetCharWidth() const;
    int     GetLineHeight() const;
    owl::TFont*  GetFont(int fontindex);
    int      GetNumLines() const;
    int     GetCharsInLine() const;
    owl::uint    GetLineData(int index, owl::uint8* buff, owl::uint size) const;
    int      GetLineLength(int index);
    int     GetMarginWidth() const;
    bool    IsShowAddress() const;
    bool    IsShowDigit() const;
    bool    IsShowAscii() const;
    bool    IsShowWideAddress() const;
    void    EnableShowAddress(bool enable = true);
    void    EnableShowDigit(bool enable = true);
    void    EnableShowAscii(bool enable = true);
    void    EnableShowWideAddress(bool enable = true);
    bool    IsReadOnly() const;
    void    EnableReadOnly(bool enable);
    bool    IsStreamSelMode() const;
    bool    IsLineSelMode() const;
    bool    IsColumnSelMode() const;
    void    SetSelMode(TSelType newtyp);
    bool    IsShowInactiveSel() const;
    void    EnableShowInactiveSel(bool enable = true);
    bool    IsCaretEnable() const;
    void    EnableCaret(bool enable = true);
    TEditPos  GetCursorPos();
    void    SetCursorPos(const TEditPos& newPos);
    bool    IsSelection() const;
    void    EnableDragDrop(bool enable = true);
    bool    IsDragDrop() const;
    void    SetSelection(const TEditRange& range);
    bool    GetSelection(TEditRange& range);
  // operations
  public:
    void    GoToAddress(int address, bool relative);
 
  protected:
    void    AdjustScroller();
    owl::TFont*  GetFont(bool italic = false, bool bold = false, bool underline = false);
    int     GetTopLine();
    int     GetOffsetChar();
    void    SetSyntaxFormat(owl::TDC& dc, int index);
    int     GetScreenLines();
    int     GetScreenChars();
    bool    IsFlagSet(owl::uint flag) const;
    void    SetFlag(owl::uint flag);
    void    ClearFlag(owl::uint flag);
    bool    IsInSelection(const TEditPos& texPos) const;
    TEditPos  Client2Text(const owl::TPoint& point, bool* sPart = 0);
    owl::TPoint  Text2Client(const TEditPos& pos);
    TPosType Client2PosType(const owl::TPoint& point);
    void    ShowCursor();
    void    HideCursor();
    void    UpdateCaret();
    int     CalculateActualOffset(int lineIndex, int charIndex);
    void    ClearSelection();
    void    SelectAll();
    void    PreCheckSelection();
    void    PostCheckSelection();
    void    ScrollToCaret(const TEditPos& cursorPos);
    void    CopySelection();
#if !defined(COOL_NODRAGDROP)
    TDragDropProxy* SetDragDropProxy(TDragDropProxy* proxy);
#endif
 
  private:
    void    CalcLineCharDim();
    owl::TFont*  CreateFont(int index);
 
  public:
    virtual THexBuffer* GetBuffer() = 0;
    virtual TTextSelection* CreateSelection(const TEditRange& range);
    void Paint(owl::TDC&, bool erase, owl::TRect&) override;
    void GetWindowClass(WNDCLASS&) override;
    auto GetWindowClassName() -> owl::TWindowClassName override;
    virtual void ResetView();
    virtual void DrawLine(owl::TDC& dc, const owl::TRect& rect, int lineIndex);
    virtual void DrawMargin(owl::TDC& dc, const owl::TRect& rect, int lineIndex);
    virtual bool CreateCaret();
#if !defined(COOL_NODRAGDROP)
    virtual DROPEFFECT GetDropEffect();
    virtual void DropSource(DROPEFFECT de);
    virtual void DropText(IDataObject* src, const owl::TPoint& point, DROPEFFECT de);
    virtual bool SetDragData();
    virtual void ExecuteDragDrop();
#endif
  public:
    virtual void FileNew();
    virtual bool FileOpen(LPCTSTR filename);
    void SetupWindow() override;
    void CleanupWindow() override;
    virtual owl::TConfigFile* CreateConfigFile();
    virtual void InvalidateLines(int startLine, int endLine2,
                                 bool invalidateMargin = false);
    virtual bool Search(const TEditPos& startPos, LPCTSTR text,
                        owl::uint len, TFindFlags flags = ffNone);
 
    void EvSize(owl::uint sizeType, const owl::TSize& size);
    bool EvSetCursor(HWND hWndCursor, owl::uint hitTest, owl::uint mouseMsg);
    void EvKillFocus(HWND hWndGetFocus);
    void EvSysColorChange();
    void CmEditCopy();     // CM_EDITCOPY
    void CeSelectEnable(owl::TCommandEnabler& tce);
    void EvSetFocus(HWND hWndLostFocus);
    void EvHScroll(owl::uint scrollCode, owl::uint thumbPos, HWND hWndCtl);
    void EvVScroll(owl::uint scrollCode, owl::uint thumbPos, HWND hWndCtl);
    void EvMouseWheel(owl::uint modKeys, int zDelta, const owl::TPoint& point);
    void EvTimer(owl::uint timerId);
    void EvLButtonDown(owl::uint modKeys, const owl::TPoint& point);
    void EvMouseMove(owl::uint modKeys, const owl::TPoint& point);
    void EvLButtonUp(owl::uint modKeys, const owl::TPoint& point);
    void EvKeyDown(owl::uint key, owl::uint repeatCount, owl::uint flags);
 
    // message handlers
  public:
    void KeyEscape(int repeatCount=1);
    void ExtendRight(int repeatCount=1);
    void MoveRight(int repeatCount=1);
    void ExtendLeft(int repeatCount=1);
    void MoveLeft(int repeatCount=1);
    void ExtendDown(int repeatCount=1);
    void MoveDown(int repeatCount=1);
    void ExtendUp(int repeatCount=1);
    void MoveUp(int repeatCoun=1);
    void ExtendPgDown(int repeatCount=1);
    void MovePgDown(int repeatCount=1);
    void ExtendPgUp(int repeatCount=1);
    void MovePgUp(int repeatCount=1);
    void ExtendCtrlHome(int repeatCount=1);
    void ExtendHome(int repeatCount=1);
    void MoveCtrlHome(int repeatCount=1);
    void MoveHome(int repeatCount=1);
    void ExtendCtrlEnd(int repeatCount=1);
    void ExtendEnd(int repeatCount=1);
    void MoveCtrlEnd(int repeatCount=1);
    void MoveEnd(int repeatCount=1);
    void ScrollDown(int repeatCount=1);
    void ScrollUp(int repeatCount=1);
 
  // data
  protected_data:
    owl::TBitmap*        MemoryBitmap;
    TEditPos        CursorPos;
    owl::uint32          Flags;
    int             LineHeight;   //  Line/character dimensions
    int             CharWidth;
    owl::TFont*          TextFonts[8];
    int             ScreenLines;
    int             ScreenChars;
    TSelType        SelType;
    TTextSelection* Selection;
    TPosType        PosType;
    static UINT     SelClipFormat;
 
#if !defined(COOL_NODRAGDROP)
    // drag drop support
    TDragDropProxy*   DragDropProxy;
    TDragDropSupport  DragDropSupport;
    owl::TPoint            SavedDragPos;
    UINT_PTR DragSelTimer;
#endif
 
  friend struct THexViewWnd::TTextSelection;
  DECLARE_RESPONSE_TABLE(THexViewWnd);
}; 
////////////////////////////////////////////////////////////////////
//
inline THexViewWnd* THexViewWnd::TTextSelection::GetParent()
  {  return Parent;}
inline bool THexViewWnd::TTextSelection::IsEmpty()
  {  return GetStart() == GetEnd(); }
inline UINT THexViewWnd::TTextSelection::GetFormat()
  {  return THexViewWnd::SelClipFormat;}
inline THexBuffer* THexViewWnd::TTextSelection::GetBuffer()
  {  return Parent->GetBuffer();}
inline THexViewWnd::TSelType THexViewWnd::TLineSelection::GetType()
  { return THexViewWnd::stLineSelection; }
inline bool THexViewWnd::TLineSelection::HasSelection(int line)
  { return (line >= Start && line < End) || (line < Start && line >= End); }
inline TEditPos THexViewWnd::TLineSelection::GetStart()
  { return TEditPos(0,Start);}
inline TEditPos THexViewWnd::TLineSelection::GetEnd()
  { return TEditPos(GetParent()->GetLineLength(End),End);}
inline void THexViewWnd::TLineSelection::Extend(const TEditPos& pos)
  { End = pos.row; }
inline THexViewWnd::TSelType THexViewWnd::TStreamSelection::GetType()
  { return THexViewWnd::stStreamSelection; }
inline THexViewWnd::TStreamSelection::TStreamSelection(
  THexViewWnd* parent, const TEditRange& range)
  : TTextSelection(parent), Range(range)
  {}
inline bool THexViewWnd::TStreamSelection::HasSelection(int line){
  return (line >= Range.srow && line <= Range.erow) ||
         (line <= Range.srow && line >= Range.erow);
}
inline TEditPos THexViewWnd::TStreamSelection::GetStart(){
  return Range.Start();
}
inline TEditPos THexViewWnd::TStreamSelection::GetEnd()
  { return Range.End(); }
inline void THexViewWnd::TStreamSelection::Extend(const TEditPos& pos) {
  Range.ecol = pos.col;
  Range.erow = pos.row;
}
//
inline THexBuffer::TSyntaxDescr& THexViewWnd::GetSyntaxDescr(int index) const {
  PRECONDITION(CONST_CAST(THexViewWnd*,this)->GetBuffer());
  return CONST_CAST(THexViewWnd*,this)->GetBuffer()->GetSyntaxDescr(index);
}
//
inline owl::TColor THexViewWnd::GetTxColor(int index) const
  { return GetSyntaxDescr(index).BkColor; }
//
inline owl::TColor THexViewWnd::GetBkColor(int index) const
  { return GetSyntaxDescr(index).BkColor; }
//
inline bool THexViewWnd::IsUnderline(int index) const
  { return GetSyntaxDescr(index).FontIndex & 0x04;}
//
inline bool THexViewWnd::IsItalic(int index) const
  { return GetSyntaxDescr(index).FontIndex & 0x02; }
//
inline bool THexViewWnd::IsBold(int index) const
  { return GetSyntaxDescr(index).FontIndex & 0x01; }
//
inline void THexViewWnd::GetFont(LOGFONT& lf) const {
  PRECONDITION(CONST_CAST(THexViewWnd*,this)->GetBuffer());
  CONST_CAST(THexViewWnd*,this)->GetBuffer()->GetFont(lf);
}
//
inline owl::TFont* THexViewWnd::GetFont(int fontindex) {
  PRECONDITION(fontindex < 4 && fontindex >=0);
  return CreateFont(fontindex);
}
//
inline bool THexViewWnd::IsFlagSet(owl::uint flag) const
  {return (Flags&flag) != 0;}
//
inline void THexViewWnd::SetFlag(owl::uint flag)
  {  Flags |= flag;}
inline void THexViewWnd::ClearFlag(owl::uint flag)
  {  Flags &= ~flag;}
inline int THexViewWnd::GetMarginWidth() const
{  return 0; }
inline bool THexViewWnd::IsShowAddress() const
  { return IsFlagSet(cfAddress); }
inline bool THexViewWnd::IsShowDigit() const
  { return IsFlagSet(cfDigit); }
inline bool THexViewWnd::IsShowAscii() const
  { return IsFlagSet(cfAscii); }
inline bool THexViewWnd::IsShowWideAddress() const
  { return IsFlagSet(cfShowWideAddr); }
inline bool THexViewWnd::IsReadOnly() const{
  PRECONDITION(CONST_CAST(THexViewWnd*,this)->GetBuffer());
  return CONST_CAST(THexViewWnd*,this)->GetBuffer()->IsReadOnly();
}
inline void THexViewWnd::EnableReadOnly(bool enable){
  PRECONDITION(GetBuffer());
  GetBuffer()->EnableReadOnly(enable);
}
inline bool THexViewWnd::IsStreamSelMode() const
  { return SelType == stStreamSelection;}
inline bool THexViewWnd::IsLineSelMode() const
  { return SelType == stLineSelection; }
inline bool THexViewWnd::IsSelection() const
  {  return Selection != 0;}
inline TEditPos THexViewWnd::GetCursorPos()
  {  return CursorPos;}
inline void THexViewWnd::CopySelection(){
  PRECONDITION(Selection);
  if(Selection)
    Selection->Copy();
}
inline void THexViewWnd::CmEditCopy()
  { CopySelection(); }
inline void THexViewWnd::CeSelectEnable(owl::TCommandEnabler& ce)
  { ce.Enable(Selection); }
inline bool THexViewWnd::IsShowInactiveSel() const
  { return IsFlagSet(cfShowInactiveSel);}
inline bool THexViewWnd::IsDragDrop() const
  { return !IsFlagSet(cfNoDragDrop); }
inline bool THexViewWnd::IsCaretEnable() const
  { return !IsFlagSet(cfNoUseCaret); }
 
 
///////////////////////////////////////////////////////////////////
// class THexEditView
// ~~~~~ ~~~~~~~~~~~~~
//
//{{THexViewWnd = THexEditView}}
class _COOLCLASS THexEditView: public THexViewWnd, public owl::TView {
  public:
    THexEditView(owl::TDocument& doc, owl::TWindow* parent = 0);
    virtual ~THexEditView();
 
    static LPCTSTR StaticName();  // put in resource
 
    auto CanClose() -> bool override;
    auto GetViewName() -> LPCTSTR override;
    auto GetWindow() -> owl::TWindow* override;
    auto SetDocTitle(LPCTSTR docname, int index) -> bool override;
 
  protected:
    bool     VnIsWindow(HWND hWnd);
 
  public_data:
 
  private:
    // Hidden to prevent accidental copying or assignment
    //
    THexEditView(const THexEditView&);
    THexEditView& operator=(const THexEditView&);
 
  DECLARE_RESPONSE_TABLE(THexEditView);
}; 
 
//
inline LPCTSTR THexEditView::StaticName()
  {  return _T("HexEdit View");}
//
inline bool THexEditView::CanClose()
  { return THexViewWnd::CanClose() && (Doc->NextView(this) ||
           Doc->NextView(0) != this || Doc->CanClose()); }
//
inline LPCTSTR THexEditView::GetViewName()
  {  return StaticName(); }
//
inline owl::TWindow* THexEditView::GetWindow()
  {  return (owl::TWindow*)this; }
//
inline bool THexEditView::VnIsWindow(HWND hWnd)
  { return hWnd == GetHandle() || IsChild(hWnd); }
//
inline bool THexEditView::SetDocTitle(LPCTSTR docname, int index)
  {  return THexViewWnd::SetDocTitle(docname, index); }
//
//
//
 
#endif // COOL_HEXEDIT_H

V524 It is odd that the body of 'GetBkColor' function is fully equivalent to the body of 'GetTxColor' function.