Script editor now is in a seperate tab

This commit is contained in:
Justin Marshall
2026-05-18 12:58:13 -07:00
parent 1c1f828271
commit 222cccc1f0
8 changed files with 5176 additions and 646 deletions
+190 -47
View File
@@ -56,15 +56,46 @@ const int FUNCPARMTOOLTIP_WIDTH = 16;
const int FUNCPARMTOOLTIP_HEIGHT = 20;
const int FUNCPARMTOOLTIP_OFFSET = 16;
const COLORREF DEFAULT_BACK_COLOR = SRE_COLOR_WHITE;
const COLORREF INVALID_BACK_COLOR = SRE_COLOR_WHITE - 2;
const COLORREF MULTILINE_COMMENT_BACK_COLOR = SRE_COLOR_WHITE - 1;
// Dark theme colors used by the docked script editor. These are kept in the
// syntax control instead of only in DialogScriptEditor because TOM restores
// m_DefaultFont during HighlightSyntax(), so a white default font/background
// here will repaint the editor white even after EM_SETBKGNDCOLOR was applied.
const COLORREF SRE_DARK_DEFAULT_TEXT = RGB( 226, 232, 240 );
const COLORREF SRE_DARK_DEFAULT_BACK = RGB( 11, 13, 18 );
const COLORREF SRE_DARK_INVALID_BACK = RGB( 17, 24, 39 );
const COLORREF SRE_DARK_MULTILINE_COMMENT_BACK = RGB( 13, 24, 18 );
const COLORREF SRE_DARK_COMMENT = RGB( 106, 153, 85 );
const COLORREF SRE_DARK_STRING = RGB( 214, 157, 133 );
const COLORREF SRE_DARK_STRING_ALT = RGB( 220, 180, 130 );
const COLORREF SRE_DARK_LITERAL = RGB( 181, 206, 168 );
const COLORREF SRE_DARK_BRACE = RGB( 255, 203, 107 );
const COLORREF DEFAULT_BACK_COLOR = SRE_DARK_DEFAULT_BACK;
const COLORREF INVALID_BACK_COLOR = SRE_DARK_INVALID_BACK;
const COLORREF MULTILINE_COMMENT_BACK_COLOR = SRE_DARK_MULTILINE_COMMENT_BACK;
static COLORREF SREMakeReadableOnDark( COLORREF color ) {
int r = GetRValue( color );
int g = GetGValue( color );
int b = GetBValue( color );
int luma = ( r * 299 + g * 587 + b * 114 ) / 1000;
// Old .def files were authored for a white editor and often use black or
// very dark colors. Blend those toward a readable foreground for the dark UI.
if ( luma < 90 ) {
r = ( r + 120 > 255 ) ? 255 : r + 120;
g = ( g + 120 > 255 ) ? 255 : g + 120;
b = ( b + 120 > 255 ) ? 255 : b + 120;
}
return RGB( r, g, b );
}
#define IDC_LISTBOX_AUTOCOMPLETE 700
#define IDC_EDITBOX_FUNCPARMS 701
static keyWord_t defaultKeyWords[] = {
{ NULL, SRE_COLOR_BLACK, "" }
{ NULL, SRE_DARK_DEFAULT_TEXT, "" }
};
BEGIN_MESSAGE_MAP(CSyntaxRichEditCtrl, CRichEditCtrl)
@@ -93,6 +124,7 @@ CSyntaxRichEditCtrl::CSyntaxRichEditCtrl
*/
CSyntaxRichEditCtrl::CSyntaxRichEditCtrl( void ) {
m_TextDoc = NULL;
m_DefaultFont = NULL;
keyWords = defaultKeyWords;
keyWordColors = NULL;
keyWordLengths = NULL;
@@ -125,9 +157,18 @@ CSyntaxRichEditCtrl::~CSyntaxRichEditCtrl
*/
CSyntaxRichEditCtrl::~CSyntaxRichEditCtrl( void ) {
FreeKeyWordsFromFile();
delete m_pchTip;
delete m_pwchTip;
m_DefaultFont->Release();
delete [] m_pchTip;
delete [] m_pwchTip;
if ( m_DefaultFont != NULL ) {
m_DefaultFont->Release();
m_DefaultFont = NULL;
}
if ( m_TextDoc != NULL ) {
m_TextDoc->Release();
m_TextDoc = NULL;
}
}
/*
@@ -136,6 +177,10 @@ CSyntaxRichEditCtrl::InitFont
================
*/
void CSyntaxRichEditCtrl::InitFont( void ) {
if ( m_TextDoc == NULL || GetSafeHwnd() == NULL ) {
return;
}
LOGFONT lf;
CFont font;
PARAFORMAT pf;
@@ -171,27 +216,39 @@ void CSyntaxRichEditCtrl::InitFont( void ) {
defaultCharFormat.yHeight = FONT_HEIGHT * 20;
defaultCharFormat.bCharSet = ANSI_CHARSET;
defaultCharFormat.bPitchAndFamily = FIXED_PITCH | FF_MODERN;
defaultCharFormat.crTextColor = SRE_COLOR_BLACK;
defaultCharFormat.crTextColor = SRE_DARK_DEFAULT_TEXT;
defaultCharFormat.crBackColor = DEFAULT_BACK_COLOR;
defaultCharFormat.dwEffects = CFE_PROTECTED;
strcpy( defaultCharFormat.szFaceName, FONT_NAME );
defaultCharFormat.cbSize = sizeof( defaultCharFormat );
SetDefaultCharFormat( defaultCharFormat );
SendMessage( EM_SETBKGNDCOLOR, 0, DEFAULT_BACK_COLOR );
defaultColor = SRE_COLOR_BLACK;
singleLineCommentColor = SRE_COLOR_DARK_GREEN;
multiLineCommentColor = SRE_COLOR_DARK_GREEN;
stringColor[0] = stringColor[1] = SRE_COLOR_DARK_CYAN;
literalColor = SRE_COLOR_GREY;
braceHighlightColor = SRE_COLOR_RED;
defaultColor = SRE_DARK_DEFAULT_TEXT;
singleLineCommentColor = SRE_DARK_COMMENT;
multiLineCommentColor = SRE_DARK_COMMENT;
stringColor[0] = SRE_DARK_STRING;
stringColor[1] = SRE_DARK_STRING_ALT;
literalColor = SRE_DARK_LITERAL;
braceHighlightColor = SRE_DARK_BRACE;
// get the default tom::ITextFont
tom::ITextRange *irange;
tom::ITextFont *ifont;
tom::ITextRange *irange = NULL;
tom::ITextFont *ifont = NULL;
m_TextDoc->Range( 0, 0, &irange );
irange->get_Font( &ifont );
if ( m_DefaultFont != NULL ) {
m_DefaultFont->Release();
m_DefaultFont = NULL;
}
if ( m_TextDoc->Range( 0, 0, &irange ) != S_OK || irange == NULL ) {
return;
}
if ( irange->get_Font( &ifont ) != S_OK || ifont == NULL ) {
irange->Release();
return;
}
ifont->get_Duplicate( &m_DefaultFont );
@@ -235,14 +292,24 @@ CSyntaxRichEditCtrl::Init
*/
void CSyntaxRichEditCtrl::Init( void ) {
// get the Rich Edit ITextDocument to use the wonky TOM interface
IRichEditOle *ire = GetIRichEditOle();
IUnknown *iu = (IUnknown *)ire;
if ( iu == NULL || iu->QueryInterface( tom::IID_ITextDocument, (void**) &m_TextDoc ) != S_OK ) {
m_TextDoc = NULL;
if ( GetSafeHwnd() == NULL ) {
return;
}
InitFont();
// get the Rich Edit ITextDocument to use the wonky TOM interface
// WM_SIZE can arrive during CRichEditCtrl::Create before Init() runs, so
// every TOM-dependent path must tolerate m_TextDoc == NULL until this succeeds.
if ( m_TextDoc == NULL ) {
IRichEditOle *ire = GetIRichEditOle();
IUnknown *iu = (IUnknown *)ire;
if ( iu == NULL || iu->QueryInterface( tom::IID_ITextDocument, (void**) &m_TextDoc ) != S_OK ) {
m_TextDoc = NULL;
}
}
if ( m_TextDoc != NULL && m_DefaultFont == NULL ) {
InitFont();
}
InitSyntaxHighlighting();
@@ -252,14 +319,18 @@ void CSyntaxRichEditCtrl::Init( void ) {
// create auto complete list box
CRect rect( 0, 0, AUTOCOMPLETE_WIDTH, AUTOCOMPLETE_HEIGHT );
autoCompleteListBox.Create( WS_DLGFRAME | WS_VISIBLE | WS_VSCROLL | LBS_SORT | LBS_NOTIFY, rect, this, IDC_LISTBOX_AUTOCOMPLETE );
autoCompleteListBox.SetFont( GetParent()->GetFont() );
autoCompleteListBox.ShowWindow( FALSE );
if ( autoCompleteListBox.GetSafeHwnd() == NULL ) {
autoCompleteListBox.Create( WS_DLGFRAME | WS_VISIBLE | WS_VSCROLL | LBS_SORT | LBS_NOTIFY, rect, this, IDC_LISTBOX_AUTOCOMPLETE );
autoCompleteListBox.SetFont( GetParent()->GetFont() );
autoCompleteListBox.ShowWindow( FALSE );
}
// create function parameter tool tip
funcParmToolTip.Create( WS_VISIBLE | WS_BORDER, rect, this, IDC_EDITBOX_FUNCPARMS );
funcParmToolTip.SetFont( GetParent()->GetFont() );
funcParmToolTip.ShowWindow( FALSE );
if ( funcParmToolTip.GetSafeHwnd() == NULL ) {
funcParmToolTip.Create( WS_VISIBLE | WS_BORDER, rect, this, IDC_EDITBOX_FUNCPARMS );
funcParmToolTip.SetFont( GetParent()->GetFont() );
funcParmToolTip.ShowWindow( FALSE );
}
}
/*
@@ -379,7 +450,7 @@ bool CSyntaxRichEditCtrl::LoadKeyWordsFromFile( const char *fileName ) {
src.ExpectTokenString( "}" );
keyword.keyWord = Mem_CopyString( name );
keyword.color = RGB( red, green, blue );
keyword.color = SREMakeReadableOnDark( RGB( red, green, blue ) );
keyword.description = Mem_CopyString( description );
keyWordsFromFile.Append( keyword );
@@ -391,7 +462,7 @@ bool CSyntaxRichEditCtrl::LoadKeyWordsFromFile( const char *fileName ) {
}
keyword.keyWord = NULL;
keyword.color = RGB( 255, 255, 255 );
keyword.color = SRE_DARK_DEFAULT_TEXT;
keyword.description = NULL;
keyWordsFromFile.Append( keyword );
@@ -548,6 +619,10 @@ CSyntaxRichEditCtrl::SetDefaultFont
================
*/
void CSyntaxRichEditCtrl::SetDefaultFont( int startCharIndex, int endCharIndex ) {
if ( m_TextDoc == NULL || m_DefaultFont == NULL ) {
return;
}
tom::ITextRange *range;
updateSyntaxHighlighting = false;
@@ -569,6 +644,10 @@ CSyntaxRichEditCtrl::SetColor
================
*/
void CSyntaxRichEditCtrl::SetColor( int startCharIndex, int endCharIndex, COLORREF foreColor, COLORREF backColor, bool bold ) {
if ( m_TextDoc == NULL ) {
return;
}
tom::ITextRange *range;
tom::ITextFont *font;
long prop;
@@ -602,6 +681,10 @@ CSyntaxRichEditCtrl::GetForeColor
================
*/
COLORREF CSyntaxRichEditCtrl::GetForeColor( int charIndex ) const {
if ( m_TextDoc == NULL ) {
return defaultColor;
}
tom::ITextRange *range;
tom::ITextFont *font;
long foreColor;
@@ -609,7 +692,7 @@ COLORREF CSyntaxRichEditCtrl::GetForeColor( int charIndex ) const {
m_TextDoc->Range( charIndex, charIndex, &range );
range->get_Font( &font );
font->get_BackColor( &foreColor );
font->get_ForeColor( &foreColor );
font->Release();
range->Release();
@@ -623,6 +706,10 @@ CSyntaxRichEditCtrl::GetBackColor
================
*/
COLORREF CSyntaxRichEditCtrl::GetBackColor( int charIndex ) const {
if ( m_TextDoc == NULL ) {
return DEFAULT_BACK_COLOR;
}
tom::ITextRange *range;
tom::ITextFont *font;
long backColor;
@@ -646,6 +733,10 @@ CSyntaxRichEditCtrl::HighlightSyntax
================
*/
void CSyntaxRichEditCtrl::HighlightSyntax( int startCharIndex, int endCharIndex ) {
if ( m_TextDoc == NULL || m_DefaultFont == NULL || !updateSyntaxHighlighting ) {
return;
}
int c, t, line, charIndex, textLength, syntaxStart, keyWordLength, keyWordIndex;
const char *keyWord;
CHARRANGE visRange;
@@ -654,6 +745,9 @@ void CSyntaxRichEditCtrl::HighlightSyntax( int startCharIndex, int endCharIndex
// get text length
GetTextRange( 0, GetTextLength(), text );
textLength = text.GetLength();
if ( textLength <= 0 ) {
return;
}
// make sure the indexes are within bounds
if ( startCharIndex < 0 ) {
@@ -684,11 +778,11 @@ void CSyntaxRichEditCtrl::HighlightSyntax( int startCharIndex, int endCharIndex
// never update beyond the visible range
if ( startCharIndex < visRange.cpMin ) {
SetColor( startCharIndex, visRange.cpMin - 1, SRE_COLOR_BLACK, INVALID_BACK_COLOR, false );
SetColor( startCharIndex, visRange.cpMin - 1, defaultColor, INVALID_BACK_COLOR, false );
startCharIndex = visRange.cpMin;
}
if ( visRange.cpMax < endCharIndex ) {
SetColor( visRange.cpMax, endCharIndex, SRE_COLOR_BLACK, INVALID_BACK_COLOR, false );
SetColor( visRange.cpMax, endCharIndex, defaultColor, INVALID_BACK_COLOR, false );
endCharIndex = visRange.cpMax;
if ( endCharIndex >= textLength ) {
endCharIndex = textLength - 1;
@@ -843,7 +937,7 @@ void CSyntaxRichEditCtrl::UpdateVisibleRange( void ) {
long backColor;
bool update = false;
if ( !updateSyntaxHighlighting ) {
if ( !updateSyntaxHighlighting || m_TextDoc == NULL || m_DefaultFont == NULL || GetTextLength() <= 0 ) {
return;
}
@@ -917,13 +1011,26 @@ CSyntaxRichEditCtrl::GetText
================
*/
void CSyntaxRichEditCtrl::GetText( idStr &text, int startCharIndex, int endCharIndex ) const {
tom::ITextRange *range;
BSTR bstr;
if ( m_TextDoc == NULL ) {
CString fallback;
GetTextRange( startCharIndex, endCharIndex, fallback );
text = fallback;
return;
}
tom::ITextRange *range = NULL;
BSTR bstr = NULL;
USES_CONVERSION;
m_TextDoc->Range( startCharIndex, endCharIndex, &range );
if ( m_TextDoc->Range( startCharIndex, endCharIndex, &range ) != S_OK || range == NULL ) {
text.Clear();
return;
}
range->get_Text( &bstr );
text = W2A( bstr );
if ( bstr != NULL ) {
::SysFreeString( bstr );
}
range->Release();
text.StripTrailingOnce( "\r" ); // remove last carriage return which is always added to a tom::ITextRange
}
@@ -945,6 +1052,10 @@ CSyntaxRichEditCtrl::FindNext
================
*/
bool CSyntaxRichEditCtrl::FindNext( const char *find, bool matchCase, bool matchWholeWords, bool searchForward ) {
if ( m_TextDoc == NULL ) {
return false;
}
long selStart, selEnd, flags, search, length, start;
tom::ITextRange *range;
@@ -994,6 +1105,10 @@ CSyntaxRichEditCtrl::ReplaceAll
================
*/
int CSyntaxRichEditCtrl::ReplaceAll( const char *find, const char *replace, bool matchCase, bool matchWholeWords ) {
if ( m_TextDoc == NULL ) {
return 0;
}
long selStart, selEnd, flags, search, length, start;
int numReplaced;
tom::ITextRange *range;
@@ -1034,6 +1149,12 @@ CSyntaxRichEditCtrl::ReplaceText
================
*/
void CSyntaxRichEditCtrl::ReplaceText( int startCharIndex, int endCharIndex, const char *replace ) {
if ( m_TextDoc == NULL ) {
SetSel( startCharIndex, endCharIndex );
ReplaceSel( replace, TRUE );
return;
}
tom::ITextRange *range;
CComBSTR bstr( replace );
@@ -1352,6 +1473,15 @@ CSyntaxRichEditCtrl::GoToLine
void CSyntaxRichEditCtrl::GoToLine( int line ) {
int index = LineIndex( line );
if ( index < 0 ) {
index = 0;
}
if ( m_TextDoc == NULL ) {
SetSel( index, index );
RedrawWindow();
return;
}
m_TextDoc->Freeze( NULL );
@@ -1756,6 +1886,10 @@ BOOL CSyntaxRichEditCtrl::OnMouseWheel( UINT nFlags, short zDelta, CPoint pt ) {
return TRUE;
}
if ( m_TextDoc == NULL ) {
return CRichEditCtrl::OnMouseWheel( nFlags, zDelta, pt );
}
m_TextDoc->Freeze( NULL );
LineScroll( -3 * ( (int) zDelta ) / WHEEL_DELTA, 0 );
@@ -1792,6 +1926,11 @@ CSyntaxRichEditCtrl::OnSize
================
*/
void CSyntaxRichEditCtrl::OnSize( UINT nType, int cx, int cy ) {
if ( m_TextDoc == NULL ) {
CRichEditCtrl::OnSize( nType, cx, cy );
return;
}
m_TextDoc->Freeze( NULL );
CRichEditCtrl::OnSize( nType, cx, cy );
@@ -1807,6 +1946,12 @@ CSyntaxRichEditCtrl::OnVScroll
================
*/
void CSyntaxRichEditCtrl::OnVScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar ) {
if ( m_TextDoc == NULL ) {
CRichEditCtrl::OnVScroll( nSBCode, nPos, pScrollBar );
SetFocus();
return;
}
m_TextDoc->Freeze( NULL );
CRichEditCtrl::OnVScroll( nSBCode, nPos, pScrollBar );
@@ -1868,16 +2013,14 @@ CSyntaxRichEditCtrl::OnChange
void CSyntaxRichEditCtrl::OnChange() {
long selStart, selEnd;
if ( !updateSyntaxHighlighting ) {
return;
if ( updateSyntaxHighlighting && m_TextDoc != NULL && m_DefaultFont != NULL ) {
GetSel( selStart, selEnd );
selStart = Min( selStart, updateRange.cpMin );
selEnd = Max( selEnd, updateRange.cpMax );
HighlightSyntax( selStart, selEnd );
}
GetSel( selStart, selEnd );
selStart = Min( selStart, updateRange.cpMin );
selEnd = Max( selEnd, updateRange.cpMax );
HighlightSyntax( selStart, selEnd );
// send EN_CHANGE notification to parent window
NMHDR pNMHDR;
pNMHDR.hwndFrom = GetSafeHwnd();