PageRenderTime 102ms CodeModel.GetById 39ms RepoModel.GetById 0ms app.codeStats 1ms

/ScintillaNET/Scintilla.cs

https://bitbucket.org/nekokun/nekokun
C# | 3754 lines | 2491 code | 616 blank | 647 comment | 543 complexity | a1b3521f073405e8be9ce6667178001a MD5 | raw file
Possible License(s): MIT, CC-BY-SA-3.0

Large files files are truncated, but you can click here to view the full file

  1. #region Using Directives
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Collections.Specialized;
  6. using System.ComponentModel;
  7. using System.Drawing;
  8. using System.Drawing.Design;
  9. using System.IO;
  10. using System.Runtime.InteropServices;
  11. using System.Security.Permissions;
  12. using System.Text;
  13. using System.Windows.Forms;
  14. using ScintillaNET.Configuration;
  15. using ScintillaNET.Design;
  16. using ScintillaNET.Properties;
  17. #endregion Using Directives
  18. namespace ScintillaNET
  19. {
  20. /// <summary>
  21. /// Represents a Scintilla text editor control.
  22. /// </summary>
  23. [Designer(typeof(ScintillaDesigner))]
  24. [Docking(DockingBehavior.Ask)]
  25. [DefaultBindingProperty("Text")]
  26. [DefaultProperty("Text")]
  27. [DefaultEvent("DocumentChanged")]
  28. public partial class Scintilla : Control, INativeScintilla, ISupportInitialize
  29. {
  30. #region Fields
  31. private static IntPtr _moduleHandle;
  32. private static string _moduleName = (IntPtr.Size == 4 ? Resources.ModuleName : Resources.ModuleName64);
  33. private static NativeMethods.Scintilla_DirectFunction _directFunction;
  34. private IntPtr _directPointer;
  35. private static readonly object _annotationChangedEventKey = new object();
  36. private static readonly object _autoCompleteAcceptedEventKey = new object();
  37. private static readonly object _beforeTextDeleteEventKey = new object();
  38. private static readonly object _beforeTextInsertEventKey = new object();
  39. private static readonly object _borderStyleChangedEventKey = new object();
  40. private static readonly object _callTipClickEventKey = new object();
  41. private static readonly object _charAddedEventKey = new object();
  42. private static readonly object _documentChangeEventKey = new object();
  43. private static readonly object _dropMarkerCollectEventKey = new object();
  44. private static readonly object _dwellEndEventKey = new object();
  45. private static readonly object _dwellStartEventKey = new object();
  46. private static readonly object _fileDropEventKey = new object();
  47. private static readonly object _foldChangedEventKey = new object();
  48. private static readonly object _hotspotClickedEventKey = new object();
  49. private static readonly object _hotspotDoubleClickedEventKey = new object();
  50. private static readonly object _hotspotReleaseClickEventKey = new object();
  51. private static readonly object _indicatorClickEventKey = new object();
  52. private static readonly object _linesNeedShownEventKey = new object();
  53. private static readonly object _loadEventKey = new object();
  54. private static readonly object _macroRecordEventKey = new object();
  55. private static readonly object _marginClickEventKey = new object();
  56. private static readonly object _markerChangedEventKey = new object();
  57. private static readonly object _modifiedChangedEventKey = new object();
  58. private static readonly object _readOnlyModifyAttemptEventKey = new object();
  59. private static readonly object _scrollEventKey = new object();
  60. private static readonly object _selectionChangedEventKey = new object();
  61. private static readonly object _styleNeededEventKey = new object();
  62. private static readonly object _textDeletedEventKey = new object();
  63. private static readonly object _textInsertedEventKey = new object();
  64. private static readonly object _uriDroppedEventKey = new object();
  65. private static readonly object _userListEventKey = new object();
  66. private static readonly object _zoomChangedEventKey = new object();
  67. private static readonly int _modifiedState = BitVector32.CreateMask();
  68. private static readonly int _acceptsReturnState = BitVector32.CreateMask(_modifiedState);
  69. private static readonly int _acceptsTabState = BitVector32.CreateMask(_acceptsReturnState);
  70. private BitVector32 _state;
  71. private AnnotationCollection _annotations;
  72. private LineWrapping _lineWrapping;
  73. private List<TopLevelHelper> _helpers = new List<TopLevelHelper>();
  74. private AutoComplete _autoComplete;
  75. private CallTip _callTip;
  76. private CaretInfo _caret;
  77. private Clipboard _clipboard;
  78. private Commands _commands;
  79. private Configuration.ConfigurationManager _configurationManager;
  80. private DocumentHandler _documentHandler;
  81. private DocumentNavigation _documentNavigation;
  82. private DropMarkers _dropMarkers;
  83. private Encoding _encoding;
  84. private EndOfLine _endOfLine;
  85. private FindReplace _findReplace;
  86. private Folding _folding;
  87. private GoTo _goto;
  88. private HotspotStyle _hotspotStyle;
  89. private Indentation _indentation;
  90. private IndicatorCollection _indicators;
  91. private Lexing _lexing;
  92. private LineCollection _lines;
  93. private LongLines _longLines;
  94. private MarginCollection _margins;
  95. private MarkerCollection _markers;
  96. private Printing _printing;
  97. private Scrolling _scrolling;
  98. private Selection _selection;
  99. private SnippetManager _snippets;
  100. private StyleCollection _styles;
  101. private UndoRedo _undoRedo;
  102. private Whitespace _whitespace;
  103. private bool _allowDrop;
  104. private string _caption;
  105. private Dictionary<string, Color> _colorBag = new Dictionary<string, Color>();
  106. /// <summary>
  107. /// Enables the brace matching from current position.
  108. /// </summary>
  109. private bool _isBraceMatching = false;
  110. private bool _isCustomPaintingEnabled = true;
  111. private bool _isInitializing = false;
  112. private List<ManagedRange> _managedRanges = new List<ManagedRange>();
  113. private bool _matchBraces = true;
  114. private INativeScintilla _ns;
  115. private Hashtable _propertyBag = new Hashtable();
  116. private SearchFlags _searchFlags = SearchFlags.Empty;
  117. private bool _supressControlCharacters = true;
  118. // List of Scintilla Supported encodings
  119. internal static readonly IList<Encoding> ValidCodePages = new Encoding[]
  120. {
  121. Encoding.ASCII,
  122. Encoding.UTF8,
  123. Encoding.Unicode, // UTF-16
  124. Encoding.GetEncoding(932), // shift_jis - Japanese (Shift-JIS)
  125. Encoding.GetEncoding(936), // gb2312 - Chinese Simplified (GB2312)
  126. Encoding.GetEncoding(949), // ks_c_5601-1987 - Korean
  127. Encoding.GetEncoding(950), // big5 - Chinese Traditional (Big5)
  128. Encoding.GetEncoding(1361) // Johab - Korean (Johab)
  129. };
  130. // This has to be set *early* because CreateParams is called before our constructor
  131. private BorderStyle _borderStyle = BorderStyle.Fixed3D;
  132. #endregion Fields
  133. #region Methods
  134. /// <summary>
  135. /// Adds a line _end marker to the _end of the document
  136. /// </summary>
  137. public void AddLastLineEnd()
  138. {
  139. EndOfLineMode eolMode = _endOfLine.Mode;
  140. string eolMarker = "\r\n";
  141. if (eolMode == EndOfLineMode.CR)
  142. eolMarker = "\r";
  143. else if (eolMode == EndOfLineMode.LF)
  144. eolMarker = "\n";
  145. int tl = TextLength;
  146. int start = tl - eolMarker.Length;
  147. if (start < 0 || GetRange(start, start + eolMarker.Length).Text != eolMarker)
  148. AppendText(eolMarker);
  149. }
  150. /// <summary>
  151. /// Appends a copy of the specified string to the _end of this instance.
  152. /// </summary>
  153. /// <param name="text">The <see cref="String"/> to append.</param>
  154. /// <returns>A <see cref="Range"/> representing the appended text.</returns>
  155. public Range AppendText(string text)
  156. {
  157. int oldLength = TextLength;
  158. NativeInterface.AppendText(Encoding.GetByteCount(text), text);
  159. return GetRange(oldLength, TextLength);
  160. }
  161. public void BeginInit()
  162. {
  163. _isInitializing = true;
  164. }
  165. public char CharAt(int position)
  166. {
  167. return _ns.GetCharAt(position);
  168. }
  169. /// <summary>
  170. /// Creates and returns a new <see cref="AnnotationCollection" /> object.
  171. /// </summary>
  172. /// <returns>A new <see cref="AnnotationCollection" /> object.</returns>
  173. [EditorBrowsable(EditorBrowsableState.Advanced)]
  174. protected virtual AnnotationCollection CreateAnnotationsInstance()
  175. {
  176. return new AnnotationCollection(this);
  177. }
  178. /// <summary>
  179. /// Creates and returns a new <see cref="LineWrapping" /> object.
  180. /// </summary>
  181. /// <returns>A new <see cref="LineWrapping" /> object.</returns>
  182. [EditorBrowsable(EditorBrowsableState.Advanced)]
  183. protected virtual LineWrapping CreateLineWrappingInstance()
  184. {
  185. return new LineWrapping(this);
  186. }
  187. /// <summary>
  188. /// Sends the specified message directly to the native Scintilla window,
  189. /// bypassing any managed APIs.
  190. /// </summary>
  191. /// <param name="msg">The message ID.</param>
  192. /// <param name="wParam">The message <c>wparam</c> field.</param>
  193. /// <param name="lParam">The message <c>lparam</c> field.</param>
  194. /// <returns>An <see cref="IntPtr"/> representing the result of the message request.</returns>
  195. /// <remarks>
  196. /// Warning: The Surgeon General Has Determined that Calling the Underlying Scintilla
  197. /// Window Directly May Result in Unexpected Behavior!
  198. /// </remarks>
  199. /// <exception cref="InvalidOperationException">
  200. /// The method was called from a thread other than the thread it was created on.
  201. /// </exception>
  202. [EditorBrowsable(EditorBrowsableState.Advanced)]
  203. public IntPtr DirectMessage(int msg, IntPtr wParam, IntPtr lParam)
  204. {
  205. // Enforce illegal cross-thread calls
  206. if (Form.CheckForIllegalCrossThreadCalls && InvokeRequired)
  207. {
  208. string message = string.Format(Resources.Culture, Resources.Exception_IllegalCrossThreadCall, Name);
  209. throw new InvalidOperationException(message);
  210. }
  211. // Call the direct function delegate
  212. return _directFunction(_directPointer, msg, wParam, lParam);
  213. }
  214. /// <summary>
  215. /// Overridden. Releases the unmanaged resources used by the <see cref="Control" /> and
  216. /// its child controls and optionally releases the managed resources.
  217. /// </summary>
  218. /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
  219. protected override void Dispose(bool disposing)
  220. {
  221. foreach (ScintillaHelperBase heler in _helpers)
  222. {
  223. heler.Dispose();
  224. }
  225. if (disposing && IsHandleCreated)
  226. {
  227. // wi11811 2008-07-28 Chris Rickard
  228. // Since we eat the destroy message in WndProc
  229. // we have to manually let Scintilla know to
  230. // clean up its resources.
  231. Message destroyMessage = new Message();
  232. destroyMessage.Msg = NativeMethods.WM_DESTROY;
  233. destroyMessage.HWnd = Handle;
  234. base.DefWndProc(ref destroyMessage);
  235. }
  236. base.Dispose(disposing);
  237. }
  238. public void EndInit()
  239. {
  240. _isInitializing = false;
  241. foreach (ScintillaHelperBase helper in _helpers)
  242. {
  243. helper.Initialize();
  244. }
  245. }
  246. /// <summary>
  247. /// Exports a HTML representation of the current document.
  248. /// </summary>
  249. /// <returns>A <see cref="String"/> containing the contents of the document formatted as HTML.</returns>
  250. /// <remarks>Only ASCII documents are supported. Other encoding types have undefined behavior.</remarks>
  251. public string ExportHtml()
  252. {
  253. StringBuilder sb = new StringBuilder();
  254. using (StringWriter sw = new StringWriter(sb))
  255. ExportHtml(sw, "Untitled", false);
  256. return sb.ToString();
  257. }
  258. /// <summary>
  259. /// Exports a HTML representation of the current document.
  260. /// </summary>
  261. /// <param name="writer">The <see cref="TextWriter"/>with which to write. </param>
  262. /// <param name="title">The title of the HTML document.</param>
  263. /// <param name="allStyles">
  264. /// <c>true</c> to output all styles including those not
  265. /// used in the document; otherwise, <c>false</c>.
  266. /// </param>
  267. /// <remarks>Only ASCII documents are supported. Other encoding types have undefined behavior.</remarks>
  268. public void ExportHtml(TextWriter writer, string title, bool allStyles)
  269. {
  270. // Make sure the document is current
  271. // Lexing.Colorize();
  272. // Get the styles used
  273. int length = NativeInterface.GetLength();
  274. bool[] stylesUsed = new bool[(int)StylesCommon.Max + 1];
  275. if (allStyles)
  276. {
  277. for (int i = 0; i < stylesUsed.Length; i++)
  278. stylesUsed[i] = true;
  279. }
  280. else
  281. {
  282. // Record all the styles used
  283. for (int i = 0; i < length; i++)
  284. stylesUsed[Styles.GetStyleAt(i) & (int)StylesCommon.Max] = true;
  285. }
  286. // The tab width
  287. int tabWidth = Indentation.TabWidth;
  288. // Start writing
  289. writer.WriteLine(@"<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.01 Transitional//EN"" ""http://www.w3.org/TR/html4/loose.dtd"">");
  290. writer.WriteLine("<html>");
  291. writer.WriteLine("<head>");
  292. writer.WriteLine("<title>{0}</title>", title);
  293. writer.WriteLine(@"<style type=""text/css"">");
  294. writer.WriteLine();
  295. // Write the body style
  296. writer.WriteLine("body {");
  297. writer.WriteLine("background-color: {0};", Utilities.ColorToHtml(Styles.Default.BackColor));
  298. if (LineWrapping.Mode == LineWrappingMode.None)
  299. writer.WriteLine("white-space: nowrap;");
  300. writer.WriteLine("}");
  301. writer.WriteLine();
  302. // Write the styles
  303. for (int i = 0; i < stylesUsed.Length; i++)
  304. {
  305. if (!stylesUsed[i])
  306. continue;
  307. Style s = Styles[i];
  308. writer.WriteLine("span.s{0} {{", i);
  309. writer.WriteLine("font-family: \"" + s.FontName + "\";");
  310. writer.WriteLine("font-size: {0}pt;", s.Size);
  311. if (s.Italic)
  312. writer.WriteLine("font-style: italic;");
  313. if (s.Bold)
  314. writer.WriteLine("font-weight: bold;");
  315. if (!s.ForeColor.IsEmpty && s.ForeColor != Color.Transparent)
  316. writer.WriteLine("color: {0};", Utilities.ColorToHtml(s.ForeColor));
  317. if (!s.BackColor.IsEmpty && s.BackColor != Color.Transparent)
  318. writer.WriteLine("background-color: {0};", Utilities.ColorToHtml(s.BackColor));
  319. writer.WriteLine("}");
  320. writer.WriteLine();
  321. }
  322. writer.WriteLine("</style>");
  323. writer.WriteLine("</head>");
  324. writer.WriteLine("<body>");
  325. // Write the document
  326. // TODO There's more to be done here to support codepages/UTF-8
  327. char lc;
  328. char c = '\0';
  329. int lastStyle = -1;
  330. for (int i = 0; i < length; i++)
  331. {
  332. lc = c;
  333. c = NativeInterface.GetCharAt(i);
  334. int style = Styles.GetStyleAt(i);
  335. if(style != lastStyle)
  336. {
  337. if(lastStyle != -1)
  338. writer.Write("</span>");
  339. writer.Write(@"<span class=""s{0}"">", style);
  340. lastStyle = style;
  341. }
  342. switch (c)
  343. {
  344. case '\0':
  345. continue;
  346. case ' ':
  347. if (lc == ' ')
  348. writer.Write("&nbsp;");
  349. else
  350. writer.Write(c);
  351. continue;
  352. case '\t':
  353. for (int t = 0; t < tabWidth; t++)
  354. writer.Write("&nbsp; ");
  355. continue;
  356. case '\r':
  357. case '\n':
  358. if (c == '\r' && i < length - 1 && NativeInterface.GetCharAt(i + 1) == '\n')
  359. i++;
  360. if (lastStyle != -1)
  361. writer.Write("</span>");
  362. writer.WriteLine("<br />");
  363. lastStyle = -1;
  364. continue;
  365. case '<':
  366. writer.Write("&lt;");
  367. continue;
  368. case '>':
  369. writer.Write("&gt;");
  370. continue;
  371. case '&':
  372. writer.Write("&amp;");
  373. continue;
  374. default:
  375. writer.Write(c);
  376. continue;
  377. }
  378. }
  379. if (lastStyle != -1)
  380. writer.Write("</span>");
  381. writer.WriteLine();
  382. writer.WriteLine("</body>");
  383. writer.WriteLine("</html>");
  384. }
  385. public int FindColumn(int line, int column)
  386. {
  387. return _ns.FindColumn(line, column);
  388. }
  389. internal void FireCallTipClick(int arrow)
  390. {
  391. CallTipArrow a = (CallTipArrow)arrow;
  392. OverloadList ol = CallTip.OverloadList;
  393. CallTipClickEventArgs e;
  394. if (ol == null)
  395. {
  396. e = new CallTipClickEventArgs(a, -1, -1, null, CallTip.HighlightStart, CallTip.HighlightEnd);
  397. }
  398. else
  399. {
  400. int newIndex = ol.CurrentIndex;
  401. if (a == CallTipArrow.Down)
  402. {
  403. if (ol.CurrentIndex == ol.Count - 1)
  404. newIndex = 0;
  405. else
  406. newIndex++;
  407. }
  408. else if (a == CallTipArrow.Up)
  409. {
  410. if (ol.CurrentIndex == 0)
  411. newIndex = ol.Count - 1;
  412. else
  413. newIndex--;
  414. }
  415. e = new CallTipClickEventArgs(a, ol.CurrentIndex, newIndex, ol, CallTip.HighlightStart, CallTip.HighlightEnd);
  416. }
  417. OnCallTipClick(e);
  418. if (e.Cancel)
  419. {
  420. CallTip.Cancel();
  421. }
  422. else
  423. {
  424. if (ol != null)
  425. {
  426. // We allow them to alse replace the list entirely or just
  427. // manipulate the New Index
  428. CallTip.OverloadList = e.OverloadList;
  429. CallTip.OverloadList.CurrentIndex = e.NewIndex;
  430. CallTip.ShowOverloadInternal();
  431. }
  432. CallTip.HighlightStart = e.HighlightStart;
  433. CallTip.HighlightEnd = e.HighlightEnd;
  434. }
  435. }
  436. internal void FireKeyDown(KeyEventArgs e)
  437. {
  438. OnKeyDown(e);
  439. }
  440. internal void FireMarginClick(SCNotification n)
  441. {
  442. Margin m = Margins[n.margin];
  443. Keys k = Keys.None;
  444. if ((n.modifiers & (int)KeyMod.Alt) == (int)KeyMod.Alt)
  445. k |= Keys.Alt;
  446. if ((n.modifiers & (int)KeyMod.Ctrl) == (int)KeyMod.Ctrl)
  447. k |= Keys.Control;
  448. if ((n.modifiers & (int)KeyMod.Shift) == (int)KeyMod.Shift)
  449. k |= Keys.Shift;
  450. OnMarginClick(new MarginClickEventArgs(k, n.position, Lines.FromPosition(n.position), m, m.AutoToggleMarkerNumber, m.IsFoldMargin));
  451. }
  452. public int GetColumn(int position)
  453. {
  454. return _ns.GetColumn(position);
  455. }
  456. /// <summary>
  457. /// Gets the text of the line containing the caret.
  458. /// </summary>
  459. /// <returns>A <see cref="String" /> representing the text of the line containing the caret.</returns>
  460. public unsafe string GetCurrentLine()
  461. {
  462. int tmp;
  463. return GetCurrentLine(out tmp);
  464. }
  465. /// <summary>
  466. /// Gets the text of the line containing the caret and the current caret position within that line.
  467. /// </summary>
  468. /// <param name="caretPosition">When this method returns, contains the byte offset of the current caret position with the line.</param>
  469. /// <returns>A <see cref="String" /> representing the text of the line containing the caret.</returns>
  470. public unsafe string GetCurrentLine(out int caretPosition)
  471. {
  472. int length = DirectMessage(NativeMethods.SCI_GETCURLINE, IntPtr.Zero, IntPtr.Zero).ToInt32();
  473. byte[] buffer = new byte[length];
  474. fixed (byte* bp = buffer)
  475. caretPosition = DirectMessage(NativeMethods.SCI_GETCURLINE, new IntPtr(buffer.Length), new IntPtr(bp)).ToInt32();
  476. return Encoding.GetString(buffer, 0, length - 1);
  477. }
  478. public Range GetRange()
  479. {
  480. return new Range(0, _ns.GetTextLength(), this);
  481. }
  482. public Range GetRange(int position)
  483. {
  484. return new Range(position, position + 1, this);
  485. }
  486. public Range GetRange(int startPosition, int endPosition)
  487. {
  488. return new Range(startPosition, endPosition, this);
  489. }
  490. /// <summary>
  491. /// Gets a word from the specified position
  492. /// </summary>
  493. public string GetWordFromPosition(int position)
  494. {
  495. // Chris Rickard 2008-07-28
  496. // Fixing implementation to actually return the word at the position...
  497. // Credit goes to Stumpii for the code.
  498. // As a side note: I think the previous code was implemented based off
  499. // some funky code I made for the snippet keyword detection, but since
  500. // it doesn't reference this method there's no reason to keep the buggy
  501. // behavior. I also removed the try..catch because in theory this
  502. // shouldn't throw and we REALLY shouldn't be eating exceptions at the
  503. // System.Exception level. If some _start popping up I can add some
  504. // conditionals or catch more specific Exceptions.
  505. int startPosition = NativeInterface.WordStartPosition(position, true);
  506. int endPosition = NativeInterface.WordEndPosition(position, true);
  507. return GetRange(startPosition, endPosition).Text;
  508. }
  509. private void HandleFileDrop(IntPtr hDrop)
  510. {
  511. StringBuilder buffer = null;
  512. uint nfiles = NativeMethods.DragQueryFile(hDrop, 0xffffffff, buffer, 0);
  513. List<string> files = new List<string>();
  514. for (uint i = 0; i < nfiles; i++)
  515. {
  516. buffer = new StringBuilder(512);
  517. NativeMethods.DragQueryFile(hDrop, i, buffer, 512);
  518. files.Add(buffer.ToString());
  519. }
  520. NativeMethods.DragFinish(hDrop);
  521. OnFileDrop(new FileDropEventArgs(files.ToArray()));
  522. }
  523. /// <summary>
  524. /// Inserts text at the current cursor position
  525. /// </summary>
  526. /// <param name="text">Text to insert</param>
  527. /// <returns>The range inserted</returns>
  528. public Range InsertText(string text)
  529. {
  530. NativeInterface.AddText(Encoding.GetByteCount(text), text);
  531. return GetRange(_caret.Position, Encoding.GetByteCount(text));
  532. }
  533. /// <summary>
  534. /// Inserts text at the given position
  535. /// </summary>
  536. /// <param name="position">The position to insert text in</param>
  537. /// <param name="text">Text to insert</param>
  538. /// <returns>The text range inserted</returns>
  539. public Range InsertText(int position, string text)
  540. {
  541. NativeInterface.InsertText(position, text);
  542. return GetRange(position, Encoding.GetByteCount(text));
  543. }
  544. /// <summary>
  545. /// Overridden. See <see cref="Control.IsInputKey"/>.
  546. /// </summary>
  547. protected override bool IsInputKey(Keys keyData)
  548. {
  549. if ((keyData & Keys.Shift) != Keys.None)
  550. keyData ^= Keys.Shift;
  551. switch (keyData)
  552. {
  553. case Keys.Tab:
  554. return _state[_acceptsTabState];
  555. case Keys.Enter:
  556. return _state[_acceptsReturnState];
  557. case Keys.Up:
  558. case Keys.Down:
  559. case Keys.Left:
  560. case Keys.Right:
  561. case Keys.F:
  562. return true;
  563. }
  564. return base.IsInputKey(keyData);
  565. }
  566. private static void LoadModule()
  567. {
  568. if (_moduleHandle == IntPtr.Zero)
  569. {
  570. // Load the Scintilla module into memory
  571. if ((_moduleHandle = NativeMethods.LoadLibrary(_moduleName)) == IntPtr.Zero)
  572. {
  573. string message = string.Format(Resources.Culture, Resources.Exception_CannotLoadModule, _moduleName);
  574. throw new Win32Exception(message, new Win32Exception(Marshal.GetLastWin32Error()));
  575. }
  576. // Get the direct function. We use GetProcAddress instead of DllImport
  577. // because we don't know the name of the module ahead of time.
  578. _directFunction = Marshal.GetDelegateForFunctionPointer(
  579. NativeMethods.GetProcAddress(_moduleHandle, "Scintilla_DirectFunction"),
  580. typeof(NativeMethods.Scintilla_DirectFunction)) as NativeMethods.Scintilla_DirectFunction;
  581. if (_directFunction == null)
  582. {
  583. string message = string.Format(Resources.Culture, Resources.Exception_InvalidModule, _moduleName);
  584. throw new Win32Exception(message, new Win32Exception(Marshal.GetLastWin32Error()));
  585. }
  586. }
  587. }
  588. private List<ManagedRange> ManagedRangesInRange(int firstPos, int lastPos)
  589. {
  590. // TODO: look into optimizing this so that it isn't a linear
  591. // search. This is fine for a few markers per document but
  592. // can be greatly improved if there are a large # of markers
  593. List<ManagedRange> ret = new List<ManagedRange>();
  594. foreach (ManagedRange mr in _managedRanges)
  595. if (mr.Start >= firstPos && mr.Start <= lastPos)
  596. ret.Add(mr);
  597. return ret;
  598. }
  599. /// <summary>
  600. /// Raises the <see cref="AnnotationChanged" /> event.
  601. /// </summary>
  602. /// <param name="e">An <see cref="AnnotationChangedEventArgs" /> that contains the event data.</param>
  603. protected virtual void OnAnnotationChanged(AnnotationChangedEventArgs e)
  604. {
  605. EventHandler<AnnotationChangedEventArgs> handler = Events[_annotationChangedEventKey] as EventHandler<AnnotationChangedEventArgs>;
  606. if (handler != null)
  607. handler(this, e);
  608. }
  609. /// <summary>
  610. /// Raises the <see cref="AutoCompleteAccepted"/> event.
  611. /// </summary>
  612. /// <param name="e">An <see cref="AutoCompleteAcceptedEventArgs"/> that contains the event data.</param>
  613. protected virtual void OnAutoCompleteAccepted(AutoCompleteAcceptedEventArgs e)
  614. {
  615. EventHandler<AutoCompleteAcceptedEventArgs> handler = Events[_autoCompleteAcceptedEventKey] as EventHandler<AutoCompleteAcceptedEventArgs>;
  616. if (handler != null)
  617. handler(this, e);
  618. if (e.Cancel)
  619. AutoComplete.Cancel();
  620. }
  621. /// <summary>
  622. /// Raises the <see cref="BackColorChanged"/> event.
  623. /// </summary>
  624. /// <param name="e">An <see cref="EventArgs"/> that contains the event data. </param>
  625. protected override void OnBackColorChanged(EventArgs e)
  626. {
  627. ResetStyles();
  628. base.OnBackColorChanged(e);
  629. }
  630. /// <summary>
  631. /// Raises the <see cref="BeforeTextDelete"/> event.
  632. /// </summary>
  633. /// <param name="e">An <see cref="TextModifiedEventArgs"/> that contains the event data.</param>
  634. protected virtual void OnBeforeTextDelete(TextModifiedEventArgs e)
  635. {
  636. int firstPos = e.Position;
  637. int lastPos = firstPos + e.Length;
  638. List<ManagedRange> deletedRanges = new List<ManagedRange>();
  639. foreach (ManagedRange mr in _managedRanges)
  640. {
  641. // These ranges lie within the deleted range so
  642. // the ranges themselves need to be deleted
  643. if (mr.Start >= firstPos && mr.End <= lastPos)
  644. {
  645. // If the entire range is being delete and NOT a superset of the range,
  646. // don't delete it, only collapse it.
  647. if (!mr.IsPoint && e.Position == mr.Start && (e.Position + e.Length == mr.End))
  648. {
  649. mr.Change(mr.Start, mr.Start);
  650. }
  651. else
  652. {
  653. // Notify the virtual Range that it needs to cleanup
  654. mr.Change(-1, -1);
  655. // Mark for deletion after this foreach:
  656. deletedRanges.Add(mr);
  657. }
  658. }
  659. else if (mr.Start >= lastPos)
  660. {
  661. // These ranges are merely offset by the deleted range
  662. mr.Change(mr.Start - e.Length, mr.End - e.Length);
  663. }
  664. else if (mr.Start >= firstPos && mr.Start <= lastPos)
  665. {
  666. // The left side of the managed range is getting
  667. // cut off
  668. mr.Change(firstPos, mr.End - e.Length);
  669. }
  670. else if (mr.Start < firstPos && mr.End >= firstPos && mr.End >= lastPos)
  671. {
  672. mr.Change(mr.Start, mr.End - e.Length);
  673. }
  674. else if (mr.Start < firstPos && mr.End >= firstPos && mr.End < lastPos)
  675. {
  676. mr.Change(mr.Start, firstPos);
  677. }
  678. }
  679. foreach (ManagedRange mr in deletedRanges)
  680. mr.Dispose();
  681. EventHandler<TextModifiedEventArgs> handler = Events[_beforeTextDeleteEventKey] as EventHandler<TextModifiedEventArgs>;
  682. if (handler != null)
  683. handler(this, e);
  684. }
  685. /// <summary>
  686. /// Raises the <see cref="BeforeTextInsert"/> event.
  687. /// </summary>
  688. /// <param name="e">An <see cref="TextModifiedEventArgs"/> that contains the event data.</param>
  689. protected virtual void OnBeforeTextInsert(TextModifiedEventArgs e)
  690. {
  691. List<ManagedRange> offsetRanges = new List<ManagedRange>();
  692. foreach (ManagedRange mr in _managedRanges)
  693. {
  694. if (mr.Start == e.Position && mr.PendingDeletion)
  695. {
  696. mr.PendingDeletion = false;
  697. ManagedRange lmr = mr;
  698. BeginInvoke(new MethodInvoker(delegate() { lmr.Change(e.Position, e.Position + e.Length); }));
  699. }
  700. // If the Range is a single point we treat it slightly
  701. // differently than a spanned range
  702. if (mr.IsPoint)
  703. {
  704. // Unlike a spanned range, if the insertion point of
  705. // the new text == the _start of the range (and thus
  706. // the _end as well) we offset the entire point.
  707. if (mr.Start >= e.Position)
  708. mr.Change(mr.Start + e.Length, mr.End + e.Length);
  709. else if (mr.End >= e.Position)
  710. mr.Change(mr.Start, mr.End + e.Length);
  711. }
  712. else
  713. {
  714. // We offset a spanned range entirely only if the
  715. // _start occurs after the insertion point of the new
  716. // text.
  717. if (mr.Start > e.Position)
  718. mr.Change(mr.Start + e.Length, mr.End + e.Length);
  719. else if (mr.End >= e.Position)
  720. {
  721. // However it the _start of the range == the insertion
  722. // point of the new text instead of offestting the
  723. // range we expand it.
  724. mr.Change(mr.Start, mr.End + e.Length);
  725. }
  726. }
  727. }
  728. EventHandler<TextModifiedEventArgs> handler = Events[_beforeTextInsertEventKey] as EventHandler<TextModifiedEventArgs>;
  729. if (handler != null)
  730. handler(this, e);
  731. }
  732. /// <summary>
  733. /// Raises the <see cref="BorderStyleChanged" /> event.
  734. /// </summary>
  735. /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
  736. protected virtual void OnBorderStyleChanged(EventArgs e)
  737. {
  738. EventHandler handler = Events[_borderStyleChangedEventKey] as EventHandler;
  739. if (handler != null)
  740. handler(this, e);
  741. }
  742. /// <summary>
  743. /// Raises the <see cref="CallTipClick"/> event.
  744. /// </summary>
  745. /// <param name="e">An <see cref="CallTipClickEventArgs"/> that contains the event data.</param>
  746. protected virtual void OnCallTipClick(CallTipClickEventArgs e)
  747. {
  748. EventHandler<CallTipClickEventArgs> handler = Events[_callTipClickEventKey] as EventHandler<CallTipClickEventArgs>;
  749. if (handler != null)
  750. handler(this, e);
  751. }
  752. /// <summary>
  753. /// Raises the <see cref="CharAdded"/> event.
  754. /// </summary>
  755. /// <param name="e">An <see cref="CharAddedEventArgs"/> that contains the event data.</param>
  756. protected virtual void OnCharAdded(CharAddedEventArgs e)
  757. {
  758. EventHandler<CharAddedEventArgs> handler = Events[_charAddedEventKey] as EventHandler<CharAddedEventArgs>;
  759. if (handler != null)
  760. handler(this, e);
  761. if (_indentation.SmartIndentType != SmartIndent.None)
  762. _indentation.CheckSmartIndent(e.Ch);
  763. }
  764. /// <summary>
  765. /// Overridden. See <see cref="Control.OnCreateControl"/>.
  766. /// </summary>
  767. protected override void OnCreateControl()
  768. {
  769. base.OnCreateControl();
  770. OnLoad(EventArgs.Empty);
  771. }
  772. /// <summary>
  773. /// Raises the <see cref="DocumentChange"/> event.
  774. /// </summary>
  775. /// <param name="e">An <see cref="NativeScintillaEventArgs"/> that contains the event data.</param>
  776. protected virtual void OnDocumentChange(NativeScintillaEventArgs e)
  777. {
  778. EventHandler<NativeScintillaEventArgs> handler = Events[_documentChangeEventKey] as EventHandler<NativeScintillaEventArgs>;
  779. if (handler != null)
  780. handler(this, e);
  781. }
  782. /// <summary>
  783. /// Provides the support for code block selection
  784. /// </summary>
  785. protected override void OnDoubleClick(EventArgs e)
  786. {
  787. base.OnDoubleClick(e);
  788. if (_isBraceMatching)
  789. {
  790. int position = CurrentPos - 1,
  791. bracePosStart = -1,
  792. bracePosEnd = -1;
  793. char character = (char)CharAt(position);
  794. switch (character)
  795. {
  796. case '{':
  797. case '(':
  798. case '[':
  799. if (!this.PositionIsOnComment(position))
  800. {
  801. bracePosStart = position;
  802. bracePosEnd = _ns.BraceMatch(position, 0) + 1;
  803. _selection.Start = bracePosStart;
  804. _selection.End = bracePosEnd;
  805. }
  806. break;
  807. }
  808. }
  809. }
  810. /// <summary>
  811. /// Raises the <see cref="DropMarkerCollect"/> event.
  812. /// </summary>
  813. /// <param name="e">An <see cref="DropMarkerCollectEventArgs"/> that contains the event data.</param>
  814. protected internal virtual void OnDropMarkerCollect(DropMarkerCollectEventArgs e)
  815. {
  816. EventHandler<DropMarkerCollectEventArgs> handler = Events[_dropMarkerCollectEventKey] as EventHandler<DropMarkerCollectEventArgs>;
  817. if (handler != null)
  818. handler(this, e);
  819. }
  820. /// <summary>
  821. /// Raises the <see cref="DwellEnd"/> event.
  822. /// </summary>
  823. /// <param name="e">An <see cref="ScintillaMouseEventArgs"/> that contains the event data.</param>
  824. protected virtual void OnDwellEnd(ScintillaMouseEventArgs e)
  825. {
  826. EventHandler<ScintillaMouseEventArgs> handler = Events[_dwellEndEventKey] as EventHandler<ScintillaMouseEventArgs>;
  827. if (handler != null)
  828. handler(this, e);
  829. }
  830. /// <summary>
  831. /// Raises the <see cref="DwellStart"/> event.
  832. /// </summary>
  833. /// <param name="e">An <see cref="ScintillaMouseEventArgs"/> that contains the event data.</param>
  834. protected virtual void OnDwellStart(ScintillaMouseEventArgs e)
  835. {
  836. EventHandler<ScintillaMouseEventArgs> handler = Events[_dwellStartEventKey] as EventHandler<ScintillaMouseEventArgs>;
  837. if (handler != null)
  838. handler(this, e);
  839. }
  840. /// <summary>
  841. /// Raises the <see cref="FileDrop"/> event.
  842. /// </summary>
  843. /// <param name="e">An <see cref="FileDropEventArgs"/> that contains the event data.</param>
  844. protected virtual void OnFileDrop(FileDropEventArgs e)
  845. {
  846. EventHandler<FileDropEventArgs> handler = Events[_fileDropEventKey] as EventHandler<FileDropEventArgs>;
  847. if (handler != null)
  848. handler(this, e);
  849. }
  850. /// <summary>
  851. /// Raises the <see cref="FoldChanged"/> event.
  852. /// </summary>
  853. /// <param name="e">An <see cref="FoldChangedEventArgs"/> that contains the event data.</param>
  854. protected virtual void OnFoldChanged(FoldChangedEventArgs e)
  855. {
  856. EventHandler<FoldChangedEventArgs> handler = Events[_foldChangedEventKey] as EventHandler<FoldChangedEventArgs>;
  857. if (handler != null)
  858. handler(this, e);
  859. }
  860. /// <summary>
  861. /// Raises the <see cref="FontChanged"/> event.
  862. /// </summary>
  863. /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
  864. protected override void OnFontChanged(EventArgs e)
  865. {
  866. ResetStyles();
  867. base.OnFontChanged(e);
  868. }
  869. /// <summary>
  870. /// Raises the <see cref="ForeColorChanged"/> event.
  871. /// </summary>
  872. /// <param name="e">An <see cref="EventArgs"/> that contains the event data. </param>
  873. protected override void OnForeColorChanged(EventArgs e)
  874. {
  875. ResetStyles();
  876. base.OnForeColorChanged(e);
  877. }
  878. /// <summary>
  879. /// Overridden. See <see cref="Control.OnGotFocus"/>.
  880. /// </summary>
  881. protected override void OnGotFocus(EventArgs e)
  882. {
  883. if (!Selection.Hidden)
  884. _ns.HideSelection(false);
  885. _ns.SetSelBack(Selection.BackColor != Color.Transparent, Utilities.ColorToRgb(Selection.BackColor));
  886. _ns.SetSelFore(Selection.ForeColor != Color.Transparent, Utilities.ColorToRgb(Selection.ForeColor));
  887. base.OnGotFocus(e);
  888. }
  889. /// <summary>
  890. /// Overridden. Raises the <see cref="Control.HandleCreated"/> event.
  891. /// </summary>
  892. /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
  893. protected override void OnHandleCreated(EventArgs e)
  894. {
  895. // TODO Recreating handle?
  896. // Get the Scintilla direct pointer
  897. _directPointer = NativeMethods.SendMessage(Handle, NativeMethods.SCI_GETDIRECTPOINTER, IntPtr.Zero, IntPtr.Zero);
  898. if (_directPointer == IntPtr.Zero)
  899. throw new Win32Exception(Resources.Exception_CannotCreateDirectFunction);
  900. base.OnHandleCreated(e);
  901. }
  902. /// <summary>
  903. /// Raises the <see cref="HotspotClick"/> event.
  904. /// </summary>
  905. /// <param name="e">A <see cref="HotspotClickEventArgs"/> that contains the event data.</param>
  906. protected virtual void OnHotspotClick(HotspotClickEventArgs e)
  907. {
  908. EventHandler<HotspotClickEventArgs> handler = Events[_hotspotClickEventKey] as EventHandler<HotspotClickEventArgs>;
  909. if (handler != null)
  910. handler(this, e);
  911. }
  912. /// <summary>
  913. /// Raises the <see cref="HotspotDoubleClick"/> event.
  914. /// </summary>
  915. /// <param name="e">A <see cref="HotspotClickEventArgs"/> that contains the event data.</param>
  916. protected virtual void OnHotspotDoubleClick(HotspotClickEventArgs e)
  917. {
  918. EventHandler<HotspotClickEventArgs> handler = Events[_hotspotDoubleClickEventKey] as EventHandler<HotspotClickEventArgs>;
  919. if (handler != null)
  920. handler(this, e);
  921. }
  922. /// <summary>
  923. /// Raises the <see cref="HotspotReleaseClick"/> event.
  924. /// </summary>
  925. /// <param name="e">A <see cref="HotspotClickEventArgs"/> that contains the event data.</param>
  926. protected virtual void OnHotspotReleaseClick(HotspotClickEventArgs e)
  927. {
  928. EventHandler<HotspotClickEventArgs> handler = Events[_hotspotReleaseClickEventKey] as EventHandler<HotspotClickEventArgs>;
  929. if (handler != null)
  930. handler(this, e);
  931. }
  932. /// <summary>
  933. /// Raises the <see cref="IndicatorClick"/> event.
  934. /// </summary>
  935. /// <param name="e">An <see cref="ScintillaMouseEventArgs"/> that contains the event data.</param>
  936. protected virtual void OnIndicatorClick(ScintillaMouseEventArgs e)
  937. {
  938. EventHandler<ScintillaMouseEventArgs> handler = Events[_indicatorClickEventKey] as EventHandler<ScintillaMouseEventArgs>;
  939. if (handler != null)
  940. handler(this, e);
  941. }
  942. /// <summary>
  943. /// Overridden. See <see cref="Control.OnKeyDown"/>.
  944. /// </summary>
  945. protected override void OnKeyDown(KeyEventArgs e)
  946. {
  947. base.OnKeyDown(e);
  948. if (!e.Handled)
  949. e.SuppressKeyPress = _commands.ProcessKey(e);
  950. }
  951. /// <summary>
  952. /// Overridden. See <see cref="Control.OnKeyPress"/>.
  953. /// </summary>
  954. protected override void OnKeyPress(KeyPressEventArgs e)
  955. {
  956. if (_supressControlCharacters && (int)e.KeyChar < 32)
  957. e.Handled = true;
  958. if (_snippets.IsEnabled && _snippets.IsOneKeySelectionEmbedEnabled && _selection.Length > 0)
  959. {
  960. Snippet s;
  961. if (_snippets.List.TryGetValue(e.KeyChar.ToString(), out s))
  962. {
  963. if (s.IsSurroundsWith)
  964. {
  965. _snippets.InsertSnippet(s);
  966. e.Handled = true;
  967. }
  968. }
  969. }
  970. base.OnKeyPress(e);
  971. }
  972. /// <summary>
  973. /// Raises the <see cref="LinesNeedShown"/> event.
  974. /// </summary>
  975. /// <param name="e">An <see cref="LinesNeedShownEventArgs"/> that contains the event data.</param>
  976. protected virtual void OnLinesNeedShown(LinesNeedShownEventArgs e)
  977. {
  978. EventHandler<LinesNeedShownEventArgs> handler = Events[_linesNeedShownEventKey] as EventHandler<LinesNeedShownEventArgs>;
  979. if (handler != null)
  980. handler(this, e);
  981. }
  982. /// <summary>
  983. /// Raises the <see cref="Load"/> event.
  984. /// </summary>
  985. /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
  986. protected virtual void OnLoad(EventArgs e)
  987. {
  988. EventHandler handler = Events[_loadEventKey] as EventHandler;
  989. if (handler != null)
  990. handler(this, e);
  991. }
  992. /// <summary>
  993. /// Overridden. See <see cref="Control.OnLostFocus"/>.
  994. /// </summary>
  995. protected override void OnLostFocus(EventArgs e)
  996. {
  997. if (Selection.HideSelection)
  998. _ns.HideSelection(true);
  999. _ns.SetSelBack(Selection.BackColorUnfocused != Color.Transparent, Utilities.ColorToRgb(Selection.BackColorUnfocused));
  1000. _ns.SetSelFore(Selection.ForeColorUnfocused != Color.Transparent, Utilities.ColorToRgb(Selection.ForeColorUnfocused));
  1001. base.OnLostFocus(e);
  1002. }
  1003. /// <summary>
  1004. /// Raises the <see cref="MacroRecord"/> event.
  1005. /// </summary>
  1006. /// <param name="e">An <see cref="MacroRecordEventArgs"/> that contains the event data.</param>
  1007. protected virtual void OnMacroRecord(MacroRecordEventArgs e)
  1008. {
  1009. EventHandler<MacroRecordEventArgs> handler = Events[_macroRecordEventKey] as EventHandler<MacroRecordEventArgs>;
  1010. if (handler != null)
  1011. handler(this, e);
  1012. }
  1013. /// <summary>
  1014. /// Raises the <see cref="MarginClick"/> event.
  1015. /// </summary>
  1016. /// <param name="e">An <see cref="MarginClickEventArgs"/> that contains the event data.</param>
  1017. protected virtual void OnMarginClick(MarginClickEventArgs e)
  1018. {
  1019. EventHandler<MarginClickEventArgs> handler = Events[_marginClickEventKey] as EventHandler<MarginClickEventArgs>;
  1020. if (handler != null)
  1021. handler(this, e);
  1022. if (e.ToggleMarkerNumber >= 0)
  1023. {
  1024. int mask = (int)Math.Pow(2, e.ToggleMarkerNumber);
  1025. if ((e.Line.GetMarkerMask() & mask) == mask)
  1026. e.Line.DeleteMarker(e.ToggleMarkerNumber);
  1027. else
  1028. e.Line.AddMarker(e.ToggleMarkerNumber);
  1029. }
  1030. if (e.ToggleFold)
  1031. e.Line.ToggleFoldExpanded();
  1032. }
  1033. /// <summary>
  1034. /// Raises the <see cref="MarkerChanged"/> event.
  1035. /// </summary>
  1036. /// <param name="e">An <see cref="MarkerChangedEventArgs"/> that contains the event data.</param>
  1037. protected virtual void OnMarkerChanged(MarkerChangedEventArgs e)
  1038. {
  1039. EventHandler<MarkerChangedEventArgs> handler = Events[_markerChangedEventKey] as EventHandler<MarkerChangedEventArgs>;
  1040. if (handler != null)
  1041. handler(this, e);
  1042. }
  1043. /// <summary>
  1044. /// Raises the <see cref="ModifiedChanged"/> event.
  1045. /// </summary>
  1046. /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
  1047. protected virtual void OnModifiedChanged(EventArgs e)
  1048. {
  1049. EventHandler handler = Events[_modifiedChangedEventKey] as EventHandler;
  1050. if (handler != null)
  1051. handler(this, e);
  1052. }
  1053. /// <summary>
  1054. /// Overridden. See <see cref="Control.OnPaint"/>.
  1055. /// </summary>
  1056. protected override void OnPaint(PaintEventArgs e)
  1057. {
  1058. base.OnPaint(e);
  1059. paintRanges(e.Graphics);
  1060. }
  1061. /// <summary>
  1062. /// Raises the <see cref="ReadOnlyModifyAttempt"/> event.
  1063. /// </summary>
  1064. /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
  1065. protected virtual void OnReadOnlyModifyAttempt(EventArgs e)
  1066. {
  1067. EventHandler handler = Events[_readOnlyModifyAttemptEventKey] as EventHandler;
  1068. if (handler != null)
  1069. handler(this, e);
  1070. }
  1071. /// <summary>
  1072. /// Raises the <see cref="Scroll"/> event.
  1073. /// </summary>
  1074. /// <param name="e">An <see cref="ScrollEventArgs"/> that contains the event data.</param>
  1075. protected virtual void OnScroll(ScrollEventArgs e)
  1076. {
  1077. EventHandler<ScrollEventArgs> handler = Events[_scrollEventKey] as EventHandler<ScrollEventArgs>;
  1078. if (handler != null)
  1079. handler(this, e);
  1080. }
  1081. /// <summary>
  1082. /// Raises the <see cref="SelectionChang…

Large files files are truncated, but you can click here to view the full file