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

<channel>
	<title>Groby Unplugged &#187; Technote</title>
	<atom:link href="http://www.robertblum.com/articles/category/technote/feed" rel="self" type="application/rss+xml" />
	<link>http://www.robertblum.com</link>
	<description>Rachel Blum on Software, Games And The Rest Of Life</description>
	<lastBuildDate>Mon, 09 Aug 2010 04:10:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>The Pain &#8211; Ruby and OSX</title>
		<link>http://www.robertblum.com/articles/2007/02/09/the-pain-ruby-and-osx</link>
		<comments>http://www.robertblum.com/articles/2007/02/09/the-pain-ruby-and-osx#comments</comments>
		<pubDate>Sat, 10 Feb 2007 03:50:08 +0000</pubDate>
		<dc:creator>Robert Blum</dc:creator>
				<category><![CDATA[OSX]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Technote]]></category>

		<guid isPermaLink="false">http://www.robertblum.com/articles/2007/02/09/the-pain-ruby-and-osx</guid>
		<description><![CDATA[Remember how I asked for advice on generating local RSS feeds a couple of days ago? My old colleague Brian pointed me to the RubyRSS package, a fairly simple interface to RSS generation. Easy, you think &#8211; after all, it&#8217;s Ruby, we have gems. Let&#8217;s use it. Since it&#8217;s going to be rather technical, the [...]]]></description>
			<content:encoded><![CDATA[<p>Remember how I asked for advice on <a href="http://www.robertblum.com/articles/2007/02/02/odds-and-ends">generating local RSS</a> feeds a couple of days ago? My old colleague Brian <a href="http://www.robertblum.com/articles/2007/02/02/odds-and-ends#comment-12583">pointed me</a> to the <a href="http://www.rubyrss.com/">RubyRSS</a> package, a fairly simple interface to RSS generation. Easy, you think &#8211; after all, it&#8217;s Ruby, we have gems. Let&#8217;s use it.</p>

<p>Since it&#8217;s going to be rather technical, the details are hidden behind the cut&#8230;</p>

<p><span id="more-95"></span></p>

<p>Except this is OSX (Tiger in my case). So there <em>is</em> no Gems. Awesome. Before you head off to install it, be aware that the Darwin Ports version of it seems broken. The best way is going directly for the source.</p>

<p><code>
    curl -O http://rubyforge-files.ruby-forum.com/rubygems/rubygems-0.9.0.tgz<br />
    tar xzvf rubygems-0.9.0.tgz<br />
    cd rubygems-0.9.0<br />
    sudo /usr/bin/ruby setup.rb
</code></p>

<p>OK, gems is installed. Next stop: simple-rss, a prerequisite for rubyrss. Conveniently enough it&#8217;s available as a gem.  Except the rdocs are broken and cause gem to spit out a flood of error messages. Seems the developers know about it, too &#8211; but why rush a new gem just for a couple of warnings&#8230;. Anyways: disabling doc installation does <em>that</em> trick.</p>

<p><code>
    sudo gem install --no-ri --no-rdoc simple-rss-1.1.gem
</code></p>

<p>That leaves the main package. And because it&#8217;s so much fun, it&#8217;s source-only, not packaged as a gem. Installation pains are to be expected, so I created a gem for you (and me) to use: <a href="http://robertblum.com/downloads/rubyrss-1.1.gem">rubyrss-1.1.gem</a></p>

<p><code>
    sudo install rubyrss-1.1.gem
</code></p>

<p>And after all this, I&#8217;m finally ready to work on the main task. More on watching directory changes in a later post&#8230;</p>

<p>Tags: <a href="http://technorati.com/tag/ruby" rel="tag" class="techtag">ruby</a> <a href="http://technorati.com/tag/osx" rel="tag" class="techtag">osx</a> <a href="http://technorati.com/tag/rss" rel="tag" class="techtag">rss</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertblum.com/articles/2007/02/09/the-pain-ruby-and-osx/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The Making of iCalFix</title>
		<link>http://www.robertblum.com/articles/2006/01/09/the-making-of-icalfix</link>
		<comments>http://www.robertblum.com/articles/2006/01/09/the-making-of-icalfix#comments</comments>
		<pubDate>Mon, 09 Jan 2006 15:36:53 +0000</pubDate>
		<dc:creator>Robert Blum</dc:creator>
				<category><![CDATA[OSX]]></category>
		<category><![CDATA[Technote]]></category>
		<category><![CDATA[iCalFix]]></category>

		<guid isPermaLink="false">http://www.robertblum.com/articles/2006/01/09/the-making-of-icalfix</guid>
		<description><![CDATA[Since quite a few people asked me how I created iCalFix, I thought it was time to share some details with you. There&#8217;s technical content ahead, so in case that&#8217;s not your cup of tea, I hid it behind a cut. While it&#8217;s OSX-specific, it might still be interesting for non-OSX programmers &#8211; the whole [...]]]></description>
			<content:encoded><![CDATA[<p>Since quite a few people asked me how I created iCalFix, I thought it was time to share some details with you. There&#8217;s technical content ahead, so in case that&#8217;s not your cup of tea, I hid it behind a cut. While it&#8217;s OSX-specific, it might still be interesting for non-OSX programmers &#8211; the whole process of writing plug-ins for Cocoa applications is rather interesting, regardless what platform you work on.</p>

<p><span id="more-41"></span>
So how does it all work? The most important piece in the puzzle is the fact that almost all Apple Applications are using ObjectiveC &#8211; a message based programming language. That means no function calls, just message dispatches. It&#8217;s not that important to plugin development, but crucial to reverse engineering. Every message is dispatched through one central function, by name.</p>

<p>The question then is, how do you get to read the messages? We need to somehow hook into a running application. When I started this project, I thought about a rather convoluted solution using <a href="http://rentzsch.com/mach_inject/">mach&#95;inject</a> &#8211; it allows you to inject arbitrary code into a running application. I thought I&#8217;d use that combined with <a href="http://rentzsch.com/mach_override">mach&#95;override</a> to override the central dispatch function <code>objc_sendmsg</code>.</p>

<p>A quick trip to the <a href="http://sourceforge.net/projects/extendamac">extendamac</a> mailing list on <a href="http://sf.net">SourceForge</a>, and the resident gurus had set me straight, though. Objective C already has message logging functionality built in. All I needed was to call <code>instrumentObjcMessageSends(YES);</code> inside iCal&#8217;s application space.</p>

<p>There are, as far as I know, two choices to do that. Either you use mach&#95;&#42;, which is a tricky business, or you write an <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/InputManager/InputManager.pdf">input manager</a> &#8211; all OSX applications load input managers &#8211; which is a slightly less tricky business.</p>

<p>This is where a second major piece comes in &#8211; <a href="http://culater.net/software/SIMBL/SIMBL.php">SIMBL</a>, the Smart InputManager Bundle Loader. It&#8217;s a piece of software that uses an input manager to load user-written plugins. All the heavy lifting is done in there, and you just need to create a bundle (sort of a DLL, for you Windows guys) with <em>one</em> entry point.</p>

<p>The code to activate message logging then boiled down to:</p>

<p><code><pre>
+ (void) install
{
    instrumentObjcMessageSends(YES);
}
</pre></code></p>

<p>Compile that as a bundle, and SIMBL will make sure it gets loaded at startup. All messages the hooked up sends from then on are logged. As you&#8217;ll soon find out, Cocoa Apps send <em>a lot</em> of messages, so prepare for some digging through multi-megabyte text files.</p>

<p>After a little while, you will have figured out which message does what. Once you are there, you need to somehow take over or intercept those messages to do your business. Since ObjectiveC is a relatively dynamic language, it&#8217;s easy to replace a method on a class with your own method &#8211; just what we want to do. The CocoaDev website has a <a href="http://www.cocoadev.com/index.pl?MethodSwizzling">great  explanation of MethodSwizzling</a>.</p>

<p>Now we&#8217;re almost there &#8211; we hooked the critical messages, but we actually need to modify data on objects to achieve any visible effect. This is where our third helper comes into play &#8211; class-dump, which can be <a href="http://www.codethecode.com/Projects/class-dump/">downloaded here</a>.</p>

<p>class-dump reads an executable and presents you with an API declaration that you can simply include in your source. Once you do that, you can call all the object modification functions you want. In short, you become a part of the executable you hooked.</p>

<p>All this allowed me to create iCalFix with less than 100 lines of code. It&#8217;s rapidly growing, since I&#8217;m busy adding new features, but the core hack is extremely simple &#8211; thanks to a lot of hard work done by others.</p>

<p>If you&#8217;d like even more detail, Mike Solomon, the author of SIMBL, has a great page on <a href="http://culater.net/wiki/moin.cgi/CocoaReverseEngineering">reverse engineering Cocoa programs</a>.</p>

<p>Tags:  <a href="http://technorati.com/tag/osx" rel="tag">osx</a>, <a href="http://technorati.com/tag/cocoa" rel="tag">cocoa</a>, <a href="http://technorati.com/tag/simbl" rel="tag">SIMBL</a>, <a href="http://technorati.com/tag/objective-c" rel="tag">objective-c</a>, <a href="http://technorati.com/tag/plugin" rel="tag">plugin</a>, <a href="http://technorati.com/tag/reverse+engineering" rel="tag">reverse engineering</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertblum.com/articles/2006/01/09/the-making-of-icalfix/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Fast Conditional breakpoints in VS.NET</title>
		<link>http://www.robertblum.com/articles/2005/12/09/fast-conditional-breakpoints-in-vsnet</link>
		<comments>http://www.robertblum.com/articles/2005/12/09/fast-conditional-breakpoints-in-vsnet#comments</comments>
		<pubDate>Fri, 09 Dec 2005 20:30:50 +0000</pubDate>
		<dc:creator>Robert Blum</dc:creator>
				<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Technote]]></category>

		<guid isPermaLink="false">http://www.robertblum.com/articles/2005/12/09/fast-conditional-breakpoints-in-vsnet</guid>
		<description><![CDATA[Since it&#8217;s Friday, I figured it&#8217;s time for another debugging tale. This weeks installment: How to have conditional breakpoints in Visual Studio that don&#8217;t cost an arm and a leg in performance &#8211; and stick around in optimized builds. While VS.NET does offer you conditional breakpoints, it does so by evaluating an expression every single [...]]]></description>
			<content:encoded><![CDATA[<p>Since it&#8217;s Friday, I figured it&#8217;s time for another debugging tale. This weeks installment: How to have conditional breakpoints in <a href="http://www.amazon.com/exec/obidos/redirect?link_code=ur2&#038;tag=robertblum-20&#038;camp=1789&#038;creative=9325&#038;path=tg%2Fdetail%2F-%2FB000BT8TRQ%2F">Visual Studio</a><img src="http://www.assoc-amazon.com/e/ir?t=robertblum-20&amp;l=ur2&amp;o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> that don&#8217;t cost an arm and a leg in performance &#8211; and stick around in optimized builds.</p>

<p><span id="more-25"></span>
While VS.NET does offer you conditional breakpoints, it does so by evaluating an expression every single time that breakpoint gets hit. Clearly, that&#8217;s not acceptable &#8211; especially if the breakpoint is hit often and the condition is rarely true.</p>

<p>You can speed this up quite a bit by moving the condition into actual (compiled) code. For that, you need a line of code that is only reached when the condition is true. I.e.
<tt><pre>
if(condition) {
   DoSomethingWithoutConsequences();
}</pre></tt></p>

<p>A breakpoint there will only be triggered if the condition is true, and the condition is evaluated in compiled code &#8211; just what we want.</p>

<p>The only drawback is that doing something without consequences gets ripped out by the optimizer ruthlessly. Which causes the <tt>if()</tt> statement to be removed too, and our whole scheme collapses. The most widely known way to work around this is incrementing a volatile global &#8211; but that adds even more code to type, and we can&#8217;t do it as a simple paste operation in a single place.</p>

<p>Thankfully, there&#8217;s an easy solution to this &#8211; the optimizer <i>never</i> touches inline assembly. So turn the above into:</p>

<p><tt><pre>
if(condition) {
   __asm{ nop };
}</pre></tt></p>

<p>Then, in the debugger, put a real breakpoint on the assembly instruction, and you&#8217;re good to go.</p>

<p>Tags: <a href="http://technorati.com/tag/debugging" rel="tag">debugging</a>,<a href="http://technorati.com/tag/debugging" rel="tag">Visual Studio</a>,<a href="http://technorati.com/tag/debugging" rel="tag">conditional breakpoint</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertblum.com/articles/2005/12/09/fast-conditional-breakpoints-in-vsnet/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HOWTO: Add a site counter to WordPress</title>
		<link>http://www.robertblum.com/articles/2005/12/08/howto-add-a-site-counter-to-wordpress</link>
		<comments>http://www.robertblum.com/articles/2005/12/08/howto-add-a-site-counter-to-wordpress#comments</comments>
		<pubDate>Thu, 08 Dec 2005 22:57:06 +0000</pubDate>
		<dc:creator>Robert Blum</dc:creator>
				<category><![CDATA[Technote]]></category>

		<guid isPermaLink="false">http://www.robertblum.com/articles/2005/12/08/howto-add-a-site-counter-to-wordpress</guid>
		<description><![CDATA[Since I&#8217;ve been asked, here&#8217;s a short recipe for adding a site counter to WordPress. All the freely available site counters give you a piece of JavaScript. I personally used one from SiteMeter, but all the other sites work pretty similarly. With WordPress, you can&#8217;t simply put it into index.html &#8211; it&#8217;s template based. You [...]]]></description>
			<content:encoded><![CDATA[<p>Since I&#8217;ve been asked, here&#8217;s a short recipe for adding a site counter to WordPress.</p>

<p><span id="more-24"></span>
All the freely available site counters give you a piece of JavaScript. I personally used one from <a href="http://www.sitemeter.com">SiteMeter</a>, but all the other sites work pretty similarly.</p>

<p>With <a href="http://www.wordpress.org">WordPress</a>, you can&#8217;t simply put it into index.html &#8211; it&#8217;s template based.  You need to embed this code in a template that is always displayed &#8211; for most WordPress themes, that&#8217;s the SideBar.</p>

<p>So how do you edit it? Log in as site adminstrator. In the Administration page, go to the Presentation Page and select the Theme Editor. Select the Sidebar template. It will show up as a PHP file &#8211; but don&#8217;t worry. It really is HTML with a bit of PHP thrown in for good measure.</p>

<p>The whole sidebar is usually embedded in a single &lt;div&gt; tag &#8211; find the end of that tag. Right before the end of that tag, paste your javascript that you got for the side counter. That&#8217;s all there is too it.</p>

<p>On some WP installations, you might not be able to edit your themes through the web interface &#8211; in this case, below the textbox, you will see the string &#8220;<i>If this file was writable you could edit it.</i>&#8220;</p>

<p>That means you need to actually log into the shell for your account and modify the file there. Thankfully, the web page gives you the path to the file relative to the WP installation directory as a title above the text box &#8211; so just cd to there, and edit the file. Et voila, your site counter is active!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertblum.com/articles/2005/12/08/howto-add-a-site-counter-to-wordpress/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Debugging strategies</title>
		<link>http://www.robertblum.com/articles/2005/12/02/debugging-strategies</link>
		<comments>http://www.robertblum.com/articles/2005/12/02/debugging-strategies#comments</comments>
		<pubDate>Fri, 02 Dec 2005 17:07:13 +0000</pubDate>
		<dc:creator>Robert Blum</dc:creator>
				<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Technote]]></category>

		<guid isPermaLink="false">http://www.robertblum.com/articles/2005/12/02/debugging-strategies</guid>
		<description><![CDATA[Have you ever wondered why some people seem to have no trouble finding bugs, while others sometimes have a hard time? I certainly did, because every minute I spend on hunting bugs is a wasted minute. So I&#8217;ve watched people debug, tried to learn from both failures and successes, and have compiled my observations here. [...]]]></description>
			<content:encoded><![CDATA[<p>Have you ever wondered why some people seem to have no trouble finding bugs, while others sometimes have a hard time? I certainly did, because every minute I spend on hunting bugs is a wasted minute. So I&#8217;ve watched people debug, tried to learn from both failures and successes, and have compiled my observations here.
<span id="more-20"></span>
This is a strategy guide to debugging. It&#8217;s not focused on particular languages or tools &#8211; in fact, many of the ideas in here can be applied to problem solving in general.</p>

<h3>Know the landscape</h3>

<p>Since we&#8217;re talking strategy, let&#8217;s stick with a &#8220;war&#8221; analogy for a moment. As in any battle, knowing the landscape is key. If you don&#8217;t understand the environment you are in, you might miss clues, misinterpret others and put way more effort into finding the problem than necessary. This means</p>

<ul><li>Know the general ideas and data paths of the debugee</li><li>Know your tools</li><li>Know the environment. OS, hardware, etc.</li></ul>

<h3>Make it reproducible</h3>

<p>Once you have a general understanding, you are prepared to actually tackle the bug. And the first step to tackling it is making it reproducible. Make it at least semi-consistently reproducible. If you cannot reproduce it easily, it is very hard to track down any problems. And before you fix it, <i>always</i> create a test that reproduces it 100% &#8211; otherwise, you&#8217;ll never be certain you fixed it.</p>

<h3>Keep a log</h3>

<p>Once you can reproduce it, <b>write it down</b>. You will forget it otherwise. Believe me, I&#8217;ve been there. In general, write down everything relevant so you can recall it easily. Some people keep it in their development log. For me, the best approach has always been putting all known facts on a whiteboard. This way, team mates can often offer insights.</p>

<h3>Collect data</h3>

<p>Now that you can make the problem happen, it is tempting to speculate what the problem is and just fix the code that is &#8220;obviously wrong&#8221;. Don&#8217;t give in to that temptation &#8211; most likely, it&#8217;s something completely different.</p>

<p>Any good theory is based on observations, and at this point, the observing has been slim &#8211; you only saw a manifestation of the bug. You don&#8217;t know if it&#8217;s the only manifestation. You don&#8217;t know if there&#8217;s more than one cause. You don&#8217;t know jack.</p>

<p>That&#8217;s fine, though. Now is the time to collect data. It&#8217;s nothing else than the scientific process &#8211; you collect data, form a theory, create testable hypotheses. Lather, rinse, repeat until your theory matches reality.</p>

<p>The collection of data can take many forms. Step through the code, add instrumentation to the code, use any kind of analysis tools available to you. Keep in mind that instrumentation quite possibly might change behavior &#8211; so be sure to test your hypotheses with the instrumentation removed, too. Heisenberg is alive and kicking.</p>

<h3>No fear</h3>

<p>Don&#8217;t let emotions override the process. Yes, sometimes the pressure is insane &#8211; you&#8217;ve got three hours before burning a disc, and you just found a crash bug. That&#8217;s OK &#8211; as long as you keep your head, you <i>will</i> find it. Just calmly collect data, and examine every hypothesis against the known data. Not only will it help you get there faster &#8211; it will also calm down your teammates, help them keeping their head.</p>

<h3>Reduce the noise</h3>

<p>&#8220;Hold on&#8221;, you say. &#8220;My code base is way too big to step through it!&#8221;. Yes, it is. It always is. That&#8217;s where you do like the Romans did: Divide &amp; Conquer. Split your code into smaller and smaller pieces, excluding the parts that are not contributing to the problem.</p>

<p>One of the best ways to do that is find a piece of code where the problem shows itself, and then follow the bad data up the call chain. That usually gives you a good idea of what systems are involved. (Here&#8217;s where knowing the road map is important!). As much as possible, shunt things that are not involved.</p>

<p>Another way to reduce the clutter is to reduce the amount of data &#8211; fix inputs not contributing to the actual problem. Force them to always be the same value.</p>

<p>If you have a &#8220;known good&#8221; version, it becomes even easier &#8211; look at the changes since then. If your build pipeline allows it, do a binary search through all the changes until you&#8217;ve narrowed it down to a single problem. (Know your tools!)</p>

<p>So now you&#8217;ve narrowed it down enough to build a theory that matches your observations. You&#8217;re ready to make the fix. You have a test case that reproduces the problem every time.</p>

<h3>How do hedgehogs make love? &#8211; Very carefully!</h3>

<p>Step back for a second, take a deep breath, and repeat after me: &#8220;One change at a time!&#8221;. Go step by step. See if the change yields results that fit your theory. If you change multiple things, tracking interactions between them is incredibly hard.</p>

<h3>If you still can&#8217;t find it</h3>

<p>Of course, sometimes things aren&#8217;t that easy. There are two pieces of advice for the &#8220;I can&#8217;t find it!&#8221; bugs.</p>

<ol><li>Double-check your assumptions. If the monitor is dark, and you <b><i>know</i></b> it&#8217;s plugged in, do yourself a favor &#8211; see if it is really plugged in.</li><li>Find a debugging buddy. Explain the symptoms &#8211; often, that&#8217;s enough to smack your forehead. Either way, don&#8217;t share your theories, since they come with built-in assumptions and might mislead.</li><h3>Happy hunting</h3>
That&#8217;s it. That is all there is to successfully debugging even the toughest problems. Yes, special problems require special techniques. But this is the general strategy. I&#8217;ve been following it for quite some time, and it seems to work for me. If you try it, let me know how it works for you.</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.robertblum.com/articles/2005/12/02/debugging-strategies/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ChallengeMap III &#8211; Safari &amp; InfoWindows and better HTML</title>
		<link>http://www.robertblum.com/articles/2005/11/29/challengemap-iii-safari-infowindows-and-better-html</link>
		<comments>http://www.robertblum.com/articles/2005/11/29/challengemap-iii-safari-infowindows-and-better-html#comments</comments>
		<pubDate>Tue, 29 Nov 2005 13:32:04 +0000</pubDate>
		<dc:creator>Robert Blum</dc:creator>
				<category><![CDATA[Technote]]></category>

		<guid isPermaLink="false">http://www.robertblum.com/articles/2005/11/29/challengemap-iii-safari-infowindows-and-better-html</guid>
		<description><![CDATA[This is just a collection of a few odds and ends encountered during the first week of opening up the ChallengeMap to the public. Safari, InfoWindows, and formatting Google Maps&#8217; InfoWindows (the bubbles that appear when you click on a marker) are broken for Safari. It will add linebreaks after pretty much every word. After [...]]]></description>
			<content:encoded><![CDATA[<p>This is just a collection of a few odds and ends encountered during the first week of opening up the <a href="http://www.robertblum.com/challengemap/map.html">ChallengeMap</a> to the public.</p>

<h3>Safari, InfoWindows, and formatting</h3>

<p>Google Maps&#8217; InfoWindows (the bubbles that appear when you click on a marker) are broken for Safari. It will add linebreaks after pretty much every word. After a bit of googling around, Google Groups (notice a pattern here?) reveals a <a href="http://groups.google.com/group/Google-Maps-API/browse_thread/thread/e803e89b0a0ca926/9867c07802d06ff6?lnk=st&#038;q=safari+infowindow&#038;rnum=2#9867c07802d06ff6">helpful thread</a>. Basically, you need to wrap all your text into a &lt;div&gt; tag with a width style element. Like this:
<code><pre>
  &lt;div style="width:204px;"&gt;some text&lt;/div&gt;
</pre></code>
204 pixels is the same width Google Maps use by default if they can&#8217;t determine the width of the containing text.</p>

<h3>Better XML</h3>

<p>It had to happen &#8211; somehow, invalid elements snuck into my XML. I don&#8217;t know <em>where</em> they came from, since my source data <i>is</i> HTML &#8211; at least a close enough relative. They still happen. And if they sneak into the XML data file for the markers, the markers will just not appear.</p>

<p>And, just to compound matters, the offending entities are different for Safari and IE. Safari complains about entities like &amp;oelig; &#8220;&amp;oelig&#8221; &#8211; which is silly, since the file <i>should</i> be treated as XML, and those entities are meaningless unless defined in a DTD. IE chokes on &#8220;&amp;&#8221;, which is less silly, since it&#8217;s part of, for example &amp;lt;, which is used to escape &#8220;&lt;&#8221; inside tags. (Of course, Safari can stand that. And <a href="http://www.mozilla.org/products/firefox/">Firefox</a> has yet another set of issues&#8230;)</p>

<p>The point remains, though &#8211; it breaks my application, and there&#8217;s no way to predict how and why. So the solution is, &#8220;replace all unknown entities&#8221;, and &#8220;Check the data file in each browser&#8221;. Thankfully, they even offer the line number where they choked, so it&#8217;s fairly easy to fix if I run into a new issue. Technically, I probably should be wrapping the text into a CDATA section. It&#8217;s on the to-do list <img src='http://www.robertblum.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>

<h3>Previous Articles</h3>

<p>If you just stumbled upon this page and want to know more about challenge maps, here are the previous ones:</p>

<ul>
  <li><a href="http://www.robertblum.com/articles/2005/11/22/challenge-map-ii-google-maps">Challenge Map II &#8211; Google Maps</a>
  <br />
Covers the Google Maps part of the application, and pitfalls encountered therein.</li>
<li><a href="http://www.robertblum.com/articles/2005/11/21/challenge-map-i-python-web-scraping">Challenge Map I &#8211; Python Web Scraping</a>
<br />
Covers extraction of data from web sites using Python &#8211; which ends up being surprisingly easy.
</li></ul>
]]></content:encoded>
			<wfw:commentRss>http://www.robertblum.com/articles/2005/11/29/challengemap-iii-safari-infowindows-and-better-html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Power Of Python</title>
		<link>http://www.robertblum.com/articles/2005/11/24/the-power-of-python</link>
		<comments>http://www.robertblum.com/articles/2005/11/24/the-power-of-python#comments</comments>
		<pubDate>Thu, 24 Nov 2005 14:40:12 +0000</pubDate>
		<dc:creator>Robert Blum</dc:creator>
				<category><![CDATA[Technote]]></category>

		<guid isPermaLink="false">http://www.robertblum.com/articles/2005/11/24/the-power-of-python</guid>
		<description><![CDATA[Just because I&#8217;m that kind of person, let me go back to yesterday&#8217;s article on setting environment variables to talk about Python and why I think it&#8217;s much better suited to many tasks. So let&#8217;s look at the same example in Python: registryKey = \ 'SYSTEM&#92;CurrentControlSet&#92;Control&#92;Session Manager&#92;Environment' variableName = 'SOMEVAR' value = 'Another String bites [...]]]></description>
			<content:encoded><![CDATA[<p>Just because I&#8217;m that kind of person, let me go back to <a href="http://www.robertblum.com/articles/2005/11/23/programatically-setting-environment-variables-in-win-32">yesterday&#8217;s article on setting environment variables</a> to talk about <a href="http://www.python.org">Python</a> and why I think it&#8217;s much better suited to many tasks.</p>

<p>So let&#8217;s look at the same example in Python:</p>

<p><code><pre>
registryKey   = \
  'SYSTEM&#92;CurrentControlSet&#92;Control&#92;Session Manager&#92;Environment'
variableName    = 'SOMEVAR'
value         = 'Another String bites the dust!'</pre></code></p>

<p>registryHandle = OpenKey( HKEY&#95;LOCAL&#95;MACHINE, registryKey )
SetValue( registryHandle, variableName, REG&#95;SZ, value )
CloseKey( registryHandle )</p>

<p>SendMessageTimeout( HWND&#95;BROADCAST,              \
                    WM&#95;SETTINGCHANGE,            \
                    0, 'Environment',             \
                    SMTO_ABORTIFHUNG, 5000 )

So what are the advantages? At first glance, you&#8217;ll see the Python program is short &#8211; half as short as the C++ sample (13 vs. 27 lines ). &#8220;How come?&#8221;, you ask. One main reason for this: <b><i>Exceptions</i></b></p>

<p>Error cases in Python are consistently handled as exceptions. There&#8217;s no need for lines and lines of error checking that do little else besides propagate the error to the next layer &#8211; which is what most C++ error handling does.</p>

<p><i>&#8220;But&#8230; aren&#8217;t exceptions only for truly exceptional cases?&#8221;</i></p>

<p>Short answer: Yes. Long answer &#8211; if a function doesn&#8217;t do what I expect it to do, that <em>is</em> an exceptional case. And at least with exceptions, I&#8217;ll know the moment it happens. Most C++ code silently ignores return codes, which hardly qualifies as a better solution.</p>

<p>Plus, I happen to think that error codes really are out-of-band communications, which is much better expressed by exceptions than by return values or extraneous parameters.</p>

<p><i>&#8220;But you could do that in C++, too!&#8221;</i></p>

<p>Yes, I could. If I wanted to write even <em>more</em> code. Exceptions are not part of the language philosophy, which means many of the APIs don&#8217;t support them. Python internalized exceptions, and the API reflects it. My goal is to write short, expressive code. If there are standardized building blocks to do that, I&#8217;m happy to use them &#8211; but C++ really doesn&#8217;t have much in terms of a support library. Which happens to be a point in favor of any post-Java language &#8211; they come with massive APIs that solve most of the basic problems for you, so you can concentrate on the problem at hand.</p>

<p>There are a couple more pluses to Python, so let me mention them really quick:</p>

<ul><li>Dynamic Typing<br />

  I don&#8217;t have to spell out that a string is really a string, and a number is really a number. Variables in Python take the type of whatever they contain. Types in C++ are for the most part busy work &#8211; you&#8217;re just spelling out something again that you&#8217;ve already said a few times.</li>

<li>Indentation<br />

  Yes, that&#8217;s right. I love the mandated indentation format for flow control &#8211; because it forces even the sloppiest of programmers to indent their code so I can read it. C++ programmers do the same thing &#8211; they just call it a coding standard and fight to the death over it. Me, I&#8217;d rather focus on the problem instead of layout opinions.
  </li></ul>

<p>There&#8217;s plenty more, but that&#8217;s for another day.</p>

<p><i>&#8220;If Python is so great, why didn&#8217;t you use it right away?&#8221;</i></p>

<p>Fair question. I actually did use it to prototype the solution, but two things conspired to make me convert this. First, I wanted to use SendNotifyMessage() &#8211; and there&#8217;s no Python binding for it yet. (Yes, that <em>is</em> a drawback of Python &#8211; I didn&#8217;t say it&#8217;s perfect!). Second, the article was mostly a summary of older notes for a colleague at work &#8211; so I picked a language he&#8217;s more comfortable with.</p>

<p><i>&#8220;So what other reasons are there NOT to use Python&#8221;</i></p>

<p>Oh, plenty. The main one I&#8217;m hearing is plain old fear of the new. I hope that&#8217;s not what&#8217;s stopping you from trying it out. However, there are some real limitations. If you need to go &#8220;direct to the metal&#8221; &#8211; i.e. interface with the OS or some hardware &#8211; you need bindings. Which usually require a dose of C/C++.</p>

<p>Even more importantly, if you need raw performance, stay away. If your application is slinging around hundreds of megabytes per second, Python might not be your tool of choice. You <em>do</em> pay a price for all those exceptions and dynamic types. The usual advice in that case is to &#8220;write the performance critical part in C/C++, the rest in Python&#8221;. That might work &#8211; I&#8217;ll defer you to others who&#8217;ve actually tried it.</p>

<p>Or maybe you already did try and can tell me if it worked?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertblum.com/articles/2005/11/24/the-power-of-python/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Programatically Setting Environment Variables in Win 32</title>
		<link>http://www.robertblum.com/articles/2005/11/23/programatically-setting-environment-variables-in-win-32</link>
		<comments>http://www.robertblum.com/articles/2005/11/23/programatically-setting-environment-variables-in-win-32#comments</comments>
		<pubDate>Wed, 23 Nov 2005 15:27:09 +0000</pubDate>
		<dc:creator>Robert Blum</dc:creator>
				<category><![CDATA[Technote]]></category>

		<guid isPermaLink="false">http://www.robertblum.com/articles/2005/11/23/programatically-setting-environment-variables-in-win-32</guid>
		<description><![CDATA[Yeesh. Driest title ever, but I really couldn&#8217;t find a better one. Anyway &#8211; there comes a time in a programmers life when he has to set an environment variable globally, so that other processes can use it. How to do that under Win32 is, despite an entry in Microsoft&#8217;s KB not exactly well known. [...]]]></description>
			<content:encoded><![CDATA[<p>Yeesh. Driest title ever, but I really couldn&#8217;t find a better one. Anyway &#8211; there comes a time in a programmers life when he has to set an environment variable globally, so that other processes can use it. How to do that under Win32 is, despite <a href="http://support.microsoft.com:80/support/kb/articles/q104/0/11.asp&#038;NoWebContent=1">an entry in Microsoft&#8217;s KB</a> not exactly well known. Probably due to the fact that they managed to make their title sound even more arcane than I did.</p>

<p>In a nutshell, you set the registry key corresponding with your environment variable and send a WM_SETTINGCHANGE message system-wide. And since it&#8217;s a system-wide send, you need to send with SendMessageTimeout &#8211; otherwise a single hung process will bring your program to a halt, too.</p>

<p>There&#8217;s only a small extra bit of information I can add: If you make this change from a program that keeps running, SendNotifyMessage() is a better choice &#8211; there&#8217;s no timeout, and Windows will keep trying to deliver your message. Without actually hanging your process. Obviously, this doesn&#8217;t work when you terminate your program, since the data you&#8217;re sending is now non-existant. (That&#8217;s what you get for sending around pointers&#8230;)</p>

<p>And, since I need this from time to time and love a code sample, here&#8217;s the actual code. [Formatting deliberate to squeeze on page]
<code><pre>
    char* pRegistryKey  = 
        "SYSTEM&#92;CurrentControlSet&#92;Control&#92;Session Manager&#92;Environment";
    char* pVariableName = "SOMEVAR";
    char* pValue        = "Another String bites the dust!";
    HKEY keyHandle;</pre></code></p>

<pre><code>if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
                  pRegistryKey, 0, 
                  KEY_SET_VALUE, &amp;keyHandle ) 
    != ERROR_SUCCESS ) 
 { return 1; }

if( RegSetValueEx( keyHandle, 
                   pVariableName, 0, 
                   REG_SZ, (BYTE*)pValue, 
                   (DWORD)strlen( pValue ) + 1) 
     != ERROR_SUCCESS )
{ return 2; }

RegCloseKey( keyHandle );

DWORD returnValue;
SendMessageTimeout( HWND_BROADCAST, 
                    WM_SETTINGCHANGE, 
                    0, (LPARAM)"Environment", 
                    SMTO_ABORTIFHUNG, 5000, 
                    &amp;returnValue);
</code></pre>

<p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertblum.com/articles/2005/11/23/programatically-setting-environment-variables-in-win-32/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Challenge Map II &#8211; Google Maps</title>
		<link>http://www.robertblum.com/articles/2005/11/22/challenge-map-ii-google-maps</link>
		<comments>http://www.robertblum.com/articles/2005/11/22/challenge-map-ii-google-maps#comments</comments>
		<pubDate>Tue, 22 Nov 2005 14:53:13 +0000</pubDate>
		<dc:creator>Robert Blum</dc:creator>
				<category><![CDATA[Technote]]></category>

		<guid isPermaLink="false">http://www.robertblum.com/articles/2005/11/22/challenge-map-ii-google-maps</guid>
		<description><![CDATA[As promised, here&#8217;s the second part of the technical details for the ChallengeMap. I&#8217;m going to cover a few details related to the Google Map API. If you&#8217;re interested in the web scraping behind the scenes, hop back to Part I. I&#8217;m not going to cover all the details of how to create the map [...]]]></description>
			<content:encoded><![CDATA[<p>As promised, here&#8217;s the second part of the technical details for the <a href="http://www.robertblum.com/challengemap/map.html">ChallengeMap</a>. I&#8217;m going to cover a few details related to the <a href="http://www.google.com/apis/maps/">Google Map API</a>. If you&#8217;re interested in the web scraping behind the scenes, hop back to <a href="http://www.robertblum.com/articles/2005/11/21/challenge-map-i-python-web-scraping">Part I</a>.</p>

<p>I&#8217;m not going to cover all the details of how to create the map &#8211; Googles <a href="http://www.google.com/apis/maps/documentation/">documentation</a> does a quite good job at that &#8211; especially if you supplement it with the community documentation effort at <a href="http://www.mapki.com">Mapki</a>. However, there are a two things that took me some time to discover &#8211; so I&#8217;m sharing them here. Not only might it help you, it also becomes part of my outboard brain.</p>

<h3>Custom Icons</h3>

<p>Yes, the documentation touches on custom icons. It&#8217;s almost useful. However, when you just want Googles default icon in a different color, things become too tricky for the simplicity of the task. So here&#8217;s the quick way:</p>

<p>First, you obviously need the original icon to modify. It lives at <a href="http://www.google.com/mapfiles/marker.png">http://www.google.com/mapfiles/marker.png</a>, and its shadow is named shadow50.png. You could probably just refer to their files if you use them unmodified. I decided to copy them to my webserver instead, in case I ever want to change them. Creating the green marker from the red one is left as an exercise to the reader, but how to create a new icon?</p>

<p>Google gives you a list of seven properties to set &#8211; here&#8217;s the code to do it properly. (You could&#8217;ve easily found out for yourself, but if you&#8217;re like me, you appreciate a good copy&amp;paste opportunity&#8230;;)</p>

<p><code>
    var baseIcon = new GIcon();<br />
    baseIcon.shadow = "icons/shadow50.png";<br />
    baseIcon.iconSize = new GSize(20, 34); <br />
    baseIcon.shadowSize = new GSize(37, 34);<br />
    baseIcon.image = "icons/marker_red.png";<br />
    baseIcon.iconAnchor = new GPoint(6, 20);<br />
    baseIcon.infoWindowAnchor = new GPoint(6, 20);<br /><br />
    var greenIcon = new GIcon( baseIcon );<br />
    greenIcon.image = "icons/marker_green.png";<br /></code></p>

<p>Note the cloning at the bottom &#8211; saves a total of six lines of code. Always a win.</p>

<h3>Creating Markers</h3>

<p>I&#8217;m creating markers from an XML data file, since keeping all Starbucks locations in my web page really didn&#8217;t seem like an option. It&#8217;s fairly forward, with one little caveat &#8211; JavaScript scoping rules. In case you, like me, say &#8220;Huh?&#8221; at this point, here&#8217;s the straightforward (but wrong!) code:</p>

<p><code>
    // Broken Code !!!<br /><br />
    var markers = xmlDoc....// Get markers<br />
    for (var i = 0; i &lt; markers.length; i++) {<br />  ... // skipped all the XML parsing<br />  var marker = new GMarker(point,icon);<br />  GEvent.addListener(marker, "click", function() {<br />    marker.openInfoWindowHtml(html);<br />
        });<br />
  } <br /></code></p>

<p>So why is this wrong? The listener is bound to the same variable all the time, &#8220;marker&#8221;. Once the loop is finished, marker is set to the <em>last</em> marker in the array, no matter which actual marker you click on. It&#8217;s an interesting little quirk that can be solved by putting each marker in a different variable. Since I don&#8217;t want to think up all the names, let&#8217;s get this solved by scoping &#8211; we put the actual creation and addition of the event into a separate function.</p>

<p><code>
     function createMarker(point,html,icon) {<br />       var marker = new GMarker(point,icon);<br />          GEvent.addListener(marker, "click", function() {<br />              marker.openInfoWindowHtml(html);<br />
        });<br />
        return marker;<br />
      }<br /></code></p>

<p>Since &#8220;marker&#8221; now leaves scope whenever the function returns, each call creates a new marker variable to be bound to. (In my opinion, declaring a variable inside a loop should do the same thing, but JavaScript disagrees with me.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertblum.com/articles/2005/11/22/challenge-map-ii-google-maps/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Challenge Map I &#8211; Python Web Scraping</title>
		<link>http://www.robertblum.com/articles/2005/11/21/challenge-map-i-python-web-scraping</link>
		<comments>http://www.robertblum.com/articles/2005/11/21/challenge-map-i-python-web-scraping#comments</comments>
		<pubDate>Mon, 21 Nov 2005 14:54:13 +0000</pubDate>
		<dc:creator>Robert Blum</dc:creator>
				<category><![CDATA[Technote]]></category>

		<guid isPermaLink="false">http://www.robertblum.com/articles/2005/11/21/challenge-map-i-python-web-scraping</guid>
		<description><![CDATA[Since I&#8217;ve been asked by several people, I&#8217;m going to go into a bit of detail on how the GoogleMap for the Starbucks Challenge came to be. For those of you not wanting to follow all the links, let me give you some quick background: The Starbucks Challenge challenges the marketing message Starbucks is sending [...]]]></description>
			<content:encoded><![CDATA[<p>
Since I&#8217;ve been asked by several people, I&#8217;m going to go into a bit of detail on how the <a href="http://www.robertblum.com/challengemap/map.html">GoogleMap</a> for the <a href="http://greenlagirl.blogspot.com/2005/11/starbucks-challenge-20.html">Starbucks Challenge</a> came to be.
</p>

<p>For those of you not wanting to follow all the links, let me give you some quick background: The Starbucks Challenge challenges the marketing message <a href="http://www.starbucks.com">Starbucks</a> is sending regarding fair trade coffee. According to them, you can always get a french pressed cup of fair trade coffee in any of their stores, if you just ask. Challenge participants then post their results, and tag it on <a href="http://del.icio.us">del.icio.us</a>. The map then gets the data from there.</p>

<p>While the using the the Google Map API itself certainly had hurdles &#8211; which are going to be covered in another article &#8211; the main difficulty to figure out at the outset was: &#8220;How do I get longitude and latitude for any store?&#8221;. Sending people a GPS unit was out of the question, but thankfully Starbucks itself is helping. Their link to the store driving directions helpfully contains exactly the data we need. Getting the page containing the link is easy, and each store is uniquely identified by a store key &#8211; perfect for tagging.</p>

<p>Getting the link out of the page is not so fun. To get this done in any reasonable amount of time, I had to go with a scripting language. I picked my current personal favorite, <a href="http://www.python.org">Python</a>. It&#8217;s easy to write and has plenty of support for web tasks. Reading the page, for example, is a one-liner.</p>

<p>How to extract the link, though? The first idea that came to mind was writing an XPATH query. However, the state of XML parsing for Python is a sorry one. There are quite a few competing packages, all with their ups and downs. Thankfully, the point was quickly rendered moot &#8211; the web page is not well-formed XHTML, and all the candidates choke on that.</p>

<p>So what we need is a package to parse the mess that qualifies as HTML. Thankfully, there&#8217;s a package to do just that: <a href="http://www.crummy.com/software/BeautifulSoup">BeautifulSoup</a>. It takes the tag soup of any HTML page and renders it navigable. Lots of heuristics to cover all the mistakes most HTML parsers allow. Let me give you the two salient pieces of code:</p>

<ol><li>Extracting the address of the store. This is stored in two &lt;span&gt; elements with the IDs of bAd2 and bAd3. Extracting that is a simple two-liner:
<p><code>
soup = BeautifulSoup( webpage )<br />
addr = soup( 'span', { 'id' : re.compile('bAd[23]') } )<br /></code></p>
Yes, that&#8217;s it. No more work.
</li><li>The actual location is similarly easy. It is a link element thoughtfully classified as a &#8220;DriveLink&#8221;. (Thank you, Starbucks!). All you need to do is get the soup of all DriveLinks, and look at the href attribute of the first one:
<p><code>
driveLink = soup( 'a', { 'id' : 'DriveLink' } )<br />
href = driveLink[0]['href']<br /></code></p>
Judicious application of a bit of regular expressions then yields longitude and latitude.
</li></ol>

<p>And that&#8217;s all there is to this, at the core. Since I like playing with code, there&#8217;s a bit more to it, of course. If the link doesn&#8217;t provide geolocation any more, it falls back to <a href="http://developer.yahoo.net/maps/rest/V1/geocode.html">Yahoo&#8217;s Geocode API</a> &#8211; just in case Starbucks decides not to be helpful any more. And as to not unduly hammer their server, the results of the Store Key lookup are of course cached. And it&#8217;s all nicely wrapped up as a module. If I ever get to clean up the code, I&#8217;ll release it here. If you need it before, just ask.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertblum.com/articles/2005/11/21/challenge-map-i-python-web-scraping/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
