Sfall-ScriptEditor

Форк
0
979 строк · 41.1 Кб
1
using System;
2
using System.Collections.Generic;
3
using System.IO;
4
using System.Text.RegularExpressions;
5
using System.Windows.Forms;
6
using System.Linq;
7

8
using ICSharpCode.TextEditor;
9
using ICSharpCode.TextEditor.Document;
10

11
using ScriptEditor.CodeTranslation;
12
using ScriptEditor.TextEditorUI;
13

14
namespace ScriptEditor.TextEditorUtilities
15
{
16
    /// <summary>
17
    /// Class for text editor functions.
18
    /// </summary>
19
    internal sealed class Utilities
20
    {
21
        private const string endKeyWord = "end";
22

23
        internal struct Quote
24
        {
25
            public int Open;
26
            public int Close;
27
        }
28

29
    #region Formating code functions
30
        // for selected code
31
        public static void FormattingCode(TextAreaControl TAC)
32
        {
33
            string textCode;
34
            int offset;
35
            if (TAC.SelectionManager.HasSomethingSelected) {
36
                ISelection select = TAC.SelectionManager.SelectionCollection[0];
37
                textCode = select.SelectedText;
38
                offset = select.Offset;
39
            } else {
40
                textCode = TextUtilities.GetLineAsString(TAC.Document, TAC.Caret.Line);
41
                offset = TAC.Caret.Offset - TAC.Caret.Column;
42
            }
43
            TAC.Document.Replace(offset, textCode.Length, FormattingCode(textCode));
44
        }
45

46
        public static void FormattingCodeSmart(TextAreaControl TAC)
47
        {
48
            string textCode = TextUtilities.GetLineAsString(TAC.Document, TAC.Caret.Line);
49

50
            int col = TAC.Caret.Column;
51
            int offset = TAC.Caret.Offset - col;
52

53
            if (col < textCode.Length)
54
                textCode = textCode.Remove(col);
55

56
            string formatText = FormattingCode(textCode);
57

58
            int diffLen = formatText.Length - textCode.Length;
59
            if (diffLen > 0) {
60
                TAC.Document.Replace(offset, textCode.Length, formatText);
61
                TAC.Caret.Column += diffLen;
62
            }
63
        }
64

65
        public static string FormattingCode(string textCode)
66
        {
67
            string[] pattern = { ":=", "!=", "==", ">=", "<=", "+=", "-=", "*=", "/=", "%=", ",", ">", "<", "+", "-", "*", "/", "%" };
68
            char[] excludeR = { ' ', '=', '+', '-', '*', '/' };
69
            char[] excludeL = { ' ', '=', '>', '<', '+', '-', '!', ':', '*', '/', '%' };
70
            char[] excludeD = { ' ', ',', '(' };
71
            const string space = " ";
72

73
            List<Quote> Quotes = new  List<Quote>();
74

75
            string[] linecode = textCode.Split('\n');
76
            for (int i = 0; i < linecode.Length; i++)
77
            {
78
                string tmp = linecode[i].TrimStart();
79
                if (tmp.Length < 3 || (tmp[0] == '/' && (tmp[1] == '/' || tmp[1] == '*'))) continue;
80
                // check Quotes
81
                GetQuotesPosition(linecode[i], Quotes);
82
                foreach (string p in pattern)
83
                {
84
                    int n = 0;
85
                    do {
86
                        n = linecode[i].IndexOf(p, n);
87
                        if (n < 0)
88
                            break;
89

90
                        // skiping quotes "..."
91
                        bool inQuotes = false;
92
                        foreach (Quote q in Quotes)
93
                        {
94
                            if (n > q.Open && n < q.Close) {
95
                                n = q.Close + 1;
96
                                inQuotes = true;
97
                                break;
98
                            }
99
                        }
100
                        if (inQuotes) {
101
                            if (n >= linecode[i].Length)
102
                                break;
103
                            continue;
104
                        }
105

106
                        // insert right space
107
                        int cPos = n + p.Length;
108
                        if (linecode[i].Length > cPos && !Char.IsWhiteSpace(linecode[i], cPos)) {
109
                            if (p.Length == 2)
110
                                linecode[i] = linecode[i].Insert(n + 2, space);
111
                            else {
112
                                if (linecode[i].IndexOfAny(excludeR, n + 1, 1) == -1) {
113
                                    if ((p == "-" && Char.IsDigit(linecode[i], n + 1)
114
                                    && linecode[i].IndexOfAny(excludeD, n - 1, 1) != -1) == false               // check NegDigit
115
                                    && ((p == "+" || p == "-") && linecode[i][n - 1].ToString() == p) == false) // check '++/--'
116
                                        linecode[i] = linecode[i].Insert(n + 1, space);
117
                                }
118
                            }
119
                        }
120
                        // insert left space
121
                        if (n > 0 && p != "," && !Char.IsWhiteSpace(linecode[i], n - 1)) {
122
                            if (p.Length == 2)
123
                                linecode[i] = linecode[i].Insert(n, space);
124
                            else {
125
                                if (linecode[i].IndexOfAny(excludeL, n - 1, 1) == -1) {
126
                                    if ((p == "-" && Char.IsDigit(linecode[i], n + 1)
127
                                        && linecode[i][n - 1] == '(') == false                                      // check NegDigit
128
                                        && ((p == "+" || p == "-") && linecode[i][n + 1].ToString() == p) == false) // check '++/--'
129
                                        linecode[i] = linecode[i].Insert(n, space);
130
                                }
131
                            }
132
                        }
133

134
                        n += p.Length;
135
                    } while (n < linecode[i].Length);
136
                }
137
                Quotes.Clear();
138
            }
139
            return string.Join("\n", linecode);
140
        }
141

142
        public static void DecIndent(TextAreaControl TAC)
143
        {
144
            int indent = -1;
145
            if (TAC.SelectionManager.HasSomethingSelected) {
146
                ISelection position = TAC.SelectionManager.SelectionCollection[0];
147

148
                for (int i = position.StartPosition.Line; i <= position.EndPosition.Line; i++)
149
                {
150
                    CheckSpacesIndent(i, ref indent, TAC.Document);
151
                }
152

153
                if (indent <= 0)
154
                    return;
155
                TAC.Document.UndoStack.StartUndoGroup();
156

157
                for (int i = position.StartPosition.Line; i <= position.EndPosition.Line; i++)
158
                {
159
                    SubDecIndent(i, indent, TAC.Document);
160
                }
161

162
                TAC.Document.UndoStack.EndUndoGroup();
163
                TextLocation srtSel = TAC.SelectionManager.SelectionCollection[0].StartPosition;
164
                TextLocation endSel = TAC.SelectionManager.SelectionCollection[0].EndPosition;
165
                srtSel.Column -= indent;
166
                endSel.Column -= indent;
167
                TAC.SelectionManager.SetSelection(srtSel, endSel);
168
            } else {
169
                int line = TAC.Caret.Line;
170
                CheckSpacesIndent(line, ref indent, TAC.Document);
171
                if (indent <= 0 || SubDecIndent(line, indent, TAC.Document))
172
                    return;
173
            }
174
            TAC.Caret.Column -= indent;
175
            //TAC.Refresh();
176
        }
177

178
        private static void CheckSpacesIndent(int line, ref int indent, IDocument document)
179
        {
180
            string LineText = TextUtilities.GetLineAsString(document, line);
181
            int len = LineText.Length;
182
            int trimlen = LineText.TrimStart().Length;
183
            if (len == 0 || trimlen == 0)
184
                return;
185

186
            int spacesLen = (len - trimlen);
187
            if (indent == -1) {
188
                // Adjust indent
189
                int adjust = spacesLen % Settings.tabSize;
190
                indent = (adjust > 0) ? adjust : Settings.tabSize;
191
            }
192
            if (spacesLen < indent)
193
                indent = spacesLen;
194
        }
195

196
        private static bool SubDecIndent(int line, int indent, IDocument document)
197
        {
198
            if (TextUtilities.GetLineAsString(document, line).TrimStart().Length == 0)
199
                return true;
200
            document.Remove(document.LineSegmentCollection[line].Offset, indent);
201
            return false;
202
        }
203

204
        public static void CommentText(TextAreaControl TAC)
205
        {
206
            string commentLine = TAC.Document.HighlightingStrategy.Properties["LineComment"];
207

208
            if (TAC.SelectionManager.HasSomethingSelected) {
209
                TAC.Document.UndoStack.StartUndoGroup();
210
                ISelection position = TAC.SelectionManager.SelectionCollection[0];
211
                for (int i = position.StartPosition.Line; i <= position.EndPosition.Line; i++)
212
                {
213
                    string LineText = TextUtilities.GetLineAsString(TAC.Document, i);
214
                    string TrimText = LineText.TrimStart();
215
                    if (TrimText.StartsWith(commentLine))
216
                        continue;
217
                    int offset = LineText.Length - TrimText.Length;
218
                    offset += TAC.Document.LineSegmentCollection[i].Offset;
219
                    TAC.Document.Insert(offset, commentLine);
220
                }
221
                TAC.Document.UndoStack.EndUndoGroup();
222
                TAC.SelectionManager.ClearSelection();
223
            } else {
224
                string LineText = TextUtilities.GetLineAsString(TAC.Document, TAC.Caret.Line);
225
                string TrimText = LineText.TrimStart();
226
                if (TrimText.StartsWith(commentLine))
227
                    return;
228
                int offset = LineText.Length - TrimText.Length;
229
                offset += TAC.Document.LineSegmentCollection[TAC.Caret.Line].Offset;
230
                TAC.Document.Insert(offset, commentLine);
231
            }
232
            TAC.Caret.Column += commentLine.Length;
233
        }
234

235
        public static void UnCommentText(TextAreaControl TAC)
236
        {
237
            string commentLine = TAC.Document.HighlightingStrategy.Properties["LineComment"];
238
            int lenComment = commentLine.Length;
239

240
            if (TAC.SelectionManager.HasSomethingSelected) {
241
                TAC.Document.UndoStack.StartUndoGroup();
242
                ISelection position = TAC.SelectionManager.SelectionCollection[0];
243
                for (int i = position.StartPosition.Line; i <= position.EndPosition.Line; i++)
244
                {
245
                    string LineText = TextUtilities.GetLineAsString(TAC.Document, i);
246
                    if (!LineText.TrimStart().StartsWith(commentLine))
247
                        continue;
248
                    int n = LineText.IndexOf(commentLine);
249
                    int offset_str = TAC.Document.LineSegmentCollection[i].Offset;
250
                    TAC.Document.Remove(offset_str + n, lenComment);
251
                }
252
                TAC.Document.UndoStack.EndUndoGroup();
253
                TAC.SelectionManager.ClearSelection();
254
            } else {
255
                string LineText = TextUtilities.GetLineAsString(TAC.Document, TAC.Caret.Line);
256
                if (!LineText.TrimStart().StartsWith(commentLine))
257
                    return;
258
                int n = LineText.IndexOf(commentLine);
259
                int offset_str = TAC.Document.LineSegmentCollection[TAC.Caret.Line].Offset;
260
                TAC.Document.Remove(offset_str + n, lenComment);
261
            }
262
            TAC.Caret.Column -= lenComment;
263
        }
264

265
        public static void AlignToLeft(TextAreaControl TAC)
266
        {
267
            if (TAC.SelectionManager.HasSomethingSelected) {
268
                ISelection position = TAC.SelectionManager.SelectionCollection[0];
269
                string LineText = TextUtilities.GetLineAsString(TAC.Document, position.StartPosition.Line);
270
                int Align = LineText.Length - LineText.TrimStart().Length; // узнаем длину отступа
271
                TAC.Document.UndoStack.StartUndoGroup();
272
                for (int i = position.StartPosition.Line + 1; i <= position.EndPosition.Line; i++)
273
                {
274
                    LineText = TextUtilities.GetLineAsString(TAC.Document, i);
275
                    int len = LineText.Length - LineText.TrimStart().Length;
276
                    if (len == 0 || len <= Align) continue;
277
                    int offset = TAC.Document.LineSegmentCollection[i].Offset;
278
                    TAC.Document.Remove(offset, len-Align);
279
                }
280
                TAC.Document.UndoStack.EndUndoGroup();
281
            }
282
        }
283
    #endregion
284

285
    # region Search Function
286
        public static bool Search(string text, string str, Regex regex, int start, bool restart, bool mcase, out int mstart, out int mlen)
287
        {
288
            if (start >= text.Length) start = 0;
289
            mstart = 0;
290
            mlen = str.Length;
291
            if (regex != null) {
292
                Match m = regex.Match(text, start);
293
                if (m.Success) {
294
                    mstart = m.Index;
295
                    mlen = m.Length;
296
                    return true;
297
                }
298
                if (!restart) return false;
299
                m = regex.Match(text);
300
                if (m.Success) {
301
                    mstart = m.Index;
302
                    mlen = m.Length;
303
                    return true;
304
                }
305
            } else {
306
                int i = text.IndexOf(str, start, (mcase) ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
307
                if (i != -1) {
308
                    mstart = i;
309
                    return true;
310
                }
311
                if (!restart) return false;
312
                i = text.IndexOf(str, (mcase) ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
313
                if (i != -1) {
314
                    mstart = i;
315
                    return true;
316
                }
317
            }
318
            return false;
319
        }
320

321
        public static bool Search(string text, string str, Regex regex, bool mcase)
322
        {
323
            return (regex == null)
324
                    ? (text.IndexOf(str, (mcase) ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase) != -1)
325
                    : regex.IsMatch(text);
326
        }
327

328
        public static bool SearchAndScroll(TextAreaControl TAC, Regex regex, string searchText, bool mcase, ref ScriptEditor.TextEditor.PositionType type, bool searchContinue = true)
329
        {
330
            int start, len;
331
            if (Search(TAC.Document.TextContent, searchText, regex, (searchContinue) ? TAC.Caret.Offset + 1 : 0, true, mcase, out start, out len)) {
332
                FindSelected(TAC, start, len, ref type);
333
                return true;
334
            }
335
            return false;
336
        }
337

338
        public static void FindSelected(TextAreaControl TAC, int start, int len, ref ScriptEditor.TextEditor.PositionType type, string replace = null)
339
        {
340
            type = ScriptEditor.TextEditor.PositionType.NoStore;
341

342
            TextLocation locstart = TAC.Document.OffsetToPosition(start);
343
            TextLocation locend = TAC.Document.OffsetToPosition(start + len);
344
            TAC.SelectionManager.SetSelection(locstart, locend);
345
            if (replace != null) {
346
                TAC.Document.Replace(start, len, replace);
347
                locend = TAC.Document.OffsetToPosition(start + replace.Length);
348
                TAC.SelectionManager.SetSelection(locstart, locend);
349
            }
350
            TAC.Caret.Position = locstart;
351
            TAC.CenterViewOn(locstart.Line, Math.Max(2, TAC.TextArea.TextView.VisibleLineCount / 4));
352
        }
353

354
        public static void SearchForAll(TabInfo tab, string searchText, Regex regex, bool mcase, DataGridView dgv, List<int> offsets, List<int> lengths)
355
        {
356
            int start, len, line, lastline = -1;
357
            int offset = 0;
358
            while (Search(tab.textEditor.Text, searchText, regex, offset, false, mcase, out start, out len))
359
            {
360
                offset = start + 1;
361
                line = tab.textEditor.Document.OffsetToPosition(start).Line;
362
                if (offsets != null) {
363
                    offsets.Add(start);
364
                    lengths.Add(len);
365
                }
366
                if (line != lastline) {
367
                    lastline = line;
368
                    string message = TextUtilities.GetLineAsString(tab.textEditor.Document, line).Trim();
369
                    Error error = new Error(message, tab.filepath, line + 1, tab.textEditor.Document.OffsetToPosition(start).Column + 1, len);
370
                    dgv.Rows.Add(tab.filename, error.line.ToString(), error);
371
                }
372
            }
373
        }
374

375
        public static void SearchForAll(string[] text, string file, string searchText, Regex regex, bool mcase, DataGridView dgv)
376
        {
377
            bool matched;
378
            for (int i = 0; i < text.Length; i++)
379
            {
380
                if (regex != null)
381
                    matched = regex.IsMatch(text[i]);
382
                else
383
                    matched = text[i].IndexOf(searchText, (mcase) ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase) != -1;
384
                if (matched) {
385
                    Error error = new Error(text[i].Trim(), file, i + 1);
386
                    dgv.Rows.Add(Path.GetFileName(file), (i + 1).ToString(), error);
387
                }
388
            }
389
        }
390

391
        public static int SearchPanel(string text, string find, int start, bool icase, bool wholeword, bool back = false)
392
        {
393
            int z;
394
            if (wholeword) {
395
                RegexOptions option = RegexOptions.Multiline;
396
                if (!icase)
397
                    option |= RegexOptions.IgnoreCase;
398
                if (back)
399
                    option |= RegexOptions.RightToLeft;
400
                z = SearchWholeWord(text, find, start, option);
401
            } else {
402
                StringComparison sc = (!icase) ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
403
                z = (back) ? text.LastIndexOf(find, start, sc)
404
                           : text.IndexOf(find, start, sc);
405
            }
406
            return z;
407
        }
408

409
        public static int SearchWholeWord(string text, string find, int start, RegexOptions option)
410
        {
411
            int z, x;
412
            string search = @"\b" + Regex.Escape(find) + @"\b";
413
            Regex s_regex = new Regex(search, option);
414

415
            if (!Search(text, find, s_regex, start, false, false, out z, out x))
416
                return -1;
417

418
            return z;
419
        }
420

421
        internal static bool IsAnyChar(char ch, char[] chars)
422
        {
423
            bool result = false;
424
            foreach (char c in chars)
425
            {
426
                if (c == ch)
427
                    result = true;
428
            }
429
            return result;
430
        }
431
    #endregion
432

433
    #region Create/Delete procedure function
434
        internal static void PrepareDeleteProcedure(Procedure proc, IDocument document)
435
        {
436
            string def_poc;
437

438
            ParserInternal.UpdateParseBuffer(document.TextContent);
439
            ProcedureBlock block = ParserInternal.GetProcedureBlock(proc.name, 0, true);
440
            block.declar = proc.d.declared;
441

442
            document.UndoStack.StartUndoGroup();
443
            DeleteProcedure(document, block, out def_poc);
444
            document.UndoStack.EndUndoGroup();
445
        }
446

447
        // Remove multi procedures
448
        internal static void DeleteProcedure(List<string> procName, IDocument document)
449
        {
450
            document.UndoStack.StartUndoGroup();
451
            foreach (var name in procName)
452
            {
453
                string def_poc;
454

455
                ParserInternal.UpdateParseBuffer(document.TextContent);
456
                ProcedureBlock block = ParserInternal.GetProcedureBlock(name, 0, true);
457
                block.declar = ParserInternal.GetDeclarationProcedureLine(name) + 1;
458
                DeleteProcedure(document, block, out def_poc);
459
            }
460
            document.UndoStack.EndUndoGroup();
461
        }
462

463
        internal static void DeleteProcedure(IDocument document, ProcedureBlock block, out string def_poc)
464
        {
465
            ISegment segmentS = document.GetLineSegment(block.begin);
466
            ISegment segmentE = document.GetLineSegment(block.end);
467
            int len = (segmentE.Offset + segmentE.Length) - segmentS.Offset;
468

469
            int inc_s = 0;
470
            int inc_e = 2;
471
            if (block.end < document.TotalNumberOfLines - 1) {
472
                if (segmentS.Offset + len + 4 <= document.TextLength) {
473
                    if (document.GetLineSegment(block.end + 1).Length == 0) {
474
                        if (block.begin > 0 && document.GetLineSegment(block.begin - 1).Length == 0) {
475
                            len += 2;
476
                            inc_s = -2;
477
                        }
478
                    }
479
                }
480
                else
481
                    inc_e = 0;
482
            } else
483
                inc_e = 0;
484
            document.Remove(segmentS.Offset + inc_s, len + inc_e);
485

486
            // declare
487
            int declarLine = block.declar - 1;
488
            if (declarLine > -1 & declarLine != block.begin) {
489
                def_poc = TextUtilities.GetLineAsString(document, declarLine);
490
                int offset = document.PositionToOffset(new TextLocation(0, declarLine));
491
                document.Remove(offset, def_poc.Length + 2);
492
            } else
493
                def_poc = null;
494
        }
495

496
        // Create procedure block
497
        internal static void InsertProcedure(TextAreaControl TAC, string name, string procblock, int declrLine, int procLine, ref int caretline)
498
        {
499
            TAC.Document.UndoStack.StartUndoGroup();
500
            TAC.SelectionManager.ClearSelection();
501

502
            // proc body paste
503
            int len = TextUtilities.GetLineAsString(TAC.Document, procLine).Trim().Length;
504
            if (len > 0) {
505
                procblock = Environment.NewLine + procblock;
506
                caretline++;
507
            }
508
            int offset = TAC.Document.PositionToOffset(new TextLocation(len, procLine));
509
            TAC.Document.Insert(offset, procblock);
510

511
            // declared paste
512
            offset = TAC.Document.PositionToOffset(new TextLocation(0, declrLine));
513
            TAC.Document.Insert(offset, "procedure " + name + ";" + Environment.NewLine);
514

515
            TAC.Document.UndoStack.EndUndoGroup();
516
        }
517
    #endregion
518

519
    #region Misc code function
520
        internal static void HighlightingSelectedText(TextAreaControl TAC)
521
        {
522
            List<TextMarker> marker = TAC.Document.MarkerStrategy.GetMarkers(0, TAC.Document.TextLength);
523
            foreach (TextMarker m in marker)
524
            {
525
                if (m.TextMarkerType == TextMarkerType.SolidBlock)
526
                    TAC.Document.MarkerStrategy.RemoveMarker(m);
527
            }
528
            if (!TAC.SelectionManager.HasSomethingSelected) return;
529

530
            string sWord = TAC.SelectionManager.SelectedText.Trim();
531
            int wordLen = sWord.Length;
532
            if (wordLen == 0 || (wordLen <= 2 && !Char.IsLetterOrDigit(sWord[0]) && wordLen == 2 && !Char.IsLetterOrDigit(sWord[1]))) return;
533

534
            string word = TAC.Document.LineSegmentCollection[TAC.Caret.Line].GetWord(TAC.SelectionManager.SelectionCollection[0].StartPosition.Column).Word;
535
            bool isWordHighlighting = (wordLen == word.Length && sWord == word);
536

537
            int seek = 0;
538
            while (seek < TAC.Document.TextLength) {
539
                seek = TAC.Document.TextContent.IndexOf(sWord, seek);
540
                if (seek == -1) break;
541
                char chS = '\0', chE = '\0';
542
                if (isWordHighlighting) {
543
                    chS = (seek > 0) ? TAC.Document.GetCharAt(seek - 1) : ' ';
544
                    chE = ((seek + wordLen) < TAC.Document.TextLength) ? TAC.Document.GetCharAt(seek + wordLen) : ' ';
545
                }
546
                if (!isWordHighlighting || !(Char.IsLetterOrDigit(chS) || chS == '_') && !(Char.IsLetterOrDigit(chE) || chE == '_'))
547
                    TAC.Document.MarkerStrategy.AddMarker(new TextMarker(seek, sWord.Length, TextMarkerType.SolidBlock,
548
                                                          ColorTheme.SelectedHighlight.BackgroundColor, ColorTheme.SelectedHighlight.Color));
549
                seek += wordLen;
550
            }
551
            TAC.SelectionManager.ClearSelection();
552
        }
553

554
        // Auto selected text color region
555
        internal static void SelectedTextColorRegion(TextLocation position, TextAreaControl TAC)
556
        {
557
            if (position.IsEmpty) position = TAC.Caret.Position;
558

559
            HighlightColor hc = TAC.Document.GetLineSegment(position.Line).GetColorForPosition(position.Column);
560
            if (hc != null && hc.BackgroundColor == ColorTheme.CodeFunctions) {
561
                int sEnd  = TextUtilities.SearchBracketForward(TAC.Document, TAC.Caret.Offset + 1, '{', '}');
562
                char c = TAC.Document.GetCharAt(TAC.Caret.Offset);
563
                if (sEnd == -1) {
564
                    if (c != '}') return;
565
                    sEnd = TAC.Caret.Offset;
566
                }
567
                int sStart = TextUtilities.SearchBracketBackward(TAC.Document, TAC.Caret.Offset - 1, '{', '}');
568
                if (sStart == -1) {
569
                    if (c != '{') return;
570
                    sStart = TAC.Caret.Offset;
571
                }
572
                int len = sEnd - sStart;
573
                if (len < 2) return;
574
                TextLocation sSel = TAC.Document.OffsetToPosition(sStart);
575
                TextLocation eSel = TAC.Document.OffsetToPosition(sEnd + 1);
576
                if (sSel.Line != eSel.Line || TAC.Document.GetText(sStart, len).IndexOfAny(new char[] { ':', ',' }) != -1) return;
577
                TAC.SelectionManager.SetSelection(sSel, eSel);
578
            }
579
        }
580

581
        // Paste autocomplete KeyWord construction code
582
        internal static bool AutoCompleteKeyWord(TextAreaControl TAC)
583
        {
584
            Caret caret = TAC.Caret;
585
            if (ColorTheme.CheckColorPosition(TAC.Document, caret.Position))
586
                return false;
587

588
            int offsetShift = 1;
589
            if (TAC.Document.TextLength == caret.Offset) offsetShift++;
590

591
            string keyword = TextUtilities.GetWordAt(TAC.Document, caret.Offset - offsetShift);
592
            if (keyword.Length < 2)
593
                return false;
594

595
            string lineText = TextUtilities.GetLineAsString(TAC.Document, caret.Line);
596
            int totalWS = 0, totalTab = 0;
597
            for (int i = 0; i < lineText.Length; i++)
598
            {
599
                if (lineText[i] == ' ')
600
                    totalWS++;
601
                else if (lineText[i] == '\t')
602
                    totalTab++;
603
                else
604
                     break;
605
            }
606

607
            int indentationSize = TAC.TextEditorProperties.IndentationSize;
608
            bool convertTab = TAC.TextEditorProperties.ConvertTabsToSpaces;
609
            if (convertTab) {
610
                totalTab *= indentationSize;
611
            } else {
612
                totalWS /= indentationSize;
613
            }
614
            int columnStart = totalWS + totalTab;
615

616
            int keyStart = TextUtilities.FindWordStart(TAC.Document, caret.Offset - offsetShift);
617
            int keyLen = caret.Offset - keyStart;
618
            bool cutKeyWord = keyword.Length > keyLen;
619
            if (cutKeyWord) keyword = keyword.Remove(keyLen);
620

621
            string beginIndent = String.Empty;
622
            if (caret.Column > keyword.Length) beginIndent = new String((convertTab) ? ' ' : '\t', columnStart);
623

624
            string indentation = beginIndent;
625
            if (convertTab)
626
                indentation += new String(' ', indentationSize);
627
            else
628
                indentation += '\t';
629

630
            int lineShift = 2, columnShift = 0;
631
            if (convertTab) {
632
                if (totalTab > 0) {
633
                    columnShift -= (totalTab / indentationSize);
634
                    columnShift += columnShift;
635
                }
636
            } else if (totalWS > 0) columnShift = (totalWS * indentationSize) - totalWS;
637

638
            bool keyWordMatch = true;
639
            string code = null;
640
            TAC.Document.UndoStack.StartUndoGroup();
641
            switch (keyword)
642
            {
643
                case "for":
644
                    code = " ({iterator} := 0; {condition}; {iterator}++) begin\r\n" + indentation + "\r\n";
645
                    columnShift += 2;
646
                    break;
647
                case "foreach":
648
                    code = " ({iterator}: {item} in {array}) begin\r\n" + indentation + "\r\n";
649
                    columnShift += 6;
650
                    break;
651
                case "while":
652
                    code = " ({condition}) do begin\r\n" + indentation + "\r\n";
653
                    columnShift += 4;
654
                    break;
655
                case "switch":
656
                    code = " ({condition}) begin\r\n" + indentation
657
                           + "case {constant} : {code}\r\n" + indentation
658
                           + "default         : {code}\r\n";
659
                    lineShift++;
660
                    columnShift += 5;
661
                    break;
662
                case "if":
663
                    code = " ({condition}) then begin\r\n" + indentation + "\r\n";
664
                    columnShift++;
665
                    break;
666
                case "ifel":
667
                    code = "({condition}) then begin" + String.Format("{0}{2}{0}{1}else{0}{2}{0}",
668
                                                        "\r\n", beginIndent, indentation);
669
                    lineShift = 4;
670
                    columnShift += 2;
671
                    TAC.Document.Remove(caret.Offset - 2, 2);
672
                    break;
673
                case "elif":
674
                    code = " if ({condition}) then begin\r\n" + indentation + "\r\n";
675
                    columnShift += 6;
676
                    TAC.Document.Replace(caret.Offset - 2, 2, "se");
677
                    break;
678
                case "else":
679
                    code = " begin\r\n" + indentation + "\r\n";
680
                    lineShift = 1;
681
                    int isize = (convertTab) ? indentationSize : 1;
682
                    columnShift = (columnStart + isize) - (columnStart + 3);
683
                    break;
684
                case "then":
685
                    code = " begin";
686
                    lineShift = 0;
687
                    columnShift = 0;
688
                    break;
689
                case "var":
690
                    code = "iable ";
691
                    lineShift = 0;
692
                    columnShift = 0;
693
                    break;
694
                case "proc":
695
                    code = "edure ";
696
                    lineShift = 0;
697
                    columnShift = 0;
698
                    break;
699
                default:
700
                    keyWordMatch = false;
701
                    break;
702
            }
703
            if (keyWordMatch) {
704
                if (lineShift != 0) {
705
                    code += beginIndent + endKeyWord + ((cutKeyWord) ? " " : String.Empty);
706
                }
707
                TAC.TextArea.InsertString(code);
708
                TAC.Caret.Position = new TextLocation(caret.Column + columnShift, caret.Line - lineShift); //+ keyword.Length - columnShift
709
                Utilities.SelectedTextColorRegion(caret.Position, TAC);
710
            }
711
            TAC.Document.UndoStack.EndUndoGroup();
712

713
            return keyWordMatch;
714
        }
715

716
        internal static void PasteIncludeFile(string sHeaderfile, TextAreaControl TAC)
717
        {
718
            if (sHeaderfile != null) {
719
                int beginLine = 1, endLine = 1;
720
                foreach (FoldMarker fm in TAC.Document.FoldingManager.FoldMarker) {
721
                    if (fm.FoldType == FoldType.Region) {
722
                        beginLine = fm.StartLine;
723
                        endLine = fm.EndLine;
724
                        break;
725
                    }
726
                }
727

728
                string includeText = "#include ";
729
                var caret = TAC.Caret.Line;
730
                if (caret >= beginLine && caret <= endLine) {
731
                    beginLine = caret;
732
                } else {
733
                    for (int line = endLine; line > 0; line--) {
734
                        string ln = TextUtilities.GetLineAsString(TAC.Document, line);
735
                        if (ln.TrimStart().StartsWith(includeText, StringComparison.OrdinalIgnoreCase)) {
736
                            beginLine = line + 1;
737
                            break;
738
                        }
739
                    }
740
                }
741

742
                includeText += "\"" + sHeaderfile + "\"" + Environment.NewLine;
743
                int offset = TAC.Document.PositionToOffset(new TextLocation(0, beginLine));
744
                TAC.Document.Insert(offset, includeText);
745
                TAC.Document.MarkerStrategy.AddMarker(new TextMarker(offset, includeText.Length, TextMarkerType.SolidBlock, ColorTheme.IncludeHighlight));
746
                TAC.ScrollTo(beginLine);
747
                TAC.Refresh();
748
            }
749
        }
750

751
    #endregion
752

753
    #region Script code text functions
754
        public static int ReplaceCommonText(Regex s_regex, ref string document, string newText, int differ)
755
        {
756
            MatchCollection matches = s_regex.Matches(document);
757

758
            int replace_count = 0;
759
            foreach (Match m in matches)
760
            {
761
                int offset = (differ * replace_count) + m.Index;
762
                document = document.Remove(offset, m.Length);
763
                document = document.Insert(offset, newText);
764
                replace_count++;
765
            }
766
            return matches.Count;
767
        }
768

769
        // используется для замены имени процедур
770
        public static int ReplaceSpecialText(Regex s_regex, ref string document, string newText, int differ)
771
        {
772
            MatchCollection matches = s_regex.Matches(document);
773

774
            int replace_count = 0;
775
            foreach (Match m in matches)
776
            {
777
                var shiftOffset = (m.Groups.Count > 1) ? m.Groups[1].Length : 0;
778
                int offset = (differ * replace_count) + (m.Index + shiftOffset);
779

780
                document = document.Remove(offset, (m.Length - shiftOffset));
781
                document = document.Insert(offset, newText);
782
                replace_count++;
783
            }
784
            return matches.Count;
785
        }
786

787
        public static void ReplaceIDocumentText(Regex s_regex, IDocument document, string newText, int differ)
788
        {
789
            MatchCollection matches = s_regex.Matches(document.TextContent);
790
            document.UndoStack.StartUndoGroup();
791

792
            int replace_count = 0;
793
            foreach (Match m in matches)
794
            {
795
                ReplaceMatch(document, newText, differ * replace_count++, m);
796
            }
797
            document.UndoStack.EndUndoGroup();
798
        }
799

800
        public static void ReplaceByReferences(Regex s_regex, IDocument document, IParserInfo pi, string newText, int differ)
801
        {
802
            MatchCollection matches = s_regex.Matches(document.TextContent);
803

804
            bool isVariable = (pi is Variable);
805

806
            bool decl = false, define = isVariable;
807
            int declared = (isVariable) ? (((Variable)pi).IsArgument) ? ((Variable)pi).adeclared : ((Variable)pi).d.declared
808
                                        : ((Procedure)pi).d.declared;
809

810
            List<Reference> references = pi.References().ToList();
811
            List<Match> renameReferences = new List<Match>();
812

813
            foreach (Match m in matches)
814
            {
815
                int line = document.OffsetToPosition(m.Index).Line + 1;
816

817
                if (!decl && declared == line) {
818
                    renameReferences.Add(m);
819
                    decl = true;
820
                } else if (!define && ((Procedure)pi).d.defined == line) { // может быть -1 если declared для процедуры не был объявлен
821
                    renameReferences.Add(m);
822
                    define = true;
823
                } else {
824
                    for (int i = 0; i < references.Count; i++)
825
                    {
826
                        if (references[i].line == line) {
827
                            renameReferences.Add(m);
828
                            references.RemoveAt(i);
829
                            break;
830
                        }
831
                    }
832
                }
833
            }
834
            document.UndoStack.StartUndoGroup();
835

836
            int replace_count = 0;
837
            foreach (Match refMatch in renameReferences)
838
            {
839
                ReplaceMatch(document, newText, differ * replace_count++, refMatch);
840
            }
841
            document.UndoStack.EndUndoGroup();
842

843
            if (references.Count > 0) MessageBox.Show("Some of the references have not been renamed.", "Warning");
844
        }
845

846
        private static void ReplaceMatch(IDocument document, string newText, int replacedCount, Match m)
847
        {
848
            var shiftOffset = (m.Groups.Count > 1) ? m.Groups[1].Length : 0;
849
            int offset = replacedCount + (m.Index + shiftOffset);
850
            document.Replace(offset, (m.Length - shiftOffset), newText);
851
        }
852

853
        internal static string GetProcedureCode(IDocument document, Procedure curProc)
854
        {
855
            if (curProc.d.start == -1 || curProc.d.end == -1) // for imported or w/o body procedure
856
                return null;
857

858
            LineSegment start = document.GetLineSegment(curProc.d.start);
859
            LineSegment end = document.GetLineSegment(curProc.d.end - 1);
860
            int length = end.Offset - start.Offset - 2; // -2 не захватываем символы CRLF
861

862
            return (length < 0) ? String.Empty : document.GetText(start.Offset, length);
863
        }
864

865
        internal static bool ReplaceProcedureCode(IDocument document,  ProgramInfo pi, string name, string code)
866
        {
867
            int index = pi.GetProcedureIndex(name);
868
            if (index == -1)
869
                return true; // procedure not found
870

871
            LineSegment start = document.GetLineSegment(pi.procs[index].d.start);
872
            LineSegment end = document.GetLineSegment(pi.procs[index].d.end - 1);
873
            int length = end.Offset - start.Offset - 2; // -2 не заменяем символы CRLF
874

875
            if (length < 0 && code.Length > 0 && !code[code.Length - 1].Equals('\n'))
876
                code += Environment.NewLine;
877

878
            if (length < 0)
879
                document.Insert(start.Offset, code);
880
            else
881
                document.Replace(start.Offset, length, code);
882

883
            return false;
884
        }
885

886
        internal static void InsertText(string iText, TextAreaControl TAC)
887
        {
888
            TAC.Document.UndoStack.StartUndoGroup();
889
            if (TAC.SelectionManager.HasSomethingSelected) {
890
                TextLocation selStart = TAC.SelectionManager.SelectionCollection[0].StartPosition;
891
                TAC.TextArea.SelectionManager.RemoveSelectedText();
892
                TAC.Caret.Position = selStart;
893
            }
894
            TAC.TextArea.InsertString(iText);
895
            TAC.Document.UndoStack.EndUndoGroup();
896
        }
897

898
        //Get block text
899
        internal static string GetRegionText(IDocument document, int _begin, int _end, int _ecol = 0, int _bcol = 0)
900
        {
901
            ISegment segmentB = document.GetLineSegment(_begin);
902
            ISegment segmentE = document.GetLineSegment(_end);
903

904
            int Offset = segmentB.Offset + _bcol;
905
            int Length;
906
            if (_ecol > 0)
907
                Length = segmentE.Offset + _ecol;
908
            else
909
                Length = segmentE.Offset + segmentE.Length;
910
            Length -= Offset;
911

912
            return document.GetText(Offset, Length);
913
        }
914

915
        //Selected and return block text [NOT USED]
916
        internal static string GetSelectBlockText(TextAreaControl TAC, int _begin, int _end, int _ecol = -1, int _bcol = 0)
917
        {
918
            if (_ecol < 0)
919
                _ecol = TAC.Document.GetLineSegment(_end).Length;
920
            TAC.SelectionManager.SetSelection(new TextLocation(_bcol, _begin), new TextLocation(_ecol, _end));
921
            return TAC.SelectionManager.SelectedText;
922
        }
923

924
        internal static string NormalizeNewLine(string text)
925
        {
926
            char[] delimetr = new char[] {'\r', '\n'};
927

928
            int offset = 0;
929
            while (offset < text.Length) {
930
                offset = text.IndexOfAny(delimetr, offset);
931
                if (offset == -1)
932
                    break;
933
                switch (text[offset]) {
934
                    case '\r':
935
                        if (offset + 1 < text.Length) {
936
                            if (text[++offset] != delimetr[1])
937
                                text = text.Insert(offset, delimetr[1].ToString());
938
                        }
939
                        break;
940
                    case '\n':
941
                        if (offset > 0 && text[offset - 1] != delimetr[0])
942
                            text = text.Insert(offset, delimetr[0].ToString());
943
                        break;
944
                }
945
                offset++;
946
            };
947
            return text;
948
        }
949

950
        internal static void ConvertToUnixPlatform(ref string text)
951
        {
952
            if (Environment.OSVersion.Platform != PlatformID.Unix) return;
953
            int offset = 0;
954
            while (offset < text.Length)
955
            {
956
                offset = text.IndexOf('\r', offset);
957
                if (offset == -1) break;
958
                text = text.Remove(offset, 1);
959
                offset++;
960
            };
961
        }
962

963
        internal static void GetQuotesPosition(string textCode, List<Quote> quotes)
964
        {
965
            int openQuotes = textCode.IndexOf('"');
966
            while (openQuotes > -1)
967
            {
968
                Quote position;
969
                position.Open = openQuotes++;
970
                position.Close = textCode.IndexOf('"', openQuotes);
971
                if (position.Close == -1)
972
                    break;
973
                quotes.Add(position);
974
                openQuotes = textCode.IndexOf('"', position.Close + 1);
975
            };
976
        }
977
    #endregion
978
    }
979
}
980

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.