<commit_before>/*
* Copyright (c) 2003-2009 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/
// AddEdit_DateTimes.cpp : implementation file
//

#include "stdafx.h"
#include "PasswordSafe.h"
#include "ThisMfcApp.h"    // For Help
#include "DboxMain.h"
#include "AddEdit_DateTimes.h"
#include "AddEdit_PropertySheet.h"

#include "corelib/PWSprefs.h"
#include "corelib/PWSAuxParse.h"

#include "resource3.h"

bool CAddEdit_DateTimes::m_bNumDaysFailed = false;

static void AFXAPI DDV_CheckMaxDays(CDataExchange* pDX, const int &how,
                                    int &numDays, const int &maxDays);

/////////////////////////////////////////////////////////////////////////////
// CAddEdit_DateTimes property page

IMPLEMENT_DYNAMIC(CAddEdit_DateTimes, CAddEdit_PropertyPage)

CAddEdit_DateTimes::CAddEdit_DateTimes(CWnd *pParent, st_AE_master_data *pAEMD)
  : CAddEdit_PropertyPage(pParent, CAddEdit_DateTimes::IDD, pAEMD),
  m_how(ABSOLUTE_EXP), m_numDays(1), m_ReuseOnPswdChange(FALSE)
{
}

CAddEdit_DateTimes::~CAddEdit_DateTimes()
{
}

void CAddEdit_DateTimes::DoDataExchange(CDataExchange* pDX)
{
  CAddEdit_PropertyPage::DoDataExchange(pDX);

  //{{AFX_DATA_MAP(CAddEdit_DateTimes)
  DDX_Text(pDX, IDC_XTIME, (CString&)M_locXTime());
  DDX_Text(pDX, IDC_CTIME, (CString&)M_locCTime());
  DDX_Text(pDX, IDC_PMTIME, (CString&)M_locPMTime());
  DDX_Text(pDX, IDC_ATIME, (CString&)M_locATime());
  DDX_Text(pDX, IDC_XTIME, (CString&)M_locXTime());
  DDX_Text(pDX, IDC_RMTIME, (CString&)M_locRMTime());

  DDX_Text(pDX, IDC_EXPDAYS, m_numDays);
  DDX_Radio(pDX, IDC_SELECTBYDATETIME, m_how);
  DDX_Check(pDX, IDC_REUSE_ON_CHANGE, m_ReuseOnPswdChange);

  DDX_Control(pDX, IDC_EXPIRYDATE, m_pDateCtl);
  DDX_Control(pDX, IDC_EXPIRYTIME, m_pTimeCtl);

  // Validation
  DDV_CheckMaxDays(pDX, m_how, m_numDays, m_maxDays);
  //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAddEdit_DateTimes, CAddEdit_PropertyPage)
  //{{AFX_MSG_MAP(CAddEdit_DateTimes)
  ON_BN_CLICKED(ID_HELP, OnHelp)
  ON_BN_CLICKED(IDC_XTIME_CLEAR, OnClearXTime)
  ON_BN_CLICKED(IDC_XTIME_SET, OnSetXTime)
  ON_BN_CLICKED(IDC_SELECTBYDATETIME, OnDateTime)
  ON_BN_CLICKED(IDC_SELECTBYDAYS, OnDays)
  ON_BN_CLICKED(IDC_REUSE_ON_CHANGE, OnReuseOnPswdChange)
  // Common
  ON_MESSAGE(PSM_QUERYSIBLINGS, OnQuerySiblings)
  //}}AFX_MSG_MAP
END_MESSAGE_MAP()

static void AFXAPI DDV_CheckMaxDays(CDataExchange* pDX, const int &how,
                                    int &numDays, const int &maxDays)
{
  if (pDX->m_bSaveAndValidate) {
    CAddEdit_DateTimes::m_bNumDaysFailed = false;
    if (how == CAddEdit_DateTimes::RELATIVE_EXP && numDays > maxDays) {
      CString csError;
      csError.Format(IDS_MAXNUMDAYSEXCEEDED, maxDays);
      AfxMessageBox(csError);
      CAddEdit_DateTimes::m_bNumDaysFailed = true;
      pDX->Fail();
      return;
    }
  }
}

BOOL CAddEdit_DateTimes::OnInitDialog()
{
  CAddEdit_PropertyPage::OnInitDialog();

  ModifyStyleEx (0, WS_EX_CONTROLPARENT);

  // Time fields
  time(&M_tttCPMTime());

  wchar_t szBuf[81];     // workspace
  CString sTimeFormat;   // the time format being worked on
  CString sDateFormat;
  CString sSearch;       // the string to search for
  int nIndex;            // index of the string, if found

  GetDlgItem(IDC_EXPDAYS)->EnableWindow(FALSE);

  // Last 32-bit date is 03:14:07 UTC on Tuesday, January 19, 2038
  // Find number of days from now to 2038/01/18 = max value here
  const CTime ct_Latest(2038, 1, 18, 0, 0, 0);
  const CTime ct_Now(CTime::GetCurrentTime());

  CTimeSpan elapsedTime = ct_Latest - ct_Now;
  m_maxDays = (int)elapsedTime.GetDays();

  CSpinButtonCtrl * pspin = (CSpinButtonCtrl *)GetDlgItem(IDC_EXPDAYSSPIN);

  pspin->SetBuddy(GetDlgItem(IDC_EXPDAYS));
  pspin->SetBase(10);
  pspin->SetRange32(1, m_maxDays);
  pspin->SetPos(1);

  // enable/disable relevant controls, depending on 'how' state
  // RELATIVE_EXP (interval) or ABSOLUTE_EXP
  if (M_XTimeInt() > 0) {
    m_how = RELATIVE_EXP;
    m_numDays = M_XTimeInt();
    m_ReuseOnPswdChange = TRUE;
    CString cs_text;
    cs_text.Format(IDS_IN_N_DAYS, M_XTimeInt());
    GetDlgItem(IDC_XTIME_RECUR)->SetWindowText(cs_text);
  }

  GetDlgItem(IDC_EXPDAYS)->EnableWindow(m_how == RELATIVE_EXP ? TRUE : FALSE);
  GetDlgItem(IDC_REUSE_ON_CHANGE)->EnableWindow(m_how == RELATIVE_EXP ? TRUE : FALSE);
  GetDlgItem(IDC_EXPIRYDATE)->EnableWindow(m_how == RELATIVE_EXP ? FALSE : TRUE);
  GetDlgItem(IDC_EXPIRYTIME)->EnableWindow(m_how == RELATIVE_EXP ? FALSE : TRUE);

  // First get the time format picture.
  VERIFY(::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STIMEFORMAT, szBuf, 80));
  sTimeFormat = szBuf;

  // Next get the separator character.
  VERIFY(::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STIME, szBuf, 80));
  // Search for ":ss".
  sSearch = szBuf;
  sSearch += L"ss";
  nIndex = sTimeFormat.Find(sSearch);

  if (nIndex != -1) {
    // Found it!  Remove it from the format picture.
    sTimeFormat.Delete(nIndex, sSearch.GetLength());
  } else {
    // No ":ss", so try ":s".
    sSearch = szBuf;
    sSearch += L"s";
    nIndex = sTimeFormat.Find(sSearch);

    if (nIndex != -1) {
      // Found it!  Remove it from the format picture.
      sTimeFormat.Delete(nIndex, sSearch.GetLength());
    }
  }
  VERIFY(::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SSHORTDATE, szBuf, 80));
  sDateFormat = szBuf;

  CDateTimeCtrl *pTimeCtl = (CDateTimeCtrl*)GetDlgItem(IDC_EXPIRYTIME);
  CDateTimeCtrl *pDateCtl = (CDateTimeCtrl*)GetDlgItem(IDC_EXPIRYDATE);
  pTimeCtl->SetFormat(sTimeFormat);
  pDateCtl->SetFormat(sDateFormat);

  CTime ct, xt;
  CTime now(CTime::GetCurrentTime());
  ct = CTime(now.GetYear(), now.GetMonth(), now.GetDay(), 0, 0, 0, -1);

  const CTime sMinDate(ct);
  const CTime sMaxDate(CTime(2038, 1, 1, 0, 0, 0, -1));

  // Set approx. limit of 32-bit times!
  pDateCtl->SetRange(&sMinDate, &sMaxDate);

  pDateCtl->SetTime(&ct);
  pTimeCtl->SetTime(&ct);

  GetDlgItem(IDC_STATIC_CURRENT_XTIME)->SetWindowText(M_locXTime());

  if (M_uicaller() == IDS_VIEWENTRY) {
    // Disable Buttons
    GetDlgItem(IDC_XTIME_CLEAR)->EnableWindow(FALSE);
    GetDlgItem(IDC_XTIME_SET)->EnableWindow(FALSE);
    GetDlgItem(IDC_SELECTBYDATETIME)->EnableWindow(FALSE);
    GetDlgItem(IDC_SELECTBYDAYS)->EnableWindow(FALSE);
    GetDlgItem(IDC_REUSE_ON_CHANGE)->EnableWindow(FALSE);
  }

  if (M_uicaller() == IDS_ADDENTRY) {
    // Hide Date & Time statistics not yet set
    GetDlgItem(IDC_STATIC_DTSTATS)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_STATIC_CTIME)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_CTIME)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_STATIC_ATIME)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_ATIME)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_STATIC_PMTIME)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_PMTIME)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_STATIC_RMTIME)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_RMTIME)->ShowWindow(SW_HIDE);
  }

  UpdateData(FALSE);

  return TRUE;
}

BOOL CAddEdit_DateTimes::OnKillActive()
{
  CAddEdit_PropertyPage::OnKillActive();

  if (UpdateData(TRUE) == FALSE)
    return FALSE;

  return TRUE;
}

LRESULT CAddEdit_DateTimes::OnQuerySiblings(WPARAM wParam, LPARAM )
{
  UpdateData(TRUE);

  // Have any of my fields been changed?
  switch (wParam) {
    case PP_DATA_CHANGED:
      if (M_locXTime()     != M_oldlocXTime() ||
          M_XTimeInt()     != M_oldXTimeInt())
        return 1L;
      break;
    case PP_UPDATE_VARIABLES:
      // Since OnOK calls OnApply after we need to verify and/or
      // copy data into the entry - we do it ourselfs here first
      if (OnApply() == FALSE)
        return 1L;
  }
  return 0L;
}

BOOL CAddEdit_DateTimes::OnApply()
{
  if (UpdateData(TRUE) == FALSE) {
    if (m_bNumDaysFailed) {
      // Set to max.
      m_numDays = m_maxDays;
      UpdateData(FALSE);
    } else
      return FALSE;  // Something else - probably max. saved passwords
  }

  return CAddEdit_PropertyPage::OnApply();
}

void CAddEdit_DateTimes::OnHelp()
{
#if defined(POCKET_PC)
  CreateProcess(L"PegHelp.exe", L"pws_ce_help.html#adddata", NULL, NULL,
                FALSE, 0, NULL, NULL, NULL, NULL);
#else
  CString cs_HelpTopic;
  cs_HelpTopic = app.GetHelpFileName() + L"::/html/entering_pwd.html";
  HtmlHelp(DWORD_PTR((LPCWSTR)cs_HelpTopic), HH_DISPLAY_TOPIC);
#endif
}

void CAddEdit_DateTimes::OnClearXTime()
{
  M_locXTime().LoadString(IDS_NEVER);
  GetDlgItem(IDC_XTIME)->SetWindowText((CString)M_locXTime());
  GetDlgItem(IDC_XTIME_RECUR)->SetWindowText(L"");
  M_tttXTime() = (time_t)0;
  M_XTimeInt() = 0;
}

void CAddEdit_DateTimes::OnSetXTime()
{
  UpdateData(TRUE);
  CTime XTime, LDate, LDateTime;

  if (m_how == ABSOLUTE_EXP) {
    VERIFY(m_pTimeCtl.GetTime(XTime) == GDT_VALID);
    VERIFY(m_pDateCtl.GetTime(LDate) == GDT_VALID);

    LDateTime = CTime(LDate.GetYear(), LDate.GetMonth(), LDate.GetDay(),
                      XTime.GetHour(), XTime.GetMinute(), 0, -1);
    M_XTimeInt() = 0;
  } else { // m_how == RELATIVE_EXP
    if (m_ReuseOnPswdChange == FALSE) { // non-recurring
      LDateTime = CTime::GetCurrentTime() + CTimeSpan(m_numDays, 0, 0, 0);
      M_XTimeInt() = 0;
    } else { // recurring interval
      LDateTime = CTime(M_tttCPMTime()) + CTimeSpan(m_numDays, 0, 0, 0);
      M_XTimeInt() = m_numDays;
    }
  }

  // m_XTimeInt is non-zero iff user specified a relative & recurring exp. date
  M_tttXTime() = (time_t)LDateTime.GetTime();
  M_locXTime() = PWSUtil::ConvertToDateTimeString(M_tttXTime(), TMC_LOCALE);

  CString cs_text(L"");
  if (M_XTimeInt() != 0) // recurring expiration
    cs_text.Format(IDS_IN_N_DAYS, M_XTimeInt());

  GetDlgItem(IDC_XTIME)->SetWindowText(M_locXTime());
  GetDlgItem(IDC_XTIME_RECUR)->SetWindowText(cs_text);
}

void CAddEdit_DateTimes::OnDays()
{
  GetDlgItem(IDC_EXPDAYS)->EnableWindow(TRUE);
  GetDlgItem(IDC_REUSE_ON_CHANGE)->EnableWindow(TRUE);
  GetDlgItem(IDC_EXPIRYDATE)->EnableWindow(FALSE);
  GetDlgItem(IDC_EXPIRYTIME)->EnableWindow(FALSE);
  m_how = RELATIVE_EXP;
}

void CAddEdit_DateTimes::OnDateTime()
{
  GetDlgItem(IDC_EXPDAYS)->EnableWindow(FALSE);
  GetDlgItem(IDC_REUSE_ON_CHANGE)->EnableWindow(FALSE);
  GetDlgItem(IDC_EXPIRYDATE)->EnableWindow(TRUE);
  GetDlgItem(IDC_EXPIRYTIME)->EnableWindow(TRUE);
  m_how = ABSOLUTE_EXP;
}

void CAddEdit_DateTimes::OnReuseOnPswdChange()
{
  ASSERT(m_how == RELATIVE_EXP); // meaningless when absolute date given
  UpdateData(TRUE);

  // If user chose "recurring", then set the max interval to ~10 years
  // (should suffice for most purposes). For non-recurring, limit is
  // the max that won't overflow time_t
  const int new_max = (m_ReuseOnPswdChange == TRUE) ? 3650 : m_maxDays;
  CSpinButtonCtrl* pspin = (CSpinButtonCtrl *)GetDlgItem(IDC_EXPDAYSSPIN);
  pspin->SetRange32(1, new_max);
  if (m_numDays > new_max)
    m_numDays = 1;

  UpdateData(FALSE);
}
<commit_msg>Redundant redundancy removal (removed a dup DDX_Text call).<commit_after>/*
* Copyright (c) 2003-2009 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/
// AddEdit_DateTimes.cpp : implementation file
//

#include "stdafx.h"
#include "PasswordSafe.h"
#include "ThisMfcApp.h"    // For Help
#include "DboxMain.h"
#include "AddEdit_DateTimes.h"
#include "AddEdit_PropertySheet.h"

#include "corelib/PWSprefs.h"
#include "corelib/PWSAuxParse.h"

#include "resource3.h"

bool CAddEdit_DateTimes::m_bNumDaysFailed = false;

static void AFXAPI DDV_CheckMaxDays(CDataExchange* pDX, const int &how,
                                    int &numDays, const int &maxDays);

/////////////////////////////////////////////////////////////////////////////
// CAddEdit_DateTimes property page

IMPLEMENT_DYNAMIC(CAddEdit_DateTimes, CAddEdit_PropertyPage)

CAddEdit_DateTimes::CAddEdit_DateTimes(CWnd *pParent, st_AE_master_data *pAEMD)
  : CAddEdit_PropertyPage(pParent, CAddEdit_DateTimes::IDD, pAEMD),
  m_how(ABSOLUTE_EXP), m_numDays(1), m_ReuseOnPswdChange(FALSE)
{
}

CAddEdit_DateTimes::~CAddEdit_DateTimes()
{
}

void CAddEdit_DateTimes::DoDataExchange(CDataExchange* pDX)
{
  CAddEdit_PropertyPage::DoDataExchange(pDX);

  //{{AFX_DATA_MAP(CAddEdit_DateTimes)
  DDX_Text(pDX, IDC_XTIME, (CString&)M_locXTime());
  DDX_Text(pDX, IDC_CTIME, (CString&)M_locCTime());
  DDX_Text(pDX, IDC_PMTIME, (CString&)M_locPMTime());
  DDX_Text(pDX, IDC_ATIME, (CString&)M_locATime());
  DDX_Text(pDX, IDC_RMTIME, (CString&)M_locRMTime());

  DDX_Text(pDX, IDC_EXPDAYS, m_numDays);
  DDX_Radio(pDX, IDC_SELECTBYDATETIME, m_how);
  DDX_Check(pDX, IDC_REUSE_ON_CHANGE, m_ReuseOnPswdChange);

  DDX_Control(pDX, IDC_EXPIRYDATE, m_pDateCtl);
  DDX_Control(pDX, IDC_EXPIRYTIME, m_pTimeCtl);

  // Validation
  DDV_CheckMaxDays(pDX, m_how, m_numDays, m_maxDays);
  //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAddEdit_DateTimes, CAddEdit_PropertyPage)
  //{{AFX_MSG_MAP(CAddEdit_DateTimes)
  ON_BN_CLICKED(ID_HELP, OnHelp)
  ON_BN_CLICKED(IDC_XTIME_CLEAR, OnClearXTime)
  ON_BN_CLICKED(IDC_XTIME_SET, OnSetXTime)
  ON_BN_CLICKED(IDC_SELECTBYDATETIME, OnDateTime)
  ON_BN_CLICKED(IDC_SELECTBYDAYS, OnDays)
  ON_BN_CLICKED(IDC_REUSE_ON_CHANGE, OnReuseOnPswdChange)
  // Common
  ON_MESSAGE(PSM_QUERYSIBLINGS, OnQuerySiblings)
  //}}AFX_MSG_MAP
END_MESSAGE_MAP()

static void AFXAPI DDV_CheckMaxDays(CDataExchange* pDX, const int &how,
                                    int &numDays, const int &maxDays)
{
  if (pDX->m_bSaveAndValidate) {
    CAddEdit_DateTimes::m_bNumDaysFailed = false;
    if (how == CAddEdit_DateTimes::RELATIVE_EXP && numDays > maxDays) {
      CString csError;
      csError.Format(IDS_MAXNUMDAYSEXCEEDED, maxDays);
      AfxMessageBox(csError);
      CAddEdit_DateTimes::m_bNumDaysFailed = true;
      pDX->Fail();
      return;
    }
  }
}

BOOL CAddEdit_DateTimes::OnInitDialog()
{
  CAddEdit_PropertyPage::OnInitDialog();

  ModifyStyleEx (0, WS_EX_CONTROLPARENT);

  // Time fields
  time(&M_tttCPMTime());

  wchar_t szBuf[81];     // workspace
  CString sTimeFormat;   // the time format being worked on
  CString sDateFormat;
  CString sSearch;       // the string to search for
  int nIndex;            // index of the string, if found

  GetDlgItem(IDC_EXPDAYS)->EnableWindow(FALSE);

  // Last 32-bit date is 03:14:07 UTC on Tuesday, January 19, 2038
  // Find number of days from now to 2038/01/18 = max value here
  const CTime ct_Latest(2038, 1, 18, 0, 0, 0);
  const CTime ct_Now(CTime::GetCurrentTime());

  CTimeSpan elapsedTime = ct_Latest - ct_Now;
  m_maxDays = (int)elapsedTime.GetDays();

  CSpinButtonCtrl * pspin = (CSpinButtonCtrl *)GetDlgItem(IDC_EXPDAYSSPIN);

  pspin->SetBuddy(GetDlgItem(IDC_EXPDAYS));
  pspin->SetBase(10);
  pspin->SetRange32(1, m_maxDays);
  pspin->SetPos(1);

  // enable/disable relevant controls, depending on 'how' state
  // RELATIVE_EXP (interval) or ABSOLUTE_EXP
  if (M_XTimeInt() > 0) {
    m_how = RELATIVE_EXP;
    m_numDays = M_XTimeInt();
    m_ReuseOnPswdChange = TRUE;
    CString cs_text;
    cs_text.Format(IDS_IN_N_DAYS, M_XTimeInt());
    GetDlgItem(IDC_XTIME_RECUR)->SetWindowText(cs_text);
  }

  GetDlgItem(IDC_EXPDAYS)->EnableWindow(m_how == RELATIVE_EXP ? TRUE : FALSE);
  GetDlgItem(IDC_REUSE_ON_CHANGE)->EnableWindow(m_how == RELATIVE_EXP ? TRUE : FALSE);
  GetDlgItem(IDC_EXPIRYDATE)->EnableWindow(m_how == RELATIVE_EXP ? FALSE : TRUE);
  GetDlgItem(IDC_EXPIRYTIME)->EnableWindow(m_how == RELATIVE_EXP ? FALSE : TRUE);

  // First get the time format picture.
  VERIFY(::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STIMEFORMAT, szBuf, 80));
  sTimeFormat = szBuf;

  // Next get the separator character.
  VERIFY(::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STIME, szBuf, 80));
  // Search for ":ss".
  sSearch = szBuf;
  sSearch += L"ss";
  nIndex = sTimeFormat.Find(sSearch);

  if (nIndex != -1) {
    // Found it!  Remove it from the format picture.
    sTimeFormat.Delete(nIndex, sSearch.GetLength());
  } else {
    // No ":ss", so try ":s".
    sSearch = szBuf;
    sSearch += L"s";
    nIndex = sTimeFormat.Find(sSearch);

    if (nIndex != -1) {
      // Found it!  Remove it from the format picture.
      sTimeFormat.Delete(nIndex, sSearch.GetLength());
    }
  }
  VERIFY(::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SSHORTDATE, szBuf, 80));
  sDateFormat = szBuf;

  CDateTimeCtrl *pTimeCtl = (CDateTimeCtrl*)GetDlgItem(IDC_EXPIRYTIME);
  CDateTimeCtrl *pDateCtl = (CDateTimeCtrl*)GetDlgItem(IDC_EXPIRYDATE);
  pTimeCtl->SetFormat(sTimeFormat);
  pDateCtl->SetFormat(sDateFormat);

  CTime ct, xt;
  CTime now(CTime::GetCurrentTime());
  ct = CTime(now.GetYear(), now.GetMonth(), now.GetDay(), 0, 0, 0, -1);

  const CTime sMinDate(ct);
  const CTime sMaxDate(CTime(2038, 1, 1, 0, 0, 0, -1));

  // Set approx. limit of 32-bit times!
  pDateCtl->SetRange(&sMinDate, &sMaxDate);

  pDateCtl->SetTime(&ct);
  pTimeCtl->SetTime(&ct);

  GetDlgItem(IDC_STATIC_CURRENT_XTIME)->SetWindowText(M_locXTime());

  if (M_uicaller() == IDS_VIEWENTRY) {
    // Disable Buttons
    GetDlgItem(IDC_XTIME_CLEAR)->EnableWindow(FALSE);
    GetDlgItem(IDC_XTIME_SET)->EnableWindow(FALSE);
    GetDlgItem(IDC_SELECTBYDATETIME)->EnableWindow(FALSE);
    GetDlgItem(IDC_SELECTBYDAYS)->EnableWindow(FALSE);
    GetDlgItem(IDC_REUSE_ON_CHANGE)->EnableWindow(FALSE);
  }

  if (M_uicaller() == IDS_ADDENTRY) {
    // Hide Date & Time statistics not yet set
    GetDlgItem(IDC_STATIC_DTSTATS)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_STATIC_CTIME)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_CTIME)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_STATIC_ATIME)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_ATIME)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_STATIC_PMTIME)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_PMTIME)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_STATIC_RMTIME)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_RMTIME)->ShowWindow(SW_HIDE);
  }

  UpdateData(FALSE);

  return TRUE;
}

BOOL CAddEdit_DateTimes::OnKillActive()
{
  CAddEdit_PropertyPage::OnKillActive();

  if (UpdateData(TRUE) == FALSE)
    return FALSE;

  return TRUE;
}

LRESULT CAddEdit_DateTimes::OnQuerySiblings(WPARAM wParam, LPARAM )
{
  UpdateData(TRUE);

  // Have any of my fields been changed?
  switch (wParam) {
    case PP_DATA_CHANGED:
      if (M_locXTime()     != M_oldlocXTime() ||
          M_XTimeInt()     != M_oldXTimeInt())
        return 1L;
      break;
    case PP_UPDATE_VARIABLES:
      // Since OnOK calls OnApply after we need to verify and/or
      // copy data into the entry - we do it ourselfs here first
      if (OnApply() == FALSE)
        return 1L;
  }
  return 0L;
}

BOOL CAddEdit_DateTimes::OnApply()
{
  if (UpdateData(TRUE) == FALSE) {
    if (m_bNumDaysFailed) {
      // Set to max.
      m_numDays = m_maxDays;
      UpdateData(FALSE);
    } else
      return FALSE;  // Something else - probably max. saved passwords
  }

  return CAddEdit_PropertyPage::OnApply();
}

void CAddEdit_DateTimes::OnHelp()
{
#if defined(POCKET_PC)
  CreateProcess(L"PegHelp.exe", L"pws_ce_help.html#adddata", NULL, NULL,
                FALSE, 0, NULL, NULL, NULL, NULL);
#else
  CString cs_HelpTopic;
  cs_HelpTopic = app.GetHelpFileName() + L"::/html/entering_pwd.html";
  HtmlHelp(DWORD_PTR((LPCWSTR)cs_HelpTopic), HH_DISPLAY_TOPIC);
#endif
}

void CAddEdit_DateTimes::OnClearXTime()
{
  M_locXTime().LoadString(IDS_NEVER);
  GetDlgItem(IDC_XTIME)->SetWindowText((CString)M_locXTime());
  GetDlgItem(IDC_XTIME_RECUR)->SetWindowText(L"");
  M_tttXTime() = (time_t)0;
  M_XTimeInt() = 0;
}

void CAddEdit_DateTimes::OnSetXTime()
{
  UpdateData(TRUE);
  CTime XTime, LDate, LDateTime;

  if (m_how == ABSOLUTE_EXP) {
    VERIFY(m_pTimeCtl.GetTime(XTime) == GDT_VALID);
    VERIFY(m_pDateCtl.GetTime(LDate) == GDT_VALID);

    LDateTime = CTime(LDate.GetYear(), LDate.GetMonth(), LDate.GetDay(),
                      XTime.GetHour(), XTime.GetMinute(), 0, -1);
    M_XTimeInt() = 0;
  } else { // m_how == RELATIVE_EXP
    if (m_ReuseOnPswdChange == FALSE) { // non-recurring
      LDateTime = CTime::GetCurrentTime() + CTimeSpan(m_numDays, 0, 0, 0);
      M_XTimeInt() = 0;
    } else { // recurring interval
      LDateTime = CTime(M_tttCPMTime()) + CTimeSpan(m_numDays, 0, 0, 0);
      M_XTimeInt() = m_numDays;
    }
  }

  // m_XTimeInt is non-zero iff user specified a relative & recurring exp. date
  M_tttXTime() = (time_t)LDateTime.GetTime();
  M_locXTime() = PWSUtil::ConvertToDateTimeString(M_tttXTime(), TMC_LOCALE);

  CString cs_text(L"");
  if (M_XTimeInt() != 0) // recurring expiration
    cs_text.Format(IDS_IN_N_DAYS, M_XTimeInt());

  GetDlgItem(IDC_XTIME)->SetWindowText(M_locXTime());
  GetDlgItem(IDC_XTIME_RECUR)->SetWindowText(cs_text);
}

void CAddEdit_DateTimes::OnDays()
{
  GetDlgItem(IDC_EXPDAYS)->EnableWindow(TRUE);
  GetDlgItem(IDC_REUSE_ON_CHANGE)->EnableWindow(TRUE);
  GetDlgItem(IDC_EXPIRYDATE)->EnableWindow(FALSE);
  GetDlgItem(IDC_EXPIRYTIME)->EnableWindow(FALSE);
  m_how = RELATIVE_EXP;
}

void CAddEdit_DateTimes::OnDateTime()
{
  GetDlgItem(IDC_EXPDAYS)->EnableWindow(FALSE);
  GetDlgItem(IDC_REUSE_ON_CHANGE)->EnableWindow(FALSE);
  GetDlgItem(IDC_EXPIRYDATE)->EnableWindow(TRUE);
  GetDlgItem(IDC_EXPIRYTIME)->EnableWindow(TRUE);
  m_how = ABSOLUTE_EXP;
}

void CAddEdit_DateTimes::OnReuseOnPswdChange()
{
  ASSERT(m_how == RELATIVE_EXP); // meaningless when absolute date given
  UpdateData(TRUE);

  // If user chose "recurring", then set the max interval to ~10 years
  // (should suffice for most purposes). For non-recurring, limit is
  // the max that won't overflow time_t
  const int new_max = (m_ReuseOnPswdChange == TRUE) ? 3650 : m_maxDays;
  CSpinButtonCtrl* pspin = (CSpinButtonCtrl *)GetDlgItem(IDC_EXPDAYSSPIN);
  pspin->SetRange32(1, new_max);
  if (m_numDays > new_max)
    m_numDays = 1;

  UpdateData(FALSE);
}
<|endoftext|>


<commit_before>//===--- Enum.cpp - Runtime declarations for enums -----------*- C++ -*--===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Swift runtime functions in support of enums.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "swift/Basic/Fallthrough.h"
#include "swift/Runtime/Metadata.h"
#include "swift/Runtime/Enum.h"
#include "Debug.h"
#include "Private.h"
#include <cstring>
#include <algorithm>

using namespace swift;

// FIXME: We should cache this in the enum's metadata.
static unsigned getNumTagBytes(size_t size, unsigned cases) {
  // We can use the payload area with a tag bit set somewhere outside of the
  // payload area to represent cases. See how many bytes we need to cover
  // all the empty cases.

  if (size >= 4)
    // Assume that one tag bit is enough if the precise calculation overflows
    // an int32.
    return 1;
  else {
    unsigned bits = size * 8U;
    unsigned casesPerTagBitValue = 1U << bits;
    unsigned numTagBitValues
      = 1 + ((cases + (casesPerTagBitValue-1U)) >> bits);
    return (numTagBitValues < 256 ? 1 :
            numTagBitValues < 65536 ? 2 : 4);
  }
}

void
swift::swift_initEnumValueWitnessTableSinglePayload(ValueWitnessTable *vwtable,
                                                     const Metadata *payload,
                                                     unsigned emptyCases) {
  auto *payloadWitnesses = payload->getValueWitnesses();
  size_t payloadSize = payloadWitnesses->getSize();
  unsigned payloadNumExtraInhabitants
    = payloadWitnesses->getNumExtraInhabitants();

  unsigned unusedExtraInhabitants = 0;

  // If there are enough extra inhabitants for all of the cases, then the size
  // of the enum is the same as its payload.
  size_t size;
  if (payloadNumExtraInhabitants >= emptyCases) {
    size = payloadSize;
    unusedExtraInhabitants = payloadNumExtraInhabitants - emptyCases;
  } else {
    size = payloadSize + getNumTagBytes(payloadSize,
                                      emptyCases - payloadNumExtraInhabitants);
  }

  size_t align = payloadWitnesses->getAlignment();
  vwtable->size = size;
  vwtable->flags = payloadWitnesses->flags
    .withExtraInhabitants(unusedExtraInhabitants > 0)
    .withInlineStorage(ValueWitnessTable::isValueInline(size, align));
  vwtable->stride = llvm::RoundUpToAlignment(size, align);

  // Substitute in better common value witnesses if we have them.
  // If the payload type is a single-refcounted pointer, and the enum has
  // a single empty case, then we can borrow the witnesses of the single
  // refcounted pointer type, since swift_retain and objc_retain are both
  // nil-aware. Most single-refcounted types will use the standard
  // value witness tables for NativeObject or UnknownObject. This isn't
  // foolproof but should catch the common case of optional class types.
  auto payloadVWT = payload->getValueWitnesses();
  if (emptyCases == 1
      && (payloadVWT == &_TWVBo
#if SWIFT_OBJC_INTEROP
          || payloadVWT == &_TWVBO
#endif
          )) {
#define COPY_PAYLOAD_WITNESS(NAME) vwtable->NAME = payloadVWT->NAME;
    FOR_ALL_FUNCTION_VALUE_WITNESSES(COPY_PAYLOAD_WITNESS)
#undef COPY_PAYLOAD_WITNESS
  } else {
    installCommonValueWitnesses(vwtable);
  }

  // If the payload has extra inhabitants left over after the ones we used,
  // forward them as our own.
  if (unusedExtraInhabitants > 0) {
    auto xiVWTable = static_cast<ExtraInhabitantsValueWitnessTable*>(vwtable);
    xiVWTable->extraInhabitantFlags = ExtraInhabitantFlags()
      .withNumExtraInhabitants(unusedExtraInhabitants);
  }
}

/// This is a small and fast implementation of memcpy with a constant count. It
/// should be a performance win for small constant values where the function
/// can be inlined, the loop unrolled and the memory accesses merged.
template <unsigned count> static void small_memcpy(void *dest, const void *src) {
  uint8_t *d8 = (uint8_t*)dest, *s8 = (uint8_t*)src;
  for (unsigned int i = 0; i < count; i++) {
    *d8++ = *s8++;
  }
}

int
swift::swift_getEnumCaseSinglePayload(const OpaqueValue *value,
                                      const Metadata *payload,
                                      unsigned emptyCases) {
  auto *payloadWitnesses = payload->getValueWitnesses();
  auto payloadSize = payloadWitnesses->getSize();
  auto payloadNumExtraInhabitants = payloadWitnesses->getNumExtraInhabitants();

  // If there are extra tag bits, check them.
  if (emptyCases > payloadNumExtraInhabitants) {
    auto *valueAddr = reinterpret_cast<const uint8_t*>(value);
    auto *extraTagBitAddr = valueAddr + payloadSize;
    unsigned extraTagBits = 0;
    // FIXME: endianness
    unsigned numBytes = getNumTagBytes(payloadSize,
                                       emptyCases-payloadNumExtraInhabitants);

    // This is specialization of the memcpy line below with
    // specialization for values of 1, 2 and 4.
    // memcpy(&extraTagBits, extraTagBitAddr, numBytes);
    if (numBytes == 1) {
      small_memcpy<1>(&extraTagBits, extraTagBitAddr);
    } else if (numBytes == 2) {
      small_memcpy<2>(&extraTagBits, extraTagBitAddr);
    } else if (numBytes == 4) {
      small_memcpy<4>(&extraTagBits, extraTagBitAddr);
    } else {
      crash("Tagbyte values should be 1, 2 or 4.");
    }

    // If the extra tag bits are zero, we have a valid payload or
    // extra inhabitant (checked below). If nonzero, form the case index from
    // the extra tag value and the value stored in the payload.
    if (extraTagBits > 0) {
      unsigned caseIndexFromExtraTagBits = payloadSize >= 4
        ? 0 : (extraTagBits - 1U) << (payloadSize*8U);

      // In practice we should need no more than four bytes from the payload
      // area.
      // FIXME: endianness.
      unsigned caseIndexFromValue = 0;
      memcpy(&caseIndexFromValue, valueAddr,
             std::min(size_t(4), payloadSize));
      return (caseIndexFromExtraTagBits | caseIndexFromValue)
        + payloadNumExtraInhabitants;
    }
  }

  // If there are extra inhabitants, see whether the payload is valid.
  if (payloadNumExtraInhabitants > 0) {
    return
      static_cast<const ExtraInhabitantsValueWitnessTable*>(payloadWitnesses)
      ->getExtraInhabitantIndex(value, payload);
  }

  // Otherwise, we have always have a valid payload.
  return -1;
}

void
swift::swift_storeEnumTagSinglePayload(OpaqueValue *value,
                                        const Metadata *payload,
                                        int whichCase, unsigned emptyCases) {
  auto *payloadWitnesses = payload->getValueWitnesses();
  auto payloadSize = payloadWitnesses->getSize();
  unsigned payloadNumExtraInhabitants
    = payloadWitnesses->getNumExtraInhabitants();

  auto *valueAddr = reinterpret_cast<uint8_t*>(value);
  auto *extraTagBitAddr = valueAddr + payloadSize;
  unsigned numExtraTagBytes = emptyCases > payloadNumExtraInhabitants
    ? getNumTagBytes(payloadSize, emptyCases - payloadNumExtraInhabitants)
    : 0;

  // For payload or extra inhabitant cases, zero-initialize the extra tag bits,
  // if any.
  if (whichCase < (int)payloadNumExtraInhabitants) {
    memset(extraTagBitAddr, 0, numExtraTagBytes);

    // If this is the payload case, we're done.
    if (whichCase == -1)
      return;

    // Store the extra inhabitant.
    static_cast<const ExtraInhabitantsValueWitnessTable*>(payloadWitnesses)
      ->storeExtraInhabitant(value, whichCase, payload);
    return;
  }

  // Factor the case index into payload and extra tag parts.
  unsigned caseIndex = whichCase - payloadNumExtraInhabitants;
  unsigned payloadIndex, extraTagIndex;
  if (payloadSize >= 4) {
    extraTagIndex = 1;
    payloadIndex = caseIndex;
  } else {
    unsigned payloadBits = payloadSize * 8U;
    extraTagIndex = 1U + (caseIndex >> payloadBits);
    payloadIndex = caseIndex & ((1U << payloadBits) - 1U);
  }

  // Store into the value.
  // FIXME: endianness.
  memcpy(valueAddr, &payloadIndex, std::min(size_t(4), payloadSize));
  if (payloadSize > 4)
    memset(valueAddr + 4, 0, payloadSize - 4);
  memcpy(extraTagBitAddr, &extraTagIndex, numExtraTagBytes);
}
<commit_msg>Avoid calling bzero in Optional.init() by specializing the common tagbyte sizes.<commit_after>//===--- Enum.cpp - Runtime declarations for enums -----------*- C++ -*--===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Swift runtime functions in support of enums.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "swift/Basic/Fallthrough.h"
#include "swift/Runtime/Metadata.h"
#include "swift/Runtime/Enum.h"
#include "Debug.h"
#include "Private.h"
#include <cstring>
#include <algorithm>

using namespace swift;

// FIXME: We should cache this in the enum's metadata.
static unsigned getNumTagBytes(size_t size, unsigned cases) {
  // We can use the payload area with a tag bit set somewhere outside of the
  // payload area to represent cases. See how many bytes we need to cover
  // all the empty cases.

  if (size >= 4)
    // Assume that one tag bit is enough if the precise calculation overflows
    // an int32.
    return 1;
  else {
    unsigned bits = size * 8U;
    unsigned casesPerTagBitValue = 1U << bits;
    unsigned numTagBitValues
      = 1 + ((cases + (casesPerTagBitValue-1U)) >> bits);
    return (numTagBitValues < 256 ? 1 :
            numTagBitValues < 65536 ? 2 : 4);
  }
}

void
swift::swift_initEnumValueWitnessTableSinglePayload(ValueWitnessTable *vwtable,
                                                     const Metadata *payload,
                                                     unsigned emptyCases) {
  auto *payloadWitnesses = payload->getValueWitnesses();
  size_t payloadSize = payloadWitnesses->getSize();
  unsigned payloadNumExtraInhabitants
    = payloadWitnesses->getNumExtraInhabitants();

  unsigned unusedExtraInhabitants = 0;

  // If there are enough extra inhabitants for all of the cases, then the size
  // of the enum is the same as its payload.
  size_t size;
  if (payloadNumExtraInhabitants >= emptyCases) {
    size = payloadSize;
    unusedExtraInhabitants = payloadNumExtraInhabitants - emptyCases;
  } else {
    size = payloadSize + getNumTagBytes(payloadSize,
                                      emptyCases - payloadNumExtraInhabitants);
  }

  size_t align = payloadWitnesses->getAlignment();
  vwtable->size = size;
  vwtable->flags = payloadWitnesses->flags
    .withExtraInhabitants(unusedExtraInhabitants > 0)
    .withInlineStorage(ValueWitnessTable::isValueInline(size, align));
  vwtable->stride = llvm::RoundUpToAlignment(size, align);

  // Substitute in better common value witnesses if we have them.
  // If the payload type is a single-refcounted pointer, and the enum has
  // a single empty case, then we can borrow the witnesses of the single
  // refcounted pointer type, since swift_retain and objc_retain are both
  // nil-aware. Most single-refcounted types will use the standard
  // value witness tables for NativeObject or UnknownObject. This isn't
  // foolproof but should catch the common case of optional class types.
  auto payloadVWT = payload->getValueWitnesses();
  if (emptyCases == 1
      && (payloadVWT == &_TWVBo
#if SWIFT_OBJC_INTEROP
          || payloadVWT == &_TWVBO
#endif
          )) {
#define COPY_PAYLOAD_WITNESS(NAME) vwtable->NAME = payloadVWT->NAME;
    FOR_ALL_FUNCTION_VALUE_WITNESSES(COPY_PAYLOAD_WITNESS)
#undef COPY_PAYLOAD_WITNESS
  } else {
    installCommonValueWitnesses(vwtable);
  }

  // If the payload has extra inhabitants left over after the ones we used,
  // forward them as our own.
  if (unusedExtraInhabitants > 0) {
    auto xiVWTable = static_cast<ExtraInhabitantsValueWitnessTable*>(vwtable);
    xiVWTable->extraInhabitantFlags = ExtraInhabitantFlags()
      .withNumExtraInhabitants(unusedExtraInhabitants);
  }
}

/// This is a small and fast implementation of memcpy with a constant count. It
/// should be a performance win for small constant values where the function
/// can be inlined, the loop unrolled and the memory accesses merged.
template <unsigned count> static void small_memcpy(void *dest, const void *src) {
  uint8_t *d8 = (uint8_t*)dest, *s8 = (uint8_t*)src;
  for (unsigned int i = 0; i < count; i++) {
    *d8++ = *s8++;
  }
}

int
swift::swift_getEnumCaseSinglePayload(const OpaqueValue *value,
                                      const Metadata *payload,
                                      unsigned emptyCases) {
  auto *payloadWitnesses = payload->getValueWitnesses();
  auto payloadSize = payloadWitnesses->getSize();
  auto payloadNumExtraInhabitants = payloadWitnesses->getNumExtraInhabitants();

  // If there are extra tag bits, check them.
  if (emptyCases > payloadNumExtraInhabitants) {
    auto *valueAddr = reinterpret_cast<const uint8_t*>(value);
    auto *extraTagBitAddr = valueAddr + payloadSize;
    unsigned extraTagBits = 0;
    // FIXME: endianness
    unsigned numBytes = getNumTagBytes(payloadSize,
                                       emptyCases-payloadNumExtraInhabitants);

    // This is specialization of the memcpy line below with
    // specialization for values of 1, 2 and 4.
    // memcpy(&extraTagBits, extraTagBitAddr, numBytes);
    if (numBytes == 1) {
      small_memcpy<1>(&extraTagBits, extraTagBitAddr);
    } else if (numBytes == 2) {
      small_memcpy<2>(&extraTagBits, extraTagBitAddr);
    } else if (numBytes == 4) {
      small_memcpy<4>(&extraTagBits, extraTagBitAddr);
    } else {
      crash("Tagbyte values should be 1, 2 or 4.");
    }

    // If the extra tag bits are zero, we have a valid payload or
    // extra inhabitant (checked below). If nonzero, form the case index from
    // the extra tag value and the value stored in the payload.
    if (extraTagBits > 0) {
      unsigned caseIndexFromExtraTagBits = payloadSize >= 4
        ? 0 : (extraTagBits - 1U) << (payloadSize*8U);

      // In practice we should need no more than four bytes from the payload
      // area.
      // FIXME: endianness.
      unsigned caseIndexFromValue = 0;
      memcpy(&caseIndexFromValue, valueAddr,
             std::min(size_t(4), payloadSize));
      return (caseIndexFromExtraTagBits | caseIndexFromValue)
        + payloadNumExtraInhabitants;
    }
  }

  // If there are extra inhabitants, see whether the payload is valid.
  if (payloadNumExtraInhabitants > 0) {
    return
      static_cast<const ExtraInhabitantsValueWitnessTable*>(payloadWitnesses)
      ->getExtraInhabitantIndex(value, payload);
  }

  // Otherwise, we have always have a valid payload.
  return -1;
}

void
swift::swift_storeEnumTagSinglePayload(OpaqueValue *value,
                                        const Metadata *payload,
                                        int whichCase, unsigned emptyCases) {
  auto *payloadWitnesses = payload->getValueWitnesses();
  auto payloadSize = payloadWitnesses->getSize();
  unsigned payloadNumExtraInhabitants
    = payloadWitnesses->getNumExtraInhabitants();

  auto *valueAddr = reinterpret_cast<uint8_t*>(value);
  auto *extraTagBitAddr = valueAddr + payloadSize;
  unsigned numExtraTagBytes = emptyCases > payloadNumExtraInhabitants
    ? getNumTagBytes(payloadSize, emptyCases - payloadNumExtraInhabitants)
    : 0;

  // For payload or extra inhabitant cases, zero-initialize the extra tag bits,
  // if any.
  if (whichCase < (int)payloadNumExtraInhabitants) {
    // The two most common values for numExtraTagBytes are zero and one.
    // Try to avoid calling bzero by specializing for these values.
    if (numExtraTagBytes != 0) {
      if (numExtraTagBytes == 1) {
        // Zero a single byte.
        *((char*)(extraTagBitAddr)) = 0;
      } else {
        // Zero the buffer.
        memset(extraTagBitAddr, 0, numExtraTagBytes);
      }
    }

    // If this is the payload case, we're done.
    if (whichCase == -1)
      return;

    // Store the extra inhabitant.
    static_cast<const ExtraInhabitantsValueWitnessTable*>(payloadWitnesses)
      ->storeExtraInhabitant(value, whichCase, payload);
    return;
  }

  // Factor the case index into payload and extra tag parts.
  unsigned caseIndex = whichCase - payloadNumExtraInhabitants;
  unsigned payloadIndex, extraTagIndex;
  if (payloadSize >= 4) {
    extraTagIndex = 1;
    payloadIndex = caseIndex;
  } else {
    unsigned payloadBits = payloadSize * 8U;
    extraTagIndex = 1U + (caseIndex >> payloadBits);
    payloadIndex = caseIndex & ((1U << payloadBits) - 1U);
  }

  // Store into the value.
  // FIXME: endianness.
  memcpy(valueAddr, &payloadIndex, std::min(size_t(4), payloadSize));
  if (payloadSize > 4)
    memset(valueAddr + 4, 0, payloadSize - 4);
  memcpy(extraTagBitAddr, &extraTagIndex, numExtraTagBytes);
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with
** the Software or, alternatively, in accordance with the terms
** contained in a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "compasssym.h"

/**
 * set the id of the accelerometer sensor
 */
char const * const CCompassSym::id("sym.compass");

/**
 * Factory function, this is used to create the compass object
 * @return CCompassSym if successful, leaves on failure
 */
CCompassSym* CCompassSym::NewL(QSensor *sensor)
    {
    CCompassSym* self = new (ELeave) CCompassSym(sensor);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop();
    return self;
    }

/**
 * Destructor
 * Closes the backend resources
 */
CCompassSym::~CCompassSym()
    {
    delete iMagnetometer;
    Close();
    }

/**
 * Default constructor
 */
CCompassSym::CCompassSym(QSensor *sensor):CSensorBackendSym(sensor)
    {
    setReading<QCompassReading>(&iReading);
    iBackendData.iSensorType = KSensrvChannelTypeIdMagneticNorthData;
    }

/**
 * start() overrides CSensorBackendSym::start()
 * This is to allow starting magnetometer before stopping the compass
 */
void CCompassSym::start()
    {
    // start the magnetometer
    iMagnetometer->start();
    // start the compass backend
    CSensorBackendSym::start();
    }

/**
 * stop() overrides CSensorBackendSym::stop()
 * This is to allow stopping magnetometer before stopping the compass
 */
void CCompassSym::stop()
    {
    // stop the magnetometer
    iMagnetometer->stop();
    // start the compass backend
    CSensorBackendSym::stop();
    }

/*
 * DataReceived is used to retrieve the sensor reading from sensor server
 * It is implemented here to handle compass sensor specific
 * reading data and provides conversion and utility code
 */
void CCompassSym::DataReceived(CSensrvChannel &aChannel, TInt aCount, TInt /*aDataLost*/)
    {
    ProcessData(aChannel, aCount, iData);
    }

void CCompassSym::ProcessReading()
    {
    // Get a lock on the reading data
    iBackendData.iReadingLock.Wait();
    iReading.setAzimuth(iData.iAngleFromMagneticNorth);
    // Retrieve and set the calibration level
    iReading.setCalibrationLevel(iMagnetometer->GetCalibrationLevel());
    // Set the timestamp
    iReading.setTimestamp(iData.iTimeStamp.Int64());
    // Release the lock
    iBackendData.iReadingLock.Signal();
    // Notify that a reading is available
    newReadingAvailable();
    }

/**
 * Second phase constructor
 * Initialize the backend resources
 */
void CCompassSym::ConstructL()
    {
    // Initialize the backend
    InitializeL();
    // Create magnetometer, this is required as in sensor server,
    // calibration data is available only for magnetometer
    iMagnetometer = CMagnetometerSensorSym::NewL(NULL);
    // Listen only for property change on magnetometer as we are
    // interested only in calibration property
    iMagnetometer->SetListening(EFalse, ETrue);
    }

<commit_msg>Fix the compass crash (for real)<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with
** the Software or, alternatively, in accordance with the terms
** contained in a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "compasssym.h"

/**
 * set the id of the accelerometer sensor
 */
char const * const CCompassSym::id("sym.compass");

/**
 * Factory function, this is used to create the compass object
 * @return CCompassSym if successful, leaves on failure
 */
CCompassSym* CCompassSym::NewL(QSensor *sensor)
    {
    CCompassSym* self = new (ELeave) CCompassSym(sensor);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop();
    return self;
    }

/**
 * Destructor
 * Closes the backend resources
 */
CCompassSym::~CCompassSym()
    {
    delete iMagnetometer;
    Close();
    }

/**
 * Default constructor
 */
CCompassSym::CCompassSym(QSensor *sensor):CSensorBackendSym(sensor)
    {
    setReading<QCompassReading>(&iReading);
    iBackendData.iSensorType = KSensrvChannelTypeIdMagneticNorthData;
    }

/**
 * start() overrides CSensorBackendSym::start()
 * This is to allow starting magnetometer before stopping the compass
 */
void CCompassSym::start()
    {
    // start the magnetometer
    iMagnetometer->start();
    // start the compass backend
    CSensorBackendSym::start();
    }

/**
 * stop() overrides CSensorBackendSym::stop()
 * This is to allow stopping magnetometer before stopping the compass
 */
void CCompassSym::stop()
    {
    // stop the magnetometer
    iMagnetometer->stop();
    // start the compass backend
    CSensorBackendSym::stop();
    }

/*
 * DataReceived is used to retrieve the sensor reading from sensor server
 * It is implemented here to handle compass sensor specific
 * reading data and provides conversion and utility code
 */
void CCompassSym::DataReceived(CSensrvChannel &aChannel, TInt aCount, TInt /*aDataLost*/)
    {
    ProcessData(aChannel, aCount, iData);
    }

void CCompassSym::ProcessReading()
    {
    // Get a lock on the reading data
    iBackendData.iReadingLock.Wait();
    iReading.setAzimuth(iData.iAngleFromMagneticNorth);
    // Retrieve and set the calibration level
    iReading.setCalibrationLevel(iMagnetometer->GetCalibrationLevel());
    // Set the timestamp
    iReading.setTimestamp(iData.iTimeStamp.Int64());
    // Release the lock
    iBackendData.iReadingLock.Signal();
    // Notify that a reading is available
    newReadingAvailable();
    }

/**
 * Second phase constructor
 * Initialize the backend resources
 */
void CCompassSym::ConstructL()
    {
    // Initialize the backend
    InitializeL();
    // Create magnetometer, this is required as in sensor server,
    // calibration data is available only for magnetometer
    // We need to have a QSensor instance for the magnetometer backend or we will crash
    iMagnetometer = CMagnetometerSensorSym::NewL(new QSensor("QMagnetometer", this));
    // Listen only for property change on magnetometer as we are
    // interested only in calibration property
    iMagnetometer->SetListening(EFalse, ETrue);
    }

<|endoftext|>


<commit_before>#include "notepad.h"
#include "ui_notepad.h"
#include <QFileDialog>
#include <QFile>
#include <QMessageBox>
#include <QTextStream>
#include <iostream>

Notepad::Notepad(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::Notepad)
{
    // TODO, not sure where to organize instantiating methods
    // Temporarily changing to a directory
    QDir working_dir("/Users/pybae/Documents");
    printf("What is the working dir: %s\n", working_dir.absolutePath().toStdString().c_str());

    file_list = working_dir.entryList();

    QStringListIterator it(file_list);
    while (it.hasNext()) {
        std::cout << it.next().toStdString() << std::endl;
    }
    ui->setupUi(this);
}

Notepad::~Notepad()
{
    delete ui;
}

// Called when the "New" option is triggered by C-n or menu
void Notepad::on_actionNew_triggered()
{
    // TODO
}

// Called when the "Open" option is triggered by C-o or menu
void Notepad::on_actionOpen_triggered()
{
    printf("What is the working dir: %s\n", working_dir.absolutePath().toStdString().c_str());
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), working_dir.absolutePath(),
            tr("Text Files (*.txt);;C++ Files (*.cpp *.h)"));

    if (!fileName.isEmpty()) {
        QFile file(fileName);
        if (!file.open(QIODevice::ReadOnly)) {
            QMessageBox::critical(this, tr("Error"), tr("Could not open file"));
            return;
        }
        QTextStream in(&file);
        ui->mainTextEdit->setText(in.readAll());
        file.close();
    }
}

// Called when the "Save" option is triggered by C-s or menu
void Notepad::on_actionSave_triggered()
{
    // TODO
}

// Called when the "Save As" option is triggered by C-S (Ctrl shift s) or menu
void Notepad::on_actionSaveAs_triggered()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), QString(),
            tr("Text Files (*.txt);;C++ Files (*.cpp *.h)"));

    if (!fileName.isEmpty()) {
        QFile file(fileName);
        if (!file.open(QIODevice::WriteOnly)) {
            // error message
            return;
        } else {
            QTextStream stream(&file);
            stream << ui->mainTextEdit->toPlainText();
            stream.flush();
            file.close();
        }
    }
}

// Called when the "Print" option is triggered by C-p or menu
void Notepad::on_actionPrint_triggered()
{
    // TODO
}

// Called when the "Exit" option is triggered by C-q or menu
void Notepad::on_actionExit_triggered()
{
    // TODO need to check if there are any unsaved buffers
    qApp->quit();
}

// Triggered when the mainTextEdit region has its text changed
// TODO figure out how frequently this method is called
void Notepad::on_mainTextEdit_textChanged()
{
    // Save the current buffer
    Notepad::on_actionSave_triggered();
}
<commit_msg>Fixed QDir working directory<commit_after>#include "notepad.h"
#include "ui_notepad.h"
#include <QFileDialog>
#include <QFile>
#include <QMessageBox>
#include <QTextStream>
#include <iostream>

Notepad::Notepad(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::Notepad)
{
    // TODO, not sure where to organize instantiating methods
    // Temporarily changing to a directory
    working_dir = QDir("/Users/pybae/Documents");
    printf("What is the working dir: %s\n", working_dir.absolutePath().toStdString().c_str());

    file_list = working_dir.entryList();

    QStringListIterator it(file_list);
    while (it.hasNext()) {
        std::cout << it.next().toStdString() << std::endl;
    }
    ui->setupUi(this);
}

Notepad::~Notepad()
{
    delete ui;
}

// Called when the "New" option is triggered by C-n or menu
void Notepad::on_actionNew_triggered()
{
    // TODO
}

// Called when the "Open" option is triggered by C-o or menu
void Notepad::on_actionOpen_triggered()
{
    printf("What is the working dir: %s\n", working_dir.absolutePath().toStdString().c_str());
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), working_dir.absolutePath(),
            tr("Text Files (*.txt);;C++ Files (*.cpp *.h)"));

    if (!fileName.isEmpty()) {
        QFile file(fileName);
        if (!file.open(QIODevice::ReadOnly)) {
            QMessageBox::critical(this, tr("Error"), tr("Could not open file"));
            return;
        }
        QTextStream in(&file);
        ui->mainTextEdit->setText(in.readAll());
        file.close();
    }
}

// Called when the "Save" option is triggered by C-s or menu
void Notepad::on_actionSave_triggered()
{
    // TODO
}

// Called when the "Save As" option is triggered by C-S (Ctrl shift s) or menu
void Notepad::on_actionSaveAs_triggered()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), QString(),
            tr("Text Files (*.txt);;C++ Files (*.cpp *.h)"));

    if (!fileName.isEmpty()) {
        QFile file(fileName);
        if (!file.open(QIODevice::WriteOnly)) {
            // error message
            return;
        } else {
            QTextStream stream(&file);
            stream << ui->mainTextEdit->toPlainText();
            stream.flush();
            file.close();
        }
    }
}

// Called when the "Print" option is triggered by C-p or menu
void Notepad::on_actionPrint_triggered()
{
    // TODO
}

// Called when the "Exit" option is triggered by C-q or menu
void Notepad::on_actionExit_triggered()
{
    // TODO need to check if there are any unsaved buffers
    qApp->quit();
}

// Triggered when the mainTextEdit region has its text changed
// TODO figure out how frequently this method is called
void Notepad::on_mainTextEdit_textChanged()
{
    // Save the current buffer
    Notepad::on_actionSave_triggered();
}
<|endoftext|>


<commit_before>/**
 * C S O U N D   V S T
 *
 * A VST plugin version of Csound, with Python scripting.
 *
 * L I C E N S E
 *
 * This software is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This software 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#ifndef CSND_CPPSOUND_H
#define CSND_CPPSOUND_H
#ifdef SWIG
%module csnd
%include "std_string.i"
%include "std_vector.i"
%{
#include "Csound.hpp"
#include "CsoundFile.hpp"
#include <string>
#include <vector>
  %}
%template(MyfltVector) std::vector<MYFLT>;
#else
#include "Csound.hpp"
#include "CsoundFile.hpp"
#include <string>
#include <vector>
#endif

#if defined(WIN32)
#define PUBLIC __declspec(dllexport)
#else
#define PUBLIC
#endif

class PUBLIC CppSound : public Csound, public CsoundFile
{
  bool go;
  bool isCompiled;
  bool isPerforming;
  size_t spoutSize;
  std::string renderedSoundfile;
public:
  PUBLIC CppSound();
  PUBLIC virtual ~CppSound();
  PUBLIC virtual CSOUND *getCsound();
  PUBLIC virtual long getThis();
  PUBLIC virtual int compile(int argc, char **argv);
  PUBLIC virtual int compile();
  PUBLIC virtual size_t getSpoutSize() const;
  PUBLIC virtual int perform(int argc, char **argv);
  PUBLIC virtual int perform();
  PUBLIC virtual int performKsmps(bool absolute);
  PUBLIC virtual void cleanup();
  PUBLIC virtual void inputMessage(std::string istatement);
  PUBLIC virtual void write(const char *text);
  PUBLIC virtual bool getIsCompiled() const;
  PUBLIC virtual void setIsPerforming(bool isPerforming);
  PUBLIC virtual bool getIsPerforming() const;
  PUBLIC virtual bool getIsGo();
  PUBLIC virtual void stop();
  PUBLIC virtual void setPythonMessageCallback();
};

#endif

<commit_msg>Fixed compile error<commit_after>/**
 * C S O U N D   V S T
 *
 * A VST plugin version of Csound, with Python scripting.
 *
 * L I C E N S E
 *
 * This software is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This software 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#ifndef CSND_CPPSOUND_H
#define CSND_CPPSOUND_H
#ifdef SWIG
%module csnd
%include "std_string.i"
%include "std_vector.i"
%{
#include "csound.hpp"
#include "CsoundFile.hpp"
#include <string>
#include <vector>
  %}
%template(MyfltVector) std::vector<MYFLT>;
#else
#include "csound.hpp"
#include "CsoundFile.hpp"
#include <string>
#include <vector>
#endif

#if defined(WIN32)
#define PUBLIC __declspec(dllexport)
#else
#define PUBLIC
#endif

class PUBLIC CppSound : public Csound, public CsoundFile
{
  bool go;
  bool isCompiled;
  bool isPerforming;
  size_t spoutSize;
  std::string renderedSoundfile;
public:
  PUBLIC CppSound();
  PUBLIC virtual ~CppSound();
  PUBLIC virtual CSOUND *getCsound();
  PUBLIC virtual long getThis();
  PUBLIC virtual int compile(int argc, char **argv);
  PUBLIC virtual int compile();
  PUBLIC virtual size_t getSpoutSize() const;
  PUBLIC virtual int perform(int argc, char **argv);
  PUBLIC virtual int perform();
  PUBLIC virtual int performKsmps(bool absolute);
  PUBLIC virtual void cleanup();
  PUBLIC virtual void inputMessage(std::string istatement);
  PUBLIC virtual void write(const char *text);
  PUBLIC virtual bool getIsCompiled() const;
  PUBLIC virtual void setIsPerforming(bool isPerforming);
  PUBLIC virtual bool getIsPerforming() const;
  PUBLIC virtual bool getIsGo();
  PUBLIC virtual void stop();
  PUBLIC virtual void setPythonMessageCallback();
};

#endif

<|endoftext|>


<commit_before>/*
   Copyright (c) 2013, Sean Kasun
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
 this list of conditions and the following disclaimer in the documentation
 and/or other materials provided with the distribution.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QAction>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QMenu>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QStatusBar>
#include <QProgressDialog>
#include <QDir>
#include "minutor.h"
#include "mapview.h"
#include "labelledslider.h"
#include "nbt.h"
#include "json.h"
#include "definitionmanager.h"
#include "settings.h"
#include "dimensions.h"
#include "worldsave.h"

Minutor::Minutor()
{
	mapview = new MapView;
	connect(mapview,SIGNAL(hoverTextChanged(QString)),
			statusBar(),SLOT(showMessage(QString)));
	dm=new DefinitionManager(this);
	mapview->attach(dm);
	connect(dm,SIGNAL(packsChanged()),
			this,SLOT(updateDimensions()));
	dimensions=dm->dimensions();
	connect(dimensions,SIGNAL(dimensionChanged(Dimension &)),
			this,SLOT(viewDimension(Dimension &)));
	settings = new Settings(this);
	connect(settings,SIGNAL(settingsUpdated()),
			this,SLOT(rescanWorlds()));

	if (settings->update)
		dm->autoUpdate();

	createActions();
	createMenus();
	createStatusBar();

	depth = new LabelledSlider;
	depth->setValue(255);

	connect(depth, SIGNAL(valueChanged(int)),
			mapview, SLOT(setDepth(int)));
	connect(this, SIGNAL(worldLoaded(bool)),
			mapview, SLOT(setEnabled(bool)));
	connect(this, SIGNAL(worldLoaded(bool)),
			depth, SLOT(setEnabled(bool)));

	QVBoxLayout *mainLayout = new QVBoxLayout;
	mainLayout->addWidget(depth);
	mainLayout->addWidget(mapview,1);
	mainLayout->setSpacing(0);
	mainLayout->setContentsMargins(0,0,0,0);

	QWidget *central=new QWidget;
	central->setLayout(mainLayout);

	setCentralWidget(central);
	layout()->setContentsMargins(0,0,0,0);

	setWindowTitle(qApp->applicationName());

	emit worldLoaded(false);
}

void Minutor::openWorld()
{
	QAction *action=qobject_cast<QAction*>(sender());
	if (action)
		loadWorld(action->data().toString());
}

void Minutor::open()
{
	QString dirName = QFileDialog::getExistingDirectory(this,tr("Open World"));
	if (!dirName.isEmpty())
	{
		QDir path(dirName);
		if (!path.exists("level.dat"))
		{
			QMessageBox::warning(this,
								 tr("Couldn't open world"),
								 tr("%1 is not a valid Minecraft world").arg(dirName),
								 QMessageBox::Cancel);
			return;
		}
		loadWorld(dirName);
	}
}

void Minutor::reload()
{
	loadWorld(currentWorld);
}

void Minutor::save()
{
	QString filename = QFileDialog::getSaveFileName(this,tr("Save PNG"),QString(),"*.png");
	if (!filename.isEmpty())
	{
		WorldSave *ws=new WorldSave(filename,mapview);
		progress=new QProgressDialog();
		progress->setCancelButton(NULL);
		progress->setMaximum(100);
		progress->show();
		connect(ws,SIGNAL(progress(QString,double)),
				this,SLOT(saveProgress(QString,double)));
		connect(ws,SIGNAL(finished()),
				this,SLOT(saveFinished()));
		QThreadPool::globalInstance()->start(ws);
	}
}

void Minutor::saveProgress(QString status, double value)
{
	progress->setValue(value*100);
	progress->setLabelText(status);
}
void Minutor::saveFinished()
{
	progress->hide();
	delete progress;
}

void Minutor::closeWorld()
{
	locations.clear();
	for (int i=0;i<players.size();i++)
	{
		jumpMenu->removeAction(players[i]);
		delete players[i];
	}
	players.clear();
	jumpMenu->setEnabled(false);
	dimensions->removeDimensions(dimMenu);
	currentWorld=QString();
	emit worldLoaded(false);
}

void Minutor::jumpToLocation()
{
	QAction *action=qobject_cast<QAction*>(sender());
	if (action)
	{
		Location loc=locations[action->data().toInt()];
		mapview->setLocation(loc.x,loc.z);
	}
}

void Minutor::jumpToXZ(int blockX, int blockZ)
{
	mapview->setLocation(blockX, blockZ);
}

void Minutor::toggleFlags()
{
	int flags = 0;
	if (lightingAct->isChecked())
		flags |= MapView::flgLighting;
	if (caveModeAct->isChecked())
		flags |= MapView::flgCaveMode;
	if (depthShadingAct->isChecked())
		flags |= MapView::flgDepthShading;
	mapview->setFlags(flags);
}

void Minutor::viewDimension(Dimension &dim)
{
	mapview->setDimension(dim.path,dim.scale);
}

void Minutor::about()
{
	QMessageBox::about(this,tr("About %1").arg(qApp->applicationName()),
					   tr("%1 v%2
\n"
						  "© Copyright %3, %4").arg(qApp->applicationName())
					   .arg(qApp->applicationVersion())
					   .arg(2013)
					   .arg(qApp->organizationName()));
}

void Minutor::updateDimensions()
{
	dimensions->getDimensions(currentWorld,dimMenu,this);
}

void Minutor::createActions()
{
	getWorldList();

	openAct=new QAction(tr("&Open..."),this);
	openAct->setShortcut(tr("Ctrl+O"));
	openAct->setStatusTip(tr("Open a world"));
	connect(openAct, SIGNAL(triggered()),
			this, SLOT(open()));

	reloadAct=new QAction(tr("&Reload"),this);
	reloadAct->setShortcut(tr("F5"));
	reloadAct->setStatusTip(tr("Reload current world"));
	connect(reloadAct, SIGNAL(triggered()),
			this, SLOT(reload()));
	connect(this, SIGNAL(worldLoaded(bool)),
			reloadAct, SLOT(setEnabled(bool)));

	saveAct=new QAction(tr("&Save PNG..."),this);
	saveAct->setShortcut(tr("Ctrl+S"));
	saveAct->setStatusTip(tr("Save as PNG"));
	connect(saveAct, SIGNAL(triggered()),
			this, SLOT(save()));
	connect(this, SIGNAL(worldLoaded(bool)),
			saveAct, SLOT(setEnabled(bool)));

	exitAct=new QAction(tr("E&xit"),this);
	exitAct->setShortcut(tr("Ctrl+Q"));
	exitAct->setStatusTip(tr("Exit %1").arg(qApp->applicationName()));
	connect(exitAct, SIGNAL(triggered()),
			this, SLOT(close()));

	jumpSpawnAct=new QAction(tr("Jump to &Spawn"),this);
	jumpSpawnAct->setShortcut(tr("F1"));
	jumpSpawnAct->setStatusTip(tr("Jump to world spawn"));
	connect(jumpSpawnAct, SIGNAL(triggered()),
			this, SLOT(jumpToLocation()));
	connect(this, SIGNAL(worldLoaded(bool)),
			jumpSpawnAct, SLOT(setEnabled(bool)));

	lightingAct=new QAction(tr("&Lighting"),this);
	lightingAct->setCheckable(true);
	lightingAct->setShortcut(tr("Ctrl+L"));
	lightingAct->setStatusTip(tr("Toggle lighting on/off"));
	connect(lightingAct, SIGNAL(triggered()),
			this, SLOT(toggleFlags()));

	depthShadingAct = new QAction(tr("&Depth shading"), this);
	depthShadingAct->setCheckable(true);
	depthShadingAct->setStatusTip(tr("Toggle shading based on relative depth"));
	connect(depthShadingAct, SIGNAL(triggered()), this, SLOT(toggleFlags()));

	caveModeAct=new QAction(tr("&Cave Mode"),this);
	caveModeAct->setCheckable(true);
	caveModeAct->setShortcut(tr("Ctrl+I"));
	caveModeAct->setStatusTip(tr("Toggle cave mode on/off"));
	connect(caveModeAct, SIGNAL(triggered()),
			this, SLOT(toggleFlags()));

	manageDefsAct=new QAction(tr("Manage &Definitions..."),this);
	manageDefsAct->setStatusTip(tr("Manage block and biome definitions"));
	connect(manageDefsAct, SIGNAL(triggered()),
			dm, SLOT(show()));

	refreshAct = new QAction(tr("Refresh"), this);
	refreshAct->setShortcut(tr("F2"));
	refreshAct->setStatusTip(tr("Reloads all chunks, but keeps the same position / dimension"));
	connect(refreshAct, SIGNAL(triggered()), mapview, SLOT(clearCache()));

	aboutAct=new QAction(tr("&About"),this);
	aboutAct->setStatusTip(tr("About %1").arg(qApp->applicationName()));
	connect(aboutAct, SIGNAL(triggered()),
			this, SLOT(about()));

	settingsAct=new QAction(tr("Settings..."),this);
	settingsAct->setStatusTip(tr("Change %1 Settings").arg(qApp->applicationName()));
	connect(settingsAct, SIGNAL(triggered()),
			settings, SLOT(show()));

	updatesAct=new QAction(tr("Check for updates..."),this);
	updatesAct->setStatusTip(tr("Check for updated packs"));
	connect(updatesAct, SIGNAL(triggered()),
			dm, SLOT(checkForUpdates()));
}

void Minutor::createMenus()
{
	fileMenu=menuBar()->addMenu(tr("&File"));
	worldMenu=fileMenu->addMenu(tr("&Open World"));

	worldMenu->addActions(worlds);
	if (worlds.size()==0) //no worlds found
		worldMenu->setEnabled(false);

	fileMenu->addAction(openAct);
	fileMenu->addAction(reloadAct);
	fileMenu->addSeparator();
	fileMenu->addAction(saveAct);
	fileMenu->addSeparator();
	fileMenu->addAction(exitAct);

	viewMenu=menuBar()->addMenu(tr("&View"));
	viewMenu->addAction(jumpSpawnAct);
	jumpMenu=viewMenu->addMenu(tr("&Jump to Player"));
	jumpMenu->setEnabled(false);
	dimMenu=viewMenu->addMenu(tr("&Dimension"));
	dimMenu->setEnabled(false);
	viewMenu->addSeparator();
	viewMenu->addAction(lightingAct);
	//viewMenu->addAction(caveModeAct);
	viewMenu->addAction(depthShadingAct);
	viewMenu->addSeparator();
	viewMenu->addAction(refreshAct);
	viewMenu->addSeparator();
	viewMenu->addAction(manageDefsAct);

	menuBar()->addSeparator();

	helpMenu=menuBar()->addMenu(tr("&Help"));
	helpMenu->addAction(aboutAct);
	helpMenu->addSeparator();
	helpMenu->addAction(settingsAct);
	helpMenu->addAction(updatesAct);
}

void Minutor::createStatusBar()
{
	statusBar()->showMessage(tr("Ready"));
}

QString Minutor::getWorldName(QDir path)
{
	if (!path.exists("level.dat")) //no level.dat?  no world
		return QString();

	NBT level(path.filePath("level.dat"));
	return level.at("Data")->at("LevelName")->toString();
}

void Minutor::getWorldList()
{
	QDir mc(settings->mcpath);
	if (!mc.cd("saves"))
		return;

	QDirIterator it(mc);
	int key=1;
	while (it.hasNext())
	{
		it.next();
		if (it.fileInfo().isDir())
		{
			QString name=getWorldName(it.filePath());
			if (!name.isNull())
			{
				QAction *w=new QAction(this);
				w->setText(name);
				w->setData(it.filePath());
				if (key<10)
				{
					w->setShortcut("Ctrl+"+QString::number(key));
					key++;
				}
				connect(w, SIGNAL(triggered()),
						this, SLOT(openWorld()));
				worlds.append(w);
			}
		}
	}
}

void Minutor::loadWorld(QDir path)
{
	closeWorld(); //just in case
	currentWorld=path;

	NBT level(path.filePath("level.dat"));

	Tag *data=level.at("Data");
	//add level name to window title
	setWindowTitle(qApp->applicationName()+" - "+data->at("LevelName")->toString());
	//save world spawn
	jumpSpawnAct->setData(locations.count());
	locations.append(Location(data->at("SpawnX")->toDouble(),
							  data->at("SpawnZ")->toDouble()));
	//show saved players
	if (path.exists("players"))
	{
		path.cd("players");
		QDirIterator it(path);
		bool hasPlayers=false;
		while (it.hasNext())
		{
			it.next();
			if (it.fileInfo().isFile())
			{
				hasPlayers=true;
				NBT player(it.filePath());
				Tag *pos=player.at("Pos");
				double posX=pos->at(0)->toDouble();
				double posZ=pos->at(2)->toDouble();
				Tag *dim=player.at("Dimension");
				if (dim && (dim->toInt() == -1))
				{
					posX *= 8;
					posZ *= 8;
				}
				QAction *p=new QAction(this);
				p->setText(it.fileInfo().completeBaseName());
				p->setData(locations.count());
				locations.append(Location(posX, posZ));
				connect(p, SIGNAL(triggered()),
						this, SLOT(jumpToLocation()));
				players.append(p);
				if (player.has("SpawnX")) //player has a bed
				{
					p=new QAction(this);
					p->setText(it.fileInfo().completeBaseName()+"'s Bed");
					p->setData(locations.count());
					locations.append(Location(player.at("SpawnX")->toDouble(),
											  player.at("SpawnZ")->toDouble()));
					connect(p, SIGNAL(triggered()),
							this, SLOT(jumpToLocation()));
					players.append(p);
				}
			}
		}
		jumpMenu->addActions(players);
		jumpMenu->setEnabled(hasPlayers);
		path.cdUp();
	}

	//show dimensions
	dimensions->getDimensions(path,dimMenu,this);
	emit worldLoaded(true);
	mapview->setLocation(locations.first().x,locations.first().z);
	toggleFlags();
}

void Minutor::rescanWorlds()
{
	worlds.clear();
	getWorldList();
	worldMenu->clear();
	worldMenu->addActions(worlds);
	worldMenu->setEnabled(worlds.count()!=0);
	//we don't care about the auto-update toggle, since that only happens
	//on startup anyway.
}
<commit_msg>added default suffix for world save to PNG<commit_after>/*
   Copyright (c) 2013, Sean Kasun
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
 this list of conditions and the following disclaimer in the documentation
 and/or other materials provided with the distribution.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QAction>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QMenu>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QStatusBar>
#include <QProgressDialog>
#include <QDir>
#include "minutor.h"
#include "mapview.h"
#include "labelledslider.h"
#include "nbt.h"
#include "json.h"
#include "definitionmanager.h"
#include "settings.h"
#include "dimensions.h"
#include "worldsave.h"

Minutor::Minutor()
{
	mapview = new MapView;
	connect(mapview,SIGNAL(hoverTextChanged(QString)),
			statusBar(),SLOT(showMessage(QString)));
	dm=new DefinitionManager(this);
	mapview->attach(dm);
	connect(dm,SIGNAL(packsChanged()),
			this,SLOT(updateDimensions()));
	dimensions=dm->dimensions();
	connect(dimensions,SIGNAL(dimensionChanged(Dimension &)),
			this,SLOT(viewDimension(Dimension &)));
	settings = new Settings(this);
	connect(settings,SIGNAL(settingsUpdated()),
			this,SLOT(rescanWorlds()));

	if (settings->update)
		dm->autoUpdate();

	createActions();
	createMenus();
	createStatusBar();

	depth = new LabelledSlider;
	depth->setValue(255);

	connect(depth, SIGNAL(valueChanged(int)),
			mapview, SLOT(setDepth(int)));
	connect(this, SIGNAL(worldLoaded(bool)),
			mapview, SLOT(setEnabled(bool)));
	connect(this, SIGNAL(worldLoaded(bool)),
			depth, SLOT(setEnabled(bool)));

	QVBoxLayout *mainLayout = new QVBoxLayout;
	mainLayout->addWidget(depth);
	mainLayout->addWidget(mapview,1);
	mainLayout->setSpacing(0);
	mainLayout->setContentsMargins(0,0,0,0);

	QWidget *central=new QWidget;
	central->setLayout(mainLayout);

	setCentralWidget(central);
	layout()->setContentsMargins(0,0,0,0);

	setWindowTitle(qApp->applicationName());

	emit worldLoaded(false);
}

void Minutor::openWorld()
{
	QAction *action=qobject_cast<QAction*>(sender());
	if (action)
		loadWorld(action->data().toString());
}

void Minutor::open()
{
	QString dirName = QFileDialog::getExistingDirectory(this,tr("Open World"));
	if (!dirName.isEmpty())
	{
		QDir path(dirName);
		if (!path.exists("level.dat"))
		{
			QMessageBox::warning(this,
								 tr("Couldn't open world"),
								 tr("%1 is not a valid Minecraft world").arg(dirName),
								 QMessageBox::Cancel);
			return;
		}
		loadWorld(dirName);
	}
}

void Minutor::reload()
{
	loadWorld(currentWorld);
}

void Minutor::save()
{
	QFileDialog fileDialog(this);
	fileDialog.setDefaultSuffix("png");
	QString filename = fileDialog.getSaveFileName(this,tr("Save world as PNG"),QString(),"*.png");
	if (!filename.isEmpty())
	{
		WorldSave *ws=new WorldSave(filename,mapview);
		progress=new QProgressDialog();
		progress->setCancelButton(NULL);
		progress->setMaximum(100);
		progress->show();
		connect(ws,SIGNAL(progress(QString,double)),
				this,SLOT(saveProgress(QString,double)));
		connect(ws,SIGNAL(finished()),
				this,SLOT(saveFinished()));
		QThreadPool::globalInstance()->start(ws);
	}
}

void Minutor::saveProgress(QString status, double value)
{
	progress->setValue(value*100);
	progress->setLabelText(status);
}
void Minutor::saveFinished()
{
	progress->hide();
	delete progress;
}

void Minutor::closeWorld()
{
	locations.clear();
	for (int i=0;i<players.size();i++)
	{
		jumpMenu->removeAction(players[i]);
		delete players[i];
	}
	players.clear();
	jumpMenu->setEnabled(false);
	dimensions->removeDimensions(dimMenu);
	currentWorld=QString();
	emit worldLoaded(false);
}

void Minutor::jumpToLocation()
{
	QAction *action=qobject_cast<QAction*>(sender());
	if (action)
	{
		Location loc=locations[action->data().toInt()];
		mapview->setLocation(loc.x,loc.z);
	}
}

void Minutor::jumpToXZ(int blockX, int blockZ)
{
	mapview->setLocation(blockX, blockZ);
}

void Minutor::toggleFlags()
{
	int flags = 0;
	if (lightingAct->isChecked())
		flags |= MapView::flgLighting;
	if (caveModeAct->isChecked())
		flags |= MapView::flgCaveMode;
	if (depthShadingAct->isChecked())
		flags |= MapView::flgDepthShading;
	mapview->setFlags(flags);
}

void Minutor::viewDimension(Dimension &dim)
{
	mapview->setDimension(dim.path,dim.scale);
}

void Minutor::about()
{
	QMessageBox::about(this,tr("About %1").arg(qApp->applicationName()),
					   tr("%1 v%2
\n"
						  "© Copyright %3, %4").arg(qApp->applicationName())
					   .arg(qApp->applicationVersion())
					   .arg(2013)
					   .arg(qApp->organizationName()));
}

void Minutor::updateDimensions()
{
	dimensions->getDimensions(currentWorld,dimMenu,this);
}

void Minutor::createActions()
{
	getWorldList();

	openAct=new QAction(tr("&Open..."),this);
	openAct->setShortcut(tr("Ctrl+O"));
	openAct->setStatusTip(tr("Open a world"));
	connect(openAct, SIGNAL(triggered()),
			this, SLOT(open()));

	reloadAct=new QAction(tr("&Reload"),this);
	reloadAct->setShortcut(tr("F5"));
	reloadAct->setStatusTip(tr("Reload current world"));
	connect(reloadAct, SIGNAL(triggered()),
			this, SLOT(reload()));
	connect(this, SIGNAL(worldLoaded(bool)),
			reloadAct, SLOT(setEnabled(bool)));

	saveAct=new QAction(tr("&Save PNG..."),this);
	saveAct->setShortcut(tr("Ctrl+S"));
	saveAct->setStatusTip(tr("Save as PNG"));
	connect(saveAct, SIGNAL(triggered()),
			this, SLOT(save()));
	connect(this, SIGNAL(worldLoaded(bool)),
			saveAct, SLOT(setEnabled(bool)));

	exitAct=new QAction(tr("E&xit"),this);
	exitAct->setShortcut(tr("Ctrl+Q"));
	exitAct->setStatusTip(tr("Exit %1").arg(qApp->applicationName()));
	connect(exitAct, SIGNAL(triggered()),
			this, SLOT(close()));

	jumpSpawnAct=new QAction(tr("Jump to &Spawn"),this);
	jumpSpawnAct->setShortcut(tr("F1"));
	jumpSpawnAct->setStatusTip(tr("Jump to world spawn"));
	connect(jumpSpawnAct, SIGNAL(triggered()),
			this, SLOT(jumpToLocation()));
	connect(this, SIGNAL(worldLoaded(bool)),
			jumpSpawnAct, SLOT(setEnabled(bool)));

	lightingAct=new QAction(tr("&Lighting"),this);
	lightingAct->setCheckable(true);
	lightingAct->setShortcut(tr("Ctrl+L"));
	lightingAct->setStatusTip(tr("Toggle lighting on/off"));
	connect(lightingAct, SIGNAL(triggered()),
			this, SLOT(toggleFlags()));

	depthShadingAct = new QAction(tr("&Depth shading"), this);
	depthShadingAct->setCheckable(true);
	depthShadingAct->setStatusTip(tr("Toggle shading based on relative depth"));
	connect(depthShadingAct, SIGNAL(triggered()), this, SLOT(toggleFlags()));

	caveModeAct=new QAction(tr("&Cave Mode"),this);
	caveModeAct->setCheckable(true);
	caveModeAct->setShortcut(tr("Ctrl+I"));
	caveModeAct->setStatusTip(tr("Toggle cave mode on/off"));
	connect(caveModeAct, SIGNAL(triggered()),
			this, SLOT(toggleFlags()));

	manageDefsAct=new QAction(tr("Manage &Definitions..."),this);
	manageDefsAct->setStatusTip(tr("Manage block and biome definitions"));
	connect(manageDefsAct, SIGNAL(triggered()),
			dm, SLOT(show()));

	refreshAct = new QAction(tr("Refresh"), this);
	refreshAct->setShortcut(tr("F2"));
	refreshAct->setStatusTip(tr("Reloads all chunks, but keeps the same position / dimension"));
	connect(refreshAct, SIGNAL(triggered()), mapview, SLOT(clearCache()));

	aboutAct=new QAction(tr("&About"),this);
	aboutAct->setStatusTip(tr("About %1").arg(qApp->applicationName()));
	connect(aboutAct, SIGNAL(triggered()),
			this, SLOT(about()));

	settingsAct=new QAction(tr("Settings..."),this);
	settingsAct->setStatusTip(tr("Change %1 Settings").arg(qApp->applicationName()));
	connect(settingsAct, SIGNAL(triggered()),
			settings, SLOT(show()));

	updatesAct=new QAction(tr("Check for updates..."),this);
	updatesAct->setStatusTip(tr("Check for updated packs"));
	connect(updatesAct, SIGNAL(triggered()),
			dm, SLOT(checkForUpdates()));
}

void Minutor::createMenus()
{
	fileMenu=menuBar()->addMenu(tr("&File"));
	worldMenu=fileMenu->addMenu(tr("&Open World"));

	worldMenu->addActions(worlds);
	if (worlds.size()==0) //no worlds found
		worldMenu->setEnabled(false);

	fileMenu->addAction(openAct);
	fileMenu->addAction(reloadAct);
	fileMenu->addSeparator();
	fileMenu->addAction(saveAct);
	fileMenu->addSeparator();
	fileMenu->addAction(exitAct);

	viewMenu=menuBar()->addMenu(tr("&View"));
	viewMenu->addAction(jumpSpawnAct);
	jumpMenu=viewMenu->addMenu(tr("&Jump to Player"));
	jumpMenu->setEnabled(false);
	dimMenu=viewMenu->addMenu(tr("&Dimension"));
	dimMenu->setEnabled(false);
	viewMenu->addSeparator();
	viewMenu->addAction(lightingAct);
	//viewMenu->addAction(caveModeAct);
	viewMenu->addAction(depthShadingAct);
	viewMenu->addSeparator();
	viewMenu->addAction(refreshAct);
	viewMenu->addSeparator();
	viewMenu->addAction(manageDefsAct);

	menuBar()->addSeparator();

	helpMenu=menuBar()->addMenu(tr("&Help"));
	helpMenu->addAction(aboutAct);
	helpMenu->addSeparator();
	helpMenu->addAction(settingsAct);
	helpMenu->addAction(updatesAct);
}

void Minutor::createStatusBar()
{
	statusBar()->showMessage(tr("Ready"));
}

QString Minutor::getWorldName(QDir path)
{
	if (!path.exists("level.dat")) //no level.dat?  no world
		return QString();

	NBT level(path.filePath("level.dat"));
	return level.at("Data")->at("LevelName")->toString();
}

void Minutor::getWorldList()
{
	QDir mc(settings->mcpath);
	if (!mc.cd("saves"))
		return;

	QDirIterator it(mc);
	int key=1;
	while (it.hasNext())
	{
		it.next();
		if (it.fileInfo().isDir())
		{
			QString name=getWorldName(it.filePath());
			if (!name.isNull())
			{
				QAction *w=new QAction(this);
				w->setText(name);
				w->setData(it.filePath());
				if (key<10)
				{
					w->setShortcut("Ctrl+"+QString::number(key));
					key++;
				}
				connect(w, SIGNAL(triggered()),
						this, SLOT(openWorld()));
				worlds.append(w);
			}
		}
	}
}

void Minutor::loadWorld(QDir path)
{
	closeWorld(); //just in case
	currentWorld=path;

	NBT level(path.filePath("level.dat"));

	Tag *data=level.at("Data");
	//add level name to window title
	setWindowTitle(qApp->applicationName()+" - "+data->at("LevelName")->toString());
	//save world spawn
	jumpSpawnAct->setData(locations.count());
	locations.append(Location(data->at("SpawnX")->toDouble(),
							  data->at("SpawnZ")->toDouble()));
	//show saved players
	if (path.exists("players"))
	{
		path.cd("players");
		QDirIterator it(path);
		bool hasPlayers=false;
		while (it.hasNext())
		{
			it.next();
			if (it.fileInfo().isFile())
			{
				hasPlayers=true;
				NBT player(it.filePath());
				Tag *pos=player.at("Pos");
				double posX=pos->at(0)->toDouble();
				double posZ=pos->at(2)->toDouble();
				Tag *dim=player.at("Dimension");
				if (dim && (dim->toInt() == -1))
				{
					posX *= 8;
					posZ *= 8;
				}
				QAction *p=new QAction(this);
				p->setText(it.fileInfo().completeBaseName());
				p->setData(locations.count());
				locations.append(Location(posX, posZ));
				connect(p, SIGNAL(triggered()),
						this, SLOT(jumpToLocation()));
				players.append(p);
				if (player.has("SpawnX")) //player has a bed
				{
					p=new QAction(this);
					p->setText(it.fileInfo().completeBaseName()+"'s Bed");
					p->setData(locations.count());
					locations.append(Location(player.at("SpawnX")->toDouble(),
											  player.at("SpawnZ")->toDouble()));
					connect(p, SIGNAL(triggered()),
							this, SLOT(jumpToLocation()));
					players.append(p);
				}
			}
		}
		jumpMenu->addActions(players);
		jumpMenu->setEnabled(hasPlayers);
		path.cdUp();
	}

	//show dimensions
	dimensions->getDimensions(path,dimMenu,this);
	emit worldLoaded(true);
	mapview->setLocation(locations.first().x,locations.first().z);
	toggleFlags();
}

void Minutor::rescanWorlds()
{
	worlds.clear();
	getWorldList();
	worldMenu->clear();
	worldMenu->addActions(worlds);
	worldMenu->setEnabled(worlds.count()!=0);
	//we don't care about the auto-update toggle, since that only happens
	//on startup anyway.
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */
#include "RptObjectListener.hxx"
#include "RptObject.hxx"
#include "RptDef.hxx"

namespace rptui
{
//============================================================================
// OObjectListener
//============================================================================

//----------------------------------------------------------------------------
OObjectListener::OObjectListener(OObjectBase* _pObject)
          :m_pObject(_pObject)
{
}

//----------------------------------------------------------------------------

OObjectListener::~OObjectListener()
{
}

// XEventListener
//----------------------------------------------------------------------------

void SAL_CALL OObjectListener::disposing( const  ::com::sun::star::lang::EventObject& ) throw( ::com::sun::star::uno::RuntimeException)
{
}

// XPropertyChangeListener
//----------------------------------------------------------------------------

void SAL_CALL OObjectListener::propertyChange( const  ::com::sun::star::beans::PropertyChangeEvent& evt ) throw( ::com::sun::star::uno::RuntimeException)
{
    m_pObject->_propertyChange( evt );
}

//----------------------------------------------------------------------------

//============================================================================
// DlgEdHint
//============================================================================

TYPEINIT1( DlgEdHint, SfxHint );

//----------------------------------------------------------------------------

DlgEdHint::DlgEdHint( DlgEdHintKind eHint )
    :eHintKind( eHint )
{
}

//----------------------------------------------------------------------------
DlgEdHint::~DlgEdHint()
{
}
//----------------------------------------------------------------------------
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>coverity#707968 Uninitialized pointer field<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */
#include "RptObjectListener.hxx"
#include "RptObject.hxx"
#include "RptDef.hxx"

namespace rptui
{
//============================================================================
// OObjectListener
//============================================================================

//----------------------------------------------------------------------------
OObjectListener::OObjectListener(OObjectBase* _pObject)
          :m_pObject(_pObject)
{
}

//----------------------------------------------------------------------------

OObjectListener::~OObjectListener()
{
}

// XEventListener
//----------------------------------------------------------------------------

void SAL_CALL OObjectListener::disposing( const  ::com::sun::star::lang::EventObject& ) throw( ::com::sun::star::uno::RuntimeException)
{
}

// XPropertyChangeListener
//----------------------------------------------------------------------------

void SAL_CALL OObjectListener::propertyChange( const  ::com::sun::star::beans::PropertyChangeEvent& evt ) throw( ::com::sun::star::uno::RuntimeException)
{
    m_pObject->_propertyChange( evt );
}

//----------------------------------------------------------------------------

//============================================================================
// DlgEdHint
//============================================================================

TYPEINIT1( DlgEdHint, SfxHint );

//----------------------------------------------------------------------------

DlgEdHint::DlgEdHint(DlgEdHintKind eHint)
    : eHintKind(eHint)
    , pDlgEdObj(NULL)
{
}

//----------------------------------------------------------------------------
DlgEdHint::~DlgEdHint()
{
}
//----------------------------------------------------------------------------
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>