+
+// ----------------------------------------------------------------------------
+// keyboard interface
+// ----------------------------------------------------------------------------
+
+void wxCalendarCtrl::OnChar(wxKeyEvent& event)
+{
+    switch ( event.KeyCode() )
+    {
+        case _T('+'):
+        case WXK_ADD:
+            SetDateAndNotify(m_date + wxDateSpan::Year());
+            break;
+
+        case _T('-'):
+        case WXK_SUBTRACT:
+            SetDateAndNotify(m_date - wxDateSpan::Year());
+            break;
+
+        case WXK_PRIOR:
+            SetDateAndNotify(m_date - wxDateSpan::Month());
+            break;
+
+        case WXK_NEXT:
+            SetDateAndNotify(m_date + wxDateSpan::Month());
+            break;
+
+        case WXK_RIGHT:
+            if ( event.ControlDown() )
+                SetDateAndNotify(wxDateTime(m_date).SetToNextWeekDay(
+                                 GetWindowStyle() & wxCAL_MONDAY_FIRST
+                                 ? wxDateTime::Sun : wxDateTime::Sat));
+            else
+                SetDateAndNotify(m_date + wxDateSpan::Day());
+            break;
+
+        case WXK_LEFT:
+            if ( event.ControlDown() )
+                SetDateAndNotify(wxDateTime(m_date).SetToPrevWeekDay(
+                                 GetWindowStyle() & wxCAL_MONDAY_FIRST
+                                 ? wxDateTime::Mon : wxDateTime::Sun));
+            else
+                SetDateAndNotify(m_date - wxDateSpan::Day());
+            break;
+
+        case WXK_UP:
+            SetDateAndNotify(m_date - wxDateSpan::Week());
+            break;
+
+        case WXK_DOWN:
+            SetDateAndNotify(m_date + wxDateSpan::Week());
+            break;
+
+        case WXK_HOME:
+            if ( event.ControlDown() )
+                SetDateAndNotify(wxDateTime::Today());
+            else
+                SetDateAndNotify(wxDateTime(1, m_date.GetMonth(), m_date.GetYear()));
+            break;
+
+        case WXK_END:
+            SetDateAndNotify(wxDateTime(m_date).SetToLastMonthDay());
+            break;
+
+        case WXK_RETURN:
+            GenerateEvent(wxEVT_CALENDAR_DOUBLECLICKED);
+            break;
+
+        default:
+            event.Skip();
+    }
+}
+
+// ----------------------------------------------------------------------------
+// holidays handling
+// ----------------------------------------------------------------------------
+
+void wxCalendarCtrl::EnableHolidayDisplay(bool display)
+{
+    long style = GetWindowStyle();
+    if ( display )
+        style |= wxCAL_SHOW_HOLIDAYS;
+    else
+        style &= ~wxCAL_SHOW_HOLIDAYS;
+
+    SetWindowStyle(style);
+
+    if ( display )
+        SetHolidayAttrs();
+    else
+        ResetHolidayAttrs();
+
+    Refresh();
+}
+
+void wxCalendarCtrl::SetHolidayAttrs()
+{
+    if ( GetWindowStyle() & wxCAL_SHOW_HOLIDAYS )
+    {
+        ResetHolidayAttrs();
+
+        wxDateTime::Tm tm = m_date.GetTm();
+        wxDateTime dtStart(1, tm.mon, tm.year),
+                   dtEnd = dtStart.GetLastMonthDay();
+
+        wxDateTimeArray hol;
+        wxDateTimeHolidayAuthority::GetHolidaysInRange(dtStart, dtEnd, hol);
+
+        size_t count = hol.GetCount();
+        for ( size_t n = 0; n < count; n++ )
+        {
+            SetHoliday(hol[n].GetDay());
+        }
+    }
+}
+
+void wxCalendarCtrl::SetHoliday(size_t day)
+{
+    wxCHECK_RET( day > 0 && day < 32, _T("invalid day in SetHoliday") );
+
+    wxCalendarDateAttr *attr = GetAttr(day);
+    if ( !attr )
+    {
+        attr = new wxCalendarDateAttr;
+    }
+
+    attr->SetHoliday(TRUE);
+
+    // can't use SetAttr() because it would delete this pointer
+    m_attrs[day - 1] = attr;
+}
+
+void wxCalendarCtrl::ResetHolidayAttrs()
+{
+    for ( size_t day = 0; day < 31; day++ )
+    {
+        if ( m_attrs[day] )
+        {
+            m_attrs[day]->SetHoliday(FALSE);
+        }
+    }
+}
+
+// ----------------------------------------------------------------------------
+// wxCalendarEvent
+// ----------------------------------------------------------------------------
+
+void wxCalendarEvent::Init()
+{
+    m_wday = wxDateTime::Inv_WeekDay;
+}
+
+wxCalendarEvent::wxCalendarEvent(wxCalendarCtrl *cal, wxEventType type)
+               : wxCommandEvent(type, cal->GetId())
+{
+    m_date = cal->GetDate();
+}
+
+#endif // wxUSE_SPINBTN
+