PageRenderTime 46ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/Source/Balder.Silverlight.SampleBrowser/SyntaxTextBox/SyntaxDocument/Document/Row/Row.cs

#
C# | 1134 lines | 713 code | 120 blank | 301 comment | 172 complexity | 9142db5822907e1648375d2f52d8c98e MD5 | raw file
Possible License(s): Apache-2.0
  1. //Original source code coming from Compona.com
  2. /*
  3. * this file was modified for resolve some bugs removed all try catch because it hide some
  4. * bug on the code and because aren't speed safe all modification are copyright of
  5. * <sebastian.faltoni[at]gmail.com> and are under the LGPL licenze
  6. */
  7. using System.Collections;
  8. using System.Windows.Media;
  9. using Fireball.Syntax;
  10. namespace Fireball.Syntax
  11. {
  12. /// <summary>
  13. /// Parser state of a row
  14. /// </summary>
  15. public enum RowState
  16. {
  17. /// <summary>
  18. /// the row is not parsed
  19. /// </summary>
  20. NotParsed = 0,
  21. /// <summary>
  22. /// the row is segment parsed
  23. /// </summary>
  24. SegmentParsed = 1,
  25. /// <summary>
  26. /// the row is both segment and keyword parsed
  27. /// </summary>
  28. AllParsed = 2
  29. }
  30. /// <summary>
  31. /// The row class represents a row in a SyntaxDocument
  32. /// </summary>
  33. public sealed class Row : IEnumerable
  34. {
  35. #region General Declarations
  36. private string mText = "";
  37. internal WordCollection mWords = new WordCollection();
  38. public WordCollection FormattedWords = new WordCollection();
  39. /// <summary>
  40. /// Segments that start on this row
  41. /// </summary>
  42. public SegmentCollection StartSegments = new SegmentCollection();
  43. /// <summary>
  44. /// Segments that ends in this row
  45. /// </summary>
  46. public SegmentCollection EndSegments = new SegmentCollection();
  47. /// <summary>
  48. /// The owner document
  49. /// </summary>
  50. public SyntaxDocument Document = null;
  51. /// <summary>
  52. /// The first collapsable segment on this row.
  53. /// </summary>
  54. public Segment StartSegment = null;
  55. /// <summary>
  56. /// The first segment that terminates on this row.
  57. /// </summary>
  58. public Segment EndSegment = null;
  59. /// <summary>
  60. ///
  61. /// </summary>
  62. public Segment Expansion_StartSegment = null;
  63. /// <summary>
  64. ///
  65. /// </summary>
  66. public Segment Expansion_EndSegment = null;
  67. private RowState _RowState = RowState.NotParsed;
  68. #region PUBLIC PROPERTY BACKCOLOR
  69. private Color _BackColor = Colors.Transparent;
  70. public Color BackColor
  71. {
  72. get { return _BackColor; }
  73. set { _BackColor = value; }
  74. }
  75. #endregion
  76. public int Depth
  77. {
  78. get
  79. {
  80. int i = 0;
  81. Segment s = this.StartSegment;
  82. while (s != null)
  83. {
  84. if (s.Scope != null && s.Scope.CauseIndent)
  85. i++;
  86. s = s.Parent;
  87. }
  88. // if (i>0)
  89. // i--;
  90. if (ShouldOutdent)
  91. i--;
  92. return i;
  93. }
  94. }
  95. public bool ShouldOutdent
  96. {
  97. get
  98. {
  99. if (this.StartSegment.EndRow == this)
  100. {
  101. if (this.StartSegment.Scope.CauseIndent)
  102. return true;
  103. }
  104. return false;
  105. }
  106. }
  107. /// <summary>
  108. /// Collection of Image indices assigned to a row.
  109. /// </summary>
  110. /// <example>
  111. /// <b>Add an image to the current row.</b>
  112. /// <code>
  113. /// MySyntaxBox.Caret.CurrentRow.Images.Add(3);
  114. /// </code>
  115. /// </example>
  116. public ImageIndexCollection Images = new ImageIndexCollection();
  117. /// <summary>
  118. /// Object tag for storage of custom user data..
  119. /// </summary>
  120. /// <example>
  121. /// <b>Assign custom data to a row</b>
  122. /// <code>
  123. /// //custom data class
  124. /// class CustomData{
  125. /// public int abc=123;
  126. /// publci string def="abc";
  127. /// }
  128. ///
  129. /// ...
  130. ///
  131. /// //assign custom data to a row
  132. /// Row MyRow=MySyntaxBox.Caret.CurrentRow;
  133. /// CustomData MyData=new CustomData();
  134. /// MyData.abc=1337;
  135. /// MyRow.Tag=MyData;
  136. ///
  137. /// ...
  138. ///
  139. /// //read custom data from a row
  140. /// Row MyRow=MySyntaxBox.Caret.CurrentRow;
  141. /// if (MyRow.Tag != null){
  142. /// CustomData MyData=(CustomData)MyRow.Tag;
  143. /// if (MyData.abc==1337){
  144. /// //Do something...
  145. /// }
  146. /// }
  147. ///
  148. ///
  149. /// </code>
  150. /// </example>
  151. public object Tag = null;
  152. /// <summary>
  153. /// The parse state of this row
  154. /// </summary>
  155. /// <example>
  156. /// <b>Test if the current row is fully parsed.</b>
  157. /// <code>
  158. /// if (MySyntaxBox.Caret.CurrentRow.RowState==RowState.AllParsed)
  159. /// {
  160. /// //do something
  161. /// }
  162. /// </code>
  163. /// </example>
  164. public RowState RowState
  165. {
  166. get { return _RowState; }
  167. set
  168. {
  169. if (value == _RowState)
  170. return;
  171. if (value == RowState.SegmentParsed && !InKeywordQueue)
  172. {
  173. this.Document.KeywordQueue.Add(this);
  174. this.InKeywordQueue = true;
  175. }
  176. if ((value == RowState.AllParsed || value == RowState.NotParsed) && InKeywordQueue)
  177. {
  178. this.Document.KeywordQueue.Remove(this);
  179. this.InKeywordQueue = false;
  180. }
  181. _RowState = value;
  182. }
  183. }
  184. //----Lookuptables-----------------
  185. // public char[] Buffer_Text =null;
  186. // // public char[] Buffer_Separators =null;
  187. //---------------------------------
  188. /// <summary>
  189. /// Returns true if the row is in the owner documents parse queue
  190. /// </summary>
  191. public bool InQueue = false; //is this line in the parseQueue?
  192. /// <summary>
  193. /// Returns true if the row is in the owner documents keyword parse queue
  194. /// </summary>
  195. public bool InKeywordQueue = false; //is this line in the parseQueue?
  196. private bool mBookmarked = false; //is this line bookmarked?
  197. private bool mBreakpoint = false; //Does this line have a breakpoint?
  198. /// <summary>
  199. /// For public use only
  200. /// </summary>
  201. public int Indent = 0; //value indicating how much this line should be indented (c style)
  202. /// <summary>
  203. /// For public use only
  204. /// </summary>
  205. public int Expansion_PixelStart = 0;
  206. /// <summary>
  207. /// For public use only
  208. /// </summary>
  209. public int Expansion_StartChar = 0;
  210. /// <summary>
  211. /// For public use only
  212. /// </summary>
  213. public int Expansion_PixelEnd = 0;
  214. /// <summary>
  215. /// For public use only
  216. /// </summary>
  217. public int Expansion_EndChar = 0;
  218. #endregion
  219. public void Clear()
  220. {
  221. mWords = new WordCollection();
  222. }
  223. public Row()
  224. {
  225. IsRendered = false;
  226. }
  227. /// <summary>
  228. /// If the row is hidden inside a collapsed segment , call this method to make the collapsed segments expanded.
  229. /// </summary>
  230. public void EnsureVisible()
  231. {
  232. if (this.RowState == RowState.NotParsed)
  233. return;
  234. Segment seg = this.StartSegment;
  235. while (seg != null)
  236. {
  237. seg.Expanded = true;
  238. seg = seg.Parent;
  239. }
  240. this.Document.ResetVisibleRows();
  241. }
  242. /// <summary>
  243. /// Gets or Sets if this row has a bookmark or not.
  244. /// </summary>
  245. public bool Bookmarked
  246. {
  247. get { return mBookmarked; }
  248. set
  249. {
  250. mBookmarked = value;
  251. if (value)
  252. Document.InvokeBookmarkAdded(this);
  253. else
  254. Document.InvokeBookmarkRemoved(this);
  255. Document.InvokeChange();
  256. }
  257. }
  258. /// <summary>
  259. /// Gets or Sets if this row has a breakpoint or not.
  260. /// </summary>
  261. public bool Breakpoint
  262. {
  263. get { return mBreakpoint; }
  264. set
  265. {
  266. mBreakpoint = value;
  267. if (value)
  268. Document.InvokeBreakPointAdded(this);
  269. else
  270. Document.InvokeBreakPointRemoved(this);
  271. Document.InvokeChange();
  272. }
  273. }
  274. public Word Add(string text)
  275. {
  276. Word xw = new Word();
  277. xw.Row = this;
  278. xw.Text = text;
  279. mWords.Add(xw);
  280. return xw;
  281. }
  282. /// <summary>
  283. /// Returns the number of words in the row.
  284. /// (this only applied if the row is fully parsed)
  285. /// </summary>
  286. public int Count
  287. {
  288. get { return mWords.Count; }
  289. }
  290. /// <summary>
  291. /// Gets or Sets the text of the row.
  292. /// </summary>
  293. public string Text
  294. {
  295. get { return mText; }
  296. set
  297. {
  298. bool ParsePreview = false;
  299. if (mText != value)
  300. {
  301. ParsePreview = true;
  302. this.Document.Modified = true;
  303. }
  304. mText = value;
  305. if (Document != null)
  306. {
  307. if (ParsePreview)
  308. {
  309. Document.Parser.ParsePreviewLine(Document.IndexOf(this));
  310. this.Document.OnApplyFormatRanges(this);
  311. }
  312. AddToParseQueue();
  313. }
  314. }
  315. }
  316. /// <summary>
  317. /// Adds this row to the parse queue
  318. /// </summary>
  319. public void AddToParseQueue()
  320. {
  321. if (!InQueue)
  322. Document.ParseQueue.Add(this);
  323. InQueue = true;
  324. this.RowState = RowState.NotParsed;
  325. }
  326. /// <summary>
  327. /// Assigns a new text to the row.
  328. /// </summary>
  329. /// <param name="Text"></param>
  330. public void SetText(string Text)
  331. {
  332. this.Document.StartUndoCapture();
  333. TextPoint tp = new TextPoint(0, this.Index);
  334. TextRange tr = new TextRange();
  335. tr.FirstColumn = 0;
  336. tr.FirstRow = tp.Y;
  337. tr.LastColumn = this.Text.Length;
  338. tr.LastRow = tp.Y;
  339. this.Document.StartUndoCapture();
  340. //delete the current line
  341. this.Document.PushUndoBlock(UndoAction.DeleteRange, this.Document.GetRange(tr), tr.FirstColumn, tr.FirstRow);
  342. //alter the text
  343. this.Document.PushUndoBlock(UndoAction.InsertRange, Text, tp.X, tp.Y);
  344. this.Text = Text;
  345. this.Document.EndUndoCapture();
  346. this.Document.InvokeChange();
  347. }
  348. /*private char[] GetSeparatorBuffer(string text, string separators)
  349. {
  350. char[] buff = text.ToCharArray();
  351. for (int i = 0; i < text.Length; i++)
  352. {
  353. char c = buff[i];
  354. if (separators.IndexOf(c) >= 0)
  355. buff[i] = ' ';
  356. else
  357. buff[i] = '.';
  358. }
  359. return buff;
  360. }*/
  361. /// <summary>
  362. /// Call this method to make all words match the case of their patterns.
  363. /// (this only applies if the row is fully parsed)
  364. /// </summary>
  365. public void MatchCase()
  366. {
  367. string s = "";
  368. foreach (Word w in mWords)
  369. {
  370. s = s + w.Text;
  371. }
  372. mText = s;
  373. }
  374. /// <summary>
  375. /// Get the Word enumerator for this row
  376. /// </summary>
  377. /// <returns></returns>
  378. public IEnumerator GetEnumerator()
  379. {
  380. return mWords.GetEnumerator();
  381. }
  382. /// <summary>
  383. /// Return the Word object at the specified index.
  384. /// </summary>
  385. public Word this[int index]
  386. {
  387. get
  388. {
  389. if (index >= 0)
  390. return (Word)mWords[index];
  391. else
  392. return new Word();
  393. }
  394. }
  395. /// <summary>
  396. /// Force a segment parse on the row.
  397. /// </summary>
  398. public void Parse()
  399. {
  400. Document.ParseRow(this);
  401. }
  402. /// <summary>
  403. /// Forces the parser to parse this row directly
  404. /// </summary>
  405. /// <param name="ParseKeywords">true if keywords and operators should be parsed</param>
  406. public void Parse(bool ParseKeywords)
  407. {
  408. Document.ParseRow(this, ParseKeywords);
  409. }
  410. public void SetExpansionSegment()
  411. {
  412. this.Expansion_StartSegment = null;
  413. this.Expansion_EndSegment = null;
  414. foreach (Segment s in this.StartSegments)
  415. {
  416. if (!this.EndSegments.Contains(s))
  417. {
  418. this.Expansion_StartSegment = s;
  419. break;
  420. }
  421. }
  422. foreach (Segment s in this.EndSegments)
  423. {
  424. if (!this.StartSegments.Contains(s))
  425. {
  426. this.Expansion_EndSegment = s;
  427. break;
  428. }
  429. }
  430. if (this.Expansion_EndSegment != null)
  431. this.Expansion_StartSegment = null;
  432. }
  433. /// <summary>
  434. /// Returns the whitespace string at the begining of this row.
  435. /// </summary>
  436. /// <returns>a string containing the whitespace at the begining of this row</returns>
  437. public string GetLeadingWhitespace()
  438. {
  439. string s = mText;
  440. int i = 0;
  441. s = s.Replace(" ", " ");
  442. for (i = 0; i < s.Length; i++)
  443. {
  444. if (s.Substring(i, 1) == " ")
  445. {
  446. }
  447. else
  448. {
  449. break;
  450. }
  451. }
  452. return mText.Substring(0, i);
  453. }
  454. public int StartWordIndex
  455. {
  456. get
  457. {
  458. if (this.Expansion_StartSegment == null)
  459. return 0;
  460. // if (this.Expansion_StartSegment.StartRow != this)
  461. // return 0;
  462. Word w = this.Expansion_StartSegment.StartWord;
  463. int i = 0;
  464. foreach (Word wo in this)
  465. {
  466. if (wo == w)
  467. break;
  468. i += wo.Text.Length;
  469. }
  470. return i;
  471. }
  472. }
  473. public Word FirstNonWsWord
  474. {
  475. get
  476. {
  477. foreach (Word w in this)
  478. {
  479. if (w.Type == WordType.xtWord)
  480. return w;
  481. }
  482. return null;
  483. }
  484. }
  485. public string GetVirtualLeadingWhitespace()
  486. {
  487. int i = this.StartWordIndex;
  488. string ws = "";
  489. foreach (char c in this.Text)
  490. {
  491. if (c == '\t')
  492. ws += c;
  493. else
  494. ws += ' ';
  495. i--;
  496. if (i <= 0)
  497. break;
  498. }
  499. return ws;
  500. }
  501. /// <summary>
  502. /// Returns the index of this row in the owner SyntaxDocument.
  503. /// </summary>
  504. public int Index
  505. {
  506. get { return this.Document.IndexOf(this); }
  507. }
  508. /// <summary>
  509. /// Returns the visible index of this row in the owner SyntaxDocument
  510. /// </summary>
  511. public int VisibleIndex
  512. {
  513. get
  514. {
  515. int i = this.Document.VisibleRows.IndexOf(this);
  516. if (i == -1)
  517. {
  518. if (this.StartSegment != null)
  519. {
  520. if (this.StartSegment.StartRow != null)
  521. {
  522. if (this.StartSegment.StartRow != this)
  523. return this.StartSegment.StartRow.VisibleIndex;
  524. else
  525. return this.Index;
  526. }
  527. else
  528. return this.Index;
  529. }
  530. else
  531. return this.Index;
  532. }
  533. else
  534. return this.Document.VisibleRows.IndexOf(this);
  535. }
  536. }
  537. /// <summary>
  538. /// Returns the next visible row.
  539. /// </summary>
  540. public Row NextVisibleRow
  541. {
  542. get
  543. {
  544. int i = this.VisibleIndex;
  545. if (i > this.Document.VisibleRows.Count)
  546. return null;
  547. if (i + 1 < this.Document.VisibleRows.Count)
  548. {
  549. return this.Document.VisibleRows[i + 1];
  550. }
  551. else
  552. return null;
  553. }
  554. }
  555. /// <summary>
  556. /// Returns the next row
  557. /// </summary>
  558. public Row NextRow
  559. {
  560. get
  561. {
  562. int i = this.Index;
  563. if (i + 1 <= this.Document.Lines.Length - 1)
  564. return this.Document[i + 1];
  565. else
  566. return null;
  567. }
  568. }
  569. /// <summary>
  570. /// Returns the first visible row before this row.
  571. /// </summary>
  572. public Row PrevVisibleRow
  573. {
  574. get
  575. {
  576. int i = this.VisibleIndex;
  577. if (i < 0)
  578. return null;
  579. if (i - 1 >= 0)
  580. return this.Document.VisibleRows[i - 1];
  581. else
  582. return null;
  583. }
  584. }
  585. /// <summary>
  586. /// Returns true if the row is collapsed
  587. /// </summary>
  588. public bool IsCollapsed
  589. {
  590. get
  591. {
  592. if (this.Expansion_StartSegment != null)
  593. if (this.Expansion_StartSegment.Expanded == false)
  594. return true;
  595. return false;
  596. }
  597. }
  598. /// <summary>
  599. /// Returns true if this row is the last part of a collepsed segment
  600. /// </summary>
  601. public bool IsCollapsedEndPart
  602. {
  603. get
  604. {
  605. if (this.Expansion_EndSegment != null)
  606. if (this.Expansion_EndSegment.Expanded == false)
  607. return true;
  608. return false;
  609. }
  610. }
  611. /// <summary>
  612. /// Returns true if this row can fold
  613. /// </summary>
  614. public bool CanFold
  615. {
  616. get { return (this.Expansion_StartSegment != null && this.Expansion_StartSegment.EndRow != null && this.Document.IndexOf(this.Expansion_StartSegment.EndRow) != 0); }
  617. }
  618. /// <summary>
  619. /// Gets or Sets if this row is expanded.
  620. /// </summary>
  621. public bool Expanded
  622. {
  623. get
  624. {
  625. if (this.CanFold)
  626. {
  627. return (this.Expansion_StartSegment.Expanded);
  628. }
  629. else
  630. {
  631. return false;
  632. }
  633. }
  634. set
  635. {
  636. if (this.CanFold)
  637. {
  638. this.Expansion_StartSegment.Expanded = value;
  639. }
  640. }
  641. }
  642. public string ExpansionText
  643. {
  644. get { return this.Expansion_StartSegment.Scope.ExpansionText; }
  645. set
  646. {
  647. Scope oScope = this.Expansion_StartSegment.Scope;
  648. Scope oNewScope = new Scope();
  649. oNewScope.CaseSensitive = oScope.CaseSensitive;
  650. oNewScope.CauseIndent = oScope.CauseIndent;
  651. oNewScope.DefaultExpanded = oScope.DefaultExpanded;
  652. oNewScope.EndPatterns = oScope.EndPatterns;
  653. oNewScope.NormalizeCase = oScope.NormalizeCase;
  654. oNewScope.Parent = oScope.Parent;
  655. oNewScope.SpawnBlockOnEnd = oScope.SpawnBlockOnEnd;
  656. oNewScope.SpawnBlockOnStart = oScope.SpawnBlockOnStart;
  657. oNewScope.Start = oScope.Start;
  658. oNewScope.Style = oScope.Style;
  659. oNewScope.ExpansionText = value;
  660. this.Expansion_StartSegment.Scope = oNewScope;
  661. this.Document.InvokeChange();
  662. }
  663. }
  664. /// <summary>
  665. /// Returns true if this row is the end part of a collapsable segment
  666. /// </summary>
  667. public bool CanFoldEndPart
  668. {
  669. get { return (this.Expansion_EndSegment != null); }
  670. }
  671. /// <summary>
  672. /// For public use only
  673. /// </summary>
  674. public bool HasExpansionLine
  675. {
  676. get
  677. {
  678. return (this.EndSegment.Parent != null);
  679. }
  680. }
  681. /// <summary>
  682. /// Returns the last row of a collapsable segment
  683. /// (this only applies if this row is the start row of the segment)
  684. /// </summary>
  685. public Row Expansion_EndRow
  686. {
  687. get
  688. {
  689. if (this.CanFold)
  690. return this.Expansion_StartSegment.EndRow;
  691. else
  692. return this;
  693. }
  694. }
  695. /// <summary>
  696. /// Returns the first row of a collapsable segment
  697. /// (this only applies if this row is the last row of the segment)
  698. /// </summary>
  699. public Row Expansion_StartRow
  700. {
  701. get
  702. {
  703. if (this.CanFoldEndPart)
  704. return this.Expansion_EndSegment.StartRow;
  705. else
  706. return this;
  707. }
  708. }
  709. /// <summary>
  710. /// Adds a word object to this row
  711. /// </summary>
  712. /// <param name="word">Word object</param>
  713. public void Add(Word word)
  714. {
  715. this.mWords.Add(word);
  716. }
  717. /// <summary>
  718. /// For public use only
  719. /// </summary>
  720. public Row VirtualCollapsedRow
  721. {
  722. get
  723. {
  724. Row r = new Row();
  725. foreach (Word w in this)
  726. {
  727. if (this.Expansion_StartSegment == w.Segment)
  728. break;
  729. r.Add(w);
  730. }
  731. Word wo = r.Add(this.CollapsedText);
  732. wo.Style = new TextStyle();
  733. wo.Style.BackColor = new Color().FromHex("#FFC0C0C0");
  734. wo.Style.ForeColor = new Color().FromHex("#FF00008B");
  735. wo.Style.Bold = true;
  736. bool found = false;
  737. if (this.Expansion_EndRow != null)
  738. {
  739. foreach (Word w in this.Expansion_EndRow)
  740. {
  741. if (found)
  742. r.Add(w);
  743. if (w == this.Expansion_EndRow.Expansion_EndSegment.EndWord)
  744. found = true;
  745. }
  746. }
  747. return r;
  748. }
  749. }
  750. /// <summary>
  751. /// Returns the text that should be displayed if the row is collapsed.
  752. /// </summary>
  753. public string CollapsedText
  754. {
  755. get
  756. {
  757. string str = "";
  758. int pos = 0;
  759. foreach (Word w in this)
  760. {
  761. pos += w.Text.Length;
  762. if (w.Segment == this.Expansion_StartSegment)
  763. {
  764. str = this.Text.Substring(pos).Trim();
  765. break;
  766. }
  767. }
  768. if (this.Expansion_StartSegment.Scope.ExpansionText != "")
  769. str = this.Expansion_StartSegment.Scope.ExpansionText.Replace("***", str);
  770. return str;
  771. }
  772. }
  773. /// <summary>
  774. /// Returns the index of a specific Word object
  775. /// </summary>
  776. /// <param name="word">Word object to find</param>
  777. /// <returns>index of the word in the row</returns>
  778. public int IndexOf(Word word)
  779. {
  780. return mWords.IndexOf(word);
  781. }
  782. /// <summary>
  783. /// For public use only
  784. /// </summary>
  785. /// <param name="PatternList"></param>
  786. /// <param name="StartWord"></param>
  787. /// <param name="IgnoreStartWord"></param>
  788. /// <returns></returns>
  789. public Word FindRightWordByPatternList(PatternList PatternList, Word StartWord, bool IgnoreStartWord)
  790. {
  791. int i = StartWord.Index;
  792. if (IgnoreStartWord)
  793. i++;
  794. Word w = null;
  795. while (i < mWords.Count)
  796. {
  797. w = this[i];
  798. if (w.Pattern != null)
  799. {
  800. if (w.Pattern.Parent != null)
  801. {
  802. if (w.Pattern.Parent == PatternList && w.Type != WordType.xtSpace && w.Type != WordType.xtTab)
  803. {
  804. return w;
  805. }
  806. }
  807. }
  808. i++;
  809. }
  810. return null;
  811. }
  812. /// <summary>
  813. /// For public use only
  814. /// </summary>
  815. /// <param name="PatternListName"></param>
  816. /// <param name="StartWord"></param>
  817. /// <param name="IgnoreStartWord"></param>
  818. /// <returns></returns>
  819. public Word FindRightWordByPatternListName(string PatternListName, Word StartWord, bool IgnoreStartWord)
  820. {
  821. int i = StartWord.Index;
  822. if (IgnoreStartWord)
  823. i++;
  824. Word w = null;
  825. while (i < mWords.Count)
  826. {
  827. w = this[i];
  828. if (w.Pattern != null)
  829. {
  830. if (w.Pattern.Parent != null)
  831. {
  832. if (w.Pattern.Parent.Name == PatternListName && w.Type != WordType.xtSpace && w.Type != WordType.xtTab)
  833. {
  834. return w;
  835. }
  836. }
  837. }
  838. i++;
  839. }
  840. return null;
  841. }
  842. /// <summary>
  843. /// For public use only
  844. /// </summary>
  845. /// <param name="PatternList"></param>
  846. /// <param name="StartWord"></param>
  847. /// <param name="IgnoreStartWord"></param>
  848. /// <returns></returns>
  849. public Word FindLeftWordByPatternList(PatternList PatternList, Word StartWord, bool IgnoreStartWord)
  850. {
  851. int i = StartWord.Index;
  852. if (IgnoreStartWord)
  853. i--;
  854. Word w = null;
  855. while (i >= 0)
  856. {
  857. w = this[i];
  858. if (w.Pattern != null)
  859. {
  860. if (w.Pattern.Parent != null)
  861. {
  862. if (w.Pattern.Parent == PatternList && w.Type != WordType.xtSpace && w.Type != WordType.xtTab)
  863. {
  864. return w;
  865. }
  866. }
  867. }
  868. i--;
  869. }
  870. return null;
  871. }
  872. /// <summary>
  873. /// For public use only
  874. /// </summary>
  875. /// <param name="PatternListName"></param>
  876. /// <param name="StartWord"></param>
  877. /// <param name="IgnoreStartWord"></param>
  878. /// <returns></returns>
  879. public Word FindLeftWordByPatternListName(string PatternListName, Word StartWord, bool IgnoreStartWord)
  880. {
  881. int i = StartWord.Index;
  882. if (IgnoreStartWord)
  883. i--;
  884. Word w = null;
  885. while (i >= 0)
  886. {
  887. w = this[i];
  888. if (w.Pattern != null)
  889. {
  890. if (w.Pattern.Parent != null)
  891. {
  892. if (w.Pattern.Parent.Name == PatternListName && w.Type != WordType.xtSpace && w.Type != WordType.xtTab)
  893. {
  894. return w;
  895. }
  896. }
  897. }
  898. i--;
  899. }
  900. return null;
  901. }
  902. /// <summary>
  903. /// For public use only
  904. /// </summary>
  905. /// <param name="BlockType"></param>
  906. /// <param name="StartWord"></param>
  907. /// <param name="IgnoreStartWord"></param>
  908. /// <returns></returns>
  909. public Word FindLeftWordByBlockType(BlockType BlockType, Word StartWord, bool IgnoreStartWord)
  910. {
  911. int i = StartWord.Index;
  912. if (IgnoreStartWord)
  913. i--;
  914. Word w = null;
  915. while (i >= 0)
  916. {
  917. w = this[i];
  918. if (w.Segment.BlockType == BlockType && w.Type != WordType.xtSpace && w.Type != WordType.xtTab)
  919. {
  920. return w;
  921. }
  922. i--;
  923. }
  924. return null;
  925. }
  926. /// <summary>
  927. /// For public use only
  928. /// </summary>
  929. /// <param name="BlockType"></param>
  930. /// <param name="StartWord"></param>
  931. /// <param name="IgnoreStartWord"></param>
  932. /// <returns></returns>
  933. public Word FindRightWordByBlockType(BlockType BlockType, Word StartWord, bool IgnoreStartWord)
  934. {
  935. int i = StartWord.Index;
  936. if (IgnoreStartWord)
  937. i++;
  938. Word w = null;
  939. while (i < mWords.Count)
  940. {
  941. w = this[i];
  942. if (w.Segment.BlockType == BlockType && w.Type != WordType.xtSpace && w.Type != WordType.xtTab)
  943. {
  944. return w;
  945. }
  946. i++;
  947. }
  948. return null;
  949. }
  950. /// <summary>
  951. /// For public use only
  952. /// </summary>
  953. /// <param name="BlockTypeName"></param>
  954. /// <param name="StartWord"></param>
  955. /// <param name="IgnoreStartWord"></param>
  956. /// <returns></returns>
  957. public Word FindLeftWordByBlockTypeName(string BlockTypeName, Word StartWord, bool IgnoreStartWord)
  958. {
  959. int i = StartWord.Index;
  960. if (IgnoreStartWord)
  961. i--;
  962. Word w = null;
  963. while (i >= 0)
  964. {
  965. w = this[i];
  966. if (w.Segment.BlockType.Name == BlockTypeName && w.Type != WordType.xtSpace && w.Type != WordType.xtTab)
  967. {
  968. return w;
  969. }
  970. i--;
  971. }
  972. return null;
  973. }
  974. /// <summary>
  975. /// For public use only
  976. /// </summary>
  977. /// <param name="BlockTypeName"></param>
  978. /// <param name="StartWord"></param>
  979. /// <param name="IgnoreStartWord"></param>
  980. /// <returns></returns>
  981. public Word FindRightWordByBlockTypeName(string BlockTypeName, Word StartWord, bool IgnoreStartWord)
  982. {
  983. int i = StartWord.Index;
  984. if (IgnoreStartWord)
  985. i++;
  986. Word w = null;
  987. while (i < mWords.Count)
  988. {
  989. w = this[i];
  990. if (w.Segment.BlockType.Name == BlockTypeName && w.Type != WordType.xtSpace && w.Type != WordType.xtTab)
  991. {
  992. return w;
  993. }
  994. i++;
  995. }
  996. return null;
  997. }
  998. /// <summary>
  999. /// Returns the row before this row.
  1000. /// </summary>
  1001. public Row PrevRow
  1002. {
  1003. get
  1004. {
  1005. int i = this.Index;
  1006. if (i - 1 >= 0)
  1007. return this.Document[i - 1];
  1008. else
  1009. return null;
  1010. }
  1011. }
  1012. public bool IsRendered { get; set; }
  1013. }
  1014. }