~ubuntu-branches/ubuntu/raring/codeblocks/raring-proposed

« back to all changes in this revision

Viewing changes to src/plugins/astyle/astyle/ASBeautifier.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Cosme Domínguez Díaz
  • Date: 2010-08-09 04:38:38 UTC
  • mfrom: (1.1.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20100809043838-a59ygguym4eg0jgw
Tags: 10.05-0ubuntu1
* New upstream release. Closes (LP: #322350)
 - Switch to dpkg-source 3.0 (quilt) format
 - Remove unneeded README.source
 - Add debian/get-source-orig script that removes all
   Windows prebuilt binaries
* Bump Standards-Version to 3.9.1
 - Stop shipping *.la files
* debian/control
 - Add cdbs package as Build-Depend
 - Add libbz2-dev and zlib1g-dev packages as
   Build-Depends (needed by libhelp_plugin.so)
 - Remove dpatch package of Build-Depends
 - Add codeblocks-contrib-debug package
 - Split architecture-independent files of codeblocks
   package in codeblocks-common package
* debian/rules
 - Switch to CDBS rules system
 - Add parallel build support
 - Add a call to debian/get-source-orig script
 - Use lzma compression (saves 23,5 MB of free space)
* debian/patches
 - Refresh 01_codeblocks_plugin_path
 - Add 02_no_Makefiles_in_debian_dir to remove any link
   in codeblocks build system to deleted Makefiles of debian directory
 - Drop 02_ftbfs_gcc44 and 03_ftbfs_glib221 (merged in upstream)
* debian/watch
 - Update to use the new host (berlios.de)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
2
 *
3
 
 *   ASBeautifier.cpp
 
3
 *   Copyright (C) 2006-2009 by Jim Pattee <jimp03@email.com>
 
4
 *   Copyright (C) 1998-2002 by Tal Davidson
 
5
 *   <http://www.gnu.org/licenses/lgpl-3.0.html>
4
6
 *
5
 
 *   This file is a part of "Artistic Style" - an indentation and
 
7
 *   This file is a part of Artistic Style - an indentation and
6
8
 *   reformatting tool for C, C++, C# and Java source files.
7
 
 *   http://astyle.sourceforge.net
8
 
 *
9
 
 *   The "Artistic Style" project, including all files needed to
10
 
 *   compile it, is free software; you can redistribute it and/or
11
 
 *   modify it under the terms of the GNU Lesser General Public
12
 
 *   License as published by the Free Software Foundation; either
13
 
 *   version 2.1 of the License, or (at your option) any later
14
 
 *   version.
15
 
 *
16
 
 *   This program is distributed in the hope that it will be useful,
 
9
 *   <http://astyle.sourceforge.net>
 
10
 *
 
11
 *   Artistic Style is free software: you can redistribute it and/or modify
 
12
 *   it under the terms of the GNU Lesser General Public License as published
 
13
 *   by the Free Software Foundation, either version 3 of the License, or
 
14
 *   (at your option) any later version.
 
15
 *
 
16
 *   Artistic Style is distributed in the hope that it will be useful,
17
17
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
18
18
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
19
 *   GNU Lesser General Public License for more details.
20
20
 *
21
 
 *   You should have received a copy of the GNU Lesser General Public
22
 
 *   License along with this project; if not, write to the
23
 
 *   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24
 
 *   Boston, MA  02110-1301, USA.
 
21
 *   You should have received a copy of the GNU Lesser General Public License
 
22
 *   along with Artistic Style.  If not, see <http://www.gnu.org/licenses/>.
25
23
 *
26
24
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
27
25
 */
32
30
#include <iostream>
33
31
 
34
32
 
35
 
#define INIT_CONTAINER(container, value)     {if ( (container) != NULL ) delete (container); (container) = (value); }
36
 
#define DELETE_CONTAINER(container)          {if ( (container) != NULL ) delete (container); }
37
 
 
38
 
 
39
33
namespace astyle
40
34
{
 
35
// static member variables
 
36
int ASBeautifier::beautifierFileType = 9;               // initialized with an invalid type
41
37
vector<const string*> ASBeautifier::headers;
42
38
vector<const string*> ASBeautifier::nonParenHeaders;
43
39
vector<const string*> ASBeautifier::preBlockStatements;
44
40
vector<const string*> ASBeautifier::assignmentOperators;
45
41
vector<const string*> ASBeautifier::nonAssignmentOperators;
 
42
vector<const string*> ASBeautifier::indentableHeaders;
46
43
 
47
44
 
48
45
/*
50
47
 */
51
48
void ASBeautifier::initStatic()
52
49
{
53
 
        static int beautifierFileType = 9;     // initialized with an invalid type
54
 
 
55
50
        if (fileType == beautifierFileType)    // don't build unless necessary
56
51
                return;
57
52
 
62
57
        assignmentOperators.clear();
63
58
        nonAssignmentOperators.clear();
64
59
        preBlockStatements.clear();
 
60
        indentableHeaders.clear();
65
61
 
66
62
        ASResource::buildHeaders(headers, fileType, true);
67
63
        ASResource::buildNonParenHeaders(nonParenHeaders, fileType, true);
68
64
        ASResource::buildAssignmentOperators(assignmentOperators);
69
65
        ASResource::buildNonAssignmentOperators(nonAssignmentOperators);
70
 
        ASResource::buildPreBlockStatements(preBlockStatements);
71
 
 
72
 
//      cout << "beaut" << endl;
 
66
        ASResource::buildPreBlockStatements(preBlockStatements, fileType);
 
67
        ASResource::buildIndentableHeaders(indentableHeaders);
73
68
}
74
69
 
75
70
/**
98
93
 
99
94
        setSpaceIndentation(4);
100
95
        setMaxInStatementIndentLength(40);
 
96
        classInitializerTabs = 1;
101
97
        setClassIndent(false);
102
98
        setSwitchIndent(false);
103
99
        setCaseIndent(false);
113
109
 
114
110
/**
115
111
 * ASBeautifier's copy constructor
 
112
 * must explicitly call the base class copy constructor
116
113
 */
117
 
ASBeautifier::ASBeautifier(const ASBeautifier &other)
 
114
ASBeautifier::ASBeautifier(const ASBeautifier &other) : ASBase(other)
118
115
{
 
116
        // these don't need to copy the stack
119
117
        waitingBeautifierStack = NULL;
120
118
        activeBeautifierStack = NULL;
121
119
        waitingBeautifierStackLengthStack = NULL;
122
120
        activeBeautifierStackLengthStack = NULL;
123
121
 
 
122
        // vector '=' operator performs a DEEP copy of all elements in the vector
 
123
 
124
124
        headerStack  = new vector<const string*>;
125
125
        *headerStack = *other.headerStack;
126
126
 
158
158
        sourceIterator = other.sourceIterator;
159
159
 
160
160
        // protected variables
161
 
        fileType = other.fileType;
162
 
        isCStyle = other.isCStyle;
163
 
        isJavaStyle = other.isJavaStyle;
164
 
        isSharpStyle = other.isSharpStyle;
165
 
 
166
161
        // variables set by ASFormatter
167
 
        // must also be updated in preprocessor
 
162
        // must also be updated in activeBeautifierStack
168
163
        inLineNumber = other.inLineNumber;
169
 
        outLineNumber = other.outLineNumber;
 
164
        horstmannIndentInStatement = other.horstmannIndentInStatement;
 
165
        nonInStatementBracket = other.nonInStatementBracket;
170
166
        lineCommentNoBeautify = other.lineCommentNoBeautify;
171
167
        isNonInStatementArray = other.isNonInStatementArray;
 
168
        isSharpAccessor = other.isSharpAccessor;
 
169
        isSharpDelegate = other.isSharpDelegate;
 
170
        isInExtern = other.isInExtern;
 
171
        isInEnum = other.isInEnum;
172
172
 
173
173
        // private variables
174
174
        indentString = other.indentString;
175
175
        currentHeader = other.currentHeader;
176
176
        previousLastLineHeader = other.previousLastLineHeader;
177
 
        immediatelyPreviousAssignmentOp = other.immediatelyPreviousAssignmentOp;
178
177
        probationHeader = other.probationHeader;
179
178
        isInQuote = other.isInQuote;
 
179
        isInVerbatimQuote = other.isInVerbatimQuote;
 
180
        haveLineContinuationChar = other.haveLineContinuationChar;
180
181
        isInComment = other.isInComment;
181
182
        isInCase = other.isInCase;
182
183
        isInQuestion = other.isInQuestion;
183
184
        isInStatement = other.isInStatement;
184
185
        isInHeader = other.isInHeader;
185
 
        isInOperator = other.isInOperator;
186
186
        isInTemplate = other.isInTemplate;
187
187
        isInDefine = other.isInDefine;
188
188
        isInDefineDefinition = other.isInDefineDefinition;
200
200
        isMinimalConditinalIndentSet = other.isMinimalConditinalIndentSet;
201
201
        shouldForceTabIndentation = other.shouldForceTabIndentation;
202
202
        emptyLineFill = other.emptyLineFill;
 
203
        lineOpensComment = other.lineOpensComment;
203
204
        backslashEndsPrevLine = other.backslashEndsPrevLine;
204
205
        blockCommentNoIndent = other.blockCommentNoIndent;
205
206
        blockCommentNoBeautify = other.blockCommentNoBeautify;
206
207
        previousLineProbationTab = other.previousLineProbationTab;
 
208
        fileType = other.fileType;
207
209
        minConditionalIndent = other.minConditionalIndent;
208
210
        parenDepth = other.parenDepth;
209
211
        indentLength = other.indentLength;
210
212
        blockTabCount = other.blockTabCount;
211
 
        leadingWhiteSpaces = other.leadingWhiteSpaces;
212
213
        maxInStatementIndent = other.maxInStatementIndent;
 
214
        classInitializerTabs = other.classInitializerTabs;
213
215
        templateDepth = other.templateDepth;
214
216
        prevFinalLineSpaceTabCount = other.prevFinalLineSpaceTabCount;
215
217
        prevFinalLineTabCount = other.prevFinalLineTabCount;
226
228
 */
227
229
ASBeautifier::~ASBeautifier()
228
230
{
229
 
        DELETE_CONTAINER(headerStack);
230
 
        DELETE_CONTAINER(tempStacks);
231
 
        DELETE_CONTAINER(blockParenDepthStack);
232
 
        DELETE_CONTAINER(blockStatementStack);
233
 
        DELETE_CONTAINER(parenStatementStack);
234
 
        DELETE_CONTAINER(bracketBlockStateStack);
235
 
        DELETE_CONTAINER(inStatementIndentStack);
236
 
        DELETE_CONTAINER(inStatementIndentStackSizeStack);
237
 
        DELETE_CONTAINER(parenIndentStack);
 
231
        deleteContainer(waitingBeautifierStack);
 
232
        deleteContainer(activeBeautifierStack);
 
233
        deleteContainer(waitingBeautifierStackLengthStack);
 
234
        deleteContainer(activeBeautifierStackLengthStack);
 
235
        deleteContainer(headerStack);
 
236
        deleteContainer(tempStacks);
 
237
        deleteContainer(blockParenDepthStack);
 
238
        deleteContainer(blockStatementStack);
 
239
        deleteContainer(parenStatementStack);
 
240
        deleteContainer(bracketBlockStateStack);
 
241
        deleteContainer(inStatementIndentStack);
 
242
        deleteContainer(inStatementIndentStackSizeStack);
 
243
        deleteContainer(parenIndentStack);
238
244
}
239
245
 
240
246
/**
261
267
void ASBeautifier::init()
262
268
{
263
269
        initStatic();
264
 
 
265
 
        INIT_CONTAINER(waitingBeautifierStack,  new vector<ASBeautifier*>);
266
 
        INIT_CONTAINER(activeBeautifierStack,  new vector<ASBeautifier*>);
267
 
 
268
 
        INIT_CONTAINER(waitingBeautifierStackLengthStack, new vector<int>);
269
 
        INIT_CONTAINER(activeBeautifierStackLengthStack, new vector<int>);
270
 
 
271
 
        INIT_CONTAINER(headerStack,  new vector<const string*>);
272
 
        INIT_CONTAINER(tempStacks, new vector<vector<const string*>*>);
 
270
        ASBase::init(getFileType());
 
271
 
 
272
        initContainer(waitingBeautifierStack, new vector<ASBeautifier*>);
 
273
        initContainer(activeBeautifierStack, new vector<ASBeautifier*>);
 
274
 
 
275
        initContainer(waitingBeautifierStackLengthStack, new vector<int>);
 
276
        initContainer(activeBeautifierStackLengthStack, new vector<int>);
 
277
 
 
278
        initContainer(headerStack,  new vector<const string*>);
 
279
 
 
280
        initContainer(tempStacks, new vector<vector<const string*>*>);
273
281
        tempStacks->push_back(new vector<const string*>);
274
282
 
275
 
        INIT_CONTAINER(blockParenDepthStack, new vector<int>);
276
 
        INIT_CONTAINER(blockStatementStack, new vector<bool>);
277
 
        INIT_CONTAINER(parenStatementStack, new vector<bool>);
 
283
        initContainer(blockParenDepthStack, new vector<int>);
 
284
        initContainer(blockStatementStack, new vector<bool>);
 
285
        initContainer(parenStatementStack, new vector<bool>);
278
286
 
279
 
        INIT_CONTAINER(bracketBlockStateStack, new vector<bool>);
 
287
        initContainer(bracketBlockStateStack, new vector<bool>);
280
288
        bracketBlockStateStack->push_back(true);
281
289
 
282
 
        INIT_CONTAINER(inStatementIndentStack, new vector<int>);
283
 
        INIT_CONTAINER(inStatementIndentStackSizeStack, new vector<int>);
 
290
        initContainer(inStatementIndentStack, new vector<int>);
 
291
        initContainer(inStatementIndentStackSizeStack, new vector<int>);
284
292
        inStatementIndentStackSizeStack->push_back(0);
285
 
        INIT_CONTAINER(parenIndentStack, new vector<int>);
 
293
        initContainer(parenIndentStack, new vector<int>);
286
294
 
287
 
        immediatelyPreviousAssignmentOp = NULL;
288
295
        previousLastLineHeader = NULL;
289
296
        currentHeader = NULL;
290
297
 
291
298
        isInQuote = false;
 
299
        isInVerbatimQuote = false;
 
300
        haveLineContinuationChar = false;
292
301
        isInComment = false;
293
302
        isInStatement = false;
294
303
        isInCase = false;
296
305
        isInClassHeader = false;
297
306
        isInClassHeaderTab = false;
298
307
        isInHeader = false;
299
 
        isInOperator = false;
300
308
        isInTemplate = false;
301
309
        isInConditional = false;
302
310
        templateDepth = 0;
303
311
        parenDepth = 0;
304
312
        blockTabCount = 0;
305
 
        leadingWhiteSpaces = 0;
306
313
        prevNonSpaceCh = '{';
307
314
        currentNonSpaceCh = '{';
308
315
        prevNonLegalCh = '{';
312
319
        prevFinalLineTabCount = 0;
313
320
        probationHeader = NULL;
314
321
        backslashEndsPrevLine = false;
 
322
        lineOpensComment = false;
315
323
        isInDefine = false;
316
324
        isInDefineDefinition = false;
317
325
        defineTabCount = 0;
320
328
        blockCommentNoBeautify = false;
321
329
        previousLineProbationTab = false;
322
330
        isNonInStatementArray = false;
323
 
        inLineNumber = -1;           // for debugging
324
 
        outLineNumber = 0;           // for debugging
 
331
        isSharpAccessor = false;
 
332
        isSharpDelegate = false;
 
333
        isInExtern = false;
 
334
        isInEnum = false;
 
335
        inLineNumber = 0;
 
336
        horstmannIndentInStatement = 0;
 
337
        nonInStatementBracket = 0;
325
338
}
326
339
 
327
340
/**
330
343
void ASBeautifier::setCStyle()
331
344
{
332
345
        fileType = C_TYPE;
333
 
        isCStyle     = true;
334
 
        isJavaStyle  = false;
335
 
        isSharpStyle = false;
336
346
}
337
347
 
338
348
/**
341
351
void ASBeautifier::setJavaStyle()
342
352
{
343
353
        fileType = JAVA_TYPE;
344
 
        isJavaStyle  = true;
345
 
        isCStyle     = false;
346
 
        isSharpStyle = false;
347
354
}
348
355
 
349
356
/**
352
359
void ASBeautifier::setSharpStyle()
353
360
{
354
361
        fileType = SHARP_TYPE;
355
 
        isSharpStyle = true;
356
 
        isCStyle     = false;
357
 
        isJavaStyle  = false;
358
362
}
359
363
 
360
364
/**
424
428
 */
425
429
void ASBeautifier::setBlockIndent(bool state)
426
430
{
427
 
        if (state)
428
 
                setBracketIndent(false); // so that we don't have both bracket and block indent
429
431
        blockIndent = state;
430
432
}
431
433
 
513
515
}
514
516
 
515
517
/**
 
518
 * get the file type.
 
519
 */
 
520
int ASBeautifier::getFileType()
 
521
{
 
522
        return fileType;
 
523
}
 
524
 
 
525
/**
516
526
 * get the number of spaces per indent
517
527
 *
518
528
 * @return   value of indentLength option.
519
 
*/
 
529
 */
520
530
int ASBeautifier::getIndentLength(void)
521
531
{
522
532
        return indentLength;
524
534
 
525
535
/**
526
536
 * get the char used for indentation, space or tab
527
 
  *
 
537
 *
528
538
 * @return   the char used for indentation.
529
539
 */
530
540
string ASBeautifier::getIndentString(void)
533
543
}
534
544
 
535
545
/**
 
546
 * get the state of the force tab indentation option.
 
547
 *
 
548
 * @return   state of force tab indentation.
 
549
 */
 
550
bool ASBeautifier::getForceTabIndentation(void)
 
551
{
 
552
        return shouldForceTabIndentation;
 
553
}
 
554
 
 
555
/**
 
556
 * get the state of the block indentation option.
 
557
 *
 
558
 * @return   state of blockIndent option.
 
559
 */
 
560
bool ASBeautifier::getBlockIndent(void)
 
561
{
 
562
        return blockIndent;
 
563
}
 
564
 
 
565
/**
 
566
 * get the state of the bracket indentation option.
 
567
 *
 
568
 * @return   state of bracketIndent option.
 
569
 */
 
570
bool ASBeautifier::getBracketIndent(void)
 
571
{
 
572
        return bracketIndent;
 
573
}
 
574
 
 
575
/**
 
576
 * get the state of the class indentation option. If true, blocks of
 
577
 * the 'class' statement will be indented one additional indent.
 
578
 *
 
579
 * @return   state of classIndent option.
 
580
 */
 
581
bool ASBeautifier::getClassIndent(void)
 
582
{
 
583
        return classIndent;
 
584
}
 
585
 
 
586
/**
 
587
 * get the state of the switch indentation option. If true, blocks of
 
588
 * the 'switch' statement will be indented one additional indent.
 
589
 *
 
590
 * @return   state of switchIndent option.
 
591
 */
 
592
bool ASBeautifier::getSwitchIndent(void)
 
593
{
 
594
        return switchIndent;
 
595
}
 
596
 
 
597
/**
536
598
 * get the state of the case indentation option. If true, lines of 'case'
537
599
 * statements will be indented one additional indent.
538
600
 *
544
606
}
545
607
 
546
608
/**
547
 
 * get C style identifier.
548
 
 * If true, a C source is being indented.
549
 
 *
550
 
 * @return   state of isCStyle option.
551
 
 */
552
 
bool ASBeautifier::getCStyle(void)
553
 
{
554
 
        return isCStyle;
555
 
}
556
 
 
557
 
/**
558
 
 * get Java style identifier.
559
 
 * If true, a Java source is being indented.
560
 
 *
561
 
 * @return   state of isJavaStyle option.
562
 
 */
563
 
bool ASBeautifier::getJavaStyle(void)
564
 
{
565
 
        return isJavaStyle;
566
 
}
567
 
 
568
 
/**
569
 
 * get C# style identifier.
570
 
 * If true, a C# source is being indented.
571
 
 *
572
 
 * @return   state of isSharpStyle option.
573
 
 */
574
 
bool ASBeautifier::getSharpStyle(void)
575
 
{
576
 
        return isSharpStyle;
577
 
}
578
 
 
579
 
/**
580
609
 * get the state of the empty line fill option.
581
610
 * If true, empty lines will be filled with the whitespace.
582
611
 * of their previous lines.
624
653
        bool lineStartsInComment = false;
625
654
        bool isInClass = false;
626
655
        bool isInSwitch = false;
627
 
        bool isImmediatelyAfterConst = false;
 
656
        bool isInOperator = false;
628
657
        bool isSpecialChar = false;
 
658
        bool haveCaseIndent = false;
 
659
        bool lineBeginsWithBracket = false;
 
660
        bool closingBracketReached = false;
 
661
        bool shouldIndentBrackettedLine = true;
 
662
        bool previousLineProbation = (probationHeader != NULL);
 
663
        bool isInQuoteContinuation = isInVerbatimQuote | haveLineContinuationChar;
629
664
        char ch = ' ';
630
665
        char prevCh;
631
 
        string outBuffer; // the newly idented line is bufferd here
 
666
        char tempCh;
632
667
        int tabCount = 0;
633
 
        const string *lastLineHeader = NULL;
634
 
        bool closingBracketReached = false;
635
668
        int spaceTabCount = 0;
636
 
        char tempCh;
637
 
        size_t headerStackSize = headerStack->size();
638
 
        bool shouldIndentBrackettedLine = true;
639
669
        int lineOpeningBlocksNum = 0;
640
670
        int lineClosingBlocksNum = 0;
641
 
        bool previousLineProbation = (probationHeader != NULL);
 
671
        int tabIncrementIn = 0;
642
672
        int i;
 
673
        int iPrelim;
 
674
        string outBuffer; // the newly idented line is buffered here
 
675
        const string *lastLineHeader = NULL;
643
676
 
644
677
        currentHeader = NULL;
645
678
        lineStartsInComment = isInComment;
646
679
        blockCommentNoBeautify = blockCommentNoIndent;
 
680
        lineOpensComment = false;
647
681
        previousLineProbationTab = false;
648
 
        outLineNumber++;
 
682
        haveLineContinuationChar = false;
649
683
 
650
684
        // handle and remove white spaces around the line:
651
685
        // If not in comment, first find out size of white space before line,
652
686
        // so that possible comments starting in the line continue in
653
687
        // relation to the preliminary white-space.
654
 
        if (!isInComment)
655
 
        {
656
 
                int strlen = originalLine.length();
657
 
                leadingWhiteSpaces = 0;
658
 
 
659
 
                for (int j = 0; j < strlen && isWhiteSpace(originalLine[j]); j++)
660
 
                {
661
 
                        if (originalLine[j] == '\t')
662
 
                                leadingWhiteSpaces += indentLength;
663
 
                        else
664
 
                                leadingWhiteSpaces++;
665
 
                }
 
688
        if (isInQuoteContinuation)
 
689
        {
 
690
                // trim a single space added by ASFormatter, otherwise leave it alone
 
691
                if (!(originalLine.length() == 1 && originalLine[0] == ' '))
 
692
                        line = originalLine;
 
693
        }
 
694
        else if (!isInComment)
 
695
        {
666
696
                line = trim(originalLine);
 
697
                if (line.length() > 0 && line[0] == '{')
 
698
                        lineBeginsWithBracket = true;
 
699
 
 
700
                size_t j = line.find_first_not_of(" \t{");
 
701
                if (j != string::npos && line.compare(j, 2, "/*") == 0)
 
702
                        lineOpensComment = true;
667
703
        }
668
704
        else
669
705
        {
670
 
                // convert leading tabs to spaces
671
 
                string spaceTabs(indentLength, ' ');
672
 
                string newLine = originalLine;
673
 
                int strlen = newLine.length();
674
 
 
675
 
                for (int j=0; j < leadingWhiteSpaces && j < strlen; j++)
676
 
                {
677
 
                        if (newLine[j] == '\t')
678
 
                        {
679
 
                                newLine.replace(j, 1, spaceTabs);
680
 
                                strlen = newLine.length();
681
 
                        }
682
 
                }
683
 
 
684
 
                // trim the comment leaving the new leading whitespace
685
 
                int trimSize = 0;
686
 
                strlen = newLine.length();
687
 
 
688
 
                while (trimSize < strlen
689
 
                        && trimSize < leadingWhiteSpaces
690
 
                        && isWhiteSpace(newLine[trimSize]))
691
 
                        trimSize++;
692
 
 
693
 
 
694
 
                while (trimSize < strlen && isWhiteSpace(newLine[strlen-1]))
695
 
                        strlen--;
696
 
 
697
 
                line = newLine.substr(trimSize, strlen);
 
706
                // trim the end of comment lines
 
707
                line = originalLine;
698
708
                size_t trimEnd = line.find_last_not_of(" \t");
699
 
                if (trimEnd != string::npos)
700
 
                {
701
 
                        int spacesToDelete = line.length() - 1 - trimEnd;
702
 
                        if (spacesToDelete > 0)
703
 
                                line.erase(trimEnd + 1, spacesToDelete);
704
 
                }
 
709
                if (trimEnd == string::npos)
 
710
                        trimEnd = 0;
 
711
                else
 
712
                        trimEnd++;
 
713
                if (trimEnd < line.length())
 
714
                        line.erase(trimEnd);
705
715
        }
706
716
 
707
 
 
708
717
        if (line.length() == 0)
709
718
        {
710
 
                if (backslashEndsPrevLine)      // must continue to clear variables
 
719
                if (backslashEndsPrevLine)  // must continue to clear variables
711
720
                        line = ' ';
712
 
                else if (emptyLineFill)
 
721
                else if (emptyLineFill && !isInQuoteContinuation && headerStack->size() > 0)
713
722
                        return preLineWS(prevFinalLineSpaceTabCount, prevFinalLineTabCount);
714
723
                else
715
724
                        return line;
716
725
        }
717
726
 
718
727
        // handle preprocessor commands
 
728
        // except C# region and endregion
719
729
 
720
 
        if (isCStyle && !isInComment && (line[0] == '#' || backslashEndsPrevLine))
 
730
        if (!isInComment
 
731
                && (line[0] == '#' || backslashEndsPrevLine)
 
732
                && line.compare(0, 7, "#region") != 0
 
733
                && line.compare(0, 10, "#endregion") != 0)
721
734
        {
722
735
                if (line[0] == '#')
723
736
                {
730
743
                        //    to be called for the actual indentation.
731
744
                        // The original beautifier will have isInDefineDefinition = true, isInDefine = false
732
745
                        // The cloned beautifier will have   isInDefineDefinition = true, isInDefine = true
733
 
                        if (preprocessorIndent && preproc.compare(0, 6, "define") == 0 &&  line[line.length() - 1] == '\\')
 
746
                        if (preprocessorIndent && preproc.compare(0, 6, "define") == 0 && line[line.length() - 1] == '\\')
734
747
                        {
735
748
                                if (!isInDefineDefinition)
736
749
                                {
839
852
        if (!isInDefine && activeBeautifierStack != NULL && !activeBeautifierStack->empty())
840
853
        {
841
854
                activeBeautifierStack->back()->inLineNumber = inLineNumber;
842
 
                activeBeautifierStack->back()->outLineNumber = outLineNumber;
 
855
                activeBeautifierStack->back()->horstmannIndentInStatement = horstmannIndentInStatement;
 
856
                activeBeautifierStack->back()->nonInStatementBracket = nonInStatementBracket;
843
857
                activeBeautifierStack->back()->lineCommentNoBeautify = lineCommentNoBeautify;
844
858
                activeBeautifierStack->back()->isNonInStatementArray = isNonInStatementArray;
845
 
                return activeBeautifierStack->back()->beautify(line);
 
859
                activeBeautifierStack->back()->isSharpAccessor = isSharpAccessor;
 
860
                activeBeautifierStack->back()->isSharpDelegate = isSharpDelegate;
 
861
                // must return originalLine not the trimmed line
 
862
                return activeBeautifierStack->back()->beautify(originalLine);
846
863
        }
847
864
 
848
865
        // calculate preliminary indentation based on data from past lines
849
866
        if (!inStatementIndentStack->empty())
850
867
                spaceTabCount = inStatementIndentStack->back();
851
868
 
852
 
 
853
 
        for (i = 0; i < (int) headerStackSize; i++)
 
869
        for (i = 0; i < (int) headerStack->size(); i++)
854
870
        {
855
871
                isInClass = false;
856
872
 
857
 
                if (blockIndent || (!(i > 0 && (*headerStack)[i-1] != &AS_OPEN_BRACKET
858
 
                                      && (*headerStack)[i] == &AS_OPEN_BRACKET)))
 
873
                if (blockIndent)
 
874
                {
 
875
                        // do NOT indent opening block for these headers
 
876
                        if (!((*headerStack)[i] == &AS_NAMESPACE
 
877
                                || (*headerStack)[i] == &AS_CLASS
 
878
                                || (*headerStack)[i] == &AS_STRUCT
 
879
                                || (*headerStack)[i] == &AS_UNION
 
880
                                || (*headerStack)[i] == &AS_CONST
 
881
                                || (*headerStack)[i] == &AS_INTERFACE
 
882
                                || (*headerStack)[i] == &AS_THROWS
 
883
                                || (*headerStack)[i] == &AS_STATIC))
 
884
                                ++tabCount;
 
885
                }
 
886
                else if (!(i > 0 && (*headerStack)[i-1] != &AS_OPEN_BRACKET
 
887
                           && (*headerStack)[i] == &AS_OPEN_BRACKET))
859
888
                        ++tabCount;
860
889
 
861
 
                if (!isJavaStyle && !namespaceIndent && i >= 1
 
890
                if (!isJavaStyle() && !namespaceIndent && i >= 1
862
891
                        && (*headerStack)[i-1] == &AS_NAMESPACE
863
892
                        && (*headerStack)[i] == &AS_OPEN_BRACKET)
864
893
                        --tabCount;
865
894
 
866
 
                if (isCStyle && i >= 1
 
895
                if (isCStyle() && i >= 1
867
896
                        && (*headerStack)[i-1] == &AS_CLASS
868
897
                        && (*headerStack)[i] == &AS_OPEN_BRACKET)
869
898
                {
873
902
                }
874
903
 
875
904
                // is the switchIndent option is on, indent switch statements an additional indent.
876
 
                else if (switchIndent && i > 1 &&
877
 
                         (*headerStack)[i-1] == &AS_SWITCH &&
878
 
                         (*headerStack)[i] == &AS_OPEN_BRACKET
879
 
                        )
 
905
                else if (switchIndent && i > 1
 
906
                         && (*headerStack)[i-1] == &AS_SWITCH
 
907
                         && (*headerStack)[i] == &AS_OPEN_BRACKET)
880
908
                {
881
909
                        ++tabCount;
882
910
                        isInSwitch = true;
884
912
 
885
913
        }
886
914
 
 
915
        iPrelim = i;
 
916
 
887
917
        if (!lineStartsInComment
888
 
                && isCStyle
 
918
                && isCStyle()
889
919
                && isInClass
890
920
                && classIndent
891
 
                && headerStackSize >= 2
892
 
                && (*headerStack)[headerStackSize-2] == &AS_CLASS
893
 
                && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET
894
 
                && line[0] == '}')
 
921
                && headerStack->size() >= 2
 
922
                && (*headerStack)[headerStack->size()-2] == &AS_CLASS
 
923
                && (*headerStack)[headerStack->size()-1] == &AS_OPEN_BRACKET
 
924
                && line[0] == '}'
 
925
                && bracketBlockStateStack->back() == true)
895
926
                --tabCount;
896
927
 
897
928
        else if (!lineStartsInComment
898
929
                 && isInSwitch
899
930
                 && switchIndent
900
 
                 && headerStackSize >= 2
901
 
                 && (*headerStack)[headerStackSize-2] == &AS_SWITCH
902
 
                 && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET
 
931
                 && headerStack->size() >= 2
 
932
                 && (*headerStack)[headerStack->size()-2] == &AS_SWITCH
 
933
                 && (*headerStack)[headerStack->size()-1] == &AS_OPEN_BRACKET
903
934
                 && line[0] == '}')
904
935
                --tabCount;
905
936
 
906
937
        if (isInClassHeader)
907
938
        {
908
 
                isInClassHeaderTab = true;
909
 
                tabCount += 2;
 
939
                if (lineStartsInComment || lineOpensComment)
 
940
                {
 
941
                        if (!lineBeginsWithBracket)
 
942
                                tabCount--;
 
943
                }
 
944
                else if (isCStyle() && !isClassAccessModifier(line))
 
945
                {
 
946
                        isInClassHeaderTab = true;
 
947
                        tabCount += classInitializerTabs;
 
948
                }
 
949
                else if (blockIndent)
 
950
                {
 
951
                        if (!lineBeginsWithBracket)
 
952
                                tabCount++;
 
953
                }
910
954
        }
911
955
 
912
956
        if (isInConditional)
919
963
 
920
964
        for (i = 0; i < (int) line.length(); i++)
921
965
        {
 
966
                outBuffer.append(1, line[i]);
 
967
 
922
968
                tempCh = line[i];
923
 
 
924
969
                prevCh = ch;
925
970
                ch = tempCh;
926
971
 
927
 
                outBuffer.append(1, ch);
928
 
 
929
972
                if (isWhiteSpace(ch))
930
 
                        continue;
931
 
 
932
 
                // check for utf8 characters
933
 
                // isalnum() will display an assert message in debug if not bypassed here
934
 
                if (ch < 0)
935
 
                        continue;
 
973
                {
 
974
                        if (ch == '\t')
 
975
                                tabIncrementIn += convertTabToSpaces(i, tabIncrementIn);
 
976
                        continue;
 
977
                }
936
978
 
937
979
                // handle special characters (i.e. backslash+character such as \n, \t, ...)
938
 
                if (isSpecialChar)
939
 
                {
940
 
                        isSpecialChar = false;
941
 
                        continue;
942
 
                }
943
 
                if (!(isInComment || isInLineComment) && line.compare(i, 2, "\\\\") == 0)
944
 
                {
945
 
                        outBuffer.append(1, '\\');
946
 
                        i++;
947
 
                        continue;
948
 
                }
949
 
                if (!(isInComment || isInLineComment) && ch == '\\')
950
 
                {
951
 
                        isSpecialChar = true;
952
 
                        continue;
953
 
                }
 
980
 
 
981
                if (isInQuote && !isInVerbatimQuote)
 
982
                {
 
983
                        if (isSpecialChar)
 
984
                        {
 
985
                                isSpecialChar = false;
 
986
                                continue;
 
987
                        }
 
988
                        if (line.compare(i, 2, "\\\\") == 0)
 
989
                        {
 
990
                                outBuffer.append(1, '\\');
 
991
                                i++;
 
992
                                continue;
 
993
                        }
 
994
                        if (ch == '\\')
 
995
                        {
 
996
                                if (peekNextChar(line, i) == ' ')   // is this '\' at end of line
 
997
                                        haveLineContinuationChar = true;
 
998
                                else
 
999
                                        isSpecialChar = true;
 
1000
                                continue;
 
1001
                        }
 
1002
                }
 
1003
                else if (isInDefine && ch == '\\')
 
1004
                        continue;
954
1005
 
955
1006
                // handle quotes (such as 'x' and "Hello Dolly")
956
1007
                if (!(isInComment || isInLineComment) && (ch == '"' || ch == '\''))
 
1008
                {
957
1009
                        if (!isInQuote)
958
1010
                        {
959
1011
                                quoteChar = ch;
960
1012
                                isInQuote = true;
 
1013
                                if (isSharpStyle() && prevCh == '@')
 
1014
                                        isInVerbatimQuote = true;
 
1015
                        }
 
1016
                        else if (isInVerbatimQuote && ch == '"')
 
1017
                        {
 
1018
                                if (peekNextChar(line, i) == '"')           // check consecutive quotes
 
1019
                                {
 
1020
                                        outBuffer.append(1, '"');
 
1021
                                        i++;
 
1022
                                }
 
1023
                                else
 
1024
                                {
 
1025
                                        isInQuote = false;
 
1026
                                        isInVerbatimQuote = false;
 
1027
                                }
961
1028
                        }
962
1029
                        else if (quoteChar == ch)
963
1030
                        {
965
1032
                                isInStatement = true;
966
1033
                                continue;
967
1034
                        }
 
1035
                }
968
1036
                if (isInQuote)
969
1037
                        continue;
970
1038
 
982
1050
                        isInComment = true;
983
1051
                        outBuffer.append(1, '*');
984
1052
                        i++;
985
 
                        size_t j = line.find_first_not_of(" \t");
986
 
                        if (!line.compare(j, 2, "/*") == 0)     // does line start with comment?
987
 
                                blockCommentNoIndent = true;    // if no, cannot indent continuation lines
 
1053
                        if (!lineOpensComment)                                  // does line start with comment?
 
1054
                                blockCommentNoIndent = true;        // if no, cannot indent continuation lines
988
1055
                        continue;
989
1056
                }
990
1057
                else if ((isInComment || isInLineComment) && line.compare(i, 2, "*/") == 0)
992
1059
                        isInComment = false;
993
1060
                        outBuffer.append(1, '/');
994
1061
                        i++;
995
 
                        blockCommentNoIndent = false;           // ok to indent next comment
 
1062
                        blockCommentNoIndent = false;           // ok to indent next comment
996
1063
                        continue;
997
1064
                }
 
1065
                // treat C# '#region' and '#endregion' statements as a line comment
 
1066
                else if (isSharpStyle() &&
 
1067
                         (line.compare(i, 7, "#region") == 0 || line.compare(i, 10, "#endregion") == 0))
 
1068
                {
 
1069
                        isInLineComment = true;
 
1070
//                      continue;
 
1071
                }
998
1072
 
999
1073
                if (isInComment || isInLineComment)
 
1074
                {
 
1075
                        // append rest of the comment up to the comment end
 
1076
                        while (i+1 < (int) line.length()
 
1077
                                && line.compare(i+1, 2, "*/") != 0)
 
1078
                                outBuffer.append(1, line[++i]);
1000
1079
                        continue;
 
1080
                }
1001
1081
 
1002
1082
                // if we have reached this far then we are NOT in a comment or string of special character...
1003
1083
 
1012
1092
 
1013
1093
                                // handle the specific probation header
1014
1094
                                isInConditional = (probationHeader == &AS_SYNCHRONIZED);
1015
 
                                if (probationHeader == &AS_CONST)
1016
 
                                        isImmediatelyAfterConst = true;
1017
1095
 
1018
1096
                                isInStatement = false;
1019
1097
                                // if the probation comes from the previous line, then indent by 1 tab count.
1020
 
                                if (previousLineProbation && ch == '{')
 
1098
                                if (previousLineProbation
 
1099
                                        && ch == '{'
 
1100
                                        && !(blockIndent
 
1101
                                             && (probationHeader == &AS_CONST || probationHeader == &AS_STATIC)))
1021
1102
                                {
1022
1103
                                        tabCount++;
1023
1104
                                        previousLineProbationTab = true;
1045
1126
                else
1046
1127
                        currentHeader = NULL;
1047
1128
 
1048
 
                if (isCStyle && isInTemplate
 
1129
                if (isCStyle() && isInTemplate
1049
1130
                        && (ch == '<' || ch == '>')
1050
 
                        &&  findHeader(line, i, nonAssignmentOperators) == NULL)
 
1131
                        &&  findOperator(line, i, nonAssignmentOperators) == NULL)
1051
1132
                {
1052
1133
                        if (ch == '<')
1053
1134
                        {
1072
1153
                {
1073
1154
                        if (ch == '(' || ch == '[')
1074
1155
                        {
 
1156
                                isInOperator = false;
 
1157
                                // if have a struct header, this is a declaration not a definition
 
1158
                                if (ch == '('
 
1159
                                        && (isInClassHeader || isInClassHeaderTab)
 
1160
                                        && headerStack->size() > 0
 
1161
                                        && headerStack->back() == &AS_STRUCT)
 
1162
                                {
 
1163
                                        headerStack->pop_back();
 
1164
                                        isInClassHeader = false;
 
1165
                                        // -1 for isInClassHeader, -2 for isInClassHeaderTab
 
1166
                                        if (isInClassHeaderTab)
 
1167
                                        {
 
1168
                                                tabCount -= (1 + classInitializerTabs);
 
1169
                                                isInClassHeaderTab = false;
 
1170
                                        }
 
1171
                                        if (tabCount < 0)
 
1172
                                                tabCount = 0;
 
1173
                                }
 
1174
 
1075
1175
                                if (parenDepth == 0)
1076
1176
                                {
1077
1177
                                        parenStatementStack->push_back(isInStatement);
1082
1182
                                inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
1083
1183
 
1084
1184
                                if (currentHeader != NULL)
1085
 
                                        registerInStatementIndent(line, i, spaceTabCount, minConditionalIndent/*indentLength*2*/, true);
 
1185
                                        registerInStatementIndent(line, i, spaceTabCount, tabIncrementIn, minConditionalIndent/*indentLength*2*/, true);
1086
1186
                                else
1087
 
                                        registerInStatementIndent(line, i, spaceTabCount, 0, true);
 
1187
                                        registerInStatementIndent(line, i, spaceTabCount, tabIncrementIn, 0, true);
1088
1188
                        }
1089
1189
                        else if (ch == ')' || ch == ']')
1090
1190
                        {
1091
1191
                                parenDepth--;
1092
1192
                                if (parenDepth == 0)
1093
1193
                                {
1094
 
                                        isInStatement = parenStatementStack->back();
1095
 
                                        parenStatementStack->pop_back();
 
1194
                                        if (!parenStatementStack->empty())      // in case of unmatched closing parens
 
1195
                                        {
 
1196
                                                isInStatement = parenStatementStack->back();
 
1197
                                                parenStatementStack->pop_back();
 
1198
                                        }
1096
1199
                                        ch = ' ';
1097
 
 
1098
1200
                                        isInConditional = false;
1099
1201
                                }
1100
1202
 
1122
1224
 
1123
1225
                if (ch == '{')
1124
1226
                {
1125
 
                        bool isBlockOpener;
1126
1227
                        // first, check if '{' is a block-opener or an static-array opener
1127
 
                        isBlockOpener = ((prevNonSpaceCh == '{' && bracketBlockStateStack->back())
1128
 
                                         || prevNonSpaceCh == '}'
1129
 
                                         || prevNonSpaceCh == ')'
1130
 
                                         || prevNonSpaceCh == ';'
1131
 
                                         || peekNextChar(line, i) == '{'
1132
 
                                         || isNonInStatementArray
1133
 
                                         || isInClassHeader
1134
 
//                                       || isBlockOpener
1135
 
                                         || isImmediatelyAfterConst
1136
 
                                         || (isInDefine &&
1137
 
                                             (prevNonSpaceCh == '('
1138
 
                                              || prevNonSpaceCh == '_'
1139
 
                                              || isalnum(prevNonSpaceCh))));
 
1228
                        bool isBlockOpener = ((prevNonSpaceCh == '{' && bracketBlockStateStack->back())
 
1229
                                              || prevNonSpaceCh == '}'
 
1230
                                              || prevNonSpaceCh == ')'
 
1231
                                              || prevNonSpaceCh == ';'
 
1232
                                              || peekNextChar(line, i) == '{'
 
1233
                                              || isInClassHeader
 
1234
                                              || isNonInStatementArray
 
1235
                                              || isSharpAccessor
 
1236
                                              || isSharpDelegate
 
1237
                                              || isInExtern
 
1238
                                              || (isInDefine &&
 
1239
                                                  (prevNonSpaceCh == '('
 
1240
                                                   || isLegalNameChar(prevNonSpaceCh))));
 
1241
 
 
1242
                        //if (isNonInStatementArray
 
1243
                        //        && prevNonSpaceCh != ')'
 
1244
                        //        && prevNonSpaceCh != '='
 
1245
                        //        && !isInEnum
 
1246
                        //        && i == nonInStatementBracket)
 
1247
                        //      isBlockOpener = false;
1140
1248
 
1141
1249
                        isInClassHeader = false;
 
1250
 
1142
1251
                        if (!isBlockOpener && currentHeader != NULL)
1143
1252
                        {
1144
1253
                                for (size_t n = 0; n < nonParenHeaders.size(); n++)
1148
1257
                                                break;
1149
1258
                                        }
1150
1259
                        }
 
1260
 
 
1261
                        // TODO: TEMPORARY??? fix to give C# }) statements a full indent
 
1262
                        // check for anonymous method
 
1263
                        //if (isBlockOpener && isSharpStyle() && !parenIndentStack->empty())
 
1264
                        //      isBlockOpener = false;
 
1265
 
1151
1266
                        bracketBlockStateStack->push_back(isBlockOpener);
 
1267
 
1152
1268
                        if (!isBlockOpener)
1153
1269
                        {
1154
1270
                                inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
1155
 
                                registerInStatementIndent(line, i, spaceTabCount, 0, true);
 
1271
                                registerInStatementIndent(line, i, spaceTabCount, tabIncrementIn, 0, true);
1156
1272
                                parenDepth++;
1157
1273
                                if (i == 0)
1158
1274
                                        shouldIndentBrackettedLine = false;
1163
1279
                        // this bracket is a block opener...
1164
1280
 
1165
1281
                        ++lineOpeningBlocksNum;
1166
 
//                      if (isInClassHeader)
1167
 
//                      isInClassHeader = false;
1168
1282
 
1169
1283
                        if (isInClassHeaderTab)
1170
1284
                        {
1171
1285
                                isInClassHeaderTab = false;
1172
1286
                                // decrease tab count if bracket is broken
1173
1287
                                size_t firstChar = line.find_first_not_of(" \t");
1174
 
                                if (firstChar != string::npos)
1175
 
                                        if (line[firstChar] == '{' && (int) firstChar == i)
1176
 
                                                tabCount -= 2;
 
1288
                                if (firstChar != string::npos
 
1289
                                        && line[firstChar] == '{'
 
1290
                                        && (int) firstChar == i)
 
1291
                                {
 
1292
                                        tabCount -= classInitializerTabs;
 
1293
                                        // decrease one more if an empty class
 
1294
                                        if (headerStack->size() > 0
 
1295
                                                && (*headerStack).back() == &AS_CLASS)
 
1296
                                        {
 
1297
                                                int nextChar = getNextProgramCharDistance(line, i);
 
1298
                                                if (line[nextChar] == '}')
 
1299
                                                        tabCount--;
 
1300
                                        }
 
1301
                                }
 
1302
                        }
 
1303
 
 
1304
                        if (bracketIndent && !namespaceIndent && headerStack->size() > 0
 
1305
                                && (*headerStack).back() == &AS_NAMESPACE)
 
1306
                        {
 
1307
                                shouldIndentBrackettedLine = false;
 
1308
                                tabCount--;
1177
1309
                        }
1178
1310
 
1179
1311
                        // do not allow inStatementIndent - should occur for Java files only
1180
 
                        if (inStatementIndentStack->size() > 0)
1181
 
                        {
1182
 
                                spaceTabCount = 0;
1183
 
                                inStatementIndentStack->back() = 0;
1184
 
                        }
 
1312
                        //if (inStatementIndentStack->size() > 0)
 
1313
                        //{
 
1314
                        //      spaceTabCount = 0;
 
1315
                        //      inStatementIndentStack->back() = 0;
 
1316
                        //}
1185
1317
 
1186
1318
                        blockParenDepthStack->push_back(parenDepth);
1187
1319
                        blockStatementStack->push_back(isInStatement);
1188
1320
 
1189
1321
                        inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
1190
1322
                        if (inStatementIndentStack->size() > 0)
 
1323
                        {
 
1324
                                spaceTabCount = 0;
1191
1325
                                inStatementIndentStack->back() = 0;
 
1326
                        }
1192
1327
 
1193
1328
                        blockTabCount += isInStatement ? 1 : 0;
1194
1329
                        parenDepth = 0;
1202
1337
                }
1203
1338
 
1204
1339
                //check if a header has been reached
1205
 
                if (isWhiteSpace(prevCh))
 
1340
                bool isPotentialHeader = isCharPotentialHeader(line, i);
 
1341
 
 
1342
                if (isPotentialHeader)
1206
1343
                {
1207
 
                        bool isIndentableHeader = true;
1208
1344
                        const string *newHeader = findHeader(line, i, headers);
 
1345
 
 
1346
                        if (newHeader != NULL)
 
1347
                        {
 
1348
                                char peekChar = peekNextChar(line, i + newHeader->length() - 1);
 
1349
 
 
1350
                                // is not a header if part of a definition
 
1351
                                if (peekChar == ',' || peekChar == ')')
 
1352
                                        newHeader = NULL;
 
1353
                                // the following accessor definitions are NOT headers
 
1354
                                // goto default; is NOT a header
 
1355
                                // default(int) keyword in C# is NOT a header
 
1356
                                else if ((newHeader == &AS_GET || newHeader == &AS_SET || newHeader == &AS_DEFAULT)
 
1357
                                         && (peekChar == ';' ||  peekChar == '('))
 
1358
                                {
 
1359
                                        newHeader = NULL;
 
1360
                                }
 
1361
                        }
 
1362
 
1209
1363
                        if (newHeader != NULL)
1210
1364
                        {
1211
1365
                                // if we reached here, then this is a header...
 
1366
                                bool isIndentableHeader = true;
 
1367
 
1212
1368
                                isInHeader = true;
1213
1369
 
1214
1370
                                vector<const string*> *lastTempStack;
1301
1457
                                else if (newHeader == &AS_CASE)
1302
1458
                                {
1303
1459
                                        isInCase = true;
1304
 
                                        --tabCount;
 
1460
                                        if (!haveCaseIndent)
 
1461
                                        {
 
1462
                                                haveCaseIndent = true;
 
1463
                                                if (!lineBeginsWithBracket)
 
1464
                                                        --tabCount;
 
1465
                                        }
1305
1466
                                }
1306
1467
                                else if (newHeader == &AS_DEFAULT)
1307
1468
                                {
1310
1471
                                }
1311
1472
                                else if (newHeader == &AS_STATIC
1312
1473
                                         || newHeader == &AS_SYNCHRONIZED
1313
 
                                         || (newHeader == &AS_CONST && isCStyle))
 
1474
                                         || (newHeader == &AS_CONST && isCStyle()))
1314
1475
                                {
1315
1476
                                        if (!headerStack->empty() &&
1316
1477
                                                (headerStack->back() == &AS_STATIC
1331
1492
                                }
1332
1493
                                else if (newHeader == &AS_TEMPLATE)
1333
1494
                                {
1334
 
                                        if (isCStyle)
 
1495
                                        if (isCStyle())
1335
1496
                                                isInTemplate = true;
1336
1497
                                        isIndentableHeader = false;
1337
1498
                                }
1338
1499
 
1339
 
 
1340
1500
                                if (isIndentableHeader)
1341
1501
                                {
1342
1502
                                        headerStack->push_back(newHeader);
1354
1514
                                i += newHeader->length() - 1;
1355
1515
 
1356
1516
                                continue;
1357
 
                        }
1358
 
                }
1359
 
 
1360
 
                if (isCStyle && !isalpha(prevCh)
1361
 
                        && line.compare(i, 8, "operator") == 0 && !isalnum(line[i+8]))
1362
 
                {
1363
 
                        isInOperator = true;
1364
 
                        outBuffer.append(AS_OPERATOR.substr(1));
1365
 
                        i += 7;
1366
 
                        continue;
1367
 
                }
1368
 
 
1369
 
                // "new" operator is a pointer, not a calculation
1370
 
                if (!isalpha(prevCh)
1371
 
                        && line.compare(i, 3, "new") == 0 && !isalnum(line[i+3]))
1372
 
                {
1373
 
                        if (prevNonSpaceCh == '=' && isInStatement && !inStatementIndentStack->empty())
1374
 
                                inStatementIndentStack->back() = 0;
1375
 
                }
 
1517
                        }  // newHeader != NULL
 
1518
                }   // isPotentialHeader
1376
1519
 
1377
1520
                if (ch == '?')
1378
1521
                        isInQuestion = true;
1379
1522
 
1380
 
 
1381
1523
                // special handling of 'case' statements
1382
1524
                if (ch == ':')
1383
1525
                {
1394
1536
                                isInQuestion = false;
1395
1537
                        }
1396
1538
 
1397
 
                        else if (isCStyle && isInClass && prevNonSpaceCh != ')')
1398
 
                        {
 
1539
                        else if (isCStyle() && isInClassHeader)
 
1540
                        {
 
1541
                                // found a 'class A : public B' definition
 
1542
                                // so do nothing special
 
1543
                        }
 
1544
 
 
1545
                        else if (isCStyle() && isdigit(peekNextChar(line, i)))
 
1546
                        {
 
1547
                                // found a bit field
 
1548
                                // so do nothing special
 
1549
                        }
 
1550
 
 
1551
                        else if (isCStyle() && isInClass && prevNonSpaceCh != ')')
 
1552
                        {
 
1553
                                // found a 'private:' or 'public:' inside a class definition
1399
1554
                                --tabCount;
1400
 
                                // found a 'private:' or 'public:' inside a class definition
1401
 
                                // so do nothing special
1402
 
                        }
1403
 
 
1404
 
                        else if (!isJavaStyle && isInClassHeader)
1405
 
                        {
1406
 
                                // found a 'class A : public B' definition
1407
 
                                // so do nothing special
1408
 
                        }
1409
 
 
1410
 
                        else if (isJavaStyle && lastLineHeader == &AS_FOR)
 
1555
                        }
 
1556
 
 
1557
                        else if (isJavaStyle() && lastLineHeader == &AS_FOR)
1411
1558
                        {
1412
1559
                                // found a java for-each statement
1413
1560
                                // so do nothing special
1414
1561
                        }
1415
1562
 
1416
 
                        else if (isCStyle && prevNonSpaceCh == ')')
 
1563
                        else if (isCStyle() && prevNonSpaceCh == ')' && !isInCase)
1417
1564
                        {
1418
1565
                                isInClassHeader = true;
1419
1566
                                if (i == 0)
1420
 
                                        tabCount += 2;
 
1567
                                        tabCount += classInitializerTabs;
1421
1568
                        }
1422
1569
                        else
1423
1570
                        {
1427
1574
                                        isInCase = false;
1428
1575
                                        ch = ';'; // from here on, treat char as ';'
1429
1576
                                }
1430
 
 
1431
 
 
1432
 
                                else // is in a label (e.g. 'label1:')
 
1577
                                else if (isCStyle() || (isSharpStyle() && peekNextChar(line, i) == ';'))    // is in a label (e.g. 'label1:')
1433
1578
                                {
1434
1579
                                        if (labelIndent)
1435
1580
                                                --tabCount; // unindent label by one indent
1436
 
                                        else
 
1581
                                        else if (!lineBeginsWithBracket)
1437
1582
                                                tabCount = 0; // completely flush indent to left
1438
1583
                                }
1439
 
 
1440
 
 
1441
 
 
1442
1584
                        }
1443
1585
                }
1444
1586
 
1514
1656
                                        }
1515
1657
                                        headerStack->pop_back();
1516
1658
 
 
1659
                                        // do not indent namespace bracket unless namespaces are indented
 
1660
                                        if (!namespaceIndent && headerStack->size() > 0
 
1661
                                                && (*headerStack).back() == &AS_NAMESPACE)
 
1662
                                                shouldIndentBrackettedLine = false;
 
1663
 
1517
1664
                                        if (!tempStacks->empty())
1518
1665
                                        {
1519
1666
                                                vector<const string*> *temp =  tempStacks->back();
1554
1701
                        continue;
1555
1702
                }
1556
1703
 
1557
 
 
1558
 
                // check for preBlockStatements ONLY if not within parenthesies
1559
 
                // (otherwise 'struct XXX' statements would be wrongly interpreted...)
1560
 
                if (isWhiteSpace(prevCh) && !isInTemplate && parenDepth == 0)
 
1704
                if (isPotentialHeader)
1561
1705
                {
1562
 
                        const string *newHeader = findHeader(line, i, preBlockStatements);
1563
 
                        if (newHeader != NULL)
1564
 
                        {
1565
 
                                isInClassHeader = true;
1566
 
                                outBuffer.append(newHeader->substr(1));
1567
 
                                i += newHeader->length() - 1;
1568
 
                                headerStack->push_back(newHeader);
1569
 
                        }
 
1706
                        // check for preBlockStatements in C/C++ ONLY if not within parenthesies
 
1707
                        // (otherwise 'struct XXX' statements would be wrongly interpreted...)
 
1708
                        if (!isInTemplate && !(isCStyle() && parenDepth > 0))
 
1709
                        {
 
1710
                                const string *newHeader = findHeader(line, i, preBlockStatements);
 
1711
                                if (newHeader != NULL)
 
1712
                                {
 
1713
                                        isInClassHeader = true;
 
1714
 
 
1715
                                        if (!isSharpStyle())
 
1716
                                                headerStack->push_back(newHeader);
 
1717
                                        // do not need 'where' in the headerStack
 
1718
                                        // do not need second 'class' statement in a row
 
1719
                                        else if (!(newHeader == &AS_WHERE
 
1720
                                                   || (newHeader == &AS_CLASS
 
1721
                                                       && headerStack->size() > 0
 
1722
                                                       && headerStack->back() == &AS_CLASS)))
 
1723
                                                headerStack->push_back(newHeader);
 
1724
 
 
1725
                                        outBuffer.append(newHeader->substr(1));
 
1726
                                        i += newHeader->length() - 1;
 
1727
                                        continue;
 
1728
                                }
 
1729
                        }
 
1730
                        const string *foundIndentableHeader = findHeader(line, i, indentableHeaders);
 
1731
 
 
1732
                        if (foundIndentableHeader != NULL)
 
1733
                        {
 
1734
                                // must bypass the header before registering the in statement
 
1735
                                outBuffer.append(foundIndentableHeader->substr(1));
 
1736
                                i += foundIndentableHeader->length() - 1;
 
1737
                                if (!isInOperator && !isInTemplate && !isNonInStatementArray)
 
1738
                                {
 
1739
                                        registerInStatementIndent(line, i, spaceTabCount, tabIncrementIn, 0, false);
 
1740
                                        isInStatement = true;
 
1741
                                }
 
1742
                                continue;
 
1743
                        }
 
1744
 
 
1745
                        if (isCStyle() && findKeyword(line, i, AS_OPERATOR))
 
1746
                                isInOperator = true;
 
1747
 
 
1748
                        // "new" operator is a pointer, not a calculation
 
1749
                        if (findKeyword(line, i, AS_NEW))
 
1750
                        {
 
1751
                                if (prevNonSpaceCh == '=' && isInStatement && !inStatementIndentStack->empty())
 
1752
                                        inStatementIndentStack->back() = 0;
 
1753
                        }
 
1754
 
 
1755
                        // append the entire name for all others
 
1756
                        string name = getCurrentWord(line, i);
 
1757
                        outBuffer.append(name.substr(1));
 
1758
                        i += name.length() - 1;
 
1759
                        continue;
1570
1760
                }
1571
1761
 
1572
1762
                // Handle operators
1573
1763
 
1574
 
                immediatelyPreviousAssignmentOp = NULL;
1575
 
 
1576
 
                // Check if an operator has been reached.
1577
 
                const string *foundAssignmentOp = findHeader(line, i, assignmentOperators, false);
1578
 
                if (foundAssignmentOp == &AS_RETURN)
1579
 
                        foundAssignmentOp = findHeader(line, i, assignmentOperators, true);
1580
 
                const string *foundNonAssignmentOp = findHeader(line, i, nonAssignmentOperators, false);
1581
 
 
1582
 
                // Since findHeader's boundry checking was not used above, it is possible
1583
 
                // that both an assignment op and a non-assignment op where found,
1584
 
                // e.g. '>>' and '>>='. If this is the case, treat the LONGER one as the
1585
 
                // found operator.
1586
 
                if (foundAssignmentOp != NULL && foundNonAssignmentOp != NULL)
1587
 
                        if (foundAssignmentOp->length() < foundNonAssignmentOp->length())
1588
 
                                foundAssignmentOp = NULL;
1589
 
                        else
1590
 
                                foundNonAssignmentOp = NULL;
1591
 
 
1592
 
                if (foundNonAssignmentOp != NULL)
1593
 
                {
1594
 
                        if (foundNonAssignmentOp->length() > 1)
1595
 
                        {
1596
 
                                outBuffer.append(foundNonAssignmentOp->substr(1));
1597
 
                                i += foundNonAssignmentOp->length() - 1;
1598
 
                        }
1599
 
                }
1600
 
 
1601
 
                else if (foundAssignmentOp != NULL)
1602
 
                {
1603
 
                        if (foundAssignmentOp->length() > 1)
1604
 
                        {
1605
 
                                outBuffer.append(foundAssignmentOp->substr(1));
1606
 
                                i += foundAssignmentOp->length() - 1;
1607
 
                        }
1608
 
 
1609
 
                        if (!isInOperator && !isInTemplate && !isNonInStatementArray)
1610
 
                        {
1611
 
                                registerInStatementIndent(line, i, spaceTabCount, 0, false);
1612
 
                                immediatelyPreviousAssignmentOp = foundAssignmentOp;
1613
 
                                isInStatement = true;
1614
 
                        }
1615
 
                }
1616
 
 
1617
 
                if (isInOperator)
1618
 
                        isInOperator = false;
1619
 
        }
 
1764
                bool isPotentialOperator = isCharPotentialOperator(ch);
 
1765
 
 
1766
                if (isPotentialOperator)
 
1767
                {
 
1768
                        // Check if an operator has been reached.
 
1769
                        const string *foundAssignmentOp = findOperator(line, i, assignmentOperators);
 
1770
                        const string *foundNonAssignmentOp = findOperator(line, i, nonAssignmentOperators);
 
1771
 
 
1772
                        // Since findHeader's boundry checking was not used above, it is possible
 
1773
                        // that both an assignment op and a non-assignment op where found,
 
1774
                        // e.g. '>>' and '>>='. If this is the case, treat the LONGER one as the
 
1775
                        // found operator.
 
1776
                        if (foundAssignmentOp != NULL && foundNonAssignmentOp != NULL)
 
1777
                        {
 
1778
                                if (foundAssignmentOp->length() < foundNonAssignmentOp->length())
 
1779
                                        foundAssignmentOp = NULL;
 
1780
                                else
 
1781
                                        foundNonAssignmentOp = NULL;
 
1782
                        }
 
1783
 
 
1784
                        if (foundNonAssignmentOp != NULL)
 
1785
                        {
 
1786
                                if (foundNonAssignmentOp->length() > 1)
 
1787
                                {
 
1788
                                        outBuffer.append(foundNonAssignmentOp->substr(1));
 
1789
                                        i += foundNonAssignmentOp->length() - 1;
 
1790
                                }
 
1791
                        }
 
1792
 
 
1793
                        else if (foundAssignmentOp != NULL)
 
1794
                        {
 
1795
                                if (foundAssignmentOp->length() > 1)
 
1796
                                {
 
1797
                                        outBuffer.append(foundAssignmentOp->substr(1));
 
1798
                                        i += foundAssignmentOp->length() - 1;
 
1799
                                }
 
1800
 
 
1801
                                if (!isInOperator && !isInTemplate && !isNonInStatementArray)
 
1802
                                {
 
1803
                                        registerInStatementIndent(line, i, spaceTabCount, tabIncrementIn, 0, false);
 
1804
                                        isInStatement = true;
 
1805
                                }
 
1806
                        }
 
1807
                }
 
1808
        }   // end of for loop  *  end of for loop  *  end of for loop  *  end of for loop
1620
1809
 
1621
1810
        // handle special cases of unindentation:
1622
1811
 
1635
1824
                && shouldIndentBrackettedLine)
1636
1825
                --tabCount;
1637
1826
 
 
1827
        // must check one less in headerStack if more than one header on a line (allow-addins)...
 
1828
        else if (!lineStartsInComment
 
1829
                 && (int) headerStack->size() > iPrelim + 1
 
1830
                 && !blockIndent
 
1831
                 && outBuffer.length() > 0
 
1832
                 && outBuffer[0] == '{'
 
1833
                 && !(lineOpeningBlocksNum > 0 && lineOpeningBlocksNum == lineClosingBlocksNum)
 
1834
                 && !(headerStack->size() > 2 && (*headerStack)[headerStack->size()-3] == &AS_OPEN_BRACKET)
 
1835
                 && shouldIndentBrackettedLine)
 
1836
                --tabCount;
 
1837
 
 
1838
        // unindent a closing bracket...
1638
1839
        else if (!lineStartsInComment
1639
1840
                 && outBuffer.length() > 0
1640
1841
                 && outBuffer[0] == '}'
1649
1850
                 && previousLineProbationTab)
1650
1851
                --tabCount; //lineOpeningBlocksNum - (blockIndent ? 1 : 0);
1651
1852
 
 
1853
        // correctly indent class continuation lines...
 
1854
        else if (!lineStartsInComment
 
1855
                 && !lineOpensComment
 
1856
                 && isInClassHeaderTab
 
1857
                 && !blockIndent
 
1858
                 && outBuffer.length() > 0
 
1859
                 && lineOpeningBlocksNum == 0
 
1860
                 && lineOpeningBlocksNum == lineClosingBlocksNum
 
1861
                 && (headerStack->size() > 0 && headerStack->back() == &AS_CLASS))
 
1862
                --tabCount;
 
1863
 
1652
1864
        if (tabCount < 0)
1653
1865
                tabCount = 0;
1654
1866
 
1655
1867
        // take care of extra bracket indentatation option...
1656
 
        if (bracketIndent && outBuffer.length() > 0 && shouldIndentBrackettedLine)
1657
 
                if (outBuffer[0] == '{' || outBuffer[0] == '}')
1658
 
                        tabCount++;
1659
 
 
 
1868
        if (!lineStartsInComment
 
1869
                && bracketIndent
 
1870
                && shouldIndentBrackettedLine
 
1871
                && outBuffer.length() > 0
 
1872
                && (outBuffer[0] == '{' || outBuffer[0] == '}'))
 
1873
                tabCount++;
1660
1874
 
1661
1875
        if (isInDefine)
1662
1876
        {
1683
1897
 
1684
1898
        if (tabCount < 0)
1685
1899
                tabCount = 0;
1686
 
        if (lineCommentNoBeautify || blockCommentNoBeautify)
 
1900
        if (lineCommentNoBeautify || blockCommentNoBeautify || isInQuoteContinuation)
1687
1901
                tabCount = spaceTabCount = 0;
1688
1902
 
1689
1903
        // finally, insert indentations into begining of line
1690
1904
 
1691
 
        prevFinalLineSpaceTabCount = spaceTabCount;
1692
 
        prevFinalLineTabCount = tabCount;
1693
 
 
1694
1905
        if (shouldForceTabIndentation)
1695
1906
        {
1696
1907
                tabCount += spaceTabCount / indentLength;
1699
1910
 
1700
1911
        outBuffer = preLineWS(spaceTabCount, tabCount) + outBuffer;
1701
1912
 
 
1913
        prevFinalLineSpaceTabCount = spaceTabCount;
 
1914
        prevFinalLineTabCount = tabCount;
 
1915
 
1702
1916
        if (lastLineHeader != NULL)
1703
1917
                previousLastLineHeader = lastLineHeader;
1704
1918
 
1720
1934
 
1721
1935
}
1722
1936
 
 
1937
bool ASBeautifier::isClassAccessModifier(string& line) const
 
1938
{
 
1939
        size_t firstChar = line.find_first_not_of(" \t");
 
1940
        if (firstChar == string::npos)
 
1941
                return false;
 
1942
        // bypass a colon
 
1943
        if (line[firstChar] == ':')
 
1944
        {
 
1945
                firstChar = line.find_first_not_of(" \t");
 
1946
                if (firstChar == string::npos)
 
1947
                        return false;
 
1948
        }
 
1949
        if (line.compare(firstChar, 7, "public ") == 0
 
1950
                || line.compare(firstChar, 8, "private ") == 0
 
1951
                || line.compare(firstChar, 10, "protected ") == 0)
 
1952
                return true;
 
1953
        return false;
 
1954
}
 
1955
 
1723
1956
/**
1724
1957
 * register an in-statement indent.
1725
1958
 */
1726
1959
void ASBeautifier::registerInStatementIndent(const string &line, int i, int spaceTabCount,
1727
 
        int minIndent, bool updateParenStack)
 
1960
        int tabIncrementIn, int minIndent, bool updateParenStack)
1728
1961
{
1729
1962
        int inStatementIndent;
1730
1963
        int remainingCharNum = line.length() - i;
1731
1964
        int nextNonWSChar = getNextProgramCharDistance(line, i);
1732
1965
 
1733
 
        // if indent is around the last char in the line, indent instead 2 spaces from the previous indent
 
1966
        // if indent is around the last char in the line, indent instead one indent from the previous indent
1734
1967
        if (nextNonWSChar == remainingCharNum)
1735
1968
        {
1736
1969
                int previousIndent = spaceTabCount;
1737
1970
                if (!inStatementIndentStack->empty())
1738
1971
                        previousIndent = inStatementIndentStack->back();
1739
 
 
1740
 
                inStatementIndentStack->push_back(/*2*/ indentLength + previousIndent);
 
1972
                int currIndent = /*2*/ indentLength + previousIndent;
 
1973
                if (currIndent > maxInStatementIndent
 
1974
                        && line[i] != '{')
 
1975
                        currIndent = indentLength * 2 + spaceTabCount;
 
1976
                inStatementIndentStack->push_back(currIndent);
1741
1977
                if (updateParenStack)
1742
1978
                        parenIndentStack->push_back(previousIndent);
1743
1979
                return;
1744
1980
        }
1745
1981
 
1746
1982
        if (updateParenStack)
1747
 
                parenIndentStack->push_back(i + spaceTabCount);
1748
 
 
1749
 
        inStatementIndent = i + nextNonWSChar + spaceTabCount;
1750
 
 
1751
 
        if (i + nextNonWSChar < minIndent)
 
1983
                parenIndentStack->push_back(i + spaceTabCount - horstmannIndentInStatement);
 
1984
 
 
1985
        int tabIncrement = tabIncrementIn;
 
1986
 
 
1987
        // check for following tabs
 
1988
        for (int j = i + 1; j < (i + nextNonWSChar); j++)
 
1989
        {
 
1990
                if (line[j] == '\t')
 
1991
                        tabIncrement += convertTabToSpaces(j, tabIncrement);
 
1992
        }
 
1993
 
 
1994
        inStatementIndent = i + nextNonWSChar + spaceTabCount + tabIncrement;
 
1995
 
 
1996
        // check for run-in statement
 
1997
        if (i > 0 && line[0] == '{')
 
1998
                inStatementIndent -= indentLength;
 
1999
 
 
2000
//      if (i + nextNonWSChar < minIndent)
 
2001
//              inStatementIndent = minIndent + spaceTabCount;
 
2002
 
 
2003
        if (inStatementIndent < minIndent)
1752
2004
                inStatementIndent = minIndent + spaceTabCount;
1753
2005
 
1754
 
        if (i + nextNonWSChar > maxInStatementIndent)
1755
 
                inStatementIndent =  indentLength * 2 + spaceTabCount;
 
2006
//      if (i + nextNonWSChar > maxInStatementIndent)
 
2007
//              inStatementIndent =  indentLength * 2 + spaceTabCount;
 
2008
 
 
2009
        if (inStatementIndent > maxInStatementIndent)
 
2010
                inStatementIndent = indentLength * 2 + spaceTabCount;
1756
2011
 
1757
2012
        if (!inStatementIndentStack->empty() &&
1758
2013
                inStatementIndent < inStatementIndentStack->back())
1759
2014
                inStatementIndent = inStatementIndentStack->back();
1760
2015
 
1761
 
        if (isNonInStatementArray)
 
2016
        // the block opener is not indented for a NonInStatementArray
 
2017
        if (isNonInStatementArray && !bracketBlockStateStack->empty() && bracketBlockStateStack->back())
1762
2018
                inStatementIndent = 0;
1763
2019
 
1764
2020
        inStatementIndentStack->push_back(inStatementIndent);
1765
2021
}
1766
2022
 
1767
2023
/**
1768
 
 * get distance to the next non-white sspace, non-comment character in the line.
 
2024
 * get distance to the next non-white space, non-comment character in the line.
1769
2025
 * if no such character exists, return the length remaining to the end of the line.
1770
2026
 */
1771
 
int ASBeautifier::getNextProgramCharDistance(const string &line, int i)
 
2027
int ASBeautifier::getNextProgramCharDistance(const string &line, int i) const
1772
2028
{
1773
2029
        bool inComment = false;
1774
2030
        int  remainingCharNum = line.length() - i;
1806
2062
        return charDistance;
1807
2063
}
1808
2064
 
1809
 
 
1810
 
/**
1811
 
 * check if a specific line position contains a header, out of several possible headers.
1812
 
 *
1813
 
 * @return    a pointer to the found header. if no header was found then return NULL.
1814
 
 */
1815
 
const string *ASBeautifier::findHeader(const string &line, int i, const vector<const string*> &possibleHeaders, bool checkBoundry)
1816
 
{
1817
 
        int maxHeaders = possibleHeaders.size();
1818
 
        // const string *header = NULL;
1819
 
        int p;
1820
 
 
1821
 
        for (p = 0; p < maxHeaders; p++)
1822
 
        {
1823
 
                const string *header = possibleHeaders[p];
1824
 
 
1825
 
                if (line.compare(i, header->length(), header->c_str()) == 0)
1826
 
                {
1827
 
                        // check that this is a header and not a part of a longer word
1828
 
                        // (e.g. not at its begining, not at its middle...)
1829
 
 
1830
 
                        int lineLength = line.length();
1831
 
                        int headerEnd = i + header->length();
1832
 
                        char startCh = (*header)[0];   // first char of header
1833
 
                        char endCh = 0;                // char just after header
1834
 
                        char prevCh = 0;               // char just before header
1835
 
 
1836
 
                        if (headerEnd < lineLength)
1837
 
                        {
1838
 
                                endCh = line[headerEnd];
1839
 
                        }
1840
 
                        if (i > 0)
1841
 
                        {
1842
 
                                prevCh = line[i-1];
1843
 
                        }
1844
 
 
1845
 
                        if (!checkBoundry)
1846
 
                        {
1847
 
                                return header;
1848
 
                        }
1849
 
                        else if (prevCh != 0
1850
 
                                 && isLegalNameChar(startCh)
1851
 
                                 && isLegalNameChar(prevCh))
1852
 
                        {
1853
 
                                return NULL;
1854
 
                        }
1855
 
                        else if (headerEnd >= lineLength
1856
 
                                 || !isLegalNameChar(startCh)
1857
 
                                 || !isLegalNameChar(endCh))
1858
 
                        {
1859
 
                                return header;
1860
 
                        }
1861
 
                        else
1862
 
                        {
1863
 
                                return NULL;
1864
 
                        }
1865
 
                }
1866
 
        }
1867
 
 
 
2065
// check if a specific line position contains a header.
 
2066
const string* ASBeautifier::findHeader(const string &line, int i,
 
2067
                                       const vector<const string*> &possibleHeaders) const
 
2068
{
 
2069
        assert(isCharPotentialHeader(line, i));
 
2070
        // check the word
 
2071
        size_t maxHeaders = possibleHeaders.size();
 
2072
        for (size_t p = 0; p < maxHeaders; p++)
 
2073
        {
 
2074
                const string* header = possibleHeaders[p];
 
2075
                const size_t wordEnd = i + header->length();
 
2076
                if (wordEnd > line.length())
 
2077
                        continue;
 
2078
                int result = (line.compare(i, header->length(), *header));
 
2079
                if (result > 0)
 
2080
                        continue;
 
2081
                if (result < 0)
 
2082
                        break;
 
2083
                // check that this is not part of a longer word
 
2084
                if (wordEnd == line.length())
 
2085
                        return header;
 
2086
                if (isLegalNameChar(line[wordEnd]))
 
2087
                        continue;
 
2088
                // is not a header if part of a definition
 
2089
                const char peekChar = peekNextChar(line, wordEnd - 1);
 
2090
                if (peekChar == ',' || peekChar == ')')
 
2091
                        break;
 
2092
                return header;
 
2093
        }
 
2094
        return NULL;
 
2095
}
 
2096
 
 
2097
 
 
2098
// check if a specific line position contains an operator.
 
2099
const string* ASBeautifier::findOperator(const string &line, int i,
 
2100
        const vector<const string*> &possibleOperators) const
 
2101
{
 
2102
        assert(isCharPotentialOperator(line[i]));
 
2103
        // find the operator in the vector
 
2104
        // the vector contains the LONGEST operators first
 
2105
        // must loop thru the entire vector
 
2106
        size_t maxOperators = possibleOperators.size();
 
2107
        for (size_t p = 0; p < maxOperators; p++)
 
2108
        {
 
2109
                const size_t wordEnd = i + (*possibleOperators[p]).length();
 
2110
                if (wordEnd > line.length())
 
2111
                        continue;
 
2112
                if (line.compare(i, (*possibleOperators[p]).length(), *possibleOperators[p]) == 0)
 
2113
                        return possibleOperators[p];
 
2114
        }
1868
2115
        return NULL;
1869
2116
}
1870
2117
 
1887
2134
}
1888
2135
 
1889
2136
/**
 
2137
 * convert tabs to spaces.
 
2138
 * i is the position of the character to convert to spaces.
 
2139
 * tabIncrementIn is the increment that must be added for tab indent characters
 
2140
 *     to get the correct column for the current tab.
 
2141
 */
 
2142
int ASBeautifier::convertTabToSpaces(int i, int tabIncrementIn) const
 
2143
{
 
2144
        int tabToSpacesAdjustment = indentLength - 1 - ((tabIncrementIn + i) % indentLength);
 
2145
        return tabToSpacesAdjustment;
 
2146
}
 
2147
 
 
2148
/**
1890
2149
 * trim removes the white space surrounding a line.
1891
2150
 *
1892
2151
 * @return          the trimmed line.
1909
2168
}
1910
2169
 
1911
2170
/**
1912
 
* peek at the next unread character.
1913
 
*
1914
 
* @return       the next unread character.
1915
 
* @param line   the line to check.
1916
 
* @param i      the current char position on the line.
1917
 
*/
1918
 
char ASBeautifier::peekNextChar(string &line, int i)
1919
 
{
1920
 
        char ch = ' ';
1921
 
        size_t peekNum = line.find_first_not_of(" \t", i + 1);
1922
 
 
1923
 
        if (peekNum == string::npos)
1924
 
                return ch;
1925
 
 
1926
 
        ch = line[peekNum];
1927
 
 
1928
 
        return ch;
 
2171
 * delete a static member vector object using swap
 
2172
 * to eliminate memory leak reporting for the vector
 
2173
 */
 
2174
void ASBeautifier::deleteStaticVectors()
 
2175
{
 
2176
        beautifierFileType = 9;         // reset to an invalid type
 
2177
        vector<const string*> headersClear;
 
2178
        headers.swap(headersClear);
 
2179
        vector<const string*> nonParenHeadersClear;
 
2180
        nonParenHeaders.swap(nonParenHeadersClear);
 
2181
        vector<const string*> preBlockStatementsClear;
 
2182
        preBlockStatements.swap(preBlockStatementsClear);
 
2183
        vector<const string*> assignmentOperatorsClear;
 
2184
        assignmentOperators.swap(assignmentOperatorsClear);
 
2185
        vector<const string*> nonAssignmentOperatorsClear;
 
2186
        nonAssignmentOperators.swap(nonAssignmentOperatorsClear);
 
2187
        vector<const string*> indentableHeadersClear;
 
2188
        indentableHeaders.swap(indentableHeadersClear);
 
2189
}
 
2190
 
 
2191
/**
 
2192
 * delete a vector object
 
2193
 * T is the type of vector
 
2194
 * used for all vectors except tempStacks
 
2195
 */
 
2196
template<typename T>
 
2197
void ASBeautifier::deleteContainer(T &container)
 
2198
{
 
2199
        if (container != NULL)
 
2200
        {
 
2201
                container->clear();
 
2202
                delete (container);
 
2203
                container = NULL;
 
2204
        }
 
2205
}
 
2206
 
 
2207
/**
 
2208
 * Delete the tempStacks vector object.
 
2209
 * The tempStacks is a vector of pointers to strings allocated with
 
2210
 * the 'new' operator.
 
2211
 * Therefore the strings have to be deleted in addition to the
 
2212
 * tempStacks entries.
 
2213
 */
 
2214
void ASBeautifier::deleteContainer(vector<vector<const string*>*>* &container)
 
2215
{
 
2216
        if (container != NULL)
 
2217
        {
 
2218
                vector<vector<const string*>*>::iterator iter = container->begin();
 
2219
                for (; iter != container->end(); iter++)
 
2220
                        delete *iter;
 
2221
                container->clear();
 
2222
                delete (container);
 
2223
                container = NULL;
 
2224
        }
 
2225
}
 
2226
 
 
2227
/**
 
2228
 * initialize a vector object
 
2229
 * T is the type of vector
 
2230
 * used for all vectors
 
2231
 */
 
2232
template<typename T>
 
2233
void ASBeautifier::initContainer(T &container, T value)
 
2234
{
 
2235
        // since the ASFormatter object is never deleted,
 
2236
        // the existing vectors must be deleted before creating new ones
 
2237
        if (container != NULL )
 
2238
                deleteContainer(container);
 
2239
        container = value;
1929
2240
}
1930
2241
 
1931
2242