home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / asty1153.zip / ASBeautifier.cpp < prev    next >
C/C++ Source or Header  |  2002-03-07  |  64KB  |  1,923 lines

  1. /*
  2.  * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
  3.  *
  4.  * ASBeautifier.cpp
  5.  * by Tal Davidson (davidsont@bigfoot.com)
  6.  * This file is a part of "Artistic Style" - an indentater and reformatter
  7.  * of C, C, C# and Java source files.
  8.  *
  9.  * The "Artistic Style" project, including all files needed to compile it,
  10.  * is free software; you can redistribute it and/or use it and/or modify it
  11.  * under the terms of the GNU General Public License as published 
  12.  * by the Free Software Foundation; either version 2 of the License, 
  13.  * or (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  18.  *
  19.  * You should have received a copy of the GNU General Public
  20.  * License along with this program.
  21.  *
  22.  * Patches:
  23.  * 18 March 1999 - Brian Rampel -
  24.  *       Fixed inverse insertion of spaces vs. tabs when in -t mode.
  25. */
  26.  
  27. #include "compiler_defines.h"
  28. #include "astyle.h"
  29.  
  30. #include <vector>
  31. #include <string>
  32. #include <cctype>
  33. #include <algorithm>
  34. #include <iostream>
  35.  
  36.  
  37. #define INIT_CONTAINER(container, value)     {if ( (container) != NULL ) delete (container); (container) = (value); }
  38. #define DELETE_CONTAINER(container)          {if ( (container) != NULL ) delete (container) ; }
  39.  
  40. #ifdef USES_NAMESPACE
  41. using namespace std;
  42. #endif
  43.  
  44.  
  45.  
  46.  
  47. #ifdef USES_NAMESPACE
  48. namespace astyle
  49. {
  50. #endif
  51.  
  52. bool ASBeautifier::calledInitStatic = false;
  53.  
  54. vector<const string*> ASBeautifier::headers;
  55. vector<const string*> ASBeautifier::nonParenHeaders;
  56. vector<const string*> ASBeautifier::preBlockStatements;
  57. vector<const string*> ASBeautifier::assignmentOperators;
  58. vector<const string*> ASBeautifier::nonAssignmentOperators;
  59.  
  60. /*
  61.  * initialize the static vars
  62.  */
  63. void ASBeautifier::initStatic()
  64. {
  65.     if (calledInitStatic)
  66.         return;
  67.  
  68.     calledInitStatic = true;
  69.  
  70.     headers.push_back(&AS_IF);
  71.     headers.push_back(&AS_ELSE);
  72.     headers.push_back(&AS_FOR);
  73.     headers.push_back(&AS_WHILE);
  74.     headers.push_back(&AS_DO);
  75.     headers.push_back(&AS_TRY);
  76.     headers.push_back(&AS_CATCH);
  77.     headers.push_back(&AS_FINALLY);
  78.     headers.push_back(&AS_SYNCHRONIZED);
  79.     headers.push_back(&AS_SWITCH);
  80.     headers.push_back(&AS_CASE);
  81.     headers.push_back(&AS_DEFAULT);
  82.     headers.push_back(&AS_FOREACH);
  83.     headers.push_back(&AS_LOCK);
  84.     headers.push_back(&AS_UNSAFE);
  85.     headers.push_back(&AS_FIXED);
  86.     headers.push_back(&AS_GET);
  87.     headers.push_back(&AS_SET);
  88.     headers.push_back(&AS_ADD);
  89.     headers.push_back(&AS_REMOVE);
  90.     //headers.push_back(&AS_PUBLIC);
  91.     //headers.push_back(&AS_PRIVATE);
  92.     //headers.push_back(&AS_PROTECTED);
  93.  
  94.     //headers.push_back(&AS_OPERATOR);
  95.     headers.push_back(&AS_TEMPLATE);
  96.     headers.push_back(&AS_CONST);
  97.     /**/
  98.     headers.push_back(&AS_STATIC);
  99.     headers.push_back(&AS_EXTERN);
  100.  
  101.     nonParenHeaders.push_back(&AS_ELSE);
  102.     nonParenHeaders.push_back(&AS_DO);
  103.     nonParenHeaders.push_back(&AS_TRY);
  104.     nonParenHeaders.push_back(&AS_FINALLY);
  105.     nonParenHeaders.push_back(&AS_STATIC);
  106.     nonParenHeaders.push_back(&AS_CONST);
  107.     nonParenHeaders.push_back(&AS_EXTERN);
  108.     nonParenHeaders.push_back(&AS_CASE);
  109.     nonParenHeaders.push_back(&AS_DEFAULT);
  110.     nonParenHeaders.push_back(&AS_UNSAFE);
  111.     nonParenHeaders.push_back(&AS_GET);
  112.     nonParenHeaders.push_back(&AS_SET);
  113.     nonParenHeaders.push_back(&AS_ADD);
  114.     nonParenHeaders.push_back(&AS_REMOVE);
  115.  
  116.  
  117.  
  118.     nonParenHeaders.push_back(&AS_PUBLIC);
  119.     nonParenHeaders.push_back(&AS_PRIVATE);
  120.     nonParenHeaders.push_back(&AS_PROTECTED);
  121.     nonParenHeaders.push_back(&AS_TEMPLATE);
  122.     nonParenHeaders.push_back(&AS_CONST);
  123. ///    nonParenHeaders.push_back(&AS_ASM);
  124.  
  125.     preBlockStatements.push_back(&AS_CLASS);
  126.     preBlockStatements.push_back(&AS_STRUCT);
  127.     preBlockStatements.push_back(&AS_UNION);
  128.     preBlockStatements.push_back(&AS_INTERFACE);
  129.     preBlockStatements.push_back(&AS_NAMESPACE);
  130.     preBlockStatements.push_back(&AS_THROWS);
  131.     preBlockStatements.push_back(&AS_EXTERN);
  132.  
  133.     assignmentOperators.push_back(&AS_ASSIGN);
  134.     assignmentOperators.push_back(&AS_PLUS_ASSIGN);
  135.     assignmentOperators.push_back(&AS_MINUS_ASSIGN);
  136.     assignmentOperators.push_back(&AS_MULT_ASSIGN);
  137.     assignmentOperators.push_back(&AS_DIV_ASSIGN);
  138.     assignmentOperators.push_back(&AS_MOD_ASSIGN);
  139.     assignmentOperators.push_back(&AS_OR_ASSIGN);
  140.     assignmentOperators.push_back(&AS_AND_ASSIGN);
  141.     assignmentOperators.push_back(&AS_XOR_ASSIGN);
  142.     assignmentOperators.push_back(&AS_GR_GR_GR_ASSIGN);
  143.     assignmentOperators.push_back(&AS_GR_GR_ASSIGN);
  144.     assignmentOperators.push_back(&AS_LS_LS_LS_ASSIGN);
  145.     assignmentOperators.push_back(&AS_LS_LS_ASSIGN);
  146.  
  147.     assignmentOperators.push_back(&AS_RETURN);
  148.  
  149.     nonAssignmentOperators.push_back(&AS_EQUAL);
  150.     nonAssignmentOperators.push_back(&AS_PLUS_PLUS);
  151.     nonAssignmentOperators.push_back(&AS_MINUS_MINUS);
  152.     nonAssignmentOperators.push_back(&AS_NOT_EQUAL);
  153.     nonAssignmentOperators.push_back(&AS_GR_EQUAL);
  154.     nonAssignmentOperators.push_back(&AS_GR_GR_GR);
  155.     nonAssignmentOperators.push_back(&AS_GR_GR);
  156.     nonAssignmentOperators.push_back(&AS_LS_EQUAL);
  157.     nonAssignmentOperators.push_back(&AS_LS_LS_LS);
  158.     nonAssignmentOperators.push_back(&AS_LS_LS);
  159.     nonAssignmentOperators.push_back(&AS_ARROW);
  160.     nonAssignmentOperators.push_back(&AS_AND);
  161.     nonAssignmentOperators.push_back(&AS_OR);
  162. }
  163.  
  164. /**
  165.  * ASBeautifier's constructor
  166.  */
  167. ASBeautifier::ASBeautifier()
  168. {
  169.     initStatic();
  170.  
  171.     waitingBeautifierStack = NULL;
  172.     activeBeautifierStack = NULL;
  173.     waitingBeautifierStackLengthStack = NULL;
  174.     activeBeautifierStackLengthStack = NULL;
  175.  
  176.     headerStack  = NULL;
  177.     tempStacks = NULL;
  178.     blockParenDepthStack = NULL;
  179.     blockStatementStack = NULL;
  180.     parenStatementStack = NULL;
  181.     bracketBlockStateStack = NULL;
  182.     inStatementIndentStack = NULL;
  183.     inStatementIndentStackSizeStack = NULL;
  184.     parenIndentStack = NULL;
  185.     sourceIterator = NULL;
  186.  
  187.     isMinimalConditinalIndentSet = false;
  188.     shouldForceTabIndentation = false;
  189.  
  190.     setSpaceIndentation(4);
  191.     setMaxInStatementIndentLength(40);
  192.     setClassIndent(false);
  193.     setSwitchIndent(false);
  194.     setCaseIndent(false);
  195.     setBlockIndent(false);
  196.     setBracketIndent(false);
  197.     setNamespaceIndent(false);
  198.     setLabelIndent(false);
  199.     setEmptyLineFill(false);
  200.     setCStyle();
  201.     setPreprocessorIndent(false);
  202. }
  203.  
  204. ASBeautifier::ASBeautifier(const ASBeautifier &other)
  205. {
  206.     waitingBeautifierStack = NULL;
  207.     activeBeautifierStack = NULL;
  208.     waitingBeautifierStackLengthStack = NULL;
  209.     activeBeautifierStackLengthStack = NULL;
  210.  
  211.     headerStack  = new vector<const string*>;
  212.     *headerStack = *other.headerStack;
  213.  
  214.     tempStacks = new vector< vector<const string*>* >;
  215.     vector< vector<const string*>* >::iterator iter;
  216.     for (iter = other.tempStacks->begin();
  217.             iter != other.tempStacks->end();
  218.             ++iter)
  219.     {
  220.         vector<const string*> *newVec = new vector<const string*>;
  221.         *newVec = **iter;
  222.         tempStacks->push_back(newVec);
  223.     }
  224.     blockParenDepthStack = new vector<int>;
  225.     *blockParenDepthStack = *other.blockParenDepthStack;
  226.  
  227.     blockStatementStack = new vector<bool>;
  228.     *blockStatementStack = *other.blockStatementStack;
  229.  
  230.     parenStatementStack =  new vector<bool>;
  231.     *parenStatementStack = *other.parenStatementStack;
  232.  
  233.     bracketBlockStateStack = new vector<bool>;
  234.     *bracketBlockStateStack = *other.bracketBlockStateStack;
  235.  
  236.     inStatementIndentStack = new vector<int>;
  237.     *inStatementIndentStack = *other.inStatementIndentStack;
  238.  
  239.     inStatementIndentStackSizeStack = new vector<int>;
  240.     *inStatementIndentStackSizeStack = *other.inStatementIndentStackSizeStack;
  241.  
  242.     parenIndentStack = new vector<int>;
  243.     *parenIndentStack = *other.parenIndentStack;
  244.  
  245.     sourceIterator = other.sourceIterator;
  246.  
  247.     indentString = other.indentString;
  248.     currentHeader = other.currentHeader;
  249.     previousLastLineHeader = other.previousLastLineHeader;
  250.     immediatelyPreviousAssignmentOp = other.immediatelyPreviousAssignmentOp;
  251.     isInQuote = other.isInQuote;
  252.     isInComment = other.isInComment;
  253.     isInCase = other.isInCase;
  254.     isInQuestion = other.isInQuestion;
  255.     isInStatement =other. isInStatement;
  256.     isInHeader = other.isInHeader;
  257.     isCStyle = other.isCStyle;
  258.     isInOperator = other.isInOperator;
  259.     isInTemplate = other.isInTemplate;
  260.     isInConst = other.isInConst;
  261.     classIndent = other.classIndent;
  262.     isInClassHeader = other.isInClassHeader;
  263.     isInClassHeaderTab = other.isInClassHeaderTab;
  264.     switchIndent = other.switchIndent;
  265.     caseIndent = other.caseIndent;
  266.     namespaceIndent = other.namespaceIndent;
  267.     bracketIndent = other.bracketIndent;
  268.     blockIndent = other.blockIndent;
  269.     labelIndent = other.labelIndent;
  270.     preprocessorIndent = other.preprocessorIndent;
  271.     parenDepth = other.parenDepth;
  272.     indentLength = other.indentLength;
  273.     blockTabCount = other.blockTabCount;
  274.     leadingWhiteSpaces = other.leadingWhiteSpaces;
  275.     maxInStatementIndent = other.maxInStatementIndent;
  276.     templateDepth = other.templateDepth;
  277.     quoteChar = other.quoteChar;
  278.     prevNonSpaceCh = other.prevNonSpaceCh;
  279.     currentNonSpaceCh = other.currentNonSpaceCh;
  280.     currentNonLegalCh = other.currentNonLegalCh;
  281.     prevNonLegalCh = other.prevNonLegalCh;
  282.     isInConditional = other.isInConditional;
  283.     minConditionalIndent = other.minConditionalIndent;
  284.     prevFinalLineSpaceTabCount = other.prevFinalLineSpaceTabCount;
  285.     prevFinalLineTabCount = other.prevFinalLineTabCount;
  286.     emptyLineFill = other.emptyLineFill;
  287.     probationHeader = other.probationHeader;
  288.     isInDefine = other.isInDefine;
  289.     isInDefineDefinition = other.isInDefineDefinition;
  290.     backslashEndsPrevLine = other.backslashEndsPrevLine;
  291.     defineTabCount = other.defineTabCount;
  292. }
  293.  
  294. /**
  295.  * ASBeautifier's destructor
  296.  */
  297. ASBeautifier::~ASBeautifier()
  298. {
  299.     DELETE_CONTAINER( headerStack );
  300.     DELETE_CONTAINER( tempStacks );
  301.     DELETE_CONTAINER( blockParenDepthStack );
  302.     DELETE_CONTAINER( blockStatementStack );
  303.     DELETE_CONTAINER( parenStatementStack );
  304.     DELETE_CONTAINER( bracketBlockStateStack );
  305.     DELETE_CONTAINER( inStatementIndentStack );
  306.     DELETE_CONTAINER( inStatementIndentStackSizeStack );
  307.     DELETE_CONTAINER( parenIndentStack );
  308.  
  309.     //DELETE_CONTAINER( sourceIterator );
  310. }
  311.  
  312. /**
  313.  * initialize the ASBeautifier.
  314.  *
  315.  * init() should be called every time a ABeautifier object is to start
  316.  * beautifying a NEW source file.
  317.  * init() recieves a pointer to a DYNAMICALLY CREATED ASSourceIterator object
  318.  * that will be used to iterate through the source code. This object will be
  319.  * deleted during the ASBeautifier's destruction, and thus should not be
  320.  * deleted elsewhere.
  321.  *
  322.  * @param iter     a pointer to the DYNAMICALLY CREATED ASSourceIterator object.
  323.  */
  324. void ASBeautifier::init(ASSourceIterator *iter)
  325. {
  326.     sourceIterator = iter;
  327.     init();
  328. }
  329.  
  330. /**
  331.  * initialize the ASBeautifier.
  332.  */
  333. void ASBeautifier::init()
  334. {
  335.     INIT_CONTAINER( waitingBeautifierStack,  new vector<ASBeautifier*> );
  336.     INIT_CONTAINER( activeBeautifierStack,  new vector<ASBeautifier*> );
  337.  
  338.     INIT_CONTAINER( waitingBeautifierStackLengthStack, new vector<int> );
  339.     INIT_CONTAINER( activeBeautifierStackLengthStack, new vector<int> );
  340.  
  341.     INIT_CONTAINER( headerStack,  new vector<const string*> );
  342.     INIT_CONTAINER( tempStacks, new vector< vector<const string*>* > );
  343.     tempStacks->push_back(new vector<const string*>);
  344.  
  345.     INIT_CONTAINER( blockParenDepthStack, new vector<int> );
  346.     INIT_CONTAINER( blockStatementStack, new vector<bool> );
  347.     INIT_CONTAINER( parenStatementStack, new vector<bool> );
  348.  
  349.     INIT_CONTAINER( bracketBlockStateStack, new vector<bool> );
  350.     bracketBlockStateStack->push_back(true);
  351.  
  352.     INIT_CONTAINER( inStatementIndentStack, new vector<int> );
  353.     INIT_CONTAINER( inStatementIndentStackSizeStack, new vector<int> );
  354.     inStatementIndentStackSizeStack->push_back(0);
  355.     INIT_CONTAINER( parenIndentStack, new vector<int> );
  356.  
  357.     immediatelyPreviousAssignmentOp = NULL;
  358.     previousLastLineHeader = NULL;
  359.  
  360.     isInQuote = false;
  361.     isInComment = false;
  362.     isInStatement = false;
  363.     isInCase = false;
  364.     isInQuestion = false;
  365.     isInClassHeader = false;
  366.     isInClassHeaderTab = false;
  367.     isInHeader = false;
  368.     isInOperator = false;
  369.     isInTemplate = false;
  370.     isInConst = false;
  371.     isInConditional = false;
  372.     templateDepth = 0;
  373.     parenDepth=0;
  374.     blockTabCount = 0;
  375.     leadingWhiteSpaces = 0;
  376.     prevNonSpaceCh = '{';
  377.     currentNonSpaceCh = '{';
  378.     prevNonLegalCh = '{';
  379.     currentNonLegalCh = '{';
  380.     prevFinalLineSpaceTabCount = 0;
  381.     prevFinalLineTabCount = 0;
  382.     probationHeader = NULL;
  383.     backslashEndsPrevLine = false;
  384.     isInDefine = false;
  385.     isInDefineDefinition = false;
  386.     defineTabCount = 0;
  387. }
  388.  
  389. /**
  390.  * set indentation style to ANSI C/C++.  
  391.  */
  392. void ASBeautifier::setCStyle()
  393. {
  394.     isCStyle = true;
  395. }
  396.  
  397. /**
  398.  * set indentation style to Java / K&R.  
  399.  */
  400. void ASBeautifier::setJavaStyle()
  401. {
  402.     isCStyle = false;
  403. }
  404.  
  405. /**
  406.  * indent using one tab per indentation
  407.  */
  408. void ASBeautifier::setTabIndentation(int length, bool forceTabs)
  409. {
  410.     indentString = "\t";
  411.     indentLength = length;
  412.     shouldForceTabIndentation = forceTabs;
  413.  
  414.     if (!isMinimalConditinalIndentSet)
  415.         minConditionalIndent = indentLength * 2;
  416. }
  417.  
  418. /**
  419.  * indent using a number of spaces per indentation.
  420.  *
  421.  * @param   length     number of spaces per indent.
  422.  */
  423. void ASBeautifier::setSpaceIndentation(int length)
  424. {
  425.     indentString=string(length, ' ');
  426.     indentLength = length;
  427.  
  428.     if (!isMinimalConditinalIndentSet)
  429.         minConditionalIndent = indentLength * 2;
  430. }
  431.  
  432. /**
  433.  * set the maximum indentation between two lines in a multi-line statement.
  434.  *
  435.  * @param   max     maximum indentation length.
  436.  */
  437. void ASBeautifier::setMaxInStatementIndentLength(int max)
  438. {
  439.     maxInStatementIndent = max;
  440. }
  441.  
  442. /**
  443.  * set the minimum indentation between two lines in a multi-line condition.
  444.  *
  445.  * @param   min     minimal indentation length.
  446.  */
  447. void ASBeautifier::setMinConditionalIndentLength(int min)
  448. {
  449.     minConditionalIndent = min;
  450.     isMinimalConditinalIndentSet = true;
  451. }
  452.  
  453. /**
  454.  * set the state of the bracket indentation option. If true, brackets will 
  455.  * be indented one additional indent.
  456.  *
  457.  * @param   state             state of option.
  458.  */
  459. void ASBeautifier::setBracketIndent(bool state)
  460. {
  461.     bracketIndent = state;
  462. }
  463.  
  464. /**
  465.  * set the state of the block indentation option. If true, entire blocks 
  466.  * will be indented one additional indent, similar to the GNU indent style.
  467.  *
  468.  * @param   state             state of option.
  469.  */
  470. void ASBeautifier::setBlockIndent(bool state)
  471. {
  472.     if (state)
  473.         setBracketIndent(false); // so that we don't have both bracket and block indent
  474.     blockIndent = state;
  475. }
  476.  
  477. /**
  478.  * set the state of the class indentation option. If true, C++ class
  479.  * definitions will be indented one additional indent.
  480.  *
  481.  * @param   state             state of option.
  482.  */
  483. void ASBeautifier::setClassIndent(bool state)
  484. {
  485.     classIndent = state;
  486. }
  487.  
  488. /**
  489.  * set the state of the switch indentation option. If true, blocks of 'switch' 
  490.  * statements will be indented one additional indent.
  491.  *
  492.  * @param   state             state of option.
  493.  */
  494. void ASBeautifier::setSwitchIndent(bool state)
  495. {
  496.     switchIndent = state;
  497. }
  498.  
  499. /**
  500.  * set the state of the case indentation option. If true, lines of 'case' 
  501.  * statements will be indented one additional indent.
  502.  *
  503.  * @param   state             state of option.
  504.  */
  505. void ASBeautifier::setCaseIndent(bool state)
  506. {
  507.     caseIndent = state;
  508. }
  509. /**
  510.  * set the state of the namespace indentation option. 
  511.  * If true, blocks of 'namespace' statements will be indented one 
  512.  * additional indent. Otherwise, NO indentation will be added.
  513.  *
  514.  * @param   state             state of option.
  515.  */
  516. void ASBeautifier::setNamespaceIndent(bool state)
  517. {
  518.     namespaceIndent = state;
  519. }
  520.  
  521. /**
  522.  * set the state of the label indentation option. 
  523.  * If true, labels will be indented one indent LESS than the
  524.  * current indentation level.
  525.  * If false, labels will be flushed to the left with NO
  526.  * indent at all.
  527.  *
  528.  * @param   state             state of option.
  529.  */
  530. void ASBeautifier::setLabelIndent(bool state)
  531. {
  532.     labelIndent = state;
  533. }
  534.  
  535. /**
  536.  * set the state of the preprocessor indentation option. 
  537.  * If true, multiline #define statements will be indented.
  538.  *
  539.  * @param   state             state of option.
  540.  */
  541. void ASBeautifier::setPreprocessorIndent(bool state)
  542. {
  543.     preprocessorIndent = state;
  544. }
  545.  
  546. /**
  547.  * set the state of the empty line fill option. 
  548.  * If true, empty lines will be filled with the whitespace.
  549.  * of their previous lines.
  550.  * If false, these lines will remain empty.
  551.  *
  552.  * @param   state             state of option.
  553.  */
  554. void ASBeautifier::setEmptyLineFill(bool state)
  555. {
  556.     emptyLineFill = state;
  557. }
  558.  
  559. /**
  560.  * check if there are any indented lines ready to be read by nextLine()
  561.  *
  562.  * @return    are there any indented lines ready?
  563.  */
  564. bool ASBeautifier::hasMoreLines() const
  565. {
  566.     return sourceIterator->hasMoreLines();
  567. }
  568.  
  569. /**
  570.  * get the next indented line.
  571.  *
  572.  * @return    indented line.
  573.  */
  574. string ASBeautifier::nextLine()
  575. {
  576.     return beautify(sourceIterator->nextLine());
  577. }
  578.  
  579. /**
  580.  * beautify a line of source code.
  581.  * every line of source code in a source code file should be sent
  582.  * one after the other to the beautify method.
  583.  *
  584.  * @return      the indented line.
  585.  * @param originalLine       the original unindented line.
  586.  */
  587. string ASBeautifier::beautify(const string &originalLine)
  588. {
  589.     string line;
  590.     bool isInLineComment = false;
  591.     bool lineStartsInComment = false;
  592.     bool isInClass = false;
  593.     bool isInSwitch = false;
  594.     bool isImmediatelyAfterConst = false;
  595.     bool isSpecialChar = false;
  596.     char ch = ' ';
  597.     char prevCh;
  598.     string outBuffer; // the newly idented line is bufferd here
  599.     int tabCount = 0;
  600.     const string *lastLineHeader = NULL;
  601.     bool closingBracketReached = false;
  602.     int spaceTabCount = 0;
  603.     char tempCh;
  604.     int headerStackSize = headerStack->size();
  605.     //bool isLineInStatement = isInStatement;
  606.     bool shouldIndentBrackettedLine = true;
  607.     int lineOpeningBlocksNum = 0;
  608.     int lineClosingBlocksNum = 0;
  609.     bool previousLineProbation = (probationHeader != NULL);
  610.     int i;
  611.  
  612.     currentHeader = NULL;
  613.  
  614.     lineStartsInComment = isInComment;
  615.  
  616.     // handle and remove white spaces around the line:
  617.     // If not in comment, first find out size of white space before line,
  618.     // so that possible comments starting in the line continue in
  619.     // relation to the preliminary white-space.
  620.     if (!isInComment)
  621.     {
  622.         leadingWhiteSpaces = 0;
  623.         while (leadingWhiteSpaces<originalLine.length() && originalLine[leadingWhiteSpaces] <= 0x20)
  624.             leadingWhiteSpaces++;
  625.  
  626.         line = trim(originalLine);
  627.     }
  628.     else
  629.     {
  630.         int trimSize;
  631.         for (trimSize=0;
  632.                 trimSize < originalLine.length() && trimSize<leadingWhiteSpaces && originalLine[trimSize] <= 0x20 ;
  633.                 trimSize++)
  634.             ;
  635.         line = originalLine.substr(trimSize);
  636.     }
  637.  
  638.  
  639.     if (line.length() == 0)
  640.     {
  641.         if (emptyLineFill)
  642.             return preLineWS(prevFinalLineSpaceTabCount, prevFinalLineTabCount);
  643.         else
  644.             return line;
  645.     }
  646.  
  647.     // handle preprocessor commands
  648.  
  649.     if (isCStyle && !isInComment && (line[0] == '#' || backslashEndsPrevLine))
  650.     {
  651.         if (line[0] == '#')
  652.         {
  653.             string preproc = trim(string(line.c_str() + 1));
  654.  
  655.  
  656.             // When finding a multi-lined #define statement, the original beautifier
  657.             // 1. sets its isInDefineDefinition flag
  658.             // 2. clones a new beautifier that will be used for the actual indentation
  659.             //    of the #define. This clone is put into the activeBeautifierStack in order
  660.             //    to be called for the actual indentation.
  661.             // The original beautifier will have isInDefineDefinition = true, isInDefine = false
  662.             // The cloned beautifier will have   isInDefineDefinition = true, isInDefine = true
  663.             if (preprocessorIndent && preproc.COMPARE(0, 6, string("define")) == 0 &&  line[line.length() - 1] == '\\')
  664.             {
  665.                 if (!isInDefineDefinition)
  666.                 {
  667.                     ASBeautifier *defineBeautifier;
  668.  
  669.                     // this is the original beautifier
  670.                     isInDefineDefinition = true;
  671.  
  672.                     // push a new beautifier into the active stack
  673.                     // this breautifier will be used for the indentation of this define
  674.                     defineBeautifier = new ASBeautifier(*this);
  675.                     //defineBeautifier->init();
  676.                     //defineBeautifier->isInDefineDefinition = true;
  677.                     //defineBeautifier->beautify("");
  678.                     activeBeautifierStack->push_back(defineBeautifier);
  679.                 }
  680.                 else
  681.                 {
  682.                     // the is the cloned beautifier that is in charge of indenting the #define.
  683.                     isInDefine = true;
  684.                 }
  685.             }
  686.             else if (preproc.COMPARE(0, 2, string("if")) == 0)
  687.             {
  688.                 // push a new beautifier into the stack
  689.                 waitingBeautifierStackLengthStack->push_back(waitingBeautifierStack->size());
  690.                 activeBeautifierStackLengthStack->push_back(activeBeautifierStack->size());
  691.                 waitingBeautifierStack->push_back(new ASBeautifier(*this));
  692.             }
  693.             else if (preproc.COMPARE(0, 4/*2*/, string("else")) == 0)
  694.             {
  695.                 if (!waitingBeautifierStack->empty())
  696.                 {
  697.                     // MOVE current waiting beautifier to active stack.
  698.                     activeBeautifierStack->push_back(waitingBeautifierStack->back());
  699.                     waitingBeautifierStack->pop_back();
  700.                 }
  701.             }
  702.             else if (preproc.COMPARE(0, 4, string("elif")) == 0)
  703.             {
  704.                 if (!waitingBeautifierStack->empty())
  705.                 {
  706.                     // append a COPY current waiting beautifier to active stack, WITHOUT deleting the original.
  707.                     activeBeautifierStack->push_back( new ASBeautifier( *(waitingBeautifierStack->back()) ) );
  708.                 }
  709.             }
  710.             else if (preproc.COMPARE(0, 5, string("endif")) == 0)
  711.             {
  712.                 int stackLength;
  713.                 ASBeautifier *beautifier;
  714.  
  715.                 if (!waitingBeautifierStackLengthStack->empty())
  716.                 {
  717.                     stackLength = waitingBeautifierStackLengthStack->back();
  718.                     waitingBeautifierStackLengthStack->pop_back();
  719.                     while (waitingBeautifierStack->size() > stackLength)
  720.                     {
  721.                         beautifier = waitingBeautifierStack->back();
  722.                         waitingBeautifierStack->pop_back();
  723.                         delete beautifier;
  724.                     }
  725.                 }
  726.  
  727.                 if (!activeBeautifierStackLengthStack->empty())
  728.                 {
  729.                     stackLength = activeBeautifierStackLengthStack->back();
  730.                     activeBeautifierStackLengthStack->pop_back();
  731.                     while (activeBeautifierStack->size() > stackLength)
  732.                     {
  733.                         beautifier = activeBeautifierStack->back();
  734.                         activeBeautifierStack->pop_back();
  735.                         delete beautifier;
  736.                     }
  737.                 }
  738.  
  739.  
  740.             }
  741.         }
  742.  
  743.         // check if the last char is a backslash
  744.         if(line.length() > 0)
  745.             backslashEndsPrevLine = (line[line.length() - 1] == '\\');
  746.         else
  747.             backslashEndsPrevLine = false;
  748.  
  749.         // check if this line ends a multi-line #define
  750.         // if so, use the #define's cloned beautifier for the line's indentation
  751.         // and then remove it from the active beautifier stack and delete it.
  752.         if (!backslashEndsPrevLine && isInDefineDefinition && !isInDefine)
  753.         {
  754.             string beautifiedLine;
  755.             ASBeautifier *defineBeautifier;
  756.  
  757.             isInDefineDefinition = false;
  758.             defineBeautifier = activeBeautifierStack->back();
  759.             activeBeautifierStack->pop_back();
  760.  
  761.             beautifiedLine = defineBeautifier->beautify(line);
  762.             delete defineBeautifier;
  763.             return beautifiedLine;
  764.         }
  765.  
  766.         // unless this is a multi-line #define, return this precompiler line as is.
  767.         if (!isInDefine && !isInDefineDefinition)
  768.             return originalLine;
  769.     }
  770.  
  771.     // if there exists any worker beautifier in the activeBeautifierStack,
  772.     // then use it instead of me to indent the current line.
  773.     if (!isInDefine && activeBeautifierStack != NULL && !activeBeautifierStack->empty())
  774.     {
  775.         return activeBeautifierStack->back()->beautify(line);
  776.     }
  777.  
  778.     // calculate preliminary indentation based on data from past lines
  779.     if (!inStatementIndentStack->empty())
  780.         spaceTabCount = inStatementIndentStack->back();
  781.  
  782.  
  783.     for (i=0; i<headerStackSize; i++)
  784.     {
  785.         isInClass = false;
  786.  
  787.         if (blockIndent || (!(i>0 && (*headerStack)[i-1] != &AS_OPEN_BRACKET
  788.                               && (*headerStack)[i] == &AS_OPEN_BRACKET)))
  789.             ++tabCount;
  790.  
  791.         if (isCStyle && !namespaceIndent && i >= 1
  792.                 && (*headerStack)[i-1] == &AS_NAMESPACE
  793.                 && (*headerStack)[i] == &AS_OPEN_BRACKET)
  794.             --tabCount;
  795.  
  796.         if (isCStyle && i >= 1
  797.                 && (*headerStack)[i-1] == &AS_CLASS
  798.                 && (*headerStack)[i] == &AS_OPEN_BRACKET )
  799.         {
  800.             if (classIndent)
  801.                 ++tabCount;
  802.             isInClass = true;
  803.         }
  804.  
  805.         // is the switchIndent option is on, indent switch statements an additional indent.
  806.         else if (switchIndent && i > 1 &&
  807.                  (*headerStack)[i-1] == &AS_SWITCH &&
  808.                  (*headerStack)[i] == &AS_OPEN_BRACKET
  809.                 )
  810.         {
  811.             ++tabCount;
  812.             isInSwitch = true;
  813.         }
  814.  
  815.     }
  816.  
  817.     if (!lineStartsInComment
  818.             && isCStyle 
  819.             && isInClass 
  820.             && classIndent 
  821.             && headerStackSize >= 2
  822.             &&(*headerStack)[headerStackSize-2] == &AS_CLASS
  823.             && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET 
  824.             && line[0] == '}')
  825.         --tabCount;
  826.  
  827.     else if (!lineStartsInComment
  828.             && isInSwitch 
  829.             && switchIndent 
  830.             && headerStackSize >= 2 
  831.             && (*headerStack)[headerStackSize-2] == &AS_SWITCH 
  832.             && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET 
  833.             && line[0] == '}')
  834.         --tabCount;
  835.  
  836.     if (isInClassHeader)
  837.     {
  838.         isInClassHeaderTab = true;
  839.         tabCount += 2;
  840.     }
  841.  
  842.     if (isInConditional)
  843.     {
  844.         --tabCount;
  845.     }
  846.  
  847.  
  848.     // parse characters in the current line.
  849.  
  850.     for (i=0; i<line.length(); i++)
  851.     {
  852.         tempCh = line[i];
  853.  
  854.         prevCh = ch;
  855.         ch = tempCh;
  856.  
  857.         outBuffer.append(1, ch);
  858.  
  859.         if (isWhiteSpace(ch))
  860.             continue;
  861.  
  862.         // handle special characters (i.e. backslash+character such as \n, \t, ...)
  863.         if (isSpecialChar)
  864.         {
  865.             isSpecialChar = false;
  866.             continue;
  867.         }
  868.         if (!(isInComment || isInLineComment) && line.COMPARE(i, 2, string("\\\\")) == 0)
  869.         {
  870.             outBuffer.append(1, '\\');
  871.             i++;
  872.             continue;
  873.         }
  874.         if (!(isInComment || isInLineComment) && ch=='\\')
  875.         {
  876.             isSpecialChar = true;
  877.             continue;
  878.         }
  879.  
  880.         // handle quotes (such as 'x' and "Hello Dolly")
  881.         if (!(isInComment || isInLineComment) && (ch=='"' || ch=='\''))
  882.             if (!isInQuote)
  883.             {
  884.                 quoteChar = ch;
  885.                 isInQuote = true;
  886.             }
  887.             else if (quoteChar == ch)
  888.             {
  889.                 isInQuote = false;
  890.                 isInStatement = true;
  891.                 continue;
  892.             }
  893.         if (isInQuote)
  894.             continue;
  895.  
  896.         // handle comments
  897.  
  898.         if ( !(isInComment || isInLineComment) && line.COMPARE(i, 2, AS_OPEN_LINE_COMMENT) == 0 )
  899.         {
  900.             isInLineComment = true;
  901.             outBuffer.append(1, '/');
  902.             i++;
  903.             continue;
  904.         }
  905.         else if ( !(isInComment || isInLineComment) && line.COMPARE(i, 2, AS_OPEN_COMMENT) == 0 )
  906.         {
  907.             isInComment = true;
  908.             outBuffer.append(1, '*');
  909.             i++;
  910.             continue;
  911.         }
  912.         else if ( (isInComment || isInLineComment) && line.COMPARE(i, 2, AS_CLOSE_COMMENT) == 0 )
  913.         {
  914.             isInComment = false;
  915.             outBuffer.append(1, '/');
  916.             i++;
  917.             continue;
  918.         }
  919.  
  920.         if (isInComment||isInLineComment)
  921.             continue;
  922.  
  923.         // if we have reached this far then we are NOT in a comment or string of special character...
  924.  
  925.         if (probationHeader != NULL)
  926.         {
  927.             if ( ((probationHeader == &AS_STATIC || probationHeader == &AS_CONST) && ch == '{')
  928.                     || (probationHeader == &AS_SYNCHRONIZED && ch == '('))
  929.             {
  930.                 // insert the probation header as a new header
  931.                 isInHeader = true;
  932.                 headerStack->push_back(probationHeader);
  933.  
  934.                 // handle the specific probation header
  935.                 isInConditional = (probationHeader == &AS_SYNCHRONIZED);
  936.                 if (probationHeader == &AS_CONST)
  937.                     isImmediatelyAfterConst = true;
  938.                 //  isInConst = true;
  939.                 /* TODO:
  940.                  * There is actually no more need for the global isInConst variable.
  941.                                * The only reason for checking const is to see if there is a const
  942.                  * immediately before an open-bracket.
  943.                  * Since CONST is now put into probation and is checked during itspost-char,
  944.                  * isImmediatelyAfterConst can be set by its own...
  945.                  */
  946.  
  947.                 isInStatement = false;
  948.                 // if the probation comes from the previous line, then indent by 1 tab count.
  949.                 if (previousLineProbation && ch == '{')
  950.                     tabCount++;
  951.                 previousLineProbation = false;
  952.             }
  953.  
  954.             // dismiss the probation header
  955.             probationHeader = NULL;
  956.         }
  957.  
  958.         prevNonSpaceCh = currentNonSpaceCh;
  959.         currentNonSpaceCh = ch;
  960.         if (!isLegalNameChar(ch) && ch != ',' && ch != ';' )
  961.         {
  962.             prevNonLegalCh = currentNonLegalCh;
  963.             currentNonLegalCh = ch;
  964.         }
  965.  
  966.         //if (isInConst)
  967.         //{
  968.         //    isInConst = false;
  969.         //    isImmediatelyAfterConst = true;
  970.         //}
  971.  
  972.         if (isInHeader)
  973.         {
  974.             isInHeader = false;
  975.             currentHeader = headerStack->back();
  976.         }
  977.         else
  978.             currentHeader = NULL;
  979.  
  980.         if (isCStyle && isInTemplate
  981.                 && (ch == '<' || ch == '>')
  982.                 &&  findHeader(line, i, nonAssignmentOperators) == NULL) //;
  983.         {
  984.             if (ch == '<')
  985.             {
  986.                 ++templateDepth;
  987.             }
  988.             else if (ch == '>')
  989.             {
  990.                 if (--templateDepth <= 0)
  991.                 {
  992.                     if (isInTemplate)
  993.                         ch = ';';
  994.                     else
  995.                         ch = 't';
  996.                     isInTemplate = false;
  997.                     templateDepth = 0;
  998.                 }
  999.             }
  1000.         }
  1001.  
  1002.         // handle parenthesies
  1003.         if (ch == '(' || ch == '[' || ch == ')' || ch == ']')
  1004.         {
  1005.             if (ch == '(' || ch == '[')
  1006.             {
  1007.                 if (parenDepth == 0)
  1008.                 {
  1009.                     parenStatementStack->push_back(isInStatement);
  1010.                     isInStatement = true;
  1011.                 }
  1012.                 parenDepth++;
  1013.  
  1014.                 inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
  1015.  
  1016.                 if (currentHeader != NULL)
  1017.                     registerInStatementIndent(line, i, spaceTabCount, minConditionalIndent/*indentLength*2*/, true);
  1018.                 else
  1019.                     registerInStatementIndent(line, i, spaceTabCount, 0, true);
  1020.             }
  1021.             else if (ch == ')' || ch == ']')
  1022.             {
  1023.                 parenDepth--;
  1024.                 if (parenDepth == 0)
  1025.                 {
  1026.                     isInStatement = parenStatementStack->back();
  1027.                     parenStatementStack->pop_back();
  1028.                     ch = ' ';
  1029.  
  1030.                     isInConditional = false;
  1031.                 }
  1032.  
  1033.                 if (!inStatementIndentStackSizeStack->empty())
  1034.                 {
  1035.                     int previousIndentStackSize = inStatementIndentStackSizeStack->back();
  1036.                     inStatementIndentStackSizeStack->pop_back();
  1037.                     while (previousIndentStackSize < inStatementIndentStack->size())
  1038.                         inStatementIndentStack->pop_back();
  1039.  
  1040.                     if (!parenIndentStack->empty())
  1041.                     {
  1042.                         int poppedIndent = parenIndentStack->back();
  1043.                         parenIndentStack->pop_back();
  1044.  
  1045.                         if (i == 0)
  1046.                             spaceTabCount = poppedIndent;
  1047.                     }
  1048.                 }
  1049.             }
  1050.  
  1051.             continue;
  1052.         }
  1053.  
  1054.  
  1055.         if (ch == '{')
  1056.         {
  1057.             bool isBlockOpener = false;
  1058.  
  1059.             // first, check if '{' is a block-opener or an static-array opener
  1060.             isBlockOpener = ( (prevNonSpaceCh == '{' && bracketBlockStateStack->back())
  1061.                               || prevNonSpaceCh == '}'
  1062.                               || prevNonSpaceCh == ')'
  1063.                               || prevNonSpaceCh == ';'
  1064.                               || isInClassHeader
  1065.                               || isBlockOpener
  1066.                               || isImmediatelyAfterConst
  1067.                               || (isInDefine &&
  1068.                                   (prevNonSpaceCh == '('
  1069.                                    || prevNonSpaceCh == '_'
  1070.                                    || isalnum(prevNonSpaceCh))) );
  1071.  
  1072.             isInClassHeader = false;
  1073.             if (!isBlockOpener && currentHeader != NULL)
  1074.             {
  1075.                 for (int n=0; n < nonParenHeaders.size(); n++)
  1076.                     if (currentHeader == nonParenHeaders[n])
  1077.                     {
  1078.                         isBlockOpener = true;
  1079.                         break;
  1080.                     }
  1081.             }
  1082.             bracketBlockStateStack->push_back(isBlockOpener);
  1083.             if (!isBlockOpener)
  1084.             {
  1085.                 inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
  1086.                 registerInStatementIndent(line, i, spaceTabCount, 0, true);
  1087.                 parenDepth++;
  1088.                 if (i == 0)
  1089.                     shouldIndentBrackettedLine = false;
  1090.  
  1091.                 continue;
  1092.             }
  1093.  
  1094.             // this bracket is a block opener...
  1095.  
  1096.             ++lineOpeningBlocksNum;
  1097.  
  1098.             if (isInClassHeader)
  1099.                 isInClassHeader = false;
  1100.             if (isInClassHeaderTab)
  1101.             {
  1102.                 isInClassHeaderTab = false;
  1103.                 tabCount -= 2;
  1104.             }
  1105.  
  1106.             blockParenDepthStack->push_back(parenDepth);
  1107.             blockStatementStack->push_back(isInStatement);
  1108.  
  1109.             inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
  1110.  
  1111.             blockTabCount += isInStatement? 1 : 0;
  1112.             parenDepth = 0;
  1113.             isInStatement = false;
  1114.  
  1115.             tempStacks->push_back(new vector<const string*>);
  1116.             headerStack->push_back(&AS_OPEN_BRACKET);
  1117.             lastLineHeader = &AS_OPEN_BRACKET; // <------
  1118.  
  1119.             continue;
  1120.         }
  1121.  
  1122.         //check if a header has been reached
  1123.         if (prevCh == ' ')
  1124.         {
  1125.             bool isIndentableHeader = true;
  1126.             const string *newHeader = findHeader(line, i, headers);
  1127.             if (newHeader != NULL)
  1128.             {
  1129.                 // if we reached here, then this is a header...
  1130.                 isInHeader = true;
  1131.  
  1132.                 vector<const string*> *lastTempStack;
  1133.                 if (tempStacks->empty())
  1134.                     lastTempStack = NULL;
  1135.                 else
  1136.                     lastTempStack = tempStacks->back();
  1137.  
  1138.                 // if a new block is opened, push a new stack into tempStacks to hold the
  1139.                 // future list of headers in the new block.
  1140.  
  1141.                 // take care of the special case: 'else if (...)'
  1142.                 if (newHeader == &AS_IF && lastLineHeader == &AS_ELSE)
  1143.                 {
  1144.                     //spaceTabCount += indentLength; // to counter the opposite addition that occurs when the 'if' is registered below...
  1145.                     headerStack->pop_back();
  1146.                 }
  1147.  
  1148.                 // take care of 'else'
  1149.                 else if (newHeader == &AS_ELSE)
  1150.                 {
  1151.                     if (lastTempStack != NULL)
  1152.                     {
  1153.                         int indexOfIf = indexOf(*lastTempStack, &AS_IF); // <---
  1154.                         if (indexOfIf != -1)
  1155.                         {
  1156.                             // recreate the header list in headerStack up to the previous 'if'
  1157.                             // from the temporary snapshot stored in lastTempStack.
  1158.                             int restackSize = lastTempStack->size() - indexOfIf - 1;
  1159.                             for (int r=0; r<restackSize; r++)
  1160.                             {
  1161.                                 headerStack->push_back(lastTempStack->back());
  1162.                                 lastTempStack->pop_back();
  1163.                             }
  1164.                             if (!closingBracketReached)
  1165.                                 tabCount += restackSize;
  1166.                         }
  1167.                         /*
  1168.                          * If the above if is not true, i.e. no 'if' before the 'else',
  1169.                          * then nothing beautiful will come out of this...
  1170.                          * I should think about inserting an Exception here to notify the caller of this...
  1171.                          */
  1172.                     }
  1173.                 }
  1174.  
  1175.                 // check if 'while' closes a previous 'do'
  1176.                 else if (newHeader == &AS_WHILE)
  1177.                 {
  1178.                     if (lastTempStack != NULL)
  1179.                     {
  1180.                         int indexOfDo = indexOf(*lastTempStack, &AS_DO); // <---
  1181.                         if (indexOfDo != -1)
  1182.                         {
  1183.                             // recreate the header list in headerStack up to the previous 'do'
  1184.                             // from the temporary snapshot stored in lastTempStack.
  1185.                             int restackSize = lastTempStack->size() - indexOfDo - 1;
  1186.                             for (int r=0; r<restackSize; r++)
  1187.                             {
  1188.                                 headerStack->push_back(lastTempStack->back());
  1189.                                 lastTempStack->pop_back();
  1190.                             }
  1191.                             if (!closingBracketReached)
  1192.                                 tabCount += restackSize;
  1193.                         }
  1194.                     }
  1195.                 }
  1196.                 // check if 'catch' closes a previous 'try' or 'catch'
  1197.                 else if (newHeader == &AS_CATCH || newHeader == &AS_FINALLY)
  1198.                 {
  1199.                     if (lastTempStack != NULL)
  1200.                     {
  1201.                         int indexOfTry = indexOf(*lastTempStack, &AS_TRY);
  1202.                         if (indexOfTry == -1)
  1203.                             indexOfTry = indexOf(*lastTempStack, &AS_CATCH);
  1204.                         if (indexOfTry != -1)
  1205.                         {
  1206.                             // recreate the header list in headerStack up to the previous 'try'
  1207.                             // from the temporary snapshot stored in lastTempStack.
  1208.                             int restackSize = lastTempStack->size() - indexOfTry - 1;
  1209.                             for (int r=0; r<restackSize; r++)
  1210.                             {
  1211.                                 headerStack->push_back(lastTempStack->back());
  1212.                                 lastTempStack->pop_back();
  1213.                             }
  1214.  
  1215.                             if (!closingBracketReached)
  1216.                                 tabCount += restackSize;
  1217.                         }
  1218.                     }
  1219.                 }
  1220.                 else if (newHeader == &AS_CASE)
  1221.                 {
  1222.                     isInCase = true;
  1223.                     if (!caseIndent)
  1224.                         --tabCount;
  1225.                 }
  1226.                 else if(newHeader == &AS_DEFAULT)
  1227.                 {
  1228.                     isInCase = true;
  1229.                     if (!caseIndent)
  1230.                         --tabCount;
  1231.                 }
  1232.                 else if (newHeader == &AS_PUBLIC || newHeader == &AS_PROTECTED || newHeader == &AS_PRIVATE)
  1233.                 {
  1234.                     if (isCStyle && !isInClassHeader)
  1235.                         --tabCount;
  1236.                     isIndentableHeader = false;
  1237.                 }
  1238.                 //else if ((newHeader == &STATIC || newHeader == &SYNCHRONIZED) &&
  1239.                 //         !headerStack->empty() &&
  1240.                 //         (headerStack->back() == &STATIC || headerStack->back() == &SYNCHRONIZED))
  1241.                 //{
  1242.                 //    isIndentableHeader = false;
  1243.                 //}
  1244.                 else if (newHeader == &AS_STATIC
  1245.                          || newHeader == &AS_SYNCHRONIZED
  1246.                          || (newHeader == &AS_CONST && isCStyle))
  1247.                 {
  1248.                     if (!headerStack->empty() &&
  1249.                             (headerStack->back() == &AS_STATIC
  1250.                              || headerStack->back() == &AS_SYNCHRONIZED
  1251.                              || headerStack->back() == &AS_CONST))
  1252.                     {
  1253.                         isIndentableHeader = false;
  1254.                     }
  1255.                     else
  1256.                     {
  1257.                         isIndentableHeader = false;
  1258.                         probationHeader = newHeader;
  1259.                     }
  1260.                 }
  1261.                 else if (newHeader == &AS_CONST)
  1262.                 {
  1263.                     // this will be entered only if NOT in C style
  1264.                     // since otherwise the CONST would be found to be a probstion header...
  1265.  
  1266.                     //if (isCStyle)
  1267.                     //  isInConst = true;
  1268.                     isIndentableHeader = false;
  1269.                 }
  1270.                 /*
  1271.                               else if (newHeader == &OPERATOR)
  1272.                               {
  1273.                                   if (isCStyle)
  1274.                                       isInOperator = true;
  1275.                                   isIndentableHeader = false;
  1276.                               }
  1277.                 */
  1278.                 else if (newHeader == &AS_TEMPLATE)
  1279.                 {
  1280.                     if (isCStyle)
  1281.                         isInTemplate = true;
  1282.                     isIndentableHeader = false;
  1283.                 }
  1284.  
  1285.  
  1286.                 if (isIndentableHeader)
  1287.                 {
  1288.                     // 3.2.99
  1289.                     //spaceTabCount-=indentLength;
  1290.                     headerStack->push_back(newHeader);
  1291.                     isInStatement = false;
  1292.                     if (indexOf(nonParenHeaders, newHeader) == -1)
  1293.                     {
  1294.                         isInConditional = true;
  1295.                     }
  1296.                     lastLineHeader = newHeader;
  1297.                 }
  1298.                 else
  1299.                     isInHeader = false;
  1300.  
  1301.                 //lastLineHeader = newHeader;
  1302.  
  1303.                 outBuffer.append(newHeader->substr(1));
  1304.                 i += newHeader->length() - 1;
  1305.  
  1306.                 continue;
  1307.             }
  1308.         }
  1309.  
  1310.         if (isCStyle && !isalpha(prevCh)
  1311.                 && line.COMPARE(i, 8, AS_OPERATOR) == 0 && !isalnum(line[i+8]))
  1312.         {
  1313.             isInOperator = true;
  1314.             outBuffer.append(AS_OPERATOR.substr(1));
  1315.             i += 7;
  1316.             continue;
  1317.         }
  1318.  
  1319.         if (ch == '?')
  1320.             isInQuestion = true;
  1321.  
  1322.  
  1323.         // special handling of 'case' statements
  1324.         if (ch == ':')
  1325.         {
  1326.             if (line.length() > i+1 && line[i+1] == ':') // look for ::
  1327.             {
  1328.                 ++i;
  1329.                 outBuffer.append(1, ':');
  1330.                 ch = ' ';
  1331.                 continue;
  1332.             }
  1333.  
  1334.             else if (isCStyle && isInClass && prevNonSpaceCh != ')')
  1335.             {
  1336.                 --tabCount;
  1337.                 // found a 'private:' or 'public:' inside a class definition
  1338.                 // so do nothing special
  1339.             }
  1340.  
  1341.             else if (isCStyle && isInClassHeader)
  1342.             {
  1343.  
  1344.                 // found a 'class A : public B' definition
  1345.                 // so do nothing special
  1346.             }
  1347.  
  1348.             else if (isInQuestion)
  1349.             {
  1350.                 isInQuestion = false;
  1351.             }
  1352.             else if (isCStyle && prevNonSpaceCh == ')')
  1353.             {
  1354.                 isInClassHeader = true;
  1355.                 if (i==0)
  1356.                     tabCount += 2;
  1357.             }
  1358.             else
  1359.             {
  1360.                 currentNonSpaceCh = ';'; // so that brackets after the ':' will appear as block-openers
  1361.                 if (isInCase)
  1362.                 {
  1363.                     isInCase = false;
  1364.                     ch = ';'; // from here on, treat char as ';'
  1365.                 }
  1366.  
  1367.  
  1368.                 else // is in a label (e.g. 'label1:')
  1369.                 {
  1370.                     if (labelIndent)
  1371.                         --tabCount; // unindent label by one indent
  1372.                     else
  1373.                         tabCount = 0; // completely flush indent to left
  1374.                 }
  1375.  
  1376.  
  1377.  
  1378.             }
  1379.         }
  1380.  
  1381.         if ((ch == ';'  || (parenDepth>0 && ch == ','))  && !inStatementIndentStackSizeStack->empty())
  1382.             while (inStatementIndentStackSizeStack->back() + (parenDepth>0 ? 1 : 0)  < inStatementIndentStack->size())
  1383.                 inStatementIndentStack->pop_back();
  1384.  
  1385.  
  1386.         // handle ends of statements
  1387.         if ( (ch == ';' && parenDepth == 0) || ch == '}'/* || (ch == ',' && parenDepth == 0)*/)
  1388.         {
  1389.             if (ch == '}')
  1390.             {
  1391.                 // first check if this '}' closes a previous block, or a static array...
  1392.                 if (!bracketBlockStateStack->empty())
  1393.                 {
  1394.                     bool bracketBlockState = bracketBlockStateStack->back();
  1395.                     bracketBlockStateStack->pop_back();
  1396.                     if (!bracketBlockState)
  1397.                     {
  1398.                         if (!inStatementIndentStackSizeStack->empty())
  1399.                         {
  1400.                             // this bracket is a static array
  1401.  
  1402.                             int previousIndentStackSize = inStatementIndentStackSizeStack->back();
  1403.                             inStatementIndentStackSizeStack->pop_back();
  1404.                             while (previousIndentStackSize < inStatementIndentStack->size())
  1405.                                 inStatementIndentStack->pop_back();
  1406.                             parenDepth--;
  1407.                             if (i == 0)
  1408.                                 shouldIndentBrackettedLine = false;
  1409.  
  1410.                             if (!parenIndentStack->empty())
  1411.                             {
  1412.                                 int poppedIndent = parenIndentStack->back();
  1413.                                 parenIndentStack->pop_back();
  1414.                                 if (i == 0)
  1415.                                     spaceTabCount = poppedIndent;
  1416.                             }
  1417.                         }
  1418.                         continue;
  1419.                     }
  1420.                 }
  1421.  
  1422.                 // this bracket is block closer...
  1423.  
  1424.                 ++lineClosingBlocksNum;
  1425.  
  1426.                 if(!inStatementIndentStackSizeStack->empty())
  1427.                     inStatementIndentStackSizeStack->pop_back();
  1428.  
  1429.                 if (!blockParenDepthStack->empty())
  1430.                 {
  1431.                     parenDepth = blockParenDepthStack->back();
  1432.                     blockParenDepthStack->pop_back();
  1433.                     isInStatement = blockStatementStack->back();
  1434.                     blockStatementStack->pop_back();
  1435.  
  1436.                     if (isInStatement)
  1437.                         blockTabCount--;
  1438.                 }
  1439.  
  1440.                 closingBracketReached = true;
  1441.                 int headerPlace = indexOf(*headerStack, &AS_OPEN_BRACKET); // <---
  1442.                 if (headerPlace != -1)
  1443.                 {
  1444.                     const string *popped = headerStack->back();
  1445.                     while (popped != &AS_OPEN_BRACKET)
  1446.                     {
  1447.                         headerStack->pop_back();
  1448.                         popped = headerStack->back();
  1449.                     }
  1450.                     headerStack->pop_back();
  1451.  
  1452.                     if (!tempStacks->empty())
  1453.                     {
  1454.                         vector<const string*> *temp =  tempStacks->back();
  1455.                         tempStacks->pop_back();
  1456.                         delete temp;
  1457.                     }
  1458.                 }
  1459.  
  1460.  
  1461.                 ch = ' '; // needed due to cases such as '}else{', so that headers ('else' tn tih case) will be identified...
  1462.             }
  1463.  
  1464.             /*
  1465.              * Create a temporary snapshot of the current block's header-list in the
  1466.              * uppermost inner stack in tempStacks, and clear the headerStack up to
  1467.              * the begining of the block.
  1468.              * Thus, the next future statement will think it comes one indent past
  1469.              * the block's '{' unless it specifically checks for a companion-header
  1470.              * (such as a previous 'if' for an 'else' header) within the tempStacks,
  1471.              * and recreates the temporary snapshot by manipulating the tempStacks.
  1472.              */
  1473.             if (!tempStacks->back()->empty())
  1474.                 while (!tempStacks->back()->empty())
  1475.                     tempStacks->back()->pop_back();
  1476.             while (!headerStack->empty() && headerStack->back() != &AS_OPEN_BRACKET)
  1477.             {
  1478.                 tempStacks->back()->push_back(headerStack->back());
  1479.                 headerStack->pop_back();
  1480.             }
  1481.  
  1482.             if (parenDepth == 0 && ch == ';')
  1483.                 isInStatement=false;
  1484.  
  1485.             isInClassHeader = false;
  1486.  
  1487.             continue;
  1488.         }
  1489.  
  1490.  
  1491.         // check for preBlockStatements ONLY if not within parenthesies
  1492.         // (otherwise 'struct XXX' statements would be wrongly interpreted...)
  1493.         if (prevCh == ' ' && !isInTemplate && parenDepth == 0)
  1494.         {
  1495.             const string *newHeader = findHeader(line, i, preBlockStatements);
  1496.             if (newHeader != NULL)
  1497.             {
  1498.                 isInClassHeader = true;
  1499.                 outBuffer.append(newHeader->substr(1));
  1500.                 i += newHeader->length() - 1;
  1501.                 //if (isCStyle)
  1502.                 headerStack->push_back(newHeader);
  1503.             }
  1504.         }
  1505.  
  1506.         // Handle operators
  1507.         //
  1508.  
  1509. ////        // PRECHECK if a '==' or '--' or '++' operator was reached.
  1510. ////        // If not, then register an indent IF an assignment operator was reached.
  1511. ////        // The precheck is important, so that statements such as 'i--==2' are not recognized
  1512. ////        // to have assignment operators (here, '-=') in them . . .
  1513.  
  1514.         const string *foundAssignmentOp = NULL;
  1515.         const string *foundNonAssignmentOp = NULL;
  1516.  
  1517.         immediatelyPreviousAssignmentOp = NULL;
  1518.  
  1519.         // Check if an operator has been reached.
  1520.         foundAssignmentOp = findHeader(line, i, assignmentOperators, false); 
  1521.         foundNonAssignmentOp = findHeader(line, i, nonAssignmentOperators, false); 
  1522.  
  1523.         // Since findHeader's boundry checking was not used above, it is possible
  1524.         // that both an assignment op and a non-assignment op where found,
  1525.         // e.g. '>>' and '>>='. If this is the case, treat the LONGER one as the 
  1526.         // found operator.
  1527.         if (foundAssignmentOp != NULL && foundNonAssignmentOp != NULL)
  1528.             if (foundAssignmentOp->length() < foundNonAssignmentOp->length())
  1529.                 foundAssignmentOp = NULL;
  1530.             else
  1531.                 foundNonAssignmentOp = NULL;
  1532.  
  1533.         if (foundNonAssignmentOp != NULL)
  1534.         {
  1535.             if (foundNonAssignmentOp->length() > 1)
  1536.             {
  1537.                 outBuffer.append(foundNonAssignmentOp->substr(1));
  1538.                 i += foundNonAssignmentOp->length() - 1;
  1539.             }
  1540.         }
  1541.  
  1542.         else if (foundAssignmentOp != NULL)
  1543.         {
  1544.             if (foundAssignmentOp->length() > 1)
  1545.             {
  1546.                 outBuffer.append(foundAssignmentOp->substr(1));
  1547.                 i += foundAssignmentOp->length() - 1;
  1548.             }
  1549.  
  1550.             if (!isInOperator && !isInTemplate)
  1551.             {
  1552.                 registerInStatementIndent(line, i, spaceTabCount, 0, false);
  1553.                 immediatelyPreviousAssignmentOp = foundAssignmentOp;
  1554.                 isInStatement = true;
  1555.             }
  1556.         }
  1557.  
  1558. /*
  1559.         immediatelyPreviousAssignmentOp = NULL;
  1560.         bool isNonAssingmentOperator = false;
  1561.         for (int n = 0; n < nonAssignmentOperators.size(); n++)
  1562.             if (line.COMPARE(i, nonAssignmentOperators[n]->length(), *(nonAssignmentOperators[n])) == 0)
  1563.             {
  1564.                 if (nonAssignmentOperators[n]->length() > 1)
  1565.                 {
  1566.                     outBuffer.append(nonAssignmentOperators[n]->substr(1));
  1567.                     i += nonAssignmentOperators[n]->length() - 1;
  1568.                 }
  1569.                 isNonAssingmentOperator = true;
  1570.                 break;
  1571.             }
  1572.         if (!isNonAssingmentOperator)
  1573.         {
  1574.             for (int a = 0; a < assignmentOperators.size(); a++)
  1575.                 if (line.COMPARE(i, assignmentOperators[a]->length(), *(assignmentOperators[a])) == 0)
  1576.                 {
  1577.                     if (assignmentOperators[a]->length() > 1)
  1578.                     {
  1579.                         outBuffer.append(assignmentOperators[a]->substr(1));
  1580.                         i += assignmentOperators[a]->length() - 1;
  1581.                     }
  1582.  
  1583.                     if (!isInOperator && !isInTemplate)
  1584.                     {
  1585.                         registerInStatementIndent(line, i, spaceTabCount, 0, false);
  1586.                         immediatelyPreviousAssignmentOp = assignmentOperators[a];
  1587.                         isInStatement = true;
  1588.                     }
  1589.                     break;
  1590.                 }
  1591.         }
  1592. */
  1593.  
  1594.         if (isInOperator)
  1595.             isInOperator = false;
  1596.     }
  1597.  
  1598.     // handle special cases of unindentation:
  1599.  
  1600.     /*
  1601.      * if '{' doesn't follow an immediately previous '{' in the headerStack
  1602.      * (but rather another header such as "for" or "if", then unindent it
  1603.      * by one indentation relative to its block.
  1604.      */
  1605.     //    cerr << endl << lineOpeningBlocksNum << " " <<  lineClosingBlocksNum << " " <<  previousLastLineHeader << endl;
  1606.  
  1607.     // indent #define lines with one less tab
  1608.     //if (isInDefine)
  1609.     //    tabCount -= defineTabCount-1;
  1610.  
  1611.  
  1612.     if (!lineStartsInComment
  1613.             && !blockIndent 
  1614.             && outBuffer.length()>0
  1615.             && outBuffer[0]=='{'
  1616.             && !(lineOpeningBlocksNum > 0 && lineOpeningBlocksNum == lineClosingBlocksNum)
  1617.             && !(headerStack->size() > 1 && (*headerStack)[headerStack->size()-2] == &AS_OPEN_BRACKET)
  1618.             && shouldIndentBrackettedLine)
  1619.         --tabCount;
  1620.  
  1621.     else if (!lineStartsInComment
  1622.             && outBuffer.length()>0 
  1623.             && outBuffer[0]=='}' 
  1624.             && shouldIndentBrackettedLine )
  1625.         --tabCount;
  1626.  
  1627.     // correctly indent one-line-blocks...
  1628.     else if (!lineStartsInComment
  1629.              && outBuffer.length()>0
  1630.              && lineOpeningBlocksNum > 0
  1631.              && lineOpeningBlocksNum == lineClosingBlocksNum
  1632.              && previousLastLineHeader != NULL
  1633.              && previousLastLineHeader != &AS_OPEN_BRACKET)
  1634.         tabCount -= 1; //lineOpeningBlocksNum - (blockIndent ? 1 : 0);
  1635.  
  1636.     if (tabCount < 0)
  1637.         tabCount = 0;
  1638.  
  1639.     // take care of extra bracket indentatation option...
  1640.     if (bracketIndent && outBuffer.length()>0 && shouldIndentBrackettedLine)
  1641.         if (outBuffer[0]=='{' || outBuffer[0]=='}')
  1642.             tabCount++;
  1643.  
  1644.  
  1645.     if (isInDefine)
  1646.     {
  1647.         if (outBuffer[0] == '#')
  1648.         {
  1649.             string preproc = trim(string(outBuffer.c_str() + 1));
  1650.             if (preproc.COMPARE(0, 6, string("define")) == 0)
  1651.             {
  1652.                 if (!inStatementIndentStack->empty()
  1653.                         && inStatementIndentStack->back() > 0)
  1654.                 {
  1655.                     defineTabCount = tabCount;
  1656.                 }
  1657.                 else
  1658.                 {
  1659.                     defineTabCount = tabCount - 1;
  1660.                     tabCount--;
  1661.                 }
  1662.             }
  1663.         }
  1664.  
  1665.         tabCount -= defineTabCount;
  1666.     }
  1667.  
  1668.     if (tabCount < 0)
  1669.         tabCount = 0;
  1670.  
  1671.  
  1672.     // finally, insert indentations into begining of line
  1673.  
  1674.     prevFinalLineSpaceTabCount = spaceTabCount;
  1675.     prevFinalLineTabCount = tabCount;
  1676.  
  1677.     if (shouldForceTabIndentation) {
  1678.         tabCount += spaceTabCount / indentLength;
  1679.         spaceTabCount = spaceTabCount % indentLength;
  1680.     }
  1681.  
  1682.     outBuffer = preLineWS(spaceTabCount,tabCount) + outBuffer;
  1683.  
  1684.     if (lastLineHeader != NULL)
  1685.         previousLastLineHeader = lastLineHeader;
  1686.  
  1687.     return outBuffer;
  1688. }
  1689.  
  1690.  
  1691. string ASBeautifier::preLineWS(int spaceTabCount, int tabCount)
  1692. {
  1693.     string ws;
  1694.  
  1695.     for (int i=0; i<tabCount; i++)
  1696.         ws += indentString;
  1697.  
  1698.     while ((spaceTabCount--) > 0)
  1699.         ws += string(" ");
  1700.  
  1701.     return ws;
  1702.  
  1703. }
  1704.  
  1705. /**
  1706.  * register an in-statement indent.
  1707.  */
  1708. void ASBeautifier::registerInStatementIndent(const string &line, int i, int spaceTabCount,
  1709.         int minIndent, bool updateParenStack)
  1710. {
  1711.     int inStatementIndent;
  1712.     int remainingCharNum = line.length() - i;
  1713.     int nextNonWSChar = 1;
  1714.  
  1715.     nextNonWSChar = getNextProgramCharDistance(line, i);
  1716.  
  1717.     // if indent is around the last char in the line, indent instead 2 spaces from the previous indent
  1718.     if (nextNonWSChar == remainingCharNum)
  1719.     {
  1720.         int previousIndent = spaceTabCount;
  1721.         if (!inStatementIndentStack->empty())
  1722.             previousIndent = inStatementIndentStack->back();
  1723.  
  1724.         inStatementIndentStack->push_back(/*2*/ indentLength + previousIndent );
  1725.         if (updateParenStack)
  1726.             parenIndentStack->push_back( previousIndent );
  1727.         return;
  1728.     }
  1729.  
  1730.     if (updateParenStack)
  1731.         parenIndentStack->push_back(i+spaceTabCount);
  1732.  
  1733.     inStatementIndent = i + nextNonWSChar + spaceTabCount;
  1734.  
  1735.     if (i + nextNonWSChar < minIndent)
  1736.         inStatementIndent = minIndent + spaceTabCount;
  1737.  
  1738.     if (i + nextNonWSChar > maxInStatementIndent)
  1739.         inStatementIndent =  indentLength*2 + spaceTabCount;
  1740.  
  1741.  
  1742.  
  1743.     if (!inStatementIndentStack->empty() &&
  1744.             inStatementIndent < inStatementIndentStack->back())
  1745.         inStatementIndent = inStatementIndentStack->back();
  1746.  
  1747.     inStatementIndentStack->push_back(inStatementIndent);
  1748. }
  1749.  
  1750. /**
  1751.  * get distance to the next non-white sspace, non-comment character in the line.
  1752.  * if no such character exists, return the length remaining to the end of the line.
  1753.  */
  1754. int ASBeautifier::getNextProgramCharDistance(const string &line, int i)
  1755. {
  1756.     bool inComment = false;
  1757.     int remainingCharNum = line.length() - i;
  1758.     int charDistance = 1;
  1759.     int ch;
  1760.  
  1761.     for (charDistance = 1; charDistance < remainingCharNum; charDistance++)
  1762.     {
  1763.         ch = line[i + charDistance];
  1764.         if (inComment)
  1765.         {
  1766.             if (line.COMPARE(i + charDistance, 2, AS_CLOSE_COMMENT) == 0)
  1767.             {
  1768.                 charDistance++;
  1769.                 inComment = false;
  1770.             }
  1771.             continue;
  1772.         }
  1773.         else if (isWhiteSpace(ch))
  1774.             continue;
  1775.         else if (ch == '/')
  1776.         {
  1777.             if (line.COMPARE(i + charDistance, 2, AS_OPEN_LINE_COMMENT) == 0)
  1778.                 return remainingCharNum;
  1779.             else if (line.COMPARE(i + charDistance, 2, AS_OPEN_COMMENT) == 0)
  1780.             {
  1781.                 charDistance++;
  1782.                 inComment = true;
  1783.             }
  1784.         }
  1785.         else
  1786.             return charDistance;
  1787.     }
  1788.  
  1789.     return charDistance;
  1790. }
  1791.  
  1792.  
  1793. /**
  1794.  * check if a specific character can be used in a legal variable/method/class name
  1795.  *
  1796.  * @return          legality of the char.
  1797.  * @param ch        the character to be checked.
  1798.  */
  1799. bool ASBeautifier::isLegalNameChar(char ch) const
  1800. {
  1801.     return (isalnum(ch) //(ch>='a' && ch<='z') || (ch>='A' && ch<='Z') || (ch>='0' && ch<='9') ||
  1802.             || ch=='.' || ch=='_' || (!isCStyle && ch=='$') || (isCStyle && ch=='~'));
  1803. }
  1804.  
  1805.  
  1806. /**
  1807.  * check if a specific line position contains a header, out of several possible headers.
  1808.  *
  1809.  * @return    a pointer to the found header. if no header was found then return NULL.
  1810.  */
  1811. const string *ASBeautifier::findHeader(const string &line, int i, const vector<const string*> &possibleHeaders, bool checkBoundry)
  1812. {
  1813.     int maxHeaders = possibleHeaders.size();
  1814.     const string *header = NULL;
  1815.     int p;
  1816.  
  1817.     for (p=0; p < maxHeaders; p++)
  1818.     {
  1819.         header = possibleHeaders[p];
  1820.         
  1821.         if (line.COMPARE(i, header->length(), *header) == 0)
  1822.         {
  1823.             // check that this is a header and not a part of a longer word
  1824.             // (e.g. not at its begining, not at its middle...)
  1825.             
  1826.             int lineLength = line.length();
  1827.             int headerEnd = i + header->length();
  1828.             char startCh = (*header)[0];   // first char of header
  1829.             char endCh = 0;                // char just after header
  1830.             char prevCh = 0;               // char just before header
  1831.  
  1832.             if (headerEnd < lineLength)
  1833.             {
  1834.                 endCh = line[headerEnd];
  1835.             }
  1836.             if (i > 0)
  1837.             {
  1838.                 prevCh = line[i-1];
  1839.             }
  1840.  
  1841.             if (!checkBoundry)
  1842.             {
  1843.                 return header;
  1844.             }
  1845.             else if (prevCh != 0 
  1846.                         && isLegalNameChar(startCh) 
  1847.                         && isLegalNameChar(prevCh))
  1848.             {
  1849.                 return NULL;
  1850.             }
  1851.             else if (headerEnd >= lineLength 
  1852.                     || !isLegalNameChar(startCh) 
  1853.                     || !isLegalNameChar(endCh))
  1854.             {
  1855.                 return header;
  1856.             }
  1857.             else
  1858.             {
  1859.                 return NULL;
  1860.             }
  1861.         }
  1862.     }
  1863.  
  1864.     return NULL;
  1865. }
  1866.  
  1867.  
  1868. /**
  1869.  * check if a specific character can be used in a legal variable/method/class name
  1870.  *
  1871.  * @return          legality of the char.
  1872.  * @param ch        the character to be checked.
  1873.  */
  1874. bool ASBeautifier::isWhiteSpace(char ch) const
  1875. {
  1876.     return (ch == ' ' || ch == '\t');
  1877. }
  1878.  
  1879. /**
  1880.  * find the index number of a string element in a container of strings
  1881.  *
  1882.  * @return              the index number of element in the ocntainer. -1 if element not found.
  1883.  * @param container     a vector of strings.
  1884.  * @param element       the element to find .
  1885.  */
  1886. int ASBeautifier::indexOf(vector<const string*> &container, const string *element)
  1887. {
  1888.     vector<const string*>::const_iterator where;
  1889.  
  1890.     where= find(container.begin(), container.end(), element);
  1891.     if (where == container.end())
  1892.         return -1;
  1893.     else
  1894.         return where - container.begin();
  1895. }
  1896.  
  1897. /**
  1898.  * trim removes the white space surrounding a line.
  1899.  *
  1900.  * @return          the trimmed line.
  1901.  * @param str       the line to trim.
  1902.  */
  1903. string ASBeautifier::trim(const string &str)
  1904. {
  1905.  
  1906.     int start = 0;
  1907.     int end = str.length() - 1;
  1908.  
  1909.     while (start < end && isWhiteSpace(str[start]))
  1910.         start++;
  1911.  
  1912.     while (start <= end && isWhiteSpace(str[end]))
  1913.         end--;
  1914.  
  1915.     string returnStr(str, start, end+1-start);
  1916.     return returnStr;
  1917. }
  1918.  
  1919. #ifdef USES_NAMESPACE
  1920. }
  1921. #endif
  1922.  
  1923.