/*****************************************************************************
* Copyright (c) 1990-2000 Digi International Inc., All Rights Reserved
* 
* This software contains proprietary and confidential information of Digi
* International Inc.  By accepting transfer of this copy, Recipient agrees
* to retain this software in confidence, to prevent disclosure to others,
* and to make no use of this software other than that for which it was
* delivered.  This is an unpublished copyrighted work of Digi International
* Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly
* prohibited.
* 
* Restricted Rights Legend
*
* Use, duplication, or disclosure by the Government is subject to
* restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in
* Technical Data and Computer Software clause at DFARS 252.227-7031 or
* subparagraphs (c)(1) and (2) of the Commercial Computer Software -
* Restricted Rights at 48 CFR 52.227-19, as applicable.
*
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
*
*****************************************************************************/

// PropStdComName.cpp : implementation file
//

#include "stdafx.h"
#include "digiasyn.h"
#include "PropStdComName.h"

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

/////////////////////////////////////////////////////////////////////////////
// CPropStdComName property page

IMPLEMENT_DYNCREATE(CPropStdComName, CPropertyPage)

CPropStdComName::CPropStdComName() : CPropertyPage(CPropStdComName::IDD)
{
	//{{AFX_DATA_INIT(CPropStdComName)
	m_nComNameIndex = -1;
	m_fEnumerateFromHere = FALSE;
	//}}AFX_DATA_INIT
	m_nExistingComNumber = 0;
   m_nSelectedComNumber = 0;
   m_nPickListCount = 0;
   for (DWORD i = 0; i < MAX_NAMES_IN_LIST; i++)
      m_nComNumberStatus[i] = COM_NUMBER_FREE;
}

CPropStdComName::~CPropStdComName()
{
}

void CPropStdComName::DoDataExchange(CDataExchange* pDX)
{
	CPropertyPage::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CPropStdComName)
	DDX_Control(pDX, IDC_CHECK_ENUMERATE_FROM_HERE, m_bcEnumerateFromHere);
	DDX_Control(pDX, IDC_COMBO_COM_NAME, m_ctlComName);
	DDX_CBIndex(pDX, IDC_COMBO_COM_NAME, m_nComNameIndex);
	DDX_Check(pDX, IDC_CHECK_ENUMERATE_FROM_HERE, m_fEnumerateFromHere);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CPropStdComName, CPropertyPage)
	//{{AFX_MSG_MAP(CPropStdComName)
	ON_CBN_SELCHANGE(IDC_COMBO_COM_NAME, OnSelchangeComboComName)
	ON_BN_CLICKED(IDC_CHECK_ENUMERATE_FROM_HERE, OnCheckEnumerateFromHere)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPropStdComName message handlers

BOOL CPropStdComName::OnInitDialog() 
{
	CPropertyPage::OnInitDialog();

   // Performance improvement only...
   m_ctlComName.InitStorage(MAX_NAMES_IN_LIST, 10);

   if (0 == m_nPickListCount)
      m_nPickListCount = DEFAULT_TO_ADD;

   // Fill the combo box....
   FillPickList();

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

BOOL CPropStdComName::FillPickList(void)
{
   BOOL fSuccess = FALSE;
   CString strComNamePrefix(COM_NAME_PREFIX);
   CString strInUse, strSystemConflict;
   strInUse.LoadString(IDS_STRING_IN_USE);
   strSystemConflict.LoadString(IDS_STRING_SYSTEM_CONFLICT);
   try
   {
      // Allow this, choose the first available
      // AffirmThrow(0 != m_nExistingComNumber);
      AffirmThrow(0 != m_nPickListCount);

      // We have a limit to the number of these
      if (m_nPickListCount > MAX_NAMES_IN_LIST)
         m_nPickListCount = MAX_NAMES_IN_LIST;

      // must want to redo the whole thing....
      if (0 != m_ctlComName.GetCount())
         m_ctlComName.ResetContent();

      // The existing port's number is greater than the specified range of com #s,
      // round up the range by DEFAULT_TO_ADD to include existing #
      if (m_nExistingComNumber >= m_nPickListCount)
         m_nPickListCount = (((m_nExistingComNumber + DEFAULT_TO_ADD) / DEFAULT_TO_ADD) * DEFAULT_TO_ADD);

      DWORD nComNumber;
      DWORD nIndex; // zero based index for drop down
      CString ComNameToAdd;
      COM_NUMBER_STATUS nStatus;
      for (nComNumber = 1; nComNumber <= m_nPickListCount; nComNumber++)
      {
         nStatus = GetComNumberStatus(nComNumber);
         switch (nStatus)
         {
         case COM_NUMBER_SYSTEM_CONFLICT:
            ComNameToAdd.Format("%s%d %s",strComNamePrefix,nComNumber,strSystemConflict);
            break;

         case COM_NUMBER_IN_USE_ABOVE_CURRENT_PORT:
            // renumbering, make these available, if not... conflict
            if (m_bcEnumerateFromHere.GetCheck())
            {  // It's OK to use the number, the port above us will release it shortly!
               ComNameToAdd.Format("%s%d",strComNamePrefix,nComNumber);
            }
            else
            {
               ComNameToAdd.Format("%s%d %s",strComNamePrefix,nComNumber,strSystemConflict);
            }
            break;

         case COM_NUMBER_FREE:
         default:
            ComNameToAdd.Format("%s%d",strComNamePrefix,nComNumber);
            if (0 == m_nExistingComNumber)
               m_nExistingComNumber = nComNumber; // If we don't have one already, grab the first free one
            break;
         }
         AffirmThrow(CB_ERR != (nIndex = m_ctlComName.AddString(ComNameToAdd)));
         m_ctlComName.SetItemData(nIndex, nStatus);
      }
      if ((nIndex + 1) < MAX_NAMES_IN_LIST)
      {
         // If there's still room, make the last entry one that allows the user to add more names
         ComNameToAdd.LoadString(IDS_STRING_MORE_NAMES);
         AffirmThrow(CB_ERR != (nIndex = m_ctlComName.AddString(ComNameToAdd)));
         m_ctlComName.SetItemData(nIndex, COM_NUMBER_ADD_MORE_NAMES);
      }
      // Finally, set the existing com name as the current selection
      //AffirmThrow(CB_ERR != (m_ctlComName.SetCurSel(m_nExistingComNumber - 1))); // zero based index...
      // D'oh!  The above resets the selection to the original COM number.
	  // Instead, we want to honor the user's current selection:
      AffirmThrow(CB_ERR != (m_ctlComName.SetCurSel(m_nSelectedComNumber - 1))); // zero based index...

      fSuccess = TRUE;
   }
   catch(CAffirmException ae)
   {
   }

   return fSuccess;
}

COM_NUMBER_STATUS CPropStdComName::GetComNumberStatus(DWORD const nNumber)
{
   return m_nComNumberStatus[nNumber - 1]; // zero based...
}

BOOL CPropStdComName::SetComNumberStatus(DWORD const nComNumber, COM_NUMBER_STATUS const nStatus)
{
   BOOL fReturn;
   if(TRUE == (fReturn = ((nComNumber > 0) && (nComNumber < MAX_NAMES_IN_LIST))))
      m_nComNumberStatus[nComNumber - 1] = nStatus;
   return fReturn;
}

//////////////////////////////////////////////////////////////////////
// We check for invalid/in-use COM numbers here, so the user may temp-
// orarily choose in-use COM numbers while renumbering (otherwise, the
// user cannot use the arrow keys to choose COM numbers).
// Added 9 July 2001 by lnb -- my first NT code!

BOOL CPropStdComName::OnKillActive()
{                          // CPropStdComName::OnKillActive()
   BOOL valid;             // TRUE if the data is valid, FALSE if the user chose an in-use COM number

   CWaitCursor wait;       // do we really need the hourglass? I copied this from OnSelchangeComboComName...
   CString ErrorMessage;

   DWORD nIndex = m_ctlComName.GetCurSel();
   COM_NUMBER_STATUS nStatus = (COM_NUMBER_STATUS)m_ctlComName.GetItemData(nIndex);
   switch (nStatus)
   {
   case COM_NUMBER_IN_USE_ABOVE_CURRENT_PORT:
      if (m_bcEnumerateFromHere.GetCheck())
      {  // It's OK to use the number, the port above us will release it shortly!
         m_nSelectedComNumber = nIndex + 1;
      }
      else
      {
         ErrorMessage.LoadString(IDS_STRING_MSB_SYSTEM_CONFLICT);
         AfxMessageBox(IDS_STRING_MSB_SYSTEM_CONFLICT,MB_ICONEXCLAMATION|MB_OK);
         //fResetSelection = TRUE;
         valid = FALSE;
      }
      break;

   case COM_NUMBER_IN_USE_BY_THIS_ADAPTER:
   case COM_NUMBER_SYSTEM_CONFLICT:
      ErrorMessage.LoadString(IDS_STRING_MSB_SYSTEM_CONFLICT);
      AfxMessageBox(IDS_STRING_MSB_SYSTEM_CONFLICT,MB_ICONEXCLAMATION|MB_OK);
      //fResetSelection = TRUE;
      valid = FALSE;
      break;

   /*
   case COM_NUMBER_ADD_MORE_NAMES:
      m_nPickListCount += DEFAULT_TO_ADD;
      FillPickList();
      //fResetSelection = TRUE;
      valid = FALSE;
      break;
   */

   case COM_NUMBER_FREE:
   default:
      m_nSelectedComNumber = nIndex + 1;
      valid = TRUE;
      break;
   }

   if (valid)
   {                             // hand-off to the base class
      valid = CPropertyPage::OnKillActive();
   }                             // hand-off to the base class
   else
   {                             // reset the combo box selection
      nStatus = (COM_NUMBER_STATUS)m_ctlComName.GetItemData(m_nExistingComNumber - 1);
      if (nStatus != COM_NUMBER_SYSTEM_CONFLICT)
      {
         m_ctlComName.SetCurSel(m_nExistingComNumber - 1); // zero based index...
         m_nSelectedComNumber = m_nExistingComNumber;
      }
   }                             // reset the combo box selection
	
   return valid;
}                                // CPropStdComName::OnKillActive()

void CPropStdComName::OnSelchangeComboComName() 
{
   CWaitCursor wait;
   CString ErrorMessage;
   BOOL fResetSelection = FALSE;

   DWORD nIndex = m_ctlComName.GetCurSel();
   COM_NUMBER_STATUS nStatus = (COM_NUMBER_STATUS)m_ctlComName.GetItemData(nIndex);
   switch (nStatus)
   {
   /*
   case COM_NUMBER_IN_USE_ABOVE_CURRENT_PORT:
      if (m_bcEnumerateFromHere.GetCheck())
      {  // It's OK to use the number, the port above us will release it shortly!
         m_nSelectedComNumber = nIndex + 1;
      }
      else
      {
         ErrorMessage.LoadString(IDS_STRING_MSB_SYSTEM_CONFLICT);
         AfxMessageBox(IDS_STRING_MSB_SYSTEM_CONFLICT,MB_ICONEXCLAMATION|MB_OK);
         fResetSelection = TRUE;
      }
      break;
   */

   /*
   case COM_NUMBER_IN_USE_BY_THIS_ADAPTER:
   case COM_NUMBER_SYSTEM_CONFLICT:
      ErrorMessage.LoadString(IDS_STRING_MSB_SYSTEM_CONFLICT);
      AfxMessageBox(IDS_STRING_MSB_SYSTEM_CONFLICT,MB_ICONEXCLAMATION|MB_OK);
      fResetSelection = TRUE;
      break;
   */

   case COM_NUMBER_ADD_MORE_NAMES:
      m_nPickListCount += DEFAULT_TO_ADD;
      FillPickList();
      fResetSelection = TRUE;
      break;

   case COM_NUMBER_FREE:
   default:
      m_nSelectedComNumber = nIndex + 1;
      break;
   }

   /*
   if (fResetSelection)
   {
      // We need to reset to the existing com name
      // NOTE: NOTE: causes re-entry into OnSelchangeComboComName(), make sure we won't do an endless loop...
      nStatus = (COM_NUMBER_STATUS)m_ctlComName.GetItemData(m_nExistingComNumber - 1);
      if ((nStatus != COM_NUMBER_ADD_MORE_NAMES) && (nStatus != COM_NUMBER_SYSTEM_CONFLICT))
      {
         m_ctlComName.SetCurSel(m_nExistingComNumber - 1); // zero based index...
         m_nSelectedComNumber = m_nExistingComNumber;
      }
   }
   */
}

void CPropStdComName::OnCheckEnumerateFromHere() 
{
   // If the com numbers overlap, we can use the overlapping ones
   FillPickList(); // Refill depending on state of check box
}
