diff --git a/src/plugins/codecompletion/parser/tokenizer.cpp b/src/plugins/codecompletion/parser/tokenizer.cpp index 66307f89d4..f9924e3dae 100644 --- a/src/plugins/codecompletion/parser/tokenizer.cpp +++ b/src/plugins/codecompletion/parser/tokenizer.cpp @@ -274,7 +274,7 @@ bool Tokenizer::SkipWhiteSpace() } // only be called when we are in a C-string, -// To check whether the current charactor is the real end of C-string +// To check whether the current character is the real end of C-string // See SkipToStringEnd() for more details bool Tokenizer::IsEscapedChar() { @@ -1148,6 +1148,8 @@ wxString Tokenizer::PeekToken() unsigned int savedLineNumber = m_LineNumber; unsigned int savedNestLevel = m_NestLevel; + int savedReplaceCount = m_IsReplaceParsing ? m_RepeatReplaceCount : -1; + if (SkipUnwanted()) m_PeekToken = DoGetToken(); else @@ -1156,17 +1158,33 @@ wxString Tokenizer::PeekToken() m_PeekTokenIndex = m_TokenIndex; m_PeekLineNumber = m_LineNumber; m_PeekNestLevel = m_NestLevel; - - m_TokenIndex = savedTokenIndex; - m_LineNumber = savedLineNumber; - m_NestLevel = savedNestLevel; + // Check whether a ReplaceBufferForReparse() was done in DoGetToken(). + // We assume m_Undo... have already been reset in ReplaceBufferForReparse(). + if (m_IsReplaceParsing && savedReplaceCount != (int)m_RepeatReplaceCount) + { + m_TokenIndex = m_UndoTokenIndex; + m_LineNumber = m_UndoLineNumber; + m_NestLevel = m_UndoNestLevel; + } + else + { + m_TokenIndex = savedTokenIndex; + m_LineNumber = savedLineNumber; + m_NestLevel = savedNestLevel; + } } return m_PeekToken; } - +/* peek is always available when we run UngetToken() once, actually the m_TokenIndex is moved + * backward one step. Note that the m_UndoTokenIndex value is not updated in this function, which + * means you are not allowed to run this function twice. + */ void Tokenizer::UngetToken() { + if(m_TokenIndex == m_UndoTokenIndex) //this means we have already run a UngetToken() before. + return; + m_PeekTokenIndex = m_TokenIndex; m_PeekLineNumber = m_LineNumber; m_PeekNestLevel = m_NestLevel; @@ -1177,6 +1195,19 @@ void Tokenizer::UngetToken() m_PeekAvailable = true; } +/* this function always start from the index of m_TokenIndex + * int X;MYMACRO;X = 1; + * Token: _^ + * Undo: ^ + * After that, we get a lexeme of name "MYMACRO", then Token index is move forward + * int X;MYMACRO;X = 1; + * Token: _______^ + * Undo: ^ + * + * Please note that if MYMACRO need to be replaced (macro expansion), we should replace the text + * then run one step again, see the details in: + * http://forums.codeblocks.org/index.php/topic,18315.msg125579.html#msg125579 + */ wxString Tokenizer::DoGetToken() { int start = m_TokenIndex; @@ -1840,6 +1871,11 @@ bool Tokenizer::ReplaceBufferForReparse(const wxString& target, bool updatePeekT // Fix token index m_TokenIndex -= bufferLen; + // Fix undo position + m_UndoTokenIndex = m_TokenIndex; + m_UndoLineNumber = m_LineNumber; + m_UndoNestLevel = m_NestLevel; + // Update the peek token if (m_PeekAvailable && updatePeekToken) { diff --git a/src/plugins/codecompletion/parser/tokenizer.h b/src/plugins/codecompletion/parser/tokenizer.h index dbc8d1b612..96f2448659 100644 --- a/src/plugins/codecompletion/parser/tokenizer.h +++ b/src/plugins/codecompletion/parser/tokenizer.h @@ -282,7 +282,10 @@ class Tokenizer /** Initialize some member variables */ void BaseInit(); - /** Do the actual lexical analysis, both GetToken() and PeekToken will internally call this function */ + /** Do the actual lexical analysis, both GetToken() and PeekToken() will internally call this + * function. It just move the m_TokenIndex one step forward, and return a lexeme before the + * m_TokenIndex. + */ wxString DoGetToken(); /** Read a file, and fill the m_Buffer */ @@ -371,16 +374,13 @@ class Tokenizer return false; }; - /** This function is not used in the current code, it is replaced by MacroReplace() */ - inline const wxString& ThisOrReplacement(const wxString& str) const - { - wxStringHashMap::const_iterator it = s_Replacements.find(str); - if (it != s_Replacements.end()) - return it->second; - return str; - }; - - /** Check the previous char before EOL is a backslash */ + /** Check the previous char before EOL is a backslash, call this function in the condition that + * the CurrentChar is '\n', here we have two cases: + * ......\\\r\n...... + * ^--current char, this is DOS style EOL + * ......\\\n...... + * ^--current char, this is Linux style EOL + */ inline bool IsBackslashBeforeEOL() { wxChar last = PreviousChar(); @@ -444,6 +444,12 @@ class Tokenizer * such as the token name, the line number of the token, the current brace nest level. */ wxString m_Token; //!< token name + /** when parsing a buffer + * ....... namespace std { int a; ....... + * ^ --- m_TokenIndex, m_Token = "std" + * m_TokenIndex is always point to the next character of a valid token, in the above example, + * it is the space after "std". + */ unsigned int m_TokenIndex; //!< index offset in buffer unsigned int m_LineNumber; //!< line offset in buffer unsigned int m_NestLevel; //!< keep track of block nesting { } diff --git a/src/src/startherepage.cpp b/src/src/startherepage.cpp index 716f89ab5d..ca8ddb54f5 100644 --- a/src/src/startherepage.cpp +++ b/src/src/startherepage.cpp @@ -240,9 +240,11 @@ void StartHerePage::RegisterColours() inited = true; ColourManager* cm = Manager::Get()->GetColourManager(); - cm->RegisterColour(_("Start here page"), _("Background colour"), wxT("start_here_background"), wxSystemSettings::GetColour(wxSYS_COLOUR_BACKGROUND)); - cm->RegisterColour(_("Start here page"), _("Link colour"), wxT("start_here_link"), *wxBLUE); - cm->RegisterColour(_("Start here page"), _("Text colour"), wxT("start_here_text"), *wxBLACK); + cm->RegisterColour(_("Start here page"), _("Background colour"), wxT("start_here_background"), + wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + cm->RegisterColour(_("Start here page"), _("Link colour"), wxT("start_here_link"), *wxBLUE); + cm->RegisterColour(_("Start here page"), _("Text colour"), wxT("start_here_text"), + wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); } void StartHerePage::Reload()