Option Explicit '------------------------------------------------------------------------------ 'FILE DESCRIPTION: Routines to reformat C/C++ source code. 'Created by Alvaro Mendez - June 10, 1999 'Last Updated: July 9, 2002 '------------------------------------------------------------------------------ Sub MakeCodeNicer 'DESCRIPTION: Reformats the source code to look nicer, the way I like it. ' Check that we have a valid source file if not CheckActiveDocument then exit sub end if ' Select the whole file and reformat it ActiveDocument.Selection.SelectAll ReformatSelection End Sub Sub MakeSelectedCodeNicer 'DESCRIPTION: Reformats the currently selected source code to look nicer. ' Check that we have a valid source file if not CheckActiveDocument then exit sub end if ' Check that there's a valid selection if ActiveDocument.Selection = "" then ShowError "NoSelection" exit sub end if ' Reformat the current selection ReformatSelection End Sub ' Verify there's an active document and that it's valid function CheckActiveDocument CheckActiveDocument = false ' Check that there's a file to reformat if ActiveDocument is Nothing then ShowError "NoFile" exit function end if ' Check that it's at least a text file if ActiveDocument.Type <> "Text" then ShowError "InvalidFile" exit function end if CheckActiveDocument = true end function ' Show one of the predefined errors in a message box. sub ShowError(strType) dim strMessage select case strType case "NoFile" strMessage = "Please open a C/C++ source file " & _ "and run this macro again." case "InvalidFile" strMessage = "Please activate a window containing " & _ "C/C++ source code and run this macro again." case "NoSelection" strMessage = "Please select the source code you want to " & _ "reformat and run this macro again." case "OutOfMemory" strMessage = "This macro is not working properly because " & _ "Visual C++ has apparently run out of memory." & _ vbLf & vbLf & "Unfortunately this is a bug in " & _ "Visual C++. It typically manifests itself " & _ "whenever the macro is run multiple times on very " & _ "large files, inside the same Visual C++ session. " & _ "The only way around it is to open a new Visual " & _ "C++ session for each large file you want to " & _ "reformat." & vbLf & vbLf & "Press OK to go back " & _ "to the original file. You should then exit Visual C++." case else strMessage = "Unknown Error of type: " & strType end select MsgBox strMessage, vbExclamation end sub ' Reformat the currently selected source code (if any) function ReformatSelection ' Check if there's something selected if ActiveDocument.Selection = "" then exit function end if ' Copy the selection to the clipboard ActiveDocument.Selection.Copy ' Open a new document and change its language to C/C++ ' This is required for SmartIndent to work. Documents.Add "Text" ActiveDocument.Language = "C/C++" ' Paste the selection into the new document ActiveDocument.Selection.Paste ' Reformat it! if not ReformatActiveDocument then ActiveWindow.Close dsSaveChangesNo exit function end if ' Select the resulting code and copy it to the clipboard ActiveDocument.Selection.SelectAll ActiveDocument.Selection.Copy ' Close the new document (without saving it) ActiveWindow.Close dsSaveChangesNo ' Paste the reformatted code back over the original selection ActiveDocument.Selection.Paste end function ' Reformat the source code in the currently active file (document) function ReformatActiveDocument ReformatActiveDocument = false ' Add spaces in a few places and get rid of it in others Replace "\:b+;", ";" Replace "\:b+::\:b+", "::" Replace "\:b+(", "(" Replace " =(", " = (" Replace "if(", "if (" Replace "for(", "for (" Replace "while(", "while (" Replace "switch(", "switch (" Replace "catch(", "catch (" Replace "return(", "return (" Replace "(\:b+", "(" Replace "\:b+)", ")" Replace ";)", "; )" Replace ";;\:b+)", ";;)" Replace "\[\:b+", "[" Replace "\:b+\]", "]" Replace "\:b+\[", "[" Replace "\:b+->", "->" Replace "->\:b+", "->" Replace "|(", "| (" Replace "&(", "& (" Replace "\+(", "+ (" Replace "\-(", "- (" Replace "\*(", "* (" Replace "/(", "/ (" ' Make sure these statements don't end on the same line they started. BreakSingleLiners "if (" BreakSingleLiners "for (" BreakSingleLiners "switch (" ' Break up any lines containing multiple statements BreakLinesWithMultipleStatements ' Make sure braces are on lines by themselves (unless followed by comments) IsolateOnLeft "{" IsolateOnRight "{" IsolateOnRight "}" IsolateOnLeft "}" ' Break up simple else statements on the same line (except "else if") Replace "else\:b+if (", "elseif(" IsolateOnRight "else\:b+" Replace "elseif(", "else if (" ' Break up case statements appearing on single lines IsolateOnRight "case .+:\:b+" IsolateOnRight "default:\:b+" IsolateOnLeft "break;" ' Add a space between these operators FixOperator "=", 1 FixOperator "==", 2 FixOperator "!=", 2 FixOperator "\+=", 2 FixOperator "-=", 2 FixOperator "\*=", 2 FixOperator "/=", 2 FixOperator "\+", 1 FixOperator "-", 1 FixOperator "<=", 2 FixOperator ">=", 2 FixOperator "<<", 2 FixOperator ">>", 2 FixOperator "&&", 2 FixOperator "||", 2 FixOperator "|", 1 FixOperator "?", 1 FixLessThanAndGreaterThanOperators FixExponents ' Append a space after these AppendSpace "," AppendSpace ";" ' Make sure the first C++ comment of every line has a space after it. InsertSpaceAfterFirstInLineComment ' Replace all the trailing whitespace (thanks to Paul Bludov) ActiveDocument.Selection.ReplaceText "\:b+\($\)", "\1", dsMatchRegExp ' Run Smart Indent on function blocks only SmartIndentFunctionBlocks ' Remove any lines that are considered extraneous (ie. extra blank lines) if not RemoveExtraneousLines then exit function end if ' Indent every "case" inside switch statements (thanks to Jim Cooper) IndentSwitchBody ' Return OK ReformatActiveDocument = true end function ' Is the cursor currently within a quoted string (or character) function IsWithinQuotes dim nCurrentLine, nCurrentColumn, iPos, strBuffer, nCount nCurrentLine = ActiveDocument.Selection.CurrentLine nCurrentColumn = ActiveDocument.Selection.CurrentColumn ActiveDocument.Selection.Cancel ActiveDocument.Selection.StartOfLine dsFirstText, dsExtend nCount = 0 iPos = 0 strBuffer = ActiveDocument.Selection ' Count all occurrences of a double quote which apply to quoted strings do while true iPos = InStr(iPos + 1, strBuffer, """", vbTextCompare) if not (iPos > 0) then exit do end if if iPos = 1 then ' if it's the first character, then it's valid nCount = nCount + 1 else ' Make sure it's not preceded by a \ or a \\ if Mid(strBuffer, iPos - 1, 1) <> "\" then nCount = nCount + 1 elseif (iPos > 2) and (Mid(strBuffer, iPos - 2, 1) = "\") then nCount = nCount + 1 end if end if loop ' If number of quotes is odd, we must be inside a quoted string! IsWithinQuotes = ((nCount > 0) and ((nCount Mod 2) <> 0)) ActiveDocument.Selection.MoveTo nCurrentLine, nCurrentColumn ' If we're not inside a quoted string, check for a quoted character if not IsWithinQuotes then ActiveDocument.Selection.CharLeft dsExtend ' If we find a quoted character left of us, check for one on the right if ActiveDocument.Selection = "'" then ActiveDocument.Selection.CharRight ActiveDocument.Selection.CharRight dsExtend if ActiveDocument.Selection = "\" then ActiveDocument.Selection.CharRight ActiveDocument.Selection.CharRight dsExtend end if ActiveDocument.Selection.CharRight ActiveDocument.Selection.CharRight dsExtend if ActiveDocument.Selection = "'" then IsWithinQuotes = true end if end if ActiveDocument.Selection.MoveTo nCurrentLine, nCurrentColumn end if ' If we're inside quotes, proceed from the next character if IsWithinQuotes then ActiveDocument.Selection.CharRight end if end function ' Is current selection preceded by a C++ comment? ("//") function IsWithinComment dim nCurrentLine, nCurrentColumn nCurrentLine = ActiveDocument.Selection.CurrentLine nCurrentColumn = ActiveDocument.Selection.CurrentColumn ActiveDocument.Selection.Cancel ActiveDocument.Selection.StartOfLine dsFirstText, dsExtend IsWithinComment = false if (InStr(1, ActiveDocument.Selection, "//", vbTextCompare) > 0) then IsWithinComment = true ' since it's commented out nCurrentLine = nCurrentLine + 1 ' we proceed from the next line end if ActiveDocument.Selection.MoveTo nCurrentLine, 1 end function ' Is the cursor on a line with a preprocessor macro? ("#define ") function IsPreprocessorMacro dim nCurrentLine, nCurrentColumn nCurrentLine = ActiveDocument.Selection.CurrentLine nCurrentColumn = ActiveDocument.Selection.CurrentColumn IsPreprocessorMacro = false ActiveDocument.Selection.EndOfLine dsExtend if (Mid(LTrimTabs(ActiveDocument.Selection), 1, 8) = "#define ") or _ (Right(ActiveDocument.Selection, 1) = "\") then IsPreprocessorMacro = true ' since it's in a macro nCurrentLine = nCurrentLine + 1 ' we proceed from the next line end if ActiveDocument.Selection.MoveTo nCurrentLine, nCurrentColumn end function ' Should the current selection be ignored? ' (ie., is it within a comment, between quotes, or inside a macro?) function ShouldIgnore ShouldIgnore = false if IsWithinQuotes then ShouldIgnore = true exit function end if if IsWithinComment then ShouldIgnore = true exit function end if if IsPreprocessorMacro then ShouldIgnore = true end if end function ' Put the cursor at the top of the document and return "" to be passed ' initially to GetCurrenPosition function InitializePosition ActiveDocument.Selection.StartOfDocument InitializePosition = "" end function ' Retrieve the current position and return true if it's greater than the ' last one. This is used to ensure that the file is only searched once ' (provided the search is started from the top) function GetCurrentPosition(strPos) dim nLastLine, nLastColumn, nCurrentLine, nCurrentColumn, iPos, ch nLastLine = -1 nLastColumn = -1 nCurrentLine = ActiveDocument.Selection.CurrentLine nCurrentColumn = ActiveDocument.Selection.CurrentColumn ' Parse the last position and extract the line and column for iPos = 1 to Len(strPos) ch = Mid(strPos, iPos, 1) if ch = "," then nLastLine = CInt(Mid(strPos, 1, iPos - 1)) nLastColumn = CInt(Mid(strPos, iPos + 1)) exit for end if next ' Return true if we're currently past the last position strPos = nCurrentLine & "," & nCurrentColumn GetCurrentPosition = (nCurrentLine > nLastLine) or _ ((nLastLine = nCurrentLine) and (nCurrentColumn > nLastColumn)) end function ' Move by a certain number of columns sub MoveByColumns(nBy) ActiveDocument.Selection.MoveTo ActiveDocument.Selection.CurrentLine, _ ActiveDocument.Selection.CurrentColumn + nBy end sub ' Replace the given strFrom with strTo case sensitively sub Replace(strFrom, strTo) dim strLastPos, bContinue strLastPos = InitializePosition do while ActiveDocument.Selection.FindText(strFrom, _ dsMatchCase + dsMatchRegExp) bContinue = GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes if not ShouldIgnore then ' Repeat the search since ShouldIgnore puts the cursor at ' the beginning of the line ActiveDocument.Selection.FindText strFrom, _ dsMatchCase + dsMatchRegExp ActiveDocument.Selection = strTo elseif not bContinue then exit do end if loop end sub ' Break the given str ending in (, so that instead of this: ' if (a) return b; ' it looks like this: ' if (a) ' return b; sub BreakSingleLiners(str) dim strLastPos, strFound, nCol, bBreak, strAfterFound ' Verify str ends in (, the beginning parenthesis if Right(str, 1) <> "(" then exit sub end if strLastPos = InitializePosition while ActiveDocument.Selection.FindText(str, dsMatchCase) and _ GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes if not ShouldIgnore then ' Repeat the search since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText str, dsMatchCase ' Find the matching brace and go to the end of the line ActiveDocument.Selection.CharRight ActiveDocument.Selection.CharLeft ExecuteCommand "GoToMatchBrace" ActiveDocument.Selection.CharRight nCol = ActiveDocument.Selection.CurrentColumn ActiveDocument.Selection.EndOfLine dsExtend strFound = LTrimTabs(ActiveDocument.Selection) ' If there's anything after the brace that isn't a comment, move ' it to the next line if (Len(strFound) > 0) and (Left(strFound, 1) <> "/") then bBreak = false ' Check if there's a "{" after the statement which should ' also be broken into multiple lines if (Mid(strFound, 1, 1) = "{") and (Len(strFound) > 1) then strAfterFound = LTrimTabs(Mid(strFound, 2)) if strAfterFound <> "" then ActiveDocument.Selection = "{" + strAfterFound ActiveDocument.Selection.MoveTo _ ActiveDocument.Selection.CurrentLine, nCol ActiveDocument.Selection.NewLine ActiveDocument.Selection.CharRight ActiveDocument.Selection.NewLine bBreak = true ' primitive but it works end if end if if not bBreak then ActiveDocument.Selection = strFound ActiveDocument.Selection.MoveTo _ ActiveDocument.Selection.CurrentLine, nCol ActiveDocument.Selection.NewLine end if end if end if wend end sub ' Trim blanks AND tabs from the left side function LTrimTabs(str) dim iPos, ch for iPos = 1 to Len(str) ch = Mid(str, iPos, 1) if ch <> " " and ch <> vbTab then exit for end if next LTrimTabs = Mid(str, iPos) end function ' Isolate the given str on a new line with nothing left of it sub IsolateOnLeft(str) dim strLastPos, nLen, bContinue, nCurrentLine, nCurrentColumn strLastPos = InitializePosition while ActiveDocument.Selection.FindText("^.*" & str, dsMatchRegExp + _ dsMatchCase) and GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes if not ShouldIgnore then ' Repeat the search since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText "^.*" & str, _ dsMatchRegExp + dsMatchCase ' Get the length of the found string ' (which may have been a regular expression) ActiveDocument.Selection.CharRight ActiveDocument.Selection.FindText str, _ dsMatchBackward + dsMatchRegExp + dsMatchCase nLen = Len(ActiveDocument.Selection) ActiveDocument.Selection.CharLeft if not ShouldIgnore then ' Now that we have the length, we need to redo ' the search and go on ActiveDocument.Selection.StartOfLine ActiveDocument.Selection.FindText "^.*" & str, _ dsMatchRegExp + dsMatchCase bContinue = false ' If we're isolating a brace, make sure its matching brace ' isn't on the same line if (str = "{") or (str = "}") then ActiveDocument.Selection.CharRight nCurrentLine = ActiveDocument.Selection.CurrentLine nCurrentColumn = ActiveDocument.Selection.CurrentColumn ActiveDocument.Selection.CharLeft ExecuteCommand "GoToMatchBrace" if ActiveDocument.Selection.CurrentLine = nCurrentLine then ActiveDocument.Selection.MoveTo _ nCurrentLine, nCurrentColumn bContinue = true ' we found it so move to the next match else ActiveDocument.Selection.MoveTo nCurrentLine, 1 ActiveDocument.Selection.FindText "^.*" & str, _ dsMatchRegExp + dsMatchCase end if end if if LTrimTabs(ActiveDocument.Selection) <> str and _ not bContinue then ActiveDocument.Selection.CharRight MoveByColumns -nLen ActiveDocument.Selection.NewLine MoveByColumns nLen end if GetCurrentPosition strLastPos end if end if wend end sub ' Isolate the given str so that everything after it is placed on the next line sub IsolateOnRight(str) dim strLastPos, strRight, nCurrentLine, nCurrentColumn, nLen strLastPos = InitializePosition while ActiveDocument.Selection.FindText(str & ".+$", _ dsMatchRegExp + dsMatchCase) and GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes ActiveDocument.Selection.CharLeft if not ShouldIgnore then ' Repeat the search since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText str & ".+$", _ dsMatchRegExp + dsMatchCase ' Get the length of the found string ' (which may have been a regular expression) ActiveDocument.Selection.CharLeft ActiveDocument.Selection.FindText str, dsMatchRegExp + dsMatchCase nLen = Len(ActiveDocument.Selection) ' Now that we have the length, we need to redo the search and go on ActiveDocument.Selection.CharLeft ActiveDocument.Selection.FindText str & ".+$", _ dsMatchRegExp + dsMatchCase strRight = LTrimTabs(Mid(ActiveDocument.Selection, nLen + 1)) ' Handle braces a bit differently if (str = "{") or (str = "}") then ' If it's a closing brace, and the code after it contains ' a semicolon, leave it alone (ie. variable definition). if (str = "}") then ActiveDocument.Selection.EndOfLine dsExtend if (InStr(1, ActiveDocument.Selection, ";", vbTextCompare) _ > 0) then strRight = "" ' we found it so move on to the next match end if ActiveDocument.Selection.CharLeft ActiveDocument.Selection.CharRight end if ' If we're isolating a brace make sure the matching brace ' isn't on the same line if (strRight <> "") then ActiveDocument.Selection.CharLeft nCurrentLine = ActiveDocument.Selection.CurrentLine nCurrentColumn = ActiveDocument.Selection.CurrentColumn ExecuteCommand "GoToMatchBrace" if ActiveDocument.Selection.CurrentLine = nCurrentLine then ActiveDocument.Selection.MoveTo _ nCurrentLine, nCurrentColumn + 1 strRight = "" ' we found it so move on to the next match else ActiveDocument.Selection.MoveTo _ nCurrentLine, nCurrentColumn ActiveDocument.Selection.FindText _ str & ".+$", dsMatchRegExp + dsMatchCase end if end if end if if (strRight <> "") and _ (Left(strRight, 1) <> "/") and _ (strRight <> ",") and _ (strRight <> ";") and _ (strRight <> "\") then ActiveDocument.Selection.CharLeft MoveByColumns nLen ActiveDocument.Selection.NewLine end if end if wend end sub ' Place the given strOperator (of nLen REAL characters) ' between spaces (if needed) sub FixOperator(strOperator, nLen) dim strLastPos, strFind strLastPos = InitializePosition ' Add one space between the operator while ActiveDocument.Selection.FindText("[A-Z,a-z,0-9,\),_,\]]" & _ strOperator & "[A-Z,a-z,0-9,\(,_,\*,"",',&]", dsMatchRegExp) and _ GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes ActiveDocument.Selection.CharLeft if not ShouldIgnore then ' Repeat the search since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText "[A-Z,a-z,0-9,\),_,\]]" & _ strOperator & "[A-Z,a-z,0-9,\(,_,\*,"",',&]", dsMatchRegExp ActiveDocument.Selection.CharLeft ActiveDocument.Selection.CharRight ActiveDocument.Selection = " " MoveByColumns nLen ActiveDocument.Selection = " " end if wend strLastPos = InitializePosition ' Fix any C++ "operator" member functions which were broken above while ActiveDocument.Selection.FindText("operator " & strOperator & " ", _ dsMatchRegExp) and GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes if not ShouldIgnore then ' Repeat the search since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText "operator " & strOperator & " ", _ dsMatchRegExp ActiveDocument.Selection.CharRight ActiveDocument.Selection.Backspace MoveByColumns -nLen ActiveDocument.Selection.Backspace end if wend end sub ' Fix "<" and ">" operators found inside for, while, and if statements. function FixLessThanAndGreaterThanOperators ' Fix "for" loops FixLessThanOrGreaterThanOperator "^\:b*for (.*;.*[A-Z,a-z,0-9,), ]+\<[^<=]" FixLessThanOrGreaterThanOperator "^\:b*for (.*;.*[A-Z,a-z,0-9,), ]+\>[^>=]" ' Fix "while" loops FixLessThanOrGreaterThanOperator "^\:b*while (.*[A-Z,a-z,0-9,), ]+\<[^<=]" FixLessThanOrGreaterThanOperator "^\:b*while (.*[A-Z,a-z,0-9,), ]+\>[^>=]" ' Fix "if" statements FixLessThanOrGreaterThanOperator "^\:b*if (.*[A-Z,a-z,0-9,), ]+\<[^<=]" FixLessThanOrGreaterThanOperator "^\:b*if (.*[A-Z,a-z,0-9,), ]+\>[^>=]" end function ' Fix "<" or ">" operator based on the given search condition. ' It assumes the condition will yield one or more characters before ' the operator and only one character after it. function FixLessThanOrGreaterThanOperator(strSearch) dim strLastPos, strFound strLastPos = InitializePosition while ActiveDocument.Selection.FindText(strSearch, dsMatchRegExp + _ dsMatchCase) and GetCurrentPosition(strLastPos) ActiveDocument.Selection.CharRight ActiveDocument.Selection.CharLeft ' Check if we're inside a comment or between quotes if not ShouldIgnore then ' Repeat the search since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText strSearch, dsMatchRegExp + _ dsMatchCase strFound = ActiveDocument.Selection ' Add a space before it (if needed) if Mid(strFound, Len(strFound) - 2, 1) <> " " then strFound = Left(strFound, Len(strFound) - 2) & " " & _ Right(strFound, 2) end if ' Add a space after it (if needed) if Right(strFound, 1) <> " " then strFound = Left(strFound, Len(strFound) - 1) & " " & _ Right(strFound, 1) end if ActiveDocument.Selection = strFound end if wend end function ' Append a space after the given strOperator (if it needs it) sub AppendSpace(strOperator) dim strLastPos, nCurrentLine, nCurrentColumn strLastPos = InitializePosition while ActiveDocument.Selection.FindText(strOperator & _ "[A-Z,a-z,0-9,\(,\-,_,\*,"",',&]", dsMatchRegExp) and _ GetCurrentPosition(strLastPos) ActiveDocument.Selection.CharLeft nCurrentLine = ActiveDocument.Selection.CurrentLine nCurrentColumn = ActiveDocument.Selection.CurrentColumn ' Check if we're inside a comment or between quotes if not ShouldIgnore then ActiveDocument.Selection.MoveTo nCurrentLine, nCurrentColumn ActiveDocument.Selection.FindText strOperator & _ "[A-Z,a-z,0-9,\(,\-,_,\*,"",',&]", dsMatchRegExp ActiveDocument.Selection.CharLeft MoveByColumns Len(strOperator) ActiveDocument.Selection = " " end if wend end sub ' Run the SmartIndent command (Alt+F8) on function blocks only. function SmartIndentFunctionBlocks dim strLastPos, nColumn, cBeforeBrace strLastPos = InitializePosition while ActiveDocument.Selection.FindText("{") and _ GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes if not ShouldIgnore then ' Repeat the action since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText "{" ' Go to matching brace and reformat tabs ExecuteCommand "GoToMatchBraceExtend" nColumn = ActiveDocument.Selection.CurrentColumn ActiveDocument.Selection.SmartFormat ActiveDocument.Selection.CharRight if ActiveDocument.Selection.CurrentColumn > nColumn then ' If SmartFormat indents the block (by mistake), unindent it ActiveDocument.Selection.CharLeft ExecuteCommand "GoToMatchBraceExtend" ActiveDocument.Selection.Unindent end if end if wend end function ' Since Microsoft's "SmartFormat" is not smart enough to indent case ' statements inside the switch body, we'll do it here. ' (Thanks to Jim Cooper) function IndentSwitchBody dim nSwitchLine, nFirstLine, nLastLine, strLastPos, iLine strLastPos = InitializePosition while ActiveDocument.Selection.FindText("switch", _ dsMatchWord + dsMatchCase) and GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes if not ShouldIgnore then nSwitchLine = ActiveDocument.Selection.CurrentLine ' Now find the opening brace and make sure it's on the next line if ActiveDocument.Selection.FindText("{") and _ not ShouldIgnore and _ (ActiveDocument.Selection.CurrentLine = nSwitchLine + 1) then ' Repeat the action since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText "{" ' Find next line in file, since earlier code put '{' on ' a line by itself nFirstLine = ActiveDocument.Selection.CurrentLine + 1 ' Go to matching brace and reformat tabs ExecuteCommand "GoToMatchBrace" ' Find previous line in file, since earlier code put '}' on ' line by itself nLastLine = ActiveDocument.Selection.CurrentLine ' Move to the line after the opening brace ActiveDocument.Selection.GoToLine nFirstLine, 1 ' Select everything between the braces and indent it for iLine = nFirstLine to nLastLine - 1 ActiveDocument.Selection.LineDown dsExtend next ActiveDocument.Selection.Indent end if end if wend end function ' Remove any lines that are considered extraneous (usually blank ones). function RemoveExtraneousLines dim strLastPos, nCurrentLine, nCurrentColumn, nLastLine, bContinue strLastPos = InitializePosition RemoveExtraneousLines = true ' Remove any blank lines that fall below any open braces ("{") while ActiveDocument.Selection.FindText("{") and _ GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes if not ShouldIgnore then ' Repeat the action since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText "{" nCurrentLine = ActiveDocument.Selection.CurrentLine nCurrentColumn = ActiveDocument.Selection.CurrentColumn ' Go to matching brace ExecuteCommand "GoToMatchBrace" ' Check if it's on the same line bContinue = (nCurrentLine <> ActiveDocument.Selection.CurrentLine) ExecuteCommand "GoToMatchBrace" ' If the matching brace is on the same line, proceed to the next brace if bContinue then ActiveDocument.Selection.LineDown ' Cut any blank lines below the { do while true ActiveDocument.Selection.StartOfLine ActiveDocument.Selection.EndOfLine dsExtend if LTrimTabs(ActiveDocument.Selection) <> "" then exit do end if ' Get the last line of the document ActiveDocument.Selection.EndOfDocument nLastLine = ActiveDocument.Selection.CurrentLine ' Remove the extra line ActiveDocument.Selection.MoveTo nCurrentLine + 1, 1 ExecuteCommand "LineCut" ' Make sure we haven't hit the bottom of the file and that LineCut worked ActiveDocument.Selection.EndOfDocument if ActiveDocument.Selection.CurrentLine = nLastLine then exit do end if ActiveDocument.Selection.MoveTo nCurrentLine + 1, 1 loop end if ActiveDocument.Selection.MoveTo nCurrentLine, nCurrentColumn end if wend strLastPos = InitializePosition ' Remove any blank lines right above any closing braces ("}") while ActiveDocument.Selection.FindText("}") and _ GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes if not ShouldIgnore then ' Repeat the action since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText "}" ActiveDocument.Selection.CharLeft ' Cut blank lines above the } do while true ActiveDocument.Selection.LineUp ActiveDocument.Selection.StartOfLine ActiveDocument.Selection.EndOfLine dsExtend nCurrentLine = ActiveDocument.Selection.CurrentLine if LTrimTabs(ActiveDocument.Selection) <> "" then if ActiveDocument.Selection.CurrentLine > 1 then ActiveDocument.Selection.LineDown end if ActiveDocument.Selection.StartOfLine ActiveDocument.Selection.FindText "}" strLastPos = ActiveDocument.Selection.CurrentLine & "," & _ ActiveDocument.Selection.CurrentColumn ActiveDocument.Selection.LineDown ActiveDocument.Selection.StartOfLine exit do end if ' Get the last line of the document ActiveDocument.Selection.EndOfDocument nLastLine = ActiveDocument.Selection.CurrentLine ' Remove the extra line ActiveDocument.Selection.MoveTo nCurrentLine, 1 ExecuteCommand "LineCut" ' Make sure LineCut worked -- if not something's really messed up ActiveDocument.Selection.EndOfDocument if ActiveDocument.Selection.CurrentLine = nLastLine then ShowError "OutOfMemory" RemoveExtraneousLines = false exit function end if ActiveDocument.Selection.MoveTo nCurrentLine, 1 loop end if wend end function ' Remove all spaces and tabs found in the current selection function RemoveSpacesInSelection dim iPos, ch, strNoSpaces for iPos = 1 to Len(ActiveDocument.Selection) ch = Mid(ActiveDocument.Selection, iPos, 1) if ch <> " " and ch <> vbTab then strNoSpaces = strNoSpaces + ch end if next ActiveDocument.Selection = strNoSpaces end function ' Fix any code with exponential notation (ie. 3.4e-2) which was ' broken when the + and - operators were fixed above (by FixOperator). function FixExponents while ActiveDocument.Selection.FindText("[0-9,\.]e [\+\!\-] [0-9]", _ dsMatchRegExp) RemoveSpacesInSelection wend end function ' Break any lines containing multiple statements (separated by semicolons) function BreakLinesWithMultipleStatements dim strLastPos, nCurrentLine, nCurrentColumn strLastPos = InitializePosition ' Search for multiple semicolons on the same line do while ActiveDocument.Selection.FindText(";.+;", dsMatchRegExp) ActiveDocument.Selection.CharLeft if not GetCurrentPosition(strLastPos) then exit do end if nCurrentLine = ActiveDocument.Selection.CurrentLine nCurrentColumn = ActiveDocument.Selection.CurrentColumn ' Check if we're inside a comment or between quotes if not ShouldIgnore then ' Repeat the action since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.MoveTo nCurrentLine, nCurrentColumn ActiveDocument.Selection.FindText ";.+;", dsMatchRegExp nCurrentLine = ActiveDocument.Selection.CurrentLine ActiveDocument.Selection.CharLeft ActiveDocument.Selection.StartOfLine dsFirstText, dsExtend ' If found, check that the semicolons don't belong to a for loop if (InStr(1, ActiveDocument.Selection, "for (", _ vbTextCompare) > 0) then ActiveDocument.Selection.MoveTo nCurrentLine + 1, 1 else if ActiveDocument.Selection <> "" then ActiveDocument.Selection.CharRight end if ActiveDocument.Selection.CharRight ActiveDocument.Selection.NewLine end if end if loop end function ' Make sure the first C++ comment of every line has a space after it. function InsertSpaceAfterFirstInLineComment dim strLastPos, nCurrentLine strLastPos = InitializePosition while ActiveDocument.Selection.FindText("//[A-Z,a-z,0-9]", dsMatchRegExp) _ and GetCurrentPosition(strLastPos) ActiveDocument.Selection.CharLeft ' Check if we're inside a comment or between quotes if not ShouldIgnore then ' Repeat the action since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText "//[A-Z,a-z,0-9]", dsMatchRegExp ActiveDocument.Selection.CharRight ActiveDocument.Selection.CharLeft ActiveDocument.Selection = " " end if wend end function ' Display a message box if bDebug is true sub DebugBox(strMessage) dim bDebug bDebug = false if bDebug then MsgBox strMessage end if end sub