RichTextBox.cs 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790
  1. // Permission is hereby granted, free of charge, to any person obtaining
  2. // a copy of this software and associated documentation files (the
  3. // "Software"), to deal in the Software without restriction, including
  4. // without limitation the rights to use, copy, modify, merge, publish,
  5. // distribute, sublicense, and/or sell copies of the Software, and to
  6. // permit persons to whom the Software is furnished to do so, subject to
  7. // the following conditions:
  8. //
  9. // The above copyright notice and this permission notice shall be
  10. // included in all copies or substantial portions of the Software.
  11. //
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  13. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  14. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  15. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  16. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  17. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  18. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  19. //
  20. // Copyright (c) 2005-2006 Novell, Inc. (http://www.novell.com)
  21. //
  22. // Authors:
  23. // Peter Bartok <[email protected]>
  24. //
  25. //
  26. // NOT COMPLETE
  27. // #define DEBUG
  28. using System;
  29. using System.Collections;
  30. using System.ComponentModel;
  31. using System.Drawing;
  32. using System.IO;
  33. using System.Text;
  34. using RTF=System.Windows.Forms.RTF;
  35. namespace System.Windows.Forms {
  36. public class RichTextBox : TextBoxBase {
  37. #region Local Variables
  38. internal bool auto_word_select;
  39. internal int bullet_indent;
  40. internal bool can_redo;
  41. internal bool detect_urls;
  42. internal string redo_action_name;
  43. internal int margin_right;
  44. internal string undo_action_name;
  45. internal float zoom;
  46. private RTF.TextMap rtf_text_map;
  47. private int rtf_skip_width;
  48. private int rtf_skip_count;
  49. private StringBuilder rtf_line;
  50. private SolidBrush rtf_color;
  51. private RTF.Font rtf_rtffont;
  52. private int rtf_rtffont_size;
  53. private FontStyle rtf_rtfstyle;
  54. private HorizontalAlignment rtf_rtfalign;
  55. private int rtf_cursor_x;
  56. private int rtf_cursor_y;
  57. private int rtf_chars;
  58. #endregion // Local Variables
  59. #region Public Constructors
  60. public RichTextBox() {
  61. accepts_return = true;
  62. auto_word_select = false;
  63. bullet_indent = 0;
  64. can_redo = false;
  65. detect_urls = true;
  66. max_length = Int32.MaxValue;
  67. redo_action_name = string.Empty;
  68. margin_right = 0;
  69. undo_action_name = string.Empty;
  70. zoom = 1;
  71. base.Multiline = true;
  72. document.CRLFSize = 1;
  73. scrollbars = RichTextBoxScrollBars.Both;
  74. alignment = HorizontalAlignment.Left;
  75. LostFocus += new EventHandler(RichTextBox_LostFocus);
  76. GotFocus += new EventHandler(RichTextBox_GotFocus);
  77. BackColor = ThemeEngine.Current.ColorWindow;
  78. ForeColor = ThemeEngine.Current.ColorWindowText;
  79. base.HScrolled += new EventHandler(RichTextBox_HScrolled);
  80. base.VScrolled += new EventHandler(RichTextBox_VScrolled);
  81. #if NET_2_0
  82. SetStyle (ControlStyles.StandardDoubleClick, false);
  83. #endif
  84. }
  85. #endregion // Public Constructors
  86. #region Private & Internal Methods
  87. private void RichTextBox_LostFocus(object sender, EventArgs e) {
  88. Invalidate();
  89. }
  90. private void RichTextBox_GotFocus(object sender, EventArgs e) {
  91. Invalidate();
  92. }
  93. #endregion // Private & Internal Methods
  94. #region Public Instance Properties
  95. public override bool AllowDrop {
  96. get {
  97. return base.AllowDrop;
  98. }
  99. set {
  100. base.AllowDrop = value;
  101. }
  102. }
  103. [DefaultValue(false)]
  104. [Localizable(true)]
  105. public override bool AutoSize {
  106. get {
  107. return auto_size;
  108. }
  109. set {
  110. base.AutoSize = value;
  111. }
  112. }
  113. [DefaultValue(false)]
  114. public bool AutoWordSelection {
  115. get {
  116. return auto_word_select;
  117. }
  118. set {
  119. auto_word_select = true;
  120. }
  121. }
  122. [Browsable(false)]
  123. [EditorBrowsable(EditorBrowsableState.Never)]
  124. public override System.Drawing.Image BackgroundImage {
  125. get { return base.BackgroundImage; }
  126. set { base.BackgroundImage = value; }
  127. }
  128. [DefaultValue(0)]
  129. [Localizable(true)]
  130. public int BulletIndent {
  131. get {
  132. return bullet_indent;
  133. }
  134. set {
  135. bullet_indent = value;
  136. }
  137. }
  138. [Browsable(false)]
  139. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  140. public bool CanRedo {
  141. get {
  142. return can_redo;
  143. }
  144. }
  145. [DefaultValue(true)]
  146. public bool DetectUrls {
  147. get {
  148. return detect_urls;
  149. }
  150. set {
  151. detect_urls = true;
  152. }
  153. }
  154. public override Font Font {
  155. get {
  156. return base.Font;
  157. }
  158. set {
  159. if (font != value) {
  160. Line start;
  161. Line end;
  162. if (auto_size) {
  163. if (PreferredHeight != Height) {
  164. Height = PreferredHeight;
  165. }
  166. }
  167. base.Font = value;
  168. // Font changes always set the whole doc to that font
  169. start = document.GetLine(1);
  170. end = document.GetLine(document.Lines);
  171. document.FormatText(start, 1, end, end.text.Length + 1, base.Font, null, null, FormatSpecified.Font);
  172. }
  173. }
  174. }
  175. public override Color ForeColor {
  176. get {
  177. return base.ForeColor;
  178. }
  179. set {
  180. base.ForeColor = value;
  181. }
  182. }
  183. [DefaultValue(Int32.MaxValue)]
  184. public override int MaxLength {
  185. get {
  186. return base.max_length;
  187. }
  188. set {
  189. base.max_length = value;
  190. }
  191. }
  192. [DefaultValue(true)]
  193. public override bool Multiline {
  194. get {
  195. return multiline;
  196. }
  197. set {
  198. base.Multiline = value;
  199. }
  200. }
  201. [Browsable(false)]
  202. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  203. [MonoTODO]
  204. public string RedoActionName {
  205. get {
  206. return redo_action_name;
  207. }
  208. }
  209. [DefaultValue(0)]
  210. [Localizable(true)]
  211. [MonoTODO("Teach TextControl.RecalculateLine to consider the right margin as well")]
  212. public int RightMargin {
  213. get {
  214. return margin_right;
  215. }
  216. set {
  217. margin_right = value;
  218. }
  219. }
  220. [Browsable(false)]
  221. [DefaultValue("")]
  222. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  223. public string Rtf {
  224. get {
  225. Line start_line;
  226. Line end_line;
  227. start_line = document.GetLine(1);
  228. end_line = document.GetLine(document.Lines);
  229. return GenerateRTF(start_line, 0, end_line, end_line.text.Length).ToString();
  230. }
  231. set {
  232. MemoryStream data;
  233. document.Empty();
  234. data = new MemoryStream(Encoding.ASCII.GetBytes(value), false);
  235. InsertRTFFromStream(data, 0, 1);
  236. data.Close();
  237. Invalidate();
  238. }
  239. }
  240. [DefaultValue(RichTextBoxScrollBars.Both)]
  241. [Localizable(true)]
  242. public RichTextBoxScrollBars ScrollBars {
  243. get {
  244. return scrollbars;
  245. }
  246. set {
  247. scrollbars = value;
  248. }
  249. }
  250. [Browsable(false)]
  251. [DefaultValue("")]
  252. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  253. public string SelectedRtf {
  254. get {
  255. return GenerateRTF(document.selection_start.line, document.selection_start.pos, document.selection_end.line, document.selection_end.pos).ToString();
  256. }
  257. set {
  258. MemoryStream data;
  259. int x;
  260. int y;
  261. int sel_start;
  262. int chars;
  263. Line line;
  264. LineTag tag;
  265. if (document.selection_visible) {
  266. document.ReplaceSelection("", false);
  267. }
  268. sel_start = document.LineTagToCharIndex(document.selection_start.line, document.selection_start.pos);
  269. data = new MemoryStream(Encoding.ASCII.GetBytes(value), false);
  270. InsertRTFFromStream(data, document.selection_start.pos, document.selection_start.line.line_no, out x, out y, out chars);
  271. data.Close();
  272. document.CharIndexToLineTag(sel_start + chars + (y - document.selection_start.line.line_no) * 2, out line, out tag, out sel_start);
  273. document.SetSelection(line, sel_start);
  274. document.PositionCaret(line, sel_start);
  275. document.DisplayCaret();
  276. ScrollToCaret();
  277. OnTextChanged(EventArgs.Empty);
  278. }
  279. }
  280. [Browsable(false)]
  281. [DefaultValue("")]
  282. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  283. public override string SelectedText {
  284. get {
  285. return base.SelectedText;
  286. }
  287. set {
  288. base.SelectedText = value;
  289. }
  290. }
  291. [Browsable(false)]
  292. [DefaultValue(HorizontalAlignment.Left)]
  293. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  294. public HorizontalAlignment SelectionAlignment {
  295. get {
  296. HorizontalAlignment align;
  297. Line start;
  298. Line end;
  299. Line line;
  300. start = document.ParagraphStart(document.selection_start.line);
  301. align = start.alignment;
  302. end = document.ParagraphEnd(document.selection_end.line);
  303. line = start;
  304. while (true) {
  305. if (line.alignment != align) {
  306. return HorizontalAlignment.Left;
  307. }
  308. if (line == end) {
  309. break;
  310. }
  311. line = document.GetLine(line.line_no + 1);
  312. }
  313. return align;
  314. }
  315. set {
  316. Line start;
  317. Line end;
  318. Line line;
  319. start = document.ParagraphStart(document.selection_start.line);
  320. end = document.ParagraphEnd(document.selection_end.line);
  321. line = start;
  322. while (true) {
  323. line.alignment = value;
  324. if (line == end) {
  325. break;
  326. }
  327. line = document.GetLine(line.line_no + 1);
  328. }
  329. this.CalculateDocument();
  330. }
  331. }
  332. [Browsable(false)]
  333. [DefaultValue(false)]
  334. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  335. [MonoTODO]
  336. public bool SelectionBullet {
  337. get {
  338. return false;
  339. }
  340. set {
  341. }
  342. }
  343. [Browsable(false)]
  344. [DefaultValue(0)]
  345. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  346. [MonoTODO]
  347. public int SelectionCharOffset {
  348. get {
  349. return 0;
  350. }
  351. set {
  352. }
  353. }
  354. [Browsable(false)]
  355. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  356. public Color SelectionColor {
  357. get {
  358. Color color;
  359. LineTag start;
  360. LineTag end;
  361. LineTag tag;
  362. start = document.selection_start.tag;
  363. end = document.selection_end.tag;
  364. color = ((SolidBrush)document.selection_start.tag.color).Color;
  365. tag = start;
  366. while (true) {
  367. if (!color.Equals(((SolidBrush)tag.color).Color)) {
  368. return Color.Empty;
  369. }
  370. if (tag == end) {
  371. break;
  372. }
  373. tag = document.NextTag(tag);
  374. if (tag == null) {
  375. break;
  376. }
  377. }
  378. return color;
  379. }
  380. set {
  381. FontDefinition attributes;
  382. int sel_start;
  383. int sel_end;
  384. attributes = new FontDefinition();
  385. attributes.color = value;
  386. sel_start = document.LineTagToCharIndex(document.selection_start.line, document.selection_start.pos);
  387. sel_end = document.LineTagToCharIndex(document.selection_end.line, document.selection_end.pos);
  388. document.FormatText(document.selection_start.line, document.selection_start.pos + 1, document.selection_end.line, document.selection_end.pos + 1, attributes);
  389. document.CharIndexToLineTag(sel_start, out document.selection_start.line, out document.selection_start.tag, out document.selection_start.pos);
  390. document.CharIndexToLineTag(sel_end, out document.selection_end.line, out document.selection_end.tag, out document.selection_end.pos);
  391. document.UpdateView(document.selection_start.line, 0);
  392. document.AlignCaret();
  393. }
  394. }
  395. [Browsable(false)]
  396. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  397. public Font SelectionFont {
  398. get {
  399. Font font;
  400. LineTag start;
  401. LineTag end;
  402. LineTag tag;
  403. start = document.selection_start.tag;
  404. end = document.selection_end.tag;
  405. font = document.selection_start.tag.font;
  406. tag = start;
  407. while (true) {
  408. if (!font.Equals(tag.font)) {
  409. return null;
  410. }
  411. if (tag == end) {
  412. break;
  413. }
  414. tag = document.NextTag(tag);
  415. if (tag == null) {
  416. break;
  417. }
  418. }
  419. return font;
  420. }
  421. set {
  422. FontDefinition attributes;
  423. int sel_start;
  424. int sel_end;
  425. attributes = new FontDefinition();
  426. attributes.font_obj = value;
  427. sel_start = document.LineTagToCharIndex(document.selection_start.line, document.selection_start.pos);
  428. sel_end = document.LineTagToCharIndex(document.selection_end.line, document.selection_end.pos);
  429. document.FormatText(document.selection_start.line, document.selection_start.pos + 1, document.selection_end.line, document.selection_end.pos + 1, attributes);
  430. document.CharIndexToLineTag(sel_start, out document.selection_start.line, out document.selection_start.tag, out document.selection_start.pos);
  431. document.CharIndexToLineTag(sel_end, out document.selection_end.line, out document.selection_end.tag, out document.selection_end.pos);
  432. document.UpdateView(document.selection_start.line, 0);
  433. document.AlignCaret();
  434. }
  435. }
  436. [Browsable(false)]
  437. [DefaultValue(0)]
  438. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  439. [MonoTODO]
  440. public int SelectionHangingIndent {
  441. get {
  442. return 0;
  443. }
  444. set {
  445. }
  446. }
  447. [Browsable(false)]
  448. [DefaultValue(0)]
  449. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  450. [MonoTODO]
  451. public int SelectionIndent {
  452. get {
  453. return 0;
  454. }
  455. set {
  456. }
  457. }
  458. [Browsable(false)]
  459. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  460. public override int SelectionLength {
  461. get {
  462. return base.SelectionLength;
  463. }
  464. set {
  465. base.SelectionLength = value;
  466. }
  467. }
  468. [Browsable(false)]
  469. [DefaultValue(false)]
  470. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  471. [MonoTODO]
  472. public bool SelectionProtected {
  473. get {
  474. return false;
  475. }
  476. set {
  477. }
  478. }
  479. [Browsable(false)]
  480. [DefaultValue(0)]
  481. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  482. [MonoTODO]
  483. public int SelectionRightIndent {
  484. get {
  485. return 0;
  486. }
  487. set {
  488. }
  489. }
  490. [Browsable(false)]
  491. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  492. [MonoTODO]
  493. public int[] SelectionTabs {
  494. get {
  495. return new int[0];
  496. }
  497. set {
  498. }
  499. }
  500. [Browsable(false)]
  501. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  502. public RichTextBoxSelectionTypes SelectionType {
  503. get {
  504. if (document.selection_start == document.selection_end) {
  505. return RichTextBoxSelectionTypes.Empty;
  506. }
  507. // Lazy, but works
  508. if (SelectedText.Length > 1) {
  509. return RichTextBoxSelectionTypes.MultiChar | RichTextBoxSelectionTypes.Text;
  510. }
  511. return RichTextBoxSelectionTypes.Text;
  512. }
  513. }
  514. [DefaultValue(false)]
  515. [MonoTODO]
  516. public bool ShowSelectionMargin {
  517. get {
  518. return false;
  519. }
  520. set {
  521. }
  522. }
  523. [Localizable(true)]
  524. public override string Text {
  525. get {
  526. return base.Text;
  527. }
  528. set {
  529. base.Text = value;
  530. }
  531. }
  532. [Browsable(false)]
  533. public override int TextLength {
  534. get {
  535. return base.TextLength;
  536. }
  537. }
  538. [Browsable(false)]
  539. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  540. public string UndoActionName {
  541. get {
  542. return document.undo.UndoName;
  543. }
  544. }
  545. [Localizable(true)]
  546. [DefaultValue(1)]
  547. public float ZoomFactor {
  548. get {
  549. return zoom;
  550. }
  551. set {
  552. zoom = value;
  553. }
  554. }
  555. #endregion // Public Instance Properties
  556. #region Protected Instance Properties
  557. protected override CreateParams CreateParams {
  558. get {
  559. return base.CreateParams;
  560. }
  561. }
  562. protected override Size DefaultSize {
  563. get {
  564. return new Size(100, 96);
  565. }
  566. }
  567. #endregion // Protected Instance Properties
  568. #region Public Instance Methods
  569. public bool CanPaste(DataFormats.Format clipFormat) {
  570. if ((clipFormat.Name == DataFormats.Rtf) ||
  571. (clipFormat.Name == DataFormats.Text) ||
  572. (clipFormat.Name == DataFormats.UnicodeText)) {
  573. return true;
  574. }
  575. return false;
  576. }
  577. public int Find(char[] characterSet) {
  578. return Find(characterSet, -1, -1);
  579. }
  580. public int Find(char[] characterSet, int start) {
  581. return Find(characterSet, start, -1);
  582. }
  583. public int Find(char[] characterSet, int start, int end) {
  584. Document.Marker start_mark;
  585. Document.Marker end_mark;
  586. Document.Marker result;
  587. if (start == -1) {
  588. document.GetMarker(out start_mark, true);
  589. } else {
  590. Line line;
  591. LineTag tag;
  592. int pos;
  593. start_mark = new Document.Marker();
  594. document.CharIndexToLineTag(start, out line, out tag, out pos);
  595. start_mark.line = line;
  596. start_mark.tag = tag;
  597. start_mark.pos = pos;
  598. }
  599. if (end == -1) {
  600. document.GetMarker(out end_mark, false);
  601. } else {
  602. Line line;
  603. LineTag tag;
  604. int pos;
  605. end_mark = new Document.Marker();
  606. document.CharIndexToLineTag(end, out line, out tag, out pos);
  607. end_mark.line = line;
  608. end_mark.tag = tag;
  609. end_mark.pos = pos;
  610. }
  611. if (document.FindChars(characterSet, start_mark, end_mark, out result)) {
  612. return document.LineTagToCharIndex(result.line, result.pos);
  613. }
  614. return -1;
  615. }
  616. public int Find(string str) {
  617. return Find(str, -1, -1, RichTextBoxFinds.None);
  618. }
  619. public int Find(string str, int start, int end, RichTextBoxFinds options) {
  620. Document.Marker start_mark;
  621. Document.Marker end_mark;
  622. Document.Marker result;
  623. if (start == -1) {
  624. document.GetMarker(out start_mark, true);
  625. } else {
  626. Line line;
  627. LineTag tag;
  628. int pos;
  629. start_mark = new Document.Marker();
  630. document.CharIndexToLineTag(start, out line, out tag, out pos);
  631. start_mark.line = line;
  632. start_mark.tag = tag;
  633. start_mark.pos = pos;
  634. }
  635. if (end == -1) {
  636. document.GetMarker(out end_mark, false);
  637. } else {
  638. Line line;
  639. LineTag tag;
  640. int pos;
  641. end_mark = new Document.Marker();
  642. document.CharIndexToLineTag(end, out line, out tag, out pos);
  643. end_mark.line = line;
  644. end_mark.tag = tag;
  645. end_mark.pos = pos;
  646. }
  647. if (document.Find(str, start_mark, end_mark, out result, options)) {
  648. return document.LineTagToCharIndex(result.line, result.pos);
  649. }
  650. return -1;
  651. }
  652. public int Find(string str, int start, RichTextBoxFinds options) {
  653. return Find(str, start, -1, options);
  654. }
  655. public int Find(string str, RichTextBoxFinds options) {
  656. return Find(str, -1, -1, options);
  657. }
  658. public char GetCharFromPosition(Point pt) {
  659. LineTag tag;
  660. int pos;
  661. PointToTagPos(pt, out tag, out pos);
  662. if (pos >= tag.line.text.Length) {
  663. return '\n';
  664. }
  665. return tag.line.text[pos];
  666. }
  667. public int GetCharIndexFromPosition(Point pt) {
  668. LineTag tag;
  669. int pos;
  670. PointToTagPos(pt, out tag, out pos);
  671. return document.LineTagToCharIndex(tag.line, pos);
  672. }
  673. public int GetLineFromCharIndex(int index) {
  674. Line line;
  675. LineTag tag;
  676. int pos;
  677. document.CharIndexToLineTag(index, out line, out tag, out pos);
  678. return line.LineNo - 1;
  679. }
  680. public Point GetPositionFromCharIndex(int index) {
  681. Line line;
  682. LineTag tag;
  683. int pos;
  684. document.CharIndexToLineTag(index, out line, out tag, out pos);
  685. return new Point((int)line.widths[pos] + 1, line.Y + 1);
  686. }
  687. public void LoadFile(System.IO.Stream data, RichTextBoxStreamType fileType) {
  688. document.Empty();
  689. // FIXME - ignoring unicode
  690. if (fileType == RichTextBoxStreamType.PlainText) {
  691. StringBuilder sb;
  692. int count;
  693. byte[] buffer;
  694. try {
  695. sb = new StringBuilder((int)data.Length);
  696. buffer = new byte[1024];
  697. } catch {
  698. throw new IOException("Not enough memory to load document");
  699. }
  700. count = 0;
  701. while (count < data.Length) {
  702. count += data.Read(buffer, count, 1024);
  703. sb.Append(buffer);
  704. }
  705. base.Text = sb.ToString();
  706. return;
  707. }
  708. InsertRTFFromStream(data, 0, 1);
  709. document.PositionCaret (document.GetLine (1), 0);
  710. document.SetSelectionToCaret (true);
  711. ScrollToCaret ();
  712. }
  713. [MonoTODO("Make smarter RTF detection?")]
  714. public void LoadFile(string path) {
  715. if (path.EndsWith(".rtf")) {
  716. LoadFile(path, RichTextBoxStreamType.RichText);
  717. } else {
  718. LoadFile(path, RichTextBoxStreamType.PlainText);
  719. }
  720. }
  721. public void LoadFile(string path, RichTextBoxStreamType fileType) {
  722. FileStream data;
  723. data = null;
  724. try {
  725. data = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 1024);
  726. LoadFile(data, fileType);
  727. }
  728. #if !DEBUG
  729. catch {
  730. throw new IOException("Could not open file " + path);
  731. }
  732. #endif
  733. finally {
  734. if (data != null) {
  735. data.Close();
  736. }
  737. }
  738. }
  739. public void Paste(DataFormats.Format clipFormat) {
  740. base.Paste(Clipboard.GetDataObject(), clipFormat, false);
  741. }
  742. [MonoTODO()]
  743. public void Redo() {
  744. }
  745. public void SaveFile(Stream data, RichTextBoxStreamType fileType) {
  746. Encoding encoding;
  747. int i;
  748. Byte[] bytes;
  749. if (fileType == RichTextBoxStreamType.UnicodePlainText) {
  750. encoding = Encoding.Unicode;
  751. } else {
  752. encoding = Encoding.ASCII;
  753. }
  754. switch(fileType) {
  755. case RichTextBoxStreamType.PlainText:
  756. case RichTextBoxStreamType.TextTextOleObjs:
  757. case RichTextBoxStreamType.UnicodePlainText: {
  758. if (!multiline) {
  759. bytes = encoding.GetBytes(document.Root.text.ToString());
  760. data.Write(bytes, 0, bytes.Length);
  761. return;
  762. }
  763. for (i = 1; i < document.Lines; i++) {
  764. bytes = encoding.GetBytes(document.GetLine(i).text.ToString() + Environment.NewLine);
  765. data.Write(bytes, 0, bytes.Length);
  766. }
  767. bytes = encoding.GetBytes(document.GetLine(document.Lines).text.ToString());
  768. data.Write(bytes, 0, bytes.Length);
  769. return;
  770. }
  771. }
  772. // If we're here we're saving RTF
  773. Line start_line;
  774. Line end_line;
  775. StringBuilder rtf;
  776. int current;
  777. int total;
  778. start_line = document.GetLine(1);
  779. end_line = document.GetLine(document.Lines);
  780. rtf = GenerateRTF(start_line, 0, end_line, end_line.text.Length);
  781. total = rtf.Length;
  782. bytes = new Byte[4096];
  783. // Let's chunk it so we don't use up all memory...
  784. for (i = 0; i < total; i += 1024) {
  785. if ((i + 1024) < total) {
  786. current = encoding.GetBytes(rtf.ToString(i, 1024), 0, 1024, bytes, 0);
  787. } else {
  788. current = total - i;
  789. current = encoding.GetBytes(rtf.ToString(i, current), 0, current, bytes, 0);
  790. }
  791. data.Write(bytes, 0, current);
  792. }
  793. }
  794. public void SaveFile(string path) {
  795. if (path.EndsWith(".rtf")) {
  796. SaveFile(path, RichTextBoxStreamType.RichText);
  797. } else {
  798. SaveFile(path, RichTextBoxStreamType.PlainText);
  799. }
  800. }
  801. public void SaveFile(string path, RichTextBoxStreamType fileType) {
  802. FileStream data;
  803. data = null;
  804. // try {
  805. data = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, 1024, false);
  806. SaveFile(data, fileType);
  807. // }
  808. // catch {
  809. // throw new IOException("Could not write document to file " + path);
  810. // }
  811. // finally {
  812. if (data != null) {
  813. data.Close();
  814. }
  815. // }
  816. }
  817. #endregion // Public Instance Methods
  818. #region Protected Instance Methods
  819. protected virtual object CreateRichEditOleCallback() {
  820. throw new NotImplementedException();
  821. }
  822. protected override void OnBackColorChanged(EventArgs e) {
  823. base.OnBackColorChanged (e);
  824. }
  825. protected virtual void OnContentsResized(ContentsResizedEventArgs e) {
  826. ContentsResizedEventHandler eh = (ContentsResizedEventHandler)(Events [ContentsResizedEvent]);
  827. if (eh != null)
  828. eh (this, e);
  829. }
  830. protected override void OnContextMenuChanged(EventArgs e) {
  831. base.OnContextMenuChanged (e);
  832. }
  833. protected override void OnHandleCreated(EventArgs e) {
  834. base.OnHandleCreated (e);
  835. }
  836. protected override void OnHandleDestroyed(EventArgs e) {
  837. base.OnHandleDestroyed (e);
  838. }
  839. protected virtual void OnHScroll(EventArgs e) {
  840. EventHandler eh = (EventHandler)(Events [HScrollEvent]);
  841. if (eh != null)
  842. eh (this, e);
  843. }
  844. [MonoTODO("Determine when to call this")]
  845. protected virtual void OnImeChange(EventArgs e) {
  846. EventHandler eh = (EventHandler)(Events [ImeChangeEvent]);
  847. if (eh != null)
  848. eh (this, e);
  849. }
  850. protected virtual void OnLinkClicked(LinkClickedEventArgs e) {
  851. LinkClickedEventHandler eh = (LinkClickedEventHandler)(Events [LinkClickedEvent]);
  852. if (eh != null)
  853. eh (this, e);
  854. }
  855. protected virtual void OnProtected(EventArgs e) {
  856. EventHandler eh = (EventHandler)(Events [ProtectedEvent]);
  857. if (eh != null)
  858. eh (this, e);
  859. }
  860. protected override void OnRightToLeftChanged(EventArgs e) {
  861. base.OnRightToLeftChanged (e);
  862. }
  863. protected virtual void OnSelectionChanged(EventArgs e) {
  864. EventHandler eh = (EventHandler)(Events [SelectionChangedEvent]);
  865. if (eh != null)
  866. eh (this, e);
  867. }
  868. protected override void OnSystemColorsChanged(EventArgs e) {
  869. base.OnSystemColorsChanged (e);
  870. }
  871. protected override void OnTextChanged(EventArgs e) {
  872. base.OnTextChanged (e);
  873. }
  874. protected virtual void OnVScroll(EventArgs e) {
  875. EventHandler eh = (EventHandler)(Events [VScrollEvent]);
  876. if (eh != null)
  877. eh (this, e);
  878. }
  879. protected override void WndProc(ref Message m) {
  880. base.WndProc (ref m);
  881. }
  882. #endregion // Protected Instance Methods
  883. #region Events
  884. static object ContentsResizedEvent = new object ();
  885. static object HScrollEvent = new object ();
  886. static object ImeChangeEvent = new object ();
  887. static object LinkClickedEvent = new object ();
  888. static object ProtectedEvent = new object ();
  889. static object SelectionChangedEvent = new object ();
  890. static object VScrollEvent = new object ();
  891. [Browsable(false)]
  892. [EditorBrowsable(EditorBrowsableState.Never)]
  893. public new event EventHandler BackgroundImageChanged {
  894. add { base.BackgroundImageChanged += value; }
  895. remove { base.BackgroundImageChanged -= value; }
  896. }
  897. public event ContentsResizedEventHandler ContentsResized {
  898. add { Events.AddHandler (ContentsResizedEvent, value); }
  899. remove { Events.RemoveHandler (ContentsResizedEvent, value); }
  900. }
  901. [Browsable(false)]
  902. [EditorBrowsable(EditorBrowsableState.Never)]
  903. public new event EventHandler DoubleClick {
  904. add { base.DoubleClick += value; }
  905. remove { base.DoubleClick -= value; }
  906. }
  907. [Browsable(false)]
  908. [EditorBrowsable(EditorBrowsableState.Never)]
  909. public new event DragEventHandler DragDrop {
  910. add { base.DragDrop += value; }
  911. remove { base.DragDrop -= value; }
  912. }
  913. [Browsable(false)]
  914. [EditorBrowsable(EditorBrowsableState.Never)]
  915. public new event DragEventHandler DragEnter {
  916. add { base.DragEnter += value; }
  917. remove { base.DragEnter -= value; }
  918. }
  919. [Browsable(false)]
  920. [EditorBrowsable(EditorBrowsableState.Never)]
  921. public new event EventHandler DragLeave {
  922. add { base.DragLeave += value; }
  923. remove { base.DragLeave -= value; }
  924. }
  925. [Browsable(false)]
  926. [EditorBrowsable(EditorBrowsableState.Never)]
  927. public new event DragEventHandler DragOver {
  928. add { base.DragOver += value; }
  929. remove { base.DragOver -= value; }
  930. }
  931. [Browsable(false)]
  932. [EditorBrowsable(EditorBrowsableState.Never)]
  933. public new event GiveFeedbackEventHandler GiveFeedback {
  934. add { base.GiveFeedback += value; }
  935. remove { base.GiveFeedback -= value; }
  936. }
  937. public event EventHandler HScroll {
  938. add { Events.AddHandler (HScrollEvent, value); }
  939. remove { Events.RemoveHandler (HScrollEvent, value); }
  940. }
  941. public event EventHandler ImeChange {
  942. add { Events.AddHandler (ImeChangeEvent, value); }
  943. remove { Events.RemoveHandler (ImeChangeEvent, value); }
  944. }
  945. public event LinkClickedEventHandler LinkClicked {
  946. add { Events.AddHandler (LinkClickedEvent, value); }
  947. remove { Events.RemoveHandler (LinkClickedEvent, value); }
  948. }
  949. public event EventHandler Protected {
  950. add { Events.AddHandler (ProtectedEvent, value); }
  951. remove { Events.RemoveHandler (ProtectedEvent, value); }
  952. }
  953. [Browsable(false)]
  954. [EditorBrowsable(EditorBrowsableState.Never)]
  955. public new event QueryContinueDragEventHandler QueryContinueDrag {
  956. add { base.QueryContinueDrag += value; }
  957. remove { base.QueryContinueDrag -= value; }
  958. }
  959. public event EventHandler SelectionChanged {
  960. add { Events.AddHandler (SelectionChangedEvent, value); }
  961. remove { Events.RemoveHandler (SelectionChangedEvent, value); }
  962. }
  963. public event EventHandler VScroll {
  964. add { Events.AddHandler (VScrollEvent, value); }
  965. remove { Events.RemoveHandler (VScrollEvent, value); }
  966. }
  967. #endregion // Events
  968. #region Private Methods
  969. internal override void SelectWord ()
  970. {
  971. document.ExpandSelection(CaretSelection.Word, false);
  972. }
  973. private void HandleControl(RTF.RTF rtf) {
  974. // Console.WriteLine ("HANDLING MAJOR: {0} MINOR: {1}", rtf.Major, rtf.Minor);
  975. switch(rtf.Major) {
  976. case RTF.Major.Unicode: {
  977. switch(rtf.Minor) {
  978. case Minor.UnicodeCharBytes: {
  979. rtf_skip_width = rtf.Param;
  980. break;
  981. }
  982. case Minor.UnicodeChar: {
  983. rtf_skip_count += rtf_skip_width;
  984. rtf_line.Append((char)rtf.Param);
  985. break;
  986. }
  987. }
  988. break;
  989. }
  990. case RTF.Major.Destination: {
  991. // Console.Write("[Got Destination control {0}]", rtf.Minor);
  992. rtf.SkipGroup();
  993. break;
  994. }
  995. case RTF.Major.CharAttr: {
  996. switch(rtf.Minor) {
  997. case Minor.ForeColor: {
  998. System.Windows.Forms.RTF.Color color;
  999. color = System.Windows.Forms.RTF.Color.GetColor(rtf, rtf.Param);
  1000. if (color != null) {
  1001. FlushText(rtf, false);
  1002. if (color.Red == -1 && color.Green == -1 && color.Blue == -1) {
  1003. this.rtf_color = new SolidBrush(ForeColor);
  1004. } else {
  1005. this.rtf_color = new SolidBrush(Color.FromArgb(color.Red, color.Green, color.Blue));
  1006. }
  1007. FlushText (rtf, false);
  1008. }
  1009. break;
  1010. }
  1011. case Minor.FontSize: {
  1012. FlushText(rtf, false);
  1013. this.rtf_rtffont_size = rtf.Param / 2;
  1014. break;
  1015. }
  1016. case Minor.FontNum: {
  1017. System.Windows.Forms.RTF.Font font;
  1018. font = System.Windows.Forms.RTF.Font.GetFont(rtf, rtf.Param);
  1019. if (font != null) {
  1020. FlushText(rtf, false);
  1021. this.rtf_rtffont = font;
  1022. }
  1023. break;
  1024. }
  1025. case Minor.Plain: {
  1026. FlushText(rtf, false);
  1027. rtf_rtfstyle = FontStyle.Regular;
  1028. break;
  1029. }
  1030. case Minor.Bold: {
  1031. FlushText(rtf, false);
  1032. if (rtf.Param == RTF.RTF.NoParam) {
  1033. rtf_rtfstyle |= FontStyle.Bold;
  1034. } else {
  1035. rtf_rtfstyle &= ~FontStyle.Bold;
  1036. }
  1037. break;
  1038. }
  1039. case Minor.Italic: {
  1040. FlushText(rtf, false);
  1041. if (rtf.Param == RTF.RTF.NoParam) {
  1042. rtf_rtfstyle |= FontStyle.Italic;
  1043. } else {
  1044. rtf_rtfstyle &= ~FontStyle.Italic;
  1045. }
  1046. break;
  1047. }
  1048. case Minor.StrikeThru: {
  1049. FlushText(rtf, false);
  1050. if (rtf.Param == RTF.RTF.NoParam) {
  1051. rtf_rtfstyle |= FontStyle.Strikeout;
  1052. } else {
  1053. rtf_rtfstyle &= ~FontStyle.Strikeout;
  1054. }
  1055. break;
  1056. }
  1057. case Minor.Underline: {
  1058. FlushText(rtf, false);
  1059. if (rtf.Param == RTF.RTF.NoParam) {
  1060. rtf_rtfstyle |= FontStyle.Underline;
  1061. } else {
  1062. rtf_rtfstyle = rtf_rtfstyle & ~FontStyle.Underline;
  1063. }
  1064. break;
  1065. }
  1066. case Minor.NoUnderline: {
  1067. FlushText(rtf, false);
  1068. rtf_rtfstyle &= ~FontStyle.Underline;
  1069. break;
  1070. }
  1071. }
  1072. break;
  1073. }
  1074. case RTF.Major.SpecialChar: {
  1075. //Console.Write("[Got SpecialChar control {0}]", rtf.Minor);
  1076. SpecialChar(rtf);
  1077. break;
  1078. }
  1079. }
  1080. }
  1081. private void SpecialChar(RTF.RTF rtf) {
  1082. switch(rtf.Minor) {
  1083. case Minor.Page:
  1084. case Minor.Sect:
  1085. case Minor.Row:
  1086. case Minor.Line:
  1087. case Minor.Par: {
  1088. FlushText(rtf, true);
  1089. break;
  1090. }
  1091. case Minor.Cell: {
  1092. Console.Write(" ");
  1093. break;
  1094. }
  1095. case Minor.NoBrkSpace: {
  1096. Console.Write(" ");
  1097. break;
  1098. }
  1099. case Minor.Tab: {
  1100. rtf_line.Append ("\t");
  1101. // FlushText (rtf, false);
  1102. break;
  1103. }
  1104. case Minor.NoReqHyphen:
  1105. case Minor.NoBrkHyphen: {
  1106. rtf_line.Append ("-");
  1107. // FlushText (rtf, false);
  1108. break;
  1109. }
  1110. case Minor.Bullet: {
  1111. Console.WriteLine("*");
  1112. break;
  1113. }
  1114. case Minor.WidowCtrl:
  1115. break;
  1116. case Minor.EmDash: {
  1117. rtf_line.Append ("\u2014");
  1118. break;
  1119. }
  1120. case Minor.EnDash: {
  1121. rtf_line.Append ("\u2013");
  1122. break;
  1123. }
  1124. /*
  1125. case Minor.LQuote: {
  1126. Console.Write("\u2018");
  1127. break;
  1128. }
  1129. case Minor.RQuote: {
  1130. Console.Write("\u2019");
  1131. break;
  1132. }
  1133. case Minor.LDblQuote: {
  1134. Console.Write("\u201C");
  1135. break;
  1136. }
  1137. case Minor.RDblQuote: {
  1138. Console.Write("\u201D");
  1139. break;
  1140. }
  1141. */
  1142. default: {
  1143. // Console.WriteLine ("skipped special char: {0}", rtf.Minor);
  1144. // rtf.SkipGroup();
  1145. break;
  1146. }
  1147. }
  1148. }
  1149. private void HandleText(RTF.RTF rtf) {
  1150. if (rtf_skip_count > 0) {
  1151. rtf_skip_count--;
  1152. return;
  1153. }
  1154. if ((RTF.StandardCharCode)rtf.Minor != RTF.StandardCharCode.nothing) {
  1155. rtf_line.Append(rtf_text_map[(RTF.StandardCharCode)rtf.Minor]);
  1156. } else {
  1157. if ((int)rtf.Major > 31 && (int)rtf.Major < 128) {
  1158. rtf_line.Append((char)rtf.Major);
  1159. } else {
  1160. //rtf_line.Append((char)rtf.Major);
  1161. Console.Write("[Literal:0x{0:X2}]", (int)rtf.Major);
  1162. }
  1163. }
  1164. }
  1165. private void FlushText(RTF.RTF rtf, bool newline) {
  1166. int length;
  1167. Font font;
  1168. length = rtf_line.Length;
  1169. if (!newline && (length == 0)) {
  1170. return;
  1171. }
  1172. if (rtf_rtffont == null) {
  1173. // First font in table is default
  1174. rtf_rtffont = System.Windows.Forms.RTF.Font.GetFont(rtf, 0);
  1175. }
  1176. font = new Font(rtf_rtffont.Name, rtf_rtffont_size, rtf_rtfstyle);
  1177. if (rtf_color == null) {
  1178. System.Windows.Forms.RTF.Color color;
  1179. // First color in table is default
  1180. color = System.Windows.Forms.RTF.Color.GetColor(rtf, 0);
  1181. if ((color == null) || (color.Red == -1 && color.Green == -1 && color.Blue == -1)) {
  1182. rtf_color = new SolidBrush(ForeColor);
  1183. } else {
  1184. rtf_color = new SolidBrush(Color.FromArgb(color.Red, color.Green, color.Blue));
  1185. }
  1186. }
  1187. rtf_chars += rtf_line.Length;
  1188. if (rtf_cursor_x == 0) {
  1189. document.Add(rtf_cursor_y, rtf_line.ToString(), rtf_rtfalign, font, rtf_color);
  1190. } else {
  1191. Line line;
  1192. line = document.GetLine(rtf_cursor_y);
  1193. if (rtf_line.Length > 0) {
  1194. document.InsertString(line, rtf_cursor_x, rtf_line.ToString());
  1195. document.FormatText(line, rtf_cursor_x + 1, line, rtf_cursor_x + 1 + length, font, rtf_color, null, FormatSpecified.Font | FormatSpecified.Color); // FormatText is 1-based
  1196. }
  1197. if (newline) {
  1198. document.Split(line, rtf_cursor_x + length);
  1199. }
  1200. }
  1201. if (newline) {
  1202. rtf_cursor_x = 0;
  1203. rtf_cursor_y++;
  1204. } else {
  1205. rtf_cursor_x += length;
  1206. }
  1207. rtf_line.Length = 0; // Empty line
  1208. }
  1209. private void InsertRTFFromStream(Stream data, int cursor_x, int cursor_y) {
  1210. int x;
  1211. int y;
  1212. int chars;
  1213. InsertRTFFromStream(data, cursor_x, cursor_y, out x, out y, out chars);
  1214. }
  1215. private void InsertRTFFromStream(Stream data, int cursor_x, int cursor_y, out int to_x, out int to_y, out int chars) {
  1216. RTF.RTF rtf;
  1217. rtf = new RTF.RTF(data);
  1218. // Prepare
  1219. rtf.ClassCallback[RTF.TokenClass.Text] = new RTF.ClassDelegate(HandleText);
  1220. rtf.ClassCallback[RTF.TokenClass.Control] = new RTF.ClassDelegate(HandleControl);
  1221. rtf_skip_width = 0;
  1222. rtf_skip_count = 0;
  1223. rtf_line = new StringBuilder();
  1224. rtf_color = null;
  1225. rtf_rtffont_size = (int)this.Font.Size;
  1226. rtf_rtfalign = HorizontalAlignment.Left;
  1227. rtf_rtfstyle = FontStyle.Regular;
  1228. rtf_rtffont = null;
  1229. rtf_cursor_x = cursor_x;
  1230. rtf_cursor_y = cursor_y;
  1231. rtf_chars = 0;
  1232. rtf.DefaultFont(this.Font.Name);
  1233. rtf_text_map = new RTF.TextMap();
  1234. RTF.TextMap.SetupStandardTable(rtf_text_map.Table);
  1235. document.SuspendRecalc ();
  1236. try {
  1237. rtf.Read(); // That's it
  1238. FlushText(rtf, false);
  1239. }
  1240. catch (RTF.RTFException e) {
  1241. #if DEBUG
  1242. throw e;
  1243. #endif
  1244. // Seems to be plain text or broken RTF
  1245. Console.WriteLine("RTF Parsing failure: {0}", e.Message);
  1246. }
  1247. to_x = rtf_cursor_x;
  1248. to_y = rtf_cursor_y;
  1249. chars = rtf_chars;
  1250. document.RecalculateDocument(CreateGraphicsInternal(), cursor_y, document.Lines, false);
  1251. document.ResumeRecalc (true);
  1252. document.Invalidate (document.GetLine(cursor_y), 0, document.GetLine(document.Lines), -1);
  1253. }
  1254. private void RichTextBox_HScrolled(object sender, EventArgs e) {
  1255. OnHScroll(e);
  1256. }
  1257. private void RichTextBox_VScrolled(object sender, EventArgs e) {
  1258. OnVScroll(e);
  1259. }
  1260. private void PointToTagPos(Point pt, out LineTag tag, out int pos) {
  1261. Point p;
  1262. p = pt;
  1263. if (p.X >= document.ViewPortWidth) {
  1264. p.X = document.ViewPortWidth - 1;
  1265. } else if (p.X < 0) {
  1266. p.X = 0;
  1267. }
  1268. if (p.Y >= document.ViewPortHeight) {
  1269. p.Y = document.ViewPortHeight - 1;
  1270. } else if (p.Y < 0) {
  1271. p.Y = 0;
  1272. }
  1273. tag = document.FindCursor(p.X + document.ViewPortX, p.Y + document.ViewPortY, out pos);
  1274. }
  1275. private void EmitRTFFontProperties(StringBuilder rtf, int prev_index, int font_index, Font prev_font, Font font) {
  1276. if (prev_index != font_index) {
  1277. rtf.Append(String.Format("\\f{0}", font_index)); // Font table entry
  1278. }
  1279. if ((prev_font == null) || (prev_font.Size != font.Size)) {
  1280. rtf.Append(String.Format("\\fs{0}", (int)(font.Size * 2))); // Font size
  1281. }
  1282. if ((prev_font == null) || (font.Bold != prev_font.Bold)) {
  1283. if (font.Bold) {
  1284. rtf.Append("\\b");
  1285. } else {
  1286. if (prev_font != null) {
  1287. rtf.Append("\\b0");
  1288. }
  1289. }
  1290. }
  1291. if ((prev_font == null) || (font.Italic != prev_font.Italic)) {
  1292. if (font.Italic) {
  1293. rtf.Append("\\i");
  1294. } else {
  1295. if (prev_font != null) {
  1296. rtf.Append("\\i0");
  1297. }
  1298. }
  1299. }
  1300. if ((prev_font == null) || (font.Strikeout != prev_font.Strikeout)) {
  1301. if (font.Strikeout) {
  1302. rtf.Append("\\strike");
  1303. } else {
  1304. if (prev_font != null) {
  1305. rtf.Append("\\strike0");
  1306. }
  1307. }
  1308. }
  1309. if ((prev_font == null) || (font.Underline != prev_font.Underline)) {
  1310. if (font.Underline) {
  1311. rtf.Append("\\ul");
  1312. } else {
  1313. if (prev_font != null) {
  1314. rtf.Append("\\ul0");
  1315. }
  1316. }
  1317. }
  1318. }
  1319. [MonoTODO("Emit unicode and other special characters properly")]
  1320. private void EmitRTFText(StringBuilder rtf, string text) {
  1321. rtf.Append(text);
  1322. }
  1323. // start_pos and end_pos are 0-based
  1324. private StringBuilder GenerateRTF(Line start_line, int start_pos, Line end_line, int end_pos) {
  1325. StringBuilder sb;
  1326. ArrayList fonts;
  1327. ArrayList colors;
  1328. Color color;
  1329. Font font;
  1330. Line line;
  1331. LineTag tag;
  1332. int pos;
  1333. int line_no;
  1334. int line_len;
  1335. int i;
  1336. int length;
  1337. sb = new StringBuilder();
  1338. fonts = new ArrayList(10);
  1339. colors = new ArrayList(10);
  1340. // Two runs, first we parse to determine tables;
  1341. // and unlike most of our processing here we work on tags
  1342. line = start_line;
  1343. line_no = start_line.line_no;
  1344. pos = start_pos;
  1345. // Add default font and color; to optimize document content we don't
  1346. // use this.Font and this.ForeColor but the font/color from the first tag
  1347. tag = LineTag.FindTag(start_line, pos);
  1348. font = tag.font;
  1349. color = ((SolidBrush)tag.color).Color;
  1350. fonts.Add(font.Name);
  1351. colors.Add(color);
  1352. while (line_no <= end_line.line_no) {
  1353. line = document.GetLine(line_no);
  1354. tag = LineTag.FindTag(line, pos);
  1355. if (line_no != end_line.line_no) {
  1356. line_len = line.text.Length;
  1357. } else {
  1358. line_len = end_pos;
  1359. }
  1360. while (pos < line_len) {
  1361. if (tag.font.Name != font.Name) {
  1362. font = tag.font;
  1363. if (!fonts.Contains(font.Name)) {
  1364. fonts.Add(font.Name);
  1365. }
  1366. }
  1367. if (((SolidBrush)tag.color).Color != color) {
  1368. color = ((SolidBrush)tag.color).Color;
  1369. if (!colors.Contains(color)) {
  1370. colors.Add(color);
  1371. }
  1372. }
  1373. pos = tag.start + tag.length - 1;
  1374. tag = tag.next;
  1375. }
  1376. pos = 0;
  1377. line_no++;
  1378. }
  1379. // We have the tables, emit the header
  1380. sb.Append("{\\rtf1\\ansi");
  1381. sb.Append("\\ansicpg1252"); // FIXME - is this correct?
  1382. // Default Font
  1383. sb.Append(String.Format("\\deff{0}", fonts.IndexOf(this.Font.Name)));
  1384. // Default Language
  1385. sb.Append("\\deflang1033\n"); // FIXME - always 1033?
  1386. // Emit the font table
  1387. sb.Append("{\\fonttbl");
  1388. for (i = 0; i < fonts.Count; i++) {
  1389. sb.Append(String.Format("{{\\f{0}", i)); // {Font
  1390. sb.Append("\\fnil"); // Family
  1391. sb.Append("\\fcharset0 "); // Charset ANSI<space>
  1392. sb.Append((string)fonts[i]); // Font name
  1393. sb.Append(";}"); // }
  1394. }
  1395. sb.Append("}\n");
  1396. // Emit the color table (if needed)
  1397. if ((colors.Count > 1) || ((((Color)colors[0]).R != this.ForeColor.R) || (((Color)colors[0]).G != this.ForeColor.G) || (((Color)colors[0]).B != this.ForeColor.B))) {
  1398. sb.Append("{\\colortbl "); // Header and NO! default color
  1399. for (i = 0; i < colors.Count; i++) {
  1400. sb.Append(String.Format("\\red{0}", ((Color)colors[i]).R));
  1401. sb.Append(String.Format("\\green{0}", ((Color)colors[i]).G));
  1402. sb.Append(String.Format("\\blue{0}", ((Color)colors[i]).B));
  1403. sb.Append(";");
  1404. }
  1405. sb.Append("}\n");
  1406. }
  1407. sb.Append("{\\*\\generator Mono RichTextBox;}");
  1408. // Emit initial paragraph settings
  1409. tag = LineTag.FindTag(start_line, start_pos);
  1410. sb.Append("\\pard"); // Reset to default paragraph properties
  1411. EmitRTFFontProperties(sb, -1, fonts.IndexOf(tag.font.Name), null, tag.font); // Font properties
  1412. sb.Append(" "); // Space separator
  1413. font = tag.font;
  1414. color = (Color)colors[0];
  1415. line = start_line;
  1416. line_no = start_line.line_no;
  1417. pos = start_pos;
  1418. while (line_no <= end_line.line_no) {
  1419. line = document.GetLine(line_no);
  1420. tag = LineTag.FindTag(line, pos);
  1421. if (line_no != end_line.line_no) {
  1422. line_len = line.text.Length;
  1423. } else {
  1424. line_len = end_pos;
  1425. }
  1426. while (pos < line_len) {
  1427. length = sb.Length;
  1428. if (tag.font != font) {
  1429. EmitRTFFontProperties(sb, fonts.IndexOf(font.Name), fonts.IndexOf(tag.font.Name), font, tag.font);
  1430. font = tag.font;
  1431. }
  1432. if (((SolidBrush)tag.color).Color != color) {
  1433. color = ((SolidBrush)tag.color).Color;
  1434. sb.Append(String.Format("\\cf{0}", colors.IndexOf(color)));
  1435. }
  1436. if (length != sb.Length) {
  1437. sb.Append(" "); // Emit space to separate keywords from text
  1438. }
  1439. // Emit the string itself
  1440. if (line_no != end_line.line_no) {
  1441. EmitRTFText(sb, tag.line.text.ToString(pos, tag.start + tag.length - pos - 1));
  1442. } else {
  1443. if (end_pos < (tag.start + tag.length - 1)) {
  1444. // Emit partial tag only, end_pos is inside this tag
  1445. EmitRTFText(sb, tag.line.text.ToString(pos, end_pos - pos));
  1446. } else {
  1447. EmitRTFText(sb, tag.line.text.ToString(pos, tag.start + tag.length - pos - 1));
  1448. }
  1449. }
  1450. pos = tag.start + tag.length - 1;
  1451. tag = tag.next;
  1452. }
  1453. if (pos >= line.text.Length) {
  1454. if (!line.soft_break) {
  1455. sb.Append("\\par\n");
  1456. }
  1457. }
  1458. pos = 0;
  1459. line_no++;
  1460. }
  1461. sb.Append("}\n");
  1462. return sb;
  1463. }
  1464. #endregion // Private Methods
  1465. }
  1466. }