Sfall-ScriptEditor
1093 строки · 47.6 Кб
1using System;
2using System.Collections.Generic;
3using System.Drawing;
4using System.IO;
5using System.Linq;
6using System.Text.RegularExpressions;
7using System.Windows.Forms;
8
9using ICSharpCode.TextEditor;
10using ICSharpCode.TextEditor.Document;
11
12using ScriptEditor.CodeTranslation;
13using ScriptEditor.TextEditorUI;
14using ScriptEditor.TextEditorUtilities;
15
16using ScriptEditor.SyntaxRules;
17
18namespace ScriptEditor
19{
20partial class TextEditor
21{
22#region Search Function
23private bool SubSearchInternal(List<int> offsets, List<int> lengths)
24{
25AddSearchTextComboBox(sf.cbSearch.Text);
26
27RegexOptions option = RegexOptions.None;
28Regex regex = null;
29
30if (!sf.cbCase.Checked) option = RegexOptions.IgnoreCase;
31
32if (sf.cbRegular.Checked)
33regex = new Regex(sf.cbSearch.Text, option);
34else if (Settings.searchWholeWord)
35regex = new Regex(@"\b" + sf.cbSearch.Text + @"\b", option);
36
37if (sf.rbFolder.Checked && (Settings.lastSearchPath == null || !Directory.Exists(Settings.lastSearchPath))) {
38MessageBox.Show("No search path set.", "Error");
39return false;
40}
41if (!sf.cbFindAll.Checked) {
42if (sf.rbCurrent.Checked || (sf.rbAll.Checked && tabs.Count < 2)) {
43if (currentTab == null)
44return false;
45if (Utilities.SearchAndScroll(currentActiveTextAreaCtrl, regex, sf.cbSearch.Text, sf.cbCase.Checked, ref PosChangeType))
46return true;
47} else if (sf.rbAll.Checked) {
48int starttab = currentTab == null ? 0 : currentTab.index;
49int endtab = starttab == 0 ? tabs.Count - 1 : starttab - 1;
50int tab = starttab - 1;
51int caretOffset = currentActiveTextAreaCtrl.Caret.Offset;
52do {
53if (++tab == tabs.Count)
54tab = 0; //restart tab
55int start, len;
56if (Utilities.Search(tabs[tab].textEditor.Text, sf.cbSearch.Text, regex, caretOffset + 1, false, sf.cbCase.Checked, out start, out len)) {
57Utilities.FindSelected(tabs[tab].textEditor.ActiveTextAreaControl, start, len, ref PosChangeType);
58if (currentTab == null || currentTab.index != tab)
59tabControl1.SelectTab(tab);
60return true;
61}
62caretOffset = 0; // search from begin
63} while (tab != endtab);
64} else {
65sf.lbFindFiles.Items.Clear();
66sf.lbFindFiles.Tag = regex;
67List<string> files = sf.GetFolderFiles();
68ProgressBarForm progress = new ProgressBarForm(this, files.Count, "Search matches...");
69for (int i = 0; i < files.Count; i++)
70{
71if (Utilities.Search(File.ReadAllText(files[i]), sf.cbSearch.Text, regex, sf.cbCase.Checked))
72sf.lbFindFiles.Items.Add(files[i]);
73progress.SetProgress = i;
74}
75progress.Dispose();
76sf.labelCount.Text = sf.lbFindFiles.Items.Count.ToString();
77if (sf.lbFindFiles.Items.Count > 0) {
78if (sf.Height < 500) sf.Height = 500;
79return true;
80}
81}
82} else {
83DataGridView dgv = CommonDGV.DataGridCreate();
84dgv.DoubleClick += dgvErrors_DoubleClick;
85
86if (sf.rbCurrent.Checked || (sf.rbAll.Checked && tabs.Count < 2)) {
87if (currentTab == null)
88return false;
89Utilities.SearchForAll(currentTab, sf.cbSearch.Text, regex, sf.cbCase.Checked, dgv, offsets, lengths);
90} else if (sf.rbAll.Checked) {
91for (int i = 0; i < tabs.Count; i++)
92Utilities.SearchForAll(tabs[i], sf.cbSearch.Text, regex, sf.cbCase.Checked, dgv, offsets, lengths);
93} else {
94List<string> files = sf.GetFolderFiles();
95ProgressBarForm progress = new ProgressBarForm(this, files.Count, "Search matches...");
96for (int i = 0; i < files.Count; i++) {
97Utilities.SearchForAll(File.ReadAllLines(files[i]), Path.GetFullPath(files[i]), sf.cbSearch.Text, regex, sf.cbCase.Checked, dgv);
98progress.SetProgress = i;
99}
100progress.Dispose();
101}
102if (dgv.RowCount > 0) {
103TabPage tp = new TabPage("Search results");
104tp.ToolTipText = "Find text: " + sf.cbSearch.Text;
105tp.Controls.Add(dgv);
106dgv.Dock = DockStyle.Fill;
107tabControl2.TabPages.Add(tp);
108tabControl2.SelectTab(tp);
109MaximizeLog();
110return true;
111}
112}
113MessageBox.Show("Search string not found", "Search");
114return false;
115}
116#endregion
117
118#region Search & Replace function form
119private string lastSearchText = string.Empty;
120
121private void findToolStripMenuItem_Click(object sender, EventArgs e)
122{
123string searchText = lastSearchText;
124if (sf == null) {
125sf = new SearchForm();
126sf.Owner = this;
127
128sf.FormClosed += delegate(object a1, FormClosedEventArgs a2) {
129lastSearchText = sf.cbSearch.Text;
130sf = null;
131};
132
133sf.lbFindFiles.MouseDoubleClick += delegate (object a1, MouseEventArgs a2) {
134if (sf.lbFindFiles.Items.Count == 0) return;
135
136string file = sf.lbFindFiles.SelectedItem.ToString();
137
138TabInfo tab = CheckTabs(tabs, file); // проверить открыт ли уже этот файл
139bool isOpen = (tab != null);
140if (!isOpen) tab = Open(file, OpenType.File, false);
141
142Utilities.SearchAndScroll(tab.textEditor.ActiveTextAreaControl, (Regex)sf.lbFindFiles.Tag,
143sf.cbSearch.Text, sf.cbCase.Checked, ref PosChangeType, false);
144
145if (isOpen) SwitchToTab(tab.index);
146};
147
148sf.bSearch.Click += new EventHandler(bSearch_Click);
149sf.bReplace.Click += new EventHandler(bReplace_Click);
150
151sf.cbSearch.Items.AddRange(SearchTextComboBox.Items.Cast<String>().ToArray());
152} else {
153sf.WindowState = FormWindowState.Normal;
154sf.Focus();
155
156searchText = sf.cbSearch.Text;
157}
158
159if (currentTab != null && currentActiveTextAreaCtrl.SelectionManager.HasSomethingSelected) {
160searchText = currentActiveTextAreaCtrl.SelectionManager.SelectedText;
161}
162if (searchText.Length == 0) {
163searchText = Clipboard.GetText();
164}
165if (searchText.Length > 0 && searchText.Length < 255) {
166sf.cbSearch.Text = searchText;
167}
168sf.Show();
169sf.cbSearch.Focus();
170sf.cbSearch.SelectAll();
171}
172
173private void bSearch_Click(object sender, EventArgs e)
174{
175sf.cbSearch.Text = sf.cbSearch.Text.Trim();
176if (sf.cbSearch.Text.Length == 0)
177return;
178SubSearchInternal(null, null);
179}
180
181void bReplace_Click(object sender, EventArgs e)
182{
183sf.cbSearch.Text = sf.cbSearch.Text.Trim();
184if (sf.rbFolder.Checked || sf.cbSearch.Text.Length == 0)
185return;
186if (sf.cbFindAll.Checked) {
187List<int> lengths = new List<int>(), offsets = new List<int>();
188if (!SubSearchInternal(offsets, lengths))
189return;
190for (int i = offsets.Count - 1; i >= 0; i--)
191{
192currentDocument.Replace(offsets[i], lengths[i], sf.tbReplace.Text);
193}
194} else {
195currentActiveTextAreaCtrl.Caret.Column--;
196if (!SubSearchInternal(null, null))
197return;
198ISelection selected = currentActiveTextAreaCtrl.SelectionManager.SelectionCollection[0];
199currentDocument.Replace(selected.Offset, selected.Length, sf.tbReplace.Text);
200selected.EndPosition = new TextLocation(selected.StartPosition.Column + sf.tbReplace.Text.Length, selected.EndPosition.Line);
201currentActiveTextAreaCtrl.SelectionManager.SetSelection(selected);
202}
203}
204
205// Search for quick panel
206private void FindForwardButton_Click(object sender, EventArgs e)
207{
208string find = SearchTextComboBox.Text.Trim();
209if (find.Length == 0 || currentTab == null)
210return;
211int z = Utilities.SearchPanel(currentTab.textEditor.Text, find, currentActiveTextAreaCtrl.Caret.Offset + 1,
212CaseButton.Checked, WholeWordButton.Checked);
213if (z != -1)
214Utilities.FindSelected(currentActiveTextAreaCtrl, z, find.Length, ref PosChangeType);
215else
216DontFind.Play();
217AddSearchTextComboBox(find);
218}
219
220private void FindBackButton_Click(object sender, EventArgs e)
221{
222string find = SearchTextComboBox.Text.Trim();
223if (find.Length == 0 || currentTab == null)
224return;
225int offset = currentActiveTextAreaCtrl.Caret.Offset;
226string text = currentTab.textEditor.Text.Remove(offset);
227int z = Utilities.SearchPanel(text, find, offset - 1, CaseButton.Checked, WholeWordButton.Checked, true);
228if (z != -1)
229Utilities.FindSelected(currentActiveTextAreaCtrl, z, find.Length, ref PosChangeType);
230else
231DontFind.Play();
232AddSearchTextComboBox(find);
233}
234
235private void ReplaceButton_Click(object sender, EventArgs e)
236{
237string find = SearchTextComboBox.Text.Trim();
238if (find.Length == 0)
239return;
240string replace = ReplaceTextBox.Text.Trim();
241int z = Utilities.SearchPanel(currentTab.textEditor.Text, find, currentActiveTextAreaCtrl.Caret.Offset,
242CaseButton.Checked, WholeWordButton.Checked);
243if (z != -1)
244Utilities.FindSelected(currentActiveTextAreaCtrl, z, find.Length, ref PosChangeType, replace);
245else
246DontFind.Play();
247AddSearchTextComboBox(find);
248}
249
250private void ReplaceAllButton_Click(object sender, EventArgs e)
251{
252string find = SearchTextComboBox.Text.Trim();
253if (find.Length == 0)
254return;
255
256string replace = ReplaceTextBox.Text.Trim();
257int z, offset = 0;
258do {
259z = Utilities.SearchPanel(currentTab.textEditor.Text, find, offset,
260CaseButton.Checked, WholeWordButton.Checked);
261if (z != -1)
262currentActiveTextAreaCtrl.Document.Replace(z, find.Length, replace);
263offset = z + 1;
264} while (z != -1);
265AddSearchTextComboBox(find);
266}
267
268private void SendtoolStripButton_Click(object sender, EventArgs e)
269{
270string word = currentActiveTextAreaCtrl.SelectionManager.SelectedText;
271if (word == string.Empty)
272word = TextUtilities.GetWordAt(currentDocument, currentActiveTextAreaCtrl.Caret.Offset);
273if (word != string.Empty)
274SearchTextComboBox.Text = word;
275}
276
277private void quickFindToolStripMenuItem_Click(object sender, EventArgs e)
278{
279if (currentTab == null)
280return;
281
282SendtoolStripButton.PerformClick();
283FindForwardButton.PerformClick();
284if (!SearchToolStrip.Visible) {
285SearchToolStrip.Visible = true;
286TabClose_button.Top += (SearchToolStrip.Visible) ? 25 : -25;
287}
288}
289
290private void Search_Panel(object sender, EventArgs e)
291{
292if (currentTab == null && !SearchToolStrip.Visible) {
293findToolStripMenuItem_Click(null, null);
294return;
295}
296SearchToolStrip.Visible = !SearchToolStrip.Visible;
297TabClose_button.Top += (SearchToolStrip.Visible) ? 25 : -25;
298}
299#endregion
300
301#region References/Decleration/Definition & Include function
302private void findReferencesToolStripMenuItem_Click(object sender, EventArgs e)
303{
304TextLocation tl = currentActiveTextAreaCtrl.Caret.Position; //(TextLocation)editorMenuStrip.Tag;
305string word = TextUtilities.GetWordAt(currentDocument, currentDocument.PositionToOffset(tl));
306
307Reference[] refs = currentTab.parseInfo.LookupReferences(word, currentTab.filepath, tl.Line);
308if (refs == null)
309return;
310if (refs.Length == 0) {
311MessageBox.Show("No references found", "Reference", MessageBoxButtons.OK, MessageBoxIcon.Information);
312return;
313}
314DataGridView dgv = CommonDGV.DataGridCreate();
315dgv.DoubleClick += dgvErrors_DoubleClick;
316
317int lastLine = 0, nextColumn = 0;
318foreach (var r in refs)
319{
320if (lastLine != r.line) nextColumn = 0;
321Error error = new Error(ErrorType.Search) {
322fileName = r.file,
323line = r.line,
324column = TextUtilities.GetLineAsString(currentDocument, r.line - 1).IndexOf(word, nextColumn, StringComparison.OrdinalIgnoreCase),
325len = word.Length,
326message = (String.Compare(Path.GetFileName(r.file), currentTab.filename, true) == 0)
327? TextUtilities.GetLineAsString(currentDocument, r.line - 1).TrimStart()
328: "< Preview is not possible: for viewing goto this the reference link >"
329};
330lastLine = r.line;
331nextColumn = error.column + word.Length;
332if (error.column > 0)
333error.column++;
334dgv.Rows.Add(r.file, r.line, error);
335}
336
337TabPage tp = new TabPage("'" + word + "' references");
338tp.Controls.Add(dgv);
339dgv.Dock = DockStyle.Fill;
340tabControl2.TabPages.Add(tp);
341tabControl2.SelectTab(tp);
342MaximizeLog();
343TextArea_SetFocus(null, null);
344}
345
346private void findDeclerationToolStripMenuItem_Click(object sender, EventArgs e)
347{
348TextLocation tl = currentActiveTextAreaCtrl.Caret.Position; //(TextLocation)editorMenuStrip.Tag;
349string word = TextUtilities.GetWordAt(currentDocument, currentDocument.PositionToOffset(tl));
350string file;
351int line;
352currentTab.parseInfo.LookupDecleration(word, currentTab.filepath, tl.Line, out file, out line);
353SelectLine(file, line);
354}
355
356private void findDefinitionToolStripMenuItem_Click(object sender, EventArgs e)
357{
358if (currentTab == null) return;
359
360string word, file = currentTab.filepath;
361int line;
362TextLocation tl = currentActiveTextAreaCtrl.Caret.Position;
363if (((ToolStripDropDownItem)sender).Tag != null) { // for "Button"
364if (!currentTab.shouldParse)
365return;
366
367ParserInternal.UpdateParseBuffer(currentTab.textEditor.Text);
368
369word = TextUtilities.GetWordAt(currentDocument, currentDocument.PositionToOffset(tl));
370line = ParserInternal.GetProcedureBlock(word, 0, true).begin;
371if (line != -1)
372line++;
373else
374return;
375} else {
376//TextLocation tl = (TextLocation)editorMenuStrip.Tag;
377word = TextUtilities.GetWordAt(currentDocument, currentDocument.PositionToOffset(tl));
378currentTab.parseInfo.LookupDefinition(word, out file, out line);
379}
380SelectLine(file, line);
381}
382
383private void openIncludeToolStripMenuItem_Click(object sender, EventArgs e)
384{
385TextLocation tl = currentActiveTextAreaCtrl.Caret.Position; //(TextLocation)editorMenuStrip.Tag;
386string[] line = TextUtilities.GetLineAsString(currentDocument, tl.Line).Split('"');
387if (line.Length < 2)
388return;
389
390if (!Settings.searchIncludePath && currentTab.filepath == null && !Path.IsPathRooted(line[1])) {
391MessageBox.Show("Cannot open includes given via a relative path for an unsaved script", "Error");
392return;
393}
394if (line[1].IndexOfAny(Path.GetInvalidPathChars()) != -1) return;
395ParserInternal.GetIncludePath(ref line[1], Path.GetDirectoryName(currentTab.filepath));
396if (Open(line[1], OpenType.File, false) == null)
397MessageBox.Show("Header file not found!\n" + line[1], null, MessageBoxButtons.OK, MessageBoxIcon.Stop);
398}
399
400private void renameToolStripMenuItem_Click(object sender, EventArgs e)
401{
402Refactor.Rename((IParserInfo)renameToolStripMenuItem.Tag, currentDocument, currentTab, tabs);
403}
404#endregion
405
406#region Autocomplete and tips function control
407private void TextArea_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
408{
409//PosChangeType = PositionType.OverridePos; // Save position change for navigation, if key was pressed
410
411if (e.KeyCode == Keys.Enter) updateHighlightPocedure = false;
412
413if (autoComplete.IsVisible) {
414autoComplete.TA_PreviewKeyDown(e);
415if (Settings.autocomplete && e.KeyCode == Keys.Back) {
416autoComplete.GenerateList(String.Empty, currentTab,
417currentActiveTextAreaCtrl.Caret.Offset - 1, toolTips.Tag, true);
418}
419}
420if (toolTips.Active) {
421if (e.KeyCode == Keys.Up || (e.KeyCode == Keys.Down && !autoComplete.IsVisible)
422|| e.KeyCode == Keys.Enter || e.KeyCode == Keys.Escape
423|| (toolTips.Tag != null && !(bool)toolTips.Tag)) {
424ToolTipsHide();
425}
426else if (e.KeyCode == Keys.Left || e.KeyCode == Keys.Right) {
427int caret = currentActiveTextAreaCtrl.Caret.Offset;
428int offset = caret;
429if (e.KeyCode == Keys.Left)
430caret--;
431else {
432caret++;
433offset = TextUtilities.SearchBracketForward(currentDocument, showTipsColumn + 1, '(', ')');
434}
435if (showTipsColumn >= caret || caret > offset) ToolTipsHide();
436}
437}
438if (e.KeyCode == Keys.Tab) { // Закрытие списка, если нажата клавиша таб после ключевого слова
439if (Utilities.AutoCompleteKeyWord(currentActiveTextAreaCtrl)) {
440e.IsInputKey = true;
441autoComplete.ShiftCaret = false;
442if (autoComplete.IsVisible)
443autoComplete.Close();
444}
445}
446}
447
448private void VScrollBar_ValueChanged(object sender, EventArgs e)
449{
450autoComplete.TA_MouseScroll(currentTab.textEditor.ActiveTextAreaControl);
451if (toolTips.Active) ToolTipsHide();
452}
453
454private void ToolTipsHide()
455{
456if (autoComplete.IsVisible && (bool)toolTips.Tag)
457autoComplete.Close();
458
459toolTips.Hide(panel1);
460toolTips.Tag = toolTips.Active = false;
461}
462
463private void TextEditor_KeyDown(object sender, KeyEventArgs e)
464{
465if (e.KeyCode == Keys.ControlKey) {
466autoComplete.Hide();
467ctrlKeyPress = true;
468}
469}
470
471private void TextEditor_KeyUp(object sender, KeyEventArgs e)
472{
473if (e.KeyCode == Keys.ControlKey) {
474autoComplete.UnHide();
475ctrlKeyPress = false;
476}
477}
478
479private void showAutocompleteWordToolStripMenuItem_Click(object sender, EventArgs e)
480{
481if (currentTab != null && Settings.autocomplete) {
482Caret caret = currentActiveTextAreaCtrl.Caret;
483if (!ColorTheme.CheckColorPosition(currentDocument, caret.Position))
484autoComplete.GenerateList(String.Empty, currentTab, caret.Offset, null);
485}
486}
487
488//
489private void ShowCodeTips(string tipText, Caret caret, int duration, bool tag = false)
490{
491int offset = TextUtilities.FindWordStart(currentDocument, caret.Offset - 1);
492offset = caret.Offset - offset;
493Point pos = caret.GetScreenPosition(caret.Line, caret.Column - offset);
494pos.Offset(currentActiveTextAreaCtrl.FindForm().PointToClient(
495currentActiveTextAreaCtrl.Parent.PointToScreen(currentActiveTextAreaCtrl.Location)));
496offset = (autoComplete.IsVisible) ? -25 : 20;
497pos.Offset(0, offset);
498
499if (tag) showTipsColumn = caret.Offset;
500
501toolTips.Active = true;
502toolTips.Tag = tag;
503toolTips.Show(tipText, panel1, pos, duration);
504}
505
506private int inputPairedBrackets = 0;
507private char keyPressChar;
508
509private void TextArea_KeyPressed(object sender, KeyPressEventArgs e)
510{
511keyPressChar = e.KeyChar;
512var caret = currentActiveTextAreaCtrl.Caret;
513
514if (Settings.autoInputPaired && e.KeyChar == '"') {
515List<Utilities.Quote> quotes = new List<Utilities.Quote>();
516Utilities.GetQuotesPosition(TextUtilities.GetLineAsString(currentDocument, caret.Line), quotes);
517// skiping quotes "..." region
518bool inQuotes = false;
519foreach (Utilities.Quote q in quotes)
520{
521if (caret.Column > q.Open && caret.Column < q.Close) {
522inQuotes = true;
523break;
524}
525}
526if (!inQuotes) {
527char chR = currentDocument.GetCharAt(caret.Offset);
528char chL = currentDocument.GetCharAt(caret.Offset - 1);
529if ((chL == '(' && chR == ')') || (chL != '"' && (chR == ' ' || chR == '\r') && !Char.IsLetterOrDigit(chL)))
530currentDocument.Insert(caret.Offset, "\"");
531else if (chL == '"' && chR == '"')
532currentDocument.Remove(caret.Offset, 1);
533}
534}
535else if (e.KeyChar == '(' || e.KeyChar == '[' || e.KeyChar == '{') {
536if (autoComplete.IsVisible) autoComplete.Close();
537if (e.KeyChar == '{') return;
538
539if (Settings.showTips && currentTab.parseInfo != null && e.KeyChar == '(') {
540string word = TextUtilities.GetWordAt(currentDocument, caret.Offset - 1);
541if (word != String.Empty) {
542string item = ProgramInfo.LookupOpcodesToken(word);
543if (item != null) {
544int z = item.IndexOf('\n');
545if (z > 0)
546item = item.Remove(z);
547}
548if (item == null)
549item = currentTab.parseInfo.LookupToken(word, null, 0, true);
550if (item != null)
551ShowCodeTips(item, caret, 50000, true);
552}
553}
554
555if (Settings.autoInputPaired && Char.IsWhiteSpace(currentDocument.GetCharAt(caret.Offset))) {
556inputPairedBrackets = 2;
557string bracket = (e.KeyChar == '[') ? "]" : ")";
558currentDocument.Insert(caret.Offset, bracket);
559}
560} else if (e.KeyChar == ')' || e.KeyChar == ']' || e.KeyChar == '}') {
561if (toolTips.Active) ToolTipsHide();
562if (e.KeyChar == '}') return;
563
564if (Settings.autoInputPaired && inputPairedBrackets > 0) {
565char bracket = (e.KeyChar == ']') ? '[' : '(';
566if (currentDocument.GetCharAt(caret.Offset -1) == bracket && currentDocument.GetCharAt(caret.Offset) == e.KeyChar) {
567currentDocument.Remove(caret.Offset, 1);
568// TODO BUG: В контроле баг при использовании TextBuffer - стирается строка символов.
569//currentDocument.TextBufferStrategy.Remove(caret.Offset, 1);
570//currentActiveTextAreaCtrl.TextArea.Refresh();
571}
572}
573} else {
574if (Settings.autocomplete) {
575if (!ColorTheme.CheckColorPosition(currentDocument, caret.Position))
576autoComplete.GenerateList(e.KeyChar.ToString(), currentTab, caret.Offset - 1, toolTips.Tag);
577}
578}
579if (inputPairedBrackets > 0) inputPairedBrackets--;
580}
581
582void TextArea_KeyUp(object sender, KeyEventArgs e)
583{
584if (!currentTab.shouldParse) return;
585updateHighlightPocedure = true;
586
587if (e.KeyCode == Keys.OemSemicolon && keyPressChar == ';') Utilities.FormattingCodeSmart(currentActiveTextAreaCtrl);
588
589if (!Settings.showTips || toolTips.Active || !Char.IsLetter(Convert.ToChar(e.KeyValue))) return;
590
591var caret = currentActiveTextAreaCtrl.Caret;
592string word = TextUtilities.GetWordAt(currentDocument, caret.Offset - 1);
593if (word != String.Empty) {
594switch (word) {
595case "for":
596case "foreach":
597case "while":
598case "switch":
599case "if":
600case "ifel":
601case "elif":
602ShowCodeTips("Press the TAB key to insert the autocode.", caret, 5000);
603break;
604}
605}
606}
607#endregion
608
609#region Navigation Back/Forward
610/*
611* AddPos - Добавлять в историю новую позицию перемещения.
612* NoStore - Не сохранять следующее перемещение в историю.
613* OverridePos - Перезаписать позицию перемещения в текущей позиции истории.
614* Disabled - Не сохранять все последуюшие перемещения в историю (до явного включения функции).
615*/
616internal enum PositionType { AddPos, NoStore, OverridePos, Disabled }
617
618private void SetBackForwardButtonState()
619{
620if (currentTab.history.pointerCur > 0)
621Back_toolStripButton.Enabled = true;
622else
623Back_toolStripButton.Enabled = false;
624
625if (currentTab.history.pointerCur == currentTab.history.pointerEnd || currentTab.history.pointerCur < 0)
626Forward_toolStripButton.Enabled = false;
627else if (currentTab.history.pointerCur > 0 || currentTab.history.pointerCur < currentTab.history.pointerEnd)
628Forward_toolStripButton.Enabled = true;
629}
630
631private void Caret_PositionChanged(object sender, EventArgs e)
632{
633string ext = Path.GetExtension(currentTab.filename).ToLowerInvariant();
634if (ext != ".ssl" && ext != ".h") return;
635
636TextLocation _position = currentActiveTextAreaCtrl.Caret.Position;
637int curLine = _position.Line + 1;
638LineStripStatusLabel.Text = "Line: " + curLine;
639ColStripStatusLabel.Text = "Col: " + (_position.Column + 1);
640
641Utilities.SelectedTextColorRegion(_position, currentActiveTextAreaCtrl);
642
643if (updateHighlightPocedure) HighlightCurrentPocedure(_position.Line);
644
645if (PosChangeType == PositionType.Disabled) return;
646PosChange:
647if (PosChangeType >= PositionType.NoStore) { // also OverridePos
648if (PosChangeType == PositionType.OverridePos && currentTab.history.pointerCur != -1)
649currentTab.history.linePosition[currentTab.history.pointerCur] = _position;
650
651PosChangeType = PositionType.AddPos; // set default
652return;
653}
654
655int diff = Math.Abs(curLine - currentTab.history.prevPosition);
656currentTab.history.prevPosition = curLine;
657if (diff > 1) {
658currentTab.history.pointerCur++;
659if (currentTab.history.pointerCur >= currentTab.history.linePosition.Count)
660currentTab.history.linePosition.Add(_position);
661else
662currentTab.history.linePosition[currentTab.history.pointerCur] = _position;
663currentTab.history.pointerEnd = currentTab.history.pointerCur;
664} else {
665PosChangeType = PositionType.OverridePos;
666goto PosChange;
667}
668
669SetBackForwardButtonState();
670}
671
672private void Back_toolStripButton_Click(object sender, EventArgs e)
673{
674if (currentTab == null || currentTab.history.pointerCur == 0)
675return;
676
677currentTab.history.pointerCur--;
678GotoViewLine();
679}
680
681private void Forward_toolStripButton_Click(object sender, EventArgs e)
682{
683if (currentTab == null || currentTab.history.pointerCur >= currentTab.history.pointerEnd)
684return;
685
686currentTab.history.pointerCur++;
687GotoViewLine();
688}
689
690private void GotoViewLine()
691{
692PosChangeType = PositionType.NoStore;
693TextLocation _position = currentTab.history.linePosition[currentTab.history.pointerCur];
694currentActiveTextAreaCtrl.Caret.Position = _position;
695currentTab.history.prevPosition = _position.Line + 1;
696
697int firstLine = currentActiveTextAreaCtrl.TextArea.TextView.FirstVisibleLine;
698int lastLine = firstLine + currentActiveTextAreaCtrl.TextArea.TextView.VisibleLineCount - 1;
699if (_position.Line <= firstLine || _position.Line + 1 >= lastLine)
700currentActiveTextAreaCtrl.CenterViewOn(currentActiveTextAreaCtrl.Caret.Line, 0);
701
702SetBackForwardButtonState();
703}
704#endregion
705
706#region Procedure function Create/Rename/Delete/Move
707// Create Handlers Procedures
708public void CreateProcBlock(string name)
709{
710if (currentTab.parseInfo.CheckExistsName(name, false)) {
711MessageBox.Show("A procedure with this name has already been declared.", "Info");
712return;
713}
714byte line = (name == "look_at_p_proc" || name == "description_p_proc") ? (byte)1 : (byte)0;
715
716ProcForm CreateProcFrm = new ProcForm(name, true);
717
718if (ProcTree.SelectedNode != null && ProcTree.SelectedNode.Tag is Procedure)
719CreateProcFrm.CopyProcedure = false;
720else
721CreateProcFrm.groupBoxProcedure.Enabled = false;
722
723ProcTree.HideSelection = false;
724
725if (CreateProcFrm.ShowDialog() == DialogResult.Cancel) {
726ProcTree.HideSelection = true;
727return;
728}
729
730InsertAt placeAt = CreateProcFrm.PlaceAt;
731
732ProcedureBlock block = new ProcedureBlock();
733if (placeAt == InsertAt.After) {
734var proc = currentHighlightProc ?? (Procedure)ProcTree.SelectedNode.Tag;
735if (proc != null) {
736block.begin = proc.d.start;
737block.end = proc.d.end;
738block.declar = proc.d.declared;
739} else {
740placeAt = InsertAt.Caret;
741}
742}
743PrepareInsertProcedure(CreateProcFrm.ProcedureName, block, placeAt, line);
744
745CreateProcFrm.Dispose();
746ProcTree.HideSelection = true;
747}
748
749// Create Procedures
750private void createProcedureToolStripMenuItem_Click(object sender, EventArgs e)
751{
752if (currentTab == null || !currentTab.shouldParse) return;
753
754string word = null;
755
756bool IsSelectProcedure = ProcTree.SelectedNode != null && ProcTree.SelectedNode.Tag is Procedure;
757if (IsSelectProcedure)
758word = ProcTree.SelectedNode.Name;
759else if (currentActiveTextAreaCtrl.SelectionManager.HasSomethingSelected)
760word = currentActiveTextAreaCtrl.SelectionManager.SelectedText;
761
762ProcForm CreateProcFrm = new ProcForm(word, false, true);
763
764CreateProcFrm.SetInsertAtArter = true;
765if (!IsSelectProcedure && currentHighlightProc == null) {
766CreateProcFrm.groupBoxProcedure.Enabled = false;
767}
768
769ProcTree.HideSelection = false;
770if (CreateProcFrm.ShowDialog() == DialogResult.Cancel) {
771ProcTree.HideSelection = true;
772return;
773}
774
775string name = CreateProcFrm.CheckName;
776if (name == null) return;
777if (currentTab.parseInfo.CheckExistsName(name, NameType.Proc)) {
778MessageBox.Show("A procedure with this name has already been declared.", "Info");
779return;
780}
781
782InsertAt placeAt = CreateProcFrm.PlaceAt;
783
784ProcedureBlock block = new ProcedureBlock();
785if (CreateProcFrm.CopyProcedure || placeAt == InsertAt.After) {
786Procedure proc = currentHighlightProc;
787if (ProcTree.SelectedNode != null) {
788proc = ProcTree.SelectedNode.Tag as Procedure;
789if (proc == null) proc = currentHighlightProc;
790}
791if (proc != null) {
792block.begin = proc.d.start;
793block.end = proc.d.end;
794block.declar = proc.d.declared;
795block.copy = CreateProcFrm.CopyProcedure;
796} else {
797placeAt = InsertAt.Caret;
798}
799}
800
801name = CreateProcFrm.ProcedureName;
802PrepareInsertProcedure(name, block, placeAt);
803
804CreateProcFrm.Dispose();
805ProcTree.HideSelection = true;
806}
807
808// Create procedure block
809private void PrepareInsertProcedure(string name, ProcedureBlock block, InsertAt placeAt = InsertAt.Caret, byte overrides = 0)
810{
811int declrLine, procLine = 0, caretline = 3;
812string procbody;
813
814//Copy from procedure
815if (block.copy) {
816procbody = Utilities.GetRegionText(currentDocument, block.begin, block.end - 2) + Environment.NewLine;
817overrides = 1;
818} else
819procbody = new string(' ', Settings.tabSize) + ("script_overrides;\r\n\r\n");
820
821string procblock = (overrides > 0)
822? "\r\nprocedure " + name + " begin\r\n" + procbody + "end"
823: "\r\nprocedure " + name + " begin\r\n\r\nend";
824
825int total = currentDocument.TotalNumberOfLines - 1;
826Procedure pTop = currentTab.parseInfo.GetTopProcedure();
827int declrEndLine = ParserInternal.GetRegionDeclaration(currentTab.textEditor.Document.TextContent, (pTop != null) ? pTop.d.start - 1 : total).end;
828int caretLine = currentActiveTextAreaCtrl.Caret.Line;
829
830if (total == 0 || caretLine <= declrEndLine) placeAt = InsertAt.End;
831
832// declaration line
833if (placeAt == InsertAt.Caret) {
834procLine = caretLine;
835Procedure p = currentTab.parseInfo.GetNearProcedure(procLine); // найти процедуру которая расположена рядом
836if (p != null) {
837declrLine = p.d.Declaration;
838if (procLine < p.d.start) {
839declrLine--; // размесить над
840}
841if ((procLine + 2) == p.d.start) {
842procblock += Environment.NewLine;
843}
844} else {
845placeAt = InsertAt.End;
846ParserInternal.UpdateParseBuffer(currentTab.textEditor.Text);
847declrLine = ParserInternal.GetEndLineProcDeclaration();
848}
849}
850else if (placeAt == InsertAt.After)
851declrLine = block.declar;
852else {
853ParserInternal.UpdateParseBuffer(currentTab.textEditor.Text);
854declrLine = ParserInternal.GetEndLineProcDeclaration();
855}
856// procedure line
857if (placeAt == InsertAt.After) {
858procLine = block.end; // after current procedure
859if (procLine > total)
860procLine = block.end = total;
861else if (block.end < total)
862block.end++;
863
864if (block.end == total || TextUtilities.GetLineAsString(currentDocument, block.end).Trim().Length > 0)
865procblock += Environment.NewLine;
866}
867else if (placeAt == InsertAt.End) {
868procLine = total; // paste to end script
869}
870if (declrLine <= -1) declrLine = declrEndLine + 1;
871
872Utilities.InsertProcedure(currentActiveTextAreaCtrl, name, procblock, declrLine, procLine, ref caretline);
873
874caretline += procLine + overrides;
875currentActiveTextAreaCtrl.Caret.Column = 0;
876currentActiveTextAreaCtrl.Caret.Line = caretline;
877currentActiveTextAreaCtrl.CenterViewOn(caretline, 0);
878
879currentHighlightProc = null;
880HighlightProcedures.AddToList(currentDocument, name);
881ForceParseScript();
882SetFocusDocument();
883}
884
885// Rename Procedures
886private void renameProcedureToolStripMenuItem_Click(object sender, EventArgs e)
887{
888Procedure proc = ProcTree.SelectedNode.Tag as Procedure;
889if (proc == null) return;
890
891ProcTree.HideSelection = false;
892string newName = Refactor.RenameProcedure(proc, currentDocument, currentTab, tabs);
893ProcTree.HideSelection = true;
894
895if (newName != null) {
896ProcTree.SelectedNode.Text = newName; // обновить имя в обозревателе
897
898// выполнить обновление
899ProcTree.Tag = TreeStatus.freeze; // предотвращает следующее обновление обозревателя
900ForceParseScript();
901SetFocusDocument();
902}
903}
904
905// Delete Procedures
906private void deleteProcedureToolStripMenuItem_Click(object sender, EventArgs e)
907{
908Procedure proc = ProcTree.SelectedNode.Tag as Procedure;
909if (proc == null) return;
910
911//if (proc.IsImported) {
912// MessageBox.Show("You can't delete the imported procedure.");
913// return;
914//}
915
916if (MessageBox.Show("Are you sure you want to delete \"" + proc.name + "\" procedure?",
917"Warning", MessageBoxButtons.YesNo) == DialogResult.No) {
918return;
919}
920Utilities.PrepareDeleteProcedure(proc, currentDocument);
921ProcTree.Nodes.Remove(ProcTree.SelectedNode);
922
923currentActiveTextAreaCtrl.SelectionManager.ClearSelection();
924
925HighlightProcedures.DeleteFromList(currentDocument, proc.name);
926
927ProcTree.Tag = TreeStatus.freeze; // предотвращает следующее обновление обозревателя
928ForceParseScript();
929UpdateNodesTags();
930SetFocusDocument();
931HighlightCurrentPocedure(currentActiveTextAreaCtrl.Caret.Line);
932}
933
934private void MoveProcedure(int sIndex)
935{
936bool moveToEnd = false;
937int root = ProcTree.Nodes.Count - 1;
938
939if (sIndex > moveActive) {
940if (sIndex >= (ProcTree.Nodes[root].Nodes.Count - 1))
941moveToEnd = true;
942else
943sIndex++;
944} else if (sIndex == moveActive)
945return; //exit move
946
947Procedure moveProc = (Procedure)ProcTree.Nodes[root].Nodes[moveActive].Tag;
948// copy body
949ParserInternal.UpdateParseBuffer(currentDocument.TextContent);
950ProcedureBlock block = ParserInternal.GetProcedureBlock(moveProc.name, 0, true);
951block.declar = moveProc.d.declared;
952
953string copy_defproc;
954string copy_procbody = Environment.NewLine + Utilities.GetRegionText(currentDocument, block.begin, block.end);
955
956currentDocument.UndoStack.StartUndoGroup();
957currentActiveTextAreaCtrl.SelectionManager.ClearSelection();
958
959Utilities.DeleteProcedure(currentDocument, block, out copy_defproc);
960
961string name = ((Procedure)ProcTree.Nodes[root].Nodes[sIndex].Tag).Name;
962
963ParserInternal.UpdateParseBuffer(currentDocument.TextContent);
964// insert declration
965int offset = 0;
966if (copy_defproc != null) {
967int p_def = ParserInternal.GetDeclarationProcedureLine(name);
968if (moveToEnd) p_def++;
969if (p_def != -1) offset = currentDocument.PositionToOffset(new TextLocation(0, p_def));
970currentDocument.Insert(offset, copy_defproc + Environment.NewLine);
971}
972//paste proc block
973block = ParserInternal.GetProcedureBlock(name, 0, true);
974int p_begin;
975if (moveToEnd) {
976p_begin = block.end + 1;
977copy_procbody = Environment.NewLine + copy_procbody;
978} else {
979p_begin = block.begin;
980copy_procbody += Environment.NewLine;
981}
982offset = currentDocument.PositionToOffset(new TextLocation(0, p_begin));
983offset += TextUtilities.GetLineAsString(currentDocument, p_begin).Length;
984
985currentDocument.Insert(offset, copy_procbody);
986currentDocument.UndoStack.EndUndoGroup();
987
988// Перемещение процедуры в дереве
989if (sIndex > moveActive && !moveToEnd)
990sIndex--;
991
992TreeNode nd = ProcTree.Nodes[root].Nodes[moveActive];
993ProcTree.Nodes[root].Nodes.RemoveAt(moveActive);
994ProcTree.Nodes[root].Nodes.Insert(sIndex, nd);
995ProcTree.SelectedNode = ProcTree.Nodes[root].Nodes[sIndex];
996ProcTree.Focus();
997ProcTree.Select();
998
999currentHighlightProc = null;
1000ParserInternal.UpdateProcInfo(ref currentTab.parseInfo, currentDocument.TextContent, currentTab.filepath);
1001CodeFolder.UpdateFolding(currentDocument, currentTab.filename, currentTab.parseInfo.procs);
1002}
1003
1004private void moveProcedureToolStripMenuItem_Click(object sender, EventArgs e)
1005{
1006if (ProcTree.SelectedNode == null)
1007return;
1008if (moveActive == -1) {
1009moveActive = ProcTree.SelectedNode.Index;
1010ProcTree.SelectedNode.ForeColor = Color.Red;
1011ProcTree.AfterSelect -= TreeView_AfterSelect;
1012ProcTree.SelectedNode = ProcTree.Nodes[0];
1013ProcTree.AfterSelect += ProcTree_AfterSelect;
1014//ProcTree.ShowNodeToolTips = false;
1015}
1016}
1017
1018private void ProcTree_MouseMove(object sender, MouseEventArgs e)
1019{
1020if (moveActive < 0)
1021return;
1022
1023TreeNode node = ProcTree.GetNodeAt(e.Location);
1024if (node != null && Functions.NodeHitCheck(e.Location, node.Bounds)) {
1025if (node.Index > moveActive)
1026ProcTree.Cursor = Cursors.PanSouth;
1027else
1028ProcTree.Cursor = Cursors.PanNorth;
1029} else
1030ProcTree.Cursor = Cursors.No;
1031}
1032
1033private void ProcTree_AfterSelect(object sender, TreeViewEventArgs e)
1034{
1035if (e.Node.Parent == null || e.Node.Parent.Text != TREEPROCEDURES[1])
1036return;
1037ProcTree.AfterSelect -= ProcTree_AfterSelect;
1038currentTab.textEditor.TextChanged -= textChanged;
1039MoveProcedure(e.Node.Index);
1040currentTab.textEditor.TextChanged += textChanged;
1041ProcTree.AfterSelect += TreeView_AfterSelect;
1042ProcTree.SelectedNode.ForeColor = ProcTree.ForeColor;
1043ProcTree.Cursor = Cursors.Hand;
1044moveActive = -1;
1045//ProcTree.ShowNodeToolTips = true;
1046// set changed document
1047textChanged(null, EventArgs.Empty);
1048}
1049
1050private void ProcTree_MouseLeave(object sender, EventArgs e)
1051{
1052if (moveActive != -1) {
1053ProcTree.AfterSelect -= ProcTree_AfterSelect;
1054ProcTree.AfterSelect += TreeView_AfterSelect;
1055ProcTree.Nodes[ProcTree.Nodes.Count - 1].Nodes[moveActive].ForeColor = ProcTree.ForeColor;
1056ProcTree.Cursor = Cursors.Hand;
1057moveActive = -1;
1058}
1059}
1060
1061private void ProcTree_MouseClick(object sender, MouseEventArgs e)
1062{
1063if (e.Button == MouseButtons.Right) {
1064ProcTree_MouseLeave(null, null);
1065}
1066}
1067
1068private void ProcMnContext_Opening(object sender, System.ComponentModel.CancelEventArgs e)
1069{
1070if (ProcTree.SelectedNode != null && ProcTree.SelectedNode.Tag is Procedure &&
1071ProcTree.SelectedNode.Parent != null && (int)ProcTree.SelectedNode.Parent.Tag == 1)
1072{
1073Procedure proc = ProcTree.SelectedNode.Tag as Procedure;
1074string pName = proc.Name;
1075if (pName.IndexOf("node") > -1 || pName == "talk_p_proc")
1076editNodeCodeToolStripMenuItem.Enabled = true;
1077else
1078editNodeCodeToolStripMenuItem.Enabled = false;
1079renameProcedureToolStripMenuItem.Enabled = true;
1080moveProcedureToolStripMenuItem.Enabled = true;
1081deleteProcedureToolStripMenuItem.Enabled = true;
1082deleteProcedureToolStripMenuItem.Text = "Delete: " + proc.name;
1083} else {
1084editNodeCodeToolStripMenuItem.Enabled = false;
1085renameProcedureToolStripMenuItem.Enabled = false;
1086moveProcedureToolStripMenuItem.Enabled = false;
1087deleteProcedureToolStripMenuItem.Enabled = false;
1088deleteProcedureToolStripMenuItem.Text = "Delete procedure";
1089}
1090}
1091#endregion
1092}
1093}
1094