<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-3468328372425900141</atom:id><lastBuildDate>Fri, 26 Feb 2010 19:11:24 +0000</lastBuildDate><title>Getting Clever</title><description>one post at a time</description><link>http://www.gettingclever.com/</link><managingEditor>noreply@blogger.com (ondrew)</managingEditor><generator>Blogger</generator><openSearch:totalResults>32</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/GettingClever" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="gettingclever" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-1190201530360060187</guid><pubDate>Thu, 27 Aug 2009 00:00:00 +0000</pubDate><atom:updated>2009-08-27T08:00:01.425+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">windows 7</category><category domain="http://www.blogger.com/atom/ns#">code 7</category><title>Code 7 Contest - I'm coming for you, Windows 7</title><description>&lt;p&gt;To finally jump on the multiprocessor bandwagon, I bought a new computer with AMD Phenom II X4 905e on Monday.&lt;/p&gt;

&lt;p&gt;Since I didn't have enough time to install my favorite Gentoo, I decided to quickly give Windows 7 RC a try.&lt;/p&gt; 

&lt;p&gt;I'm quite impressed with the functionality offered out of the box. All the hardware is usable and I didn't even bothered to install any drivers (except for Catalyst), since I'm going to wipe the partition clean in couple of weeks.&lt;/p&gt;

&lt;p&gt;But as I already have Windows 7 up and running, I decided to take part in &lt;a href="http://code7contest.com"&gt;code7contest&lt;/a&gt;. I do not expect to win or anything - I set my goals humbly and want to at least get full version of Windows 7 (hopefully they will give them out to all participants). That's how cheap I am :).&lt;/p&gt;

&lt;p&gt;The first couple of milestones/prerequisites are already completed: &lt;/p&gt;

&lt;p&gt;
  &lt;ol&gt;
    &lt;li&gt;Install ViM&lt;/li&gt;
    &lt;li&gt;Install Visual C++ 2008 Express (for compiler :))&lt;/li&gt;
    &lt;li&gt;Install Windows 7 SDK RC&lt;/li&gt;
    &lt;li&gt;Compile program using Win32 API functions introduced in Windows 7&lt;/li&gt;  
  &lt;/ol&gt;
&lt;/p&gt;

&lt;p&gt;I am very aware about the shortcomings of following code - don't copy paste it - it's just something to test if I can call Windows 7 API functions without any LoadLibrary calls.&lt;/p&gt;

&lt;pre class="c"&gt;
 //snip

 WCHAR *a = (WCHAR *) malloc(100);
 
 SetCurrentProcessExplicitAppUserModelID(L"Hello");
 GetCurrentProcessExplicitAppUserModelID((PWSTR *)&amp;a);
 MessageBox(NULL, a, a, MB_OK);

 //snip
&lt;/pre&gt;

&lt;p&gt;Next task is to prepare a plan and post a milestone overview with dates.&lt;/p&gt;

&lt;p&gt;Hopefully regular work on the contest entry will force me into updating this blog more regularly.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-1190201530360060187?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2009/08/code-7-contest-im-coming-for-you.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-5604490614789977504</guid><pubDate>Wed, 11 Feb 2009 00:00:00 +0000</pubDate><atom:updated>2009-02-11T08:00:00.575+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">win32</category><category domain="http://www.blogger.com/atom/ns#">C++</category><title>Display clipboard formats</title><description>&lt;p&gt;While researching an issue with how different versions of Citrix servers and Citrix clients handle copy pasting between remote and local applications I found myself in need of a little app, which would show me what data formats I have in clipboard right now.&lt;/p&gt;

&lt;p&gt;So here goes another utility, which I can't imagine anyone will find usefull.&lt;/p&gt;

&lt;pre class="c"&gt;
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0610
#define UNICODE
#include &amp;lt;windows.h&amp;gt;
#define IDI_MYICON 201

int main(void)
{
 wchar_t full[50000];
 wchar_t *index = full;
 wchar_t name[255];
 unsigned int format = 0;

 OpenClipboard(NULL);

 do {
  format = EnumClipboardFormats(format);
  GetClipboardFormatName(format, name, 255);
  index += wsprintf(index, L"%d : %ls\n", format, name);
 } while (format != 0);

 MessageBox(NULL, full, L"Clipboard formats", MB_OK);

 CloseClipboard();
 return 0;
}
&lt;/pre&gt;

&lt;p&gt;The code quite naïvely assumes, that the output buffer won't be longer than 50 000 characters, so in case you have so many formats in clipboard, the code will overflow. :)&lt;/p&gt;

&lt;p&gt;For convenience binary version follows &lt;a href="http://ondrew.googlepages.com/clipview.zip"&gt;clipview.zip&lt;/a&gt; (6.8 kB)&lt;/p&gt;

&lt;p&gt;If you copy paste for example Excel data into clipboard and run this program, the output will look like this:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://ondrew.googlepages.com/clipview.png" alt="List of clipboard format IDs and descriptions"/&gt;

&lt;p&gt;Obligatory thanks to Mark James for creating the amazing &lt;a href="http://www.famfamfam.com/lab/icons/silk/"&gt;Silk icons&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-5604490614789977504?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2009/02/display-clipboard-formats.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-1654564584090665802</guid><pubDate>Mon, 02 Feb 2009 00:00:00 +0000</pubDate><atom:updated>2009-02-02T08:00:00.402+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">gentoo</category><category domain="http://www.blogger.com/atom/ns#">linux</category><category domain="http://www.blogger.com/atom/ns#">mplayer</category><title>Mplayer Mouse Volume Issue</title><description>&lt;p&gt;Before reinstalling my Gentoo, I had this strange issue with my mouse when watching movies in &lt;a href="http://mplayerhq.hu"&gt;MPlayer&lt;/a&gt;. Everytime I clicked my left mouse button, MPlayer would increase volume.&lt;/p&gt;

&lt;p&gt;I could easily remap the functionality of mouse in MPlayer not to mess with volume, but whichever value I remapped the functionality to, it always unpaused movies and displayed the annoying volume status over the movie.&lt;/p&gt;

&lt;p&gt;I was looking for solution for quite some time, but the problem magically disappeared after re-installation, so I quickly forgot about it. Until yesterday of course :)&lt;/p&gt;

&lt;p&gt;Since I have new versions of pretty much everything, I concluded, it will be issue with my configuration and not a bug.&lt;/p&gt;

&lt;p&gt;I'm using Microsoft SideWinder mouse&lt;/p&gt;

&lt;img src="http://ondrew.googlepages.com/sidewinder.jpg" alt="Microsoft SideWinder Mouse" /&gt;

&lt;p&gt;so I decided to dig in the logs to find out, what is going on. &lt;code&gt;dmesg&lt;/code&gt; and &lt;code&gt;/var/log&lt;/code&gt; weren't very helpful, so I decided to look what's going on in MPlayer.&lt;/p&gt;

&lt;p&gt;I started MPlayer in strace&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;
$ strace mplayer movie.ogg 2&gt;&amp;1 | grep input
...
open("/dev/input/js0", O_RDONLY|O_NONBLOCK|O_LARGEFILE) = 3
...
&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;MPlayer was opening some joystick for reading. But I didn't have any joystick plugged in, since I borrowed my gamepad to a friend two days ago.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Heuréka!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Looking in &lt;code&gt;/sys/devices&lt;/code&gt; folder, I found out, that Microsoft SideWinder mouse registers itself as mouse device as well as joystick device. Before I unplugged my gamepad, MPlayer was attaching itself to my gamepad at &lt;code&gt;/dev/input/js0&lt;/code&gt; and since I don't have it connected anymore, mouse gets assigned to &lt;code&gt;js0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With this knowledge, the fix was extremely easy:&lt;/p&gt;

&lt;blockquote&gt;
echo "input:js-dev=no" &gt;&gt; ~/.mplayer/config
&lt;/blockquote&gt;

&lt;p&gt;And voilá. Everything works as expected.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-1654564584090665802?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2009/02/mplayer-mouse-volume-issue.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-6190493766809575561</guid><pubDate>Fri, 30 Jan 2009 00:00:00 +0000</pubDate><atom:updated>2009-01-30T17:20:38.740+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">linux</category><category domain="http://www.blogger.com/atom/ns#">unix</category><category domain="http://www.blogger.com/atom/ns#">mail</category><category domain="http://www.blogger.com/atom/ns#">perl</category><title>Sending mail with multiple attachments from Perl</title><description>&lt;p&gt;It always annoys me a whole lot, when I'm writing some Unix/Linux shell script and I need to send an email with attachments - there simply isn't an easy way.&lt;/p&gt;

&lt;p&gt;Standard &lt;core&gt;mail&lt;/code&gt; doesn't support any attachments whatsoever, in some versions of &lt;code&gt;mailx&lt;/code&gt; one attachment is supported and &lt;code&gt;mpack&lt;/code&gt; is generally not available at all.&lt;/p&gt;

&lt;p&gt;Since I found out, that some of the servers, I need to deploy my script to, don't even have &lt;code&gt;uuencode&lt;/code&gt; installed, I decided to write myself a small standalone utility in Perl for sending multi-attachment emails.&lt;/p&gt;

&lt;p&gt;There are lots of existing solutions in CPAN for this, but I specifically needed something, that's using only core Perl modules and sendmail - things I can count to find on every server.&lt;/p&gt;

&lt;pre class="cpp"&gt;
#!/usr/bin/perl
use strict;
use MIME::Base64;

if ($#ARGV &amp;lt; 2)
{
        print(STDERR "Not enough parameters\n\n");
        print(STDERR "Usage:\n");
        print(STDERR "\t./send.pl e\@mail \"Subject\" file1 file2 ...\n");
        print(STDERR "\t./send.pl \"e\@mail,a\@ddress\" \"Subject\" file1 file2 ...\n\n");
        exit -1;
}

#Sendmail requires email addresses to be separated by comma AND space
my $to = $ARGV[0];
$to =~ s/,/, /g;

open STDOUT, "|/usr/sbin/sendmail -t";

my $boundary = "_----------=_10167391557129230";

print("Content-Transfer-Encoding: 7bit\n");
print("Content-Type: multipart/mixed; boundary=\"$boundary\"\n");
print("MIME-Version: 1.0\n");
print("Date: ".`date`);
print("To: $to\n");
print("Subject: $ARGV[1]\n\n");

for (my $i = 2; $i &amp;lt;= $#ARGV; $i++)
{
        my $basename = `basename $ARGV[$i]`;
        $basename =~ s/\s//g;
        print("\n--".$boundary."\n");
        print("Content-Transfer-Encoding: base64\n");
        print("Content-Type: application/octet-stream; name=\"$basename\"\n\n");

        local $/=undef;
        open FILE, $ARGV[$i] or die "Couldn't open file $ARGV[$i]";
        binmode FILE;
        my $content = &amp;lt;FILE&amp;gt;;
        close FILE;

        print encode_base64($content)."\n\n";
}

print("--$boundary\n.\n");
&lt;/pre&gt;

&lt;p&gt;The code depends on two things:
&lt;ol&gt;
 &lt;li&gt;&lt;code&gt;sendmail&lt;/code&gt; being available in &lt;code&gt;/usr/sbin&lt;/code&gt;&lt;/li&gt;
 &lt;li&gt;Perl core module &lt;code&gt;MIME::Base64&lt;/code&gt; - every standard Perl installation has this.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is a little issue in the code - the MIME boundary is hard coded and not checked for uniqueness, but since we're using Base64 there is not much possibility of a clash.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-6190493766809575561?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2009/01/sending-mail-with-multiple-attachments.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-1715817858276965979</guid><pubDate>Sun, 11 Jan 2009 00:00:00 +0000</pubDate><atom:updated>2009-01-11T08:00:00.948+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">gentoo</category><category domain="http://www.blogger.com/atom/ns#">linux</category><title>Free Desktop At Last</title><description>&lt;p&gt;When &lt;a href="http://www.gettingclever.com/2009/01/bringing-gentoo-into-2009.html"&gt;reinstalling&lt;/a&gt; my Gentoo, I decided to give the &lt;a href="http://www.x.org/wiki/radeon"&gt;radeon&lt;/a&gt; - open source ATI driver - a try. I have Radeon 9600XT and I always had issues with the closed source fglrx driver from ATI.&lt;/p&gt;

&lt;p&gt;I wasn't expecting much from the free driver, but the current functionality simply blew me away - dual monitors, 3D acceleration, video playback - everything works nicely. I can't honestly think of anything more I could ask for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thank you guys so much!!!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Currently the stable xorg-server is version 1.3 and xorg-x11 is at version 7.2, but since I like my software freshly build (plus I wanted to give the compiz fusing a try), I had to accept the unstable packages when compiling.&lt;/p&gt;

&lt;blockquote&gt;
 &lt;code&gt;ACCEPT_KEYWORDS="~x86" emerge xorg-x11 xorg-server&lt;/code&gt;
&lt;/blockquote&gt;

&lt;p&gt;Gentoo is a distribution for power users/developers, so I sometimes find the release process little too conservative. I would mark packages as stable much sooner, but that's probably just me :).&lt;/p&gt;

&lt;p&gt;So now I'm just moving wobbly windows around my desktop and grinning :))&lt;/p&gt;

&lt;p&gt;Freedom at last.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-1715817858276965979?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2009/01/free-desktop-at-last.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-8354852422951047214</guid><pubDate>Tue, 06 Jan 2009 00:00:00 +0000</pubDate><atom:updated>2009-01-06T08:00:00.260+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">gentoo</category><category domain="http://www.blogger.com/atom/ns#">linux</category><title>Bringing Gentoo into 2009</title><description>&lt;p&gt;I was forced to use Windows exclusively for past couple of months due to various reasons and I was missing my &lt;a href="http://gentoo.org"&gt;Gentoo&lt;/a&gt; installation a lot. As a New Year's gift to my computer I decided to reinstall the whole thing, because the installation has been quite dated with lot of unused packages, many obsolete flags and still on gcc 3.4&lt;/p&gt;

&lt;p&gt;I was thinking how to do the installation most conveniently, but eventually decided to wipe the whole installation away and keep only&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;/etc/passwd&lt;/li&gt;
 &lt;li&gt;/etc/shadow&lt;/li&gt;
 &lt;li&gt;/etc/fstab&lt;/li&gt;
 &lt;li&gt;/home/&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Accidentally I managed to delete my &lt;code&gt;/lib&lt;/code&gt; folder while doing the cleanup and was left with non working system :)&lt;/p&gt;

&lt;p&gt;Because my computer doesn't have any working CD/DVD drives and can't boot from USB, I was really happy Grub can find kernel images on FAT32 partitions&lt;/p&gt;

&lt;p&gt;So I downloaded the Gentoo LiveCD, unpacked it to my Windows harddrive and restarted the computer&lt;/p&gt;

&lt;pre class="c++"&gt;
 kernel (hd0,0)/gentoo_livecd/isolinux/gentoo
 initrd (hd0,0)/gentoo_livecd/isolinux/gentoo.igz
 boot
&lt;/pre&gt;

&lt;p&gt;The kernel got loaded and to my extreme surprise the gentoo.igz ramdisk contains a minimal shell with busybox, so I was able to do all the mounting, deleting and copying files I needed. Yeey from Gentoo and Linux.&lt;/p&gt;

&lt;p&gt;So guess what I'm doing now? Compiling... :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-8354852422951047214?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2009/01/bringing-gentoo-into-2009.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-508274319661075679</guid><pubDate>Mon, 29 Dec 2008 00:00:00 +0000</pubDate><atom:updated>2009-01-29T21:04:26.785+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">win32</category><category domain="http://www.blogger.com/atom/ns#">C++</category><title>List your HWNDs</title><description>&lt;p&gt;For Win32 GUI debugging I'm usually using &lt;a href="http://www.windows-spy.com/"&gt;WinSpector&lt;/a&gt; (I highly recommend it), but as it turns out WinSpector doesn't display owner windows (or maybe I just can't find it).&lt;/p&gt;

&lt;p&gt;I was debugging a foreground activation error when the application was running through Citrix. As it turns out in certain combinations of Citrix clients and Citrix server registry setting, the windows ownership on the client is different than on the desktop.&lt;/p&gt;

&lt;p&gt;I highly doubt this will be useful to anyone else but me, but here it goes anyway: lshwnd - program for listing all HWNDs, their parents and their owners.&lt;/p&gt;

&lt;pre class="cpp"&gt;
#define UNICODE

#include &amp;lt;windows.h&amp;gt;
#include &amp;lt;vector&amp;gt;

wchar_t name[1000];

BOOL CALLBACK myEnum(HWND hwnd, LPARAM lParam)
{
 std::vector&amp;lt;HWND&amp;gt; *windows = (std::vector&amp;lt;HWND&amp;gt;*)lParam;
 windows-&amp;gt;push_back(hwnd);
}

void enumerate(HWND hwnd, int depth)
{
 std::vector&amp;lt;HWND&amp;gt; windows;
 EnumChildWindows(hwnd, myEnum, LPARAM(&amp;windows));
 GetWindowText(hwnd, name, 1000);

 for (int i = 0; i &amp;lt; depth; i++)
  wprintf(L"    ");
 
 wprintf(L"%x:%x - %s\n", hwnd, GetAncestor(hwnd, GA_ROOTOWNER), name);

 for (int i = 0; i &amp;lt; windows.size(); i++)
 {
  enumerate(windows[i], depth+1);
 }
}

int main()
{
 enumerate(NULL, 0);

 return 0;
}
&lt;/pre&gt;

&lt;p&gt;
Usage is quite easy, you start

&lt;blockquote&gt;
 lshwnd.exe &amp;gt; hwnd.txt
&lt;/blockquote&gt;

and you will get a list of all your HWNDs in a tree structure according to parent child relationship. Every HWND is represented as 

&lt;/p&gt;

&lt;pre&gt;
parent:parent_owner parent_window_title
 child:child_owner child_window_title
&lt;/pre&gt;

&lt;p&gt;
&lt;img src="http://ondrew.googlepages.com/lshwnd.png" alt="Relationship structure"/&gt;
&lt;/p&gt;

&lt;p&gt;Version for download &lt;a href="http://ondrew.googlepages.com/lshwnd.zip"&gt;lshwnd.zip&lt;/a&gt; - 11 kB &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-508274319661075679?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2008/12/list-your-hwnds.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-7837667795084381050</guid><pubDate>Fri, 26 Dec 2008 00:00:00 +0000</pubDate><atom:updated>2008-12-26T08:00:00.299+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">living without admin</category><category domain="http://www.blogger.com/atom/ns#">C#</category><title>Snooping on TCP connections - Putting the MAN in the Middle</title><description>&lt;p&gt;It's quite often when debugging a networking application, that you have to look at the underlaying data. You might say, this is very easy with existing tools like &lt;a href="http://www.tcpdump.org"&gt;tcpdump&lt;/a&gt; and &lt;a href="http://www.winpcap.org/windump/"&gt;windump&lt;/a&gt;. But let's say you have to do it on a remote server without admin rights. Suddenly the task is not so easy.&lt;/p&gt;

&lt;p&gt;You can usually get away with telnet in case you need to simulate the client or more preferably netcat (where you can simulate the server as well). However sometimes you just want to watch the communication between two endpoints.&lt;/p&gt;

&lt;p&gt;You basically need a tunnel, that will forward all communication and simultaneously write all the data to file / screen.&lt;/p&gt;

&lt;p&gt;I wrote a little program for that, it's called &lt;code&gt;middleman&lt;/code&gt; and it saves all communication in files. New file is created for every connection and raw data from both endpoints are written into this &lt;em&gt;one&lt;/em&gt; file. If the protocol, you will be monitoring is hard to understand, you can modify the program to split the communication into two files, the program is quite simple, so it shouldn't be much of a problem:&lt;/p&gt;

&lt;pre class="csharp"&gt;
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;

class Client
{
 int id;
 TcpClient local;
 TcpClient remote;
 NetworkStream localStream;
 NetworkStream remoteStream;
 FileStream file;

 public Client(TcpClient newLocal, string remoteAddress, int remotePort, int nid)
 {
  local = newLocal;
  localStream = local.GetStream();
  remote = new TcpClient(remoteAddress, remotePort);
  remoteStream = remote.GetStream();
  id = nid;

  file = new FileStream("session_" + Convert.ToString(nid) + ".txt", FileMode.Create);
 }

 public void process()
 {
  int time = 0;
  int i;
  Byte[] bytes = new Byte[4096];
  while(true)
  {
   if (localStream.DataAvailable)
   {
    if ( (i = localStream.Read(bytes, 0, bytes.Length)) != 0)
    {
     try 
     {
      if (remoteStream.CanWrite)
      {
       remoteStream.Write(bytes, 0, i);
       file.Write(bytes, 0, i);
      }
     }
     catch (Exception)
     {
      break;
     }
    }
    time = 0;
   }

   if (remoteStream.DataAvailable)
   {
    if ( (i = remoteStream.Read(bytes, 0, bytes.Length)) != 0)
    {
     try
     {
      if (localStream.CanWrite)
      {
       localStream.Write(bytes, 0, i);
       file.Write(bytes, 0, i);
      }
     }
     catch (Exception)
     {
      break;
     }
    }
    time = 0;
   }

   time++;

   Thread.Sleep(1);

   if (time &gt; 5000)
    break;
  }
  remote.Close();
  local.Close();
  file.Close();
 }
}

class ManInTheMiddle
{
 static int Main(string[] args)
 {
  int localPort, remotePort;
  string localAddress, remoteAddress;

  switch (args.Length)
  {
   case 2 :
    remoteAddress = args[0];
    remotePort = localPort = Int32.Parse(args[1]);
    localAddress = "127.0.0.1";
    break;

   case 3:
    remoteAddress = args[0];
    remotePort = Int32.Parse(args[1]);
    localAddress = "127.0.0.1";
    localPort = Int32.Parse(args[2]);
    break;
   case 4:
    remoteAddress = args[0];
    remotePort = Int32.Parse(args[1]);
    localAddress = args[2];
    localPort = Int32.Parse(args[2]);
    break;
   default:
    Console.WriteLine("MiddleMan - Tool for snooping on TCP/IP connections");
    Console.WriteLine("");
    Console.WriteLine("Usage: middleman remote_server port");
    Console.WriteLine("Usage: middleman remote_server remote_port local_port");
    Console.WriteLine("Usage: middleman remote_server remote_port local_ip_address local_port");
    Console.WriteLine("");
    Console.WriteLine("");
    Console.WriteLine("MiddleMan starts listening as a server on local_ip_address (default 127.0.0.1)");
    Console.WriteLine("on local_port. All incoming connections to this server are forwarded");
    Console.WriteLine("to remote_server:remote_port and logged into a file.");
    Console.WriteLine("");
    Console.WriteLine("");
    return 0;
  }
  
  TcpListener server = new TcpListener(IPAddress.Parse(localAddress), localPort);
  server.Start();

  int id = 0;

  while(true)
  {
   Client client = new Client(server.AcceptTcpClient(), remoteAddress, remotePort, id++);
   Thread w = new Thread(new ThreadStart(client.process));
   w.Start();
  }
 }
}
&lt;/pre&gt;

&lt;p&gt;The usage is quite simple, you specify the IP address or hostname, which you want to connect your tunnel to and the port&lt;/p&gt;

&lt;blockquote&gt;
 middleman www.google.com 80
&lt;/blockquote&gt;

&lt;p&gt;From now on, all the communication that goes to &lt;code&gt;localhost:80&lt;/code&gt; will be forwarded to &lt;code&gt;google:80&lt;/code&gt; and will be simultaneously written to a file&lt;/p&gt;

&lt;p&gt;In case you specify only one port (as in the example above), middleman will start listening on the same port as is the remote server listening on (in this case 80). If for whatever reason you can't use the same port on the local machine, you can start middleman like this:&lt;/p&gt;

&lt;blockquote&gt;
 middleman www.google.com 80 81
&lt;/blockquote&gt;

&lt;p&gt;which means - forward all requests from &lt;code&gt;localhost:81&lt;/code&gt; to &lt;code&gt;google.com:80&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Simple demonstration video follows:&lt;/p&gt;

&lt;object width="640" height="505"&gt;&lt;param name="movie" value="http://www.youtube.com/v/O8beycAY6Ak&amp;hl=en&amp;fs=1ap=%2526fmt%3D18"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/O8beycAY6Ak&amp;hl=en&amp;fs=1&amp;ap=%2526fmt%3D18" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="505"&gt;&lt;/embed&gt;&lt;/object&gt;

&lt;p&gt;Download &lt;a href="http://ondrew.googlepages.com/middleman.zip"&gt;middleman.zip&lt;/a&gt; - 6kB&lt;/p&gt;

&lt;p&gt;Obligatory thanks to Mark James for creating the amazing &lt;a href="http://www.famfamfam.com/lab/icons/silk/"&gt;Silk icons&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-7837667795084381050?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2008/12/snooping-on-tcp-connections-putting-man.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-1636219139927588421</guid><pubDate>Wed, 24 Dec 2008 00:00:00 +0000</pubDate><atom:updated>2008-12-24T18:07:52.761+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ludum dare</category><category domain="http://www.blogger.com/atom/ns#">Lua</category><category domain="http://www.blogger.com/atom/ns#">C++</category><title>Ludum Dare 2008</title><description>&lt;p&gt;The theme of this year's Ludum Dare competition was &amp;quot;Roads&amp;quot;. So how did I do?&lt;/p&gt;

&lt;h3&gt;The game&lt;/h3&gt;

&lt;p&gt;Here is a video from my game&lt;/p&gt;

&lt;object width="480" height="295"&gt;&lt;param name="movie" value="http://www.youtube.com/v/sZMWQI0e8S4&amp;hl=en&amp;fs=1&amp;ap=%2526fmt%3D18"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/sZMWQI0e8S4&amp;hl=en&amp;fs=1&amp;ap=%2526fmt%3D18" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="295"&gt;&lt;/embed&gt;&lt;/object&gt;

&lt;p&gt;and the game itself &lt;a href="http://ondrew.googlepages.com/ludum2008_chopper_speed2.7z"&gt;Chopper vs Trucks&lt;/a&gt; 3 MB&lt;/p&gt;

&lt;h3&gt;The Backend&lt;/h3&gt;

&lt;p&gt;In the beginning I wanted to use Lua to define the game logic, but I found out, that it's not easy to integrate OPP with Lua, so I wrote the whole logic in C++. But I definitely want to investigate Lua integration with C++ further to use it in my following projects.&lt;/p&gt;

&lt;p&gt;What really paid of was my one-click deployment system. I was running a webserver on my development PC and every time I wanted to test something I made a release:&lt;/p&gt;

&lt;blockquote&gt;
7zip a -r -x!.\* /$(RELEASE_DIR)/angiine.release/angiine$(DATE).7z $(ANGIINE_DIR)
&lt;br /&gt;
 cp /$(RELEASE_DIR)/angiine.release/angiine$(DATE).7z /$(RELEASE_DIR)/angiine.release/angiine_current.7z
&lt;/blockquote&gt;

&lt;p&gt;And on the target computer I had a batch file looking like this&lt;/p&gt;

&lt;blockquote&gt;
 wget http://server/angiine_current.7z
&lt;br /&gt;
 7z x angiine.current.7z
&lt;br /&gt;
 cd angiine/bin/ 
&lt;br /&gt;
 ./angiine
&lt;/blockquote&gt;

&lt;p&gt;The whole cycle &lt;em&gt;&amp;quot;recompile, package, download, unpack and start&amp;quot;&lt;/em&gt; took about ten to fifteen seconds. I was able to test the game on two different computers almost seamlessly and I can't recommend this hard enough.&lt;/p&gt;

&lt;p&gt;For real masochist you can check you all the versions of the game I managed to produce during the 48 hours - &lt;a href="http://ondrew.googlepages.com/angiine.releases.7z"&gt;angiine.releases.7z&lt;/a&gt; 4 MB&lt;/p&gt;

&lt;h3&gt;The Progress&lt;/h3&gt;

&lt;p&gt;During the compo, I spent quite some time on loading 3D models to my C++ program. I should have prepared my base library and not waste my time with this during the competition time.&lt;/p&gt;

&lt;p&gt;
 Here are some progress screenshots of the game:
&lt;/p&gt;

&lt;p&gt;
 &lt;img src="http://ondrew.googlepages.com/ludum2008_heli01.png" alt="Progress screenshot #1"/&gt;
 &lt;img src="http://ondrew.googlepages.com/ludum2008_heli02.png" alt="Progress screenshot #2" /&gt;
 &lt;img src="http://ondrew.googlepages.com/ludum2008_heli03.png" alt="Progress screenshot #3" /&gt;
 &lt;img src="http://ondrew.googlepages.com/ludum2008_heli04.png" alt="Progress screenshot #4" /&gt;
 &lt;img src="http://ondrew.googlepages.com/ludum2008_final01.png" alt="Final screenshot #1" /&gt;
 &lt;img src="http://ondrew.googlepages.com/ludum2008_final02.png" alt="Final screenshot #2" /&gt;
&lt;/p&gt;

&lt;p&gt;For more information, you can look at my almost award winning journal :) &lt;a href="http://www.ludumdare.com/compo/?category_name=ld13&amp;author_name=ondrew"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Statistics&lt;/h3&gt;

&lt;p&gt;For anyone interested, here is my timelapse&lt;/p&gt;

&lt;p&gt;
&lt;object width="480" height="295"&gt;&lt;param name="movie" value="http://www.youtube.com/v/PAu-JOiZpYk&amp;hl=en&amp;fs=1&amp;ap=%2526fmt%3D18"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/PAu-JOiZpYk&amp;hl=en&amp;fs=1&amp;ap=%2526fmt%3D18" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="295"&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;/p&gt;

&lt;p&gt;This is an overview of which programs I used the most during the competition:
&lt;/p&gt;

&lt;p&gt;
 &lt;img src="http://chart.apis.google.com/chart?cht=p&amp;chs=600x400&amp;chd=t:43.0437,12.0542,10.3466,8.73933,5.92667,5.37418,3.8674,3.4656,2.15972,1.70768,1.25565,0.652938&amp;chl=gvim|console|firefox|blender|angiine|mplayer|totalcmd|photoshop|scrnsave.scr|miranda|hh|gimp-2.6"/&gt;
&lt;/p&gt;

&lt;h3&gt;Results&lt;/h3&gt;

&lt;p&gt;
 &lt;table&gt;
  &lt;tr&gt;&lt;td&gt;Overall&lt;/td&gt;&lt;td&gt;32/59&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;Fun&lt;/td&gt;&lt;td&gt;39/59&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;Innovation&lt;/td&gt;&lt;td&gt;28/59&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;Theme&lt;/td&gt;&lt;td&gt;42/59&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;Polish&lt;/td&gt;&lt;td&gt;40/59&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;Graphics&lt;/td&gt;&lt;td&gt;20/59&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;Audio&lt;/td&gt;&lt;td&gt;42/59&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;Humor&lt;/td&gt;&lt;td&gt;28/59&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;Technical&lt;/td&gt;&lt;td&gt;12/59&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;Food&lt;/td&gt;&lt;td&gt;28/59&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;Journal&lt;/td&gt;&lt;td&gt;5/59&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;Towlr&lt;/td&gt;&lt;td&gt;29/59&lt;/td&gt;&lt;/tr&gt;
 &lt;/table&gt;

 My best scores were in categories Journal (5th place - &lt;a href="http://www.ludumdare.com/compo/?category_name=ld13&amp;amp;author_name=ondrew"&gt;link&lt;/a&gt;) and Technical (12th place). I'm very happy about that, but I will definitely try to do better next time :).
&lt;/p&gt;

&lt;p&gt;So that was my Ludum Dare compo overview - I had extreme fun, I slept very little and after turning my game in, I got amazing sense of accomplishment. Kudos to the organizers, I'm already looking forward to the next one.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-1636219139927588421?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2008/12/ludum-dare-2008.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-3239728918909454493</guid><pubDate>Tue, 02 Dec 2008 00:00:00 +0000</pubDate><atom:updated>2008-12-02T08:20:29.876+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">win32</category><category domain="http://www.blogger.com/atom/ns#">ludum dare</category><title>Preparing for Ludum Dare 2008 - Take multimonitor screenshots</title><description>&lt;p&gt;It's part of the whole Ludum Dare experience to record your desktop every few minutes and create a movie afterwords which overviews your progress.&lt;/p&gt;

&lt;p&gt;Since I recently became a proud owner of a second monitor, I found myself in need for a multi-monitor screenshot making tool. There are probably some utilities, which do exactly that, but I'm too lazy to look for them and decided to write my own tool.&lt;/p&gt;

&lt;p&gt;This is just a very stupid prototype, which I will be using/testing during the competition. It doesn't save the files into one image but one image per monitor. That's kind of unfortunate, but composing picture from different DCs is no fun.&lt;/p&gt;

&lt;p&gt;The other thing the program does is that it records which program was in foreground while you took the screenshot and records the data into sqlite database&lt;/p&gt;

&lt;p&gt;So afterwards you can just start &lt;code&gt;sqlite3 data.db&lt;/code&gt; and type in following command:&lt;/p&gt;

&lt;blockquote&gt;
SELECT process, count(*) AS sum FROM work GROUP BY process ORDER BY sum;
&lt;/blockquote&gt;

&lt;p&gt;You'll receive a nice overview about which application you used the most during the competition / monitoring time.&lt;/p&gt;

&lt;p&gt;Here you can see my relative application use in the past 10 months on my work computer:&lt;/p&gt;

&lt;img src="http://chart.apis.google.com/chart?cht=p&amp;chs=600x400&amp;chd=t:100,40,28,23,21,16,16,14,11,11,7,4,4,3,3&amp;chl=firefox|outlook|gvim|totalcmd|miranda|putty|console|mplayer|wfica32|explorer|iexplore|excel|acrord32|wjview|winword" alt="I spend more than 50% of my time in firefox"/&gt;

&lt;p&gt;I guess I'm researching a lot :)&lt;/p&gt;

&lt;p&gt;So for anyone interested, the download is - &lt;a href="http://ondrew.googlepages.com/logger-0.1.zip"&gt;logger-0.1.zip&lt;/a&gt; (300 kB)
&lt;/p&gt;

&lt;p&gt;Thanks to Mark James for creating the amazing &lt;a href="http://www.famfamfam.com/lab/icons/silk/"&gt;Silk icons&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-3239728918909454493?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2008/12/preparing-for-ludum-dare-2008-take.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-4501106381566204658</guid><pubDate>Mon, 01 Dec 2008 00:00:00 +0000</pubDate><atom:updated>2008-12-01T08:00:01.031+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ludum dare</category><title>Preparing for Ludum Dare 2008 - Looking Back at my 48 Hour Compos History</title><description>&lt;p&gt;As many young programmers I actually got into programming by writing games (or more precisely by trying to write games :) ).&lt;/p&gt;

&lt;p&gt;In past years I've been constantly programming one game or another, not really finishing one, but often jumping to different project whenever new idea/technology came along.&lt;/p&gt;

&lt;p&gt;Therefore I always liked the idea of 48 hours game programming competitions. You have to create a game according to some theme within one weekend. You have to create everything from scratch - the code, the graphics and the sounds. Although it might seem like a very short time and very limiting, it's quite the opposite. I've never found myself as concentrated, motivated and productive as within these weekends.&lt;/p&gt;

&lt;p&gt;Due to Real Life&amp;trade; I actually managed to finish a game just once out of my three tries. However I'm dedicated to finish a game in Ludum Dare 2008, which takes place this weekend.&lt;/p&gt;

&lt;p&gt;But before I can start preparing for this years competition, I have to take a look at the past&lt;/p&gt;

&lt;h2&gt;Ludum Dare 2004&lt;/h2&gt;

&lt;p&gt;This was my first 48hrs competition and it was a blast. Also this is the only competition, I actually managed to finish a game.&lt;/p&gt;

&lt;p&gt;The theme was Infection, the name of the game was &amp;quot;Awesome Adventures of Superhand&amp;quot; and I'm going to let one fellow competitor summarize my game:&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;philhassey:&lt;/strong&gt; I liked the hand marching around kicking stuff :)&lt;/blockquote&gt;

&lt;p&gt;That was actually one of the nicest reviews I got and to this day, I'm extremely proud of it.&lt;/p&gt;

&lt;p&gt;I'm fairly confident, that I had the smoothest walkcycle in the whole competition. I simply took my digital camera, recorded a short video of my hand walking around against a sheet of white paper and then processed it into a walkcycle. I had the animations for my character finished in about two hours.&lt;/p&gt;

&lt;img src="http://ondrew.googlepages.com/ludum2004_superhand1.png" alt="SuperHand walking around and kicking stuff in the park"/&gt;

&lt;p&gt;Unfortunately I decided for resolution of 800x600, which is a lot of pixels to draw. So I spent quite a lot of time drawing background - sky, trees, road and trying to make them look as good as possible.&lt;/p&gt;

&lt;p&gt;The game had tons of problems - it would crash on startup on some computers, wouldn't run without sound card (forgot to test for lack of it), the speed of the game was driven by framerate, the difficulty was too hard, etc. But all in all, I finished a game in two days and that's all that matters to me :).&lt;/p&gt;

&lt;img src="http://ondrew.googlepages.com/ludum2004_superhand2.png" alt="SuperHand walking around and kicking stuff in the street"/&gt;

&lt;p&gt;An unexpected thing happened about two hours before deadline. The game was playable, the gameplay was reasonably fun and there weren't any bugs I was aware of - the game was finished. I felt an overwhelming sense of accomplishment. I felt I could do anything. In about twenty minutes I created a menu.&lt;/p&gt;

&lt;img src="http://ondrew.googlepages.com/ludum2004_superhandmenu.png" alt="Awesome adventures of Superhand Menu Screen"/&gt;

&lt;p&gt;And in another ten I created an intro screen. I was on top of my productivity and I was certain, I will be able to add any feature I could think of.&lt;/p&gt;

&lt;img src="http://ondrew.googlepages.com/ludum2004_superhandintro.png" alt="Awesome adventures of Superhand Intro"/&gt;

&lt;p&gt;But I didn't think of anymore features, I just played the game over and over and basked in the newfound sense of accomplishment and it was awesome.&lt;/p&gt;

&lt;h2&gt;TINS 2005 (TINS Is Not Speedhack)&lt;/h2&gt;

&lt;p&gt;A year later a TINS competition came by and I had no other option than to sign up. The competition archives are located &lt;a href="http://amarillion.bafsoft.net/tins05/"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;artistic genre: parody&lt;/li&gt;
 &lt;li&gt;artistic rule: give the player something to Unlock&lt;/li&gt;
 &lt;li&gt;artistic rule: trolls are cool, have a troll in your game&lt;/li&gt;
 &lt;li&gt;technical rule: make clever use of sine waves&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although I'm no pixel artist, I was actually able to come up with some sprites within a reasonable time frame. The idea of the game was a troll working in big corporate company. It would have been a little adventure/platform shooter.&lt;/p&gt;

&lt;p&gt;I fell ill before I could come up with a clever use of sine waves, but I figured, that the enemy would be simply shooting them or something. Not really clever, but hey, my main character is a troll :).&lt;/p&gt;

&lt;img src="http://ondrew.googlepages.com/tins05_level1.png" alt="Troll in the office"/&gt;

&lt;p&gt;Some of troll's actions&lt;/p&gt;

&lt;img src="http://ondrew.googlepages.com/tins05_trol.png" alt="Troll actions"/&gt;

&lt;p&gt;and walkcycle and gruesome death of an enemy&lt;/p&gt;

&lt;img src="http://ondrew.googlepages.com/tins05_enemy.png" alt="Enemy walking and dying"/&gt;

&lt;p&gt;Unfortunately I fell ill during this competition, so I couldn't finish.&lt;/p&gt;

&lt;p&gt;But the good thing was that I started to work in 320x200 resolution - lot less pixels to cover and it has this cool retro look to it.&lt;/p&gt;

&lt;h2&gt;Ludum Dare 2006&lt;/h2&gt;

&lt;p&gt;The theme for this competition was &amp;quot;Swarms&amp;quot;. This time I decided, that it's finally time to learn some OpenGL, so I started writing my game in 3D without any previous knowledge.&lt;/p&gt;

&lt;p&gt;The idea was, that you will be a gravitation centre of a particle swarm and you will be travelling in a tube with a lot of obstacles. The center will be able to exert gravity on all the particles and pull them towards itself.&lt;/p&gt;

&lt;p&gt;To my surprise I was actually able to pull the 3D off, what I didn't managed was Real Life&amp;trade;, awesomeness of gravity and 3D collisions. The collisions took so much time to fake right, that it would probably be faster to implement them for real.&lt;/p&gt;

&lt;img src="http://ondrew.googlepages.com/ludum2006_swarm1.png" alt="Swarming 1"/&gt;

&lt;p&gt;When I implemented gravity, the &amp;quot;game&amp;quot; became so interesting, that I spend couple of hours just chasing particles on the screen. I would move the gravity there and back just to watch the particles speed up, get pulled in different direction, rotate, slow down etc.&lt;/p&gt;

&lt;p&gt;This point is quite critical for all my game projects. As soon as my game is playable and provides the tiniest amount of challenge/fun, I get completely hooked and play it over and over.&lt;/p&gt;

&lt;img src="http://ondrew.googlepages.com/ludum2006_swarm2.png" alt="Swarming 2"/&gt;

&lt;p&gt;I can imagine it happens to other programmers as well, because it's your own creation, that you are playing, but for the future successes in 48hr competitions I should avoid this habit :).&lt;/p&gt;

&lt;h2&gt;Learnings&lt;/h2&gt;

&lt;p&gt;So what did I learn from the past:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Buy a lot of oranges, so that you don't fall ill&lt;/li&gt;
 &lt;li&gt;&lt;strong&gt;DO NOT PLAY YOUR GAME&lt;/strong&gt;&lt;/li&gt;
 &lt;li&gt;Choose a low resolution&lt;/li&gt;
 &lt;li&gt;Choose wisely between 2D and 3D
  &lt;ul&gt;
   &lt;li&gt;2D is hard&lt;/li&gt;
   &lt;li&gt;3D is harder&lt;/li&gt;
   &lt;li&gt;sprites are a lot of work&lt;/li&gt;
   &lt;li&gt;3D models are easy to create, move, rotate and to scale&lt;/li&gt;
  &lt;/ul&gt;
 &lt;/li&gt;
 &lt;li&gt;Have a distribution channel in place, so that your friends can test your game without any effort from your side (script that automatically uploads your game somewhere, etc). This is tremendous help and if it's automated it's tremendous time saver.&lt;/p&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-4501106381566204658?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2008/12/preparing-for-ludum-dare-2008-looking.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-1945261339773157323</guid><pubDate>Tue, 23 Sep 2008 06:00:00 +0000</pubDate><atom:updated>2008-09-23T14:22:46.883+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">win32</category><category domain="http://www.blogger.com/atom/ns#">fonts</category><category domain="http://www.blogger.com/atom/ns#">living without admin</category><category domain="http://www.blogger.com/atom/ns#">C++</category><title>Using Fonts Without Installation</title><description>&lt;p&gt;And here we go again, the same old story - corporate environment, users unable to install additional fonts. I find the font management in Windows pretty weak, all users are locked into the same setting, without any kind of possibility how to tailor it to their preferences. &lt;strong&gt;Until now that is!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What happens during font installation:
 &lt;ol&gt;
  &lt;li&gt;Font file is copied to &lt;code&gt;%WINDIR%\Fonts&lt;/code&gt; directory&lt;/li&gt;
  &lt;li&gt;New font entry is created in registry &lt;code&gt;HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts&lt;/code&gt; describing font's name and file.&lt;/li&gt;
  &lt;li&gt;Function &lt;a href="http://msdn.microsoft.com/en-us/library/ms534231(VS.85).aspx"&gt;AddFontResource&lt;/a&gt; is called, which updates the global font table.&lt;/li&gt;
 &lt;/ol&gt;
&lt;/p&gt;

&lt;p&gt;Since the &lt;code&gt;AddFontResource&lt;/code&gt; function doesn't require the font to reside in Windows Fonts directory neither the relevant entry in registry to exist, we can just call it with font placed anywhere. The following code illustrates how:&lt;/p&gt;

&lt;pre class="cpp"&gt;
#include &amp;lt;windows.h&amp;gt;
#include &amp;lt;ctype.h&amp;gt;

char* lower(char *s)
{
 char *result = (char *)malloc(strlen(s)+1);
 result[strlen(s)] = '\0';
 for (int i = strlen(s) - 1; i &amp;gt;= 0; i--)
 {
  result[i] = tolower(s[i]);
 }
 
 return result;
}

void processDirectory(char *initial, char *dir)
{
 char *wildcard = (char *)malloc(strlen(initial) + strlen(dir) + 2);

 memset(wildcard, 0, strlen(initial) + strlen(dir) + 2);
 strcat(wildcard, initial);

 strcat(wildcard, "\\");
 strcat(wildcard, dir);

 char *fulldir = (char *)malloc(strlen(wildcard));
 strcpy(fulldir, wildcard);
 strcat(wildcard, "\\*");

 WIN32_FIND_DATA data;

 HANDLE search = FindFirstFile(wildcard, &amp;data);

 if (search == INVALID_HANDLE_VALUE)
  return;

 do
 {
  if ((data.dwFileAttributes &amp; FILE_ATTRIBUTE_DIRECTORY)  
     &amp;&amp; (strcmp(data.cFileName, ".") != 0)
     &amp;&amp; (strcmp(data.cFileName, "..") != 0))
  {
   processDirectory(fulldir, data.cFileName);
  }
  else if (!(data.dwFileAttributes &amp; FILE_ATTRIBUTE_DIRECTORY))
  {
   char *s = lower(data.cFileName);
   if (strstr(s+strlen(s)-4, ".ttf") != 0)
   {
    int fontLength = strlen(fulldir) + strlen(data.cFileName) + 2;
    char *font = (char*)malloc(fontLength);
    memset(font, 0, fontLength);
    strcat(font, fulldir);
    strcat(font, "\\");
    strcat(font, data.cFileName);

    AddFontResource(font);
    free(font);
   }
   free(s);
  }
 } while(FindNextFile(search, &amp;data));

 free(wildcard);
 free(fulldir);

 FindClose(search);
}

int main(int argc, char *argv[])
{
 if (argc &amp;gt; 1)
 {
  for (int i = 1; i &amp;lt; argc; i++)
   processDirectory(argv[i], "");
 }
 else
  processDirectory(".", "");

 SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);

 return 0;
}
&lt;/pre&gt;

&lt;p&gt;Most of the code is dealing with string concatenation and not the real task at hand, but I didn't want to use C++ &lt;code&gt;string&lt;/code&gt; to keep it nicely Win32 :)&lt;/p&gt;

&lt;p&gt;What it actually does is that it takes a list of directories as arguments and goes recursively through all of them and every file ending with &lt;code&gt;.ttf&lt;/code&gt; adds as a new font resource to the system. In case no directories are supplied as parameters, the current directory is used.&lt;/p&gt;

&lt;p&gt;If you want to use it regularly, create a directory with your fonts and add to your Startup folder link to fontload.exe and give it as a parameter the name of your folder. Then after every computer start, your fonts get loaded automatically.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://ondrew.googlepages.com/fontload.png" alt="F:\Projects\fontload\fontload.exe F:\MyFonts"/&gt;&lt;/p&gt;

&lt;p&gt;Please note:
 &lt;ul&gt;
  &lt;li&gt;It takes quite a while to broadcast the notification that new fonts are available to all windows. The time is quite independent on amount of fonts installed and takes about twenty seconds on my computer.&lt;/li&gt;
  &lt;li&gt;Some applications might be very unhappy about this, if you encounter crashes, it could be this program's fault. Although it works fine for me, doesn't mean it will work for you :).&lt;/p&gt;
  &lt;li&gt;There is nothing preventing you from deleting the font files, which are loaded, so expect hilarious results upon doing so.&lt;/li&gt;
  &lt;li&gt;This program doesn't care about font unloading. If you want to unload the fonts, just restart the computer or figure out, how to use the &lt;a href="http://msdn.microsoft.com/en-us/library/ms533925(VS.85).aspx"&gt;RemoveFontResource&lt;/a&gt; function&lt;/li&gt;
 &lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;Source and binary version can be downloaded here - &lt;a href="http://ondrew.googlepages.com/fontload.zip"&gt;fontload.zip&lt;/a&gt; - 7kB.&lt;/p&gt;

&lt;p&gt;Next time, we will use this knowledge to create a simple font viewer, which will pollute the global font table only on request :).&lt;/p&gt;

&lt;p&gt;Obligatory thanks to Mark James for creating the amazing &lt;a href="http://www.famfamfam.com/lab/icons/silk/"&gt;Silk icons&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-1945261339773157323?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2008/09/using-fonts-without-installation.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-4917041139660125409</guid><pubDate>Fri, 12 Sep 2008 06:00:00 +0000</pubDate><atom:updated>2008-09-12T14:00:00.122+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">java</category><category domain="http://www.blogger.com/atom/ns#">hpux</category><category domain="http://www.blogger.com/atom/ns#">unix</category><category domain="http://www.blogger.com/atom/ns#">C++</category><title>Listing Full Command Line on HP-UX</title><description>&lt;p&gt;There is one very annoying limitation on HP-UX - there is no &lt;code&gt;/proc&lt;/code&gt; folder and ps command can display maximum 63 characters from processes command line. There is no simple way how to display full command line of a specified process.&lt;/p&gt;

&lt;p&gt;If you're working with Java programs, you know, that the first 63 characters barely reach the classpath definition. Usually it's just the path to the java binary.&lt;/p&gt;

&lt;p&gt;Yesterday I needed to find out, if one java program is not running multiple times. And guess what, it's almost impossible to find out on a server with tens of different java programs running. After lot of searching I came up with this program - it lists all the running process ids and their respective command lines. There is no original code happening, it's basically, this &lt;a href="http://forums12.itrc.hp.com/service/forums/questionanswer.do?threadId=349348&amp;admit=109447627+1221116039160+28353475"&gt;forum post&lt;/a&gt; merged with &lt;a href="http://docs.hp.com/en/B2355-90130/pstat.2.html"&gt;this manual page&lt;/a&gt;.&lt;/p&gt;

&lt;pre class="cpp"&gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;sys/pstat.h&amp;gt;
#include &amp;lt;sys/pstat/pstat_ops.h&amp;gt;
#define BURST 20
#define MAX_LENGTH 1024

struct pst_status pst[BURST];

int main(void)
{
char command [MAX_LENGTH];
        union pstun pu;

        int i, count;
        int idx = 0;/* index within the context */
        /* loop until count == 0, will occur all have been returned */

        while ((count=pstat_getproc(pst, sizeof(pst[0]),BURST,idx))&amp;gt;0)
        {
                for (i = 0; i &amp;lt; count; i++)
                {
                        pu.pst_command = command;
                        if (pstat(PSTAT_GETCOMMANDLINE, pu, MAX_LENGTH, 1, pst[i].pst_pid) == -1)
                        {
                                printf("ERROR: failure using pid(%d)\n", pst[i].pst_pid);
                                exit(-1);
                        }
                        printf("%d: %s\n",  pst[i].pst_pid, pu.pst_command);
                }
                idx = pst[count-1].pst_idx + 1;
        }

        if (count == -1)
                perror("pstat_getproc()");
}
&lt;/pre&gt;

&lt;p&gt;Compile the code with the following command&lt;/p&gt;

&lt;blockquote&gt;
 cc pstat.c -o pstat +DD64
&lt;/blockquote&gt;

&lt;p&gt;You have to include the &lt;code&gt;+DD64&lt;/code&gt; if you're on a 64bit system. Otherwise, you'll get following error:&lt;/p&gt;

&lt;blockquote&gt;
pstat_getproc(): Value too large to be stored in data type
&lt;/blockquote&gt;

&lt;p&gt;Of course, about five seconds after finishing this article I found a way how to do it with the original HP-UX &lt;code&gt;ps&lt;/code&gt; command, so please disregard my blabbering :)&lt;/p&gt;

&lt;blockquote&gt;
ps -exx
&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-4917041139660125409?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2008/09/listing-full-command-line-on-hp-ux.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-1170401052864749410</guid><pubDate>Mon, 01 Sep 2008 06:00:00 +0000</pubDate><atom:updated>2008-09-01T14:00:01.231+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">python</category><category domain="http://www.blogger.com/atom/ns#">SDL</category><category domain="http://www.blogger.com/atom/ns#">C++</category><title>Integrating SDL with Python</title><description>&lt;p&gt;&lt;a href="/2008/08/integrating-sdl-with-lua.html"&gt;Last time&lt;/a&gt; we embedded Lua interpreter into a simple OpenGL application and today I'm going to try the same with &lt;a href="http://python.org/"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I will use the same SDL skeleton, so we can concentrate only on the Python part.&lt;/p&gt;

&lt;h4&gt;Python skeleton&lt;/h4&gt;

&lt;p&gt;Embedding Python interpreter is a little more complicated than embedding Lua, so we will actually make it in three distinct steps.&lt;/p&gt;

&lt;h5&gt;1. Minimal Python&lt;/h5&gt;

&lt;pre class="cpp"&gt;
#include &amp;lt;Python.h&amp;gt;

int main(void)
{
        Py_Initialize();
        FILE *f = fopen("skeleton.py", "r");
        PyRun_SimpleFile(f, "skeleton.py");
        fclose(f);
        Py_Finalize();
}
&lt;/pre&gt;

&lt;blockquote&gt;g++ minimal.cpp -o python_minimal -lpython25&lt;/blockquote&gt;
&lt;p&gt;For compiling on Linux just replace &lt;code&gt;-lpython25&lt;/code&gt; with &lt;code&gt;-lpython2.5&lt;/code&gt;. The library is named differently&lt;/p&gt;

&lt;p&gt;Compile this program with &lt;a href="http://www.mingw.org"&gt;Mingw&lt;/a&gt; on Windows and you will experience a crash. Compiling with Microsoft compiler or compiling on Linux works correctly. What's going on? After some searching, I found the answer in &lt;a href="http://blender.org"&gt;Blender&lt;/a&gt; source, which pointed me to the main page of Python &lt;a href="http://docs.python.org/api/veryhigh.html"&gt;embedding documentation&lt;/a&gt;, where it explicitly says, that the file descriptors passed to &lt;code&gt;PyRun_*File&lt;/code&gt; function, have to be created by the same runtime libraries. Since I'm using Mingw, I had to avoid all the &lt;code&gt;PyRun_*File&lt;/code&gt; functions and pass the Python script to the interpreter as a string.&lt;/p&gt;

&lt;h5&gt;2. Minimal Python as a String&lt;/h5&gt;

&lt;pre class="cpp"&gt;
#include &amp;lt;Python.h&amp;gt;

int main(int argc, char*argv[])
{
 Py_Initialize();

 FILE *f = fopen("skeleton.py", "r");
 fseek(f, 0, SEEK_END);
 size_t length = ftell(f);
 fseek(f, 0, SEEK_SET);
 char *data = (char *)malloc(length + 1);
 fread(data, 1, length, f);
 data[length] = '\0';
 fclose(f);

 PyRun_SimpleString(data);
 Py_Finalize();

 return 0;
}
&lt;/pre&gt;

&lt;p&gt;All this code does is opening a file, reading the contents and passing it to Python interpreter, nothing really spectacular. You can place any Python code into &lt;code&gt;skeleton.py&lt;/code&gt; such as:&lt;/p&gt;

&lt;pre class="python"&gt;
print 'Hello from Python'
&lt;/pre&gt;

&lt;h5&gt;3. Calling C Functions from Python&lt;/h5&gt;

&lt;p&gt;To be able to call a C function from Python you have to do a little more than in case of Lua. You have to create a new module for a set of functions with &lt;code&gt;Py_InitModule&lt;/code&gt;. In subsequent Python code you have to &lt;code&gt;import&lt;/code&gt; from this module.&lt;/p&gt;

&lt;pre class="cpp"&gt;
#include &amp;lt;Python.h&amp;gt;

// our function, which we call from Python
PyObject * redraw(PyObject *self, PyObject *args)
{
 double theta;
 PyArg_ParseTuple(args, "d", &amp;theta);
 printf("%g\n", theta);

 return Py_BuildValue("");
}

// list of methods, which will put into module Foo
static PyMethodDef methods[] =
{
 { "redraw", redraw, METH_VARARGS, "updates the screen" },
 {NULL}
};

int main(int argc, char*argv[])
{
 Py_Initialize();

 FILE *f = fopen("mixed.py", "r");
 fseek(f, 0, SEEK_END);
 size_t length = ftell(f);
 fseek(f, 0, SEEK_SET);
 char *data = (char *)malloc(length+1);
 fread(data, 1, length, f);
 data[length] = '\0';
 fclose(f);

 // init our module
 PyObject *module = Py_InitModule("Foo", methods);
 PyRun_SimpleString(data);
 Py_Finalize();

 return 0;
}
&lt;/pre&gt;

&lt;p&gt;When run in conjunction with this little Python script, it will print out all the rotations of the triangle, which will we display in SDL version later.&lt;/p&gt;

&lt;pre class="python"&gt;
from Foo import *
i = 1
while (i &lt; 2000):
 redraw(i)
 i += 0.5
&lt;/pre&gt;

&lt;h4&gt;Skeletons mixed&lt;/h4&gt;

&lt;p&gt;And now we need just to merge in the SDL code together and we're done&lt;/p&gt;

&lt;pre class="cpp"&gt;
#include &amp;lt;Python.h&amp;gt;
#include &amp;lt;SDL/SDL.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;
#include &amp;lt;gl/gl.h&amp;gt;

PyObject * redraw(PyObject *self, PyObject *args)
{
 double theta;
 PyArg_ParseTuple(args, "d", &amp;theta);

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glLoadIdentity();
 glTranslatef(0.0f,0.0f,0.0f);
 glRotatef(theta, 0.0f, 0.0f, 1.0f);
 glBegin(GL_TRIANGLES);
 glColor3f(1.0f, 0.0f, 0.0f);
 glVertex2f(0.0f, 1.0f);
 glColor3f(0.0f, 1.0f, 0.0f);
 glVertex2f(0.87f, -0.5f);
 glColor3f(0.0f, 0.0f, 1.0f);
 glVertex2f(-0.87f, -0.5f);
 glEnd();

 SDL_GL_SwapBuffers();
 return Py_BuildValue("");
}

static PyMethodDef methods[] =
{
 { "redraw", redraw, METH_VARARGS, "updates the screen" },
 {NULL}
};

int main(int argc, char*argv[])
{
 atexit(SDL_Quit);
 if( SDL_Init(SDL_INIT_VIDEO) &amp;lt; 0 ) {
  fprintf(stderr,"Couldn't initialize SDL: %s\n", SDL_GetError());
  exit(1);
 }

 SDL_Surface *screen = SDL_SetVideoMode(400, 400, 32, SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_OPENGL);

 glViewport(0, 0, 400, 400);
 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 glClearDepth(1.0);
 glDepthFunc(GL_LESS);
 glEnable(GL_DEPTH_TEST);
 glShadeModel(GL_SMOOTH);
 glMatrixMode(GL_PROJECTION);
 glMatrixMode(GL_MODELVIEW);

 Py_Initialize();

 FILE *f = fopen("mixed.py", "r");
 fseek(f, 0, SEEK_END);
 size_t length = ftell(f);
 fseek(f, 0, SEEK_SET);
 char *data = (char *)malloc(length+1);
 fread(data, 1, length, f);
 data[length] = '\0';
 fclose(f);

 PyObject *module = Py_InitModule("Foo", methods);
 PyRun_SimpleString(data);
 Py_Finalize();

 return 0;
}
&lt;/pre&gt;

&lt;p&gt;The result, we're getting, is of course the same as last time&lt;/p&gt;

&lt;p&gt;&lt;img src="http://ondrew.googlepages.com/python_triangle.png" alt="Colorful triangle drawn by OpenGL called from Python" /&gt;&lt;/p&gt;

&lt;p&gt;In this case as well I couldn't find any statistically significant speed difference between native C and interpreted Python.&lt;/p&gt;

&lt;p&gt;All sources and binaries can be downloaded &lt;a href="http://ondrew.googlepages.com/pythonsdl.zip"&gt;here&lt;/a&gt; 4 MB&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Very interesting side note:&lt;/strong&gt; when implementing this example I found out an extremely awesome thing. New versions of &lt;a href="http://www.mingw.org"&gt;Mingw&lt;/a&gt; allow linking directly to DLLs. You don't need no &lt;code&gt;.a&lt;/code&gt;, &lt;code&gt;.la&lt;/code&gt; or &lt;code&gt;.lib&lt;/code&gt; files. You can just direct the compiler/linker to the directory with the DLL you're referencing and it will automagically resolve the symbols from within the DLL - &lt;strong&gt;simply AWESOME!!!&lt;/strong&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-1170401052864749410?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2008/09/integrating-sdl-with-python.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-8273293209900563466</guid><pubDate>Thu, 28 Aug 2008 06:00:00 +0000</pubDate><atom:updated>2008-08-29T10:40:30.680+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Lua</category><category domain="http://www.blogger.com/atom/ns#">SDL</category><category domain="http://www.blogger.com/atom/ns#">C++</category><title>Integrating SDL with Lua</title><description>&lt;p&gt;For my next little game project I decided to use SDL, OpenGL and preferably some sort of scripting language to handle the game logic. Not that I couldn't write the game logic in C/C++, but I wanted to try out, how this integration of scripting language into your application works.&lt;/p&gt;

&lt;p&gt;The language I decided to try first was &lt;a href="http://www.lua.org/"&gt;Lua&lt;/a&gt;. It has been used in many games, so it felt like a natural choice.&lt;/p&gt;

&lt;h4&gt;SDL skeleton&lt;/h4&gt;

&lt;p&gt;First we need some SDL/OpenGL skeleton, which will initialize SDL and OpenGL. Basically we need the simplest OpenGL application there is.&lt;/p&gt;

&lt;pre class="cpp"&gt;
#include &amp;lt;windows.h&amp;gt;
#include &amp;lt;SDL/SDL.h&amp;gt;
#include &amp;lt;gl/gl.h&amp;gt;

static int redraw(float theta)
{
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

 glLoadIdentity();
 glTranslatef(0.0f,0.0f,0.0f);
 glRotatef(theta, 0.0f, 0.0f, 1.0f);

 glBegin(GL_TRIANGLES);
 glColor3f(1.0f, 0.0f, 0.0f);
 glVertex2f(0.0f, 1.0f);
 glColor3f(0.0f, 1.0f, 0.0f);
 glVertex2f(0.87f, -0.5f);
 glColor3f(0.0f, 0.0f, 1.0f);
 glVertex2f(-0.87f, -0.5f);
 glEnd();

 SDL_GL_SwapBuffers();
}

int main(int argc, char*argv[])
{
 SDL_Init(SDL_INIT_VIDEO);
 SDL_Surface *screen = SDL_SetVideoMode(400, 400, 32, SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_OPENGL);

 glViewport(0, 0, 400, 400);
 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 glClearDepth(1.0);
 glDepthFunc(GL_LESS);
 glEnable(GL_DEPTH_TEST);
 glShadeModel(GL_SMOOTH);
 glMatrixMode(GL_PROJECTION);
 glMatrixMode(GL_MODELVIEW);

 for (float theta = 0; theta &amp;lt; 20000; theta += 0.5)
 {
  redraw(theta);
 }

 return 0;
}
&lt;/pre&gt;

&lt;p&gt;To compile, we have to use&lt;/p&gt;

&lt;blockquote&gt;&lt;code&gt;g++ -o sdl main.cpp -lmingw32 -lSDLmain -lSDL -lopengl32 -mwindows&lt;/code&gt;&lt;/blockquote&gt;

&lt;p&gt;For Linux just remove &lt;code&gt;-lmingw32&lt;/code&gt; and &lt;code&gt;-mwindows&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Please note, that the relative order of libraries and main.cpp is important. SDL overrides the default &lt;code&gt;main&lt;/code&gt; function, same as Win32 does, so switching the order will result in a linking error.&lt;/p&gt;

&lt;p&gt;After successful compilation, you should get an application looking like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://ondrew.googlepages.com/lua_sdl.zip"&gt;&lt;img src="http://ondrew.googlepages.com/lua_triangle.png" alt="OpenGL Triangle"/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code itself is quite ridiculous (especially the &lt;code&gt;for&lt;/code&gt; loop with floating point number), but the reason will become clear, when we insert the Lua language scripting.&lt;/p&gt;

&lt;h4&gt;Lua skeleton&lt;/h4&gt;

&lt;p&gt;Now we need a minimal example of Lua processing, so that we get a feeling for the Lua code. It's actually quite simple, you include the appropriate header files (in my case I'm using the C++ version of header files that comes with Lua, because, I'm planning to use C++ in my project). Afterwords you just initialize Lua and call the appropriate script file. It's pretty self explanatory:&lt;/p&gt;

&lt;pre class="cpp"&gt;
#include &amp;lt;lua/lua.hpp&amp;gt;

int main(int argc, char*argv[])
{
 lua_State *L=lua_open();
 luaL_openlibs(L);

 if (luaL_dofile(L, "skeleton.lua")!=0) fprintf(stderr,"%s\n",lua_tostring(L,-1));

 lua_close(L);

 return 0;
}
&lt;/pre&gt;

&lt;p&gt;We compile this with:&lt;/p&gt;

&lt;blockquote&gt;g++ -o lua_skeleton lua_skeleton.cpp -llua&lt;/blockquote&gt;

&lt;p&gt;Now we need to create a simple Lua script &lt;code&gt;skeleton.lua&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="cpp"&gt;
io.write("Hello from Lua\n")
&lt;/pre&gt;

&lt;p&gt;Upon running we should get a result looking like this&lt;/p&gt;
&lt;p&gt;&lt;img src="http://ondrew.googlepages.com/lua_skeleton.png" alt="Hello from Lua" /&gt;&lt;/p&gt;

&lt;h4&gt;Skeletons mixed&lt;/h4&gt;

&lt;p&gt;And now we need to mix these two programs together. I want to offload the rotation of triangle to Lua, that will allow me to test how to call functions from Lua and how to retrieve variables to Lua.&lt;/p&gt;

&lt;pre class="cpp"&gt;
#include &amp;lt;windows.h&amp;gt;
#include &amp;lt;SDL/SDL.h&amp;gt;
#include &amp;lt;gl/gl.h&amp;gt;
#include &amp;lt;lua/lua.hpp&amp;gt;

static int redraw(lua_State *L)
{
 float theta = lua_tonumber(L, 1);

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glLoadIdentity();
 glTranslatef(0.0f,0.0f,0.0f);
 glRotatef(theta, 0.0f, 0.0f, 1.0f);
 glBegin(GL_TRIANGLES);
 glColor3f(1.0f, 0.0f, 0.0f);
 glVertex2f(0.0f, 1.0f);
 glColor3f(0.0f, 1.0f, 0.0f);
 glVertex2f(0.87f, -0.5f);
 glColor3f(0.0f, 0.0f, 1.0f);
 glVertex2f(-0.87f, -0.5f);
 glEnd();

 SDL_GL_SwapBuffers();
}

int main(int argc, char*argv[])
{
 lua_State *L=lua_open();
 luaL_openlibs(L);

 lua_register(L, "redraw", redraw);

 atexit(SDL_Quit);
 if( SDL_Init(SDL_INIT_VIDEO) &amp;lt; 0 ) {
  fprintf(stderr,"Couldn't initialize SDL: %s\n", SDL_GetError());
  exit(1);
 }

 SDL_Surface *screen = SDL_SetVideoMode(400, 400, 32, SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_OPENGL);

 glViewport(0, 0, 400, 400);
 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 glClearDepth(1.0);
 glDepthFunc(GL_LESS);
 glEnable(GL_DEPTH_TEST);
 glShadeModel(GL_SMOOTH);
 glMatrixMode(GL_PROJECTION);
 glMatrixMode(GL_MODELVIEW);

 if (luaL_dofile(L, "mixed.lua")!=0) fprintf(stderr,"%s\n",lua_tostring(L,-1));
 lua_close(L);

 return 0;
}
&lt;/pre&gt;

&lt;p&gt;The Lua script looks as follows. I chose the increment step 0.5, so that I can see possible speed difference between Lua's processing of floating point and C.&lt;/p&gt;

&lt;pre class="cpp"&gt;
for i = 1.00, 20000, 0.5 do
 redraw(i)
end 
&lt;/pre&gt;

&lt;p&gt;To my tremendous surprise the Lua code performs as fast as the C code. I did a couple of measurements on different computers and I couldn't find a statistically significant difference (Lua was hitting 96 % - 101 % framerate of pure C version). Without performance issues in the way, it looks like I might be using Lua as a scripting language in my project.&lt;/p&gt;

&lt;p&gt;To download all the source code and binaries, click here &lt;a href="http://ondrew.googlepages.com/luasdl.zip"&gt;luasdl.zip&lt;/a&gt; 440 kB&lt;/p&gt;

&lt;p&gt;Next time, we will look at the performance and integration with Python.&lt;/p&gt;

&lt;p&gt;Code highlighted with &lt;a href="http://code.google.com/p/syntaxhighlighter/"&gt;syntaxhighlighter&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-8273293209900563466?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2008/08/integrating-sdl-with-lua.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-1119305457050403020</guid><pubDate>Wed, 27 Aug 2008 06:00:00 +0000</pubDate><atom:updated>2008-08-29T10:44:25.355+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">linux</category><category domain="http://www.blogger.com/atom/ns#">dig that code</category><category domain="http://www.blogger.com/atom/ns#">unix</category><title>Switch User With a Fork</title><description>&lt;p&gt;I like open source. Mainly because of the fact, that when I'm curious why or how something works, I can just go and check. Although my previous posts were mainly Win32 related, I'm actually a hard core Linux geek stuck in corporate windows environment :). So I decided to start a section &lt;strong&gt;&amp;quot;Dig that code&amp;quot;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I have many friends, who like Linux as much as I do, who write scripts and programs all the time, but who would never download and check someone else's code to find out, what's going on and why something does / doesn't work. (I'm obviously talking about people who already can program, not about users). I think there is some sort of barrier people feel when touching code for the first time, so I'm going to document my steps.&lt;/p&gt;

&lt;p&gt;Today's example will be quite basic and simple. The question is, you're logged into a computer, where the &lt;a href="http://en.wikipedia.org/wiki/Fork_bomb"&gt;fork bomb&lt;/a&gt; is currently running. You need to become root to start killing everything. However you can't start any additional programs because the resource limit is already reached.&lt;/p&gt;

&lt;p&gt;I thought the answer is &lt;code&gt;exec su&lt;/code&gt;, until I actually tried it out.&lt;/p&gt;

&lt;h4&gt;Theory&lt;/h4&gt;

&lt;p&gt;System call &lt;a href="http://linux.die.net/man/2/execve"&gt;execve&lt;/a&gt; replaces the currently running process with the process from the specified filename. So what should happen upon calling &lt;code&gt;exec su&lt;/code&gt; is&lt;/p&gt;

&lt;p&gt;
 &lt;ol&gt;
  &lt;li&gt;shell is replaced by su&lt;/li&gt;
  &lt;li&gt;su asks for root credentials&lt;/li&gt;
  &lt;li&gt;upon successful confirmation, su calles execve and is replaced by a new shell&lt;/li&gt;
 &lt;/ol&gt;
&lt;/p&gt;

&lt;h4&gt;Practice&lt;/h4&gt;

&lt;p&gt;Easy way how to test this is&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;pre&gt;
$ echo $$
FIRST_PID
$ exec su
# echo $$
SECOND_PID
&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If the number FIRST_PID equals to SECOND_PID, then you would be able to avoid the fork bomb, however when trying it out, I got different numbers on couple of modern distributions I tried - Gentoo 2008.0 stable, Fedora 8 and Red Hat Enterprise Linux 5.2. I tried on couple of Unixes as well and guess what? The pid number stayed the same. I decided to investigate - dig that code.&lt;/p&gt;

&lt;p&gt;The first thing I did, was that I downloaded &lt;a href="http://ftp.gnu.org/gnu/coreutils/"&gt;coreutils&lt;/a&gt; and went for the su.c. However to my surprise the relevant lines were looking like this:&lt;/p&gt;

&lt;p&gt;&lt;pre class="cpp"&gt;
static void
run_shell (char const *shell, char const *command, char **additional_args,
    size_t n_additional_args)
{
  size_t n_args = 1 + fast_startup + 2 * !!command + n_additional_args + 1;
  char const **args = xnmalloc (n_args, sizeof *args);
  size_t argno = 1;

  if (simulate_login)
    {
      char *arg0;
      char *shell_basename;

      shell_basename = last_component (shell);
      arg0 = xmalloc (strlen (shell_basename) + 2);
      arg0[0] = '-';
      strcpy (arg0 + 1, shell_basename);
      args[0] = arg0;
    }
  else
    args[0] = last_component (shell);
  if (fast_startup)
    args[argno++] = "-f";
  if (command)
    {
      args[argno++] = "-c";
      args[argno++] = command;
    }
  memcpy (args + argno, additional_args, n_additional_args * sizeof *args);
  args[argno + n_additional_args] = NULL;
  execv (shell, (char **) args); // &amp;lt;- notice this

  {
    int exit_status = (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
    error (0, errno, "%s", shell);
    exit (exit_status);
  }
}
&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;Obviously, there's happening something fishy, because &lt;code&gt;su&lt;/code&gt; is calling &lt;strong&gt;execv&lt;/strong&gt;. There is simply no possibility for the final shell to have a different pid. So I used equery and rpm to find out, where the &lt;code&gt;/bin/su&lt;/code&gt; command comes from. And to my surprise it doesn't come from coreutils, but from the shadow package.&lt;/p&gt;

&lt;p&gt;After downloading the &lt;a href="http://packages.debian.org/source/stable/shadow"&gt;shadow package&lt;/a&gt;, unpacking and checking su.c, I found&lt;/p&gt;

&lt;p&gt;&lt;pre class="cpp"&gt;
/* This I ripped out of su.c from sh-utils after the Mandrake pam patch
 * have been applied.  Some work was needed to get it integrated into
 * su.c from shadow.
 */
static void run_shell (const char *shellstr, char *args[], int doshell,
         char *const envp[])
{
 int child;
 sigset_t ourset;
 int status;
 int ret;

 child = fork (); // &amp;lt;- notice this
 if (child == 0) { /* child shell */
  pam_end (pamh, PAM_SUCCESS);

  if (doshell)
   (void) shell (shellstr, (char *) args[0], envp);
  else
   (void) execve (shellstr, (char **) args, envp);
  exit (errno == ENOENT ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
 } else if (child == -1) {
  (void) fprintf (stderr, "%s: Cannot fork user shell\n", Prog);
  SYSLOG ((LOG_WARN, "Cannot execute %s", shellstr));
  closelog ();
  exit (1);
 }

 ....

}
&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;So there you have it, the forking happens in shadow's version of &lt;code&gt;su&lt;/code&gt;, which is today quite a standard among distributions, because of the PAM integration. So next time you find yourself on a system with a fork bomb, you know who to thank to :).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-1119305457050403020?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2008/08/switch-user-with-fork.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-151596480975641879</guid><pubDate>Tue, 05 Aug 2008 06:00:00 +0000</pubDate><atom:updated>2009-02-28T01:11:11.835+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">database</category><category domain="http://www.blogger.com/atom/ns#">oracle</category><title>Simple Oracle Client</title><description>&lt;p&gt;After a longer pause because of vacation and general busyness/laziness I present you a standalone simple command line Oracle client.&lt;/p&gt;

&lt;p&gt;It's not standalone as in independent on Oracle code (it comes with 106 megabytes of Oracle dll's), but it doesn't need any installation, doesn't modify registry and it doesn't need any privileges, just unpack it and run. Yeah I know, you're thinking &lt;em&gt;&amp;quot;&lt;strong&gt;106&lt;/strong&gt; megabytes for dll that connects to database it's enormous&amp;quot;&lt;/em&gt;. Truth to be told, I have no idea, what is Oracle doing in so much code.&lt;/p&gt;

&lt;p&gt;The client itself, it's written in C# and it's pretty basic. Reads SQL statements from standard input, executes them in DB, sends output to standard output and errors to standard error. Nothing really spectacular.&lt;/p&gt;

&lt;pre class="csharp"&gt;
      using System;
      using System.IO;
      using System.Text.RegularExpressions;
      using System.Collections.Generic;
      
      using Oracle.DataAccess.Client;
       
      class SimpleOracleClient
      {
              OracleConnection con;
              OracleCommand cmd;
              TextWriter output;
              TextWriter error;
       
              bool headers = true;
              string separator = ";\t";
       
              SimpleOracleClient(string connectionString)
              {
                      output = Console.Out;
                      error = Console.Error;
       
                      con = new OracleConnection(connectionString);
                      con.Open();
       
                      Console.Error.WriteLine("Connected to Oracle " + con.ServerVersion);
              }
       
              ~SimpleOracleClient()
              {
                      if (output != Console.Out)
                              output.Close();
                      if (error != Console.Error)
                              error.Close();
       
                      con.Close();
                      con.Dispose();
              }
       
              void Execute(string command)
              {
                      cmd = new OracleCommand(command, con);
       
                      OracleDataReader myReader;
       
                      try {
                              myReader = cmd.ExecuteReader();
       
       
                              if (headers)
                              {
                                      for (int i = 0; i &amp;lt; myReader.FieldCount; i++)
                                      {
                                              error.Write(myReader.GetName(i) + separator);
                                      }
             
                                      error.WriteLine();
                                      error.WriteLine();
                              }
       
                              while(myReader.Read())
                              {
                                      for (int i = 0; i &amp;lt; myReader.FieldCount; i++)
                                      {
                                              output.Write(myReader.GetValue(i).ToString() + separator);
                                      }
                                      output.WriteLine();
       
                              }
       
                              if (headers)
                              {
                                      for (int i = 0; i &amp;lt; myReader.FieldCount; i++)
                                      {
                                              error.Write(myReader.GetName(i) + separator);
                                      }
                                      error.WriteLine();
                              }
       
                              output.Flush();
                              error.Flush();
       
                              myReader.Close();
       
                      }
                      catch (OracleException e)
                      {
                              Console.Error.WriteLine(e.Message);
                      }
              }
       
              static string getConnectionString(string[] args)
              {
                      Dictionary&amp;lt;string, string&amp;gt; options = new Dictionary&amp;lt;string, string&amp;gt;();
       
                      options.Add("host", "localhost");
                      options.Add("port", "1521");
                      options.Add("service", "ora");
                      options.Add("user", "Administrator");
                      options.Add("password", "Administrator");
       
                      string connectionString;
       
                      if (args.Length == 0)
                      {
                              connectionString = Console.ReadLine();
                      }
                      else if (args.Length == 1)
                      {
                              connectionString = args[0];
                      }
                      else
                      {
                              for (int i = 0; i &amp;lt; args.Length; i++)
                              {
                                      string name = args[i].Substring(1).ToLower();
                                      if (options.ContainsKey(name))
                                      {
                                              options[name] = args[i+1];
                                      }
                              }
       
                              connectionString = "Data Source=(DESCRIPTION="
                                              + "(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)"
                                              + "(HOST=" + options["host"] + ")"  
                                              + "(PORT=" + options["port"] + ")))"
                                              + "(CONNECT_DATA=(SERVER=DEDICATED)"
                                              + "(SERVICE_NAME=" + options["service"] + ")));"
                                              + "User Id=" + options["user"] + ";"
                                              + "Password=" + options["password"] + ";";
                      }
       
                      return connectionString;
              }
       
              static int Main(string[] args)
              {
                      Console.Error.WriteLine("Simple Oracle Client 0.1");
                      SimpleOracleClient s = new SimpleOracleClient(getConnectionString(args));
       
                      Dictionary&amp;lt;string, string&amp;gt; helper = new Dictionary&amp;lt;string, string&amp;gt;();
                      helper.Add(".tables", "SELECT table_name FROM all_tables");
                      helper.Add(".databases", "SELECT * FROM user_tablespaces");
       
                      string line = "";
       
                      while ((line += Console.ReadLine()) != null)
                      {
                              if (line.Length == 0)
                                      continue;
       
                              string[] command = Regex.Split(line.Trim().ToLower(), " +");
       
                              if (command[0] == ".quit" || command[0] == ".exit")
                                      break;
       
                              bool processed = true;
       
                              switch (command[0])
                              {
                                      case ".headers":
                                      case ".header":
                                              if (command.Length &amp;gt; 1 &amp;&amp; Regex.Match(command[1], "(on)|1|(true)").Success)
                                              {
                                                      s.headers = true;
                                              }
                                              else if (command.Length &amp;gt; 1 &amp;&amp; Regex.Match(command[1], "(off)|0|(false)").Success)
                                              {
                                                      s.headers = false;
                                              }
                                              else
                                              {
                                                      Console.Error.WriteLine("Headers " + (s.headers ? "on" : "off"));
                                              }
                                              break;
       
                                      case ".output":
                                              if (command[1] == "stdout")
                                              {
                                                      if (s.output != Console.Out)
                                                      {
                                                              s.output.Close();
                                                              s.output = Console.Out;
                                                              s.error = Console.Error;
                                                      }
                                              }
                                              else
                                              {
                                                      if (s.output != Console.Out)
                                                      {
                                                              s.output.Close();
                                                      }
                                                      s.output = new StreamWriter(command[1]);
                                                      s.error = s.output;
                                              }
                                              break;
       
                                      case ".separator":
                                              if (command.Length &amp;gt; 1)
                                              {
                                                      s.separator = command[1];
                                              }
                                              else
                                              {
                                                      Console.Error.WriteLine("Separator is '{0}'", s.separator);
                                              }
                                              break;
       
                                      case ".help":
                                              Console.Error.WriteLine("Simple Oracle Client 0.1");
                                              Console.Error.WriteLine("For updates, please see http://www.gettingclever.com");
                                              Console.Error.WriteLine("");
                                              Console.Error.WriteLine(".exit - exits the program");
                                              Console.Error.WriteLine(".headers [on|off] - turn headers on");
                                              Console.Error.WriteLine(".output FILENAME - sends output to FILENAME");
                                              Console.Error.WriteLine(".output stdout - sends output to stdout");
                                              Console.Error.WriteLine(".quit - quits the program");
                                              Console.Error.WriteLine(".separator STRING - uses STRING as column separator");
                                              Console.Error.WriteLine("");
                                              break;
       
                                      default:
                                              processed = false;
                                              break;
                              }
       
                              if (!processed)
                              {
                                      if (line[line.Length-1] == '\\')
                                      {
                                              line = line.Substring(0, line.Length-1);
                                              continue;
                                      }
                                      else
                                      {
                                              if (helper.ContainsKey(line))
                                              {
                                                      s.Execute(helper[line]);
                                              }
                                              else
                                              {
                                                      s.Execute(line);
                                              }
                                      }
                              }
                              line = "";
                      }
       
                      return 0;
              }
      } 
&lt;/pre&gt;
 
&lt;p&gt;&lt;h3&gt;Connecting to the database&lt;/h3&gt;
There are three different ways to establish a connection to the DB.
 &lt;ol&gt;
  &lt;li&gt;
   &lt;strong&gt;Specify the connection string on the command line&lt;/strong&gt;
   &lt;img src="http://ondrew.googlepages.com/oracle.0.1-connectionString.png" alt="oracle.exe &amp;quot;"Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=example.com)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=example)));User Id=test;Password=secret;"&amp;quot;" /&gt;
  Notice the double quotes surrounding the whole connection string, they are needed, so that the whole connection string is considered as a whole.
  &lt;/li&gt;
  
  &lt;li&gt;&lt;strong&gt;Specify connection details on the command line&lt;/strong&gt;
   &lt;img src="http://ondrew.googlepages.com/oracle.0.1-connectionParams.png" alt="oracle.exe -host example.com -port 1521 -service example -user test -password secret" /&gt;
  &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;Type in the connection string as first line from standard input&lt;/strong&gt; - this option is probably the most useful for scripting and at the same time most secure, since it doesn't display the password in process list.
   &lt;img src="http://ondrew.googlepages.com/oracle.0.1-connectionStdin.png" alt="Send the connection string as first line in standard input" /&gt;
  &lt;/li&gt;
 &lt;/ol&gt;
&lt;/p&gt;

&lt;p&gt;&lt;h3&gt;Working with the database&lt;/h3&gt;
When connected to the database, the work is pretty straightforward, you issue SQL commands and the results get displayed. Inspired by &lt;a href="http://sqlite.org"&gt;sqlite&lt;/a&gt; I implemented couple of useful &lt;em&gt;dot-commands&lt;/em&gt;. 

&lt;table&gt;
&lt;tr&gt;&lt;td&gt;.databases&lt;/td&gt;&lt;td&gt;Lists available databases&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;.exit&lt;/td&gt;&lt;td&gt;Exits the application&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;.headers [on|off]&lt;/td&gt;&lt;td&gt;Switches displaying of column headers on and off&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;.help&lt;/td&gt;&lt;td&gt;Displays help screen&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;.output FILENAME&lt;/td&gt;&lt;td&gt;Sends all output to FILENAME&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;.output stdout&lt;/td&gt;&lt;td&gt;Sends all output to standard output&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;.quit&lt;/td&gt;&lt;td&gt;Quits the application&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;.separator [NEW_SEPARATOR_STRING]&lt;/td&gt;&lt;td&gt;Sets new separator string&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;.tables&lt;/td&gt;&lt;td&gt;Lists available tables&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/p&gt;

&lt;p&gt;&lt;h3&gt;Things to keep in mind&lt;/h3&gt;
This is just a very basic client. There is no support for multiple SQL statements.&lt;/p&gt;

&lt;p&gt;Following statement will fail&lt;/p&gt;
&lt;blockquote&gt;
 SELECT * FROM table1; SELECT * FROM table2;
&lt;/blockquote&gt;
Because it's up to the client application to separate individual SQL statements.
&lt;/p&gt;

&lt;p&gt;Not only that, but even this statement will fail because of the trailing semicolon.
&lt;blockquote&gt;
 SELECT * FROM table1;
&lt;/blockquote&gt;
&lt;/p&gt;

&lt;p&gt;This is a work in progress, there are quirks, which I'm aware of and bugs, which I'm not. I'll keep on updating this client, but keep in mind, that it was written in one afternoon, while travelling back from work. &lt;strong&gt;Use at your own risk&lt;/strong&gt;. I use it on production databases, which doesn't mean you should.&lt;/p&gt;

&lt;p&gt;Link to the code and binaries &lt;a href="http://www.mediafire.com/?ti1lrrrrmyl"&gt;oracle.0.1.7z&lt;/a&gt; - 20 MB, hosted on &lt;a href="http://www.mediafire.com"&gt;MediaFire&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's &lt;a href="http://www.7-zip.org/"&gt;7zipped&lt;/a&gt; for minimal download size. Standard zip yielded results somewhere about 37 megabytes.&lt;/p&gt;

&lt;p&gt;&lt;h3&gt;Planned enhancements&lt;/h3&gt;
&lt;ul&gt;
 &lt;li&gt;Interactive password query&lt;/li&gt;
 &lt;li&gt;SQL parsing - possibility to enter multiple SQL statements, comments etc&lt;/li&gt;
 &lt;li&gt;Plain file import&lt;/li&gt;
 &lt;li&gt;History of commands&lt;/li&gt;
&lt;/ul&gt;
If you have any feature requests, please post them in comments or write and email (everything send to this domain comes to me).
&lt;/p&gt;

&lt;p&gt;Tested with Oracle 10.2.0.3 and 11.1.0.6&lt;/p&gt;

&lt;p&gt;Please note, that the oracle client library creates &lt;code&gt;%USERPROFILE%\Oracle&lt;/code&gt; folder, which is safe to delete.&lt;/p&gt;

&lt;p&gt;Obligatory thanks to Mark James for creating the amazing &lt;a href="http://www.famfamfam.com/lab/icons/silk/"&gt;Silk icons&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Update [15th September 2008]: Fixed the download link, I apologize for not using a direct link. I must buy some hosting.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-151596480975641879?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2008/08/simple-oracle-client.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-2893785336106028504</guid><pubDate>Wed, 09 Jul 2008 06:00:00 +0000</pubDate><atom:updated>2008-08-27T16:37:36.926+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">raytracer</category><category domain="http://www.blogger.com/atom/ns#">C++</category><title>Raytracing Chaos</title><description>&lt;p&gt;I've spent about five hours on my raytracer and I must say, it's been a blast. It's the most fun you can have while programming. Seriously, if you're not writing a raytracer at this very moment, please stop whatever you're doing and start writing one right now.&lt;/p&gt;

&lt;p&gt;So far I've been writing doing most of the invisible stuff, like world and camera setup, ray collision detection and so on, but I have already some pictures. I did some kind of mistake and I couldn't figure what. The pictures should have a couple spheres on them, but it looks more like stripes and chaos. However if I wanted, I wouldn't be probably able to create such nice pictures :)&lt;/p&gt;

&lt;p&gt;&lt;img src="http://ondrew.googlepages.com/ray01_cross.png" alt="cross"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://ondrew.googlepages.com/ray01_face.png" alt="face"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://ondrew.googlepages.com/ray01_lines.png" alt="lines"/&gt;&lt;/p&gt;

&lt;p&gt;Finally I found out where the bug was, I forgot to normalize the vector giving the direction of the casted ray. Since I was counting with the length of the vector being one in the ray collision detection code, the results have been quite strange. After fixing the results finally looks like spheres. There is no occlusion code yet, but I have naive lighting finished.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://ondrew.googlepages.com/ray01_spheres.png" alt="lines"/&gt;&lt;/p&gt;

&lt;p&gt;The next step is to write exporter for Blender, write a parser and render some my of my models.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-2893785336106028504?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2008/07/raytracing-chaos.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-1530445728738865477</guid><pubDate>Thu, 03 Jul 2008 06:00:00 +0000</pubDate><atom:updated>2008-07-03T14:00:14.609+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">raytracer</category><category domain="http://www.blogger.com/atom/ns#">C++</category><title>Raytracer Rules</title><description>&lt;p&gt;Thinking about the Raytracer, I am about to &lt;a href="/2008/06/tetris-raytracer-compiler.html"&gt;write&lt;/a&gt;. I figured that there must be some CS school assignments already setting rules for this subject. Google search revealed some of them:
 &lt;ul&gt;
  &lt;li&gt;&lt;a href="http://www.cs.cmu.edu/afs/cs.cmu.edu/user/jkh/www/462_s07/assts/assignment3/"&gt;http://www.cs.cmu.edu/afs/cs.cmu.edu/user/jkh/www/462_s07/assts/assignment3/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.mikejutan.com/raytracer/"&gt;http://www.mikejutan.com/raytracer/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.cs.cmu.edu/~fp//courses/graphics/asst7/"&gt;http://www.cs.cmu.edu/~fp//courses/graphics/asst7/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.graphics.cornell.edu/online/box/data.html"&gt;http://www.graphics.cornell.edu/online/box/data.html&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.cs.princeton.edu/courses/archive/fall96/cs426/Assignments/Project5.html"&gt;http://www.cs.princeton.edu/courses/archive/fall96/cs426/Assignments/Project5.html&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.cs.virginia.edu/~gfx/Courses/2004/Intro.Fall.04/assignments/raytracer.html"&gt;http://www.cs.virginia.edu/~gfx/Courses/2004/Intro.Fall.04/assignments/raytracer.html&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.jasonwaltman.com/graphics/raytracing.html"&gt;http://www.jasonwaltman.com/graphics/raytracing.html&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.cc.gatech.edu/classes/AY2003/cs4451a_fall/a5.html"&gt;http://www.cc.gatech.edu/classes/AY2003/cs4451a_fall/a5.html&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.gg.caltech.edu/~cs174ta/Winter/Homework/Homework2/homework2.html"&gt;http://www.gg.caltech.edu/~cs174ta/Winter/Homework/Homework2/homework2.html&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.cs.lth.se/EDA101/assignments/assignment1/"&gt;http://www.cs.lth.se/EDA101/assignments/assignment1/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.cs.unc.edu/~salomon/COMP236/hw4/"&gt;http://www.cs.unc.edu/~salomon/COMP236/hw4/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.cs.jhu.edu/~cohen/RenderingTechniques/assignment1.html"&gt;http://www.cs.jhu.edu/~cohen/RenderingTechniques/assignment1.html&lt;/a&gt;&lt;/li&gt;
 &lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;I like the first assignment the most, so these are the rules, I'm setting for myself
 &lt;ol&gt;
  &lt;li&gt;Functional requirements
   &lt;ol&gt;
    &lt;li&gt;Reflective spheres&lt;/li&gt;
    &lt;li&gt;Rectangles (preferably checkered planes as well :) )&lt;/li&gt;
    &lt;li&gt;Scene parser&lt;/li&gt;
    &lt;li&gt;Blender exporter of geometry and scene settings&lt;/li&gt;
    &lt;li&gt;Output in some braindead file format, probably just RGBRGB or PPM&lt;/li&gt;
    &lt;li&gt;Spatial partitioning&lt;/li&gt;
    &lt;li&gt;Bonus - Cornell Box&lt;/li&gt;
   &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Time and size contraints
   &lt;ol&gt;
    &lt;li&gt;Deadline 15th August&lt;/li&gt;
    &lt;li&gt;Three reflective spheres on checkered background in 1024x768 have to be rendered in less than 30s&lt;/li&gt;
   &lt;/ol&gt;
  &lt;/li&gt;
 &lt;/ol&gt;
&lt;/p&gt;

&lt;p&gt;The speed constrain is pretty vague, but since I don't have anything to benchmark it against, let's stick with this.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-1530445728738865477?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2008/07/raytracer-rules.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-578742005188699189</guid><pubDate>Wed, 02 Jul 2008 06:00:00 +0000</pubDate><atom:updated>2008-08-29T11:00:08.528+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">java</category><category domain="http://www.blogger.com/atom/ns#">python</category><category domain="http://www.blogger.com/atom/ns#">C#</category><title>Return From Finally</title><description>&lt;p&gt;Just today I was helping with some bug in Java and came across interesting problem - what happens if you use &lt;code&gt;return&lt;/code&gt; within try/catch statement? Should the &lt;code&gt;finally&lt;/code&gt; section fire up or not? I simplified the problem to following code snippet:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does the following code print out?&lt;/strong&gt;&lt;/p&gt;

&lt;pre class="java"&gt;
class ReturnFromFinally {
 public static int a() {
  try {
   return 1;
  }
  catch (Exception e) {}
  finally{
   return 2;
  }
 }

        public static void main(String[] args) {
  System.out.println(a());
        }
}
&lt;/pre&gt;

&lt;p&gt;My initial guess would be, that it should print out "&lt;code&gt;1&lt;/code&gt;", I'm calling return, so I assume, one will be returned. However, it is not the case:&lt;/p&gt;

&lt;p&gt;&lt;img alt="The second return is executed" src="http://ondrew.googlepages.com/ReturnFromFinally_java.png"/&gt;&lt;/p&gt;

&lt;p&gt;I understand the logic, &lt;code&gt;finally&lt;/code&gt; section has to be executed, but somehow I feel uneasy about this. Let's see what C# does in this case:&lt;/p&gt;

&lt;pre class="csharp"&gt;
class ReturnFromFinally
{
 public static int a()
 {
  try {
          return 1;
  }
  catch (System.Exception e) {}
  finally 
  { 
   return 2;
  }
 }

 public static void Main(string[] args)
 {
  System.Console.WriteLine(a());
 }
}
&lt;/pre&gt;

&lt;p&gt;&lt;img alt="error CS0157: Control cannot leave the body of a finally clause" src="http://ondrew.googlepages.com/ReturnFromFinally_dotnet.png"/&gt;&lt;/p&gt;

&lt;p&gt;I prefer much rather this behavior, control flow cannot be messed with in &lt;code&gt;finally&lt;/code&gt; clause, so it prevents us from shooting ourself in the foot. Just for the sake of completeness, let's check what other languages do.&lt;/p&gt;

&lt;p&gt;Python:&lt;/p&gt;
&lt;pre class="python"&gt;
def a():
 try:
  return 1
 finally:
  return 2

print a()
&lt;/pre&gt;

&lt;p&gt;&lt;img alt="Python returns 2 as well" src="http://ondrew.googlepages.com/ReturnFromFinally_python.png"/&gt;&lt;/p&gt;

&lt;p&gt;JavaScript:&lt;/p&gt;
&lt;pre class="javascript"&gt;
&amp;lt;script&amp;gt;
function ReturnFromFinally()
{
 try
 {
  return 1;
 }
 catch (e)
 {
 }
 finally
 {
  return 2;
 }
}
&amp;lt;/script&amp;gt;
&amp;lt;a onclick="alert(ReturnFromFinally());"&amp;gt;Click here&amp;lt;/a&amp;gt;
&lt;/pre&gt;

&lt;script&gt;
function ReturnFromFinally()
{
 try
 {
  return 1;
 }
 catch (e)
 {
 }
 finally
 {
  return 2;
 }
}
&lt;/script&gt;

&lt;p&gt;&lt;img onclick="alert(ReturnFromFinally());" alt="JavaScript returns 2 as well" src="http://ondrew.googlepages.com/ReturnFromFinally_javascript.png"/&gt;&lt;/p&gt;

&lt;p&gt;There is no &lt;code&gt;finally&lt;/code&gt; clause in C++ and PHP, so I can't try out the last two languages I have compiler/interpreter for.&lt;/p&gt;

&lt;p&gt;Our little experiment nicely showed, that C# has the nicest approach to this problem, but I was quite surprised to learn, that all the other languages handle the problem the same way.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-578742005188699189?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2008/07/return-from-finally.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-7661826811359002015</guid><pubDate>Tue, 01 Jul 2008 06:00:00 +0000</pubDate><atom:updated>2008-08-27T16:36:55.061+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">win32</category><category domain="http://www.blogger.com/atom/ns#">tetris</category><title>Tetris Stage One Finished</title><description>&lt;p&gt;So, yesterday was the deadline for my &lt;a href="/2008/06/tetris-raytracer-compiler.html"&gt;Tetris&lt;/a&gt; project. How did I do?&lt;/p&gt;

&lt;p&gt;I finished a basic Tetris game. The blocks fall, the finished rows disappear. You can rotate the blocks and that's it. It doesn't have any kind of score, levels or anything else. It redraws ugly, because it doesn't use dirty rectangles, but that shouldn't be that hard to add.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://ondrew.googlepages.com/tetris.02.png"/&gt;&lt;/p&gt;

&lt;p&gt;I consider this project finished for the time being, although the code is quite ugly. I will now try to go for the raytracer, because I can't wait to try writing one :).&lt;/p&gt;

&lt;p&gt;However before going for the compiler, I will schedule it as next little project of mine. Clean up the Tetris game, add local &amp; network multiplayer support and include pretty graphics.&lt;/p&gt;

&lt;p&gt;Should someone very inconsiderate be interested in playing this, &lt;a href="http://ondrew.googlepages.com/tetris.02.zip"&gt;here&lt;/a&gt; you go. (10kB)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-7661826811359002015?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2008/07/tetris-stage-one-finished.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-1939627961721823160</guid><pubDate>Fri, 27 Jun 2008 06:00:00 +0000</pubDate><atom:updated>2008-08-29T11:01:39.612+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">win32</category><category domain="http://www.blogger.com/atom/ns#">living without admin</category><title>Prevent Your Desktop From Locking</title><description>&lt;p&gt;In corporate environments you usually cannot change your screensaver timeout/desktop locking timeout. In case you have some application, that should be running with the screen off (like media player, Flash presentation etc.) you might ask how to prevent the screen from locking.&lt;/p&gt;

&lt;p&gt;And here's a program that does it for you: MouseMoving program. It actually doesn't move the mouse, it sends a message to the input queue, that the mouse is in the same position, thus non disrupting your mouse movements while working.&lt;/p&gt;

&lt;pre class="cpp"&gt;
#define WIN32_LEAN_AND_MEAN
#define WINWER 0x0610
#define _WIN32_WINNT 0x0610
#include &amp;lt;windows.h&amp;gt;

int main(void)
{
 INPUT i;
 while (1)
 {
  i.type = INPUT_MOUSE;
  i.mi.dx = 0;
  i.mi.dy = 0;
  i.mi.mouseData = 0;
  i.mi.dwFlags = (MOUSEEVENTF_MOVE || MOUSEEVENTF_ABSOLUTE);
  i.mi.time = 0;
  i.mi.dwExtraInfo = GetMessageExtraInfo();
  SendInput(1, &amp;i, sizeof(i));
  Sleep(1000);
 }
 return 0;
}
&lt;/pre&gt;

&lt;p&gt;For convenience binary version follows &lt;a href="http://ondrew.googlepages.com/mousemove.zip"&gt;mousemove.zip&lt;/a&gt; (6.5 kB)&lt;/p&gt;

&lt;p&gt;I found this utility really useful when I had to connect to a remote computer via VNC. I started the &lt;a href="http://www.tightvnc.org"&gt;TightVNC&lt;/a&gt; server on the computer, but I had to come back to the computer in couple of hours. When VNC is not running as a service (and here it wasn't, I had no admin rights to that computer), you can't unlock the computer. So I started the mousemoving utility, which prevented the computer from locking and could connect happily in couple of hours back.&lt;/p&gt;

&lt;p&gt;It's of course a completely wrong answer to completely wrong question. The program, that should be running undisrupted should be handling the WM_SYSCOMMAND notification and react to SC_MONITORPOWER/SC_SCREENSAVE messages. However according to MSDN article on &lt;a href="http://msdn.microsoft.com/en-us/library/ms646360(VS.85).aspx"&gt;WM_SYSCOMMAND&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;blockquote&gt;&lt;strong&gt;Microsoft Windows Vista and later:&lt;/strong&gt; If password protection is enabled by policy, the screen saver is started regardless of what an application does with the SC_SCREENSAVE notification—even if fails to pass it to DefWindowProc.&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;Currently I have no Vista machine to try it out, so the mousemoving application seemed like a better idea, however the article on &lt;a href="http://msdn.microsoft.com/en-us/library/ms646310(VS.85).aspx"&gt;SendInput&lt;/a&gt; says:&lt;/p&gt;

&lt;p&gt;&lt;blockquote&gt;&lt;strong&gt;Microsoft Windows Vista.&lt;/strong&gt; This function is subject to UIPI. Applications are permitted to inject input only into applications that are at an equal or lesser integrity level.&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;So maybe not even the MouseMove program will work in Windows Vista, I can't really tell without trying it out. You Vista users out there, please send a comment.&lt;/p&gt;

&lt;p&gt;Obligatory thanks to Mark James for creating the amazing &lt;a href="http://www.famfamfam.com/lab/icons/silk/"&gt;Silk icons&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-1939627961721823160?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2008/06/prevent-your-desktop-from-locking.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-9220716611417123717</guid><pubDate>Wed, 25 Jun 2008 06:00:00 +0000</pubDate><atom:updated>2008-06-25T14:12:31.500+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">living without admin</category><title>Reimage is Pure Evil</title><description>&lt;p&gt;My work computer is &lt;strong&gt;slow&lt;/strong&gt;. But it's not because of the hardware, it's not because I'm running extremely computationally expensive tasks, it's because of corporate stupidity.&lt;/p&gt;

&lt;p&gt;I work for a large multinational company, which has a dedicated department for creating "standard builds". These contain everything from operating system, office, antivirus to our corporate utilities. Since everything in the images is preconfigured, the desktop guys completely lost the ability to troubleshoot. The path of least resistance is to simply reimage every computer they get their hands on.&lt;/p&gt;

&lt;p&gt;This has three consequences:
 &lt;ul&gt;
  &lt;li&gt;the corporate standard build has to fit all employees&lt;/li&gt;
  &lt;li&gt;the desktop guys don't educate themselves&lt;/li&gt;
  &lt;li&gt;even a monkey can be a desktop guy&lt;/li&gt;
 &lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;The economical side of this solution seems favorable at first look, but I actually want to claim otherwise. Having locked down computer with standard builds actually costs more then having educated desktop department.&lt;/p&gt;

&lt;p&gt;During my studies I used to work as &lt;strong&gt;the&lt;/strong&gt; desktop department in a company of 70 people and I had never had to do a full reinstall. Everyone had administrative rights, when something went wrong I troubleshooted the computer spending from five minutes to three hours on a problem and I was able to fix everything. I explained the users what went wrong and gradually I had less and less work, because the users actually started to understand how computers work (I admit I was quite lucky).&lt;/p&gt;

&lt;p&gt;True the employee to desktop guy ration was only 70:1, whereas in my current company is 199:1, but these guys are not even trying. &lt;em&gt;Something is wrong on your computer? Bring it down for reinstall&lt;/em&gt;. No one learns anything and the problem is most likely going to repeat itself.&lt;/p&gt;

&lt;p&gt;But that's not the worst part of it, the worst is the one size fits all approach. The computers come preloaded with so many utilities and services, that it literally takes minimum fifteen minutes to start up. In my case I have eight programs running under my account, which I have to kill after every startup, and 19 services which I don't use and which I can't do anything about without administrative privileges.&lt;/p&gt;

&lt;p&gt;So for the convenience of the desktop department, everyone in the company spends first fifteen minutes waiting for the computer to start up. For one desktop guy to have easy and convenient work, 199 people have to suffer.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://chart.apis.google.com/chart?cht=p&amp;chd=t:19.9,0.1&amp;chs=700x400&amp;chl=Productive%20Employees|Desktop%20Guys"/&gt;&lt;/p&gt;

&lt;p&gt;As a result people simply stop turning their computers off, they keep them running the whole night, wasting electricity.&lt;/p&gt;

&lt;p&gt;Well done CTOs. I'm sure all the wasted mandays and electricity are much cheaper then to hire a couple more desktop guys.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-9220716611417123717?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2008/06/reimage-is-pure-evil.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-5750243848211023560</guid><pubDate>Tue, 24 Jun 2008 06:00:00 +0000</pubDate><atom:updated>2008-08-29T11:02:49.919+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><title>JavaScript Object Inspector</title><description>&lt;p&gt;Following my previous little JavaScript hack to display the &lt;a href="/2008/06/javascript-stacktrace.html"&gt;stacktrace&lt;/a&gt; in Internet Explorer, I decided to write myself an object inspector. It lists all the properties and all the subproperties of objects.&lt;/p&gt;

&lt;p&gt;There is actually nothing fancy about the script, the most important line is &lt;code&gt;for i in o&lt;/code&gt;, which in JavaScript lists all property names of an object. The rest is just syntactic sugar - opening the window, defining stylesheet, onclick handler etc.&lt;/p&gt;

&lt;pre class="javascript"&gt;
function v(o, level)
{
	w = window.open('', 'debug');

	if (level == undefined)
	{
		w.document.write('&amp;lt;style&amp;gt;div {border-style:solid;border-width:1pt;margin-left:10pt;padding:2pt;} .v{display:block} .i{display:none}&amp;lt;/style&amp;gt;');
		w.document.write('&amp;lt;script&amp;gt;function d(a){a.className=a.className=="v"?"i":"v";}&amp;lt;/script&amp;gt;');
		w.document.write('&amp;lt;div class="v"&amp;gt;'); 
	}
	else
		w.document.write('&amp;lt;div class="i"&amp;gt;'); 

	if (o == undefined)
		w.document.write('undefined &amp;lt;br /&amp;gt;');
	else if (typeof (o) == 'object')
		for (i in o)
			if (o[i] != undefined &amp;&amp; typeof (o[i]) == 'object') 
			{
				if ((i != 'parentNode') &amp;&amp; (i != 'parentElement') &amp;&amp; (i != 'nextSibling') &amp;&amp; 
				    (i != 'previousSibling') &amp;&amp; (i != 'ownerDocument') &amp;&amp; (i != 'offsetParent') &amp;&amp; 
				    (i != 'ownerElement') &amp;&amp; (i != 'document') &amp;&amp; (i != 'namespaces') &amp;&amp; (i != 'parentTextEdit'))
				{
					w.document.write('&amp;lt;p onclick="d(this.nextSibling);"&amp;gt;&amp;lt;b&amp;gt;['+ i +'] = ' + o[i] +'&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;');
					v(o[i], 1);
				}
			}
			else if (typeof (o[i]) != 'function')
				w.document.write('&amp;lt;p&amp;gt;['+ i +'] = ' + o[i] +'&amp;lt;/p&amp;gt;');

	w.document.write('&amp;lt;/div&amp;gt;');
}
&lt;/pre&gt;

&lt;script&gt;
function v(o, level)
{
	w = window.open('', 'debug');

	if (level == undefined)
	{
		w.document.write('&lt;style&gt;div {border-style:solid;border-width:1pt;margin-left:10pt;padding:2pt;} .v{display:block} .i{display:none}&lt;/style&gt;');
		w.document.write('&lt;script&gt;function d(a){a.className=a.className=="v"?"i":"v";}\&lt;\/script\&gt;');
		w.document.write('&lt;div class="v"&gt;'); 
	}
	else
		w.document.write('&lt;div class="i"&gt;'); 

	if (o == undefined)
		w.document.write('undefined &lt;br /&gt;');
	else if (typeof (o) == 'object')
		for (i in o)
			if (o[i] != undefined &amp;&amp; typeof (o[i]) == 'object') 
			{
				if ((i != 'parentNode') &amp;&amp; (i != 'parentElement') &amp;&amp; (i != 'nextSibling') &amp;&amp; 
				    (i != 'previousSibling') &amp;&amp; (i != 'ownerDocument') &amp;&amp; (i != 'offsetParent') &amp;&amp; 
				    (i != 'ownerElement') &amp;&amp; (i != 'document') &amp;&amp; (i != 'namespaces') &amp;&amp; (i != 'parentTextEdit'))
				{
					w.document.write('&lt;p onclick="d(this.nextSibling);"&gt;&lt;b&gt;['+ i +'] = ' + o[i] +'&lt;/b&gt;&lt;/p&gt;');
					v(o[i], 1);
				}
			}
			else if (typeof (o[i]) != 'function')
				w.document.write('&lt;p&gt;['+ i +'] = ' + o[i] +'&lt;/p&gt;');

	w.document.write('&lt;/div&gt;');
}
&lt;/script&gt;

&lt;p&gt;To try it out, click on &lt;p onclick="v(this);"&gt;&lt;strong&gt;this link&lt;/strong&gt;&lt;/p&gt;. A new window should appear listing all the links properties looking something like this.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://ondrew.googlepages.com/JavaScript-Object-Inspector.png"/&gt;&lt;/p&gt;

&lt;p&gt;Tested in Internet Explorer, Firefox and Opera&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-5750243848211023560?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2008/06/javascript-object-inspector.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3468328372425900141.post-5379966123435529153</guid><pubDate>Mon, 23 Jun 2008 06:00:00 +0000</pubDate><atom:updated>2008-08-27T16:35:41.842+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">win32</category><category domain="http://www.blogger.com/atom/ns#">tetris</category><title>Tetris Progress Report 1</title><description>&lt;p&gt;So, how's the &lt;a href="/2008/06/tetris-raytracer-compiler.html"&gt;Tetris&lt;/a&gt; going. So far I've spent about four hours on the project and I have window creation, simple GDI drawing, handling of input and timing. I'm quite positively surprised how easy it was so far. For my first Win32 GUI project, it's coming along quite nicely. I basically have all the building blocks in place, I just need to implement the Tetris logic.&lt;/p&gt;

&lt;p&gt;Currently I'm at 11776 bytes (stripped executable), which leaves me confident, that I will be able to squeeze in the 17kB I set for a goal :). I've found out, that I can't use any standard libraries, because they introduce too much overhead. I was thinking about using &lt;code&gt;std::vector&lt;/code&gt; for some stuff, but I will have to go with simple arrays.&lt;/p&gt;

&lt;p&gt;What I'm currently thinking the most about is the data structure I will be using for the Tetris pieces. The obvious 4x4 array is not really suitable for rotations of all pieces, unless I define the centre of gravity for each piece separately. It's a possible solution, but really elegant.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://ondrew.googlepages.com/tetris.01.png"/&gt;&lt;/p&gt;

&lt;p&gt;To download this really preliminary version, click here &lt;a href="http://ondrew.googlepages.com/tetris.01.zip"&gt;here&lt;/a&gt; (10 kB). It's basically just a block falling down, which you can move left and right.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3468328372425900141-5379966123435529153?l=www.gettingclever.com' alt='' /&gt;&lt;/div&gt;</description><link>http://www.gettingclever.com/2008/06/tetris-progress-report-1.html</link><author>noreply@blogger.com (ondrew)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item></channel></rss>
