public RTFBuilder ColorArg(string arg) { if (arg.StartsWith("\"") || arg.StartsWith("\'")) { bool colon = arg.EndsWith(arg[0].ToString() + ":"); if (arg.Length == 1 || (!arg.EndsWith(arg[0].ToString()) && !colon)) { return(RTFBuilder.Colored(RTFBuilder.WavyUnderline(RTFBuilder.For(arg)), ColorTable.PINK)); } RTFBuilder res = new RTFBuilder(); res.Append(RTFBuilder.Colored(RTFBuilder.For(arg[0].ToString()), ColorTable.DARK_CYAN)); res.Append(RTFBuilder.Colored(ColorArg(arg.Substring(1, arg.Length - (colon ? 3 : 2))), ColorTable.DARK_CYAN)); res.Append(RTFBuilder.Colored(RTFBuilder.For(arg[0].ToString()), ColorTable.DARK_CYAN)); if (colon) { res.Append(RTFBuilder.For(":")); } return(res); } RTFBuilder built = new RTFBuilder(); StringBuilder sb = new StringBuilder(); int deep = 0; for (int i = 0; i < arg.Length; i++) { if (arg[i] == '<') { if (deep == 0) { built.Append(RTFBuilder.For(sb.ToString())); sb.Clear(); } deep++; } else if (deep > 0 && arg[i] == '>') { deep--; if (deep == 0) { built.Append(RTFBuilder.BackColored(RTFBuilder.Colored(RTFBuilder.For("<"), ColorTable.DARK_GRAY), ColorTable.LIGHT_GRAY)); if (sb.Length > 1) { built.Append(RTFBuilder.BackColored(RTFBuilder.Colored(ColorInsideTag(sb.ToString().Substring(1, sb.Length - 1)), ColorTable.DARK_GRAY), ColorTable.LIGHT_GRAY)); } built.Append(RTFBuilder.BackColored(RTFBuilder.Colored(RTFBuilder.For(">"), ColorTable.DARK_GRAY), ColorTable.LIGHT_GRAY)); sb.Clear(); continue; } } sb.Append(arg[i]); } built.Append(RTFBuilder.For(sb.ToString())); return(built); }
// TODO: Accelerate this method as much as possible using async and whatever else we can do! // Maybe also replace RTFBuilder with lower-level / simpler calls somehow. private void T_Tick(object sender, EventArgs e) { if (!textChanged || NoDup) { return; } NoDup = true; // Setup Suspend(this); int start = RTFBox.SelectionStart; int len = RTFBox.SelectionLength; Point scroll = GetScrollPos(RTFBox); // Update RTF string[] lines = RTFBox.Text.Replace("\r", "").Split('\n'); RTFBuilder rtf = new RTFBuilder(); RTFBox.Rtf = ""; for (int i = 0; i < lines.Length; i++) { string line = lines[i]; string trim = lines[i].Trim(); if (trim.Length != 0) { if (trim.StartsWith("#")) { string nospace = trim.Replace(" ", ""); if (nospace.StartsWith("#-") || nospace.StartsWith("#|") || nospace.StartsWith("#+")) { rtf.Append(RTFBuilder.Colored(RTFBuilder.For(line), ColorTable.RED)); } else { rtf.Append(RTFBuilder.Colored(RTFBuilder.For(line), ColorTable.GREEN)); } } else if (trim.StartsWith("-")) { int dash = line.IndexOf('-'); rtf.Append(RTFBuilder.Colored(RTFBuilder.For(line.Substring(0, dash + 1)), ColorTable.BLACK)); string fullcmd = line.Substring(dash + 1); if (fullcmd.Length <= 1) { rtf.Append(RTFBuilder.Colored(RTFBuilder.For(fullcmd), ColorTable.BLACK)); } else { if (fullcmd[0] != ' ') { rtf.Append(RTFBuilder.Colored(RTFBuilder.WavyUnderline(RTFBuilder.For(fullcmd)), ColorTable.PINK)); } else { rtf.Append(RTFBuilder.For(" ")); string basecmd = fullcmd.Substring(1); if (basecmd.Length > 0) { int space = basecmd.IndexOf(' '); if (space == -1) { rtf.Append(RTFBuilder.Colored(RTFBuilder.For(basecmd), ColorTable.PURPLE)); } else { rtf.Append(RTFBuilder.Colored(RTFBuilder.For(basecmd.Substring(0, space)), ColorTable.PURPLE)); rtf.Append(RTFBuilder.For(" ")); rtf.Append(RTFBuilder.Colored(ColorArgs(basecmd.Substring(space + 1)), ColorTable.BLACK)); } } } } } else if (trim.EndsWith(":")) { RTFBuilder coloredcolon = RTFBuilder.Colored(RTFBuilder.For(":"), ColorTable.GRAY); rtf.Append(RTFBuilder.Colored(RTFBuilder.For(line).Replace(":", coloredcolon), ColorTable.BLUE)); } else if (trim.Contains(": ")) { int ind = line.IndexOf(": "); RTFBuilder coloredcolon = RTFBuilder.Colored(RTFBuilder.For(":"), ColorTable.GRAY); rtf.Append(RTFBuilder.Colored(RTFBuilder.For(line.Substring(0, ind)).Replace(":", coloredcolon), ColorTable.BLUE)); rtf.Append(coloredcolon); rtf.Append(RTFBuilder.Colored(RTFBuilder.Italic(RTFBuilder.For(line.Substring(ind + 1))), ColorTable.BLACK)); } else { rtf.Append(RTFBuilder.Colored(RTFBuilder.WavyUnderline(RTFBuilder.For(line)), ColorTable.PINK)); } } else { rtf.Append(RTFBuilder.For(line)); } if (i < lines.Length - 1) { rtf.AppendLine(); } } RTFBox.Rtf = rtf.FinalOutput((int)(zoom * 24)); // Fix line numbers int lineCount = RTFBox.GetLineFromCharIndex(RTFBox.Text.Length) + 1; RTFBuilder bLines = new RTFBuilder(); for (int i = 0; i < lineCount; i++) { bLines.Append(RTFBuilder.For((i + 1).ToString())); bLines.AppendLine(); } LinesRTFBox.Rtf = bLines.FinalOutput((int)(zoom * 24)); LinesRTFBox.SelectAll(); LinesRTFBox.SelectionAlignment = HorizontalAlignment.Right; LinesRTFBox.ShowSelectionMargin = false; LinesRTFBox.ScrollBars = RichTextBoxScrollBars.None; // Set back to normal Resume(this); RTFBox.Select(start, len); // TODO: Mess with selecting fresh text a bit less often. SetScrollPos(RTFBox, scroll); RTFBox.Invalidate(); LinesRTFBox.Invalidate(); textChanged = false; Scripts[tabControl1.SelectedIndex].Saved = Scripts[tabControl1.SelectedIndex].IgnoreOneSaveNotif; Scripts[tabControl1.SelectedIndex].IgnoreOneSaveNotif = false; FixTabName(tabControl1.SelectedIndex); z = zoom; NoDup = false; }