Stopwatch class from .net 2.0 framework ported .net 1.1

Here is the handy Stopwatch class from .net 2.0 framework back ported .net 1.1. Enjoy…

/// <summary>Provides a set of methods and properties that you can use to accurately measure elapsed time.</summary>  
public class Stopwatch  
{  
    #region SafeNativeMethods  
    [DllImport("kernel32.dll")]  
    private static extern bool QueryPerformanceFrequency(out long lpFrequency);  
    [DllImport("kernel32.dll")]  
    private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);  
    #endregion //SafeNativeMethods  
    #region Public Fields          
    /// <summary>Gets the frequency of the timer as the number of ticks per second. This field is read-only.</summary>  
    public static readonly long Frequency;  
      
    /// <summary>Indicates whether the timer is based on a high-resolution performance counter. This field is read-only.</summary>  
    public static readonly bool IsHighResolution;  
     
    #endregion //Public Fields  
     
    #region Private Fields  
    private long elapsed;          
    private bool isRunning;  
    private long startTimeStamp;  
      
    private static readonly double tickFrequency;  
    #endregion //Private Fields  
    #region Constructors  
    static Stopwatch()  
    {  
        if (!QueryPerformanceFrequency(out Stopwatch.Frequency))  
        {  
            Stopwatch.IsHighResolution = false;  
            Stopwatch.Frequency = TimeSpan.TicksPerSecond;  
            Stopwatch.tickFrequency = 1;  
        }  
        else  
        {  
            Stopwatch.IsHighResolution = true;  
            Stopwatch.tickFrequency = TimeSpan.TicksPerSecond;  
            Stopwatch.tickFrequency /= ((double)Stopwatch.Frequency);  
        }  
    }  
      
    /// <summary>Initializes a new instance of the Stopwatch class.</summary>  
    public Stopwatch()  
    {  
        this.Reset();  
    }  
    #endregion //Constructors  
     
    #region Private Methods  
    private long GetElapsedDateTimeTicks()  
    {  
        long ticks = this.GetRawElapsedTicks();  
        if (Stopwatch.IsHighResolution)  
        {  
            double highTicks = ticks;  
            highTicks *= Stopwatch.tickFrequency;  
            return (long)highTicks;  
        }  
        return ticks;  
    }  
    private long GetRawElapsedTicks()          
    {  
        long elapsedTimestamp = this.elapsed;  
        if (this.isRunning)  
        {  
            long currentTimestamp = Stopwatch.GetTimestamp();  
            long endTimestamp = currentTimestamp - this.startTimeStamp;  
            elapsedTimestamp += endTimestamp;  
        }  
        return elapsedTimestamp;  
    }  
    #endregion //Private Methods  
    #region Public Methods  
    /// <summary>Gets the current number of ticks in the timer mechanism.</summary>  
    /// <returns>A long integer representing the tick counter value of the underlying timer mechanism.</returns>  
    public static long GetTimestamp()          
    {  
        if (Stopwatch.IsHighResolution)  
        {  
            long ticks = 0;  
            QueryPerformanceCounter(out ticks);  
            return ticks;  
        }  
        return DateTime.UtcNow.Ticks;  
    }  
    /// <summary>Stops time interval measurement and resets the elapsed time to zero.</summary>  
    public void Reset()          
    {  
        this.elapsed = 0;  
        this.isRunning = false;  
        this.startTimeStamp = 0;  
    }  
    /// <summary>Starts, or resumes, measuring elapsed time for an interval.</summary>  
    public void Start()          
    {  
        if (!this.isRunning)  
        {  
            this.startTimeStamp = Stopwatch.GetTimestamp();  
            this.isRunning = true;  
        }  
    }  
    /// <summary>Initializes a new Stopwatch instance, sets the elapsed time property to zero, and starts measuring elapsed time.</summary>  
    /// <returns>A Stopwatch that has just begun measuring elapsed time.</returns>  
    public static Stopwatch StartNew()          
    {  
        Stopwatch stopwatch = new Stopwatch();  
        stopwatch.Start();  
        return stopwatch;  
    }  
    /// <summary>Stops measuring elapsed time for an interval.</summary>  
    public void Stop()          
    {  
        if (this.isRunning)  
        {  
            long currentTimestamp = Stopwatch.GetTimestamp();  
            long endTimestamp = currentTimestamp - this.startTimeStamp;  
            this.elapsed += endTimestamp;  
            this.isRunning = false;  
        }  
    }  
    #endregion //Public Methods  
     
    #region Public Properties  
    /// <summary>Gets the total elapsed time measured by the current instance.</summary>  
    /// <value>A read-only System.TimeSpan representing the total elapsed time measured by the current instance.</value>  
    public TimeSpan Elapsed  
    {  
        get { return new TimeSpan(this.GetElapsedDateTimeTicks()); }  
    }  
      
    /// <summary>Gets the total elapsed time measured by the current instance, in milliseconds.</summary>  
    public long ElapsedMilliseconds  
    {  
        get { return (this.GetElapsedDateTimeTicks() / TimeSpan.TicksPerMillisecond); }  
    }  
    /// <summary>Gets the total elapsed time measured by the current instance, in timer ticks.</summary>  
    public long ElapsedTicks  
    {  
        get { return this.GetRawElapsedTicks(); }  
    }  
      
    /// <summary>Gets a value indicating whether the Stopwatch timer is running.</summary>  
    public bool IsRunning  
    {  
        get { return this.isRunning; }  
    }  
    #endregion //Public Properties  
}

Code Snippet to Convert Word Tense

Here is a useful code snippet to convert the tense of a word from single to plural and vise versa. The code uses a series of regular expression to examine the word and convert it using the correct grammar.

public string MakePlural(string name)  
{  
    Regex plural1 = new Regex("(?<keep>[^aeiou])y$");  
    Regex plural2 = new Regex("(?<keep>[aeiou]y)$");  
    Regex plural3 = new Regex("(?<keep>[sxzh])$");  
    Regex plural4 = new Regex("(?<keep>[^sxzhy])$");  
  
    if(plural1.IsMatch(name))  
        return plural1.Replace(name, "${keep}ies");  
    else if(plural2.IsMatch(name))  
        return plural2.Replace(name, "${keep}s");  
    else if(plural3.IsMatch(name))  
        return plural3.Replace(name, "${keep}es");  
    else if(plural4.IsMatch(name))  
        return plural4.Replace(name, "${keep}s");  
  
    return name;  
}  
  
public string MakeSingle(string name)  
{  
    Regex single1 = new Regex("(?<keep>[^aeiou])ies$");  
    Regex single2 = new Regex("(?<keep>[aeiou]y)s$");  
    Regex single3 = new Regex("(?<keep>[sxzh])es$");  
    Regex single4 = new Regex("(?<keep>[^sxzhy])s$");  
  
    if(single1.IsMatch(name))  
        return single1.Replace(name, "${keep}y");  
    else if(single2.IsMatch(name))  
        return single2.Replace(name, "${keep}");  
    else if(single3.IsMatch(name))  
        return single3.Replace(name, "${keep}");  
    else if(single4.IsMatch(name))  
        return single4.Replace(name, "${keep}");  
  
    return name;  
}

Fix for the RichTextBox Undo Information Lost When Retrieving Text

In my work with the RichTextBox control, I’ve often run into this bug in the RichEdit control. You can read more about this bug by looking at Microsoft’s knowledge base article - 812943. If you are unable to get the latest Riched20.dll then you can get around the problem using the following code …

using System;  
using System.Runtime.InteropServices;  
using System.Text;  
using System.Windows.Forms;  
  
namespace TextUndoBuffer  
{  
    /// <summary>    
    /// Work around for KB 812943, The RichEdit Control Undo    
    /// Information May Be Lost When the Control Retrieves Text.   
    /// </summary>    
    public class RichTextBoxEx : RichTextBox  
    {  
        // RichEdit messages (Richedit.h)   
        private const int EM_GETTEXTEX = (WM_USER + 94);  
        private const int EM_GETTEXTLENGTHEX = (WM_USER + 95);  
        // Flags for the GETEXTEX data structure   
        private const int GT_DEFAULT = 0;  
        // Flags for the GETTEXTLENGTHEX data structure   
        // Fast computation of a "close" answer   
        private const int GTL_CLOSE = 4;  
        // Do default (return # of chars)   
        private const int GTL_DEFAULT = 0;   
        private const int WM_USER = 0x0400;  
  
        public override string Text  
        {  
            get  
            {  
                GETTEXTLENGTHEX getLength = new GETTEXTLENGTHEX();  
                getLength.flags = GTL_CLOSE; //get buffer size   
                getLength.codepage = 1200; //Unicode   
                  
                int textLength = SendMessage(  
                    base.Handle, EM_GETTEXTLENGTHEX,   
                    ref getLength, 0);  
  
                GETTEXTEX getText = new GETTEXTEX();  
                //add space for null terminator   
                getText.cb = textLength + 2;   
                getText.flags = GT_DEFAULT;  
                getText.codepage = 1200; //Unicode   
                  
                StringBuilder sb = new StringBuilder(getText.cb);  
                  
                SendMessage(base.Handle, EM_GETTEXTEX, ref getText, sb);  
                  
                return sb.ToString();  
            }  
            set  
            {  
                base.Text = value;  
            }  
        }  
  
        public override int TextLength  
        {  
            get  
            {  
                GETTEXTLENGTHEX getLength = new GETTEXTLENGTHEX();  
                //Returns the number of characters   
                getLength.flags = GTL_DEFAULT;   
                getLength.codepage = 1200; //Unicode   
                return SendMessage(base.Handle, EM_GETTEXTLENGTHEX, ref getLength, 0);  
            }  
        }  
  
        [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]  
        private static extern int SendMessage(IntPtr hWnd, int msg,  
                                              ref GETTEXTEX wParam, StringBuilder lParam);  
  
        [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]  
        private static extern int SendMessage(IntPtr hWnd, int msg,  
                                              ref GETTEXTLENGTHEX wParam, int lParam);  
 
        #region Nested type: GETTEXTEX  
  
        [StructLayout(LayoutKind.Sequential)]  
        private struct GETTEXTEX  
        {  
            public Int32 cb;  
            public Int32 flags;  
            public Int32 codepage;  
            public IntPtr lpDefaultChar;  
            public IntPtr lpUsedDefChar;  
        }  
 
        #endregion  
 
        #region Nested type: GETTEXTLENGTHEX  
  
        [StructLayout(LayoutKind.Sequential)]  
        private struct GETTEXTLENGTHEX  
        {  
            public Int32 flags;  
            public Int32 codepage;  
        }  
 
        #endregion  
    }  
}

How to integrate NetSpell with FreeTextBox

The following code snippet show how intergrate NetSpell with FreeTextBox.

Download the latest version of FreeTextBox and NetSpell.

Copy NetSpell.SpellChecker.dll to the bin folder and add the following files to the same folder as default.aspx for FreeTextBox.

  • spell.css
  • spell.js
  • SpellCheck.aspx 

Copy the dic folder to the FreeTextBox folder.  Then modify the web.config file so the path to the dic folder matches.

<configuration>
    <appSettings>
        <add key="DictionaryFolder" value="dic" />
    </appSettings>
</configuration>

Modify Default.aspx to look like this

<script language="JavaScript" src="spell.js" type="text/javascript"></script>
<FTB:FREETEXTBOX id="FreeTextBox1" runat="Server">
    <TOOLBARS>
        <FTB:TOOLBAR runat="server">
            <FTB:NetSpell runat="server" />
        </FTB:TOOLBAR>
    </TOOLBARS>
</FTB:FREETEXTBOX>

Now when you run the web site there should be a new toolbar that has a spell check button. When the spell check button is clicked, NetSpell should load and start checking the text in the FreeTextBox.

You can look in the demo\Demo.Web.FreeTextBox folder of the latest package of NetSpell for an example of how to integrate NetSpell with FreeTextBox.

3.x UPDATE:

As of FreeTextBox 3.0, NetSpell is intergrated.  The sample code above has been update to reflect what is needed in 3.0


How to create a custom dictionary

The following are some simple steps to create a custom dictionary.

Step 1

Create a text file with all the words you would like to use in the dictionary. The text file should have one word per line like so …

apple
banana
grape
orange
peach
pineapple

Step 2

Run the Dictionary Build tool. Create a new dictionary.

Step 3

Load the text file into the new dictionary by using the Dictionary > Add OpenOffice Word List.

Step 4

Open the en-US.dic dictionary in the dictionary build tool. Copy everything in the Near Miss Data tab for the en-US.dic to the new dictionary’s Near Miss Data tab. Also, copy the data from the Phonetic Rules tab to the new dictionary.

Step 5

Generate the phonetic code cache for the new dictionary by use the Dictionary > Generate Phonetic Cache.

You should now be able to use the new dictioanry in NetSpell to check words and generate suggestions from the new word list.