From: <Saved by Microsoft Internet Explorer 5>
Subject: Coding Horror: Creating Smaller Virtual Machines
Date: Mon, 6 Nov 2006 13:11:34 -0800
MIME-Version: 1.0
Content-Type: multipart/related;
	type="text/html";
	boundary="----=_NextPart_000_0000_01C701A5.15C25F40"
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2962

This is a multi-part message in MIME format.

------=_NextPart_000_0000_01C701A5.15C25F40
Content-Type: text/html;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.codinghorror.com/blog/archives/000639.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" =
"http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
<HTML><HEAD><TITLE>Coding Horror: Creating Smaller Virtual =
Machines</TITLE>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Diso-8859-1"><LINK=20
href=3D"http://www.codinghorror.com/blog/styles-site.css" =
type=3Dtext/css=20
rel=3Dstylesheet><LINK=20
href=3D"http://www.codinghorror.com/blog/includes/SyntaxHighlighter.css" =

type=3Dtext/css rel=3Dstylesheet><LINK title=3DRSS=20
href=3D"http://www.codinghorror.com/blog/index.xml" =
type=3Dapplication/rss+xml=20
rel=3Dalternate><LINK title=3DHome =
href=3D"http://www.codinghorror.com/blog/"=20
rel=3Dstart><LINK title=3D"Creating Smaller Virtual Machines"=20
href=3D"http://www.codinghorror.com/blog/archives/000639.html"=20
rel=3Dprev></MTENTRYPREVIOUS><LINK=20
title=3D"I Pity The Fool Who Doesn't Write Unit Tests"=20
href=3D"http://www.codinghorror.com/blog/archives/000640.html" =
rel=3Dnext>
<SCRIPT language=3Djavascript type=3Dtext/javascript>
function OpenTrackback (c) {
    window.open(c, 'trackback', =
'width=3D580,height=3D580,resizable=3D1');
}

var HOST =3D 'www.codinghorror.com';
function setCookie (name, value, expires, path, domain, secure) {
    var curCookie =3D name + "=3D" + escape(value) + ((expires) ? "; =
expires=3D" + expires.toGMTString() : "") + ((path) ? "; path=3D" + path =
: "") + ((domain) ? "; domain=3D" + domain : "") + ((secure) ? "; =
secure" : "");
    document.cookie =3D curCookie;
}

function getCookie (name) {
    var prefix =3D name + '=3D';
    var c =3D document.cookie;
    var nullstring =3D '';
    var cookieStartIndex =3D c.indexOf(prefix);
    if (cookieStartIndex =3D=3D -1)
        return nullstring;
    var cookieEndIndex =3D c.indexOf(";", cookieStartIndex + =
prefix.length);
    if (cookieEndIndex =3D=3D -1)
        cookieEndIndex =3D c.length;
    return unescape(c.substring(cookieStartIndex + prefix.length, =
cookieEndIndex));
}

function fixDate (date) {
    var base =3D new Date(0);
    var skew =3D base.getTime();
    if (skew > 0)
        date.setTime(date.getTime() - skew);
}

function rememberMe (f) {
    var now =3D new Date();
    fixDate(now);
    now.setTime(now.getTime() + 365 * 24 * 60 * 60 * 1000);
    setCookie('mtcmtauth', f.author.value, now, '', HOST, '');
    setCookie('mtcmthome', f.url.value, now, '', HOST, '');
}

</SCRIPT>
<!--
<rdf:RDF xmlns:rdf=3D"http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         =
xmlns:trackback=3D"http://madskills.com/public/xml/rss/module/trackback/"=

         xmlns:dc=3D"http://purl.org/dc/elements/1.1/">
<rdf:Description
    rdf:about=3D"http://www.codinghorror.com/blog/archives/000639.html"
    =
trackback:ping=3D"http://www.codinghorror.com/mtype/mt-tb-renamed.cgi/639=
"
    dc:title=3D"Creating Smaller Virtual Machines"
    =
dc:identifier=3D"http://www.codinghorror.com/blog/archives/000639.html"
    dc:subject=3D""
    dc:description=3D" Now that Virtual PC is finally free, I&apos;ve =
become obsessed with producing the smallest possible Windows XP Virtual =
PC image. It&apos;s quite a challenge, because a default XP install can =
eat up well over a gigabyte. Once you factor..."
    dc:creator=3D"Jeff Atwood"
    dc:date=3D"2006-07-19T23:59:59-08:00" />
</rdf:RDF>
--><LINK href=3D"http://www.codinghorror.com/favicon.ico" =
rel=3D"shortcut icon">
<META content=3D"MSHTML 6.00.2900.2995" name=3DGENERATOR></HEAD>
<BODY>
<TABLE width=3D"100%">
  <TBODY>
  <TR>
    <TD width=3D110><IMG height=3D91 alt=3D"I <3 Steve McConnell"=20
      =
src=3D"http://www.codinghorror.com/blog/images/coding-horror-official-log=
o-small.png"=20
      width=3D100 border=3D0>*</TD>
    <TD width=3D*><A href=3D"http://www.codinghorror.com/blog/"><IMG =
height=3D25=20
      alt=3D"Coding Horror"=20
      =
src=3D"http://www.codinghorror.com/blog/images/coding-horror-text.png"=20
      width=3D275 border=3D0></A><BR><SPAN class=3Ddescription>.NET and =
human=20
      factors<BR>by Jeff Atwood</SPAN> </TD>
    <TD width=3D250>
      <DIV class=3Dside>
      <FORM action=3Dhttp://www.codinghorror.com/mtype/mt-search.cgi=20
      method=3Dget><INPUT type=3Dhidden value=3D2 name=3DIncludeBlogs> =
<INPUT id=3Dsearch=20
      name=3Dsearch>&nbsp; <INPUT type=3Dsubmit value=3DSearch>=20
  </FORM></DIV></TD></TR></TBODY></TABLE>
<DIV id=3Dcontainer>
<DIV class=3Dblog>
<DIV id=3Dmenu><A =
href=3D"http://www.codinghorror.com/blog/archives/000638.html">=AB=20
Why Can't Database Tables Index Themselves?</A> | <A=20
href=3D"http://www.codinghorror.com/blog/">Main</A> | <A=20
href=3D"http://www.codinghorror.com/blog/archives/000640.html">I Pity =
The Fool Who=20
Doesn't Write Unit Tests =BB</A> </DIV></DIV>
<DIV class=3Dblog>
<H2 class=3Ddate>July 19, 2006</H2>
<DIV class=3Dblogbody>
<H3 class=3Dtitle>Creating Smaller Virtual Machines</H3>
<P>Now that <A=20
href=3D"http://www.microsoft.com/windows/virtualpc/default.mspx">Virtual =
PC is=20
finally free</A>, I've become obsessed with producing <B>the smallest =
possible=20
Windows XP Virtual PC image</B>. It's quite a challenge, because a =
default XP=20
install can eat up well over a gigabyte. Once you factor in the swapfile =
and=20
other overhead, you're generally talking about around 2-4 gigabytes for=20
relatively simple configurations.=20
<P>My best result so far, however, is a <B>641 megabyte</B> virtual =
machine=20
image of a clean, <I>fully patched</I> Windows XP install. Not bad. And =
here's=20
how I did it.=20
<P>First, start with the obvious stuff:=20
<P>
<OL>
  <LI>Install Windows XP SP2. Take all default options.=20
  <LI>Connect to Windows update; install all critical updates.=20
  <LI>Install VM additions.=20
  <LI>Turn off system restore.=20
  <UL>
    <LI>Right click My Computer; select properties=20
    <LI>Click the System Restore tab=20
    <LI>Click the "Turn off System Restore" checkbox=20
    <LI>OK all the way back out </LI></UL>
  <LI>Set Visual Effects to minimum.=20
  <UL>
    <LI>Right click My Computer; select Properties=20
    <LI>Click the Advanced tab=20
    <LI>Click the Performance Settings button=20
    <LI>Click the "Adjust for best performance" checkbox=20
    <LI>OK all the way back out. </LI></UL>
  <LI>Shut down. </LI></OL>
<P><I>Don't install anything else yet!</I> Remember, we're trying to get =
to a=20
minimal baseline install of Windows XP first. A nice, flat platform to =
build on.=20

<P>It's critical to <B>turn off system restore</B>, because that eats up =

hundreds of megabytes of disk space. In a virtual machine environment, =
having a=20
rollback path doesn't make sense anyway. And if the Windows software =
environment=20
wasn't so pathological, we wouldn't need complex rollback support =
embedded in=20
the OS, either, but I digress.=20
<P>Now let's put together our toolkit of virtual machine optimization:=20
<P>
<UL>
  <LI><A href=3D"http://www.litepc.com/xplite.html">XPlite</A> ($)=20
  <LI><A href=3D"http://www.ccleaner.com/">Crap Cleaner</A>=20
  <LI><A=20
  =
href=3D"http://www.microsoft.com/windowsxp/downloads/powertoys/xppowertoy=
s.mspx">TweakUI</A>=20

  <LI><A =
href=3D"http://www.whitneyfamily.org/Hacks/?item=3DDefrag">Whitney=20
  Defragger</A>=20
  <LI><A href=3D"http://www.invirtus.com/">Invirtus VM Optimizer</A> ($, =
optional)=20
  </LI></UL>
<P>Thes utilities are mostly free. And, except for Crap Cleaner, they =
don't even=20
require installers. Just plop all the files for each one into a folder; =
I call=20
mine VM-utils. Copy this folder to the target VM.=20
<P>
<OL>
  <LI>Use TweakUI to <A=20
  href=3D"http://www.codinghorror.com/blog/archives/000565.html">turn on =
automatic=20
  login</A>. Otherwise you have to distribute <B>login credentials</B> =
with your=20
  VM, and who wants to do that?=20
  <P></P>
  <LI>Now, use <A href=3D"http://www.litepc.com/xplite.html">XPlite</A> =
to tear=20
  out all the <B>annoying, unnecessary bits of Windows XP</B>:=20
  <P><IMG height=3D449 alt=3D"XPlite Screenshot"=20
  src=3D"http://www.codinghorror.com/blog/images/xplite-screenshot.png" =
width=3D572=20
  border=3D0>=20
  <P>XPlite is easily the best utility of its type; it removes scads of =
useless=20
  things built into XP that have no explicit uninstall mechanism. =
Unfortunately,=20
  XPlite is payware. There is a free version, but it's crippled; it can =
only=20
  remove a fraction of the items the full version can. See the full list =
of=20
  items it can remove along the right-hand side of the <A=20
  href=3D"http://www.litepc.com/xplite.html">product page</A>.=20
  <P>By default, XPlite generally shows things that are safe to remove. =
Note=20
  that the "Advanced Components" item is shown in that screenshot, which =
is=20
  definitely stuff that's <I>not</I> safe to remove unless you really =
know what=20
  you're doing. Anyway, here's what I consider totally safe to remove in =

  XPlite's standard list:=20
  <P>
  <UL>
    <LI>Accessibility Options=20
    <LI>Communication and Messaging=20
    <LI>Server Components=20
    <LI>Games=20
    <LI>System Services </LI></UL>
  <P>The others require a bit of judicious selection.=20
  <P>
  <UL>
    <LI>Accessories - you probably want Notepad, Calc, and the other =
essential=20
    applets. A world without Notepad is a world I don't want to live in. =

    <LI>Internet Utilities - if you want to keep the default IE6 inside =
XP, I'd=20
    leave this alone. With the notable exception of MSN Explorer, which =
is=20
    always safe to drop.=20
    <LI>Multimedia - if you have sound enabled, selectively keep some of =
this,=20
    otherwise dump it all. It's highly unlikely you would ever want to =
watch=20
    videos or listen to music inside your VM, right? Right?=20
    <LI>Operating System Options - you may want to keep the core fonts =
if you're=20
    planning to browse the web within the VM. Also, beware of removing =
the=20
    service pack update files. Most of this is safe to dump, though. =
However,=20
    you will need the VB6 runtimes for Crap Cleaner to run!=20
    <LI>System Tools &amp; Utilities - I'd leave Dr. Watson, and =
possibly=20
    PerfMon, WSH and Zip folder support. </LI></UL>
  <P>Once you've made your selections, let XPlite do its thing. It's =
worth the=20
  effort, because you'll have an unbelievably squeaky clean Start menu =
when it's=20
  done. Who knew Windows XP could be this.. <I>simple?</I>=20
  <P></P>
  <LI>Install and run <A href=3D"http://www.ccleaner.com/">Crap =
Cleaner</A>.=20
  Perform the default analysis, then do a <B>cleanup</B>. This step is =
really=20
  optional; it only cleans up a couple megabytes of log files and =
miscellaneous=20
  junk. Be sure to uninstall Crap Cleaner when you're done, too.=20
  <P></P>
  <LI>Now that we've cleaned everything up, we need to <B>defragment the =

  disk</B>.=20
  <P><IMG height=3D228 alt=3D"whitney defragmenter screenshot"=20
  =
src=3D"http://www.codinghorror.com/blog/images/whitney-defragmenter-scree=
nshot.png"=20
  width=3D608 border=3D0>=20
  <P>You can use any defragmenter you like, of course, but this one is =
free and=20
  works quite well.=20
  <P>
  <OL>
    <LI>Navigate to the folder where you put your VM utilities, =
including the <A=20
    href=3D"http://www.whitneyfamily.org/Hacks/?item=3DDefrag">Whitney=20
    Defragger</A>.=20
    <LI>Open a command prompt=20
    <LI>Copy the defragmenting program to our windows system folder:=20
    <P></P><PRE>copy bootdfrg.exe c:\windows\system32\
</PRE>
    <P></P>
    <LI>Install the defragmenting service:=20
    <P></P><PRE>defrag -i
</PRE>
    <P></P>
    <LI>Schedule a defragmentation of the c:\ drive for the next boot:=20
    <P></P><PRE>defrag -d c: -B
</PRE>
    <P></P>
    <LI>Restart the virtual machine.=20
    <LI>The defragmenter will run before Windows loads. Let it run to=20
    completion. It may take a little while, but it provides lots of =
textual=20
    feedback on what it's doing.=20
    <P></P></LI></OL>
  <LI>Now we have to <B>zero the free space on the drive</B>. You have =
your=20
  choice of the free Microsoft Virtual PC Pre-Compactor, or the =
inexpensive <A=20
  href=3D"http://www.invirtus.com/">Invirtus VM Optimizer</A>. Both do =
the same=20
  thing, but the Invirtus tool results in an image that's about 15 =
percent=20
  smaller (641 megabytes vs. 758 megabytes, in my test) than the =
Microsoft tool.=20

  <P>Either way, you're mounting an ISO. The Microsoft Pre-Compactor is =
in a=20
  folder named "Virtual Machine Additions" under your Virtual PC install =
folder.=20
  Once mounted, the precompactor will autorun. Let it prep the drive; =
this=20
  doesn't take long.=20
  <P>Cleanly shut down the virtual machine.=20
  <P></P>
  <LI>Finally, <B>shrink the virtual machine hard drive</B> using the =
disk=20
  wizard available from the Virtual PC UI:=20
  <P>
  <OL>
    <LI>Click the File | Virtual Disk Wizard drop-down menu=20
    <LI>Edit an existing virtual disk=20
    <LI>Select the correct disk image=20
    <LI>Select "Compact it"=20
    <LI>Select "replacing the original file" </LI></OL>
  <P>.. and prepare to marvel at the tiny size* of the resulting hard =
drive=20
  image! </P></LI></OL>
<OL></OL>
<P>It's really quite amazing how snappy and compact Windows XP can be, =
<B>once=20
you remove all the useless cruft from it</B>.=20
<P>* that's what <A =
href=3D"http://en.wikiquote.org/wiki/The_Office_(US)">she=20
said</A>.=20
<P><A name=3Dmore></A><SPAN class=3Dposted>Posted by Jeff Atwood at July =
19, 2006=20
11:59 PM | <A onclick=3D"OpenTrackback(this.href); return false"=20
href=3D"http://www.codinghorror.com/mtype/mt-tb-renamed.cgi?__mode=3Dview=
&amp;entry_id=3D639">TrackBack</A>=20
<BR></SPAN></P></DIV>
<DIV class=3Dcomments-head><A name=3Dcomments></A>Comments</DIV>
<DIV class=3Dcomments-body>
<P>The resulting 758 megabyte .vhd (Virtual Hard Drive) image is also =
highly=20
compressible.</P>
<P>I created a self-extracting RAR image of the .vhd and the .vmc file =
-- it's=20
only *243* megabytes!</P>
<P>Really cool!</P><SPAN class=3Dcomments-post style=3D"MARGIN-LEFT: =
20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12020">Jeff=20
Atwood</A> on July 20, 2006 11:19 AM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>Have you tried running VMOptimizer on the final image, to see if you =
can=20
squeeze it down a bit more?</P>
<P><A =
href=3D"http://www.invirtus.com/">http://www.invirtus.com/</A><BR></P><SP=
AN=20
class=3Dcomments-post style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12021">Kevin=20
Dente</A> on July 20, 2006 11:37 AM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>This is del.icio.us material! What a cool concept that you can =
distribute a=20
full VM on a single CD-R!</P>
<P>Since my laptop doesn't have a DVD Burner, I struggled with this.</P>
<P>However, as soon as you install Visual Studio / Sharepoint / SQL =
Server, and=20
such it will push it over the 800mb limit, but at least you can have a =
CD of=20
something to start with.</P>
<P>Good work.</P><SPAN class=3Dcomments-post style=3D"MARGIN-LEFT: =
20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12022">Ben=20
Scheirman</A> on July 20, 2006 11:39 AM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>You may want to look at the free nLite tool to create a stripped-down =
Windows=20
XP CD. It appears to include some of the same functionality as XPlite, =
but=20
applies it before the OS is installed.</P>
<P><A =
href=3D"http://www.nliteos.com/">http://www.nliteos.com/</A></P><SPAN=20
class=3Dcomments-post style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12023">Alex=20
Tsang</A> on July 20, 2006 11:50 AM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>Nlite's great for creating very stripped-down disc images to install =
from. It=20
provides cleaning options very similar to XpLite and is free. </P><SPAN=20
class=3Dcomments-post style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12024">Pat=20
cavit</A> on July 20, 2006 12:05 PM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>it would be nice to have a heavily trimmed down windows xp install =
entirely=20
geared towards gaming</P>
<P>for us linux and mac users to install on another partition</P><SPAN=20
class=3Dcomments-post style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12025">oldman</A>=20
on July 20, 2006 12:09 PM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>Compress it with 7-Zip instead of RAR, and you'll save even more =
space.</P>
<P><A href=3D"http://www.7-zip.org/">http://www.7-zip.org/</A></P>
<P>It's free (LGPL).</P><SPAN class=3Dcomments-post =
style=3D"MARGIN-LEFT: 20px">C-J=20
Berg on July 20, 2006 12:43 PM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>&gt; Have you tried running VMOptimizer on the final image</P>
<P>I was skeptical, but VMOptimizer worked. You use their special ISO to =
compact=20
instead of the buil in Pre-Compaction ISO. Here's what I got...</P>
<P>Original size: 758 megabytes<BR>VMOptimizer size: 641 =
megabytes</P><SPAN=20
class=3Dcomments-post style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12028">Jeff=20
Atwood</A> on July 20, 2006 12:44 PM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>Did you turn off hibernation support? hiberfil.sys is a big as the =
VM's=20
ram.</P><SPAN class=3Dcomments-post style=3D"MARGIN-LEFT: 20px">Leonel =
on July 20,=20
2006 01:58 PM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>I have an XP boot CD made using...something (I forget what), so =
that's=20
obviously a very small build.</P><SPAN class=3Dcomments-post=20
style=3D"MARGIN-LEFT: 20px">[ICR] on July 20, 2006 02:04 PM</SPAN> =
</DIV>
<DIV class=3Dcomments-body>
<P>"Unfortunately, XPlite is payware"</P>
<P>Why is paying for a good product an issue? Don't you<BR>like to get =
paid for=20
the develpment work you do?</P>
<P>Like many out there I like open source and free whenever it makes =
since but=20
clearly you liked the product and shouldn't the developer or team that =
created=20
be rewarded. </P><SPAN class=3Dcomments-post style=3D"MARGIN-LEFT: =
20px">VHF on July=20
20, 2006 02:12 PM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>&gt; hiberfil.sys is a big as the VM's ram.</P>
<P>Hibernation is generally off by default in XP.. I always have to =
manually=20
enable it.</P>
<P>&gt; Why is paying for a good product an issue?</P>
<P>It's not an issue. In fact I bought a copy of XPlite during the =
composition=20
of this post. But one of these things is not like the other..</P><SPAN=20
class=3Dcomments-post style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12037">Jeff=20
Atwood</A> on July 20, 2006 02:22 PM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>I'll second the VMOptimizer recommendation. It saves tons of time, =
does a=20
great job, and it's a very inexpensive. One of the few pieces of =
software I was=20
happy to buy.</P>
<P>And 7-Zip's worth it when you get to files that size. I wrote up some =
info on=20
it before here:<BR><A=20
href=3D"http://weblogs.asp.net/jgalloway/archive/2005/05/07/406074.aspx">=
http://weblogs.asp.net/jgalloway/archive/2005/05/07/406074.aspx</A><BR>I =

think one of the switch names may have changed in newer 7-Zip =
releases.</P>
<P>True, a lot of people don't have 7-Zip installed, but it's really =
easy to=20
make an SFX (self-extracting zip), so you distribute an EXE file which =
unzips=20
itself.</P><SPAN class=3Dcomments-post style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12038">Jon=20
Galloway</A> on July 20, 2006 03:01 PM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>Great post, but seriously, I'm amazed you'd waste this kind of time =
and not=20
just use Virtual Optimizer.</P>
<P><A=20
href=3D"http://www.hanselman.com/blog/InvirtusVirtualMachineOptimizer.asp=
x">http://www.hanselman.com/blog/InvirtusVirtualMachineOptimizer.aspx</A>=
</P>
<P>On my post you said this functionality wasn't worth $40. You MUST =
have spent=20
at least an hour messing with this and writing this post. How much are =
you paid=20
an hour? ;)</P><SPAN class=3Dcomments-post style=3D"MARGIN-LEFT: =
20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12039">Scott=20
Hanselman</A> on July 20, 2006 05:16 PM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>And another thing...no way I'm installing a defrager made by the =
"Whitney=20
Family." Who do you trust?</P>
<P>pagedfrg by SysInternals: <BR><A=20
href=3D"http://www.sysinternals.com/Utilities/PageDefrag.html">http://www=
.sysinternals.com/Utilities/PageDefrag.html</A></P>
<P>:P</P><SPAN class=3Dcomments-post style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12040">Scott=20
Hanselman</A> on July 20, 2006 05:18 PM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>&gt; I'm amazed you'd waste this kind of time and not just use =
Virtual=20
Optimizer.</P>
<P>The Virtual Optimizer only zeroes out the drive. it doesn't..</P>
<P>1) Reduce the size of Windows XP<BR>2) Defragment the drive</P>
<P>It does provide a 15% size reduction, which is nice, but it's hardly =
the=20
entire point of the article. It does work as advertised, but personally, =
I'd=20
rather spend that $40 on XPlite.</P>
<P>&gt; no way I'm installing a defrager made by the "Whitney Family." =
Who do=20
you trust?</P>
<P>Yes, it might destroy my.. virtual.. machine.. oh no. ;)</P><SPAN=20
class=3Dcomments-post style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12043">Jeff=20
Atwood</A> on July 20, 2006 09:51 PM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>There was a big thread at neowin.net's forum where some guys tried to =
have=20
the smallest windows folder. One of those guys wrote a complete guide =
which you=20
can read at <A=20
href=3D"http://www.bold-fortune.com/forums/index.php?showtopic=3D229">htt=
p://www.bold-fortune.com/forums/index.php?showtopic=3D229</A>=20
</P>
<P>Everything is done manually<BR></P><SPAN class=3Dcomments-post=20
style=3D"MARGIN-LEFT: 20px">FlorentG on July 21, 2006 12:57 AM</SPAN> =
</DIV>
<DIV class=3Dcomments-body>
<P>I wonder if Parallels' compressor (trialware) would compress any =
better than=20
Invirtus VM Optimizer or Virtual PC?<BR><A=20
href=3D"http://www.parallels.com/en/products/compressor/workstation/">htt=
p://www.parallels.com/en/products/compressor/workstation/</A></P><SPAN=20
class=3Dcomments-post style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12046">George</A>=20
on July 21, 2006 02:15 AM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>Why free matters: I'm allowed to use free utilities at work, but =
anything I=20
have to pay for requires a lot of red tape. It is actually easier to get =
a $600=20
tool than say a $40 tool.</P><SPAN class=3Dcomments-post=20
style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12048">rsbohn</A>=20
on July 21, 2006 05:18 AM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>I assume you did this, but not specifically mentioned:</P>
<P>Go into the Windows directory and delete all the patch backup =
directories,=20
these can easily add up to &gt; 50MB space on disk.</P><SPAN =
class=3Dcomments-post=20
style=3D"MARGIN-LEFT: 20px">Richard on July 21, 2006 06:55 AM</SPAN> =
</DIV>
<DIV class=3Dcomments-body>
<P>Jeff:</P>
<P>Have you also gotten rid of all of the driver cab files. Your =
hardware is a=20
known issue, so you shouldn't need any of the autodetect hardware stuff. =
I=20
believe it is "%windows%/driver cache." In the past when Connectix owned =
it, I=20
would even minimize the size of the swapfile. With 2GB RAM, my VM's are =
hardly=20
noticable during demos.</P>
<P>I must say though, if anyone reading this is going to do =
presentations with=20
VM's--don't say..."It's the VMs fault"--it's your fault if you haven't =
prepared=20
a correctly working VM (including plenty of RAM to go with it)! It's =
like=20
Hanselman's comment on "I know you can't read this, but..." See=20
hanselman.com/tools for ways to fix that too.</P><SPAN =
class=3Dcomments-post=20
style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12052">Brian=20
Sherwin</A> on July 21, 2006 07:18 AM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>Hi,</P>
<P>I thought you might be interested in this thread concerning the so =
called=20
"TinyXP" build that is claimed to be sub 70 MB in size. </P>
<P><A=20
href=3D"http://www.xtremesystems.org/forums/showthread.php?t=3D84885">htt=
p://www.xtremesystems.org/forums/showthread.php?t=3D84885</A></P>
<P>I haven't personally verified claims, so i will be very interested in =
the=20
results if you choose to test it.</P>
<P>Here's another idea - how come we don't see VM image freely =
distributed over=20
Bit-Torrent and such? I mean as far as i understand - if the system is=20
Sysprep'ed prior to distribution - it will require license key and in =
many ways=20
will be indentical to a regular install, so that doesn't necessarily =
equate to=20
piracy. At least that's not my intention bringing it up.</P>
<P>Fine, maybe Microsoft can be opposed to 3rd party distribution for =
one reason=20
or another - but they themselves could defenitely distribute beta =
versions of=20
their products in such form, no?</P><SPAN class=3Dcomments-post=20
style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12053">Vlad=20
Ivanov</A> on July 21, 2006 07:35 AM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>I am sorry, i had the link in my bookmarks for a while, so my memory =
of the=20
contents was a little bit hazy - i just visited the link again prompted =
by your=20
post and i'd like to make a correction:</P>
<P>It's a 100MB install that results in a 400MB installed image, that is =
claimed=20
to only use 40MB of RAM to run. </P>
<P>Seems like still an improvement over your results.</P><SPAN=20
class=3Dcomments-post style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12054">Vlad=20
Ivanov</A> on July 21, 2006 07:42 AM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>You should change your path from:</P>
<P>C:\windows\system32\</P>
<P>to:</P>
<P>%WINDIR%\system32\</P>
<P>:-)</P><SPAN class=3Dcomments-post style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12055">Omar=20
Shahine</A> on July 21, 2006 08:40 AM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>&gt; Have you also gotten rid of all of the driver cab files. Your =
hardware=20
is a known issue, so you shouldn't need any of the autodetect hardware =
stuff. I=20
believe it is "%windows%/driver cache." </P>
<P>Good idea. I ticked those two boxes in XPlite (remove cached server =
pack=20
files, remove cached driver files). I tried to run Invirtus again, but =
it=20
refused -- "can only run one time per VM for trial edition". Instead, I =
ran the=20
invirtus drive zero-ing command line tool ( InvirtusFreeSpace.exe ) =
that's on=20
the Invirtus trial ISO image. That produced the same compaction results =
as doing=20
an autorun (!)</P>
<P>The resulting image is now 587 megabytes.</P><SPAN =
class=3Dcomments-post=20
style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12058">Jeff=20
Atwood</A> on July 21, 2006 10:18 AM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>Does all this work with virtual server too, or this a vpc thing=20
only?<BR></P><SPAN class=3Dcomments-post style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12062">Malcolm=20
Anderson</A> on July 21, 2006 03:20 PM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>Here's an easy one:</P>
<P>Still not using that good old modem and are not planning to in the=20
foreseeable future? Got a xDSL line, Wifi connection or LAN you always =
hook up=20
to?</P>
<P>I thought so...</P>
<P>Then why not kill all the modem driver description files from=20
"%systemroot%\inf"? They're the "mdm*.inf" ones and they take up quite a =
few=20
megabytes.</P>
<P>Btw.: Does anyone know a simple way to locate other deletable driver =
files...=20
like say: old ISA-card drivers, drivers from obsolete graphic cards and =
TV-tuner=20
devices?</P><SPAN class=3Dcomments-post style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12070">Henrik=20
Spuur Hansen</A> on July 21, 2006 05:56 PM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>this post is a keeper!</P>
<P>(lb tucks the entry away in his del.icio.us account)</P><SPAN=20
class=3Dcomments-post style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12095">lb</A>=20
on July 23, 2006 03:13 AM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>You can also delete %WINDIR%\$NtUninstall--------$ folders: I am =
assuming=20
that you would keep a backup of 'original' virtual image somewhere safe =
(like=20
DVD or CD), and these folders can run up to several hundred MB..</P>
<P>I would also reduce/disable trash bin size and space your browser =
allocates=20
for disk cache.</P><SPAN class=3Dcomments-post style=3D"MARGIN-LEFT: =
20px">Maksim=20
Pavlishin on July 24, 2006 11:55 AM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>Has anyone had any luck with Win2k3? I can only get to about 1.5 GB =
with SQL=20
Server and IIS. </P><SPAN class=3Dcomments-post style=3D"MARGIN-LEFT: =
20px">dave on=20
July 31, 2006 01:37 PM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>Another interesting idea: once the "base" drive image is created you =
can=20
switch the virtualPC machine to use a differential drive based on the =
"base"=20
drive. This differential drive can be kept in sync using FolderShare so =
you can=20
use the same Virtual machine from different computers without many=20
synchronization troubles.</P><SPAN class=3Dcomments-post=20
style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12355">Paperino</A>=20
on July 31, 2006 03:47 PM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>Sounds great - no good for test machines where you need it to be a =
pure=20
'out-of-the-box' self-resetting VM, but just the ticket for specialist =
needs,=20
such as setting up a Subversion server, or creating a sandboxed Internet =
browser=20
VM.</P>
<P>Hmm - your filter is now blocking (dot)info web addresses as =
'questionable=20
content'.</P><SPAN class=3Dcomments-post style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D12368">Paul=20
Coddington</A> on August 1, 2006 05:58 AM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>Just shrunk my Win2k3 base drive to &lt; 1GB using the methods =
outlined here=20
and the Invirtus optimizer.</P>
<P>Thanks!</P><SPAN class=3Dcomments-post style=3D"MARGIN-LEFT: 20px"><A =

href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D13062">Bryant=20
Likes</A> on August 22, 2006 05:16 PM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>We've got a 14Mb XP iso booting cmd.exe as shell and a standard =
project that=20
will create a 50Mb XP boot CD with explorer as shell (not to mention a =
few other=20
features like the hability to boot and run from RAM)</P>
<P>This is done using WinBuilder and the projects that come included =
with it.=20
All our works and developments are free to everyone.</P><SPAN=20
class=3Dcomments-post style=3D"MARGIN-LEFT: 20px"><A=20
href=3D"http://www.codinghorror.com/mtype/mt-comments-renamed.cgi?__mode=3D=
red&amp;id=3D13150">Nuno=20
Brito</A> on August 25, 2006 04:27 AM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>hey, just randomly came across this when searching for something =
else... just=20
goign to say, i run TinyXP and it does what it says, i'm using it as a =
main OS=20
though as my windows xp was broken and i didnt realise when i formatted =
my pc...=20
but tinyxp does use 40mb of ram and around about 400mb installed... it's =
a great=20
OS.</P><SPAN class=3Dcomments-post style=3D"MARGIN-LEFT: =
20px">lonewolfxix on=20
September 13, 2006 03:42 PM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<P>Hmmm, seems possible to get it small enough to fit on a flash drive.=20
</P><SPAN class=3Dcomments-post style=3D"MARGIN-LEFT: 20px">lee on =
November 4, 2006=20
10:55 AM</SPAN> </DIV>
<DIV class=3Dcomments-body>
<FORM name=3Dcomments_form onsubmit=3DrememberMe(this)=20
action=3Dhttp://www.codinghorror.com/mtype/mt-comments-renamed.cgi=20
method=3Dpost><INPUT type=3Dhidden value=3D1 name=3Dstatic> <INPUT =
type=3Dhidden value=3D639=20
name=3Dentry_id> <LABEL for=3Dauthor>Name:</LABEL><BR><INPUT id=3Dauthor =
tabIndex=3D1=20
name=3Dauthor><BR><BR><LABEL for=3Durl>Website:</LABEL><BR><INPUT =
id=3Durl tabIndex=3D2=20
name=3Durl><BR><BR><LABEL for=3Dcaptcha>Enter the word<BR><IMG =
height=3D26=20
alt=3Dword.png src=3D"http://www.codinghorror.com/blog/images/word.png" =
width=3D99=20
border=3D0></LABEL><BR><INPUT id=3Dcaptcha tabIndex=3D3 =
name=3Dcaptcha><BR><BR><LABEL=20
for=3Dtext>Your comments:</LABEL> (<SPAN style=3D"COLOR: red">no =
HTML</SPAN>)<BR><TEXTAREA id=3Dtext tabIndex=3D4 name=3Dtext rows=3D10 =
cols=3D50></TEXTAREA><BR><BR><INPUT style=3D"FONT-WEIGHT: bold" =
type=3Dsubmit value=3D&nbsp;Post&nbsp; name=3Dpost><BR><BR></FORM>
<SCRIPT language=3Djavascript type=3Dtext/javascript>
document.comments_form.author.value =3D getCookie("mtcmtauth");
document.comments_form.url.value =3D getCookie("mtcmthome");
</SCRIPT>
</DIV></DIV></DIV>
<TABLE width=3D"100%">
  <TBODY>
  <TR>
    <TD align=3Dleft width=3D50></TD>
    <TD align=3Dright width=3D*><SPAN style=3D"FONT-SIZE: 70%">Content =
(c) 2006 <A=20
      =
href=3D"http://www.codinghorror.com/blog/archives/000021.html">Jeff=20
      Atwood</A>. Logo image used with permission of the author. (c) =
1993 Steven=20
      C. McConnell. All Rights =
Reserved.</SPAN></TD></TR></TBODY></TABLE>
<SCRIPT language=3Djavascript=20
src=3D"http://www.codinghorror.com/blog/includes/shCore.js"></SCRIPT>

<SCRIPT language=3Djavascript=20
src=3D"http://www.codinghorror.com/blog/includes/shBrushCSharp.js"></SCRI=
PT>

<SCRIPT language=3Djavascript=20
src=3D"http://www.codinghorror.com/blog/includes/shBrushVb.js"></SCRIPT>

<SCRIPT language=3Djavascript=20
src=3D"http://www.codinghorror.com/blog/includes/shBrushSql.js"></SCRIPT>=


<SCRIPT language=3Djavascript=20
src=3D"http://www.codinghorror.com/blog/includes/shBrushXml.js"></SCRIPT>=


<SCRIPT =
language=3Djavascript>dp.SyntaxHighlighter.HighlightAll('code');</SCRIPT>=

</BODY></HTML>

------=_NextPart_000_0000_01C701A5.15C25F40
Content-Type: image/png
Content-Transfer-Encoding: base64
Content-Location: http://www.codinghorror.com/blog/images/coding-horror-official-logo-small.png

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

------=_NextPart_000_0000_01C701A5.15C25F40
Content-Type: image/png
Content-Transfer-Encoding: base64
Content-Location: http://www.codinghorror.com/blog/images/coding-horror-text.png

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

------=_NextPart_000_0000_01C701A5.15C25F40
Content-Type: image/png
Content-Transfer-Encoding: base64
Content-Location: http://www.codinghorror.com/blog/images/xplite-screenshot.png

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

------=_NextPart_000_0000_01C701A5.15C25F40
Content-Type: image/png
Content-Transfer-Encoding: base64
Content-Location: http://www.codinghorror.com/blog/images/whitney-defragmenter-screenshot.png

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
SUVORK5CYII=

------=_NextPart_000_0000_01C701A5.15C25F40
Content-Type: image/png
Content-Transfer-Encoding: base64
Content-Location: http://www.codinghorror.com/blog/images/word.png

iVBORw0KGgoAAAANSUhEUgAAAGMAAAAaBAMAAABROP+vAAAAK3RFWHRDcmVhdGlvbiBUaW1lAE1v
biAzIEFwciAyMDA2IDAyOjM2OjE0IC0wODAwxRwmfgAAAAd0SU1FB9YEBgcgFrxHK/gAAAAJcEhZ
cwAACxEAAAsRAX9kX5EAAAAEZ0FNQQAAsY8L/GEFAAAAMFBMVEX+/v6mpqYlJSVoaGi3t7fGxsbZ
2dlFRUUAAACGhoZZWVmUlJQ1NTUVFRXp6el3d3cODfvlAAAAAXRSTlMAQObYZgAAAfdJREFUOMul
1D1ok1EUgOE3/dLfpEmEDl0KRasEXDo4pIvUQSxOAUE3CW4KhQ+xEKFimtr0NW3SjCIIFRTiZEGE
Dg4OHTIGdMgYHKQKBQeHTuKQiFKSYvVMF+59uOdwz7nwb3EBgACiOYA9AMaAic5+stY9GLS7i1vO
ADSq7Fbh85Tnb14g0aqSNJUEvuhFBkMIbHbEDXU9xbjFpBUid1VDFlyn4cZzeFdRXzZC7nxwE4C4
e3ktcFbvpa0R3m5olu8WF7/qNjFLV1TDMZt5twGGfZ/IWICMuZHH8JZEXSBtyBPniVkiqg/CwGbc
rS4hsACHtodSMAx1gXwRJs0SswRu0Q5s0jJ1hAAks70JgU1GzPYg4/ePIQchPcjy4MO+JLZCDxJZ
YSjdjyy3e5GRNfomZrcLjpDdUn9SoidpPOKY8um+fpdkbAOtck+y+icZd6ND8h1iLuJvMk/MDeKW
YcwmRAEmdf2aBSJ67iBH3upcxsuphOZY8EcqpuGLtBDXJV4BnKqr5RzRhk7DgmYnLbOvVfatwKLu
ZPzGoXo610ltqtNsg61VYNRpBqxBowiBIVDfYt81uKqzv6byWcfGdwCeAjNAMAu8BoiFxKwAo2t/
O+efgIypk3wNH9/MpQLnTyAGVJc2T3JJXdWdE4jImYnrl/I1/id+AtByBs0nqRwTAAAAAElFTkSu
QmCC

------=_NextPart_000_0000_01C701A5.15C25F40
Content-Type: text/css;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.codinghorror.com/blog/styles-site.css

BODY {
	FONT-SIZE: 80%; BACKGROUND: #fff; MARGIN: 0px 0px 20px; FONT-FAMILY: =
tahoma, arial, sans-serif
}
BLOCKQUOTE {
	PADDING-RIGHT: 5px; PADDING-LEFT: 5px; BACKGROUND: #f5f5f5; =
PADDING-BOTTOM: 5px; COLOR: #333; PADDING-TOP: 5px; FONT-STYLE: normal; =
FONT-FAMILY: Arial, Sans-Serif
}
PRE {
	BORDER-RIGHT: silver 2px dotted; PADDING-RIGHT: 5px; BORDER-TOP: silver =
2px dotted; PADDING-LEFT: 5px; FONT-SIZE: 9pt; PADDING-BOTTOM: 5px; =
MARGIN: 0px auto; OVERFLOW: auto; BORDER-LEFT: silver 2px dotted; WIDTH: =
95%; LINE-HEIGHT: 100%; PADDING-TOP: 5px; BORDER-BOTTOM: silver 2px =
dotted; max-height: 450px
}
.code {
	BORDER-RIGHT: silver 2px dotted; PADDING-RIGHT: 5px; BORDER-TOP: silver =
2px dotted; PADDING-LEFT: 5px; FONT-SIZE: 9pt; PADDING-BOTTOM: 5px; =
MARGIN: 0px auto; OVERFLOW: auto; BORDER-LEFT: silver 2px dotted; WIDTH: =
95%; LINE-HEIGHT: 100%; PADDING-TOP: 5px; BORDER-BOTTOM: silver 2px =
dotted; max-height: 450px
}
H1 {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: =
0px; PADDING-TOP: 0px
}
H2 {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: =
0px; PADDING-TOP: 0px
}
H3 {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: =
0px; PADDING-TOP: 0px
}
#banner {
	PADDING-RIGHT: 15px; BORDER-TOP: #666 4px double; PADDING-LEFT: 15px; =
FONT-WEIGHT: normal; PADDING-BOTTOM: 15px; COLOR: #333; PADDING-TOP: =
15px
}
#banner A {
	COLOR: #333; TEXT-DECORATION: none
}
#banner A:link {
	COLOR: #333; TEXT-DECORATION: none
}
#banner A:visited {
	COLOR: #333; TEXT-DECORATION: none
}
#banner A:active {
	COLOR: #333; TEXT-DECORATION: none
}
#banner A:hover {
	COLOR: #333; TEXT-DECORATION: none
}
.description {
	TEXT-TRANSFORM: none; COLOR: #333
}
#content {
	BORDER-RIGHT: #fff 1px solid; BORDER-TOP: #fff 1px solid; BACKGROUND: =
#fff; MARGIN-BOTTOM: 20px; MARGIN-LEFT: 225px; BORDER-LEFT: #fff 1px =
solid; WIDTH: 70%; MARGIN-RIGHT: 20px; BORDER-BOTTOM: #fff 1px solid; =
POSITION: absolute
}
#container {
	BORDER-RIGHT: #fff 1px solid; BORDER-TOP: #fff 1px solid; BACKGROUND: =
#fff; BORDER-LEFT: #fff 1px solid; BORDER-BOTTOM: #fff 1px solid
}
#links {
	BORDER-RIGHT: #fff 1px solid; PADDING-RIGHT: 15px; BORDER-TOP: #fff 1px =
solid; PADDING-LEFT: 15px; PADDING-BOTTOM: 15px; BORDER-LEFT: #fff 1px =
solid; WIDTH: 200px; PADDING-TOP: 15px; BORDER-BOTTOM: #fff 1px solid
}
.blog {
	PADDING-RIGHT: 15px; PADDING-LEFT: 15px; BACKGROUND: #fff
}
.blogbody {
	FONT-WEIGHT: normal; BACKGROUND: #fff; COLOR: #333; LINE-HEIGHT: 130%
}
.blogbody A {
	FONT-WEIGHT: normal
}
.blogbody A:link {
	FONT-WEIGHT: normal
}
.blogbody A:visited {
	FONT-WEIGHT: normal
}
.blogbody A:active {
	FONT-WEIGHT: normal
}
.blogbody A:hover {
	FONT-WEIGHT: normal
}
.title {
	COLOR: #666
}
#menu {
	BACKGROUND: #fff; TEXT-ALIGN: center
}
.date {
	FONT-WEIGHT: bold; MARGIN-BOTTOM: 10px; COLOR: black; BORDER-BOTTOM: =
#999 1px solid
}
.posted {
	MARGIN-BOTTOM: 25px; COLOR: #000000
}
.calendar {
	PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: normal; BACKGROUND: =
#fff; PADDING-BOTTOM: 2px; COLOR: #666; LINE-HEIGHT: 140%; PADDING-TOP: =
2px; TEXT-ALIGN: left
}
.calendarhead {
	PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; BACKGROUND: =
#fff; PADDING-BOTTOM: 2px; TEXT-TRANSFORM: uppercase; COLOR: #666600; =
PADDING-TOP: 2px; LETTER-SPACING: 0.3em; TEXT-ALIGN: left
}
.side {
	PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: normal; BACKGROUND: =
#fff; PADDING-BOTTOM: 2px; COLOR: #333; LINE-HEIGHT: 140%; PADDING-TOP: =
2px
}
.sidetitle {
	PADDING-RIGHT: 2px; MARGIN-TOP: 15px; PADDING-LEFT: 2px; FONT-WEIGHT: =
bold; BACKGROUND: #fff; PADDING-BOTTOM: 2px; TEXT-TRANSFORM: uppercase; =
COLOR: #666; PADDING-TOP: 2px; LETTER-SPACING: 0.3em
}
.syndicate {
	PADDING-RIGHT: 2px; MARGIN-TOP: 15px; PADDING-LEFT: 2px; BACKGROUND: =
#fff; PADDING-BOTTOM: 2px; LINE-HEIGHT: 140%; PADDING-TOP: 2px
}
.comments-body {
	PADDING-RIGHT: 5px; PADDING-LEFT: 10px; FONT-WEIGHT: normal; =
BACKGROUND: #f5f5f5; MARGIN-BOTTOM: 10px; PADDING-BOTTOM: 15px; COLOR: =
#333; LINE-HEIGHT: 140%; PADDING-TOP: 5px
}
.comments-post {
	FONT-WEIGHT: normal; BACKGROUND: #f5f5f5; COLOR: #333
}
.trackback-url {
	BORDER-RIGHT: #999 1px dotted; PADDING-RIGHT: 5px; BORDER-TOP: #999 1px =
dotted; PADDING-LEFT: 5px; FONT-WEIGHT: normal; BACKGROUND: #fff; =
PADDING-BOTTOM: 5px; BORDER-LEFT: #999 1px dotted; COLOR: #666; =
LINE-HEIGHT: 140%; PADDING-TOP: 5px; BORDER-BOTTOM: #999 1px dotted
}
.trackback-body {
	FONT-WEIGHT: normal; BACKGROUND: #fff; PADDING-BOTTOM: 10px; COLOR: =
#666; LINE-HEIGHT: 140%; PADDING-TOP: 10px; BORDER-BOTTOM: #999 1px =
dotted
}
.trackback-post {
	FONT-WEIGHT: normal; BACKGROUND: #fff; COLOR: #666
}
.comments-head {
	MARGIN-TOP: 20px; FONT-WEIGHT: bold; BACKGROUND: #fff; MARGIN-BOTTOM: =
5px; COLOR: #666
}
#banner-commentspop {
	BORDER-RIGHT: #fff 1px solid; PADDING-RIGHT: 15px; BORDER-TOP: #fff 1px =
solid; PADDING-LEFT: 15px; FONT-WEIGHT: bold; BACKGROUND: #003366; =
PADDING-BOTTOM: 5px; BORDER-LEFT: #fff 1px solid; COLOR: #fff; =
PADDING-TOP: 5px
}
.linecomment {
	COLOR: #ff8000
}
.blockcomment {
	COLOR: #ff8000
}
.prepro {
	COLOR: #0000bb
}
.select {
=09
}
.quote {
	COLOR: #dd0000
}
.category1 {
	COLOR: #007700
}
.category2 {
	COLOR: #0000bb
}
.category3 {
	COLOR: #0000bb
}

------=_NextPart_000_0000_01C701A5.15C25F40
Content-Type: text/css;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.codinghorror.com/blog/includes/SyntaxHighlighter.css

.dp-highlighter {
	WIDTH: 100%
}
.dp-highlighter TABLE {
	MARGIN: 2px 0px; WIDTH: 100%; BORDER-COLLAPSE: collapse; =
BACKGROUND-COLOR: #fff
}
.dp-highlighter TBODY.hide {
	DISPLAY: none
}
.dp-highlighter TBODY.show {
	DISPLAY: block
}
.dp-highlighter TD {
	FONT-SIZE: small; FONT-FAMILY: monospace
}
.dp-highlighter .tools-corner {
	FONT-SIZE: small; BACKGROUND-COLOR: #eee
}
.dp-highlighter .tools {
	PADDING-RIGHT: 8px; PADDING-LEFT: 0px; FONT-SIZE: small; =
PADDING-BOTTOM: 1px; PADDING-TOP: 1px; BACKGROUND-COLOR: #eee; =
TEXT-ALIGN: right
}
.dp-highlighter .tools-corner {
	BACKGROUND-COLOR: #eee
}
.dp-highlighter .tools A {
	COLOR: navy; FONT-FAMILY: Tahoma, Verdana, Arial; TEXT-DECORATION: none
}
.dp-highlighter .tools A:hover {
	COLOR: red; TEXT-DECORATION: underline
}
.dp-highlighter .gutter {
	PADDING-RIGHT: 5px; PADDING-LEFT: 10px; VERTICAL-ALIGN: top; WIDTH: =
5px; COLOR: white; BACKGROUND-COLOR: darkgray; TEXT-ALIGN: right
}
.dp-highlighter .line1 {
	PADDING-LEFT: 10px; WHITE-SPACE: nowrap
}
.line2 {
	PADDING-LEFT: 10px; WHITE-SPACE: nowrap
}
.dp-about {
	MARGIN: 0px; BACKGROUND-COLOR: #fff
}
.dp-about TABLE {
	FONT-SIZE: 70%; WIDTH: 100%; FONT-FAMILY: Tahoma, Verdana, Arial, =
sans-serif! important; HEIGHT: 100%
}
.dp-about TD {
	PADDING-RIGHT: 10px; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; =
VERTICAL-ALIGN: top; PADDING-TOP: 10px
}
.dp-about .copy {
	BORDER-BOTTOM: #aca899 1px solid; HEIGHT: 95%
}
.dp-about .title {
	FONT-WEIGHT: bold; COLOR: red
}
.dp-about .para {
	MARGIN-BOTTOM: 4px
}
.dp-about .footer {
	BORDER-TOP: #fff 1px solid; BACKGROUND-COLOR: #eceadb; TEXT-ALIGN: =
right
}
.dp-about .close {
	FONT-SIZE: 70%; WIDTH: 60px; FONT-FAMILY: Tahoma, Verdana, Arial, =
sans-serif! important; HEIGHT: 22px; BACKGROUND-COLOR: #eceadb
}
.dp-c {
=09
}
.dp-c .comment {
	COLOR: green
}
.dp-c .string {
	COLOR: black; BACKGROUND-COLOR: lightyellow
}
.dp-c .preprocessor {
	COLOR: gray
}
.dp-c .keyword {
	COLOR: blue
}
.dp-c .vars {
	COLOR: #d00
}
.dp-vb {
=09
}
.dp-vb .comment {
	COLOR: green
}
.dp-vb .string {
	COLOR: black; BACKGROUND-COLOR: lightyellow
}
.dp-vb .preprocessor {
	COLOR: gray
}
.dp-vb .keyword {
	COLOR: blue
}
.dp-sql {
=09
}
.dp-sql .comment {
	COLOR: green
}
.dp-sql .string {
	COLOR: black; BACKGROUND-COLOR: lightyellow
}
.dp-sql .keyword {
	COLOR: blue
}
.dp-sql .func {
	COLOR: #ff1493
}
.dp-sql .op {
	COLOR: #808080
}
.dp-xml {
=09
}
.dp-xml .cdata {
	COLOR: #ff1493
}
.dp-xml .comments {
	COLOR: green
}
.dp-xml .tag {
	COLOR: blue
}
.dp-xml .tag-name {
	FONT-WEIGHT: bold; COLOR: blue
}
.dp-xml .attribute {
	COLOR: red
}
.dp-xml .attribute-value {
	COLOR: blue
}

------=_NextPart_000_0000_01C701A5.15C25F40
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.codinghorror.com/blog/includes/shCore.js

/**
 * Code Syntax Highlighter.
 * Version 1.3.0
 * Copyright (C) 2004 Alex Gorbatchev.
 * http://www.dreamprojections.com/syntaxhighlighter/
 *=20
 * This library is free software; you can redistribute it and/or modify =
it under the terms of the GNU Lesser General=20
 * Public License as published by the Free Software Foundation; either =
version 2.1 of the License, or (at your option)=20
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but =
WITHOUT ANY WARRANTY; without even the implied=20
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See =
the GNU Lesser General Public License for more=20
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public =
License along with this library; if not, write to=20
 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, =
Boston, MA 02111-1307 USA=20
 */

//
// create namespaces
//
var dp =3D {
	sh :					// dp.sh
	{
		Utils	: {},		// dp.sh.Utils
		Brushes	: {},		// dp.sh.Brushes
		Strings : {},
		Version : '1.3.0'
	}
};

dp.sh.Strings =3D {
	AboutDialog : '<html><head><title>About...</title></head><body =
class=3D"dp-about"><table cellspacing=3D"0"><tr><td class=3D"copy"><p =
class=3D"title">dp.SyntaxHighlighter</div><div class=3D"para">Version: =
{V}</p><p><a =
href=3D"http://www.dreamprojections.com/syntaxhighlighter/?ref=3Dabout" =
target=3D"_blank">http://www.dreamprojections.com/SyntaxHighlighter</a></=
p>&copy;2004-2005 Alex Gorbatchev. All right reserved.</td></tr><tr><td =
class=3D"footer"><input type=3D"button" class=3D"close" value=3D"OK" =
onClick=3D"window.close()"/></td></tr></table></body></html>',
=09
	// tools
	ExpandCode : '+ expand code',
	ViewPlain : 'view plain',
	Print : 'print',
	CopyToClipboard : 'copy to clipboard',
	About : '?',
=09
	CopiedToClipboard : 'The code is in your clipboard now.'
};

dp.SyntaxHighlighter =3D dp.sh;

//
// Dialog and toolbar functions
//

dp.sh.Utils.Expand =3D function(sender)
{
	var table =3D sender;
	var span =3D sender;

	// find the span in which the text label and pipe contained so we can =
hide it
	while(span !=3D null && span.tagName !=3D 'SPAN')
		span =3D span.parentNode;

	// find the table
	while(table !=3D null && table.tagName !=3D 'TABLE')
		table =3D table.parentNode;
=09
	// remove the 'expand code' button
	span.parentNode.removeChild(span);
=09
	table.tBodies[0].className =3D 'show';
	table.parentNode.style.height =3D '100%'; // containing div isn't =
getting updated properly when the TBODY is shown
}

// opens a new windows and puts the original unformatted source code =
inside.
dp.sh.Utils.ViewSource =3D function(sender)
{
	var code =3D sender.parentNode.originalCode;
	var wnd =3D window.open('', '_blank', 'width=3D750, height=3D400, =
location=3D0, resizable=3D1, menubar=3D0, scrollbars=3D1');
=09
	code =3D code.replace(/</g, '&lt;');
=09
	wnd.document.write('<pre>' + code + '</pre>');
	wnd.document.close();
}

// copies the original source code in to the clipboard (IE only)
dp.sh.Utils.ToClipboard =3D function(sender)
{
	var code =3D sender.parentNode.originalCode;
=09
	// This works only for IE. There's a way to make it work with Mozilla =
as well,
	// but it requires security settings changed on the client, which isn't =
by
	// default, so 99% of users won't have it working anyways.
	if(window.clipboardData)
	{
		window.clipboardData.setData('text', code);
	=09
		alert(dp.sh.Strings.CopiedToClipboard);
	}
}

// creates an invisible iframe, puts the original source code inside and =
prints it
dp.sh.Utils.PrintSource =3D function(sender)
{
	var td		=3D sender.parentNode;
	var code	=3D td.processedCode;
	var iframe	=3D document.createElement('IFRAME');
	var doc		=3D null;
	var wnd		=3D=20

	// this hides the iframe
	iframe.style.cssText =3D 'position:absolute; width:0px; height:0px; =
left:-5px; top:-5px;';
=09
	td.appendChild(iframe);
=09
	doc =3D iframe.contentWindow.document;
	code =3D code.replace(/</g, '&lt;');
=09
	doc.open();
	doc.write('<pre>' + code + '</pre>');
	doc.close();
=09
	iframe.contentWindow.focus();
	iframe.contentWindow.print();
=09
	td.removeChild(iframe);
}

dp.sh.Utils.About =3D function()
{
	var wnd	=3D window.open('', '_blank', =
'dialog,width=3D320,height=3D150,scrollbars=3D0');
	var doc	=3D wnd.document;
=09
	var styles =3D document.getElementsByTagName('style');
	var links =3D document.getElementsByTagName('link');
=09
	doc.write(dp.sh.Strings.AboutDialog.replace('{V}', dp.sh.Version));
=09
	// copy over ALL the styles from the parent page
	for(var i =3D 0; i < styles.length; i++)
		doc.write('<style>' + styles[i].innerHTML + '</style>');

	for(var i =3D 0; i < links.length; i++)
		if(links[i].rel.toLowerCase() =3D=3D 'stylesheet')
			doc.write('<link type=3D"text/css" rel=3D"stylesheet" href=3D"' + =
links[i].href + '"></link>');
=09
	doc.close();
	wnd.focus();
}

//
// Match object
//
dp.sh.Match =3D function(value, index, css)
{
	this.value		=3D value;
	this.index		=3D index;
	this.length		=3D value.length;
	this.css		=3D css;
}

//
// Highlighter object
//
dp.sh.Highlighter =3D function()
{
	this.addGutter =3D true;
	this.addControls =3D true;
	this.collapse =3D false;
	this.tabsToSpaces =3D true;
}

// static callback for the match sorting
dp.sh.Highlighter.SortCallback =3D function(m1, m2)
{
	// sort matches by index first
	if(m1.index < m2.index)
		return -1;
	else if(m1.index > m2.index)
		return 1;
	else
	{
		// if index is the same, sort by length
		if(m1.length < m2.length)
			return -1;
		else if(m1.length > m2.length)
			return 1;
	}
	return 0;
}

// gets a list of all matches for a given regular expression
dp.sh.Highlighter.prototype.GetMatches =3D function(regex, css)
{
	var index =3D 0;
	var match =3D null;

	while((match =3D regex.exec(this.code)) !=3D null)
	{
		this.matches[this.matches.length] =3D new dp.sh.Match(match[0], =
match.index, css);
	}
}

dp.sh.Highlighter.prototype.AddBit =3D function(str, css)
{
	var span =3D document.createElement('span');
=09
	str =3D str.replace(/&/g, '&amp;');
	str =3D str.replace(/ /g, '&nbsp;');
	str =3D str.replace(/</g, '&lt;');
	str =3D str.replace(/\n/gm, '&nbsp;<br>');

	// when adding a piece of code, check to see if it has line breaks in =
it=20
	// and if it does, wrap individual line breaks with span tags
	if(css !=3D null)
	{
		var regex =3D new RegExp('<br>', 'gi');
	=09
		if(regex.test(str))
		{
			var lines =3D str.split('&nbsp;<br>');
		=09
			str =3D '';
		=09
			for(var i =3D 0; i < lines.length; i++)
			{
				span			=3D document.createElement('SPAN');
				span.className	=3D css;
				span.innerHTML	=3D lines[i];
			=09
				this.div.appendChild(span);
			=09
				// don't add a <BR> for the last line
				if(i + 1 < lines.length)
					this.div.appendChild(document.createElement('BR'));
			}
		}
		else
		{
			span.className =3D css;
			span.innerHTML =3D str;
			this.div.appendChild(span);
		}
	}
	else
	{
		span.innerHTML =3D str;
		this.div.appendChild(span);
	}
}

// checks if one match is inside any other match
dp.sh.Highlighter.prototype.IsInside =3D function(match)
{
	if(match =3D=3D null || match.length =3D=3D 0)
		return;
=09
	for(var i =3D 0; i < this.matches.length; i++)
	{
		var c =3D this.matches[i];
	=09
		if(c =3D=3D null)
			continue;
	=09
		if((match.index > c.index) && (match.index <=3D c.index + c.length))
			return true;
	}
=09
	return false;
}

dp.sh.Highlighter.prototype.ProcessRegexList =3D function()
{
	for(var i =3D 0; i < this.regexList.length; i++)
		this.GetMatches(this.regexList[i].regex, this.regexList[i].css);
}

dp.sh.Highlighter.prototype.ProcessSmartTabs =3D function(code)
{
	var lines	=3D code.split('\n');
	var result	=3D '';
	var tabSize	=3D 4;
	var tab		=3D '\t';

	// This function inserts specified amount of spaces in the string
	// where a tab is while removing that given tab.=20
	function InsertSpaces(line, pos, count)
	{
		var left	=3D line.substr(0, pos);
		var right	=3D line.substr(pos + 1, line.length);	// pos + 1 will get =
rid of the tab
		var spaces	=3D '';
	=09
		for(var i =3D 0; i < count; i++)
			spaces +=3D ' ';
	=09
		return left + spaces + right;
	}

	// This function process one line for 'smart tabs'
	function ProcessLine(line, tabSize)
	{
		if(line.indexOf(tab) =3D=3D -1)
			return line;

		var pos =3D 0;

		while((pos =3D line.indexOf(tab)) !=3D -1)
		{
			// This is pretty much all there is to the 'smart tabs' logic.
			// Based on the position within the line and size of a tab,=20
			// calculate the amount of spaces we need to insert.
			var spaces =3D tabSize - pos % tabSize;
		=09
			line =3D InsertSpaces(line, pos, spaces);
		}
	=09
		return line;
	}

	// Go through all the lines and do the 'smart tabs' magic.
	for(var i =3D 0; i < lines.length; i++)
		result +=3D ProcessLine(lines[i], tabSize) + '\n';
=09
	return result;
}

dp.sh.Highlighter.prototype.SwitchToTable =3D function()
{
	// thanks to Lachlan Donald from SitePoint.com for this <br/> tag fix.
	var html;=09
	html =3D this.div.innerHTML;
	html =3D html.replace(/\n/gi, '');
	html =3D html.replace(/<(br)\/?>/gi, '\n');

	var lines	=3D html.split('\n');
	var row		=3D null;
	var cell	=3D null;
	var tBody	=3D null;
	var html	=3D '';
	var pipe	=3D ' | ';
	=09
	// creates an anchor to a utility
	function UtilHref(util, text)
	{
		return '<a href=3D"#" onclick=3D"dp.sh.Utils.' + util + '(this); =
return false;">' + text + '</a>';
	}
=09
	tBody =3D document.createElement('TBODY');	// can be created and all =
others go to tBodies collection.

	this.table.appendChild(tBody);
	=09
	if(this.addGutter =3D=3D true)
	{
		row =3D tBody.insertRow(-1);
		cell =3D row.insertCell(-1);
		cell.className =3D 'tools-corner';
	}

	if(this.addControls =3D=3D true)
	{
		var tHead =3D document.createElement('THEAD');	// controls will be =
placed in here
		this.table.appendChild(tHead);

		row =3D tHead.insertRow(-1);

		// add corner if there's a gutter
		if(this.addGutter =3D=3D true)
		{
			cell =3D row.insertCell(-1);
			cell.className =3D 'tools-corner';
		}
	=09
		cell =3D row.insertCell(-1);
	=09
		// preserve some variables for the controls
		cell.originalCode =3D this.originalCode;
		cell.processedCode =3D this.code;
		cell.className =3D 'tools';
	=09
		if(this.collapse =3D=3D true)
		{
			tBody.className =3D 'hide';
			cell.innerHTML +=3D '<span><b>' + UtilHref('Expand', =
dp.sh.Strings.ExpandCode) + '</b>' + pipe + '</span>';
		}

		cell.innerHTML +=3D UtilHref('ViewSource', dp.sh.Strings.ViewPlain) + =
pipe + UtilHref('PrintSource', dp.sh.Strings.Print);
	=09
		// IE has this clipboard object which is easy enough to use
		if(window.clipboardData)
			cell.innerHTML +=3D pipe + UtilHref('ToClipboard', =
dp.sh.Strings.CopyToClipboard);
	=09
		cell.innerHTML +=3D pipe + UtilHref('About', dp.sh.Strings.About);
	}

	for(var i =3D 0, lineIndex =3D this.firstLine; i < lines.length - 1; =
i++, lineIndex++)
	{
		row =3D tBody.insertRow(-1);
	=09
		if(this.addGutter =3D=3D true)
		{
			cell =3D row.insertCell(-1);
			cell.className =3D 'gutter';
			cell.innerHTML =3D lineIndex;
		}

		cell =3D row.insertCell(-1);
		cell.className =3D 'line' + (i % 2 + 1);		// uses .line1 and .line2 =
css styles for alternating lines
		cell.innerHTML =3D lines[i];
	}
=09
	this.div.innerHTML	=3D '';
}

dp.sh.Highlighter.prototype.Highlight =3D function(code)
{
	function Trim(str)
	{
		return str.replace(/^\s*(.*?)[\s\n]*$/g, '$1');
	}
=09
	function Chop(str)
	{
		return str.replace(/\n*$/, '').replace(/^\n*/, '');
	}

	function Unindent(str)
	{
		var lines =3D str.split('\n');
		var indents =3D new Array();
		var regex =3D new RegExp('^\\s*', 'g');
		var min =3D 1000;

		// go through every line and check for common number of indents
		for(var i =3D 0; i < lines.length && min > 0; i++)
		{
			if(Trim(lines[i]).length =3D=3D 0)
				continue;
			=09
			var matches =3D regex.exec(lines[i]);

			if(matches !=3D null && matches.length > 0)
				min =3D Math.min(matches[0].length, min);
		}

		// trim minimum common number of white space from the begining of =
every line
		if(min > 0)
			for(var i =3D 0; i < lines.length; i++)
				lines[i] =3D lines[i].substr(min);

		return lines.join('\n');
	}
=09
	// This function returns a portions of the string from pos1 to pos2 =
inclusive
	function Copy(string, pos1, pos2)
	{
		return string.substr(pos1, pos2 - pos1);
	}

	var pos	=3D 0;
=09
	this.originalCode =3D code;
	this.code =3D Chop(Unindent(code));
	this.div =3D document.createElement('DIV');
	this.table =3D document.createElement('TABLE');
	this.matches =3D new Array();

	if(this.CssClass !=3D null)
		this.table.className =3D this.CssClass;

	// replace tabs with spaces
	if(this.tabsToSpaces =3D=3D true)
		this.code =3D this.ProcessSmartTabs(this.code);

	this.table.border =3D 0;
	this.table.cellSpacing =3D 0;
	this.table.cellPadding =3D 0;

	this.ProcessRegexList();=09

	// if no matches found, add entire code as plain text
	if(this.matches.length =3D=3D 0)
	{
		this.AddBit(this.code, null);
		this.SwitchToTable();
		return;
	}

	// sort the matches
	this.matches =3D this.matches.sort(dp.sh.Highlighter.SortCallback);

	// The following loop checks to see if any of the matches are inside
	// of other matches. This process would get rid of highligting strings
	// inside comments, keywords inside strings and so on.
	for(var i =3D 0; i < this.matches.length; i++)
		if(this.IsInside(this.matches[i]))
			this.matches[i] =3D null;

	// Finally, go through the final list of matches and pull the all
	// together adding everything in between that isn't a match.
	for(var i =3D 0; i < this.matches.length; i++)
	{
		var match =3D this.matches[i];

		if(match =3D=3D null || match.length =3D=3D 0)
			continue;
	=09
		this.AddBit(Copy(this.code, pos, match.index), null);
		this.AddBit(match.value, match.css);
	=09
		pos =3D match.index + match.length;
	}
=09
	this.AddBit(this.code.substr(pos), null);

	this.SwitchToTable();
}

dp.sh.Highlighter.prototype.GetKeywords =3D function(str)=20
{
	return '\\b' + str.replace(/ /g, '\\b|\\b') + '\\b';
}

// highlightes all elements identified by name and gets source code from =
specified property
dp.sh.HighlightAll =3D function(name, showGutter /* optional */, =
showControls /* optional */, collapseAll /* optional */, firstLine /* =
optional */)
{
	function FindValue()
	{
		var a =3D arguments;
	=09
		for(var i =3D 0; i < a.length; i++)
		{
			if(a[i] =3D=3D null)
				continue;
			=09
			if(typeof(a[i]) =3D=3D 'string' && a[i] !=3D '')
				return a[i] + '';
	=09
			if(typeof(a[i]) =3D=3D 'object' && a[i].value !=3D '')
				return a[i].value + '';
		}
	=09
		return null;
	}
=09
	function IsOptionSet(value, list)
	{
		for(var i =3D 0; i < list.length; i++)
			if(list[i] =3D=3D value)
				return true;
	=09
		return false;
	}
=09
	function GetOptionValue(name, list, defaultValue)
	{
		var regex =3D new RegExp('^' + name + '\\[(\\w+)\\]$', 'gi');
		var matches =3D null;

		for(var i =3D 0; i < list.length; i++)
			if((matches =3D regex.exec(list[i])) !=3D null)
				return matches[1];
	=09
		return defaultValue;
	}

	var elements =3D document.getElementsByTagName("PRE");
	var highlighter =3D null;
	var registered =3D new Object();
	var propertyName =3D 'value';
=09
	// if no code blocks found, leave
	if(elements =3D=3D null)
		return;
=09
	if (elements.length =3D=3D 0)
	    return;

	// register all brushes
	for(var brush in dp.sh.Brushes)
	{
		var aliases =3D dp.sh.Brushes[brush].Aliases;
	=09
		if(aliases =3D=3D null)
			continue;
	=09
		for(var i =3D 0; i < aliases.length; i++)
			registered[aliases[i]] =3D brush;
	}

	for(var i =3D 0; i < elements.length; i++)
	{
		var element =3D elements[i];
		var options =3D FindValue(
				element.attributes['class'], element.className,=20
				element.attributes['language'], element.language
				);
		var language =3D '';
	=09
		if(options =3D=3D null)
			continue;
	=09
		options =3D options.split(':');
	=09
		language =3D options[0].toLowerCase();
	=09
		if(registered[language] =3D=3D null)
			continue;
	=09
		// instantiate a brush
		highlighter =3D new dp.sh.Brushes[registered[language]]();
=09
		highlighter.addGutter =3D (showGutter =3D=3D null) ? =
!IsOptionSet('nogutter', options) : showGutter;
		highlighter.addControls =3D (showControls =3D=3D null) ? =
!IsOptionSet('nocontrols', options) : showControls;
		highlighter.collapse =3D (collapseAll =3D=3D null) ? =
IsOptionSet('collapse', options) : collapseAll;
	=09
		// first line idea comes from Andrew Collington, thanks!
		highlighter.firstLine =3D (firstLine =3D=3D null) ? =
parseInt(GetOptionValue('firstline', options, 1)) : firstLine;
   	=09
		if (navigator.appVersion.indexOf("MSIE") =3D=3D -1) {=09
		    // innerText isn't available in Mozilla variants
			highlighter.Highlight(dp.sh.Utils.HtmlDecode(element.innerHTML));
		}=20
		else
		{
			highlighter.Highlight(element.innerText);
		}	=09

		// hide the original element
		element.style.display =3D 'none';

		// place the result table inside a div
		var div =3D document.createElement('DIV');
	=09
		div.className =3D 'dp-highlighter';
		div.appendChild(highlighter.table);

		element.parentNode.insertBefore(div, element);	=09
	}=09
}


// Gecko rendering engine (Mozilla, Firefox) can't do .innerText
// so we must convert .innerHTML to .innerText using this function
//
// http://blogs.msdn.com/aoakley/archive/2003/11/12/49645.aspx=20
// http://lab.msdn.microsoft.com/annotations/htmldecode.js
//
dp.sh.Utils.HtmlDecode =3D function(s)
{
	var out =3D "";
	if (s=3D=3Dnull) return;

	var l =3D s.length;
	for (var i=3D0; i<l; i++)
	{
		var ch =3D s.charAt(i);
	=09
		if (ch =3D=3D '&')=20
		{
			var semicolonIndex =3D s.indexOf(';', i+1);
		=09
            if (semicolonIndex > 0)=20
            {
				var entity =3D s.substring(i + 1, semicolonIndex);
				if (entity.length > 1 && entity.charAt(0) =3D=3D '#')=20
				{
					if (entity.charAt(1) =3D=3D 'x' || entity.charAt(1) =3D=3D 'X')
						ch =3D String.fromCharCode(eval('0'+entity.substring(1)));
					else
						ch =3D String.fromCharCode(eval(entity.substring(1)));
				}
		        else=20
			    {
					switch (entity)
					{
						case 'quot': ch =3D String.fromCharCode(0x0022); break;
						case 'amp': ch =3D String.fromCharCode(0x0026); break;
						case 'lt': ch =3D String.fromCharCode(0x003c); break;
						case 'gt': ch =3D String.fromCharCode(0x003e); break;
						case 'nbsp': ch =3D String.fromCharCode(0x00a0); break;
						case 'iexcl': ch =3D String.fromCharCode(0x00a1); break;
						case 'cent': ch =3D String.fromCharCode(0x00a2); break;
						case 'pound': ch =3D String.fromCharCode(0x00a3); break;
						case 'curren': ch =3D String.fromCharCode(0x00a4); break;
						case 'yen': ch =3D String.fromCharCode(0x00a5); break;
						case 'brvbar': ch =3D String.fromCharCode(0x00a6); break;
						case 'sect': ch =3D String.fromCharCode(0x00a7); break;
						case 'uml': ch =3D String.fromCharCode(0x00a8); break;
						case 'copy': ch =3D String.fromCharCode(0x00a9); break;
						case 'ordf': ch =3D String.fromCharCode(0x00aa); break;
						case 'laquo': ch =3D String.fromCharCode(0x00ab); break;
						case 'not': ch =3D String.fromCharCode(0x00ac); break;
						case 'shy': ch =3D String.fromCharCode(0x00ad); break;
						case 'reg': ch =3D String.fromCharCode(0x00ae); break;
						case 'macr': ch =3D String.fromCharCode(0x00af); break;
						case 'deg': ch =3D String.fromCharCode(0x00b0); break;
						case 'plusmn': ch =3D String.fromCharCode(0x00b1); break;
						case 'sup2': ch =3D String.fromCharCode(0x00b2); break;
						case 'sup3': ch =3D String.fromCharCode(0x00b3); break;
						case 'acute': ch =3D String.fromCharCode(0x00b4); break;
						case 'micro': ch =3D String.fromCharCode(0x00b5); break;
						case 'para': ch =3D String.fromCharCode(0x00b6); break;
						case 'middot': ch =3D String.fromCharCode(0x00b7); break;
						case 'cedil': ch =3D String.fromCharCode(0x00b8); break;
						case 'sup1': ch =3D String.fromCharCode(0x00b9); break;
						case 'ordm': ch =3D String.fromCharCode(0x00ba); break;
						case 'raquo': ch =3D String.fromCharCode(0x00bb); break;
						case 'frac14': ch =3D String.fromCharCode(0x00bc); break;
						case 'frac12': ch =3D String.fromCharCode(0x00bd); break;
						case 'frac34': ch =3D String.fromCharCode(0x00be); break;
						case 'iquest': ch =3D String.fromCharCode(0x00bf); break;
						case 'Agrave': ch =3D String.fromCharCode(0x00c0); break;
						case 'Aacute': ch =3D String.fromCharCode(0x00c1); break;
						case 'Acirc': ch =3D String.fromCharCode(0x00c2); break;
						case 'Atilde': ch =3D String.fromCharCode(0x00c3); break;
						case 'Auml': ch =3D String.fromCharCode(0x00c4); break;
						case 'Aring': ch =3D String.fromCharCode(0x00c5); break;
						case 'AElig': ch =3D String.fromCharCode(0x00c6); break;
						case 'Ccedil': ch =3D String.fromCharCode(0x00c7); break;
						case 'Egrave': ch =3D String.fromCharCode(0x00c8); break;
						case 'Eacute': ch =3D String.fromCharCode(0x00c9); break;
						case 'Ecirc': ch =3D String.fromCharCode(0x00ca); break;
						case 'Euml': ch =3D String.fromCharCode(0x00cb); break;
						case 'Igrave': ch =3D String.fromCharCode(0x00cc); break;
						case 'Iacute': ch =3D String.fromCharCode(0x00cd); break;
						case 'Icirc': ch =3D String.fromCharCode(0x00ce); break;
						case 'Iuml': ch =3D String.fromCharCode(0x00cf); break;
						case 'ETH': ch =3D String.fromCharCode(0x00d0); break;
						case 'Ntilde': ch =3D String.fromCharCode(0x00d1); break;
						case 'Ograve': ch =3D String.fromCharCode(0x00d2); break;
						case 'Oacute': ch =3D String.fromCharCode(0x00d3); break;
						case 'Ocirc': ch =3D String.fromCharCode(0x00d4); break;
						case 'Otilde': ch =3D String.fromCharCode(0x00d5); break;
						case 'Ouml': ch =3D String.fromCharCode(0x00d6); break;
						case 'times': ch =3D String.fromCharCode(0x00d7); break;
						case 'Oslash': ch =3D String.fromCharCode(0x00d8); break;
						case 'Ugrave': ch =3D String.fromCharCode(0x00d9); break;
						case 'Uacute': ch =3D String.fromCharCode(0x00da); break;
						case 'Ucirc': ch =3D String.fromCharCode(0x00db); break;
						case 'Uuml': ch =3D String.fromCharCode(0x00dc); break;
						case 'Yacute': ch =3D String.fromCharCode(0x00dd); break;
						case 'THORN': ch =3D String.fromCharCode(0x00de); break;
						case 'szlig': ch =3D String.fromCharCode(0x00df); break;
						case 'agrave': ch =3D String.fromCharCode(0x00e0); break;
						case 'aacute': ch =3D String.fromCharCode(0x00e1); break;
						case 'acirc': ch =3D String.fromCharCode(0x00e2); break;
						case 'atilde': ch =3D String.fromCharCode(0x00e3); break;
						case 'auml': ch =3D String.fromCharCode(0x00e4); break;
						case 'aring': ch =3D String.fromCharCode(0x00e5); break;
						case 'aelig': ch =3D String.fromCharCode(0x00e6); break;
						case 'ccedil': ch =3D String.fromCharCode(0x00e7); break;
						case 'egrave': ch =3D String.fromCharCode(0x00e8); break;
						case 'eacute': ch =3D String.fromCharCode(0x00e9); break;
						case 'ecirc': ch =3D String.fromCharCode(0x00ea); break;
						case 'euml': ch =3D String.fromCharCode(0x00eb); break;
						case 'igrave': ch =3D String.fromCharCode(0x00ec); break;
						case 'iacute': ch =3D String.fromCharCode(0x00ed); break;
						case 'icirc': ch =3D String.fromCharCode(0x00ee); break;
						case 'iuml': ch =3D String.fromCharCode(0x00ef); break;
						case 'eth': ch =3D String.fromCharCode(0x00f0); break;
						case 'ntilde': ch =3D String.fromCharCode(0x00f1); break;
						case 'ograve': ch =3D String.fromCharCode(0x00f2); break;
						case 'oacute': ch =3D String.fromCharCode(0x00f3); break;
						case 'ocirc': ch =3D String.fromCharCode(0x00f4); break;
						case 'otilde': ch =3D String.fromCharCode(0x00f5); break;
						case 'ouml': ch =3D String.fromCharCode(0x00f6); break;
						case 'divide': ch =3D String.fromCharCode(0x00f7); break;
						case 'oslash': ch =3D String.fromCharCode(0x00f8); break;
						case 'ugrave': ch =3D String.fromCharCode(0x00f9); break;
						case 'uacute': ch =3D String.fromCharCode(0x00fa); break;
						case 'ucirc': ch =3D String.fromCharCode(0x00fb); break;
						case 'uuml': ch =3D String.fromCharCode(0x00fc); break;
						case 'yacute': ch =3D String.fromCharCode(0x00fd); break;
						case 'thorn': ch =3D String.fromCharCode(0x00fe); break;
						case 'yuml': ch =3D String.fromCharCode(0x00ff); break;
						case 'OElig': ch =3D String.fromCharCode(0x0152); break;
						case 'oelig': ch =3D String.fromCharCode(0x0153); break;
						case 'Scaron': ch =3D String.fromCharCode(0x0160); break;
						case 'scaron': ch =3D String.fromCharCode(0x0161); break;
						case 'Yuml': ch =3D String.fromCharCode(0x0178); break;
						case 'fnof': ch =3D String.fromCharCode(0x0192); break;
						case 'circ': ch =3D String.fromCharCode(0x02c6); break;
						case 'tilde': ch =3D String.fromCharCode(0x02dc); break;
						case 'Alpha': ch =3D String.fromCharCode(0x0391); break;
						case 'Beta': ch =3D String.fromCharCode(0x0392); break;
						case 'Gamma': ch =3D String.fromCharCode(0x0393); break;
						case 'Delta': ch =3D String.fromCharCode(0x0394); break;
						case 'Epsilon': ch =3D String.fromCharCode(0x0395); break;
						case 'Zeta': ch =3D String.fromCharCode(0x0396); break;
						case 'Eta': ch =3D String.fromCharCode(0x0397); break;
						case 'Theta': ch =3D String.fromCharCode(0x0398); break;
						case 'Iota': ch =3D String.fromCharCode(0x0399); break;
						case 'Kappa': ch =3D String.fromCharCode(0x039a); break;
						case 'Lambda': ch =3D String.fromCharCode(0x039b); break;
						case 'Mu': ch =3D String.fromCharCode(0x039c); break;
						case 'Nu': ch =3D String.fromCharCode(0x039d); break;
						case 'Xi': ch =3D String.fromCharCode(0x039e); break;
						case 'Omicron': ch =3D String.fromCharCode(0x039f); break;
						case 'Pi': ch =3D String.fromCharCode(0x03a0); break;
						case 'Rho': ch =3D String.fromCharCode(0x03a1); break;
						case 'Sigma': ch =3D String.fromCharCode(0x03a3); break;
						case 'Tau': ch =3D String.fromCharCode(0x03a4); break;
						case 'Upsilon': ch =3D String.fromCharCode(0x03a5); break;
						case 'Phi': ch =3D String.fromCharCode(0x03a6); break;
						case 'Chi': ch =3D String.fromCharCode(0x03a7); break;
						case 'Psi': ch =3D String.fromCharCode(0x03a8); break;
						case 'Omega': ch =3D String.fromCharCode(0x03a9); break;
						case 'alpha': ch =3D String.fromCharCode(0x03b1); break;
						case 'beta': ch =3D String.fromCharCode(0x03b2); break;
						case 'gamma': ch =3D String.fromCharCode(0x03b3); break;
						case 'delta': ch =3D String.fromCharCode(0x03b4); break;
						case 'epsilon': ch =3D String.fromCharCode(0x03b5); break;
						case 'zeta': ch =3D String.fromCharCode(0x03b6); break;
						case 'eta': ch =3D String.fromCharCode(0x03b7); break;
						case 'theta': ch =3D String.fromCharCode(0x03b8); break;
						case 'iota': ch =3D String.fromCharCode(0x03b9); break;
						case 'kappa': ch =3D String.fromCharCode(0x03ba); break;
						case 'lambda': ch =3D String.fromCharCode(0x03bb); break;
						case 'mu': ch =3D String.fromCharCode(0x03bc); break;
						case 'nu': ch =3D String.fromCharCode(0x03bd); break;
						case 'xi': ch =3D String.fromCharCode(0x03be); break;
						case 'omicron': ch =3D String.fromCharCode(0x03bf); break;
						case 'pi': ch =3D String.fromCharCode(0x03c0); break;
						case 'rho': ch =3D String.fromCharCode(0x03c1); break;
						case 'sigmaf': ch =3D String.fromCharCode(0x03c2); break;
						case 'sigma': ch =3D String.fromCharCode(0x03c3); break;
						case 'tau': ch =3D String.fromCharCode(0x03c4); break;
						case 'upsilon': ch =3D String.fromCharCode(0x03c5); break;
						case 'phi': ch =3D String.fromCharCode(0x03c6); break;
						case 'chi': ch =3D String.fromCharCode(0x03c7); break;
						case 'psi': ch =3D String.fromCharCode(0x03c8); break;
						case 'omega': ch =3D String.fromCharCode(0x03c9); break;
						case 'thetasym': ch =3D String.fromCharCode(0x03d1); break;
						case 'upsih': ch =3D String.fromCharCode(0x03d2); break;
						case 'piv': ch =3D String.fromCharCode(0x03d6); break;
						case 'ensp': ch =3D String.fromCharCode(0x2002); break;
						case 'emsp': ch =3D String.fromCharCode(0x2003); break;
						case 'thinsp': ch =3D String.fromCharCode(0x2009); break;
						case 'zwnj': ch =3D String.fromCharCode(0x200c); break;
						case 'zwj': ch =3D String.fromCharCode(0x200d); break;
						case 'lrm': ch =3D String.fromCharCode(0x200e); break;
						case 'rlm': ch =3D String.fromCharCode(0x200f); break;
						case 'ndash': ch =3D String.fromCharCode(0x2013); break;
						case 'mdash': ch =3D String.fromCharCode(0x2014); break;
						case 'lsquo': ch =3D String.fromCharCode(0x2018); break;
						case 'rsquo': ch =3D String.fromCharCode(0x2019); break;
						case 'sbquo': ch =3D String.fromCharCode(0x201a); break;
						case 'ldquo': ch =3D String.fromCharCode(0x201c); break;
						case 'rdquo': ch =3D String.fromCharCode(0x201d); break;
						case 'bdquo': ch =3D String.fromCharCode(0x201e); break;
						case 'dagger': ch =3D String.fromCharCode(0x2020); break;
						case 'Dagger': ch =3D String.fromCharCode(0x2021); break;
						case 'bull': ch =3D String.fromCharCode(0x2022); break;
						case 'hellip': ch =3D String.fromCharCode(0x2026); break;
						case 'permil': ch =3D String.fromCharCode(0x2030); break;
						case 'prime': ch =3D String.fromCharCode(0x2032); break;
						case 'Prime': ch =3D String.fromCharCode(0x2033); break;
						case 'lsaquo': ch =3D String.fromCharCode(0x2039); break;
						case 'rsaquo': ch =3D String.fromCharCode(0x203a); break;
						case 'oline': ch =3D String.fromCharCode(0x203e); break;
						case 'frasl': ch =3D String.fromCharCode(0x2044); break;
						case 'euro': ch =3D String.fromCharCode(0x20ac); break;
						case 'image': ch =3D String.fromCharCode(0x2111); break;
						case 'weierp': ch =3D String.fromCharCode(0x2118); break;
						case 'real': ch =3D String.fromCharCode(0x211c); break;
						case 'trade': ch =3D String.fromCharCode(0x2122); break;
						case 'alefsym': ch =3D String.fromCharCode(0x2135); break;
						case 'larr': ch =3D String.fromCharCode(0x2190); break;
						case 'uarr': ch =3D String.fromCharCode(0x2191); break;
						case 'rarr': ch =3D String.fromCharCode(0x2192); break;
						case 'darr': ch =3D String.fromCharCode(0x2193); break;
						case 'harr': ch =3D String.fromCharCode(0x2194); break;
						case 'crarr': ch =3D String.fromCharCode(0x21b5); break;
						case 'lArr': ch =3D String.fromCharCode(0x21d0); break;
						case 'uArr': ch =3D String.fromCharCode(0x21d1); break;
						case 'rArr': ch =3D String.fromCharCode(0x21d2); break;
						case 'dArr': ch =3D String.fromCharCode(0x21d3); break;
						case 'hArr': ch =3D String.fromCharCode(0x21d4); break;
						case 'forall': ch =3D String.fromCharCode(0x2200); break;
						case 'part': ch =3D String.fromCharCode(0x2202); break;
						case 'exist': ch =3D String.fromCharCode(0x2203); break;
						case 'empty': ch =3D String.fromCharCode(0x2205); break;
						case 'nabla': ch =3D String.fromCharCode(0x2207); break;
						case 'isin': ch =3D String.fromCharCode(0x2208); break;
						case 'notin': ch =3D String.fromCharCode(0x2209); break;
						case 'ni': ch =3D String.fromCharCode(0x220b); break;
						case 'prod': ch =3D String.fromCharCode(0x220f); break;
						case 'sum': ch =3D String.fromCharCode(0x2211); break;
						case 'minus': ch =3D String.fromCharCode(0x2212); break;
						case 'lowast': ch =3D String.fromCharCode(0x2217); break;
						case 'radic': ch =3D String.fromCharCode(0x221a); break;
						case 'prop': ch =3D String.fromCharCode(0x221d); break;
						case 'infin': ch =3D String.fromCharCode(0x221e); break;
						case 'ang': ch =3D String.fromCharCode(0x2220); break;
						case 'and': ch =3D String.fromCharCode(0x2227); break;
						case 'or': ch =3D String.fromCharCode(0x2228); break;
						case 'cap': ch =3D String.fromCharCode(0x2229); break;
						case 'cup': ch =3D String.fromCharCode(0x222a); break;
						case 'int': ch =3D String.fromCharCode(0x222b); break;
						case 'there4': ch =3D String.fromCharCode(0x2234); break;
						case 'sim': ch =3D String.fromCharCode(0x223c); break;
						case 'cong': ch =3D String.fromCharCode(0x2245); break;
						case 'asymp': ch =3D String.fromCharCode(0x2248); break;
						case 'ne': ch =3D String.fromCharCode(0x2260); break;
						case 'equiv': ch =3D String.fromCharCode(0x2261); break;
						case 'le': ch =3D String.fromCharCode(0x2264); break;
						case 'ge': ch =3D String.fromCharCode(0x2265); break;
						case 'sub': ch =3D String.fromCharCode(0x2282); break;
						case 'sup': ch =3D String.fromCharCode(0x2283); break;
						case 'nsub': ch =3D String.fromCharCode(0x2284); break;
						case 'sube': ch =3D String.fromCharCode(0x2286); break;
						case 'supe': ch =3D String.fromCharCode(0x2287); break;
						case 'oplus': ch =3D String.fromCharCode(0x2295); break;
						case 'otimes': ch =3D String.fromCharCode(0x2297); break;
						case 'perp': ch =3D String.fromCharCode(0x22a5); break;
						case 'sdot': ch =3D String.fromCharCode(0x22c5); break;
						case 'lceil': ch =3D String.fromCharCode(0x2308); break;
						case 'rceil': ch =3D String.fromCharCode(0x2309); break;
						case 'lfloor': ch =3D String.fromCharCode(0x230a); break;
						case 'rfloor': ch =3D String.fromCharCode(0x230b); break;
						case 'lang': ch =3D String.fromCharCode(0x2329); break;
						case 'rang': ch =3D String.fromCharCode(0x232a); break;
						case 'loz': ch =3D String.fromCharCode(0x25ca); break;
						case 'spades': ch =3D String.fromCharCode(0x2660); break;
						case 'clubs': ch =3D String.fromCharCode(0x2663); break;
						case 'hearts': ch =3D String.fromCharCode(0x2665); break;
						case 'diams': ch =3D String.fromCharCode(0x2666); break;
						default: ch =3D ''; break;
					}
				}
				i =3D semicolonIndex;=20
			}
		}	=09
		out +=3D ch;
	}
	return out;=09
}
------=_NextPart_000_0000_01C701A5.15C25F40
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.codinghorror.com/blog/includes/shBrushCSharp.js

dp.sh.Brushes.CSharp =3D function()
{
	var keywords =3D	'abstract as base bool break byte case catch char =
checked class const ' +
					'continue decimal default delegate do double else enum event =
explicit ' +
					'extern false finally fixed float for foreach get goto if implicit =
in int ' +
					'interface internal is lock long namespace new null object operator =
out ' +
					'override params private protected public readonly ref return sbyte =
sealed set ' +
					'short sizeof stackalloc static string struct switch this throw =
true try ' +
					'typeof uint ulong unchecked unsafe ushort using virtual void =
while';

	this.regexList =3D [
		// There's a slight problem with matching single line comments and =
figuring out
		// a difference between // and ///. Using lookahead and lookbehind =
solves the
		// problem, unfortunately JavaScript doesn't support lookbehind. So =
I'm at a=20
		// loss how to translate that regular expression to JavaScript =
compatible one.
//		{ regex: new =
RegExp('(?<!/)//(?!/).*$|(?<!/)////(?!/).*$|/\\*[^\\*]*(.)*?\\*/', =
'gm'),	css: 'comment' },			// one line comments starting with anything =
BUT '///' and multiline comments
//		{ regex: new RegExp('(?<!/)///(?!/).*$', 'gm'),											css: =
'comments' },		// XML comments starting with ///

		{ regex: new RegExp('//.*$', 'gm'),							css: 'comment' },			// one =
line comments
		{ regex: new RegExp('/\\*[\\s\\S]*?\\*/', 'g'),				css: 'comment' },			=
// multiline comments
		{ regex: new RegExp('"(?:\\.|[^\\""])*"', 'g'),				css: 'string' },			=
// strings
		{ regex: new RegExp('^\\s*#.*', 'gm'),						css: 'preprocessor' },		// =
preprocessor tags like #region and #endregion
		{ regex: new RegExp(this.GetKeywords(keywords), 'gm'),		css: 'keyword' =
}			// c# keyword
		];

	this.CssClass =3D 'dp-c';
}

dp.sh.Brushes.CSharp.prototype	=3D new dp.sh.Highlighter();
dp.sh.Brushes.CSharp.Aliases	=3D ['c#', 'c-sharp', 'csharp'];

------=_NextPart_000_0000_01C701A5.15C25F40
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.codinghorror.com/blog/includes/shBrushVb.js

dp.sh.Brushes.Vb =3D function()
{
	var keywords =3D	'AddHandler AddressOf AndAlso Alias And Ansi As =
Assembly Auto ' +
					'Boolean ByRef Byte ByVal Call Case Catch CBool CByte CChar CDate ' =
+
					'CDec CDbl Char CInt Class CLng CObj Const CShort CSng CStr CType ' =
+
					'Date Decimal Declare Default Delegate Dim DirectCast Do Double =
Each ' +
					'Else ElseIf End Enum Erase Error Event Exit False Finally For =
Friend ' +
					'Function Get GetType GoSub GoTo Handles If Implements Imports In ' =
+
					'Inherits Integer Interface Is Let Lib Like Long Loop Me Mod Module =
' +
					'MustInherit MustOverride MyBase MyClass Namespace New Next Not =
Nothing ' +
					'NotInheritable NotOverridable Object On Option Optional Or OrElse =
' +
					'Overloads Overridable Overrides ParamArray Preserve Private =
Property ' +
					'Protected Public RaiseEvent ReadOnly ReDim REM RemoveHandler =
Resume ' +
					'Return Select Set Shadows Shared Short Single Static Step Stop =
String ' +
					'Structure Sub SyncLock Then Throw To True Try TypeOf Unicode Until =
' +
					'Variant When While With WithEvents WriteOnly Xor';

	this.regexList =3D [
		{ regex: new RegExp('\'.*$', 'gm'),							css: 'comment' },			// one =
line comments
		{ regex: new RegExp('"(?:\\.|[^\\""])*"', 'g'),				css: 'string' },			=
// strings
		{ regex: new RegExp('^\\s*#.*', 'gm'),						css: 'preprocessor' },		// =
preprocessor tags like #region and #endregion
		{ regex: new RegExp(this.GetKeywords(keywords), 'gm'),		css: 'keyword' =
}			// c# keyword
		];

	this.CssClass =3D 'dp-vb';
}

dp.sh.Brushes.Vb.prototype	=3D new dp.sh.Highlighter();
dp.sh.Brushes.Vb.Aliases	=3D ['vb', 'vb.net'];

------=_NextPart_000_0000_01C701A5.15C25F40
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.codinghorror.com/blog/includes/shBrushSql.js

dp.sh.Brushes.Sql =3D function()
{
	var funcs	=3D	'abs avg case cast coalesce convert count =
current_timestamp ' +
					'current_user day isnull left lower month nullif replace right ' +
					'session_user space substring sum system_user upper user year';

	var keywords =3D	'absolute action add after alter as asc at =
authorization begin bigint ' +
					'binary bit by cascade char character check checkpoint close =
collate ' +
					'column commit committed connect connection constraint contains =
continue ' +
					'create cube current current_date current_time cursor database date =
' +
					'deallocate dec decimal declare default delete desc distinct double =
drop ' +
					'dynamic else end end-exec escape except exec execute false fetch =
first ' +
					'float for force foreign forward free from full function global =
goto grant ' +
					'group grouping having hour ignore index inner insensitive insert =
instead ' +
					'int integer intersect into is isolation key last level load local =
max min ' +
					'minute modify move name national nchar next no numeric of off on =
only ' +
					'open option order out output partial password precision prepare =
primary ' +
					'prior privileges procedure public read real references relative =
repeatable ' +
					'restrict return returns revoke rollback rollup rows rule schema =
scroll ' +
					'second section select sequence serializable set size smallint =
static ' +
					'statistics table temp temporary then time timestamp to top =
transaction ' +
					'translation trigger true truncate uncommitted union unique update =
values ' +
					'varchar varying view when where with work';

	var operators =3D	'all and any between cross in join like not null or =
outer some';

	this.regexList =3D [
		{ regex: new RegExp('--(.*)$', 'gm'),						css: 'comment' },			// one =
line and multiline comments
		{ regex: new RegExp('"(?:\\.|[^\\""])*"', 'g'),				css: 'string' },			=
// strings
		{ regex: new RegExp('\'(?:\\.|[^\\\'\'])*\'', 'g'),			css: 'string' },	=
		// strings
		{ regex: new RegExp(this.GetKeywords(funcs), 'gmi'),		css: 'func' },			=
	// functions
		{ regex: new RegExp(this.GetKeywords(operators), 'gmi'),	css: 'op' },		=
		// operators and such
		{ regex: new RegExp(this.GetKeywords(keywords), 'gmi'),		css: =
'keyword' }			// keyword
		];

	this.CssClass =3D 'dp-sql';
}

dp.sh.Brushes.Sql.prototype	=3D new dp.sh.Highlighter();
dp.sh.Brushes.Sql.Aliases	=3D ['sql'];

------=_NextPart_000_0000_01C701A5.15C25F40
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.codinghorror.com/blog/includes/shBrushXml.js

dp.sh.Brushes.Xml =3D function()
{
	this.CssClass =3D 'dp-xml';
}

dp.sh.Brushes.Xml.prototype	=3D new dp.sh.Highlighter();
dp.sh.Brushes.Xml.Aliases	=3D ['xml', 'xhtml', 'xslt', 'html', 'xhtml'];

dp.sh.Brushes.Xml.prototype.ProcessRegexList =3D function()
{
	function push(array, value)
	{
		array[array.length] =3D value;
	}
=09
	/* If only there was a way to get index of a group within a match, the =
whole XML
	   could be matched with the expression looking something like that:
=09
	   (<!\[CDATA\[\s*.*\s*\]\]>)
	   | (<!--\s*.*\s*?-->)
	   | (<)*(\w+)*\s*(\w+)\s*=3D\s*(".*?"|'.*?'|\w+)(/*>)*
	   | (</?)(.*?)(/?>)
	*/
	var index	=3D 0;
	var match	=3D null;
	var regex	=3D null;

	// Match CDATA in the following format <![ ... [ ... ]]>
	// <\!\[[\w\s]*?\[(.|\s)*?\]\]>
	this.GetMatches(new RegExp('<\\!\\[[\\w\\s]*?\\[(.|\\s)*?\\]\\]>', =
'gm'), 'cdata');
=09
	// Match comments
	// <!--\s*.*\s*?-->
	this.GetMatches(new RegExp('<!--\\s*.*\\s*?-->', 'gm'), 'comments');

	// Match attributes and their values
	// (\w+)\s*=3D\s*(".*?"|\'.*?\'|\w+)*
	regex =3D new RegExp('([\\w-\.]+)\\s*=3D\\s*(".*?"|\'.*?\'|\\w+)*', =
'gm');
	while((match =3D regex.exec(this.code)) !=3D null)
	{
		push(this.matches, new dp.sh.Match(match[1], match.index, =
'attribute'));
=09
		// if xml is invalid and attribute has no property value, ignore it=09
		if(match[2] !=3D undefined)
		{
			push(this.matches, new dp.sh.Match(match[2], match.index + =
match[0].indexOf(match[2]), 'attribute-value'));
		}
	}

	// Match opening and closing tag brackets
	// </*\?*(?!\!)|/*\?*>
	this.GetMatches(new RegExp('</*\\?*(?!\\!)|/*\\?*>', 'gm'), 'tag');

	// Match tag names
	// </*\?*\s*(\w+)
	regex =3D new RegExp('</*\\?*\\s*([\\w-\.]+)', 'gm');
	while((match =3D regex.exec(this.code)) !=3D null)
	{
		push(this.matches, new dp.sh.Match(match[1], match.index + =
match[0].indexOf(match[1]), 'tag-name'));
	}
}

------=_NextPart_000_0000_01C701A5.15C25F40--

