Kaydet (Commit) 7e4db91a authored tarafından Noel Grandin's avatar Noel Grandin Kaydeden (comit) Michael Stahl

Convert SfxShellStack_Impl from SfxPtrArr to std::vector

Change-Id: I1ffd615a505029242a87337c9ef42c8156c42d70
Reviewed-on: https://gerrit.libreoffice.org/3394Reviewed-by: 's avatarMichael Stahl <mstahl@redhat.com>
Tested-by: 's avatarMichael Stahl <mstahl@redhat.com>
üst af4a9471
...@@ -28,11 +28,11 @@ ...@@ -28,11 +28,11 @@
#include <sfx2/bindings.hxx> #include <sfx2/bindings.hxx>
#include <sfx2/viewfrm.hxx> #include <sfx2/viewfrm.hxx>
#include <map> #include <map>
#include <vector>
class SfxSlotServer; class SfxSlotServer;
class SfxShell; class SfxShell;
class SfxRequest; class SfxRequest;
class SfxShellStack_Impl;
class SfxHintPoster; class SfxHintPoster;
class SfxViewFrame; class SfxViewFrame;
class SfxBindings; class SfxBindings;
...@@ -41,6 +41,8 @@ class SfxPopupMenuManager; ...@@ -41,6 +41,8 @@ class SfxPopupMenuManager;
class SfxModule; class SfxModule;
struct SfxDispatcher_Impl; struct SfxDispatcher_Impl;
typedef std::vector<SfxShell*> SfxShellStack_Impl;
namespace com namespace com
{ {
namespace sun namespace sun
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> // due to bsearch #include <stdlib.h> // due to bsearch
#include <algorithm>
#include <svtools/helpopt.hxx> #include <svtools/helpopt.hxx>
...@@ -37,7 +38,6 @@ ...@@ -37,7 +38,6 @@
#include "appdata.hxx" #include "appdata.hxx"
#include "sfx2/sfxhelp.hxx" #include "sfx2/sfxhelp.hxx"
#include <sfx2/dispatch.hxx> #include <sfx2/dispatch.hxx>
#include <sfx2/minstack.hxx>
#include <sfx2/msg.hxx> #include <sfx2/msg.hxx>
#include <sfx2/objface.hxx> #include <sfx2/objface.hxx>
#include <sfx2/bindings.hxx> #include <sfx2/bindings.hxx>
...@@ -67,8 +67,6 @@ DBG_NAME(SfxDispatcherFillState) ...@@ -67,8 +67,6 @@ DBG_NAME(SfxDispatcherFillState)
typedef std::vector<SfxRequest*> SfxRequestPtrArray; typedef std::vector<SfxRequest*> SfxRequestPtrArray;
DECL_PTRSTACK(SfxShellStack_Impl, SfxShell*, 8, 4 );
struct SfxToDo_Impl struct SfxToDo_Impl
{ {
SfxShell* pCluster; SfxShell* pCluster;
...@@ -552,14 +550,15 @@ sal_Bool SfxDispatcher::CheckVirtualStack( const SfxShell& rShell, sal_Bool bDee ...@@ -552,14 +550,15 @@ sal_Bool SfxDispatcher::CheckVirtualStack( const SfxShell& rShell, sal_Bool bDee
for(std::deque<SfxToDo_Impl>::reverse_iterator i = pImp->aToDoStack.rbegin(); i != pImp->aToDoStack.rend(); ++i) for(std::deque<SfxToDo_Impl>::reverse_iterator i = pImp->aToDoStack.rbegin(); i != pImp->aToDoStack.rend(); ++i)
{ {
if(i->bPush) if(i->bPush)
aStack.Push(i->pCluster); aStack.push_back(i->pCluster);
else else
{ {
SfxShell* pPopped(NULL); SfxShell* pPopped(NULL);
do do
{ {
DBG_ASSERT( aStack.Count(), "popping from empty stack" ); DBG_ASSERT( !aStack.empty(), "popping from empty stack" );
pPopped = aStack.Pop(); pPopped = aStack.back();
aStack.pop_back();
} }
while(i->bUntil && pPopped != i->pCluster); while(i->bUntil && pPopped != i->pCluster);
DBG_ASSERT(pPopped == i->pCluster, "popping unpushed SfxInterface"); DBG_ASSERT(pPopped == i->pCluster, "popping unpushed SfxInterface");
...@@ -568,9 +567,9 @@ sal_Bool SfxDispatcher::CheckVirtualStack( const SfxShell& rShell, sal_Bool bDee ...@@ -568,9 +567,9 @@ sal_Bool SfxDispatcher::CheckVirtualStack( const SfxShell& rShell, sal_Bool bDee
sal_Bool bReturn; sal_Bool bReturn;
if ( bDeep ) if ( bDeep )
bReturn = aStack.Contains(&rShell); bReturn = std::find(aStack.begin(), aStack.end(), &rShell) != aStack.end();
else else
bReturn = aStack.Top() == &rShell; bReturn = aStack.back() == &rShell;
return bReturn; return bReturn;
} }
...@@ -596,15 +595,15 @@ sal_uInt16 SfxDispatcher::GetShellLevel( const SfxShell& rShell ) ...@@ -596,15 +595,15 @@ sal_uInt16 SfxDispatcher::GetShellLevel( const SfxShell& rShell )
SFX_STACK(SfxDispatcher::GetShellLevel); SFX_STACK(SfxDispatcher::GetShellLevel);
Flush(); Flush();
for ( sal_uInt16 n = 0; n < pImp->aStack.Count(); ++n ) for ( sal_uInt16 n = 0; n < pImp->aStack.size(); ++n )
if ( pImp->aStack.Top( n ) == &rShell ) if ( *( pImp->aStack.rbegin() + n ) == &rShell )
return n; return n;
if ( pImp->pParent ) if ( pImp->pParent )
{ {
sal_uInt16 nRet = pImp->pParent->GetShellLevel(rShell); sal_uInt16 nRet = pImp->pParent->GetShellLevel(rShell);
if ( nRet == USHRT_MAX ) if ( nRet == USHRT_MAX )
return nRet; return nRet;
return nRet + pImp->aStack.Count(); return nRet + pImp->aStack.size();
} }
return USHRT_MAX; return USHRT_MAX;
...@@ -624,9 +623,9 @@ SfxShell *SfxDispatcher::GetShell(sal_uInt16 nIdx) const ...@@ -624,9 +623,9 @@ SfxShell *SfxDispatcher::GetShell(sal_uInt16 nIdx) const
*/ */
{ {
sal_uInt16 nShellCount = pImp->aStack.Count(); sal_uInt16 nShellCount = pImp->aStack.size();
if ( nIdx < nShellCount ) if ( nIdx < nShellCount )
return pImp->aStack.Top(nIdx); return *(pImp->aStack.rbegin() + nIdx);
else if ( pImp->pParent ) else if ( pImp->pParent )
return pImp->pParent->GetShell( nIdx - nShellCount ); return pImp->pParent->GetShell( nIdx - nShellCount );
return 0; return 0;
...@@ -717,8 +716,8 @@ void SfxDispatcher::DoActivate_Impl( sal_Bool bMDI, SfxViewFrame* /* pOld */ ) ...@@ -717,8 +716,8 @@ void SfxDispatcher::DoActivate_Impl( sal_Bool bMDI, SfxViewFrame* /* pOld */ )
if ( IsAppDispatcher() ) if ( IsAppDispatcher() )
return; return;
for ( int i = int(pImp->aStack.Count()) - 1; i >= 0; --i ) for ( int i = int(pImp->aStack.size()) - 1; i >= 0; --i )
pImp->aStack.Top( (sal_uInt16) i )->DoActivate_Impl(pImp->pFrame, bMDI); (*(pImp->aStack.rbegin() + i ))->DoActivate_Impl(pImp->pFrame, bMDI);
if ( bMDI && pImp->pFrame ) if ( bMDI && pImp->pFrame )
{ {
...@@ -743,8 +742,8 @@ void SfxDispatcher::DoActivate_Impl( sal_Bool bMDI, SfxViewFrame* /* pOld */ ) ...@@ -743,8 +742,8 @@ void SfxDispatcher::DoActivate_Impl( sal_Bool bMDI, SfxViewFrame* /* pOld */ )
void SfxDispatcher::DoParentActivate_Impl() void SfxDispatcher::DoParentActivate_Impl()
{ {
for ( int i = int(pImp->aStack.Count()) - 1; i >= 0; --i ) for ( int i = int(pImp->aStack.size()) - 1; i >= 0; --i )
pImp->aStack.Top( (sal_uInt16) i )->ParentActivate(); (*(pImp->aStack.rbegin() + i ))->ParentActivate();
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
...@@ -798,8 +797,8 @@ void SfxDispatcher::DoDeactivate_Impl( sal_Bool bMDI, SfxViewFrame* pNew ) ...@@ -798,8 +797,8 @@ void SfxDispatcher::DoDeactivate_Impl( sal_Bool bMDI, SfxViewFrame* pNew )
if ( IsAppDispatcher() && !pSfxApp->IsDowning() ) if ( IsAppDispatcher() && !pSfxApp->IsDowning() )
return; return;
for ( sal_uInt16 i = 0; i < pImp->aStack.Count(); ++i ) for ( sal_uInt16 i = 0; i < pImp->aStack.size(); ++i )
pImp->aStack.Top(i)->DoDeactivate_Impl(pImp->pFrame, bMDI); (*(pImp->aStack.rbegin() + i))->DoDeactivate_Impl(pImp->pFrame, bMDI);
sal_Bool bHidePopups = bMDI && pImp->pFrame; sal_Bool bHidePopups = bMDI && pImp->pFrame;
if ( pNew && pImp->pFrame ) if ( pNew && pImp->pFrame )
...@@ -831,8 +830,8 @@ void SfxDispatcher::DoDeactivate_Impl( sal_Bool bMDI, SfxViewFrame* pNew ) ...@@ -831,8 +830,8 @@ void SfxDispatcher::DoDeactivate_Impl( sal_Bool bMDI, SfxViewFrame* pNew )
void SfxDispatcher::DoParentDeactivate_Impl() void SfxDispatcher::DoParentDeactivate_Impl()
{ {
for ( int i = int(pImp->aStack.Count()) - 1; i >= 0; --i ) for ( int i = int(pImp->aStack.size()) - 1; i >= 0; --i )
pImp->aStack.Top( (sal_uInt16) i )->ParentDeactivate(); (*(pImp->aStack.rbegin() + i))->ParentDeactivate();
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
...@@ -869,7 +868,7 @@ int SfxDispatcher::GetShellAndSlot_Impl ...@@ -869,7 +868,7 @@ int SfxDispatcher::GetShellAndSlot_Impl
SfxSlotServer aSvr; SfxSlotServer aSvr;
if ( _FindServer(nSlot, aSvr, bModal) ) if ( _FindServer(nSlot, aSvr, bModal) )
{ {
if ( bOwnShellsOnly && aSvr.GetShellLevel() >= pImp->aStack.Count() ) if ( bOwnShellsOnly && aSvr.GetShellLevel() >= pImp->aStack.size() )
return sal_False; return sal_False;
*ppShell = GetShell(aSvr.GetShellLevel()); *ppShell = GetShell(aSvr.GetShellLevel());
...@@ -916,10 +915,10 @@ void SfxDispatcher::_Execute ...@@ -916,10 +915,10 @@ void SfxDispatcher::_Execute
SfxDispatcher *pDispat = this; SfxDispatcher *pDispat = this;
while ( pDispat ) while ( pDispat )
{ {
sal_uInt16 nShellCount = pDispat->pImp->aStack.Count(); sal_uInt16 nShellCount = pDispat->pImp->aStack.size();
for ( sal_uInt16 n=0; n<nShellCount; n++ ) for ( sal_uInt16 n=0; n<nShellCount; n++ )
{ {
if ( &rShell == pDispat->pImp->aStack.Top(n) ) if ( &rShell == *(pDispat->pImp->aStack.rbegin() + n) )
{ {
if ( eCallMode & SFX_CALLMODE_RECORD ) if ( eCallMode & SFX_CALLMODE_RECORD )
rReq.AllowRecording( sal_True ); rReq.AllowRecording( sal_True );
...@@ -959,13 +958,13 @@ const SfxSlot* SfxDispatcher::GetSlot( const String& rCommand ) ...@@ -959,13 +958,13 @@ const SfxSlot* SfxDispatcher::GetSlot( const String& rCommand )
{ {
// Count the number of Shells on the linked Dispatcher // Count the number of Shells on the linked Dispatcher
Flush(); Flush();
sal_uInt16 nTotCount = pImp->aStack.Count(); sal_uInt16 nTotCount = pImp->aStack.size();
if ( pImp->pParent ) if ( pImp->pParent )
{ {
SfxDispatcher *pParent = pImp->pParent; SfxDispatcher *pParent = pImp->pParent;
while ( pParent ) while ( pParent )
{ {
nTotCount = nTotCount + pParent->pImp->aStack.Count(); nTotCount = nTotCount + pParent->pImp->aStack.size();
pParent = pParent->pImp->pParent; pParent = pParent->pImp->pParent;
} }
} }
...@@ -1413,7 +1412,7 @@ void SfxDispatcher::_Update_Impl( sal_Bool bUIActive, sal_Bool bIsMDIApp, sal_Bo ...@@ -1413,7 +1412,7 @@ void SfxDispatcher::_Update_Impl( sal_Bool bUIActive, sal_Bool bIsMDIApp, sal_Bo
SfxShell *pStatusBarShell = NULL; SfxShell *pStatusBarShell = NULL;
SfxSlotPool* pSlotPool = &SfxSlotPool::GetSlotPool( GetFrame() ); SfxSlotPool* pSlotPool = &SfxSlotPool::GetSlotPool( GetFrame() );
sal_uInt16 nTotCount = pImp->aStack.Count(); sal_uInt16 nTotCount = pImp->aStack.size();
for ( sal_uInt16 nShell = nTotCount; nShell > 0; --nShell ) for ( sal_uInt16 nShell = nTotCount; nShell > 0; --nShell )
{ {
SfxShell *pShell = GetShell( nShell-1 ); SfxShell *pShell = GetShell( nShell-1 );
...@@ -1589,9 +1588,9 @@ void SfxDispatcher::FlushImpl() ...@@ -1589,9 +1588,9 @@ void SfxDispatcher::FlushImpl()
if(i->bPush) if(i->bPush)
{ {
// Actually push // Actually push
DBG_ASSERT(!pImp->aStack.Contains(i->pCluster), DBG_ASSERT( std::find(pImp->aStack.begin(), pImp->aStack.end(), i->pCluster) != pImp->aStack.end(),
"pushed SfxShell already on stack" ); "pushed SfxShell already on stack" );
pImp->aStack.Push(i->pCluster); pImp->aStack.push_back(i->pCluster);
i->pCluster->SetDisableFlags(pImp->nDisableFlags); i->pCluster->SetDisableFlags(pImp->nDisableFlags);
// Mark the moved shell // Mark the moved shell
...@@ -1604,8 +1603,9 @@ void SfxDispatcher::FlushImpl() ...@@ -1604,8 +1603,9 @@ void SfxDispatcher::FlushImpl()
bool bFound = false; bool bFound = false;
do do
{ {
DBG_ASSERT( pImp->aStack.Count(), "popping from empty stack" ); DBG_ASSERT( !pImp->aStack.empty(), "popping from empty stack" );
pPopped = pImp->aStack.Pop(); pPopped = pImp->aStack.back();
pImp->aStack.pop_back();
pPopped->SetDisableFlags( 0 ); pPopped->SetDisableFlags( 0 );
bFound = (pPopped == i->pCluster); bFound = (pPopped == i->pCluster);
...@@ -1788,7 +1788,7 @@ sal_Bool SfxDispatcher::_TryIntercept_Impl ...@@ -1788,7 +1788,7 @@ sal_Bool SfxDispatcher::_TryIntercept_Impl
{ {
// Maybe the parent is also belongs to a component // Maybe the parent is also belongs to a component
SfxDispatcher *pParent = pImp->pParent; SfxDispatcher *pParent = pImp->pParent;
sal_uInt16 nLevels = pImp->aStack.Count(); sal_uInt16 nLevels = pImp->aStack.size();
while ( pParent && pParent->pImp->pFrame ) while ( pParent && pParent->pImp->pFrame )
{ {
if ( pParent->pImp->pFrame->GetFrame().HasComponent() ) if ( pParent->pImp->pFrame->GetFrame().HasComponent() )
...@@ -1805,7 +1805,7 @@ sal_Bool SfxDispatcher::_TryIntercept_Impl ...@@ -1805,7 +1805,7 @@ sal_Bool SfxDispatcher::_TryIntercept_Impl
break; break;
} }
else else
nLevels = nLevels + pParent->pImp->aStack.Count(); nLevels = nLevels + pParent->pImp->aStack.size();
pParent = pParent->pImp->pParent; pParent = pParent->pImp->pParent;
} }
...@@ -1868,13 +1868,13 @@ sal_Bool SfxDispatcher::_FindServer ...@@ -1868,13 +1868,13 @@ sal_Bool SfxDispatcher::_FindServer
// Count the number of Shells in the linked dispatchers. // Count the number of Shells in the linked dispatchers.
Flush(); Flush();
sal_uInt16 nTotCount = pImp->aStack.Count(); sal_uInt16 nTotCount = pImp->aStack.size();
if ( pImp->pParent ) if ( pImp->pParent )
{ {
SfxDispatcher *pParent = pImp->pParent; SfxDispatcher *pParent = pImp->pParent;
while ( pParent ) while ( pParent )
{ {
nTotCount = nTotCount + pParent->pImp->aStack.Count(); nTotCount = nTotCount + pParent->pImp->aStack.size();
pParent = pParent->pImp->pParent; pParent = pParent->pImp->pParent;
} }
} }
...@@ -1916,7 +1916,7 @@ sal_Bool SfxDispatcher::_FindServer ...@@ -1916,7 +1916,7 @@ sal_Bool SfxDispatcher::_FindServer
{ {
sal_Bool bRet = pImp->pParent->_FindServer( nSlot, rServer, bModal ); sal_Bool bRet = pImp->pParent->_FindServer( nSlot, rServer, bModal );
rServer.SetShellLevel rServer.SetShellLevel
( rServer.GetShellLevel() + pImp->aStack.Count() ); ( rServer.GetShellLevel() + pImp->aStack.size() );
return bRet; return bRet;
} }
else else
...@@ -1927,7 +1927,7 @@ sal_Bool SfxDispatcher::_FindServer ...@@ -1927,7 +1927,7 @@ sal_Bool SfxDispatcher::_FindServer
// search through all the shells of the chained dispatchers // search through all the shells of the chained dispatchers
// from top to bottom // from top to bottom
sal_uInt16 nFirstShell = pImp->bModal && !bModal ? pImp->aStack.Count() : 0; sal_uInt16 nFirstShell = pImp->bModal && !bModal ? pImp->aStack.size() : 0;
for ( sal_uInt16 i = nFirstShell; i < nTotCount; ++i ) for ( sal_uInt16 i = nFirstShell; i < nTotCount; ++i )
{ {
SfxShell *pObjShell = GetShell(i); SfxShell *pObjShell = GetShell(i);
...@@ -2071,7 +2071,7 @@ SfxPopupMenuManager* SfxDispatcher::Popup( sal_uInt16 nConfigId,Window *pWin, co ...@@ -2071,7 +2071,7 @@ SfxPopupMenuManager* SfxDispatcher::Popup( sal_uInt16 nConfigId,Window *pWin, co
if ( rDisp.pImp->bQuiet ) if ( rDisp.pImp->bQuiet )
{ {
nConfigId = 0; nConfigId = 0;
nShLevel = rDisp.pImp->aStack.Count(); nShLevel = rDisp.pImp->aStack.size();
} }
Window *pWindow = pWin ? pWin : rDisp.pImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow(); Window *pWindow = pWin ? pWin : rDisp.pImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow();
...@@ -2097,7 +2097,7 @@ void SfxDispatcher::ExecutePopup( sal_uInt16 nConfigId, Window *pWin, const Poin ...@@ -2097,7 +2097,7 @@ void SfxDispatcher::ExecutePopup( sal_uInt16 nConfigId, Window *pWin, const Poin
if ( rDisp.pImp->bQuiet ) if ( rDisp.pImp->bQuiet )
{ {
nConfigId = 0; nConfigId = 0;
nShLevel = rDisp.pImp->aStack.Count(); nShLevel = rDisp.pImp->aStack.size();
} }
Window *pWindow = pWin ? pWin : rDisp.pImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow(); Window *pWindow = pWin ? pWin : rDisp.pImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow();
...@@ -2259,10 +2259,10 @@ SfxItemState SfxDispatcher::QueryState( sal_uInt16 nSID, ::com::sun::star::uno:: ...@@ -2259,10 +2259,10 @@ SfxItemState SfxDispatcher::QueryState( sal_uInt16 nSID, ::com::sun::star::uno::
sal_Bool SfxDispatcher::IsReadOnlyShell_Impl( sal_uInt16 nShell ) const sal_Bool SfxDispatcher::IsReadOnlyShell_Impl( sal_uInt16 nShell ) const
{ {
sal_uInt16 nShellCount = pImp->aStack.Count(); sal_uInt16 nShellCount = pImp->aStack.size();
if ( nShell < nShellCount ) if ( nShell < nShellCount )
{ {
SfxShell* pShell = pImp->aStack.Top( nShell ); SfxShell* pShell = *( pImp->aStack.rbegin() + nShell );
if( pShell->ISA( SfxModule ) || pShell->ISA( SfxApplication ) || pShell->ISA( SfxViewFrame ) ) if( pShell->ISA( SfxModule ) || pShell->ISA( SfxApplication ) || pShell->ISA( SfxViewFrame ) )
return sal_False; return sal_False;
else else
...@@ -2273,23 +2273,16 @@ sal_Bool SfxDispatcher::IsReadOnlyShell_Impl( sal_uInt16 nShell ) const ...@@ -2273,23 +2273,16 @@ sal_Bool SfxDispatcher::IsReadOnlyShell_Impl( sal_uInt16 nShell ) const
return sal_True; return sal_True;
} }
// A dirty trick, to get hold of the methods of the private base class
// SfxShellStack_Impl
class StackAccess_Impl : public SfxShellStack_Implarr_
{};
void SfxDispatcher::RemoveShell_Impl( SfxShell& rShell ) void SfxDispatcher::RemoveShell_Impl( SfxShell& rShell )
{ {
Flush(); Flush();
// The cast is because SfxShellStack_Impl member has non of its own sal_uInt16 nCount = pImp->aStack.size();
StackAccess_Impl& rStack = *((StackAccess_Impl*) (&pImp->aStack));
sal_uInt16 nCount = rStack.Count();
for ( sal_uInt16 n=0; n<nCount; ++n ) for ( sal_uInt16 n=0; n<nCount; ++n )
{ {
if ( rStack[n] == &rShell ) if ( pImp->aStack[n] == &rShell )
{ {
rStack.Remove( n ); pImp->aStack.erase( pImp->aStack.begin() + n );
rShell.SetDisableFlags( 0 ); rShell.SetDisableFlags( 0 );
rShell.DoDeactivate_Impl(pImp->pFrame, sal_True); rShell.DoDeactivate_Impl(pImp->pFrame, sal_True);
break; break;
...@@ -2339,8 +2332,8 @@ sal_Bool SfxDispatcher::IsUpdated_Impl() const ...@@ -2339,8 +2332,8 @@ sal_Bool SfxDispatcher::IsUpdated_Impl() const
void SfxDispatcher::SetDisableFlags( sal_uInt32 nFlags ) void SfxDispatcher::SetDisableFlags( sal_uInt32 nFlags )
{ {
pImp->nDisableFlags = nFlags; pImp->nDisableFlags = nFlags;
for ( int i = int(pImp->aStack.Count()) - 1; i >= 0; --i ) for ( SfxShellStack_Impl::const_reverse_iterator it = pImp->aStack.rbegin(); it != pImp->aStack.rend(); ++it )
pImp->aStack.Top( (sal_uInt16) i )->SetDisableFlags( nFlags ); (*it)->SetDisableFlags( nFlags );
} }
sal_uInt32 SfxDispatcher::GetDisableFlags() const sal_uInt32 SfxDispatcher::GetDisableFlags() const
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment