2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 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 Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
29 #include "../../idlib/precompiled.h"
32 #include "CSyntaxRichEditCtrl.h"
34 #ifdef ID_DEBUG_MEMORY
40 // NOTE: known bug, if you directly jump to a not yet highligted page with the first line starting
41 // inside a multi-line comment then the multi-line comment is not picked up and highlighted
43 const int AUTOCOMPLETE_WIDTH = 200;
44 const int AUTOCOMPLETE_HEIGHT = 180;
45 const int AUTOCOMPLETE_OFFSET = 16;
47 const int FUNCPARMTOOLTIP_WIDTH = 16;
48 const int FUNCPARMTOOLTIP_HEIGHT = 20;
49 const int FUNCPARMTOOLTIP_OFFSET = 16;
51 const COLORREF DEFAULT_BACK_COLOR = SRE_COLOR_WHITE;
52 const COLORREF INVALID_BACK_COLOR = SRE_COLOR_WHITE - 2;
53 const COLORREF MULTILINE_COMMENT_BACK_COLOR = SRE_COLOR_WHITE - 1;
55 #define IDC_LISTBOX_AUTOCOMPLETE 700
56 #define IDC_EDITBOX_FUNCPARMS 701
58 static keyWord_t defaultKeyWords[] = {
59 { NULL, SRE_COLOR_BLACK, "" }
62 BEGIN_MESSAGE_MAP(CSyntaxRichEditCtrl, CRichEditCtrl)
63 ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify)
64 ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify)
73 ON_NOTIFY_REFLECT(EN_PROTECTED, OnProtected)
74 ON_CONTROL_REFLECT(EN_CHANGE, OnChange)
75 ON_LBN_SELCANCEL(IDC_LISTBOX_AUTOCOMPLETE, OnAutoCompleteListBoxChange)
76 ON_LBN_SELCHANGE(IDC_LISTBOX_AUTOCOMPLETE, OnAutoCompleteListBoxChange)
77 ON_LBN_DBLCLK(IDC_LISTBOX_AUTOCOMPLETE, OnAutoCompleteListBoxDblClk)
83 CSyntaxRichEditCtrl::CSyntaxRichEditCtrl
86 CSyntaxRichEditCtrl::CSyntaxRichEditCtrl( void ) {
88 keyWords = defaultKeyWords;
90 keyWordLengths = NULL;
91 caseSensitive = false;
92 allowPathNames = true;
93 keyWordAutoCompletion = true;
94 updateRange.cpMin = 0;
95 updateRange.cpMax = 0;
96 updateSyntaxHighlighting = true;
99 autoCompleteStart = -1;
100 funcParmToolTipStart = -1;
101 bracedSection[0] = -1;
102 bracedSection[1] = -1;
103 GetObjectMembers = NULL;
104 GetFunctionParms = NULL;
108 keyWordToolTip = NULL;
115 CSyntaxRichEditCtrl::~CSyntaxRichEditCtrl
118 CSyntaxRichEditCtrl::~CSyntaxRichEditCtrl( void ) {
119 FreeKeyWordsFromFile();
122 m_DefaultFont->Release();
127 CSyntaxRichEditCtrl::InitFont
130 void CSyntaxRichEditCtrl::InitFont( void ) {
137 memset( &lf, 0, sizeof( lf ) );
138 lf.lfHeight = FONT_HEIGHT * 10;
139 lf.lfWidth = FONT_WIDTH * 10;
140 lf.lfCharSet = ANSI_CHARSET;
141 lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
142 strcpy( lf.lfFaceName, FONT_NAME );
143 font.CreatePointFontIndirect( &lf );
147 // get the tab size in twips
148 logx = ::GetDeviceCaps( GetDC()->GetSafeHdc(), LOGPIXELSX );
149 tabSize = TAB_SIZE * FONT_WIDTH * 1440 / logx;
152 memset( &pf, 0, sizeof( PARAFORMAT ) );
153 pf.cbSize = sizeof( PARAFORMAT );
154 pf.dwMask = PFM_TABSTOPS;
155 for ( pf.cTabCount = 0; pf.cTabCount < MAX_TAB_STOPS; pf.cTabCount++ ) {
156 pf.rgxTabs[pf.cTabCount] = pf.cTabCount * tabSize;
161 memset( &defaultCharFormat, 0, sizeof( defaultCharFormat ) );
162 defaultCharFormat.dwMask = CFM_CHARSET | CFM_FACE | CFM_SIZE | CFM_BOLD | CFM_COLOR | CFM_PROTECTED | CFM_BACKCOLOR;
163 defaultCharFormat.yHeight = FONT_HEIGHT * 20;
164 defaultCharFormat.bCharSet = ANSI_CHARSET;
165 defaultCharFormat.bPitchAndFamily = FIXED_PITCH | FF_MODERN;
166 defaultCharFormat.crTextColor = SRE_COLOR_BLACK;
167 defaultCharFormat.crBackColor = DEFAULT_BACK_COLOR;
168 defaultCharFormat.dwEffects = CFE_PROTECTED;
169 strcpy( defaultCharFormat.szFaceName, FONT_NAME );
170 defaultCharFormat.cbSize = sizeof( defaultCharFormat );
172 SetDefaultCharFormat( defaultCharFormat );
174 defaultColor = SRE_COLOR_BLACK;
175 singleLineCommentColor = SRE_COLOR_DARK_GREEN;
176 multiLineCommentColor = SRE_COLOR_DARK_GREEN;
177 stringColor[0] = stringColor[1] = SRE_COLOR_DARK_CYAN;
178 literalColor = SRE_COLOR_GREY;
179 braceHighlightColor = SRE_COLOR_RED;
181 // get the default tom::ITextFont
182 tom::ITextRange *irange;
183 tom::ITextFont *ifont;
185 m_TextDoc->Range( 0, 0, &irange );
186 irange->get_Font( &ifont );
188 ifont->get_Duplicate( &m_DefaultFont );
196 CSyntaxRichEditCtrl::SetCharType
199 void CSyntaxRichEditCtrl::SetCharType( int first, int last, int type ) {
200 for ( int i = first; i <= last; i++ ) {
207 CSyntaxRichEditCtrl::InitSyntaxHighlighting
210 void CSyntaxRichEditCtrl::InitSyntaxHighlighting( void ) {
211 SetCharType( 0x00, 0xFF, CT_PUNCTUATION );
212 SetCharType( '\0', ' ', CT_WHITESPACE );
213 SetCharType( '/', '/', CT_COMMENT );
214 SetCharType( '\"', '\"', CT_STRING );
215 SetCharType( '\'', '\'', CT_LITERAL );
216 SetCharType( 'a', 'z', CT_NAME );
217 SetCharType( 'A', 'Z', CT_NAME );
218 SetCharType( '_', '_', CT_NAME );
219 SetCharType( '#', '#', CT_NAME );
220 SetCharType( '0', '9', CT_NUMBER );
225 CSyntaxRichEditCtrl::Init
228 void CSyntaxRichEditCtrl::Init( void ) {
230 // get the Rich Edit ITextDocument to use the wonky TOM interface
231 IRichEditOle *ire = GetIRichEditOle();
232 IUnknown *iu = (IUnknown *)ire;
233 if ( iu == NULL || iu->QueryInterface( tom::IID_ITextDocument, (void**) &m_TextDoc ) != S_OK ) {
239 InitSyntaxHighlighting();
241 SetEventMask( GetEventMask() | ENM_CHANGE | ENM_KEYEVENTS | ENM_MOUSEEVENTS | ENM_PROTECTED ); // ENM_SCROLLEVENTS
243 EnableToolTips( TRUE );
245 // create auto complete list box
246 CRect rect( 0, 0, AUTOCOMPLETE_WIDTH, AUTOCOMPLETE_HEIGHT );
247 autoCompleteListBox.Create( WS_DLGFRAME | WS_VISIBLE | WS_VSCROLL | LBS_SORT | LBS_NOTIFY, rect, this, IDC_LISTBOX_AUTOCOMPLETE );
248 autoCompleteListBox.SetFont( GetParent()->GetFont() );
249 autoCompleteListBox.ShowWindow( FALSE );
251 // create function parameter tool tip
252 funcParmToolTip.Create( WS_VISIBLE | WS_BORDER, rect, this, IDC_EDITBOX_FUNCPARMS );
253 funcParmToolTip.SetFont( GetParent()->GetFont() );
254 funcParmToolTip.ShowWindow( FALSE );
259 CSyntaxRichEditCtrl::FindKeyWord
262 ID_INLINE int CSyntaxRichEditCtrl::FindKeyWord( const char *keyWord, int length ) const {
265 if ( caseSensitive ) {
266 hash = idStr::Hash( keyWord, length );
268 hash = idStr::IHash( keyWord, length );
270 for ( i = keyWordHash.First( hash ); i != -1; i = keyWordHash.Next( i ) ) {
271 if ( length != keyWordLengths[i] ) {
274 if ( caseSensitive ) {
275 if ( idStr::Cmpn( keyWords[i].keyWord, keyWord, length ) != 0 ) {
279 if ( idStr::Icmpn( keyWords[i].keyWord, keyWord, length ) != 0 ) {
290 CSyntaxRichEditCtrl::SetKeyWords
293 void CSyntaxRichEditCtrl::SetKeyWords( const keyWord_t kws[] ) {
294 int i, numKeyWords, hash;
298 for ( numKeyWords = 0; keyWords[numKeyWords].keyWord; numKeyWords++ ) {
301 delete keyWordColors;
302 keyWordColors = new COLORREF[numKeyWords];
304 for ( i = 0; i < numKeyWords; i++ ) {
305 keyWordColors[i] = keyWords[i].color;
308 delete keyWordLengths;
309 keyWordLengths = new int[numKeyWords];
311 for ( i = 0; i < numKeyWords; i++ ) {
312 keyWordLengths[i] = idStr::Length( keyWords[i].keyWord );
315 keyWordHash.Clear( 1024, 1024 );
316 for ( i = 0; i < numKeyWords; i++ ) {
317 if ( caseSensitive ) {
318 hash = idStr::Hash( keyWords[i].keyWord, keyWordLengths[i] );
320 hash = idStr::IHash( keyWords[i].keyWord, keyWordLengths[i] );
322 keyWordHash.Add( hash, i );
328 CSyntaxRichEditCtrl::LoadKeyWordsFromFile
331 bool CSyntaxRichEditCtrl::LoadKeyWordsFromFile( const char *fileName ) {
333 idToken token, name, description;
334 byte red, green, blue;
337 if ( !src.LoadFile( fileName ) ) {
341 FreeKeyWordsFromFile();
343 while( src.ReadToken( &token ) ) {
344 if ( token.Icmp( "keywords" ) == 0 ) {
345 src.ExpectTokenString( "{" );
346 while( src.ReadToken( &token ) ) {
347 if ( token == "}" ) {
350 if ( token == "{" ) {
353 src.ExpectTokenType( TT_STRING, 0, &name );
354 src.ExpectTokenString( "," );
357 src.ExpectTokenString( "(" );
358 src.ExpectTokenType( TT_NUMBER, TT_INTEGER, &token );
359 red = token.GetIntValue();
360 src.ExpectTokenString( "," );
361 src.ExpectTokenType( TT_NUMBER, TT_INTEGER, &token );
362 green = token.GetIntValue();
363 src.ExpectTokenString( "," );
364 src.ExpectTokenType( TT_NUMBER, TT_INTEGER, &token );
365 blue = token.GetIntValue();
366 src.ExpectTokenString( ")" );
367 src.ExpectTokenString( "," );
370 src.ExpectTokenType( TT_STRING, 0, &description );
371 src.ExpectTokenString( "}" );
373 keyword.keyWord = Mem_CopyString( name );
374 keyword.color = RGB( red, green, blue );
375 keyword.description = Mem_CopyString( description );
377 keyWordsFromFile.Append( keyword );
381 src.SkipBracedSection();
385 keyword.keyWord = NULL;
386 keyword.color = RGB( 255, 255, 255 );
387 keyword.description = NULL;
388 keyWordsFromFile.Append( keyword );
390 SetKeyWords( keyWordsFromFile.Ptr() );
397 CSyntaxRichEditCtrl::FreeKeyWordsFromFile
400 void CSyntaxRichEditCtrl::FreeKeyWordsFromFile( void ) {
401 for ( int i = 0; i < keyWordsFromFile.Num(); i++ ) {
402 Mem_Free( const_cast<char *>( keyWordsFromFile[i].keyWord ) );
403 Mem_Free( const_cast<char *>( keyWordsFromFile[i].description ) );
405 keyWordsFromFile.Clear();
410 CSyntaxRichEditCtrl::SetDefaultColor
413 void CSyntaxRichEditCtrl::SetDefaultColor( const COLORREF color ) {
414 defaultColor = color;
419 CSyntaxRichEditCtrl::SetCommentColor
422 void CSyntaxRichEditCtrl::SetCommentColor( const COLORREF color ) {
423 singleLineCommentColor = color;
424 multiLineCommentColor = color;
429 CSyntaxRichEditCtrl::SetStringColor
432 void CSyntaxRichEditCtrl::SetStringColor( const COLORREF color, const COLORREF altColor ) {
433 stringColor[0] = color;
434 if ( altColor == -1 ) {
435 stringColor[1] = color;
437 stringColor[1] = altColor;
443 CSyntaxRichEditCtrl::SetLiteralColor
446 void CSyntaxRichEditCtrl::SetLiteralColor( const COLORREF color ) {
447 literalColor = color;
452 CSyntaxRichEditCtrl::SetObjectMemberCallback
455 void CSyntaxRichEditCtrl::SetObjectMemberCallback( objectMemberCallback_t callback ) {
456 GetObjectMembers = callback;
461 CSyntaxRichEditCtrl::SetFunctionParmCallback
464 void CSyntaxRichEditCtrl::SetFunctionParmCallback( toolTipCallback_t callback ) {
465 GetFunctionParms = callback;
470 CSyntaxRichEditCtrl::SetToolTipCallback
473 void CSyntaxRichEditCtrl::SetToolTipCallback( toolTipCallback_t callback ) {
474 GetToolTip = callback;
479 CSyntaxRichEditCtrl::SetCaseSensitive
482 void CSyntaxRichEditCtrl::SetCaseSensitive( bool caseSensitive ) {
483 this->caseSensitive = caseSensitive;
488 CSyntaxRichEditCtrl::AllowPathNames
491 void CSyntaxRichEditCtrl::AllowPathNames( bool allow ) {
492 allowPathNames = allow;
497 CSyntaxRichEditCtrl::EnableKeyWordAutoCompletion
500 void CSyntaxRichEditCtrl::EnableKeyWordAutoCompletion( bool enable ) {
501 keyWordAutoCompletion = enable;
506 CSyntaxRichEditCtrl::GetVisibleRange
509 CHARRANGE CSyntaxRichEditCtrl::GetVisibleRange( void ) const {
511 int firstLine, lastLine;
514 firstLine = GetFirstVisibleLine();
515 GetClientRect( &rectArea );
516 lastLine = firstLine + ( rectArea.bottom / ( defaultCharFormat.yHeight / 20 ) );
518 if ( lastLine >= GetLineCount() ) {
519 lastLine = GetLineCount() - 1;
521 range.cpMin = LineIndex( firstLine );
522 if ( range.cpMin < 0 ) {
525 range.cpMax = LineIndex( lastLine );
526 if ( range.cpMax == -1 ) {
527 range.cpMax = range.cpMin + LineLength( range.cpMin );
529 range.cpMax += LineLength( range.cpMax );
531 if ( range.cpMax >= GetTextLength() ) {
532 range.cpMax = GetTextLength() - 1;
539 CSyntaxRichEditCtrl::SetDefaultFont
542 void CSyntaxRichEditCtrl::SetDefaultFont( int startCharIndex, int endCharIndex ) {
543 tom::ITextRange *range;
545 updateSyntaxHighlighting = false;
547 m_TextDoc->Range( startCharIndex, endCharIndex, &range );
549 m_TextDoc->Undo( tom::tomSuspend, NULL );
550 range->put_Font( m_DefaultFont );
551 m_TextDoc->Undo( tom::tomResume, NULL );
555 updateSyntaxHighlighting = true;
560 CSyntaxRichEditCtrl::SetColor
563 void CSyntaxRichEditCtrl::SetColor( int startCharIndex, int endCharIndex, COLORREF foreColor, COLORREF backColor, bool bold ) {
564 tom::ITextRange *range;
565 tom::ITextFont *font;
568 updateSyntaxHighlighting = false;
570 m_TextDoc->Range( startCharIndex, endCharIndex, &range );
571 range->get_Font( &font );
573 m_TextDoc->Undo( tom::tomSuspend, &prop );
574 font->put_ForeColor( foreColor );
575 m_TextDoc->Undo( tom::tomResume, &prop );
577 m_TextDoc->Undo( tom::tomSuspend, &prop );
578 font->put_BackColor( backColor );
579 m_TextDoc->Undo( tom::tomResume, &prop );
581 m_TextDoc->Undo( tom::tomSuspend, &prop );
582 font->put_Bold( bold ? tom::tomTrue : tom::tomFalse );
583 m_TextDoc->Undo( tom::tomResume, &prop );
588 updateSyntaxHighlighting = true;
593 CSyntaxRichEditCtrl::GetForeColor
596 COLORREF CSyntaxRichEditCtrl::GetForeColor( int charIndex ) const {
597 tom::ITextRange *range;
598 tom::ITextFont *font;
601 m_TextDoc->Range( charIndex, charIndex, &range );
602 range->get_Font( &font );
604 font->get_BackColor( &foreColor );
614 CSyntaxRichEditCtrl::GetBackColor
617 COLORREF CSyntaxRichEditCtrl::GetBackColor( int charIndex ) const {
618 tom::ITextRange *range;
619 tom::ITextFont *font;
622 m_TextDoc->Range( charIndex, charIndex, &range );
623 range->get_Font( &font );
625 font->get_BackColor( &backColor );
635 CSyntaxRichEditCtrl::HighlightSyntax
637 Update the syntax highlighting for the given character range.
640 void CSyntaxRichEditCtrl::HighlightSyntax( int startCharIndex, int endCharIndex ) {
641 int c, t, line, charIndex, textLength, syntaxStart, keyWordLength, keyWordIndex;
647 GetTextRange( 0, GetTextLength(), text );
648 textLength = text.GetLength();
650 // make sure the indexes are within bounds
651 if ( startCharIndex < 0 ) {
654 if ( endCharIndex < 0 ) {
655 endCharIndex = textLength - 1;
656 } else if ( endCharIndex >= textLength ) {
657 endCharIndex = textLength - 1;
660 // move the start index to the beginning of the line
661 for ( ; startCharIndex > 0; startCharIndex-- ) {
662 if ( idStr::CharIsNewLine( text[startCharIndex-1] ) ) {
667 // move the end index to the end of the line
668 for ( ; endCharIndex < textLength - 1; endCharIndex++ ) {
669 if ( idStr::CharIsNewLine( text[endCharIndex+1] ) ) {
674 // get the visible char range
675 visRange = GetVisibleRange();
677 // never update beyond the visible range
678 if ( startCharIndex < visRange.cpMin ) {
679 SetColor( startCharIndex, visRange.cpMin - 1, SRE_COLOR_BLACK, INVALID_BACK_COLOR, false );
680 startCharIndex = visRange.cpMin;
682 if ( visRange.cpMax < endCharIndex ) {
683 SetColor( visRange.cpMax, endCharIndex, SRE_COLOR_BLACK, INVALID_BACK_COLOR, false );
684 endCharIndex = visRange.cpMax;
685 if ( endCharIndex >= textLength ) {
686 endCharIndex = textLength - 1;
690 // test if the start index is inside a multi-line comment
691 if ( startCharIndex > 0 ) {
692 // multi-line comments have a slightly different background color
693 if ( GetBackColor( startCharIndex-1 ) == MULTILINE_COMMENT_BACK_COLOR ) {
694 for( ; startCharIndex > 0; startCharIndex-- ) {
695 if ( text[startCharIndex] == '/' && text[startCharIndex+1] == '*' ) {
702 // test if the end index is inside a multi-line comment
703 if ( endCharIndex < textLength - 1 ) {
704 // multi-line comments have a slightly different background color
705 if ( GetBackColor( endCharIndex+1 ) == MULTILINE_COMMENT_BACK_COLOR ) {
706 for( endCharIndex++; endCharIndex < textLength - 1; endCharIndex++ ) {
707 if ( text[endCharIndex-1] == '*' && text[endCharIndex] == '/' ) {
715 stringColorLine = -1;
716 stringColorIndex = 0;
718 // set the default color
719 SetDefaultFont( startCharIndex, endCharIndex + 1 );
721 // syntax based colors
722 for( charIndex = startCharIndex; charIndex <= endCharIndex; charIndex++ ) {
724 t = charType[text[charIndex]];
726 case CT_WHITESPACE: {
727 if ( idStr::CharIsNewLine( text[charIndex] ) ) {
733 c = text[charIndex+1];
735 // single line comment
736 syntaxStart = charIndex;
737 for ( charIndex += 2; charIndex < textLength; charIndex++ ) {
738 if ( idStr::CharIsNewLine( text[charIndex] ) ) {
742 SetColor( syntaxStart, charIndex + 1, singleLineCommentColor, DEFAULT_BACK_COLOR, false );
743 } else if ( c == '*' ) {
744 // multi-line comment
745 syntaxStart = charIndex;
746 for ( charIndex += 2; charIndex < textLength; charIndex++ ) {
747 if ( text[charIndex] == '*' && text[charIndex+1] == '/' ) {
752 SetColor( syntaxStart, charIndex + 1, multiLineCommentColor, MULTILINE_COMMENT_BACK_COLOR, false );
757 if ( line != stringColorLine ) {
758 stringColorLine = line;
759 stringColorIndex = 0;
761 syntaxStart = charIndex;
762 for ( charIndex++; charIndex < textLength; charIndex++ ) {
764 if ( charType[c] == CT_STRING && text[charIndex-1] != '\\' ) {
767 if ( idStr::CharIsNewLine( c ) ) {
772 SetColor( syntaxStart, charIndex + 1, stringColor[stringColorIndex], DEFAULT_BACK_COLOR, false );
773 stringColorIndex ^= 1;
777 syntaxStart = charIndex;
778 for ( charIndex++; charIndex < textLength; charIndex++ ) {
780 if ( charType[c] == CT_LITERAL && text[charIndex-1] != '\\' ) {
783 if ( idStr::CharIsNewLine( c ) ) {
788 SetColor( syntaxStart, charIndex + 1, literalColor, DEFAULT_BACK_COLOR, false );
795 syntaxStart = charIndex;
796 keyWord = ((const char *)text) + charIndex;
797 for ( charIndex++; charIndex < textLength; charIndex++ ) {
800 if ( t != CT_NAME && t != CT_NUMBER ) {
802 if ( !allowPathNames || ( c != '/' && c != '\\' && c != '.' ) ) {
807 keyWordLength = charIndex - syntaxStart;
808 keyWordIndex = FindKeyWord( keyWord, keyWordLength );
809 if ( keyWordIndex != -1 ) {
810 SetColor( syntaxStart, syntaxStart + keyWordLength, keyWordColors[keyWordIndex], DEFAULT_BACK_COLOR, false );
814 case CT_PUNCTUATION: {
820 // show braced section
826 CSyntaxRichEditCtrl::UpdateVisibleRange
828 Updates the visible character range if it is not yet properly highlighted.
831 void CSyntaxRichEditCtrl::UpdateVisibleRange( void ) {
833 tom::ITextRange *range;
834 tom::ITextFont *font;
838 if ( !updateSyntaxHighlighting ) {
842 visRange = GetVisibleRange();
844 m_TextDoc->Range( visRange.cpMin, visRange.cpMax, &range );
845 range->get_End( &visRange.cpMax );
847 range->get_Font( &font );
849 range->SetRange( visRange.cpMin, visRange.cpMin );
851 range->get_Start( &visRange.cpMin );
852 if ( visRange.cpMin >= visRange.cpMax ) {
855 font->get_BackColor( &backColor );
856 if ( backColor == INVALID_BACK_COLOR ) {
860 if ( range->Move( tom::tomCharFormat, 1, NULL ) != S_OK ) {
869 HighlightSyntax( visRange.cpMin, visRange.cpMax - 1 );
875 CSyntaxRichEditCtrl::GetCursorPos
878 void CSyntaxRichEditCtrl::GetCursorPos( int &line, int &column, int &character ) const {
880 char buffer[MAX_STRING_CHARS];
882 GetSel( start, end );
883 line = LineFromChar( start );
884 start -= LineIndex( line );
885 GetLine( line, buffer, sizeof( buffer ) );
886 for ( column = 1, character = 0; character < start; character++ ) {
887 if ( idStr::CharIsTab( buffer[character] ) ) {
889 column -= column % TAB_SIZE;
899 CSyntaxRichEditCtrl::GetText
902 void CSyntaxRichEditCtrl::GetText( idStr &text ) const {
903 GetText( text, 0, GetTextLength() );
908 CSyntaxRichEditCtrl::GetText
911 void CSyntaxRichEditCtrl::GetText( idStr &text, int startCharIndex, int endCharIndex ) const {
912 tom::ITextRange *range;
916 m_TextDoc->Range( startCharIndex, endCharIndex, &range );
917 range->get_Text( &bstr );
920 text.StripTrailingOnce( "\r" ); // remove last carriage return which is always added to a tom::ITextRange
925 CSyntaxRichEditCtrl::SetText
928 void CSyntaxRichEditCtrl::SetText( const char *text ) {
930 ReplaceSel( text, FALSE );
936 CSyntaxRichEditCtrl::FindNext
939 bool CSyntaxRichEditCtrl::FindNext( const char *find, bool matchCase, bool matchWholeWords, bool searchForward ) {
940 long selStart, selEnd, flags, search, length, start;
941 tom::ITextRange *range;
943 if ( find[0] == '\0' ) {
947 GetSel( selStart, selEnd );
950 flags |= matchCase ? tom::tomMatchCase : 0;
951 flags |= matchWholeWords ? tom::tomMatchWord : 0;
953 if ( searchForward ) {
954 m_TextDoc->Range( selEnd, GetTextLength(), &range );
955 search = GetTextLength() - selEnd;
957 m_TextDoc->Range( 0, selStart, &range );
961 if ( range->FindShit( A2BSTR(find), search, flags, &length ) == S_OK ) {
963 m_TextDoc->Freeze( NULL );
965 range->get_Start( &start );
968 SetSel( start, start + length );
970 int line = Max( (int) LineFromChar( start ) - 5, 0 );
971 LineScroll( line - GetFirstVisibleLine(), 0 );
973 UpdateVisibleRange();
975 m_TextDoc->Unfreeze( NULL );
985 CSyntaxRichEditCtrl::ReplaceAll
988 int CSyntaxRichEditCtrl::ReplaceAll( const char *find, const char *replace, bool matchCase, bool matchWholeWords ) {
989 long selStart, selEnd, flags, search, length, start;
991 tom::ITextRange *range;
992 CComBSTR bstr( find );
994 if ( find[0] == '\0' ) {
998 m_TextDoc->Freeze( NULL );
1000 GetSel( selStart, selEnd );
1003 flags |= matchCase ? tom::tomMatchCase : 0;
1004 flags |= matchWholeWords ? tom::tomMatchWord : 0;
1006 m_TextDoc->Range( 0, GetTextLength(), &range );
1007 search = GetTextLength();
1010 while( range->FindShit( bstr, search, flags, &length ) == S_OK ) {
1011 range->get_Start( &start );
1012 ReplaceText( start, start + length, replace );
1018 m_TextDoc->Unfreeze( NULL );
1025 CSyntaxRichEditCtrl::ReplaceText
1028 void CSyntaxRichEditCtrl::ReplaceText( int startCharIndex, int endCharIndex, const char *replace ) {
1029 tom::ITextRange *range;
1030 CComBSTR bstr( replace );
1032 m_TextDoc->Range( startCharIndex, endCharIndex, &range );
1033 range->put_Text( bstr );
1039 CSyntaxRichEditCtrl::AutoCompleteInsertText
1042 void CSyntaxRichEditCtrl::AutoCompleteInsertText( void ) {
1043 long selStart, selEnd;
1046 index = autoCompleteListBox.GetCurSel();
1049 autoCompleteListBox.GetText( index, text );
1050 GetSel( selStart, selEnd );
1051 selStart = autoCompleteStart;
1052 SetSel( selStart, selEnd );
1053 ReplaceSel( text, TRUE );
1059 CSyntaxRichEditCtrl::AutoCompleteUpdate
1062 void CSyntaxRichEditCtrl::AutoCompleteUpdate( void ) {
1063 long selStart, selEnd;
1067 GetSel( selStart, selEnd );
1068 GetText( text, autoCompleteStart, selStart );
1069 index = autoCompleteListBox.FindString( -1, text );
1070 if ( index >= 0 && index < autoCompleteListBox.GetCount() ) {
1071 autoCompleteListBox.SetCurSel( index );
1077 CSyntaxRichEditCtrl::AutoCompleteShow
1080 void CSyntaxRichEditCtrl::AutoCompleteShow( int charIndex ) {
1084 autoCompleteStart = charIndex;
1085 point = PosFromChar( charIndex );
1086 GetClientRect( rect );
1087 if ( point.y < rect.bottom - AUTOCOMPLETE_OFFSET - AUTOCOMPLETE_HEIGHT ) {
1088 rect.top = point.y + AUTOCOMPLETE_OFFSET;
1089 rect.bottom = point.y + AUTOCOMPLETE_OFFSET + AUTOCOMPLETE_HEIGHT;
1091 rect.top = point.y - AUTOCOMPLETE_HEIGHT;
1092 rect.bottom = point.y;
1094 rect.left = point.x;
1095 rect.right = point.x + AUTOCOMPLETE_WIDTH;
1096 autoCompleteListBox.MoveWindow( &rect );
1097 autoCompleteListBox.ShowWindow( TRUE );
1098 AutoCompleteUpdate();
1103 CSyntaxRichEditCtrl::AutoCompleteHide
1106 void CSyntaxRichEditCtrl::AutoCompleteHide( void ) {
1107 autoCompleteStart = -1;
1108 autoCompleteListBox.ShowWindow( FALSE );
1113 CSyntaxRichEditCtrl::ToolTipShow
1116 void CSyntaxRichEditCtrl::ToolTipShow( int charIndex, const char *string ) {
1117 CPoint point, p1, p2;
1120 funcParmToolTipStart = charIndex;
1121 funcParmToolTip.SetWindowText( string );
1122 p1 = funcParmToolTip.PosFromChar( 0 );
1123 p2 = funcParmToolTip.PosFromChar( strlen( string ) - 1 );
1124 point = PosFromChar( charIndex );
1125 GetClientRect( rect );
1126 if ( point.y < rect.bottom - FUNCPARMTOOLTIP_OFFSET - FUNCPARMTOOLTIP_HEIGHT ) {
1127 rect.top = point.y + FUNCPARMTOOLTIP_OFFSET;
1128 rect.bottom = point.y + FUNCPARMTOOLTIP_OFFSET + FUNCPARMTOOLTIP_HEIGHT;
1130 rect.top = point.y - FUNCPARMTOOLTIP_HEIGHT;
1131 rect.bottom = point.y;
1133 rect.left = point.x;
1134 rect.right = point.x + FUNCPARMTOOLTIP_WIDTH + p2.x - p1.x;
1135 funcParmToolTip.MoveWindow( &rect );
1136 funcParmToolTip.ShowWindow( TRUE );
1141 CSyntaxRichEditCtrl::ToolTipHide
1144 void CSyntaxRichEditCtrl::ToolTipHide( void ) {
1145 funcParmToolTipStart = -1;
1146 funcParmToolTip.ShowWindow( FALSE );
1151 CSyntaxRichEditCtrl::BracedSectionStart
1154 bool CSyntaxRichEditCtrl::BracedSectionStart( char braceStartChar, char braceEndChar ) {
1155 long selStart, selEnd;
1159 GetSel( selStart, selEnd );
1160 GetText( text, 0, GetTextLength() );
1162 for ( brace = 1, i = selStart; i < text.Length(); i++ ) {
1163 if ( text[i] == braceStartChar ) {
1165 } else if ( text[i] == braceEndChar ) {
1173 bracedSection[0] = selStart - 1;
1174 bracedSection[1] = i;
1175 BracedSectionShow();
1178 return ( brace == 0 );
1183 CSyntaxRichEditCtrl::BracedSectionEnd
1186 bool CSyntaxRichEditCtrl::BracedSectionEnd( char braceStartChar, char braceEndChar ) {
1187 long selStart, selEnd;
1191 GetSel( selStart, selEnd );
1192 GetText( text, 0, GetTextLength() );
1194 for ( brace = 1, i = Min( selStart-2, (long)text.Length()-1 ); i >= 0; i-- ) {
1195 if ( text[i] == braceStartChar ) {
1200 } else if ( text[i] == braceEndChar ) {
1206 bracedSection[0] = i;
1207 bracedSection[1] = selStart - 1;
1208 BracedSectionAdjustEndTabs();
1209 BracedSectionShow();
1212 return ( brace == 0 );
1217 CSyntaxRichEditCtrl::BracedSectionAdjustEndTabs
1220 void CSyntaxRichEditCtrl::BracedSectionAdjustEndTabs( void ) {
1221 int line, lineIndex, length, column, numTabs, i;
1225 line = LineFromChar( bracedSection[0] );
1226 length = GetLine( line, buffer, sizeof( buffer ) );
1227 for ( numTabs = 0; numTabs < length; numTabs++ ) {
1228 if ( !idStr::CharIsTab( buffer[numTabs] ) ) {
1231 text.Append( '\t' );
1234 line = LineFromChar( bracedSection[1] );
1235 lineIndex = LineIndex( line );
1236 length = GetLine( line, buffer, sizeof( buffer ) );
1237 column = bracedSection[1] - lineIndex;
1238 for ( i = 0; i < column; i++ ) {
1239 if ( charType[buffer[i]] != CT_WHITESPACE ) {
1244 ReplaceText( lineIndex, lineIndex + column, text );
1246 bracedSection[1] += numTabs - column;
1247 SetSel( bracedSection[1]+1, bracedSection[1]+1 );
1252 CSyntaxRichEditCtrl::BracedSectionShow
1255 void CSyntaxRichEditCtrl::BracedSectionShow( void ) {
1256 for ( int i = 0; i < 2; i++ ) {
1257 if ( bracedSection[i] >= 0 ) {
1258 SetColor( bracedSection[i], bracedSection[i] + 1, braceHighlightColor, DEFAULT_BACK_COLOR, true );
1265 CSyntaxRichEditCtrl::BracedSectionHide
1268 void CSyntaxRichEditCtrl::BracedSectionHide( void ) {
1269 for ( int i = 0; i < 2; i++ ) {
1270 if ( bracedSection[i] >= 0 ) {
1271 SetColor( bracedSection[i], bracedSection[i] + 1, defaultColor, DEFAULT_BACK_COLOR, false );
1272 bracedSection[i] = -1;
1279 CSyntaxRichEditCtrl::GetNameBeforeCurrentSelection
1282 bool CSyntaxRichEditCtrl::GetNameBeforeCurrentSelection( CString &name, int &charIndex ) const {
1283 long selStart, selEnd;
1284 int line, column, length;
1287 GetSel( selStart, selEnd );
1288 charIndex = selStart;
1289 line = LineFromChar( selStart );
1290 length = GetLine( line, buffer, sizeof( buffer ) );
1291 column = selStart - LineIndex( line ) - 1;
1293 buffer[column--] = '\0';
1294 } while( charType[buffer[column]] == CT_WHITESPACE );
1295 for ( length = 0; length < column; length++ ) {
1296 if ( charType[buffer[column-length-1]] != CT_NAME ) {
1301 name = buffer + column - length;
1309 CSyntaxRichEditCtrl::GetNameForMousePosition
1312 bool CSyntaxRichEditCtrl::GetNameForMousePosition( idStr &name ) const {
1313 int charIndex, startCharIndex, endCharIndex, type;
1316 charIndex = CharFromPos( mousePoint );
1318 for ( startCharIndex = charIndex; startCharIndex > 0; startCharIndex-- ) {
1319 GetText( text, startCharIndex - 1, startCharIndex );
1320 type = charType[text[0]];
1321 if ( type != CT_NAME && type != CT_NUMBER ) {
1326 for ( endCharIndex = charIndex; endCharIndex < GetTextLength(); endCharIndex++ ) {
1327 GetText( text, endCharIndex, endCharIndex + 1 );
1328 type = charType[text[0]];
1329 if ( type != CT_NAME && type != CT_NUMBER ) {
1334 GetText( name, startCharIndex, endCharIndex );
1336 return ( endCharIndex > startCharIndex );
1341 CSyntaxRichEditCtrl::GoToLine
1344 void CSyntaxRichEditCtrl::GoToLine( int line ) {
1346 int index = LineIndex( line );
1348 m_TextDoc->Freeze( NULL );
1350 SetSel( index, index );
1352 m_TextDoc->Unfreeze( NULL );
1354 UpdateVisibleRange();
1361 CSyntaxRichEditCtrl::OnToolHitTest
1364 int CSyntaxRichEditCtrl::OnToolHitTest( CPoint point, TOOLINFO* pTI ) const {
1365 CRichEditCtrl::OnToolHitTest( point, pTI );
1367 pTI->hwnd = GetSafeHwnd();
1368 pTI->uId = (UINT_PTR)GetSafeHwnd();
1369 pTI->uFlags |= TTF_IDISHWND;
1370 pTI->lpszText = LPSTR_TEXTCALLBACK;
1371 pTI->rect = CRect( point, point );
1372 pTI->rect.right += 100;
1373 pTI->rect.bottom += 20;
1379 CSyntaxRichEditCtrl::OnToolTipNotify
1382 BOOL CSyntaxRichEditCtrl::OnToolTipNotify( UINT id, NMHDR *pNMHDR, LRESULT *pResult ) {
1383 TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
1384 TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
1390 if ( GetNameForMousePosition( name ) ) {
1393 if ( GetToolTip == NULL || !GetToolTip( name, toolTip ) ) {
1395 int keyWordIndex = FindKeyWord( name, name.Length() );
1397 if ( keyWordIndex != -1 && keyWords[keyWordIndex].description[0] != '\0' ) {
1398 toolTip = keyWords[keyWordIndex].description;
1400 toolTip = name.c_str();
1404 AFX_MODULE_THREAD_STATE *state = AfxGetModuleThreadState();
1406 // set max tool tip width to enable multi-line tool tips using "\r\n" for line breaks
1407 state->m_pToolTip->SetMaxTipWidth( 500 );
1409 // set the number of milliseconds after which the tool tip automatically disappears
1410 state->m_pToolTip->SetDelayTime( TTDT_AUTOPOP, 5000 + toolTip.GetLength() * 50 );
1413 if( pNMHDR->code == TTN_NEEDTEXTA ) {
1415 m_pchTip = new TCHAR[toolTip.GetLength() + 2];
1416 lstrcpyn( m_pchTip, toolTip, toolTip.GetLength() + 1 );
1417 pTTTW->lpszText = (WCHAR*)m_pchTip;
1420 m_pwchTip = new WCHAR[toolTip.GetLength() + 2];
1421 _mbstowcsz( m_pwchTip, toolTip, toolTip.GetLength() + 1 );
1422 pTTTW->lpszText = (WCHAR*)m_pwchTip;
1425 if( pNMHDR->code == TTN_NEEDTEXTA ) {
1427 m_pchTip = new TCHAR[toolTip.GetLength() + 2];
1428 _wcstombsz( m_pchTip, toolTip, toolTip.GetLength() + 1 );
1429 pTTTA->lpszText = (LPTSTR)m_pchTip;
1432 m_pwchTip = new WCHAR[toolTip.GetLength() + 2];
1433 lstrcpyn( m_pwchTip, toolTip, toolTip.GetLength() + 1 );
1434 pTTTA->lpszText = (LPTSTR) m_pwchTip;
1445 CSyntaxRichEditCtrl::OnGetDlgCode
1448 UINT CSyntaxRichEditCtrl::OnGetDlgCode() {
1449 // get all keys, including tabs
1450 return DLGC_WANTALLKEYS | DLGC_WANTARROWS | DLGC_WANTCHARS | DLGC_WANTMESSAGE | DLGC_WANTTAB;
1455 CSyntaxRichEditCtrl::OnKeyDown
1458 void CSyntaxRichEditCtrl::OnKeyDown( UINT nKey, UINT nRepCnt, UINT nFlags ) {
1460 if ( m_TextDoc == NULL ) {
1464 if ( autoCompleteStart >= 0 ) {
1468 case VK_UP: { // up arrow
1469 sel = Max( 0, autoCompleteListBox.GetCurSel() - 1 );
1470 autoCompleteListBox.SetCurSel( sel );
1473 case VK_DOWN: { // down arrow
1474 sel = Min( autoCompleteListBox.GetCount() - 1, autoCompleteListBox.GetCurSel() + 1 );
1475 autoCompleteListBox.SetCurSel( sel );
1478 case VK_PRIOR: { // page up key
1479 sel = Max( 0, autoCompleteListBox.GetCurSel() - 10 );
1480 autoCompleteListBox.SetCurSel( sel );
1483 case VK_NEXT: { // page down key
1484 sel = Min( autoCompleteListBox.GetCount() - 1, autoCompleteListBox.GetCurSel() + 10 );
1485 autoCompleteListBox.SetCurSel( sel );
1488 case VK_HOME: { // home key
1489 autoCompleteListBox.SetCurSel( 0 );
1493 autoCompleteListBox.SetCurSel( autoCompleteListBox.GetCount() - 1 );
1496 case VK_RETURN: // enter key
1497 case VK_TAB: { // tab key
1498 AutoCompleteInsertText();
1502 case VK_LEFT: // left arrow
1503 case VK_RIGHT: // right arrow
1504 case VK_INSERT: // insert key
1505 case VK_DELETE: { // delete key
1511 BracedSectionHide();
1514 case VK_TAB: { // multi-line tabs
1515 long selStart, selEnd;
1517 GetSel( selStart, selEnd );
1519 // if multiple lines are selected add tabs to, or remove tabs from all of them
1520 if ( selEnd > selStart ) {
1523 text = GetSelText();
1525 if ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 ) {
1526 if ( idStr::CharIsTab( text[0] ) ) {
1527 text.Delete( 0, 1 );
1529 for ( int i = 0; i < text.GetLength() - 2; i++ ) {
1530 if ( idStr::CharIsNewLine( text[i] ) ) {
1533 } while( idStr::CharIsNewLine( text[i] ) );
1534 if ( idStr::CharIsTab( text[i] ) ) {
1535 text.Delete( i, 1 );
1540 text.Insert( 0, '\t' );
1541 for ( int i = 0; i < text.GetLength() - 1; i++ ) {
1542 if ( idStr::CharIsNewLine( text[i] ) ) {
1545 } while( idStr::CharIsNewLine( text[i] ) );
1546 text.Insert( i, '\t' );
1551 ReplaceSel( text, TRUE );
1552 SetSel( selStart, selStart + text.GetLength() );
1554 ReplaceSel( "\t", TRUE );
1558 case VK_RETURN: { // auto-indentation
1559 long selStart, selEnd;
1560 int line, length, numTabs, i;
1564 GetSel( selStart, selEnd );
1565 line = LineFromChar( selStart );
1566 length = GetLine( line, buffer, sizeof( buffer ) );
1567 for ( numTabs = 0; numTabs < length; numTabs++ ) {
1568 if ( !idStr::CharIsTab( buffer[numTabs] ) ) {
1573 for ( i = numTabs; i < length; i++ ) {
1574 if ( buffer[i] == '{' ) {
1577 } else if ( buffer[i] == '}' && !first ) {
1582 for ( i = 0; i < numTabs; i++ ) {
1583 text.Append( '\t' );
1585 ReplaceSel( text, TRUE );
1590 m_TextDoc->Freeze( NULL );
1592 CRichEditCtrl::OnKeyDown( nKey, nRepCnt, nFlags );
1594 UpdateVisibleRange();
1596 m_TextDoc->Unfreeze( NULL );
1601 CSyntaxRichEditCtrl::OnChar
1604 void CSyntaxRichEditCtrl::OnChar( UINT nChar, UINT nRepCnt, UINT nFlags ) {
1606 if ( nChar == VK_TAB ) {
1607 return; // tab is handle in OnKeyDown
1610 CRichEditCtrl::OnChar( nChar, nRepCnt, nFlags );
1612 // if the auto-complete list box is up
1613 if ( autoCompleteStart >= 0 ) {
1614 long selStart, selEnd;
1616 if ( charType[nChar] == CT_NAME ) {
1617 AutoCompleteUpdate();
1619 } else if ( nChar == VK_BACK ) {
1620 GetSel( selStart, selEnd );
1621 if ( selStart > autoCompleteStart ) {
1622 AutoCompleteUpdate();
1632 // if the function parameter tool tip is up
1633 if ( funcParmToolTipStart >= 0 ) {
1634 long selStart, selEnd;
1636 if ( nChar == ')' || nChar == VK_ESCAPE ) {
1638 } else if ( nChar == VK_BACK ) {
1639 GetSel( selStart, selEnd );
1640 if ( selStart < funcParmToolTipStart ) {
1646 // show keyword auto-completion
1647 if ( keyWordAutoCompletion && charType[nChar] == CT_NAME && funcParmToolTipStart < 0 ) {
1648 long selStart, selEnd;
1649 int line, column, length, i;
1652 GetSel( selStart, selEnd );
1653 line = LineFromChar( selStart );
1654 length = GetLine( line, buffer, sizeof( buffer ) );
1655 column = selStart - LineIndex( line );
1656 if ( column <= 1 || charType[buffer[column-2]] == CT_WHITESPACE ) {
1657 if ( column >= length-1 || charType[buffer[column]] == CT_WHITESPACE ) {
1659 autoCompleteListBox.ResetContent();
1660 for ( i = 0; keyWords[i].keyWord; i++ ) {
1661 autoCompleteListBox.AddString( keyWords[i].keyWord );
1663 AutoCompleteShow( selStart - 1 );
1669 // highlight braced sections
1670 if ( nChar == '{' ) {
1671 BracedSectionStart( '{', '}' );
1672 } else if ( nChar == '}' ) {
1673 BracedSectionEnd( '{', '}' );
1674 } else if ( nChar == '(' ) {
1675 BracedSectionStart( '(', ')' );
1676 } else if ( nChar == ')' ) {
1677 BracedSectionEnd( '(', ')' );
1678 } else if ( nChar == '[' ) {
1679 BracedSectionStart( '[', ']' );
1680 } else if ( nChar == ']' ) {
1681 BracedSectionEnd( '[', ']' );
1682 } else if ( nChar == '<' ) {
1683 BracedSectionStart( '<', '>' );
1684 } else if ( nChar == '>' ) {
1685 BracedSectionEnd( '<', '>' );
1688 // show object member auto-completion
1689 if ( nChar == '.' && GetObjectMembers && funcParmToolTipStart < 0 ) {
1693 if ( GetNameBeforeCurrentSelection( name, charIndex ) ) {
1694 autoCompleteListBox.ResetContent();
1695 if ( GetObjectMembers( name, autoCompleteListBox ) ) {
1696 AutoCompleteShow( charIndex );
1702 // show function parameter tool tip
1703 if ( nChar == '(' && GetFunctionParms ) {
1707 if ( GetNameBeforeCurrentSelection( name, charIndex ) ) {
1709 if ( GetFunctionParms( name, parmString ) ) {
1710 ToolTipShow( charIndex, parmString );
1719 CSyntaxRichEditCtrl::OnLButtonDown
1722 void CSyntaxRichEditCtrl::OnLButtonDown( UINT nFlags, CPoint point ) {
1724 if ( autoCompleteStart >= 0 ) {
1728 BracedSectionHide();
1730 CRichEditCtrl::OnLButtonDown( nFlags, point );
1735 CSyntaxRichEditCtrl::OnMouseWheel
1738 BOOL CSyntaxRichEditCtrl::OnMouseWheel( UINT nFlags, short zDelta, CPoint pt ) {
1739 if ( autoCompleteStart >= 0 ) {
1743 sel = Max( 0, autoCompleteListBox.GetCurSel() - ( zDelta / WHEEL_DELTA ) );
1745 sel = Min( autoCompleteListBox.GetCount() - 1, autoCompleteListBox.GetCurSel() - ( zDelta / WHEEL_DELTA ) );
1747 autoCompleteListBox.SetCurSel( sel );
1751 m_TextDoc->Freeze( NULL );
1753 LineScroll( -3 * ( (int) zDelta ) / WHEEL_DELTA, 0 );
1755 UpdateVisibleRange();
1757 m_TextDoc->Unfreeze( NULL );
1764 CSyntaxRichEditCtrl::OnMouseMove
1767 void CSyntaxRichEditCtrl::OnMouseMove( UINT nFlags, CPoint point ) {
1768 CRichEditCtrl::OnMouseMove( nFlags, point );
1770 if ( point != mousePoint ) {
1773 // remove tool tip and activate the tool tip control, otherwise
1774 // tool tips stop working until the mouse moves over another window first
1775 AFX_MODULE_THREAD_STATE *state = AfxGetModuleThreadState();
1776 state->m_pToolTip->Pop();
1777 state->m_pToolTip->Activate( TRUE );
1783 CSyntaxRichEditCtrl::OnSize
1786 void CSyntaxRichEditCtrl::OnSize( UINT nType, int cx, int cy ) {
1787 m_TextDoc->Freeze( NULL );
1789 CRichEditCtrl::OnSize( nType, cx, cy );
1791 m_TextDoc->Unfreeze( NULL );
1793 UpdateVisibleRange();
1798 CSyntaxRichEditCtrl::OnVScroll
1801 void CSyntaxRichEditCtrl::OnVScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar ) {
1802 m_TextDoc->Freeze( NULL );
1804 CRichEditCtrl::OnVScroll( nSBCode, nPos, pScrollBar );
1808 UpdateVisibleRange();
1810 m_TextDoc->Unfreeze( NULL );
1815 CSyntaxRichEditCtrl::OnProtected
1818 void CSyntaxRichEditCtrl::OnProtected( NMHDR *pNMHDR, LRESULT *pResult ) {
1819 ENPROTECTED* pEP = (ENPROTECTED*)pNMHDR;
1823 updateRange = pEP->chrg;
1825 switch( pEP->msg ) {
1826 case WM_MOUSEMOVE: {
1830 updateRange.cpMin = pEP->chrg.cpMin;
1831 updateRange.cpMax = pEP->chrg.cpMin + strlen( (LPCTSTR) pEP->lParam );
1857 CSyntaxRichEditCtrl::OnChange
1860 void CSyntaxRichEditCtrl::OnChange() {
1861 long selStart, selEnd;
1863 if ( !updateSyntaxHighlighting ) {
1867 GetSel( selStart, selEnd );
1868 selStart = Min( selStart, updateRange.cpMin );
1869 selEnd = Max( selEnd, updateRange.cpMax );
1871 HighlightSyntax( selStart, selEnd );
1873 // send EN_CHANGE notification to parent window
1875 pNMHDR.hwndFrom = GetSafeHwnd();
1876 pNMHDR.idFrom = GetDlgCtrlID();
1877 pNMHDR.code = EN_CHANGE;
1878 GetParent()->SendMessage( WM_NOTIFY, ( EN_CHANGE << 16 ) | GetDlgCtrlID(), (LPARAM)&pNMHDR );
1883 CSyntaxRichEditCtrl::OnAutoCompleteListBoxChange
1886 void CSyntaxRichEditCtrl::OnAutoCompleteListBoxChange() {
1887 // steal focus back from the auto-complete list box
1893 CSyntaxRichEditCtrl::OnAutoCompleteListBoxDblClk
1896 void CSyntaxRichEditCtrl::OnAutoCompleteListBoxDblClk() {
1897 // steal focus back from the auto-complete list box
1900 // insert current auto-complete selection
1901 AutoCompleteInsertText();