<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Red Stars</title>
	<atom:link href="http://blog.red-stars.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.red-stars.net</link>
	<description>Programming, food, and rambling</description>
	<lastBuildDate>Sat, 27 Feb 2010 13:22:24 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>PHP Array Performance</title>
		<link>http://blog.red-stars.net/uncategorized/php-array-performance/</link>
		<comments>http://blog.red-stars.net/uncategorized/php-array-performance/#comments</comments>
		<pubDate>Fri, 26 Feb 2010 13:42:02 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.red-stars.net/?p=204</guid>
		<description><![CDATA[Index Checking
The functional difference between array_key_exists($key, $array) and isset($array[$key]) is that isset returns false when the key exists but contains null. Functionality aside, there is a demonstrable performance difference.
$dataSet = array();
$size = 0x1FFFF;

$i = $size;
while ($i--)
	$dataSet[$i] = $i+1;

$start = microtime(true);

$i = $size;
while ($i--)
	array_key_exists($i, $dataSet); //isset($dataSet[$i]);

echo "Time: ". (microtime(true) - $start);
Sure enough, after averaging a few [...]]]></description>
			<content:encoded><![CDATA[<a name="3)Index Checking"></a><h3>Index Checking</h3>
<p>The functional difference between array_key_exists($key, $array) and isset($array[$key]) is that isset returns false when the key exists but contains null. Functionality aside, there is a demonstrable performance difference.</p>
<pre class="brush:php">$dataSet = array();
$size = 0x1FFFF;

$i = $size;
while ($i--)
	$dataSet[$i] = $i+1;

$start = microtime(true);

$i = $size;
while ($i--)
	array_key_exists($i, $dataSet); //isset($dataSet[$i]);

echo "Time: ". (microtime(true) - $start);</pre>
<p>Sure enough, after averaging a few benchmarks together the outcome was clear.</p>
<dl>
<dt>isset</dt>
<dd>0.0248870849609</dd>
<dt>array_key_exists</dt>
<dd>0.604112148285</dd>
</dl>
<p>When performance is important target isset() when applicable. It&#8217;s even possible to use a fall through to increase performance, here&#8217;s an example from my Options class: if (!isset($this->_options[$resolvedName]) &#038;&#038; !array_key_exists($resolvedName, $this->_options))</p>
<a name="3)Append Performance"></a><h3>Append Performance</h3>
<p>In the following test case there was no performance difference between usage of append or directly addressing an index.</p>
<pre class="brush:php">$dataSet = array();
$size = 0x1FFFF;
$i = $size;

$start = microtime(true);

while ($i--)
	$dataSet[] = $i+1; //$dataSet[$i] = $i+1;

echo "Time: ". (microtime(true) - $start);</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.red-stars.net/uncategorized/php-array-performance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Remodeling PHP&#8217;s compact()/extract() into an OO Pattern</title>
		<link>http://blog.red-stars.net/technology/programming/web/remodeling-phps-compactextract-into-an-oo-pattern/</link>
		<comments>http://blog.red-stars.net/technology/programming/web/remodeling-phps-compactextract-into-an-oo-pattern/#comments</comments>
		<pubDate>Sun, 11 Oct 2009 16:38:47 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.red-stars.net/?p=185</guid>
		<description><![CDATA[A common usage, at least for extract(), has been to allow an associative array to be passed to a function for use as named optional parameters, however, there is a lot wrong with dumping an array into the symbol table and then checking if what you want exists or not.
I have designed a pattern that [...]]]></description>
			<content:encoded><![CDATA[<p>A common usage, at least for extract(), has been to allow an associative array to be passed to a function for use as named optional parameters, however, there is <em>a lot</em> wrong with dumping an array into the symbol table and then checking if what you want exists or not.</p>
<p>I have designed a pattern that allows an object to accept and address public level optional named arguments without the problems that could be associated with the compact()/extract() pattern. This pattern does require at least PHP 5.3 (uses late static binding) and overloads __get/__set preventing the child class from doing so.</p>
<p><span id="more-185"></span></p>
<a name="2)Usage"></a><h2>Usage</h2>
<p>Possible optional keys are defined as class constants, if one is addressed or set that is undefined an exception will be thrown. Instead of using extract(), the inherited SetOptionalProperties($array) method should be called to set the values. The value&#8217;s can be addressed by it&#8217;s constants name like it&#8217;s a property, like $instance->ConstantName. Default values can be given by overloading the protected static $_defaultOptions member. The example shows this in with more detail:</p>
<a name="3)Example"></a><h3>Example</h3>
<pre class="brush:php">class MyClass extends Options {
	public $Property;

	const MyOption = "MyOption";
	const AnotherOption = "AnotherOption";

	protected static $_defaultOptions = array(self::AnotherOption = "default value!");

	public function __construct($property, $options = array()) {
		$this->Property = $property;
		$this->SetOptionalProperties($options); // this allows Options to access the optional values.
	}
}

$instance = new MyClass("property's value", array(MyClass::MyOption = "my option value!"));
echo "MyOption: '{$instance->MyOption}', AnotherOption: '{$instance->AnotherOption}', Property: '{$instance->Property}'";</pre>
<a name="4)Output:"></a><h4>Output:</h4>
<pre>MyOption: 'my option value!', AnotherOption: 'default value!', Property: 'property's value'</pre>
<a name="3)Class"></a><h3>Class</h3>
<pre class="brush:php">abstract class Options {
	/// The array which stores the optional values
	private $_options = array();

	/// This array should be overloaded by child classes if default values are going to be used.
	protected static $_defaultOptions = array();

	/// Use Options::$AllowUndefinedProperties = true; to prevent exceptions from being thrown when an undefined
	/// property is set or fetched.
	public static $AllowUndefinedProperties = false;

	public function &#038;__get($name) {
		$resolvedName = $this->ResolveOptionName($name);

		// Do we have a value? Use the isset/array_key_exists fall through to speed up access to existing non-null entries.
		if (!isset($this->_options[$resolvedName]) &#038;&#038; !array_key_exists($resolvedName, $this->_options)) {
			// Do we have a default value?
			if (array_key_exists($resolvedName, static::$_defaultOptions))
				$this->_options[$resolvedName] = static::$_defaultOptions[$resolvedName];
			else
				$this->_options[$resolvedName] = null;
		}

		return $this->_options[$resolvedName];
	}

	public function __set($name, $value) {
		$resolvedName = $this->ResolveOptionName($name);

		return $this->_options[$resolvedName] = $value;
	}

	public function __isset($name) {
		$resolvedName = $this->ResolveOptionName($name);

		return isset($this->_options[$resolvedName]);
	}

	public function __unset($name) {
		$resolvedName = $this->ResolveOptionName($name);

		unset($this->_options[$resolvedName]);
	}

	/**
	 * Set the optional properties for the class.
	 * @param $options A [ClassConstant] = Value indexed array of optional properties.
	 */
	protected function SetOptionalProperties(array $options) {
		$this->_options = $options;
	}

	/// Resolve any aliases name to the proper name.
	private function ResolveOptionName($name) {
		$constant = "static::". $name;

		if (defined($constant))
			return constant($constant);
		else if (!self::$AllowUndefinedProperties)
			throw new Exception("Undefined property or option '$name' being set in ". get_called_class());

	}
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.red-stars.net/technology/programming/web/remodeling-phps-compactextract-into-an-oo-pattern/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Queryable Food Nutrition Database</title>
		<link>http://blog.red-stars.net/technology/programming/web/queryable-food-nutrition-database/</link>
		<comments>http://blog.red-stars.net/technology/programming/web/queryable-food-nutrition-database/#comments</comments>
		<pubDate>Wed, 07 Oct 2009 16:42:06 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.red-stars.net/?p=175</guid>
		<description><![CDATA[The USDA releases data for food nutritional information. I&#8217;ve taken this data and loaded it into my local database, and created a front end to allow it to be queryable.
Database Schema


Sample Queries
Top 150 protein containing foods
SELECT Foods.Description, concat( NutrientValue, Units ) AS Value
FROM Foods
JOIN NutrientDefinitions ON ( NutrientName = 'Protein' )
JOIN NutrientData
USING ( NutrientID, FoodID [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.ars.usda.gov/Services/docs.htm?docid=17478">The USDA</a> releases data for food nutritional information. I&#8217;ve taken this data and loaded it into my local database, and created <a href="http://fooddb.red-stars.net">a front end to allow it to be queryable.</a></p>
<a name="2)Database Schema"></a><h2>Database Schema</h2>
<p><img src="http://red-stars.net/pictures/fooddb.png" alt="database schema" /></p>
<p><span id="more-175"></span></p>
<a name="2)Sample Queries"></a><h2>Sample Queries</h2>
<a name="3)Top 150 protein containing foods"></a><h3>Top 150 protein containing foods</h3>
<p><code>SELECT Foods.Description, concat( NutrientValue, Units ) AS Value<br />
FROM Foods<br />
JOIN NutrientDefinitions ON ( NutrientName = 'Protein' )<br />
JOIN NutrientData<br />
USING ( NutrientID, FoodID )<br />
ORDER BY NutrientValue DESC<br />
LIMIT 150</code></p>
<a name="3)Top 100 protein containing legumes"></a><h3>Top 100 protein containing legumes</h3>
<p><code>SELECT Foods.Description, concat( NutrientValue, Units ) AS Value<br />
FROM FoodGroups<br />
JOIN Foods<br />
USING ( CategoryID )<br />
JOIN NutrientDefinitions ON ( NutrientName = 'Protein' )<br />
JOIN NutrientData<br />
USING ( NutrientID, FoodID )<br />
WHERE FoodGroups.Description like '%LEGUME%'<br />
ORDER BY NutrientValue DESC<br />
LIMIT 100</code></p>
<a name="3)Top 150 iron containing foods"></a><h3>Top 150 iron containing foods</h3>
<p><code>SELECT Foods.Description, concat( NutrientValue, Units ) AS Value<br />
FROM Foods<br />
JOIN NutrientDefinitions ON ( NutrientName like '%Iron%' )<br />
JOIN NutrientData<br />
USING ( NutrientID, FoodID )<br />
ORDER BY NutrientValue DESC<br />
LIMIT 150</code></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.red-stars.net/technology/programming/web/queryable-food-nutrition-database/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Message Hasher</title>
		<link>http://blog.red-stars.net/technology/software/message-hasher/</link>
		<comments>http://blog.red-stars.net/technology/software/message-hasher/#comments</comments>
		<pubDate>Tue, 06 Oct 2009 01:09:09 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.red-stars.net/?p=168</guid>
		<description><![CDATA[A small web-based message hasher, good for generating hashes of small amounts of text. No binary support yet, but it&#8217;s planned via file uploads!


	#hasherform {
		display: inline-block;
		width: 400px;
	}
	#hasherform .wide {
		width: 100%;
	}
	#hasherform form * {
		margin-top: 8px;
	}
	#hasherform textarea {
		height: 10em;
	}


Short Message Hasher

		Algorithm

				md2
	md4
	md5
	sha1
	sha256
	sha384
	sha512
	ripemd128
	ripemd160
	ripemd256
	ripemd320
	whirlpool
	tiger128,3
	tiger160,3
	tiger192,3
	tiger128,4
	tiger160,4
	tiger192,4
	snefru
	gost
	adler32
	crc32
	crc32b
	haval128,3
	haval160,3
	haval192,3
	haval224,3
	haval256,3
	haval128,4
	haval160,4
	haval192,4
	haval224,4
	haval256,4
	haval128,5
	haval160,5
	haval192,5
	haval224,5
	haval256,5
		

		Message
		
Return as raw data

	

]]></description>
			<content:encoded><![CDATA[<p>A small web-based message hasher, good for generating hashes of small amounts of text. No binary support yet, but it&#8217;s planned via file uploads!</p>
<p><span id="more-168"></span><br />
<style type="text/css">
	#hasherform {
		display: inline-block;
		width: 400px;
	}
	#hasherform .wide {
		width: 100%;
	}
	#hasherform form * {
		margin-top: 8px;
	}
	#hasherform textarea {
		height: 10em;
	}
</style>
<fieldset id="hasherform">
<legend>Short Message Hasher</legend>
<form method="get" target="/index.php">
		<label for="algorithm">Algorithm</label></p>
<select name="algorithm" class="wide" id="algorithm">
				<option value="md2">md2</option><br />
	<option value="md4">md4</option><br />
	<option value="md5">md5</option><br />
	<option value="sha1">sha1</option><br />
	<option value="sha256">sha256</option><br />
	<option value="sha384">sha384</option><br />
	<option value="sha512">sha512</option><br />
	<option value="ripemd128">ripemd128</option><br />
	<option value="ripemd160">ripemd160</option><br />
	<option value="ripemd256">ripemd256</option><br />
	<option value="ripemd320">ripemd320</option><br />
	<option value="whirlpool">whirlpool</option><br />
	<option value="tiger128,3">tiger128,3</option><br />
	<option value="tiger160,3">tiger160,3</option><br />
	<option value="tiger192,3">tiger192,3</option><br />
	<option value="tiger128,4">tiger128,4</option><br />
	<option value="tiger160,4">tiger160,4</option><br />
	<option value="tiger192,4">tiger192,4</option><br />
	<option value="snefru">snefru</option><br />
	<option value="gost">gost</option><br />
	<option value="adler32">adler32</option><br />
	<option value="crc32">crc32</option><br />
	<option value="crc32b">crc32b</option><br />
	<option value="haval128,3">haval128,3</option><br />
	<option value="haval160,3">haval160,3</option><br />
	<option value="haval192,3">haval192,3</option><br />
	<option value="haval224,3">haval224,3</option><br />
	<option value="haval256,3">haval256,3</option><br />
	<option value="haval128,4">haval128,4</option><br />
	<option value="haval160,4">haval160,4</option><br />
	<option value="haval192,4">haval192,4</option><br />
	<option value="haval224,4">haval224,4</option><br />
	<option value="haval256,4">haval256,4</option><br />
	<option value="haval128,5">haval128,5</option><br />
	<option value="haval160,5">haval160,5</option><br />
	<option value="haval192,5">haval192,5</option><br />
	<option value="haval224,5">haval224,5</option><br />
	<option value="haval256,5">haval256,5</option><br />
		</select>
<p>
		<label for="message">Message</label><br />
		<textarea name="data" class="wide" id="message"></textarea></p>
<input type="checkbox" name="raw" id="rawcheckbox" /><label for="rawcheckbox">Return as raw data</label></p>
<input type="submit" value="Hash!" />
	</form>
</fieldset>
]]></content:encoded>
			<wfw:commentRss>http://blog.red-stars.net/technology/software/message-hasher/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GraphicsPath Front &#8211; Vector drawing software</title>
		<link>http://blog.red-stars.net/technology/program/graphicspath-front-vector-drawing-software/</link>
		<comments>http://blog.red-stars.net/technology/program/graphicspath-front-vector-drawing-software/#comments</comments>
		<pubDate>Wed, 19 Aug 2009 02:12:49 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Program]]></category>

		<guid isPermaLink="false">http://blog.red-stars.net/?p=154</guid>
		<description><![CDATA[GraphicsPath Front is vector drawing software based upon the GraphicsPath .net class.
Download (source and binaries) &#8212; Execute \bin\debug\GraphicsPathFront.exe or compile from source.
Some of the notable features include:

Save/load vectorized graphics, or save in numerous rasterized formats.
Configurable and snap-to&#8217;able grid.
Live preview of what&#8217;s being drawn, including rendering in real-time.
The ability to render as mouse input. (Need to [...]]]></description>
			<content:encoded><![CDATA[</li></li><p><img src="http://red-stars.net/pictures/graphicspathfront.png" alt="screenshot" /></p>
<p>GraphicsPath Front is vector drawing software based upon the GraphicsPath .net class.</p>
<p><a href="http://red-stars.net/programs/GraphicsPathFront.zip">Download</a> (source and binaries) &mdash; Execute <code>\bin\debug\GraphicsPathFront.exe</code> or compile from source.</p>
<p>Some of the notable features include:</p>
<ul>
<li>Save/load vectorized graphics, or save in numerous rasterized formats.</li>
<li>Configurable and snap-to&#8217;able grid.</li>
<li>Live preview of what&#8217;s being drawn, including rendering in real-time.</li>
<li>The ability to render as mouse input. (Need to see the videos to understand!)
<ul>
<li><a href="http://red-stars.net/pictures/renderingfont.avi">Rendering an elaborate font as mouse input to Microsoft Paint.</a></li>
<li><a href="http://red-stars.net/pictures/renderingcard.avi">Rendering a vectorized playing card as mouse input to Microsoft Paint.</a></li>
</li>
</ul>
</ul>
<p>There are several limitations in this program due to the limits of the underlying GraphicsPath class. Though the code is in place to do so, nodes can not be directly edited once created, for example. Nor can different paths be drawn using different pens.</p>
<p><span id="more-154"></span><div class="toc"><h2>Contents</h2><ol>
<li><a href="#3)DrawingGrid class">DrawingGrid class</a>
<li><a href="#3)DrawingTools class">DrawingTools class</a>
</ol>
</ol>
</ol>
</div></p>
<p>Below are some samples of the code from the project. Note that some of the limitations of the code highlighting plugin are apparent in generics being passed as generic types, and with XML comments.</p>
<a name="3)DrawingGrid class"></a><h3>DrawingGrid class</h3>
<p>The class which manages the drawing of and mouse handling for the grid.</p>
<pre class="brush:csharp">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace CrayonAutomaton {
    /// <summary>
    /// Create a GraphicsPath based grid in memory.
    /// </summary>
    class DrawingGrid {
        /// <summary>An event that is triggered when ever the grid is regenerated and needs to be redisplayed.</summary>
        public event Action GridUpdated;

        /// <summary>Gets or Sets the total area of the grid.</summary>
        public Size GridSize {
            get { return _gridSize; }
            set {
                _gridSize = value;
                makeGrid();
            }
        }
        /// <summary>Gets or Sets the size of each grid cell.</summary>
        public Size CellSize {
            get { return _cellSize; }
            set {
                _cellSize = value;
                makeGrid();
            }
        }
        /// <summary>Gets or Sets the color of the drawn grid.</summary>
        public Color GridColor {
            get { return _gridColor; }
            set {
                _gridColor = value;
                makeGrid();
            }
        }
        /// <summary>Gets the grid vector</summary>
        public GraphicsPath Grid { get { return path; } }
        /// <summary>Gets or Sets if 'GridPositionFromPoint()' snaps passed Point to the grid.</summary>
        public bool SnapPointsToGrid { get; set; }
        /// <summary>Gets or Sets if grid is drawn when asked to</summary>
        public bool Visible {
            get { return _visible; }
            set {
                _visible = value;
                if (GridUpdated != null)
                    GridUpdated();
            }
        }

        private Size _gridSize;
        private Size _cellSize;
        private Color _gridColor;
        private bool _visible;
        private bool noRendering = false;
        private GraphicsPath path = new GraphicsPath();

        public DrawingGrid(Size gridSize) : this(gridSize, new Size(20, 20), Color.LightGray, true) { }
        public DrawingGrid(Size gridSize, Size cellSize) : this(gridSize, cellSize, Color.LightGray, true) { }
        public DrawingGrid(Size gridSize, Size cellSize, Color gridColor) : this(gridSize, cellSize, gridColor, true) { }
        /// <summary>Creates an instance of a class for drawing a grid on an image</summary>
        ///
<param name="gridSize">Total area of grid to draw</param>
        ///
<param name="cellSize">Size of each cell to draw</param>
        ///
<param name="gridColor">Color to draw the grid</param>
        ///
<param name="snapPointsToGrid">Determins if 'GridPositionFromPoint()' snaps passed Point to the grid.</param>
        public DrawingGrid(Size gridSize, Size cellSize, Color gridColor, bool snapPointsToGrid) {
            BeginUpdate();
            GridSize = gridSize;
            CellSize = cellSize;
            GridColor = gridColor;
            SnapPointsToGrid = snapPointsToGrid;
            Visible = true;
            EndUpdate();
        }

        /// <summary>'Snaps' the passed point to grid, returns as-is if snapping to grid is disabled.</summary>
        public Point GridPositionFromPoint(Point point) {
            if (!SnapPointsToGrid)
                return point;
            Point gridPoint = new Point();
            gridPoint.X = (int)Math.Floor((decimal)(point.X / CellSize.Width)) * CellSize.Width;
            gridPoint.Y = (int)Math.Floor((decimal)(point.Y / CellSize.Height)) * CellSize.Height;
            if (point.X % CellSize.Width > CellSize.Width / 2)
                gridPoint.X += CellSize.Width;
            if (point.Y % CellSize.Height > CellSize.Height / 2)
                gridPoint.Y += CellSize.Height;
            return gridPoint;
        }
        /// <summary>Draws grid to Graphic 'g' if Visible, regenerates grid if 'size' is different</summary>
        public void DrawToGraphic(Graphics g, Size size) {
            if (Visible) {
                if (size != GridSize)
                    GridSize = size;
                g.DrawPath(new Pen(GridColor), Grid);
            }
        }
        /// <summary>Draws grid to Graphic 'g' if Visible</summary>
        public void DrawToGraphic(Graphics g) {
            if (Visible)
                g.DrawPath(new Pen(GridColor), Grid);
        }
        /// <summary>Prevents (costly) regeneration of grid during property changes.</summary>
        public void BeginUpdate() { noRendering = true; }
        /// <summary>Allows grid to be regenerated by property changes again, also regenerates grid.</summary>
        public void EndUpdate() {
            noRendering = false;
            makeGrid();
        }

        /// <summary>(Re)render the grid to the 'path' variable.</summary>
        private void makeGrid() {
            /* Do not render if durring an 'update' */
            if (noRendering)
                return;

            int cellX = CellSize.Width;
            int cellY = CellSize.Height;

            /* Clear old grid */
            path.Reset();

            /* Add vertical lines (columes) */
            do {
                path.StartFigure();
                path.AddLine(cellX, 0, cellX, GridSize.Height);
            } while ((cellX += CellSize.Width) < GridSize.Width);

            /* Add horizontal lines (rows) */
            do {
                path.StartFigure();
                path.AddLine(0, cellY, GridSize.Width, cellY);
            } while ((cellY += CellSize.Height) < GridSize.Height);

            /* Call all grid updated events */
            if (GridUpdated != null)
                GridUpdated();
        }
    }
}</pre>
<a name="3)DrawingTools class"></a><h3>DrawingTools class</h3>
<p>A collection of drawing tools and an abstract class and event driven drawing tool system.</p>
<pre class="brush:csharp">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace CrayonAutomaton {
    /// <summary>A collection of DrawingTool</summary>
    class DrawingTools {
        /// <summary>Event for when an update is required.</summary>
        public event Action PreviewUpdate;

        /// <summary>Gets or Sets the currently in-use drawing tool.</summary>
        public DrawingTool Tool { get; set; }
        /// <summary>A collection of DrawingTools</summary>
        public List<DrawingTool> Tools { get; set; }
        /// <summary>Functions which are called on the mouse input before the mouse data is used.</summary>
        public IEnumerable<Func<Point, Point>> MouseInputFilters {
            get { return _mouseInputFilters; }
            set {
                performToAllTools(delegate(DrawingTool tool) { tool.MouseInputFilters = value; });
                _mouseInputFilters = value;
            }
        }
        public GraphicsPath Path {
            get { return _path; }
            set {
                performToAllTools(delegate(DrawingTool tool) { tool.Path = value; });
                _path = value;
            }
        }

        private GraphicsPath _path;
        private IEnumerable<Func<Point, Point>> _mouseInputFilters;

        public DrawingTools(GraphicsPath path, Func<Point, Point> mouseInputFilter/*, Control hookToSurface*/)
            : this(path, new[] { mouseInputFilter }) { }
        /// <summary>Instances a usable collection of DrawingTool's</summary>
        ///
<param name="path">Path for the tools to draw to</param>
        public DrawingTools(GraphicsPath path, IEnumerable<Func<Point, Point>> mouseInputFilters/*, Control hookToSurface*/) {
            /* Instance all locally coded drawing tools */
            Tools = new List<DrawingTool>(new DrawingTool[] {
                new NullDrawingTool(),
                new LineDrawingTool(),
                new RectangleDrawingTool(),
                new EllipseDrawingTool(),
                new FreeDrawDrawingTool(),
                new TextDrawingTool()
            });

            /* Set-up all required members */
            performToAllTools(delegate(DrawingTool tool) { tool.ParentCollection = this; });
            Path = path;
            MouseInputFilters = mouseInputFilters;

            SetTool("");
        }

        public void Preview() {
            if (PreviewUpdate != null)
                PreviewUpdate();
        }
        public void HookToolsToSurface(Control surface) {

        }

        public bool SetTool(DrawingTool tool) { return SetTool(tool.Name); }
        /// <summary>Changes the in-use tool based upon 'name'</summary>
        /// <returns>Returns 'true' if a tool is found and set, 'false' otherwise.</returns>
        public bool SetTool(string name) {
            foreach (DrawingTool curTool in Tools)
                if (curTool.Name == name) {
                    Tool = curTool;
                    return true;
                }
            return false;
        }

        private void performToAllTools(Action<DrawingTool> delegateFunction) {
            foreach (DrawingTool curTool in Tools)
                delegateFunction(curTool);
        }
    }

    abstract class DrawingTool : IEquatable<DrawingTool> {
        /// <summary>Get the tools name</summary>
        public string Name { get { return _name; } }
        /// <summary>A value indicating if the mouse is presently inside the drawing area</summary>
        public bool IsMouseInside { get; set; }
        public GraphicsPath Path { get; set; }
        public IEnumerable<Func<Point, Point>> MouseInputFilters { get; set; }
        public MouseButtons MouseButtonState { get; set; }
        public DrawingTools ParentCollection { get; set; }

        private string _name;

        protected Point mouseDownLocation;

        /// <summary>Abstract class for drawing tools</summary>
        ///
<param name="name">Name of the drawing tool, must be unique</param>
        protected DrawingTool(string name) {
            _name = name;
            IsMouseInside = false;
        }

        /// <summary>Call to pass the mouse down event to the in-use tool.</summary>
        public void MouseDown(Point point) {
            point = filterMouseInput(point);
            mouseDownLocation = point;
            mouseDown(point);
        }
        /// <summary>Call to pass the mouse move event to the in-use tool.</summary>
        public void MouseMove(Point point) {
            point = filterMouseInput(point);
            mouseMove(point);
        }
        /// <summary>Call to pass the mouse up event to the in-use tool.</summary>
        public void MouseUp(Point point) {
            point = filterMouseInput(point);
            mouseUp(point);
        }
        public void MouseLeave() {
            IsMouseInside = false;
            mouseLeave();
        }
        public void MouseEnter() {
            IsMouseInside = true;
            mouseEnter();
        }
        public void Render(Point currentMouseLocation) { Render(Path, currentMouseLocation); }
        public void Render(GraphicsPath path, Point currentMouseLocation) {
            render(path, filterMouseInput(currentMouseLocation));
        }

        protected virtual void mouseMove(Point point) {}
        protected virtual void mouseUp(Point point) { }

        /// <summary>This function should be override if it's possible to render with mouseDownLocation and the currentMouseLocation.
        /// If this function is not overloaded, drawing is still possible, but preview rendering is not.</summary>
        protected virtual void render(GraphicsPath path, Point currentMouseLocation) { }
        /// <summary>Override if mouse down detection is needed</summary>
        protected virtual void mouseDown(Point point) { }
        /// <summary>Override if mouse enter detection is needed</summary>
        protected virtual void mouseEnter() { }
        /// <summary>Override if mouse up detection is needed</summary>
        protected virtual void mouseLeave() { }

        /// <summary>Returns passed point as processed by the list of provided filters in MouseFilterList</summary>
        protected Point filterMouseInput(Point point) {
            foreach (Func<Point, Point> curFilter in MouseInputFilters)
                point = curFilter(point);
            return point;
        }
        /// <summary>Reorders the passed points so that point1 is to the upper left of point2</summary>
        /// <returns>Returns the distance between refactored point1 and point2</returns>
        protected Size orderPoints(ref Point point1, ref Point point2) {
            point1.X = Math.Min(point1.X, point2.X);
            point1.Y = Math.Min(point1.Y, point2.Y);
            point2.X = Math.Max(point1.X, point2.X);
            point2.Y = Math.Max(point1.Y, point2.Y);
            return new Size(point2.X - point1.X, point2.Y - point1.Y);
        }
        /// <summary>Returns a rectangle from where MouseDown and mouseUpPoint occured</summary>
        protected Rectangle mouseDragRectangle(Point mouseUpPoint) {
            return new Rectangle(mouseDownLocation, orderPoints(ref mouseDownLocation, ref mouseUpPoint));
        }

        public override string ToString() { return Name; }
        public bool Equals(DrawingTool obj) { return obj.GetHashCode() == GetHashCode(); }
        public override int GetHashCode() { return Name.GetHashCode(); }
    }

    /// <summary>A base level null drawing tool for default tool selection</summary>
    class NullDrawingTool : DrawingTool {
        public NullDrawingTool()
            : base(string.Empty) { }
    }

    /// <summary>A DrawingTool for drawing single lines</summary>
    class LineDrawingTool : DrawingTool {
        public LineDrawingTool()
            : base("Line") { }

        protected override void render(GraphicsPath path, Point currentMouseLocation) {
            path.AddLine(mouseDownLocation, currentMouseLocation);
        }

        protected override void mouseUp(Point point) {
            Render(point);
        }
    }

    /// <summary>A DrawingTool for drawing single rectangles</summary>
    class RectangleDrawingTool : DrawingTool {
        public RectangleDrawingTool()
            : base("Rectangle") { }

        protected override void render(GraphicsPath path, Point currentMouseLocation) {
            path.AddRectangle(mouseDragRectangle(currentMouseLocation));
        }

        protected override void mouseUp(Point point) {
            Render(point);
        }
    }

    /// <summary>A DrawingTool for drawing single ellipses</summary>
    class EllipseDrawingTool : DrawingTool {
        public EllipseDrawingTool()
            : base("Ellipse") { }

        protected override void render(GraphicsPath path, Point currentMouseLocation) {
            path.AddEllipse(mouseDragRectangle(currentMouseLocation));
        }

        protected override void mouseUp(Point point) {
            Render(point);
        }
    }

    /// <summary>A DrawingTool for 'free hand' drawing</summary>
    class FreeDrawDrawingTool : DrawingTool {
        Point lastPoint;

        public FreeDrawDrawingTool()
            : base("Free Draw") { }
        protected override void mouseDown(Point point) {
            lastPoint = point;
        }
        protected override void mouseMove(Point point) {
            if (MouseButtonState == MouseButtons.Left) {
                drawLine(point);
                lastPoint = point;
            }
        }
        protected override void mouseUp(Point point) {
            drawLine(point);
        }

        private void drawLine(Point point) {
            Path.AddLine(lastPoint, point);
        }
    }

    class TextDrawingTool : DrawingTool {
        public TextDrawingTool()
            : base("Text") { }

        enterTextDialog textDialog;

        protected override void mouseUp(Point point) {
            textDialog = new enterTextDialog(ParentCollection.Preview);
            if (textDialog.ShowDialog() == DialogResult.OK)
                render(Path, point);
        }

        void textDialog_PreviewUpdateEvent() {
        }

        protected override void render(GraphicsPath path, Point currentMouseLocation) {
            path.AddString(textDialog.EnteredText,
                textDialog.SelectedFont.FontFamily,
                (int)textDialog.SelectedFont.Style,
                textDialog.SelectedFont.Size,
                mouseDownLocation,
                StringFormat.GenericDefault);
        }
    }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.red-stars.net/technology/program/graphicspath-front-vector-drawing-software/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://red-stars.net/pictures/renderingfont.avi" length="1108164" type="video/x-msvideo" />
<enclosure url="http://red-stars.net/pictures/renderingcard.avi" length="216944" type="video/x-msvideo" />
		</item>
		<item>
		<title>Boggle.exe</title>
		<link>http://blog.red-stars.net/technology/program/boggle-exe/</link>
		<comments>http://blog.red-stars.net/technology/program/boggle-exe/#comments</comments>
		<pubDate>Wed, 19 Aug 2009 01:54:28 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Program]]></category>

		<guid isPermaLink="false">http://blog.red-stars.net/?p=150</guid>
		<description><![CDATA[Boggle.exe is a computerized version of the Hasbro dice game. It&#8217;s intended to be played by multiple people infront of the computer using pens and paper, no internet play is supported as it&#8217;s ridiculously easy to cheat. The main neat feature of Boggle.exe over it&#8217;s physical counterpart is a board solver. Once the game is [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://red-stars.net/pictures/boggle.png" alt="screenshot" /></p>
<p><em>Boggle.exe</em> is a computerized version of the Hasbro dice game. It&#8217;s intended to be played by multiple people infront of the computer using pens and paper, no internet play is supported as it&#8217;s ridiculously easy to cheat. The main neat feature of Boggle.exe over it&#8217;s physical counterpart is a board solver. Once the game is over, all of the valid words inside of the board are shown and can be highlighted (see picture).</p>
<p><a href="http://red-stars.net/programs/Boggle.zip">Download</a> (source and executable) &mdash; Extract to it&#8217;s own directory and run <code>\bin\debug\Boggle.exe</code>. words.txt must be in the same directory as the executable.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.red-stars.net/technology/program/boggle-exe/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Installing Windows 7 from and to the same hard drive</title>
		<link>http://blog.red-stars.net/technology/software/installing-windows-7-from-and-to-the-same-hard-drive/</link>
		<comments>http://blog.red-stars.net/technology/software/installing-windows-7-from-and-to-the-same-hard-drive/#comments</comments>
		<pubDate>Tue, 18 Aug 2009 01:25:42 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://red-stars.net/wordpress/?p=105</guid>
		<description><![CDATA[The reason why is pretty simple, DVDs are not remotely as fast as any other media, and in 2009, it&#8217;s starting to show. Flash drives are larger, faster, and more versatile than DVDs, and they&#8217;re costing less and less. But what about an older system that can not boot from USB storage? Well, there is [...]]]></description>
			<content:encoded><![CDATA[</li></li><p>The reason why is pretty simple, DVDs are not remotely as fast as any other media, and in 2009, it&#8217;s starting to show. Flash drives are larger, faster, and more versatile than DVDs, and they&#8217;re costing less and less. But what about an older system that can not boot from USB storage? Well, there is an option, and that&#8217;s to use the destination drive as the source. Install the drive into a separate computer (via a usb dongle is fine) and follow these steps. Note that these directions work if you&#8217;re trying to make a bootable USB flash drive, too.</p>
<p><span id="more-105"></span><div class="toc"><h2>Contents</h2><ol>
<li><a href="#3)Making partitions and setting the drive as active">Making partitions and setting the drive as active</a>
<li><a href="#3)Installing the boot loader">Installing the boot loader</a>
</ol>
</ol>
</ol>
</div></p>
<p>First on a different system you should remove all existing partitions and create new ones (optional), then set the partition as active, give it a boot loader, then give it the installation files.</p>
<a name="3)Making partitions and setting the drive as active"></a><h3>Making partitions and setting the drive as active</h3>
<p>First execute <code>diskpart.exe</code> from inside of a console. You&#8217;ll need to determine which drive is the hard drive you intend to do this to. Type in <code>list disk</code>. From now on, the drive number will be referred to as <em>n</em>.</p>
<p><code>select disk <em>n</em><br />
clean<br />
create partition primary<br />
select partition 1<br />
active<br />
format fs=NTFS quick<br />
assign<br />
exit</code></p>
<p><code>clean</code> will remove all existing partitions, then the partition is made and selected, <code>active</code> will mark is at an active partition which signals a bootloader to use this partition, the partition is then formatted, and mounted. Determine the drive letter assigned to the partition, this will be referred to as <em>m</em>.</p>
<a name="3)Installing the boot loader"></a><h3>Installing the boot loader</h3>
<p>Using the <code>bootsect.exe</code> executable found in the <code>\boot\</code> directory of your Vista or Windows 7 DVD, install <b>Windows Boot Manager</b> (BOOTMGR) onto the drive using <code>bootsect.exe /nt60 <em>m:</em></code> . I can confirm that using a 32 bit executable to make a 64 bit installer does work, and vice versa.</p>
<p>That&#8217;s it! You&#8217;re all done! Boot from the drive and the installer will run.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.red-stars.net/technology/software/installing-windows-7-from-and-to-the-same-hard-drive/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Replacing an Inspiron 1525 LCD video</title>
		<link>http://blog.red-stars.net/technology/computer-repair/replacing-an-inspiron-1525-lcd-video/</link>
		<comments>http://blog.red-stars.net/technology/computer-repair/replacing-an-inspiron-1525-lcd-video/#comments</comments>
		<pubDate>Sun, 16 Aug 2009 16:46:27 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Computer Repair]]></category>

		<guid isPermaLink="false">http://red-stars.net/wordpress/?p=101</guid>
		<description><![CDATA[Simple step by step guide to replacing the LCD on a Dell Inspiron 1525 laptop.


Check out the source code that went into making this video! It uses AviSynth scripting to speed up small sections.
video = DirectShowSource("MVI_0480.AVI")
fps = 20
speedfactor = 4
return video.Trim(0,2300) ++ \
	video.Trim(2300,3250).AssumeFPS(fps*speedfactor).ChangeFPS(fps) ++ \
	video.Trim(3251,5999) ++ \
	video.Trim(6000, 6300).AssumeFPS(fps*speedfactor).ChangeFPS(fps) ++ \
	video.Trim(6301,9599) ++ \
	video.Trim(9600, 11300).AssumeFPS(fps*speedfactor).ChangeFPS(fps) ++ \
	video.Trim(11301,0)
]]></description>
			<content:encoded><![CDATA[<p>Simple step by step guide to replacing the LCD on a Dell Inspiron 1525 laptop.</p>
<p><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/56e3fSk_XdM&#038;hl=en&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/56e3fSk_XdM&#038;hl=en&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></p>
<p><span id="more-101"></span></p>
<p>Check out the source code that went into making this video! It uses AviSynth scripting to speed up small sections.<br />
<code>video = DirectShowSource("MVI_0480.AVI")</p>
<p>fps = 20<br />
speedfactor = 4</p>
<p>return video.Trim(0,2300) ++ \<br />
	video.Trim(2300,3250).AssumeFPS(fps*speedfactor).ChangeFPS(fps) ++ \<br />
	video.Trim(3251,5999) ++ \<br />
	video.Trim(6000, 6300).AssumeFPS(fps*speedfactor).ChangeFPS(fps) ++ \<br />
	video.Trim(6301,9599) ++ \<br />
	video.Trim(9600, 11300).AssumeFPS(fps*speedfactor).ChangeFPS(fps) ++ \<br />
	video.Trim(11301,0)</code></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.red-stars.net/technology/computer-repair/replacing-an-inspiron-1525-lcd-video/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Hacking Windows XP PowerToy Calculator to run in Vista</title>
		<link>http://blog.red-stars.net/technology/software/hacking-windows-xp-powertoy-calculator-to-run-in-vista/</link>
		<comments>http://blog.red-stars.net/technology/software/hacking-windows-xp-powertoy-calculator-to-run-in-vista/#comments</comments>
		<pubDate>Wed, 22 Jul 2009 19:29:05 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://red-stars.net/wordpress/?p=74</guid>
		<description><![CDATA[How far would you go to use your favorite calculator? If the answer isn't a 75mb trace log, than you fail.]]></description>
			<content:encoded><![CDATA[</li></li><p>This was more of a project than I was originally expecting, Microsoft prevents the Windows XP Powertoy Calculator from running in Vista in 2 separate places, but in the end, it runs perfectly in Vista, all the limitations are false. <em>(Edit: I can confirm that this hacked copy works in Windows 7, too!)</em></p>
<p>Don&#8217;t feel like doing this yourself? <a href="http://red-stars.net/random/PowerCalc.exe">No need!</a> <img src='http://blog.red-stars.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><span id="more-74"></span><div class="toc"><h2>Contents</h2><ol>
<li><a href="#3)Part 1: The Installer">Part 1: The Installer</a>
<li><a href="#3)Part 2: Oh... no...">Part 2: Oh... no...</a>
</ol>
</ol>
</ol>
</div></p>
<a name="3)Part 1: The Installer"></a><h3>Part 1: The Installer</h3>
<p><img src="http://red-stars.net/pictures/powercalc/01-cant_install.png" /><br />
When running <code>PowerCalcPowertoySetup.exe</code>, it complained that I&#8217;m not on Windows XP. Fair enough, but is that really important?</p>
<p>The exe installer dumped the MSI file at <code>C:\Windows\Downloaded Installations\Calculator Powertoy for Windows XP.msi</code> which I ran <a href="http://dennisbareis.com/msidiff.htm">MsiDiff</a> on to dump the MSI script. This gave me <code>Calculator Powertoy for Windows XP.msi.MmDumpTxt</code> which I searched for the above error in.</p>
<pre class="brush:plain"><$Row
	Condition="VersionNT = 501"
	Description="The powertoys require Windows XP or a service pack. They will not function on a version of Windows earlier or later than Windows XP."
></pre>
<p>Perfect. 501 is the Windows XP kernel version. Lets change that to the Vista kernal version in the MSI&#8230;<br />
<img src="http://red-stars.net/pictures/powercalc/02-hex.png" /></p>
<p><img src="http://red-stars.net/pictures/powercalc/03-installer.png" /><br />
Sweet! It worked!</p>
<a name="3)Part 2: Oh&#8230; no&#8230;"></a><h3>Part 2: Oh&#8230; no&#8230;</h3>
<p>Running <code>PowerCalc.exe</code> causes it to exit before ever giving us a GUI. Lets do a trace in <a href="http://www.ollydbg.de/">OllyDbg</a> and see what we can figure out.</p>
<pre class="brush:plain">01018405	Main	JE SHORT PowerCal.0101840C
0101840C	Main	TEST BYTE PTR SS:[EBP-30],1
01018410	Main	JE SHORT PowerCal.01018423
01018412	Main	MOVZX ECX,WORD PTR SS:[EBP-2C]	ECX=0000000A
01018416	Main	JMP SHORT PowerCal.01018426
01018426	Main	PUSH ECX	Arg4 = 0000000A
01018427	Main	PUSH EAX	Arg3 = 001E1F33
01018428	Main	PUSH EBX	Arg2 = 00000000
01018429	Main	PUSH PowerCal.01000000	Arg1 = 01000000
0101842E	Main	CALL PowerCal.01001FD3	EAX=00000000, ECX=D73F2C3E, EDX=7F68081A
01018433	Main	MOV ESI,EAX
01018435	Main	MOV DWORD PTR SS:[EBP-7C],ESI
01018438	Main	CMP DWORD PTR SS:[EBP-60],EBX
0101843B	Main	JNZ SHORT PowerCal.01018444
0101843D	Main	PUSH ESI	status = 0
0101843E	Main	CALL DWORD PTR DS:[<&#038;msvcrt.exit>]	ECX=0006FE28, EDX=00000000, EBP=0006FE84, ESI=00000001, EDI=00831BF0
    Process terminated, exit code 0</pre>
<p>The bottom of the trace-over  isn&#8217;t telling us much. Lets check out some of these offsets in <a href="http://www.hex-rays.com/idapro/">IDA Pro</a> and see what we can come up with.</p>
<p><img src="http://red-stars.net/pictures/powercalc/04-ida_lower.png" /><br />
All the stuff around <code>0101843B</code> seems to exit the program, and none of these other offsets get us anywhere&#8230; lets run a trace-into and see what we get.</p>
<p>Aside from a 75mb text file, we get: (search from the bottom up for our programs address space! There&#8217;s a lot of external code in there!).</p>
<pre class="brush:plain">010180E3	Main	RETN
01001FD1	Main	LEAVE	EBP=0006FEE4
01001FD2	Main	RETN
01001FDF	Main	TEST EAX,EAX
01001FE1	Main	JE PowerCal.010020A0
010020A0	Main	XOR EAX,EAX
010020A2	Main	POP ESI
010020A3	Main	LEAVE	EBP=0006FF88
010020A4	Main	RETN 10
01018433	Main	MOV ESI,EAX
01018435	Main	MOV DWORD PTR SS:[EBP-7C],ESI
01018438	Main	CMP DWORD PTR SS:[EBP-60],EBX
0101843B	Main	JNZ SHORT PowerCal.01018444
0101843D	Main	PUSH ESI	status = 0
0101843E	Main	CALL DWORD PTR DS:[<&#038;msvcrt.exit>]
exit	Main	MOV EDI,EDI</pre>
<p>Now we&#8217;re talking! It looks like a function returns and then the program exits. Lets check out the call to that function.<br />
<img src="http://red-stars.net/pictures/powercalc/05-function_call.png" /></p>
<p>One path goes to the exit, the other&#8230; doesn&#8217;t! Lets check out <code>sub_1001F60</code> to see what it does&#8230;<br />
<br /><img src="http://red-stars.net/pictures/powercalc/06-evil_version_check.png" /><br />
It&#8217;s our evil Windows Version Checking function!</p>
<p>In OllyDbg lets goto the <code>jz loc_10020A0</code> after the function call, right click, and goto &#8220;nop&#8221; and press run. This causes the program to <em>always</em> follow the non-exiting code path.<br />
<img src="http://red-stars.net/pictures/powercalc/07-noping.png" /></p>
<p><img src="http://red-stars.net/pictures/powercalc/08-success.png" /><br />
Success!</p>
<p><img src="http://red-stars.net/pictures/powercalc/09-hex.png" /><br />
Lets hex edit that into the executable so it&#8217;s like this all the time.</p>
<p>We can now use our calculator!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.red-stars.net/technology/software/hacking-windows-xp-powertoy-calculator-to-run-in-vista/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Process Monitor and other tools to fix a broken installation.</title>
		<link>http://blog.red-stars.net/technology/software/using-process-monitor-and-other-tools-to-fix-a-broken-installation/</link>
		<comments>http://blog.red-stars.net/technology/software/using-process-monitor-and-other-tools-to-fix-a-broken-installation/#comments</comments>
		<pubDate>Wed, 22 Jul 2009 16:30:27 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://red-stars.net/wordpress/?p=67</guid>
		<description><![CDATA[Sometimes things break, sometimes the only way to fix them breaks, sometimes you need to use kernel hooks to fix your favorite toy.]]></description>
			<content:encoded><![CDATA[<p>Today the stars were aligned and my VMWare installation decided to stop working. It&#8217;s time for an upgrade, anyways.</p>
<p><img src="http://red-stars.net/pictures/vmwarefix/01-cannot_install.png" /><br />
Oh, that makes sense. So lets uninstall the old version.</p>
<p><img src="http://red-stars.net/pictures/vmwarefix/02-cannot_uninstall.png" /><br />
Can&#8217;t install the new, can&#8217;t uninstall the old. Time for some hackery!</p>
<p><span id="more-67"></span><div class="toc"><h2>Contents</h2><ol>
</ol>
</div></p>
<p>First lets find out the name of the culprit installer with <a href="http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx">Process Explorer</a>&#8217;s find tool, then in <a href="http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx">Process Monitor</a> lets setup a filter to this executable.<br />
<img src="http://red-stars.net/pictures/vmwarefix/03-01-setup_filter.png" /><br />Re-running the installer lets us see what it&#8217;s accessing. Using that we can find out what makes it think it&#8217;s installed so we can trick it into thinking it&#8217;s doing a fresh install. Once the error screen comes up, unattach the event monitor in Process Monitor (control+e).</p>
<p><img src="http://red-stars.net/pictures/vmwarefix/03-finding_traces.png" /><br />
This looks interesting. It&#8217;s the registry key used by Window&#8217;s Add/Remove Programs.</p>
<p><img src="http://red-stars.net/pictures/vmwarefix/04-renaming_installer_class.png" /><br />
Lets rename it to prevent the installer from seeing it then re-run the installer. Hmm&#8230; Semi-success. The installer now gives us the same error, but in a different place, so lets re-Process Monitor the installer.<br />
<img src="http://red-stars.net/pictures/vmwarefix/05-finding_more_traces.png" /><br />
Well! This looks very interesting! Lets rename this one as well&#8230;<br />
<img src="http://red-stars.net/pictures/vmwarefix/06-renaming.png" /></p>
<p>Hey! It&#8217;s installing!</p>
<p>Finally, time to get back to work.<br />
<img src="http://red-stars.net/pictures/vmwarefix/07-dll_error.png" /><br />
Crap!</p>
<p>A DLL did not get replaced during the installation and a version mis-match is causing problems (why put the version number in the filename and not update it?). After a harddrive-wide search, I found sigc-2.0.dll in <code>C:\Program Files\VMware\VMware Workstation</code>. Good news is the installer has all of the installation files out in the open, so no need to dump cabs or hack the msi. I replaced copy in the Program Files directory with the one from the installer&#8217;s directory and&#8230;<br />
<img src="http://red-stars.net/pictures/vmwarefix/08-working.png" /><br />
Success!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.red-stars.net/technology/software/using-process-monitor-and-other-tools-to-fix-a-broken-installation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Creating a Google Page Rank Finder in Javascript</title>
		<link>http://blog.red-stars.net/technology/programming/web/creating-a-google-page-rank-finder-in-javascript/</link>
		<comments>http://blog.red-stars.net/technology/programming/web/creating-a-google-page-rank-finder-in-javascript/#comments</comments>
		<pubDate>Wed, 22 Jul 2009 14:06:28 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://red-stars.net/wordpress/?p=63</guid>
		<description><![CDATA[The google.search.WebSearch API quickly explained, also quickly complained about. It's fast, powerful, and well done, but Google gypped us on functionality.]]></description>
			<content:encoded><![CDATA[</li><p>An interesting technology are Google Page Rank Finders. What they do is discover which result and page number a website is in Google&#8217;s search results for a given term.</p>
<p>I thought an interesting implementation would be a completely client side one written in Javascript using Google&#8217;s search API. To spoil the ending, after creating this I discovered the API only allows 8 results per page and 8 pages, making this useless if the site is beyond the 64th result, but the API is interesting and powerful regardless.</p>
<p>The finished version can be found at <a href="http://pagerank.red-stars.net/">pagerank.red-stars.net</a> with the complete <a href="http://pagerank.red-stars.net/pagerank.js">Javascript</a>.</p>
<p><span id="more-63"></span><div class="toc"><h2>Contents</h2><ol>
<li><a href="#3)google.search.WebSearch() object">google.search.WebSearch() object</a>
</ol>
</ol>
</ol>
</div></p>
<a name="3)google.search.WebSearch() object"></a><h3>google.search.WebSearch() object</h3>
<p>The WebSearch() object is relatively simple, once instanced, all it needs is a call back to be setup before it can be used.</p>
<pre class="brush:javascript">var webSearch = new google.search.WebSearch();
webSearch.setSearchCompleteCallback(this, searchComplete, null);
webSearch.execute("cookies");</pre>
<p>The function searchComplete() will be called when the search for &#8220;cookies&#8221; completes. It&#8217;s important that our instance of WebSearch named webSearch is inside of a scope which is viewable from searchComplete() because the callback is argumentless.
<pre class="brush:javascript">function searchComplete() {
	// Make sure that there are results.
	if (webSearch.results &#038;&#038; webSearch.results.length > 0) {
		var results = webSearch.results;
		// Go through every result.
		for (var resultIndex = 0; resultIndex < results.length; resultIndex++) {
			var result = results[resultIndex];
			// Show a messagebox with the results information.
			alert(result.html.innerHTML);
		}
	}
}</pre>
<p>We used the .html property from the result which gives us a Google-looking result. Now what if we wanted more than just the first page?</p>
<pre class="brush:javascript">var currentPageIndex = 0;
function searchComplete() {
	// Make sure that there are results.
	if (webSearch.results &#038;&#038; webSearch.results.length > 0) {
		currentPageIndex++;
		var results = webSearch.results;
		// Go through every result.
		for (var resultIndex = 0; resultIndex < results.length; resultIndex++) {
			var result = results[resultIndex];
			// Show a messagebox with the results information.
			alert(result.html.innerHTML);
		}

		// Check if another page exists, if so, perform the request.
		if (currentPageIndex < webSearch.cursor.pages.length)
			webSearch.gotoPage(currentPageIndex);
	}
}</pre>
<p>The <code>cursor</code> object contains an array called pages who's length is used to determine the number of pages available. This will go through all available search results. When <code>gotoPage</code> is called, our call back function is once again executed when the search is finished.</p>
<p>A complete reference to the WebSearch and associate classes <a href="http://code.google.com/apis/ajaxsearch/documentation/reference.html">is available on code.google.com</a>. The API is decent and flexible, if not limited in functionality.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.red-stars.net/technology/programming/web/creating-a-google-page-rank-finder-in-javascript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>System.Drawing.Drawing2D.PathPointType defined.</title>
		<link>http://blog.red-stars.net/technology/programming/csharp/system-drawing-drawing2d-pathpointtype-defined/</link>
		<comments>http://blog.red-stars.net/technology/programming/csharp/system-drawing-drawing2d-pathpointtype-defined/#comments</comments>
		<pubDate>Tue, 21 Jul 2009 19:07:57 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://red-stars.net/wordpress/?p=50</guid>
		<description><![CDATA[Microsoft's under-documented class getting it's rightful treatment.]]></description>
			<content:encoded><![CDATA[<p>I had a project which involved raw access to the data stored inside of a System.Drawing.Drawing2D.GraphicsPath and found that the <a title="MSDN Document" href="http://msdn.microsoft.com/en-us/library/3ch9cxht.aspxhttp://">MSDN Document</a> for PathPointType was rather lacking, but it&#8217;s not too complex.</p>
<p><span id="more-50"></span></p>
<p>Inside of GraphicsPath is a byte array called PathTypes that contains PathPointType and a PointF array called PathPoints (the same data is also stored in GraphicsPath.PathData.Points and GraphicsPath.PathData.Types). They relate to each other by index, so PathTypes[n] is the PathPointTypes for PathPoints[n].</p>
<p>The reason PathTypes is stored as bytes and not PathPointType is because multiple values will be contained per byte. To separate the two, you must use a bitwise AND operation of your value against the bit mask PathPointType.PathTypeMask. The resulting value is either Start, Line or Bezier (Bezier3 is equal to Bezier).</p>
<p>You can NOT modify these collections directly. Instead, you must make a new instance of GraphicsPaths and pass modified collections to them via the (PointF[], byte[]) constructor.</p>
<table style="width: 100%; border: 1px solid black;">
<caption>PathPointType values</caption>
<thead>
<tr>
<td><strong>PathPointType</strong></td>
<td><strong>Value</strong>
<td><strong>Description</strong></td>
</td>
</tr>
</thead>
<tbody>
<tr>
<td>Start</td>
<td style="text-align: right;">0</td>
<td>Start of graphics path. Move cursor then put pen down.</td>
</tr>
<tr>
<td>Line</td>
<td style="text-align: right;">1</td>
<td>Move pen to given location.</td>
</tr>
<tr>
<td>Bezier</td>
<td style="text-align: right;">3</td>
<td>Draw curve.</td>
</tr>
<tr>
<td>Bezier3</td>
<td style="text-align: right;">3</td>
<td><em>Equal to Bezier.</em></td>
</tr>
<tr>
<td>PathTypeMask</td>
<td style="text-align: right;">7</td>
<td>Mask for extracting types from PathTypes.</td>
</tr>
<tr>
<td>DashMode</td>
<td style="text-align: right;">16</td>
<td>Draw in dashes, not solid lines.</td>
</tr>
<tr>
<td>PathMarker</td>
<td style="text-align: right;">32</td>
<td>Lift pen, move pen to new location, then if the pen was down before, place back down.</td>
</tr>
<tr>
<td>CloseSubpath</td>
<td style="text-align: right;">128</td>
<td>Move mouse to point from the last Start (closing the path) then lift pen.</td>
</tr>
</tbody>
</table>
<p>Below is code which parses the PathTypes and PathPoints and causes actions in a class which renders the GraphicsPath as mouse output where the mouse is down when the pen should be down, and the mouse moves to the location the pen should be, etc. Please note this code renders Bezier curves as lines.</p>
<pre class="brush:csharp">int index=0;
PointF firstPoint = new PointF(); // Used to store the starting position so closed paths can reposition here.
// Loop through all path data
foreach (PointF point in Path.PathPoints) {
	byte curType = Path.PathTypes[index];
				// Extract the item type by the bit mask
	byte itemType = (byte)(curType &#038; (byte)PathPointType.PathTypeMask);

	// Draw the different object types
	if (itemType == (byte)PathPointType.Start) {
		firstPoint = point;
		input.MousePos(point);
		input.LeftButtonDown();
	} else if ((itemType == (byte)PathPointType.Line) || (itemType == (byte)PathPointType.Bezier) || (itemType == (byte)PathPointType.Bezier3))
		input.MousePos(point);

	// Handle all additional flags
	if (isType(curType, PathPointType.PathMarker)) {
		bool wasMouseDown = false;
		if (input.IsMouseDown) {
			wasMouseDown = true;
			input.LeftButtonUp();
		}
		input.MousePos(point);
		if (wasMouseDown)
			input.LeftButtonDown();
	}

	if (isType(curType, PathPointType.CloseSubpath)) {
		input.MousePos(firstPoint);
		input.LeftButtonUp();
	}
	index++;
}
input.LeftButtonUp();</pre>
<pre class="brush:csharp">private bool isType(byte type, PathPointType isType) {
	return (type &amp; (byte)isType) != 0;
 }</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.red-stars.net/technology/programming/csharp/system-drawing-drawing2d-pathpointtype-defined/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automated Local Backup of a Remote MySQL Database</title>
		<link>http://blog.red-stars.net/technology/software/automated-local-backup-of-a-remote-mysql-database/</link>
		<comments>http://blog.red-stars.net/technology/software/automated-local-backup-of-a-remote-mysql-database/#comments</comments>
		<pubDate>Thu, 16 Jul 2009 20:15:39 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://red-stars.net/wordpress/?p=33</guid>
		<description><![CDATA[Scared your $10.00/year web host is going to blow up or disappear some evening? Me too! So I wrote this script.]]></description>
			<content:encoded><![CDATA[</li></li></li><p>I always like to take backing up into my own hands, and a database is potentially the most important thing on your server next to only the code driving it all, which in nature typically has a local copy anyways.</p>
<p><span id="more-33"></span><div class="toc"><h2>Contents</h2><ol>
<li><a href="#3)Step 1: mysqldump and the remote script">Step 1: mysqldump and the remote script</a>
<li><a href="#3)Step 2: wget, rar and the local script">Step 2: wget, rar and the local script</a>
<li><a href="#3)Step 3: Scheduling">Step 3: Scheduling</a>
</ol>
</ol>
</ol>
</div></p>
<p>The local machine is a Windows Vista workstation and the remote is a webserver running LAMP.</p>
<p>The security of the locally backup database file is only as secure as the machine it-self. If you&#8217;re not sure what this means, do <em>not</em> backup sensitive data using this method.</p>
<a name="3)Step 1: mysqldump and the remote script"></a><h3>Step 1: mysqldump and the remote script</h3>
<p><code>mysqldump</code> is a program which can dump the contents of a MySQL database. It should be used with a MySQL user which has read access to all of the databases on your server that you wish to backup.</p>
<p><code>mysqldump</code> will be executed by PHP on the remote server and the output will be passed back over standard http.</p>
<pre class="brush:php">
</pre>
<p>Update the variables in the above script and save as <code>index.php</code>. Upload this file to it&#8217;s own directory on your server, for example <code>/www/sqlbackup/</code>.</p>
<p><code>/www/sqlbackup/</code> should be configured as a password protected directory to prevent access by anyone to it.</p>
<a name="3)Step 2: wget, rar and the local script"></a><h3>Step 2: wget, rar and the local script</h3>
<p><a href="http://users.ugent.be/~bpuype/wget/" target="_blank">Download wget</a> into your <code>%windir</code>. This is a command line utility that can be used to download remote files and pages from http and ftp servers.</p>
<p>Optionally, <a href="http://www.rarlabs.com/" target="_blank">install WinRAR</a> to add compression.</p>
<pre class="brush:text">wget --http-user=... --http-password=... --output-document=C:\Users\Joe\Documents\Scripts\sqlbackup\backup.txt http://www.yourserver.com/sqlbackup/
"C:\program files\winrar\rar.exe" u -dw -y -p... backup.rar backup.txt</pre>
<p>The first line uses <code>wget</code> to download the output from our remote script to <code>backup.txt</code>. The user, password, remote, and local locations all need to be changed to suite your configuration. This should be saved into <code>script.bat</code> in it&#8217;s own directory on your local workstation, example <code>C:\Users\Joe\Documents\Scripts\sqlbackup\</code>.</p>
<p>The second line compresses the downloaded file into <code>backup.rar</code> and sets the password of the rar to whatever follows the -p argument. Note that the rar password ads very minimal security due to the script, which contains the password, being in the same directory. This line is optional and can be omitted.</p>
<p>Run <code>backup.bat</code> to make sure that everything is working fine.</p>
<a name="3)Step 3: Scheduling"></a><h3>Step 3: Scheduling</h3>
<p>In a command window, enter <code>at 13:00 /EVERY:M,T,W,Th,F,S,Su C:\Users\Joe\Documents\Scripts\sqlbackup\backup.bat</code></p>
<p>This will cause the above local script to execute everyday at 1:00PM everyday of the week.</p>
<p>There&#8217;s nothing else to it! Keep in mind, once again, that this will make any of the dumped MySQL contents as insecure as your computer is!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.red-stars.net/technology/software/automated-local-backup-of-a-remote-mysql-database/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Food: The Way I See It</title>
		<link>http://blog.red-stars.net/food/food-rant/food-the-way-i-see-it/</link>
		<comments>http://blog.red-stars.net/food/food-rant/food-the-way-i-see-it/#comments</comments>
		<pubDate>Tue, 14 Jul 2009 17:32:51 +0000</pubDate>
		<dc:creator>admin0</dc:creator>
				<category><![CDATA[Food Rant]]></category>

		<guid isPermaLink="false">http://red-stars.net/wordpress/?p=7</guid>
		<description><![CDATA[A food eater's over educated manifesto. ]]></description>
			<content:encoded><![CDATA[</li></li></li><p>It all starts when we first start, at birth. Once separated from mother, we wont be long for this world with out something to eat. Thus starts our relationship with something so universally appreciated, that you&#8217;ll be hard pressed to name a culture or a religion that never mentions it, something more important than grade point averages or your car lease, the thing that your body turns into itself, and what has the power to give you a good quality of life, or tear you down.</p>
<p><span id="more-7"></span><div class="toc"><h2>Contents</h2><ol>
<li><a href="#3)How It All Begins">How It All Begins</a>
<li><a href="#3)Trouble in Paradise">Trouble in Paradise</a>
<li><a href="#3)The Upside">The Upside</a>
</ol>
</ol>
</ol>
</div></p>
<a name="3)How It All Begins"></a><h3>How It All Begins</h3>
<p>If you&#8217;re anything like me, your earliest memories of food come from mom, assuming the even earlier food dealings went through her, too. Things didn&#8217;t change much from the inutero days immediately, but with enough time, the kitchen would stop being the land of potions and other magical dealings, and become what is truly the land of nurturing, even self nurturing.</p>
<p>But something happened in the land of the mystics. Evil forces must be brewing about. One third of the US population is overweight, and another third is obese, or some other debated figure, but the court isn&#8217;t out, we&#8217;re fat, some taking up multiple seats, others getting sick and dying. How did this happen? When did the nurturing food start becoming a poison we can not resist?</p>
<a name="3)Trouble in Paradise"></a><h3>Trouble in Paradise</h3>
<p>A lot of what has destroyed food has occurred for a single reason: <em>food is cheap</em>. When something gets too cheap, it can become too difficult to make money by selling. This is why we turned oats into granola bars, wheat into pasta into canned pasta, water into soda, and believe it or not, corn and soy into beef. Call it greed, call it economic forces, call it human nature, but when food is as cheap as it is and someones trying to turn a buck from it, it starts to move away from health and along other axis&#8217;, like convenience and taste.</p>
<p>Making pasta involves planting tomato, basil, wheat, onions, and garlic, then harvesting and milling the wheat&#8230; well, you see where this is going. Even from the super market, it involves boiling water, browning onions and garlic, doing things semi-properly, and having enough skill to keep yourself entertained with the dish. Or it involves using a can opener, or calling the local pizza chain.</p>
<p>Even worse is the treatment done to poor things such as oats. A perfectly affordable and healthy food turned by Quaker into Cinnamon Roll flavored &#8220;Oatmeal Express,&#8221; a single serving in a ready-to-use cup for 79 cents per ounce, unlike run of the mill (literally!) rolled oats, which are 8 cents per ounce, and already cook near-instantly. Then the box has endless fix-all health claims on it. Please do not eat oats unless you need a straight carbohydrate for energy. Do not eat them with intentions of reducing your risk for heart disease, that comes from complete life style.</p>
<p>Because food is cheap, it&#8217;s become convenient. We&#8217;re now able to pay more to have more of the work done for us. The kitchen realm that is inhabited by mystics is now always so for some people. They never learn the sacred art of feeding themselves. Which use to be alright. Portions and meals were dictated by someone who cared enough about you to keep you healthy, something a fast food chain can be a bit careless about at times. Sadly, now even when that person is mom, chances has it she&#8217;s as lost in the strong currents of the supermarket and advertising seas as everyone else.</p>
<p>The convenience is truly a luxury of the modern age. Never before in history has food ever been this around us, this available to us, but never before have we been so separated from it. The American farmers aren&#8217;t the best paid of our society, they&#8217;re actually very low on the totem pole. The American government pays farmers not to grow their crops as well as pays in-part for others to guarantee that they will always be cheap. We get pouty if the food we want is not available. We get oranges year round coast to coast, and more often than not, they ain&#8217;t half bad. We see two types of commercial cooks today, burger flippers and Wolfgang Puck. Commercial products are made by people closer to chemists than cook, even the cans with Wolfgang Puck&#8217;s face on the front or innocent Little Debbie.</p>
<a name="3)The Upside"></a><h3>The Upside</h3>
<p>It&#8217;s not all doom and gloom, there is good news in all of this, and that&#8217;s that <em>food is cheap</em>. I&#8217;m not talking about Kraft Mac &#8216;n Cheese or the Value Menu. I&#8217;m talking about food. The items your great grandparents would recognize. The stuff your body can use to turn into a good you.</p>
<p>In this blog, and some of my other projects, I hope to show you some food, and share some ramblings to help you understand my point of view. It&#8217;s a little bit insane, but trust me, you&#8217;ve tried Weight Watchers, you&#8217;ve tried Jenny Craig, Atkins, South Beach, and so on, now try out my style, even if it&#8217;s just for a week, you may like what you find in yourself, and I wont even ask you to buy snack bars from me.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.red-stars.net/food/food-rant/food-the-way-i-see-it/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
