PageRenderTime 55ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/Backup/FireballFX/Fireball.SyntaxDocument/Syntax/Document/Row/Row.cs

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