Code Coverage Statistics for Source File

C:\Users\Marcus\Documents\MyCode\2007\SharpSelectWord\SharpSelectWord\Src\ExtendBlockSelection.cs

Sequence Point Coverage
86,9%
133 of 153
Branch Coverage
N/A
0 of 0
Lines
360
Highlight: Uncovered Code Covered Code
L V Source
1
// SharpSelectWord is a addin to SharpDevelop that can select text.
2
// Copyright (C) 2007  Marcus Holmgren
3
// 
4
// This library is free software; you can redistribute it and/or
5
// modify it under the terms of the GNU Lesser General Public
6
// License as published by the Free Software Foundation; either
7
// version 2.1 of the License, or (at your option) any later version.
8
// 
9
// This library is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
// Lesser General Public License for more details.
13
// 
14
// You should have received a copy of the GNU Lesser General Public
15
// License along with this library; if not, write to the Free Software
16
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18
19
using System;
20
using System.Collections.Generic;
21
using ICSharpCode.TextEditor;
22
using ICSharpCode.TextEditor.Document;
23
24
namespace MarcusHolmgren.SharpDevelop.SelectWord
25
{
26
    public sealed class ExtendBlockSelection : ISelection
27
    {
28
        private readonly IDocument itsDocument;
29
        private TextLocation itsStartPosition;
30
        private TextLocation itsEndPosition;
31
        private int itsOffset;
32
        private int itsEndOffset;
33
        private string itsSelectedText;
34
35
        /// <summary>
36
        /// Initialize a new instance of the ExtendBlockSelection class.
37
        /// </summary>
38
        /// <param name="document">Object that implements the IDocument interface.</param>
39
        /// <param name="selection">The current selection.</param>
40
19
        public ExtendBlockSelection(IDocument document, ISelection selection)
41
        {
42
19
            if (document == null)
43
1
                throw new ArgumentNullException("document");
44
45
18
            if (selection == null)
46
1
                throw new ArgumentNullException("selection");
47
48
17
            itsDocument = document;
49
17
            itsOffset = selection.Offset;
50
17
            itsEndOffset = selection.EndOffset;
51
52
17
            ExtendCurrentSelection();
53
        }
54
55
56
        public void ExtendCurrentSelection()
57
        {
58
17
            if (CurrentSelectionIsCompleteLine())
59
2
                ExtendLine();
60
            else
61
15
                ExtendBlock();
62
63
17
            AdjustEndOffset();
64
65
17
            StartPosition = itsDocument.OffsetToPosition(Offset);
66
17
            EndPosition = itsDocument.OffsetToPosition(EndOffset);
67
68
17
            itsSelectedText = itsDocument.GetText(Offset, EndOffset - Offset);
69
17
        }
70
71
72
        private ExtensionDirection GetExtensionDirection()
73
        {
74
15
            bool searching = true;
75
15
            ExtensionDirection direction = ExtensionDirection.None;
76
77
15
            if (Offset != 0) itsOffset++;
78
15
            itsEndOffset--;
79
80
            do
81
            {
82
60
                if (MoveLeft() && IsLeftBlockChar(itsDocument.GetCharAt(Offset)))
83
                {
84
6
                    direction = ExtensionDirection.Right;
85
6
                    searching = false;
86
                }
87
54
                else if (MoveRight() && IsRightBlockChar(itsDocument.GetCharAt(EndOffset)))
88
                {
89
5
                    if (EndOffset == (itsDocument.TextLength - 1))
90
0
                        direction = ExtensionDirection.None;
91
                    else
92
5
                        direction = ExtensionDirection.Left;
93
5
                    searching = false;
94
                }
95
96
60
                if (searching)
97
                {
98
49
                    if (itsDocument.GetCharAt(Offset) == '\n')
99
0
                        direction = ExtensionDirection.Right;
100
101
49
                    if (itsDocument.GetCharAt(EndOffset) == '\n')
102
4
                        direction = ExtensionDirection.Left;
103
104
49
                    if (direction != ExtensionDirection.None)
105
4
                        searching = false;
106
                }
107
60
            } while (searching);
108
109
15
            return direction;
110
15
        }
111
112
        private void AdjustEndOffset()
113
        {
114
17
            MoveRight();
115
116
17
            if (itsEndOffset == (itsDocument.TextLength - 1))
117
3
                itsEndOffset = itsDocument.TextLength;
118
17
        }
119
120
        private void ExtendBlock()
121
        {
122
15
            ExtensionDirection direction = GetExtensionDirection();
123
124
15
            if (direction == ExtensionDirection.Right)
125
6
                ExtendSelectionRight();
126
127
128
15
            if (direction == ExtensionDirection.Left)
129
9
                ExtendSelectionLeft();
130
131
132
            /*
133
                //TODO direction search
134
                if (direction == ExtensionDirection.None)
135
                    System.Diagnostics.Debug.WriteLine("None direction");
136
                */
137
15
        }
138
139
        private void ExtendLine()
140
        {
141
42
            while (MoveLeft())
142
            {
143
42
                if (itsDocument.GetCharAt(Offset) == '\n')
144
                {
145
2
                    itsOffset++;
146
2
                    break;
147
                }
148
            }
149
150
42
            while (MoveRight())
151
            {
152
42
                if (itsDocument.GetCharAt(EndOffset) == '\n')
153
2
                    break;
154
            }
155
2
        }
156
157
        private bool CurrentSelectionIsCompleteLine()
158
        {
159
17
            return MoveLeft() && itsDocument.GetCharAt(Offset) == '\n' && itsDocument.GetCharAt(EndOffset - 1) == '\n';
160
17
        }
161
162
        private void ExtendSelectionLeft()
163
        {
164
            char blockChar;
165
9
            char tempChar = itsDocument.GetCharAt(EndOffset);
166
9
            switch (tempChar)
167
            {
168
                case ')':
169
0
                    blockChar = '(';
170
0
                    break;
171
                case '}':
172
0
                    blockChar = '{';
173
0
                    break;
174
                case ']':
175
0
                    blockChar = '[';
176
0
                    break;
177
                case '>':
178
0
                    blockChar = '<';
179
0
                    break;
180
                default:
181
9
                    blockChar = tempChar;
182
9
                    break;
183
            }
184
9
            char[] validChars = new char[] {blockChar, '\n'};
185
            do
186
            {
187
87
                if (IsValidChar(itsDocument.GetCharAt(Offset), validChars))
188
7
                    break;
189
80
            } while (MoveLeft());
190
191
9
            if (itsDocument.GetCharAt(Offset) == '\n')
192
            {
193
4
                while (itsDocument.GetCharAt(EndOffset) != '\n')
194
0
                    MoveRight();
195
196
4
                itsOffset++;
197
            }
198
9
        }
199
200
        private void ExtendSelectionRight()
201
        {
202
            char blockChar;
203
6
            char tempChar = itsDocument.GetCharAt(Offset);
204
6
            switch (tempChar)
205
            {
206
                case '(':
207
2
                    blockChar = ')';
208
2
                    break;
209
                case '{':
210
0
                    blockChar = '}';
211
0
                    break;
212
                case '[':
213
0
                    blockChar = ']';
214
0
                    break;
215
                case '<':
216
0
                    blockChar = '>';
217
0
                    break;
218
                default:
219
4
                    blockChar = tempChar;
220
4
                    break;
221
            }
222
6
            char[] validChars = new char[] {blockChar, '\n'};
223
            do
224
            {
225
21
                if (IsValidChar(itsDocument.GetCharAt(EndOffset), validChars))
226
4
                    break;
227
17
            } while (MoveRight());
228
229
6
            if (itsDocument.GetCharAt(EndOffset) == '\n')
230
            {
231
0
                while (itsDocument.GetCharAt(Offset) != '\n')
232
0
                    MoveLeft();
233
234
0
                itsOffset++;
235
            }
236
6
        }
237
238
        /// <summary>
239
        /// Moves offset one position to the left if possible.
240
        /// </summary>
241
        /// <returns>True if offset decreased with one position, otherwise false.</returns>
242
        private bool MoveLeft()
243
        {
244
199
            bool result = false;
245
199
            if (itsOffset > 0)
246
            {
247
171
                itsOffset--;
248
171
                result = true;
249
            }
250
199
            return result;
251
199
        }
252
253
        /// <summary>
254
        /// Validates if the character is a opening block character.
255
        /// </summary>
256
        /// <param name="c">Character to test for validity.</param>
257
        /// <returns>True if it is a opening block char, otherwise false.</returns>
258
        private static bool IsLeftBlockChar(char c)
259
        {
260
36
            char[] validChars = new char[] {'"', '(', '<', '{', '['};
261
36
            return IsValidChar(c, validChars);
262
36
        }
263
264
        /// <summary>
265
        /// Moves endoffset one position to the right if possible.
266
        /// </summary>
267
        /// <returns>True if endoffset increased with one position, otherwise false.</returns>
268
        private bool MoveRight()
269
        {
270
130
            bool result = false;
271
130
            if (itsEndOffset < itsDocument.TextLength - 1)
272
            {
273
124
                itsEndOffset++;
274
124
                result = true;
275
            }
276
130
            return result;
277
130
        }
278
279
        /// <summary>
280
        /// Validates if the character is a closing block character.
281
        /// </summary>
282
        /// <param name="c">Character to test for validity.</param>
283
        /// <returns>True if it is a closing block char, otherwise false.</returns>
284
        private static bool IsRightBlockChar(char c)
285
        {
286
53
            char[] validChars = new char[] {'"', ')', '>', '}', ']'};
287
53
            return IsValidChar(c, validChars);
288
53
        }
289
290
        private static bool IsValidChar(char c, IEnumerable<char> validChars)
291
        {
292
197
            bool result = false;
293
858
            foreach (char validChar in validChars)
294
661
                if (c == validChar) result = true;
295
197
            return result;
296
197
        }
297
298
        private enum ExtensionDirection
299
        {
300
            None = 0,
301
            Left = 1,
302
            Right = 2
303
        }
304
305
        
306
        public bool ContainsOffset(int offset)
307
        {
308
7
            return itsOffset != offset;
309
7
        }
310
311
        public TextLocation StartPosition
312
        {
313
24
            get { return itsStartPosition; }
314
17
            set { itsStartPosition = value; }
315
        }
316
317
        public TextLocation EndPosition
318
        {
319
24
            get { return itsEndPosition; }
320
17
            set { itsEndPosition = value; }
321
        }
322
323
        public int Offset
324
        {
325
325
            get { return itsOffset; }
326
        }
327
328
        public int EndOffset
329
        {
330
240
            get { return itsEndOffset; }
331
        }
332
333
        public int Length
334
        {
335
7
            get { return IsEmpty ? 0 : SelectedText.Length; }
336
        }
337
338
        public bool IsRectangularSelection
339
        {
340
7
            get { return false; }
341
        }
342
343
        public bool IsEmpty
344
        {
345
14
            get { return string.IsNullOrEmpty(SelectedText) ? true : false; }
346
        }
347
348
        public string SelectedText
349
        {
350
28
            get { return itsSelectedText; }
351
        }
352
353
354
        public bool ContainsPosition(TextLocation position)
355
        {
356
7
            System.Diagnostics.Debug.WriteLine("ContainsPosition");
357
7
            return false;
358
        }
359
    }
360
}