// OptEdit.cpp : implementation file
//

#include "stdafx.h"
#include "afxpriv.h"

#include "WgsCnf.h"
#include "CnfDoc.h"
#include "modifier.h"
#include "YesNo.h"
#include "StrEdit.h"
#include "OptEdit.h"
#include "EnumComb.h"
#include "cstrutil.h"
#include "LangComb.h"
#include "DrawBut.h"
#include "gcommlib.h"
#include "cnf.h"
#include "lingo.h"
#include "edtoff.h"
#include "fioapi.h"
#include "CnfAsrt.h"
#include "mainfrm.h"
#include "FileUtil.h"
#include "regutil.h"

#define FILREV "$Revision: $"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// OptionEditView

//   used to give the view a gray background
//
static DWORD  backColor = GetSysColor( COLOR_3DLIGHT );
CBrush OptionEditView::m_brush(backColor);
CFont *OptionEditView::m_ourFont = NULL;
char OptionEditView::altbuf[ 32 * 1024 ];

const int padding = 10;   // padding around controls

IMPLEMENT_DYNCREATE(OptionEditView, CScrollView)

OptionEditView::OptionEditView()
{
     m_description = NULL;
     m_combo = NULL;
     m_edit = NULL;
     m_radios = NULL;
     m_langList = NULL;
     m_drawButton = NULL;
     m_limits = NULL;

     hasEdit = FALSE;
     hasButtons = FALSE;
     hasCombo = FALSE;
     hasMultiEdit = FALSE;

     m_curLang = 0;
}

OptionEditView::~OptionEditView()
{
     RemoveOldControls();

     if (m_ourFont != NULL)
     {
          LOGFONT   lf;

          m_ourFont->GetLogFont( &lf );

          SaveLogfont( "settings", "EditViewFontInfo", lf );

          delete m_ourFont;
          m_ourFont = NULL;
     }
}


BEGIN_MESSAGE_MAP(OptionEditView, CScrollView)
     //{{AFX_MSG_MAP(OptionEditView)
     ON_WM_ERASEBKGND()
     ON_WM_SIZE()
     ON_WM_CONTEXTMENU()
	ON_COMMAND(ID_FILE_PRINT, OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, OnFilePrintPreview)
     ON_WM_CTLCOLOR()
	ON_COMMAND(IDD_TEXTREPORT, OnTextreport)
	//}}AFX_MSG_MAP

     //   enable 3D controls for this view
     //
     ON_MESSAGE(WM_QUERY3DCONTROLS, OnQuery3dControls)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// OptionEditView drawing

void OptionEditView::OnInitialUpdate()
{
     if (m_ourFont != NULL)
          SetFont( m_ourFont, FALSE );

     CScrollView::OnInitialUpdate();

     CRect cliRect;
     GetClientRect( cliRect );

     int     width = cliRect.Width();

     CSize sizeTotal;

     sizeTotal.cx = width;
     sizeTotal.cy = 300;
     SetScrollSizes(MM_TEXT, sizeTotal);
}

void OptionEditView::OnDraw(CDC* pDC)
{
     CDocument* pDoc = GetDocument();
     // TODO: add draw code here
}

/////////////////////////////////////////////////////////////////////////////
// OptionEditView diagnostics

#ifdef _DEBUG
void OptionEditView::AssertValid() const
{
     CScrollView::AssertValid();
}

void OptionEditView::Dump(CDumpContext& dc) const
{
     CScrollView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// OptionEditView message handlers


void OptionEditView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo) 
{
     // TODO: Add your specialized code here and/or call the base class
     
     CScrollView::OnPrepareDC(pDC, pInfo);

     if (pDC->GetBkMode() == TRANSPARENT)
          pDC->SetBkMode( OPAQUE );

     if (pDC != NULL)
          pDC->SetBkColor( backColor );
}

BOOL OptionEditView::OnEraseBkgnd(CDC* pDC) 
{
     CBrush backBrush( backColor );
     CBrush* pOldBrush = pDC->SelectObject(&backBrush);

     CRect rect;
     pDC->GetClipBox(&rect);     // Erase the area needed

     pDC->PatBlt(rect.left, rect.top, rect.Width(),
                 rect.Height(), PATCOPY);
     pDC->SelectObject(pOldBrush);
     return TRUE;
}


void OptionEditView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 
{
     if (lHint == SelectionChanged)
     {
          CnfAssert( pHint != NULL );

          Modifier *theMod = static_cast< Modifier * >( pHint );
          CnfAssert( theMod != NULL );

          m_key = theMod->itemKey;

          CString descText;
          CString editText;

          hasEdit = FALSE;
          hasButtons = FALSE;
          hasCombo = FALSE;
          hasMultiEdit = FALSE;

          CString origValue;
          const CString *origValues = NULL;

          if ((theMod->treeData != NULL) &&
               (theMod->treeData->opPtr != NULL)
             )
          {
               descText = theMod->treeData->opPtr->lineDesc;
               editText = theMod->treeData->opPtr->curValue;

               origValue = theMod->treeData->opPtr->origValue;
               origValues = theMod->treeData->opPtr->origValues;
          }

          int       tlen = 0;

          CString   floorStr;
          CString   ceilStr;

          CHAR      type = 0;
          long      floor = -1;
          long      ceiling = -1;

          if (theMod->treeData->opPtr != NULL)
          {
               type = theMod->treeData->opPtr->type;

               floor = theMod->treeData->opPtr->floor;
               ceiling = theMod->treeData->opPtr->ceiling;

               switch (type)
               {
                    case 'C':
                         tlen = 1;
                         hasEdit = TRUE;
                         break;

                    case 'S':
                         tlen = floor = ceiling;
                         hasEdit = TRUE;
                         floorStr.Format( "Maximum length: %li chars", ceiling );
                         break;

                    case 'N':
                    case 'L':
                         floorStr.Format( "%d", floor );
                         ceilStr.Format( "%d", ceiling );
                         tlen = max( floorStr.GetLength(), ceilStr.GetLength() );
                         floorStr.Format( "Minimum: %d", floor );
                         if (ceiling > 0)
                         {
                              ceilStr.Format( "Maximum: %d", ceiling );
                         }
                         hasEdit = TRUE;
                         break;

                    case 'H':
                         floorStr.Format( "%lX", floor );
                         ceilStr.Format( "%lX", ceiling );
                         tlen = max( floorStr.GetLength(), ceilStr.GetLength() );
                         floorStr.Format( "Minimum: %lX (hex)", floor );
                         if (ceiling > 0)
                         {
                              ceilStr.Format( "Maximum: %lX (hex)", ceiling );
                         }
                         hasEdit = TRUE;
                         break;

                    case 'T':
                         hasMultiEdit = TRUE;
                         break;

                    case 'B':
                         hasButtons = TRUE;
                         break;

                    case 'E':
                         hasCombo = TRUE;
                         break;
               }
          }

          CRect cliRect;
          GetClientRect( cliRect );

          int     width = cliRect.Width();

          CDC    *theDC = GetDC();

          int       CXDLGFRAME = GetSystemMetrics( SM_CXDLGFRAME );
          int       CYDLGFRAME = GetSystemMetrics( SM_CYDLGFRAME );

          int       textBottom = padding;
          int       tsize = 30;
          int       twidth = 0;

          if (theDC != NULL)
          {
               if (m_ourFont != NULL)
               {
                    theDC->SelectObject( m_ourFont );
                    SetFont( m_ourFont );
               }

               CSize    extent = theDC->GetTextExtent( descText );

               int       textLines = 1;

               if (extent.cx > (width - 20))
               {
                    textLines = ((extent.cx + (width - 20) / 2) / (width - 20)) + 1;
                    twidth = width - (padding * 2);
               }
               else
               {
                    twidth = extent.cx;
               }

               textBottom = (textLines * extent.cy) + 10; 

               TEXTMETRIC metrics;
               theDC->GetTextMetrics( &metrics );
               tsize = metrics.tmHeight;
          }

          int       controlTop = textBottom + 15;

          RemoveOldControls();

          m_description = new CStatic;

          m_description->Create( descText, 
                            WS_VISIBLE | WS_CHILD,
                            CRect( 10, 10, width - 10, textBottom ),
                            this
                          );

          int       bottom = textBottom;
          int       right = twidth + padding;

          if (m_ourFont != NULL)
          {
               m_description->SetFont( m_ourFont, FALSE );
               m_description->SetWindowText( descText );
          }

          if (hasButtons)
          {
               m_radios = new YesNoButton[ 2 ];

               int       buttonHeight = (tsize * 3) / 2;

               for ( int count = 0; count < 2; ++count )
               {
                    CString caption = (count == 0) ? "YES" : "NO";

                    int       buttonTop = controlTop + count * buttonHeight;
                    int       buttonBottom = buttonTop + buttonHeight - 2;

                    CRect  buttonRect( 10, buttonTop,
                                           75, buttonBottom
                                         );

                    m_radios[ count ].Create( caption,
                                                  BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | ((count == 0) ? WS_GROUP : 0),
                                                  buttonRect,
                                                  this,
                                                  ID_MYGROUP + count
                                               );

                    if (m_ourFont != NULL)
                    {
                         m_radios[ count ].SetFont( m_ourFont );
                         m_radios[ count ].SetWindowText( caption );
                    }

                    m_radios[ count ].SetKey( theMod->itemKey );
                    m_radios[ count ].SetCheck( caption == editText );
                    m_radios[ count ].SetOriginalValue( caption == origValue );

                    bottom = max( bottom, buttonBottom );
                    right = max( right, 75 );
               }

               m_radios[ 0 ].SetNext    ( &m_radios[ 1 ] );
               m_radios[ 1 ].SetPrevious( &m_radios[ 0 ] );
          }
          else if (hasEdit)
          {
               m_edit = new StringEdit;

               int       textHeight = (tsize + (2 * CYDLGFRAME));

               int       twidth = 0;

               if (tlen > 0)
               {
                    int  fudge = max( (tlen * 15) / 100, 1 );

                    twidth = GetMaxWidth( theDC, tlen ) + (2 * CXDLGFRAME);

               }

               CRect     editRect( 10, controlTop, 
                                   width - 10, controlTop + textHeight 
                                 );

               if (twidth > 0)
                    editRect.right = 10 + twidth;

               bottom = max( bottom, editRect.bottom );
               right = max( right, editRect.right );

               m_edit->Create( WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_BORDER,
                               editRect,
                               this,
                               ID_MYGROUP + 5,
                               theMod->treeData
                             );

               if (m_ourFont != NULL)
               {
                    m_edit->SetFont( m_ourFont );
               }

               if (tlen > 0)
               {
                    m_edit->LimitText( tlen );
               }

               m_edit->SetWindowText( editText );
               m_edit->SetKey( theMod->itemKey );
               m_edit->SetEditDetails( type, floor, ceiling );
               m_edit->SetOriginalValue( origValue );

               if ((floorStr != "") || (ceilStr != ""))
               {
                    CSize    floorExtent = theDC->GetTextExtent( floorStr );
                    CSize    ceilExtent  = theDC->GetTextExtent( ceilStr );

                    int      limitWidth  = max( floorExtent.cx, ceilExtent.cx );
                    int      limitHeight = floorExtent.cy + ceilExtent.cy;

                    int       limitTop = controlTop + textHeight + 10;
                    int       limitBottom = limitTop + limitHeight;
                    
                    CString   theText( floorStr );

                    if (ceilStr.GetLength() > 0)
                    {
                         if (theText.GetLength() > 0)
                         {
                              theText += "\r\n";
                         }
                         theText += ceilStr;
                    }
                    
                    m_limits = new CStatic;
                    CnfAssert( m_limits != NULL );

                    m_limits->Create( "", 
                                      WS_VISIBLE | WS_CHILD,
                                      CRect( 10, limitTop, 
                                             10 + limitWidth, limitBottom 
                                           ),
                                      this
                                    );

                    m_limits->SetFont( m_ourFont );
                    m_limits->SetWindowText( theText );

                    bottom = max( bottom, limitBottom );
                    right = max( right, 10 + limitWidth );
               }
          }
          else if (hasMultiEdit)
          {
               int       textHeight = (tsize + (2 * CYDLGFRAME));
               int       buttonHeight = (tsize * 3) / 2;

               int       controlHeight = max( textHeight, buttonHeight );

               int       controlWidth = width - 20;
               int       space = 10;

               int       comboWidth = ((controlWidth - space) * 2) / 3;
               int       buttonWidth = controlWidth - comboWidth - space;

               int       comboLeft = 10;
               int       comboRight = comboLeft + comboWidth - 1;
               int       buttonLeft = comboRight + space + 1;
               int       buttonRight = width - 10;

               int       controlBottom = controlTop + controlHeight - 1;

               CRect     editRect( cliRect );

               editRect.top = controlBottom + 6;
               editRect.left += 10;
               editRect.bottom -= 10;
               editRect.right -= 10;

               CRect     comboRect( comboLeft, controlTop,
                                    comboRight, controlBottom
                                  );
               CRect     buttonRect( buttonLeft, controlTop,
                                     buttonRight, controlBottom
                                   );

               right = max( right, max( comboRight, buttonRight ) );

               m_langList = new LangCombo;
               m_langList->Create( comboRect,
                                   this,
                                   ID_MYGROUP,
                                   m_ourFont,
                                   tsize,
                                   nlingo,
                                   (const char **)langchoose
                                 );

               m_drawButton = new DrawButton;
               m_drawButton->Create( buttonRect, this, ID_MYGROUP + 1, m_ourFont );

               m_edit = new StringEdit;

               m_edit->Create( WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL |
                               ES_AUTOVSCROLL | WS_BORDER | ES_MULTILINE | 
                               WS_HSCROLL | WS_VSCROLL,
                               editRect,
                               this,
                               ID_MYGROUP + 2,
                               theMod->treeData
                             );

               if (m_ourFont != NULL)
               {
                    m_edit->SetFont( m_ourFont );
               }

               m_edit->SetKey( theMod->itemKey );
               m_edit->SetEditDetails( type, floor, ceiling );
               m_edit->SetOriginalValues( origValues );

               SelectLanguage( m_curLang );

               right = max( right, editRect.right );
               bottom = max( bottom, editRect.bottom );
          }
          else if (hasCombo)
          {
               m_combo = new EnumCombo;
               m_combo->Create( this, 10, width - 10, controlTop,
                                tsize, CYDLGFRAME, CXDLGFRAME,
                                ID_MYGROUP + 6,
                                theMod->treeData->opPtr->enList,
                                m_ourFont,
                                theDC
                              );

               CnfAssert( theMod->treeData != NULL );
               CnfAssert( theMod->treeData->opPtr != NULL );

               m_combo->SelectString( -1, theMod->treeData->opPtr->curValue );
               m_combo->SetKey( theMod->itemKey );
               m_combo->SetOriginalValue( origValue );

               CRect     cliRect;
               m_combo->GetWindowRect( cliRect );

               CRect     viewRect;
               GetWindowRect( viewRect );

               right = max( right, cliRect.right - viewRect.left );
               bottom = max( bottom, cliRect.bottom - viewRect.right );
          }

          SetScrollSizes( MM_TEXT, CSize( right + padding - 1, bottom + padding -1 ) );
     }
     else if (lHint == FileSaved)
     {
          CnfDoc *doc = static_cast< CnfDoc * >( GetDocument() );

          CnfAssert( doc != NULL );

          option    *op = NULL;
          TreeData  ourData;

          if (doc->Lookup( m_key, ourData ))
          {
               op = ourData.opPtr;
          }

          if (op != NULL)
          {
               if (hasEdit)
               {
                    CnfAssert( m_edit != NULL );
                    m_edit->SetOriginalValue( op->origValue );
               }
               else if (hasMultiEdit)
               {
                    CnfAssert( m_edit != NULL );
                    CnfAssert( op->origValues != NULL );
                    m_edit->SetOriginalValues( op->origValues );
               }
               else if (hasCombo)
               {
                    CnfAssert( m_combo != NULL );
                    m_combo->SetOriginalValue( op->origValue );
               }
               else if (hasButtons)
               {
                    CnfAssert( m_radios != NULL );

                    for ( int count = 0; count < 2; ++count )
                    {
                         CString   val;
                         m_radios[ count ].GetWindowText( val );
                         BOOL      origVal = (val == op->origValue);

                         m_radios[ count ].SetOriginalValue( origVal );
                    }
               }
          }
     }
     else if (lHint == FocusOnEdit)
     {
          if (hasEdit || hasMultiEdit)
          {
               m_edit->SetFocus();
          }
          else if (hasCombo)
          {
               m_combo->SetFocus();
          }
          else if (hasButtons)
          {
               for ( int count = 0; count < 2; ++count )
               {
                    if (m_radios[ count ].GetCheck())
                    {
                         m_radios[ count ].SetFocus();
                         break;
                    }
               }
          }
     }
     else if ((lHint != ItemModified) && (lHint != ItemAdded))
          CScrollView::OnUpdate( pSender, lHint, pHint );
}


void OptionEditView::SetFontChars( const LOGFONT &lf, BOOL replaceOld )
{
     if (replaceOld && (m_ourFont != NULL))
     {
          delete m_ourFont;
          m_ourFont = NULL;
     }

     if (m_ourFont == NULL)
     {
          m_ourFont = new CFont;

          BOOL createRes = m_ourFont->CreateFontIndirect( &lf );
          CnfAssert( createRes );
     }
}


void OptionEditView::OnSize(UINT nType, int cx, int cy) 
{
     CScrollView::OnSize(nType, cx, cy);
     
     if (hasMultiEdit && (nType != SIZE_MINIMIZED) && (m_edit != NULL))
     {
          CRect     cliRect;
          GetClientRect( &cliRect );
          CRect     editRect( cliRect );

          WINDOWPLACEMENT wp;

          m_edit->GetWindowPlacement( &wp );

          editRect.top = wp.rcNormalPosition.top;
          editRect.left   += padding;
          editRect.bottom -= padding;
          editRect.right  -= padding;

          wp.rcNormalPosition = editRect;

          if ((editRect.right  >= editRect.left + 40) &&
              (editRect.bottom >= editRect.left + 20)
             )
          {
               m_edit->SetWindowPlacement( &wp );
          }

          WINDOWPLACEMENT buttonWp;
          m_drawButton->GetWindowPlacement( &buttonWp );
          const RECT &button = buttonWp.rcNormalPosition;

          int       bottom = editRect.bottom;
          int       right = max( editRect.right, button.right );

          SetScrollSizes( MM_TEXT, CSize( right + padding, bottom + padding ) );
     }
}

void OptionEditView::SelectLanguage( int langNo )
{
     CnfAssert( langNo >= 0 );
     CnfAssert( langNo <  nlingo );

     m_curLang = langNo;

     CnfAssert( m_edit != NULL );
     CnfAssert( hasMultiEdit );

     m_edit->SelectLanguage( langNo );

     CnfAssert( m_langList != NULL );
     m_langList->SelectLanguage( langNo );          

     CString   drawName = languages[m_curLang]->editor;
     CString   drawFn;

     if (drawName != "")
     {
          int       end = drawName.Find( ' ' );

          if (end >= 0)
               drawName = drawName.Left( end );

          drawFn = drawName;

          end = drawName.Find( '.' );

          if (end >= 0)
               drawName = drawName.Left( end );
     }

     m_drawButton->EnableWindow( ExecutableExists( drawFn ) );

     if (drawName == "")
          m_drawButton->SetWindowText( "Draw" );
     else
          m_drawButton->SetWindowText( drawName );
}

int OptionEditView::GetCurLang() const
{
     CnfAssert( m_curLang >= 0 );
     CnfAssert( m_curLang <  nlingo );

     return( m_curLang );
}


void OptionEditView::CustomEdit()
{
     CnfAssert( hasMultiEdit );
     CnfAssert( m_edit != NULL );

     m_edit->GetWindowText( m_origText );

     char      tfn[ 256 ];

     sprintf(tfn,"CNF*%s",languages[m_curLang]->extans);
     uniqfn(tfn);

     CString cmdbuf;
     cmdbuf.Format( languages[m_curLang]->editor,tfn,tfn);

     stzcpy( altbuf, m_origText, bufsize );

     //   BOOL    allowed = allowOtherUtil();
     //   CnfAssert( allowed );
     int rc = edtoff((char *)(const char *)cmdbuf,altbuf,bufsize,tfn);

     if (rc != EOLATER)
     {
          //   BOOL    canRun = canRunUtil();
          //   CnfAssert( canRun );
     }

     switch (rc)
     {
          case  EOABORT:              // operator aborted editing, recover old data
          case  EONOCHG:                                       // no change to data
               break;

          case  EONOTME:              // I'm not the editor specified in "command"
               MessageBox( "No appropriate editor/drawing program was\r\n"
                           "found for this text block.  The original\r\n"
                           "text will not be changed.",
                           "Unable to edit Text Block"
                         );
               break;

          case  EOERROR:    // some kind of error occurred (see about edterr below)
               {
                    CString   msgText;
                    msgText.Format( "Error editing text block:\r\n\r\n%s\r\n\r\n"
                                    "The original text will not be changed.",
                                    edterr
                                  );
                    MessageBox( msgText, "Unable to edit Text Block" );
               }
               break;

          case  EOTRUNC:                             // data truncated (ref ibsize)
               MessageBox( "Data truncated.  Do more with this." );
               break;

          case  EOSAVE :                            // Done editing, save this data
               if (altbuf != m_origText )
                    m_edit->ChangeText( altbuf );
               break;

          case EOLATER:  // work in progress
               m_edit->EnableWindow( FALSE );

               if (hasMultiEdit)
               {
                    CnfAssert( m_drawButton != NULL );
                    CnfAssert( m_langList != NULL );

                    m_drawButton->EnableWindow( FALSE );
                    m_langList->EnableWindow( FALSE );
               }

               break;

          default:
               catastro( "Unknown return from edtoff(): %08X", rc );
               break;
     }
}

void OptionEditView::RemoveOldControls()
{
     if (m_description != NULL)
     {
          delete m_description;
          m_description = NULL;
     }
     if (m_edit != NULL)
     {
          delete m_edit;
          m_edit = NULL;
     }
     if (m_combo != NULL)
     {
          delete m_combo;
          m_combo = NULL;
     }
     if (m_radios != NULL)
     {
          delete [] m_radios;
          m_radios = NULL;
     }
     if (m_langList != NULL)
     {
          delete m_langList;
          m_langList = NULL;
     }
     if (m_drawButton != NULL)
     {
          delete m_drawButton;
          m_drawButton = NULL;
     }
     if (m_limits != NULL)
     {
          delete m_limits;
          m_limits = NULL;
     }
}

BOOL OptionEditView::ValidateCurrentItem()
{
     BOOL      valid = TRUE;

     if ((hasEdit || hasMultiEdit) && (m_edit != NULL))
     {
          valid = m_edit->IsValid();
     }

     return( valid );
}

HBRUSH OptionEditView::OnCtlColor( CDC *pDC, CWnd *pWnd, UINT nCtlColor )
{
     if (pWnd->IsKindOf( RUNTIME_CLASS( CEdit ) ) ||
         pWnd->IsKindOf( RUNTIME_CLASS( CComboBox ) )
        )
     {
          pDC->SetBkColor( GetSysColor( COLOR_WINDOW ) );
          return( GetSysColorBrush( COLOR_WINDOW ) );
     }

     if (pDC != NULL)
     {
          pDC->SetBkColor( backColor );
     }

     return( m_brush );
//     return( OnGrayCtlColor( pDC, pWnd, nCtlColor ) );
}

int OptionEditView::GetMaxWidth( CDC *dc, int tlen ) const
{
     CnfAssert( dc != NULL );
     CnfAssert( tlen >= 0 );

     CString   wstring;

     for ( int count = 0; count < tlen; ++count )
     {
          wstring += 'W';
     }

     CSize     extent = dc->GetTextExtent( wstring );

     return( extent.cx );
}

void OptionEditView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) 
{
     // TODO: Add your specialized code here and/or call the base class
     
     CScrollView::OnActivateView(bActivate, pActivateView, pDeactiveView);

     if (bActivate)
     {
          if (hasEdit || hasMultiEdit)
          {
               CnfAssert( m_edit != NULL );
               m_edit->SetFocus();
          }
          else if (hasCombo)
          {
               CnfAssert( m_combo != NULL );
               m_combo->SetFocus();
          }
          else if (hasButtons)
          {
               CnfAssert( m_radios != NULL );
               m_radios->SetFocus();
          }
     }
}

CMainFrame *OptionEditView::GetFrame() const
{
     const CWnd *wnd = this;

     while (! wnd->IsKindOf( RUNTIME_CLASS( CMainFrame ) ))
     {
          wnd = wnd->GetParent();

          CnfAssert( wnd != NULL );
     }

     return( (CMainFrame *)wnd );
}


void OptionEditView::FinishExternal( int rc )
{
     m_edit->EnableWindow( TRUE );

     switch (rc)
     {
          case  EOABORT:              // operator aborted editing, recover old data
          case  EONOCHG:                                       // no change to data
               break;

          case  EONOTME:              // I'm not the editor specified in "command"
               MessageBox( "No appropriate editor/drawing program was\r\n"
                           "found for this text block.  The original\r\n"
                           "text will not be changed.",
                           "Unable to edit Text Block"
                         );
               break;

          case  EOERROR:    // some kind of error occurred (see about edterr below)
               {
                    CString   msgText;
                    msgText.Format( "Error editing text block:\r\n\r\n%s\r\n\r\n"
                                    "The original text will not be changed.",
                                    edterr
                                  );
                    MessageBox( msgText, "Unable to edit Text Block" );
               }
               break;

          case  EOTRUNC:                             // data truncated (ref ibsize)
               MessageBox( "Data truncated.  Do more with this." );
               break;

          case  EOSAVE :                            // Done editing, save this data
               if (altbuf != m_origText )
                    m_edit->ChangeText( altbuf );
               break;

          case EOLATER:  // work in progress
               CnfAssert( FALSE );
               break;

          default:
               catastro( "Unknown return from edtoff(): %08X", rc );
               break;
     }

     if (hasMultiEdit)
     {
          CnfAssert( m_drawButton != NULL );
          CnfAssert( m_langList != NULL );

          m_drawButton->EnableWindow( TRUE );
          m_langList->EnableWindow( TRUE );
     }

     //   BOOL    canRun = canRunUtil();
     //   CnfAssert( canRun );

     return;
}


void OptionEditView::OnContextMenu(CWnd* pWnd, CPoint point) 
{
     (void)pWnd;
     (void)point;

     EditFont();
}

BOOL OptionEditView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) 
{
     BOOL result = CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);

     if (result)
     {
          LOGFONT   lf;

          if (ReadLogfont( "settings", "EditViewFontInfo", lf ))
          {
               SetFontChars( lf, TRUE );
          }
     }

     return( result );
}

void OptionEditView::EditFont()
{
     if (! ValidateCurrentItem())
     {
          MessageBeep( MB_ICONASTERISK );
     }
     else
     {
          CFont    *font = GetFont();

          if (font == NULL)
          {
               font = m_ourFont;
          }

          CnfAssert( font != NULL );

          LOGFONT   lf;
          font->GetLogFont( &lf );

          CFontDialog dlg( &lf, CF_SCREENFONTS, NULL, this );

          if (dlg.DoModal() == IDOK)
          {
               SetFontChars( lf, TRUE );
               SetFont( m_ourFont );

               TreeData ourData;
               CnfDoc *doc = static_cast< CnfDoc * >( GetDocument() );
               CnfAssert( doc != NULL );

               BOOL      lookRes = doc->Lookup( m_key, ourData );
               CnfAssert( lookRes );

               Modifier mod;
               mod.treeData = &ourData;
               mod.itemKey = m_key;

               OnUpdate( NULL, SelectionChanged, &mod );
          }
     }
}

void OptionEditView::OnFilePrint() 
{
     CnfDoc *doc = static_cast< CnfDoc * >( GetDocument() );

     if (doc != NULL)
     {
          OptionTree *tv = doc->GetTreeView();
          CnfAssert( tv != NULL );

          tv->Print();
     }
}

void OptionEditView::OnFilePrintPreview() 
{
     CnfDoc *doc = static_cast< CnfDoc * >( GetDocument() );

     if (doc != NULL)
     {
          OptionTree *tv = doc->GetTreeView();
          CnfAssert( tv != NULL );

          tv->PrintPreview();
     }
}

void OptionEditView::OnTextreport() 
{
     CnfDoc *doc = static_cast< CnfDoc * >( GetDocument() );

     if (doc != NULL)
     {
          OptionTree *tv = doc->GetTreeView();
          CnfAssert( tv != NULL );

          tv->TextReport();
     }
}
