/**************************************************************
 * 
 * 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
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



#ifndef _BASIDE2_HXX
#define _BASIDE2_HXX

#include <svheader.hxx>

#include <bastypes.hxx>
#include <bastype3.hxx>
#include <basidesh.hxx>

class ExtTextEngine;
class ExtTextView;
class SvxSearchItem;
#include <svtools/svtabbx.hxx>
#include <svtools/headbar.hxx>

#ifndef _SV_BUTTON_HXX //autogen
#include <vcl/button.hxx>
#endif
#include <basic/sbmod.hxx>
#include <vcl/split.hxx>
#include "svl/lstner.hxx"
#include <svtools/colorcfg.hxx>

#include <sfx2/progress.hxx>
#include <svtools/syntaxhighlight.hxx>

DBG_NAMEEX( ModulWindow )

#define MARKER_NOMARKER	0xFFFF

namespace utl
{
    class SourceViewConfig;
}

// #108672 Helper functions to get/set text in TextEngine
// using the stream interface (get/setText() only supports
// tools Strings limited to 64K).
::rtl::OUString getTextEngineText( ExtTextEngine* pEngine );
void setTextEngineText( ExtTextEngine* pEngine, const ::rtl::OUString aStr );

class ProgressInfo : public SfxProgress
{
private:
	sal_uLong					nCurState;

public:

	inline			ProgressInfo( SfxObjectShell* pObjSh, const String& rText, sal_uLong nRange );

//	inline void		StartProgress( const String& rName, sal_uLong nStates );
//	inline void		EndProgress();
	inline void		StepProgress();
};

inline ProgressInfo::ProgressInfo( SfxObjectShell* pObjSh, const String& rText, sal_uLong nRange )
	: SfxProgress( pObjSh, rText, nRange )
{
	nCurState = 0;
}

// inline void ProgressInfo::StartProgress( const String& rName, sal_uLong nStates )
// {
// 	nCurState = 0;
// 	if ( pStbMgr )
// 		pStbMgr->StartProgressMode( rName, nStates );
// }

// inline void ProgressInfo::EndProgress()
// {
// 	if ( pStbMgr )
// 		pStbMgr->EndProgressMode();
//}

inline void ProgressInfo::StepProgress()
{
	SetState( ++nCurState );
}


namespace svt {
class SourceViewConfig;
}

class EditorWindow : public Window, public SfxListener, public utl::ConfigurationListener
{
private:
	ExtTextView*	pEditView;
	ExtTextEngine*	pEditEngine;

    utl::SourceViewConfig* pSourceViewConfig;

	long			nCurTextWidth;

	SyntaxHighlighter	aHighlighter;
	Timer			aSyntaxIdleTimer;
	Table			aSyntaxLineTable;
	DECL_LINK( SyntaxTimerHdl, Timer * );
	ProgressInfo*	pProgress;
	ModulWindow*	pModulWindow;

    virtual void DataChanged(DataChangedEvent const & rDCEvt);

	using			Window::Notify;
	virtual void	Notify( SfxBroadcaster& rBC, const SfxHint& rHint );

	void			ImpDoHighlight( sal_uLong nLineOff );
    void            ImplSetFont();

	sal_Bool			bHighlightning;
	sal_Bool			bDoSyntaxHighlight;
	sal_Bool			bDelayHighlight;

    virtual
    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer >
    GetComponentInterface(sal_Bool bCreate = sal_True);

protected:
	virtual void	Paint( const Rectangle& );
	virtual void	Resize();
	virtual void	KeyInput( const KeyEvent& rKeyEvt );
	virtual void	MouseMove( const MouseEvent& rMEvt );
	virtual void	MouseButtonDown( const MouseEvent& rMEvt );
	virtual void	MouseButtonUp( const MouseEvent& rMEvt );
	virtual void	Command( const CommandEvent& rCEvt );
	virtual void	LoseFocus();
	virtual void	RequestHelp( const HelpEvent& rHEvt );
    virtual void    ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 );

	void			DoSyntaxHighlight( sal_uLong nPara );
	String			GetWordAtCursor();
	sal_Bool			ImpCanModify();

public:
					EditorWindow( Window* pParent );
					~EditorWindow();

	ExtTextEngine*	GetEditEngine()	const	{ return (ExtTextEngine*)pEditEngine; }
	ExtTextView*	GetEditView() const		{ return pEditView; }
	ProgressInfo*	GetProgress() const		{ return pProgress; }

	void			CreateProgress( const String& rText, sal_uLong nRange );
	void			DestroyProgress();

	void			ParagraphInsertedDeleted( sal_uLong nNewPara, sal_Bool bInserted );
	void			DoDelayedSyntaxHighlight( sal_uLong nPara );

	void			CreateEditEngine();
	void			SetScrollBarRanges();
	void			InitScrollBars();
	void			SetModulWindow( ModulWindow* pWin )
						{ pModulWindow = pWin; }

	void			ForceSyntaxTimeout();
	sal_Bool			SetSourceInBasic( sal_Bool bQuiet = sal_True );

	sal_Bool			CanModify() { return ImpCanModify(); }
};


class BreakPointWindow : public Window
{
private:
	long			nCurYOffset;
	sal_uInt16			nMarkerPos;
	BreakPointList	aBreakPointList;
	ModulWindow*	pModulWindow;
	sal_Bool			bErrorMarker;
    bool m_bHighContrastMode;

    virtual void DataChanged(DataChangedEvent const & rDCEvt);

    void setBackgroundColor(Color aColor);

protected:
	virtual void	Paint( const Rectangle& );
	virtual void	Resize();
	BreakPoint* 	FindBreakPoint( const Point& rMousePos );
	void			ShowMarker( sal_Bool bShow );
	virtual void	MouseButtonDown( const MouseEvent& rMEvt );
	virtual void	Command( const CommandEvent& rCEvt );

	sal_Bool			SyncYOffset();

public:
					BreakPointWindow( Window* pParent );
					~BreakPointWindow();

	void			SetModulWindow( ModulWindow* pWin )
						{ pModulWindow = pWin; }

	void			SetMarkerPos( sal_uInt16 nLine, sal_Bool bErrorMarker = sal_False );

	void			DoScroll( long nHorzScroll, long nVertScroll );
	long&			GetCurYOffset() 		{ return nCurYOffset; }
	BreakPointList&	GetBreakPoints()		{ return aBreakPointList; }
};


class WatchTreeListBox : public SvHeaderTabListBox
{
	String aEditingRes;

protected:
	virtual sal_Bool	EditingEntry( SvLBoxEntry* pEntry, Selection& rSel  );
	virtual sal_Bool	EditedEntry( SvLBoxEntry* pEntry, const String& rNewText );

	sal_Bool 			ImplBasicEntryEdited( SvLBoxEntry* pEntry, const String& rResult );
	SbxBase*		ImplGetSBXForEntry( SvLBoxEntry* pEntry, bool& rbArrayElement );

//	virtual DragDropMode	NotifyBeginDrag( SvLBoxEntry* );
//	virtual sal_Bool	NotifyQueryDrop( SvLBoxEntry* );

//	virtual sal_Bool	NotifyMoving( SvLBoxEntry* pTarget, SvLBoxEntry* pEntry,
//						SvLBoxEntry*& rpNewParent, sal_uLong& rNewChildPos );
//	virtual sal_Bool	NotifyCopying( SvLBoxEntry* pTarget, SvLBoxEntry* pEntry,
//						SvLBoxEntry*& rpNewParent, sal_uLong& rNewChildPos );
//	sal_Bool			NotifyCopyingMoving( SvLBoxEntry* pTarget, SvLBoxEntry* pEntry,
//						SvLBoxEntry*& rpNewParent, sal_uLong& rNewChildPos, sal_Bool bMove );

public:
	WatchTreeListBox( Window* pParent, WinBits nWinBits );
	~WatchTreeListBox();

	void			RequestingChilds( SvLBoxEntry * pParent );
	void			UpdateWatches( bool bBasicStopped = false );

	using			SvTabListBox::SetTabs;
	virtual void	SetTabs();
};



class WatchWindow : public BasicDockingWindow
{
private:
	String				aWatchStr;
	ExtendedEdit		aXEdit;
	ImageButton 		aRemoveWatchButton;
	WatchTreeListBox	aTreeListBox;
	HeaderBar			aHeaderBar;

protected:
	virtual void	Resize();
	virtual void	Paint( const Rectangle& rRect );

	DECL_LINK( ButtonHdl, ImageButton * );
	DECL_LINK( TreeListHdl, SvTreeListBox * );
	DECL_LINK( implEndDragHdl, HeaderBar * );
	DECL_LINK( EditAccHdl, Accelerator * );


public:
					WatchWindow( Window* pParent );
					~WatchWindow();

	void			AddWatch( const String& rVName );
	sal_Bool			RemoveSelectedWatch();
	void			UpdateWatches( bool bBasicStopped = false );

	WatchTreeListBox&	GetWatchTreeListBox() { return aTreeListBox; }
};


class StackWindow : public BasicDockingWindow
{
private:
	SvTreeListBox	aTreeListBox;
	ImageButton 	aGotoCallButton;
	String			aStackStr;

protected:
	virtual void	Resize();
	virtual void	Paint( const Rectangle& rRect );
	DECL_LINK( ButtonHdl, ImageButton * );

public:
					StackWindow( Window* pParent );
					~StackWindow();

	void			UpdateCalls();
};


class ComplexEditorWindow : public Window
{
private:
	BreakPointWindow	aBrkWindow;
	EditorWindow		aEdtWindow;
	ScrollBar			aEWVScrollBar;

    virtual void DataChanged(DataChangedEvent const & rDCEvt);

protected:
	virtual void		Resize();
	DECL_LINK( ScrollHdl, ScrollBar * );

public:
						ComplexEditorWindow( ModulWindow* pParent );

	BreakPointWindow&	GetBrkWindow() 		{ return aBrkWindow; }
	EditorWindow&		GetEdtWindow() 		{ return aEdtWindow; }
	ScrollBar&			GetEWVScrollBar() 	{ return aEWVScrollBar; }
};


#define SYNTAX_COLOR_MAX	5

class ModulWindow: public IDEBaseWindow
{
	friend class BasicIDEShell;

private:
    StarBASICRef        xBasic;
	short				nValid;
	ComplexEditorWindow aXEditorWindow;
	BasicStatus 		aStatus;
	SbModuleRef 		xModule;
	ModulWindowLayout*	pLayout;
	String				aCurPath;
    ::rtl::OUString		m_aModule;

	DECL_LINK( BasicErrorHdl, StarBASIC * );
	long				BasicBreakHdl( StarBASIC* pBasic );

	void				CheckCompileBasic();
	sal_Bool				BasicExecute();

	void				GoOnTop();
	void				AssertValidEditEngine();

    sal_Int32           FormatAndPrint( Printer* pPrinter, sal_Int32 nPage = -1 );
	SbModuleRef 		XModule();
protected:
	virtual void	Resize();
	virtual void	GetFocus();
	virtual void	Paint( const Rectangle& );
	virtual void	Deactivating();
	virtual void	DoInit();
	virtual void	DoScroll( ScrollBar* pCurScrollBar );

public:
                    ModulWindow( ModulWindowLayout* pParent, const ScriptDocument& rDocument, String aLibName,
                        String aName, ::rtl::OUString& aModule );

					~ModulWindow();

	virtual void	ExecuteCommand( SfxRequest& rReq );
	virtual void	GetState( SfxItemSet& );
	virtual void	StoreData();
	virtual void	UpdateData();
	virtual sal_Bool 	CanClose();
	// virtual void	PrintData( Printer* pPrinter );
    // return number of pages to be printed
    virtual sal_Int32 countPages( Printer* pPrinter );
    // print page
    virtual void printPage( sal_Int32 nPage, Printer* pPrinter );
	virtual String	GetTitle();
    virtual BasicEntryDescriptor CreateEntryDescriptor();
	virtual sal_Bool	AllowUndo();
	virtual void	SetReadOnly( sal_Bool bReadOnly );
    virtual sal_Bool    IsReadOnly();

    StarBASIC*      GetBasic() { XModule(); return xBasic; }

	SbModule*		GetSbModule() { return xModule; }
    void			SetSbModule( SbModule* pModule ) { xModule = pModule; }
	String			GetSbModuleName();

	sal_Bool			CompileBasic();
	sal_Bool			BasicRun();
	sal_Bool			BasicStepOver();
	sal_Bool			BasicStepInto();
	sal_Bool			BasicStepOut();
	void			BasicStop();
	sal_Bool			BasicToggleBreakPoint();
	void			BasicToggleBreakPointEnabled();
	void			ManageBreakPoints();
	void			UpdateBreakPoint( const BreakPoint& rBrk );
	void			BasicAddWatch();
	void			BasicRemoveWatch();

	sal_Bool			LoadBasic();
	sal_Bool			SaveBasicSource();
	sal_Bool			ImportDialog();

	void			EditMacro( const String& rMacroName );

//	void			InsertFromObjectCatalog( ObjectCatalog* pObjDlg );

	sal_Bool			ToggleBreakPoint( sal_uLong nLine );

	BasicStatus&	GetBasicStatus() { return aStatus; }

	virtual sal_Bool	IsModified();
    virtual sal_Bool    IsPasteAllowed();

	void			FrameWindowMoved();
	void			ShowCursor( sal_Bool bOn );

	virtual sal_uInt16	GetSearchOptions();
	sal_uInt16			StartSearchAndReplace( const SvxSearchItem& rSearchItem, sal_Bool bFromStart = sal_False );

	virtual Window* GetLayoutWindow();

	EditorWindow&		GetEditorWindow() 		{ return aXEditorWindow.GetEdtWindow(); }
	BreakPointWindow&	GetBreakPointWindow() 	{ return aXEditorWindow.GetBrkWindow(); }
	ScrollBar&			GetEditVScrollBar() 	{ return aXEditorWindow.GetEWVScrollBar(); }
	ExtTextEngine*		GetEditEngine() 		{ return GetEditorWindow().GetEditEngine(); }
	ExtTextView*		GetEditView() 			{ return GetEditorWindow().GetEditView(); }
	BreakPointList& 	GetBreakPoints()		{ return GetBreakPointWindow().GetBreakPoints(); }
	ModulWindowLayout*	GetLayout() const 		{ return pLayout; }

	virtual void		BasicStarted();
	virtual void		BasicStopped();

    virtual ::svl::IUndoManager*
                        GetUndoManager();

    const ::rtl::OUString&	GetModule() const { return m_aModule; }
    void					SetModule( const ::rtl::OUString& aModule ) { m_aModule = aModule; }
};

class ModulWindowLayout: public Window, public utl::ConfigurationListener
{
private:

	Splitter		aVSplitter;
	Splitter		aHSplitter;

	WatchWindow 	aWatchWindow;
	StackWindow 	aStackWindow;

	sal_Bool			bVSplitted;
	sal_Bool			bHSplitted;

    ModulWindow * m_pModulWindow;

    Color m_aSyntaxColors[TT_KEYWORDS + 1];
    svtools::ColorConfig m_aColorConfig;

    ImageList m_aImagesNormal;
    ImageList m_aImagesHighContrast;

    virtual void DataChanged(DataChangedEvent const & rDCEvt);

    virtual void ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 );

    void updateSyntaxHighlighting();

    DECL_LINK( SplitHdl, Splitter * );

    void            ArrangeWindows();

protected:
	virtual void	Resize();
	virtual void	Paint( const Rectangle& rRect );

public:
					ModulWindowLayout( Window* pParent );
					~ModulWindowLayout();

	void			DockaWindow( DockingWindow* pDockingWin );
	sal_Bool			IsToBeDocked( DockingWindow* pDockingWin, const Point& rPos, Rectangle& rRect );

	void			SetModulWindow( ModulWindow* pModWin );
	ModulWindow*	GetModulWindow() const { return m_pModulWindow; }

	WatchWindow& 	GetWatchWindow()	{ return aWatchWindow; }
	StackWindow& 	GetStackWindow()	{ return aStackWindow; }

    Image getImage(sal_uInt16 nId, bool bHighContrastMode) const;

    inline Color const & getSyntaxColor(TokenTypes eType) const
    { return m_aSyntaxColors[eType]; }
};

#endif	// _BASIDE2_HXX
