/* =========================================================================== IceTech GPL Source Code Copyright (C) 2026 Justin Marshall This file is part of the IceTech GPL Source Code (?IceTech Source Code?). IceTech Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. IceTech Source Code 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 General Public License for more details. You should have received a copy of the GNU General Public License along with IceTech Source Code. If not, see . In addition, the IceTech Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the IceTech Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing Justin Marshall, justinmarshall20@gmail.com =========================================================================== */ #ifndef __DIALOGSCRIPTEDITOR_H__ #define __DIALOGSCRIPTEDITOR_H__ #pragma once class CScriptEditorCtrl; //============================================================================= // DialogScriptEditor // // Dockable Script Editor tab page. This version intentionally does not use // the old syntax-rich edit control. The text editor is a custom dark-themed // CWnd owned by DialogScriptEditor, with double-buffered manual drawing, // caret/selection handling, syntax coloring, find/replace, virtual pk5 script // opening, automatic incremental IntelliSense, signature help, and Save As/New // file support. //============================================================================= class DialogScriptEditor : public CWnd { DECLARE_DYNAMIC(DialogScriptEditor) public: DialogScriptEditor( CWnd* pParent = NULL ); virtual ~DialogScriptEditor(); BOOL Create( CWnd *pParent, UINT nID ); BOOL Create( const RECT &rect, CWnd *pParent, UINT nID ); void OpenFile( const char *fileName ); bool SaveFile( void ); bool SaveFileAs( void ); bool ReloadFile( void ); void NewFile( void ); bool HasOpenFile( void ) const; bool IsDirty( void ) const; const char * GetFileName( void ) const; void SetActive( BOOL bActive ); void FocusEditor( void ); void LayoutChildren( void ); void ShowIntelliSense( bool forced = false ); void HideIntelliSense( void ); static DialogScriptEditor *GetPrimaryEditor( void ); //{{AFX_VIRTUAL(DialogScriptEditor) virtual BOOL PreTranslateMessage( MSG* pMsg ); virtual BOOL OnCmdMsg( UINT nID, int nCode, void *pExtra, AFX_CMDHANDLERINFO *pHandlerInfo ); //}}AFX_VIRTUAL protected: //{{AFX_MSG(DialogScriptEditor) afx_msg int OnCreate( LPCREATESTRUCT lpCreateStruct ); afx_msg void OnDestroy(); afx_msg void OnActivate( UINT nState, CWnd* pWndOther, BOOL bMinimized ); afx_msg void OnMove( int x, int y ); afx_msg void OnSize( UINT nType, int cx, int cy ); afx_msg void OnSizing( UINT nSide, LPRECT lpRect ); afx_msg void OnSetFocus( CWnd *pOldWnd ); afx_msg void OnTimer( UINT_PTR nIDEvent ); afx_msg BOOL OnEraseBkgnd( CDC *pDC ); afx_msg HBRUSH OnCtlColor( CDC *pDC, CWnd *pWnd, UINT nCtlColor ); afx_msg void OnPaint(); afx_msg void OnDrawItem( int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct ); afx_msg void OnMeasureItem( int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct ); afx_msg BOOL OnToolTipNotify( UINT id, NMHDR *pNMHDR, LRESULT *pResult ); afx_msg void OnFileNew(); afx_msg void OnFileOpen(); afx_msg void OnFileSaveAs(); afx_msg void OnEditGoToLine(); afx_msg void OnEditFind(); afx_msg void OnEditFindNext(); afx_msg void OnEditReplace(); afx_msg void OnEditShowIntelliSense(); afx_msg LRESULT OnFindDialogMessage( WPARAM wParam, LPARAM lParam ); afx_msg LRESULT OnDeferredIntelliSense( WPARAM wParam, LPARAM lParam ); afx_msg LRESULT OnIntelliSenseKey( WPARAM wParam, LPARAM lParam ); afx_msg void OnEnChangeEdit( NMHDR *pNMHDR, LRESULT *pResult ); afx_msg void OnEditorSelectionChanged( NMHDR *pNMHDR, LRESULT *pResult ); afx_msg void OnIntelliSenseDblClick(); afx_msg void OnIntelliSenseSelChange(); afx_msg void OnBnClickedOk(); afx_msg void OnBnClickedCancel(); //}}AFX_MSG DECLARE_MESSAGE_MAP() private: CStatic m_titleLabel; CStatic m_pathLabel; CStatic m_statusLine; CStatic m_languageLabel; CStatic m_signatureHelp; CScriptEditorCtrl *scriptEdit; CListBox m_intellisenseList; CButton newButton; CButton openButton; CButton saveAsButton; CButton okButton; CButton cancelButton; CButton findButton; CButton replaceButton; CButton goToButton; CFont m_editorFont; CFont m_uiFont; CBrush m_backBrush; CBrush m_panelBrush; CBrush m_editBrush; CBrush m_hotBrush; static toolTip_t toolTips[]; static DialogScriptEditor *primaryEditor; HACCEL m_hAccel; CRect initialRect; CFindReplaceDialog *findDlg; CString findStr; CString replaceStr; bool matchCase; bool matchWholeWords; bool searchForward; idStr fileName; idStr loadedText; int firstLine; bool isDirty; bool internalChange; BOOL isActive; bool m_intelliSenseReady; bool m_intelliSenseCoreReady; bool m_virtualFileListReady; bool m_backgroundScanActive; int m_backgroundScanNextFile; UINT_PTR m_intelliSenseTimer; int m_indexedScriptFiles; int m_indexedSymbols; private: void InitScriptEvents( void ); void InitEditorChrome( void ); void ApplyDarkTheme( void ); void ConfigureEditorForFile( const char *fileName ); void EnsureIntelliSenseCore( void ); void EnsureVirtualScriptFileList( bool forceRebuild = false ); void StartIntelliSenseBackgroundScan( bool forceRebuild = false ); void IndexNextScriptFiles( int maxFiles ); void UpdateLiveCompletions( void ); void BuildIntelliSenseDatabase( bool forceRebuild = false ); void RebuildVirtualScriptFileList( void ); bool OpenFileFromDialog( void ); bool PromptSavePath( CString &selectedPath ); bool SaveFileAsDialog( void ); bool LoadTextFromFile( const char *path, idStr &text ) const; bool WriteTextToFile( const char *path, const char *text, int textLength ) const; bool IsNativeFilePath( const char *path ) const; void SetDirty( bool dirty ); void UpdateTitle( void ); void UpdateStatusBar( void ); void UpdateLanguageLabel( const char *extension ); void SetEditorTextNormalized( const char *text ); bool GetEditorTextNormalized( idStr &text ) const; bool ConfirmDiscardChanges( void ); bool HandleIntelliSenseKey( MSG *msg ); bool IsMemberCompletionContext( long wordStart ) const; bool IsFunctionArgumentContext( void ) const; void CompleteIntelliSense( void ); void PopulateIntelliSense( const CString &prefix, bool forced ); bool GetFunctionSignatureBeforeCaret( CString &functionName, CString &signature, int &argumentIndex ) const; void ShowFunctionParameterHint( void ); void HideFunctionParameterHint( void ); void PositionParameterHint( void ); CString GetCurrentWord( long *wordStart = NULL, long *wordEnd = NULL ) const; bool IsIdentifierChar( int ch ) const; bool StartsWithNoCase( const CString &text, const CString &prefix ) const; void InsertCompletion( const CString &completion ); void PositionIntelliSenseWindow( void ); }; DialogScriptEditor *ScriptEditorGetPrimaryEditor( void ); #endif /* !__DIALOGSCRIPTEDITOR_H__ */