private static int InsertText(TextBuffer buffer, int offset, string data, Stack stack) { TagStart tagStart = (TagStart)stack.Peek(); TextIter insertAt = buffer.GetIterAtOffset(offset); TextTag textTag = DocumentUtils.GetAssociatedTextTag(buffer, tagStart.Tag); DocumentUtils.AddText(buffer, ref insertAt, data, textTag); // buffer.InsertWithTags (ref insertAt, data, textTag); #if DEBUG Console.WriteLine("Text: {0} Value: {1} Start: {2}", textTag.Name, data, offset); #endif return(insertAt.Offset); }
/// <summary> /// Redefine the standard Liquid {% if %} tag to allow "{% elsif %}" or "{% elseif %}". /// </summary> private void RegisterLavaElseIfTag() { var ifTag = LogicalExpression .AndSkip(TagEnd) .And(_anyTagsListParser) .And(ZeroOrMany( TagStart.SkipAnd(Terms.Text("elsif").Or(Terms.Text("elseif"))).SkipAnd(LogicalExpression).AndSkip(TagEnd).And(_anyTagsListParser)) .Then(x => x.Select(e => new ElseIfStatement(e.Item1, e.Item2)).ToList())) .And(ZeroOrOne( CreateTag("else").SkipAnd(_anyTagsListParser)) .Then(x => x != null ? new ElseStatement(x) : null)) .AndSkip(CreateTag("endif").ElseError($"'{{% endif %}}' was expected")) .Then <Statement>(x => new IfStatement(x.Item1, x.Item2, x.Item4, x.Item3)) .ElseError("Invalid 'if' tag"); RegisteredTags["if"] = ifTag; }
private static int InsertEndElement(TextBuffer buffer, int offset, Stack stack, ref int depth) { TextIter insertAt, applyStart, applyEnd; TagStart tagStart = (TagStart)stack.Pop(); string suffix = '#' + depth.ToString(); #if DEBUG Console.WriteLine("Element: {0}, End: {1}", tagStart.Tag.Name, offset); #endif if (((DocumentTag)tagStart.Tag).IsEditable) { if (tagStart.Start + 1 == offset) { offset = DocumentUtils.AddStub(buffer, offset, "To be added test", suffix); } insertAt = buffer.GetIterAtOffset(offset); buffer.Insert(ref insertAt, "]"); offset += 1; } else if (tagStart.Start == offset) { offset = DocumentUtils.AddPaddingEmpty(buffer, offset, suffix); } applyStart = buffer.GetIterAtOffset(tagStart.Start); applyEnd = buffer.GetIterAtOffset(offset); buffer.ApplyTag(tagStart.Tag, applyStart, applyEnd); offset = FormatEnd(buffer, offset, suffix, tagStart.Name); depth--; #if DEBUG Console.WriteLine("Applied: {0}, Start: {1}, End: {2}", tagStart.Tag.Name, tagStart.Start, offset); #endif // Padding between tag regions suffix = "#" + depth; offset = DocumentUtils.AddPadding(buffer, offset, suffix); return(offset); }
public static void Deserialize (Gtk.TextBuffer buffer, Gtk.TextIter start, XmlTextReader xml) { int offset = start.Offset; Stack<TagStart> stack = new Stack<TagStart> (); TagStart tag_start; NoteTagTable note_table = buffer.TagTable as NoteTagTable; int curr_depth = -1; // A stack of boolean values which mark if a // list-item contains content other than another list Stack<bool> list_stack = new Stack<bool> (); while (xml.Read ()) { switch (xml.NodeType) { case XmlNodeType.Element: if (xml.Name == "note-content") break; tag_start = new TagStart (); tag_start.Start = offset; if (note_table != null && note_table.IsDynamicTagRegistered (xml.Name)) { tag_start.Tag = note_table.CreateDynamicTag (xml.Name); } else if (xml.Name == "list") { curr_depth++; break; } else if (xml.Name == "list-item") { if (curr_depth >= 0) { if (xml.GetAttribute ("dir") == "rtl") { tag_start.Tag = note_table.GetDepthTag (curr_depth, Pango.Direction.Rtl); } else { tag_start.Tag = note_table.GetDepthTag (curr_depth, Pango.Direction.Ltr); } list_stack.Push (false); } else { Logger.Error("</list> tag mismatch"); } } else { tag_start.Tag = buffer.TagTable.Lookup (xml.Name); } if (tag_start.Tag is NoteTag) { ((NoteTag) tag_start.Tag).Read (xml, true); } stack.Push (tag_start); break; case XmlNodeType.Text: case XmlNodeType.Whitespace: case XmlNodeType.SignificantWhitespace: Gtk.TextIter insert_at = buffer.GetIterAtOffset (offset); buffer.Insert (ref insert_at, xml.Value); offset += xml.Value.Length; // If we are inside a <list-item> mark off // that we have encountered some content if (list_stack.Count > 0) { list_stack.Pop (); list_stack.Push (true); } break; case XmlNodeType.EndElement: if (xml.Name == "note-content") break; if (xml.Name == "list") { curr_depth--; break; } tag_start = stack.Pop (); if (tag_start.Tag == null) break; Gtk.TextIter apply_start, apply_end; apply_start = buffer.GetIterAtOffset (tag_start.Start); apply_end = buffer.GetIterAtOffset (offset); if (tag_start.Tag is NoteTag) { ((NoteTag) tag_start.Tag).Read (xml, false); } // Insert a bullet if we have reached a closing // <list-item> tag, but only if the <list-item> // had content. DepthNoteTag depth_tag = tag_start.Tag as DepthNoteTag; if (depth_tag != null && list_stack.Pop ()) { ((NoteBuffer) buffer).InsertBullet (ref apply_start, depth_tag.Depth, depth_tag.Direction); buffer.RemoveAllTags (apply_start, apply_start); offset += 2; } else if (depth_tag == null) { buffer.ApplyTag (tag_start.Tag, apply_start, apply_end); } break; default: Logger.Warn ("Unhandled element {0}. Value: '{1}'", xml.NodeType, xml.Value); break; } } }
public static void Deserialize (Gtk.TextBuffer buffer, Gtk.TextIter start, string content) { StringReader reader = new StringReader(content); int intCharacter; char convertedCharacter; int offset = start.Offset; string sbuffer = String.Empty; Stack<TagStart> stack = new Stack<TagStart> (); TagStart tag_start; while (true) { intCharacter = reader.Read (); if (intCharacter == -1) break; convertedCharacter = Convert.ToChar (intCharacter); if (sbuffer != String.Empty || convertedCharacter == '<') { sbuffer += convertedCharacter; if (sbuffer == "<bold>") { tag_start = new TagStart (); tag_start.Start = offset; tag_start.Tag = buffer.TagTable.Lookup ("bold"); stack.Push (tag_start); sbuffer = String.Empty; } else if (sbuffer == "<italic>") { tag_start = new TagStart (); tag_start.Start = offset; tag_start.Tag = buffer.TagTable.Lookup ("italic"); stack.Push (tag_start); sbuffer = String.Empty; } else if (sbuffer == "</bold>" || sbuffer == "</italic>") { if (stack.Count > 0) { tag_start = stack.Pop (); Gtk.TextIter apply_start, apply_end; apply_start = buffer.GetIterAtOffset (tag_start.Start); apply_end = buffer.GetIterAtOffset (offset); buffer.ApplyTag (tag_start.Tag, apply_start, apply_end); sbuffer = String.Empty; } } else if (sbuffer.Length > 9) { Gtk.TextIter insert_at = buffer.GetIterAtOffset(offset); buffer.Insert (ref insert_at, sbuffer); offset += sbuffer.Length; sbuffer = String.Empty; } } else { Gtk.TextIter insert_at = buffer.GetIterAtOffset(offset); buffer.Insert (ref insert_at, convertedCharacter.ToString ()); offset += 1; } } }
private static int InsertStartElement(TextBuffer buffer, int offset, XmlTextReader xmlReader, Stack stack, ref int depth, ref int count) { string elementName = xmlReader.Name; string suffix = String.Empty; DocumentTagTable tagTable = (DocumentTagTable)buffer.TagTable; bool emptyElement = xmlReader.IsEmptyElement; bool isDynamic = DocumentTagTable.IsDynamic(elementName); TextIter insertAt, applyStart, applyEnd; depth++; // We define a suffix so each dynamic tag has an unique name. // Suffix has format: #{depth level} if (isDynamic) { suffix = "#" + depth; } // We add any needed string to give format to the document. offset = FormatStart(buffer, offset, suffix, elementName); TagStart tagStart = new TagStart(); tagStart.Start = offset; tagStart.Name = elementName; // We first lookup the tag name, if the element is dynamic, we can // have three scenarios. // 1) The tag is not in the table: So we create it in the spot. // 2) Tag is in table but it priority is wrong: We created a new // dynamic tag with an extra suffix. Format #{depth level}.{count} // 3) Tag is in table with right priority: We reuse it and we don't // create a new dymamic tag. tagStart.Tag = tagTable.Lookup(elementName + suffix); if (isDynamic && tagStart.Tag == null) { tagStart.Tag = tagTable.CreateDynamicTag(elementName + suffix); } else if (isDynamic && tagStart.Tag != null && tagStart.Tag.Priority < ((TagStart)stack.Peek()).Tag.Priority) { suffix += "." + count; tagStart.Tag = tagTable.CreateDynamicTag(elementName + suffix); count++; } #if DEBUG try { Console.WriteLine("Element: {0} Start: {1}", tagStart.Tag.Name, tagStart.Start); } catch (NullReferenceException) { Console.WriteLine("Error: Missing {0} element", xmlReader.Name); Environment.Exit(1); } #endif // If element has attributes we have to get them and deserialize them. if (xmlReader.HasAttributes) { offset = DeserializeAttributes(buffer, offset, xmlReader, suffix); } // Special case when an elment is empty. // Case A: If element is editable a string stub is inserted to allow edition. // Case B: If element is not editable then a padding is inserted to handle // TextTag behaviour in which zero length ranges are lost. if (emptyElement) { if (((DocumentTag)tagStart.Tag).IsEditable) { insertAt = buffer.GetIterAtOffset(offset); buffer.Insert(ref insertAt, "["); offset += 1; offset = DocumentUtils.AddStub(buffer, offset, "Click to Add Documentation", suffix); insertAt = buffer.GetIterAtOffset(offset); buffer.Insert(ref insertAt, "]"); offset += 1; } else { offset = DocumentUtils.AddPaddingEmpty(buffer, offset, suffix); } applyStart = buffer.GetIterAtOffset(tagStart.Start); applyEnd = buffer.GetIterAtOffset(offset); buffer.ApplyTag(tagStart.Tag, applyStart, applyEnd); offset = FormatEnd(buffer, offset, suffix, elementName); // Padding between tag regions offset = DocumentUtils.AddPadding(buffer, offset, suffix); depth--; #if DEBUG Console.WriteLine("Empty Element: {0}, Start: {1}, End: {2}", tagStart.Tag.Name, tagStart.Start, offset); #endif } else { stack.Push(tagStart); if (((DocumentTag)tagStart.Tag).IsEditable) { insertAt = buffer.GetIterAtOffset(offset); buffer.Insert(ref insertAt, "["); offset += 1; } } return(offset); }
private static int InsertStartElement (TextBuffer buffer, int offset, XmlTextReader xmlReader, Stack stack, ref int depth, ref int count) { string elementName = xmlReader.Name; string suffix = String.Empty; DocumentTagTable tagTable = (DocumentTagTable) buffer.TagTable; bool emptyElement = xmlReader.IsEmptyElement; bool isDynamic = DocumentTagTable.IsDynamic (elementName); TextIter insertAt, applyStart, applyEnd; depth++; // We define a suffix so each dynamic tag has an unique name. // Suffix has format: #{depth level} if (isDynamic) suffix = "#" + depth; // We add any needed string to give format to the document. offset = FormatStart (buffer, offset, suffix, elementName); TagStart tagStart = new TagStart (); tagStart.Start = offset; tagStart.Name = elementName; // We first lookup the tag name, if the element is dynamic, we can // have three scenarios. // 1) The tag is not in the table: So we create it in the spot. // 2) Tag is in table but it priority is wrong: We created a new // dynamic tag with an extra suffix. Format #{depth level}.{count} // 3) Tag is in table with right priority: We reuse it and we don't // create a new dymamic tag. tagStart.Tag = tagTable.Lookup (elementName + suffix); if (isDynamic && tagStart.Tag == null) tagStart.Tag = tagTable.CreateDynamicTag (elementName + suffix); else if (isDynamic && tagStart.Tag != null && tagStart.Tag.Priority < ((TagStart) stack.Peek ()).Tag.Priority) { suffix += "." + count; tagStart.Tag = tagTable.CreateDynamicTag (elementName + suffix); count++; } #if DEBUG try { Console.WriteLine ("Element: {0} Start: {1}", tagStart.Tag.Name, tagStart.Start); } catch (NullReferenceException) { Console.WriteLine ("Error: Missing {0} element", xmlReader.Name); Environment.Exit (1); } #endif // If element has attributes we have to get them and deserialize them. if (xmlReader.HasAttributes) offset = DeserializeAttributes (buffer, offset, xmlReader, suffix); // Special case when an elment is empty. // Case A: If element is editable a string stub is inserted to allow edition. // Case B: If element is not editable then a padding is inserted to handle // TextTag behaviour in which zero length ranges are lost. if (emptyElement) { if (((DocumentTag) tagStart.Tag).IsEditable) { insertAt = buffer.GetIterAtOffset (offset); buffer.Insert (ref insertAt, "["); offset += 1; offset = DocumentUtils.AddStub (buffer, offset, "Click to Add Documentation", suffix); insertAt = buffer.GetIterAtOffset (offset); buffer.Insert (ref insertAt, "]"); offset += 1; } else offset = DocumentUtils.AddPaddingEmpty (buffer, offset, suffix); applyStart = buffer.GetIterAtOffset (tagStart.Start); applyEnd = buffer.GetIterAtOffset (offset); buffer.ApplyTag (tagStart.Tag, applyStart, applyEnd); offset = FormatEnd (buffer, offset, suffix, elementName); // Padding between tag regions offset = DocumentUtils.AddPadding (buffer, offset, suffix); depth--; #if DEBUG Console.WriteLine ("Empty Element: {0}, Start: {1}, End: {2}", tagStart.Tag.Name, tagStart.Start, offset); #endif } else { stack.Push (tagStart); if (((DocumentTag) tagStart.Tag).IsEditable) { insertAt = buffer.GetIterAtOffset (offset); buffer.Insert (ref insertAt, "["); offset += 1; } } return offset; }