SyntaxHighlighter part2

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Text;
using System.Runtime.InteropServices;

namespace UrielGuy.SyntaxHighlightingTextBox
{
 /// <summary>
 /// A textbox the does syntax highlighting.
 /// </summary>
 public class SyntaxHighlightingTextBox : System.Windows.Forms.RichTextBox
 {
  #region Members

  //Members exposed via properties
  private SeperaratorCollection mSeperators = new SeperaratorCollection(); 
  private HighLightDescriptorCollection mHighlightDescriptors = new HighLightDescriptorCollection();
  private bool mCaseSesitive = false;
  private bool mFilterAutoComplete = false;

  //Internal use members
  private bool mAutoCompleteShown = false;
  private bool mParsing = false;
  private bool mIgnoreLostFocus = false;

  private AutoCompleteForm mAutoCompleteForm = new AutoCompleteForm();

  //Undo/Redo members
  private ArrayList mUndoList = new ArrayList();
  private Stack mRedoStack = new Stack();
  private bool mIsUndo = false;
  private UndoRedoInfo mLastInfo = new UndoRedoInfo("", new Win32.POINT(), 0);
  private int mMaxUndoRedoSteps = 50;

  #endregion

  #region Properties
  /// <summary>
  /// Determines if token recognition is case sensitive.
  /// </summary>
  [Category("Behavior")]
  public bool CaseSensitive
  {
   get
   {
    return mCaseSesitive;
   }
   set
   {
    mCaseSesitive = value;
   }
  }


  /// <summary>
  /// Sets whether or not to remove items from the Autocomplete window as the user types...
  /// </summary>
  [Category("Behavior")]
  public bool FilterAutoComplete
  {
   get
   {
    return mFilterAutoComplete;
   }
   set
   {
    mFilterAutoComplete = value;
   }
  }

  /// <summary>
  /// Set the maximum amount of Undo/Redo steps.
  /// </summary>
  [Category("Behavior")]
  public int MaxUndoRedoSteps
  {
   get
   {
    return mMaxUndoRedoSteps;
   }
   set
   {
    mMaxUndoRedoSteps = value;
   }
  }

   /// <summary>
   /// A collection of charecters. a token is every string between two seperators.
   /// </summary>
   ///
   public SeperaratorCollection Seperators
  {
   get
   {
    return mSeperators;
   }
  }
  
  /// <summary>
  /// The collection of highlight descriptors.
  /// </summary>
  ///
  public HighLightDescriptorCollection HighlightDescriptors
  {
   get
   {
    return mHighlightDescriptors;
   }
  }

  #endregion

  #region Overriden methods

  /// <summary>
  /// The on text changed overrided. Here we parse the text into RTF for the highlighting.
  /// </summary>
  /// <param name="e"></param>
  protected override void OnTextChanged(EventArgs e)
  {
   if (mParsing) return;
   mParsing = true;
   Win32.LockWindowUpdate(Handle);
   base.OnTextChanged(e);

   if (!mIsUndo)
   {
    mRedoStack.Clear();
    mUndoList.Insert(0,mLastInfo);
    this.LimitUndo();
    mLastInfo = new UndoRedoInfo(Text, GetScrollPos(), SelectionStart);
   }
   
   //Save scroll bar an cursor position, changeing the RTF moves the cursor and scrollbars to top positin
   Win32.POINT scrollPos = GetScrollPos();
   int cursorLoc = SelectionStart;

   //Created with an estimate of how big the stringbuilder has to be...
   StringBuilder sb = new
    StringBuilder((int)(Text.Length * 1.5 + 150));
 
   //Adding RTF header
   sb.Append(@"{/rtf1/fbidis/ansi/ansicpg1255/deff0/deflang1037{/fonttbl{");
   
   //Font table creation
   int fontCounter = 0;
   Hashtable fonts = new Hashtable();
   AddFontToTable(sb, Font, ref fontCounter, fonts);
   foreach (HighlightDescriptor hd in mHighlightDescriptors)
   {
    if ((hd.Font !=  null) && !fonts.ContainsKey(hd.Font.Name))
    {
     AddFontToTable(sb, hd.Font,ref fontCounter, fonts);
    }
   }
   sb.Append("}/n");

   //ColorTable
   
   sb.Append(@"{/colortbl ;");
   Hashtable colors = new Hashtable();
   int colorCounter = 1;
   AddColorToTable(sb, ForeColor, ref colorCounter, colors);
   AddColorToTable(sb, BackColor, ref colorCounter, colors);
   
   foreach (HighlightDescriptor hd in mHighlightDescriptors)
   {
    if (!colors.ContainsKey(hd.Color))
    {
     AddColorToTable(sb, hd.Color, ref colorCounter, colors);
    }
   }  

   //Parsing text
 
   sb.Append("}/n").Append(@"/viewkind4/uc1/pard/ltrpar");
   SetDefaultSettings(sb, colors, fonts);

   char[] sperators = mSeperators.GetAsCharArray();

   //Replacing "/" to "//" for RTF...
   string[] lines = Text.Replace("//","").Replace("{", "//{").Replace("}", "//}").Split('/n');
   for (int lineCounter = 0 ; lineCounter < lines.Length; lineCounter++)
   {
    if (lineCounter != 0)
    {
     AddNewLine(sb);
    }
    string line = lines[lineCounter];
    string[] tokens = mCaseSesitive ? line.Split(sperators) : line.ToUpper().Split(sperators);
    if (tokens.Length == 0)
    {
     sb.Append(line);
     AddNewLine(sb);
     continue;
    }

    int tokenCounter = 0;
    for (int i = 0; i < line.Length ;)
    {
     char curChar = line[i];
     if (mSeperators.Contains(curChar))
     {
      sb.Append(curChar);
      i++;
     }
     else
     {
      string curToken = tokens[tokenCounter++];
      bool bAddToken = true;
      foreach (HighlightDescriptor hd in mHighlightDescriptors)
      {
       string compareStr = mCaseSesitive ? hd.Token : hd.Token.ToUpper();
       bool match = false;

       //Check if the highlight descriptor matches the current toker according to the DescriptoRecognision property.
       switch (hd.DescriptorRecognition)
       {
        case DescriptorRecognition.WholeWord:
         if (curToken == compareStr)
         {
           match = true;
         }
         break;
        case DescriptorRecognition.StartsWith:
         if (curToken.StartsWith(compareStr))
         {
          match = true;
         }
         break;
        case DescriptorRecognition.Contains:
         if (curToken.IndexOf(compareStr) != -1)
         {
          match = true;
         }
         break;
       }
       if (!match)
       {
        //If this token doesn't match chech the next one.
        continue;
       }

       //printing this token will be handled by the inner code, don't apply default settings...
       bAddToken = false;
 
       //Set colors to current descriptor settings.
       SetDescriptorSettings(sb, hd, colors, fonts);

       //Print text affected by this descriptor.
       switch (hd.DescriptorType)
       {
        case DescriptorType.Word:
         sb.Append(line.Substring(i, curToken.Length));
         SetDefaultSettings(sb, colors, fonts);
         i += curToken.Length;
         break;
        case DescriptorType.ToEOL:
         sb.Append(line.Remove(0, i));
         i = line.Length;
         SetDefaultSettings(sb, colors, fonts);
         break;
        case DescriptorType.ToCloseToken:
         while((line.IndexOf(hd.CloseToken, i) == -1) && (lineCounter < lines.Length))
         {
          sb.Append(line.Remove(0, i));
          lineCounter++;
          if (lineCounter < lines.Length)
          {
           AddNewLine(sb);
           line = lines[lineCounter];
           i = 0;
          }
          else
          {
           i = line.Length;
          }
         }
         if (line.IndexOf(hd.CloseToken, i) != -1)
         {
          sb.Append(line.Substring(i, line.IndexOf(hd.CloseToken, i) + hd.CloseToken.Length - i) );
          line = line.Remove(0, line.IndexOf(hd.CloseToken, i) + hd.CloseToken.Length);
          tokenCounter = 0;
          tokens = mCaseSesitive ? line.Split(sperators) : line.ToUpper().Split(sperators);
          SetDefaultSettings(sb, colors, fonts);
          i = 0;
         }
         break;
       }
       break;
      }
      if (bAddToken)
      {
       //Print text with default settings...
       sb.Append(line.Substring(i, curToken.Length));
       i+= curToken.Length;
      }
     }
    }
   }
 
//   System.Diagnostics.Debug.WriteLine(sb.ToString());
   Rtf = sb.ToString();

   //Restore cursor and scrollbars location.
   SelectionStart = cursorLoc;

   mParsing = false;
  
   SetScrollPos(scrollPos);
   Win32.LockWindowUpdate((IntPtr)0);
   Invalidate();
   
   if (mAutoCompleteShown)
   {
    if (mFilterAutoComplete)
    {
     SetAutoCompleteItems();
     SetAutoCompleteSize();
     SetAutoCompleteLocation(false);
    }
    SetBestSelectedAutoCompleteItem();
   }

  }


  protected override void OnVScroll(EventArgs e)
  {
   if (mParsing) return;
   base.OnVScroll (e);
  }

  protected override void OnMouseDown(MouseEventArgs e)
  {
   HideAutoCompleteForm();
   base.OnMouseDown (e);
  }

  /// <summary>
  /// Taking care of Keyboard events
  /// </summary>
  /// <param name="m"></param>
  /// <remarks>
  /// Since even when overriding the OnKeyDown methoed and not calling the base function
  /// you don't have full control of the input, I've decided to catch windows messages to handle them.
  /// </remarks>
  protected override void WndProc(ref Message m)
  {
   switch (m.Msg)
   {
    case Win32.WM_PAINT:
    {
     //Don't draw the control while parsing to avoid flicker.
     if (mParsing)
     {
      return;
     }
     break;
    }
    case Win32.WM_KEYDOWN:
    {
     if (mAutoCompleteShown)
     {
      switch ((Keys)(int)m.WParam)
      {
       case Keys.Down:
       {
        if (mAutoCompleteForm.Items.Count != 0)
        {
         mAutoCompleteForm.SelectedIndex = (mAutoCompleteForm.SelectedIndex + 1) % mAutoCompleteForm.Items.Count;
        }
        return;
       }
       case Keys.Up:
       {
        if (mAutoCompleteForm.Items.Count != 0)
        {
         if (mAutoCompleteForm.SelectedIndex < 1)
         {
          mAutoCompleteForm.SelectedIndex = mAutoCompleteForm.Items.Count - 1;
         }
         else
         {
          mAutoCompleteForm.SelectedIndex--;
         }
        }
        return;
       }
       case Keys.Enter:
       case Keys.Space:
       {
        AcceptAutoCompleteItem();
        return;
       }
       case Keys.Escape:
       {
        HideAutoCompleteForm();
        return;
       }
        
      }
     }
     else
     {
      if (((Keys)(int)m.WParam == Keys.Space) &&
       ((Win32.GetKeyState(Win32.VK_CONTROL) & Win32.KS_KEYDOWN) != 0))
      {
       CompleteWord();
      }
      else if (((Keys)(int)m.WParam == Keys.Z) &&
       ((Win32.GetKeyState(Win32.VK_CONTROL) & Win32.KS_KEYDOWN) != 0))
      {
       Undo();
       return;
      }
      else if (((Keys)(int)m.WParam == Keys.Y) &&
       ((Win32.GetKeyState(Win32.VK_CONTROL) & Win32.KS_KEYDOWN) != 0))
      {
       Redo();
       return;
      }
     }
     break;
    }
    case Win32.WM_CHAR:
    {
     switch ((Keys)(int)m.WParam)
     {
      case Keys.Space:
       if ((Win32.GetKeyState(Win32.VK_CONTROL) & Win32.KS_KEYDOWN )!= 0)
       {
        return;
       }
       break;
      case Keys.Enter:
       if (mAutoCompleteShown) return;
       break;
     }
    }
    break;

   }
   base.WndProc (ref m);
  }


  /// <summary>
  /// Hides the AutoComplete form when losing focus on textbox.
  /// </summary>
  /// <param name="e"></param>
  protected override void OnLostFocus(EventArgs e)
  {
   if (!mIgnoreLostFocus)
   {
    HideAutoCompleteForm();
   }
   base.OnLostFocus (e);
  }


  #endregion

  #region Undo/Redo Code
  public new bool CanUndo
  {
   get
   {
    return mUndoList.Count > 0;
   }
  }
  public new bool CanRedo
  {
   get
   {
    return mRedoStack.Count > 0;
   }
  }

  private void LimitUndo()
  {
   while (mUndoList.Count > mMaxUndoRedoSteps)
   {
    mUndoList.RemoveAt(mMaxUndoRedoSteps);
   }
  }

  public new void Undo()
  {
   if (!CanUndo)
    return;
   mIsUndo = true;
   mRedoStack.Push(new UndoRedoInfo(Text, GetScrollPos(), SelectionStart));
   UndoRedoInfo info = (UndoRedoInfo)mUndoList[0];
   mUndoList.RemoveAt(0);
   Text = info.Text;
   SelectionStart = info.CursorLocation;
   SetScrollPos(info.ScrollPos);
   mLastInfo = info;
   mIsUndo = false;
  }
  public new void Redo()
  {
   if (!CanRedo)
    return;
   mIsUndo = true;
   mUndoList.Insert(0,new UndoRedoInfo(Text, GetScrollPos(), SelectionStart));
   LimitUndo();
   UndoRedoInfo info = (UndoRedoInfo)mRedoStack.Pop();
   Text = info.Text;
   SelectionStart = info.CursorLocation;
   SetScrollPos(info.ScrollPos);
   mIsUndo = false;
  }

  private class UndoRedoInfo
  {
   public UndoRedoInfo(string text, Win32.POINT scrollPos, int cursorLoc)
   {
    Text = text;
    ScrollPos = scrollPos;
    CursorLocation = cursorLoc;
   }
   public readonly Win32.POINT ScrollPos;
   public readonly int CursorLocation;
   public readonly string Text;
  }
  #endregion

  #region AutoComplete functions

  /// <summary>
  /// Entry point to autocomplete mechanism.
  /// Tries to complete the current word. if it fails it shows the AutoComplete form.
  /// </summary>
  private void CompleteWord()
  {
   int curTokenStartIndex = Text.LastIndexOfAny(mSeperators.GetAsCharArray(), Math.Min(SelectionStart, Text.Length - 1))+1;
   int curTokenEndIndex= Text.IndexOfAny(mSeperators.GetAsCharArray(), SelectionStart);
   if (curTokenEndIndex == -1)
   {
    curTokenEndIndex = Text.Length;
   }
   string curTokenString = Text.Substring(curTokenStartIndex, Math.Max(curTokenEndIndex - curTokenStartIndex,0)).ToUpper();
   
   string token = null;
   foreach (HighlightDescriptor hd in mHighlightDescriptors)
   {
    if (hd.UseForAutoComplete && hd.Token.ToUpper().StartsWith(curTokenString))
    {
     if (token == null)
     {
      token = hd.Token;
     }
     else
     {
      token = null;
      break;
     }
    }
   }
   if (token == null)
   {
    ShowAutoComplete();
   }
   else
   {
    SelectionStart = curTokenStartIndex;
    SelectionLength = curTokenEndIndex - curTokenStartIndex;
    SelectedText = token;
    SelectionStart = SelectionStart + SelectionLength;
    SelectionLength = 0;
   }
  }

  /// <summary>
  /// replace the current word of the cursor with the one from the AutoComplete form and closes it.
  /// </summary>
  /// <returns>If the operation was succesful</returns>
  private bool AcceptAutoCompleteItem()
  {
   
   if (mAutoCompleteForm.SelectedItem == null)
   {
    return false;
   }
   
   int curTokenStartIndex = Text.LastIndexOfAny(mSeperators.GetAsCharArray(), Math.Min(SelectionStart, Text.Length - 1)) + 1;
   int curTokenEndIndex= Text.IndexOfAny(mSeperators.GetAsCharArray(), SelectionStart);
   if (curTokenEndIndex == -1)
   {
    curTokenEndIndex = Text.Length;
   }
   SelectionStart = Math.Max(curTokenStartIndex, 0);
   SelectionLength = Math.Max(0,curTokenEndIndex - curTokenStartIndex);
   SelectedText = mAutoCompleteForm.SelectedItem;
   SelectionStart = SelectionStart + SelectionLength;
   SelectionLength = 0;
   
   HideAutoCompleteForm();
   return true;
  }

 

  /// <summary>
  /// Finds the and sets the best matching token as the selected item in the AutoCompleteForm.
  /// </summary>
  private void SetBestSelectedAutoCompleteItem()
  {
   int curTokenStartIndex = Text.LastIndexOfAny(mSeperators.GetAsCharArray(), Math.Min(SelectionStart, Text.Length - 1))+1;
   int curTokenEndIndex= Text.IndexOfAny(mSeperators.GetAsCharArray(), SelectionStart);
   if (curTokenEndIndex == -1)
   {
    curTokenEndIndex = Text.Length;
   }
   string curTokenString = Text.Substring(curTokenStartIndex, Math.Max(curTokenEndIndex - curTokenStartIndex,0)).ToUpper();
   
   if ((mAutoCompleteForm.SelectedItem != null) &&
    mAutoCompleteForm.SelectedItem.ToUpper().StartsWith(curTokenString))
   {
    return;
   }

   int matchingChars = -1;
   string bestMatchingToken = null;

   foreach (string item in mAutoCompleteForm.Items)
   {
    bool isWholeItemMatching = true;
    for (int i = 0 ; i < Math.Min(item.Length, curTokenString.Length); i++)
    {
     if (char.ToUpper(item[i]) != char.ToUpper(curTokenString[i]))
     {
      isWholeItemMatching = false;
      if (i-1 > matchingChars)
      {
       matchingChars = i;
       bestMatchingToken = item;
       break;
      }
     }
    }
    if (isWholeItemMatching &&
     (Math.Min(item.Length, curTokenString.Length) > matchingChars))
    {
     matchingChars = Math.Min(item.Length, curTokenString.Length);
     bestMatchingToken = item;
    }
   }
   
   if (bestMatchingToken != null)
   {
    mAutoCompleteForm.SelectedIndex = mAutoCompleteForm.Items.IndexOf(bestMatchingToken);
   }


  }

  /// <summary>
  /// Sets the items for the AutoComplete form.
  /// </summary>
  private void SetAutoCompleteItems()
  {
   mAutoCompleteForm.Items.Clear();
   string filterString = "";
   if (mFilterAutoComplete)
   {
   
    int filterTokenStartIndex = Text.LastIndexOfAny(mSeperators.GetAsCharArray(), Math.Min(SelectionStart, Text.Length - 1))+1;
    int filterTokenEndIndex= Text.IndexOfAny(mSeperators.GetAsCharArray(), SelectionStart);
    if (filterTokenEndIndex == -1)
    {
     filterTokenEndIndex = Text.Length;
    }
    filterString = Text.Substring(filterTokenStartIndex, filterTokenEndIndex - filterTokenStartIndex).ToUpper();
   }
  
   foreach (HighlightDescriptor hd in mHighlightDescriptors)
   {
    if (hd.Token.ToUpper().StartsWith(filterString) && hd.UseForAutoComplete)
    {
     mAutoCompleteForm.Items.Add(hd.Token);
    }
   }
   mAutoCompleteForm.UpdateView();
  }
  
  /// <summary>
  /// Sets the size. the size is limited by the MaxSize property in the form itself.
  /// </summary>
  private void SetAutoCompleteSize()
  {
   mAutoCompleteForm.Height = Math.Min(
    Math.Max(mAutoCompleteForm.Items.Count, 1) * mAutoCompleteForm.ItemHeight + 4,
    mAutoCompleteForm.MaximumSize.Height);
  }

  /// <summary>
  /// closes the AutoCompleteForm.
  /// </summary>
  private void HideAutoCompleteForm()
  {
   mAutoCompleteForm.Visible = false;
   mAutoCompleteShown = false;
  }
  

  /// <summary>
  /// Sets the location of the AutoComplete form, maiking sure it's on the screen where the cursor is.
  /// </summary>
  /// <param name="moveHorizontly">determines wheather or not to move the form horizontly.</param>
  private void SetAutoCompleteLocation(bool moveHorizontly)
  {
   Point cursorLocation = GetPositionFromCharIndex(SelectionStart);
   Screen screen = Screen.FromPoint(cursorLocation);
   Point optimalLocation = new Point(PointToScreen(cursorLocation).X-15, (int)(PointToScreen(cursorLocation).Y + Font.Size*2 + 2));
   Rectangle desiredPlace = new Rectangle(optimalLocation , mAutoCompleteForm.Size);
   desiredPlace.Width = 152;
   if (desiredPlace.Left < screen.Bounds.Left)
   {
    desiredPlace.X = screen.Bounds.Left;
   }
   if (desiredPlace.Right > screen.Bounds.Right)
   {
    desiredPlace.X -= (desiredPlace.Right - screen.Bounds.Right);
   }
   if (desiredPlace.Bottom > screen.Bounds.Bottom)
   {
    desiredPlace.Y = cursorLocation.Y - 2 - desiredPlace.Height;
   }
   if (!moveHorizontly)
   {
    desiredPlace.X = mAutoCompleteForm.Left;
   }

   mAutoCompleteForm.Bounds = desiredPlace;
  }

  /// <summary>
  /// Shows the Autocomplete form.
  /// </summary>
  public void ShowAutoComplete()
  {
   SetAutoCompleteItems();
   SetAutoCompleteSize();
   SetAutoCompleteLocation(true);
   mIgnoreLostFocus = true;
   mAutoCompleteForm.Visible = true;
   SetBestSelectedAutoCompleteItem();
   mAutoCompleteShown = true;
   Focus();
   mIgnoreLostFocus = false;
  }

  #endregion

  #region Rtf building helper functions

  /// <summary>
  /// Set color and font to default control settings.
  /// </summary>
  /// <param name="sb">the string builder building the RTF</param>
  /// <param name="colors">colors hashtable</param>
  /// <param name="fonts">fonts hashtable</param>
  private void SetDefaultSettings(StringBuilder sb, Hashtable colors, Hashtable fonts)
  {
   SetColor(sb, ForeColor, colors);
   SetFont(sb, Font, fonts);
   SetFontSize(sb, (int)Font.Size);
   EndTags(sb);
  }

  /// <summary>
  /// Set Color and font to a highlight descriptor settings.
  /// </summary>
  /// <param name="sb">the string builder building the RTF</param>
  /// <param name="hd">the HighlightDescriptor with the font and color settings to apply.</param>
  /// <param name="colors">colors hashtable</param>
  /// <param name="fonts">fonts hashtable</param>
  private void SetDescriptorSettings(StringBuilder sb, HighlightDescriptor hd, Hashtable colors, Hashtable fonts)
  {
   SetColor(sb, hd.Color, colors);
   if (hd.Font != null)
   {
    SetFont(sb, hd.Font, fonts);
    SetFontSize(sb, (int)hd.Font.Size);
   }
   EndTags(sb);

  }
  /// <summary>
  /// Sets the color to the specified color
  /// </summary>
  private void SetColor(StringBuilder sb, Color color, Hashtable colors)
  {
   sb.Append(@"/cf").Append(colors[color]);
  }
  /// <summary>
  /// Sets the backgroung color to the specified color.
  /// </summary>
  private void SetBackColor(StringBuilder sb, Color color, Hashtable colors)
  {
   sb.Append(@"/cb").Append(colors[color]);
  }
  /// <summary>
  /// Sets the font to the specified font.
  /// </summary>
  private void SetFont(StringBuilder sb, Font font, Hashtable fonts)
  {
   if (font == null) return;
   sb.Append(@"/f").Append(fonts[font.Name]);
  }
  /// <summary>
  /// Sets the font size to the specified font size.
  /// </summary>
  private void SetFontSize(StringBuilder sb, int size)
  {
   sb.Append(@"/fs").Append(size*2);
  }
  /// <summary>
  /// Adds a newLine mark to the RTF.
  /// </summary>
  private void AddNewLine(StringBuilder sb)
  {
   sb.Append("//par/n");
  }
  /// <summary>
  /// Ends a RTF tags section.
  /// </summary>
  private void EndTags(StringBuilder sb)
  {
   sb.Append(' ');
  }
  /// <summary>
  /// Adds a font to the RTF's font table and to the fonts hashtable.
  /// </summary>
  /// <param name="sb">The RTF's string builder</param>
  /// <param name="font">the Font to add</param>
  /// <param name="counter">a counter, containing the amount of fonts in the table</param>
  /// <param name="fonts">an hashtable. the key is the font's name. the value is it's index in the table</param>
  private void AddFontToTable(StringBuilder sb, Font font, ref int counter, Hashtable fonts)
  {
 
   sb.Append(@"/f").Append(counter).Append(@"/fnil/fcharset0").Append(font.Name).Append(";}");
   fonts.Add(font.Name, counter++);
  }
  /// <summary>
  /// Adds a color to the RTF's color table and to the colors hashtable.
  /// </summary>
  /// <param name="sb">The RTF's string builder</param>
  /// <param name="color">the color to add</param>
  /// <param name="counter">a counter, containing the amount of colors in the table</param>
  /// <param name="colors">an hashtable. the key is the color. the value is it's index in the table</param>
  private void AddColorToTable(StringBuilder sb, Color color, ref int counter, Hashtable colors)
  {
 
   sb.Append(@"/red").Append(color.R).Append(@"/green").Append(color.G).Append(@"/blue")
    .Append(color.B).Append(";");
   colors.Add(color, counter++);
  }

  #endregion

  #region Scrollbar positions functions
  /// <summary>
  /// Sends a win32 message to get the scrollbars' position.
  /// </summary>
  /// <returns>a POINT structore containing horizontal and vertical scrollbar position.</returns>
  private unsafe Win32.POINT GetScrollPos()
  {
   Win32.POINT res = new Win32.POINT();
   IntPtr ptr = new IntPtr(&res);
   Win32.SendMessage(Handle, Win32.EM_GETSCROLLPOS, 0, ptr);
   return res;

  }
  /// <summary>
  /// Sends a win32 message to set scrollbars position.
  /// </summary>
  /// <param name="point">a POINT conatining H/Vscrollbar scrollpos.</param>
  private unsafe void SetScrollPos(Win32.POINT point)
  {
   IntPtr ptr = new IntPtr(&point);
   Win32.SendMessage(Handle, Win32.EM_SETSCROLLPOS, 0, ptr);

  }
  #endregion
 }

 

 

using  System;
using  System.Runtime;
using  System.Runtime.InteropServices;

using  HWND  =  System.IntPtr;

namespace  UrielGuy.SyntaxHighlightingTextBox
{
    
/// <summary>
    
/// Summary description for Win32.
    
/// </summary>

    public class Win32
    
{
        
private Win32()
        
{
        }


        
public const int WM_USER = 0x400;
        
public const int WM_PAINT = 0xF;
        
public const int WM_KEYDOWN = 0x100;
        
public const int WM_KEYUP = 0x101;
        
public const int WM_CHAR = 0x102;

        
public const int EM_GETSCROLLPOS  =       (WM_USER + 221);
        
public const int EM_SETSCROLLPOS  =       (WM_USER + 222);

        
public const int VK_CONTROL = 0x11;
        
public const int VK_UP = 0x26;
        
public const int VK_DOWN = 0x28;
        
public const int VK_NUMLOCK = 0x90;

        
public const short KS_ON = 0x01;
        
public const short KS_KEYDOWN = 0x80;

        [StructLayout(LayoutKind.Sequential)]
        
public struct POINT 
        
{
            
public int x;
            
public int y;
        }


        [DllImport(
"user32")] public static extern int SendMessage(HWND hwnd, int wMsg, int wParam, IntPtr lParam);
        [DllImport(
"user32")] public static extern int PostMessage(HWND hwnd, int wMsg, int wParam, int lParam);
        [DllImport(
"user32")] public static extern short GetKeyState(int nVirtKey);
        [DllImport(
"user32")] public static extern int LockWindowUpdate(HWND hwnd);

    }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值