Monday, January 17, 2005

I recently had some C# code that that had to be made localizable. Most articles about localization/internationalization that you find on the web would talk about how nice Visual Studio is for code internationalization and would show nice examples of how many ways the forms-designer would extract code out into a resx file. I am perfectly ok with studio doing all the work for you. However there are very often, strings in your actual code that studio does not externalize to resx files.

 

Strings.rb is a ruby script that will parse your C# code base and identify literal string definitions in the code base and will move them to your resx file. The code was hacked up to fill out a personal need so your mileage on this may vary. The tool certainly isn’t fool proof and there are certain cases that it doesn’t handle too well. If you are however on the smart-scripter side of things then you may find it useful.

 

The script needs to be setup for your specific project. Once done you can run it several times on your code base and it can incrementally catch strings and externalize them for you. This is handy to have while your code is still undergoing changes so new strings can be identified as they pop up and can be moved out.

 

Getting Started

 

Downloads

1) First thing download the script (strings.rb) and put it in your project folder.

 

2) Download and install ruby from here – http://rubyforge.org/frs/?group_id=167, its about 12mb and the installation happens in a snap.

 

3) Download an install REXML library for XML handling in Ruby from here –

http://www.germane-software.com/archives/rexml_3.1.2.zip

http://www.germane-software.com/software/rexml/docs/tutorial.html

 

 

Patching Strings.rb for your project

1) You need to patch the script file to have the correct path to your resx file and the path to your wrapper class that will be used to read strings from your resx file.

 

Open the script file in a text editor. (If you have ruby installed you should find this editor called scite in the ruby installation folder – that’s a nice editor. Alternately you might want to try installing scite - http://scintilla.sourceforge.net/SciTEDownload.html - about 600k).

 

In your project identify your resx file. It will usually be in Properties\Resources.resx.

Change the following line the rb file to reflect the path path to your resx file.

strings.rb:4:$resx_fn = "properties/Resources.resx"

(The actual line number might change a bit)

 

2) Now create a new class in your project called Strings. VS should typically create an empty class definition file that looks like this.

 

#region Using directives

 

using System;

using System.Collections.Generic;

using System.Text;

 

#endregion

 

namespace <Some Namespace>

{

    public class Strings

    {

 

 

    }

}

 

Patch the file with the following additions

- Add a using directive for your ‘Properties’ namespace.

- Add a comment that stays //start and one that says //stop. These ad as delimiters between with the script will generate the string definitions.

 

 

#region Using directives

 

using System;

using System.Collections.Generic;

using System.Text;

using <Some namespace>.Properties;

 

#endregion

 

namespace <Some Namespace>

{

    public class Strings

    {

 

//start

//stop

 

    }

}

 

3) This is the wrapper class into which the script will generate string definitions. You need to patch the script with the path to this class file. Basically patch this line –

strings.rb:5:$stringsclass_fn = "helper/Strings.cs"

 

Done

If you have got this far then your installation is done and you are ready to go.

For sake of completeness let me just list out things again –

1) download the script and put it into the project folder

2) install ruby

3) install the REXML library for Ruby

4) patch the script with the path to the resx file of the project

5) create a empty Strings class and add the namespace directive and comment markers to it

6) patch the script to have the correct path to your Strings.cs file.

 

What does the script do?

The script does a few basic things.

1) it parses your *.cs files in all subdirectories and looks for strings.

2) when it finds a string a it prompts the user for an action

3) if it is a string that should be localized the user can provide a pseudonym for the string. On getting this name the script will -

            1) add the string and the name to the resx file

            2) add a property to the Strings class that will read the string from the rex file

            3) replace the string literal in the code with a call to the property.

 

Running the script

To run the script after all the previous setup, simply go to the command line and type strings.rb

 

Here is a sample run of the Strings.rb script

Let me take up a simple project and show you how the internationalization script works.

 

Here is a project that has only one Program.cs file –

#region Using directives

 

using System;

using System.Collections.Generic;

using System.Text;

 

#endregion

 

namespace ConsoleApplication1

{

    class Program

    {

        static void Main(string[] args)

        {

            string a = "hello world";

            string x = "skip this line";

            string b = "escape sequences  \n\r\t\\\"";

            string c = @"cant handle this one";

        }

    }

}

 

The resx file looks like this –

<?xml version="1.0" encoding="utf-8"?>

<root>

  <resheader name="resmimetype">

    <value>text/microsoft-resx</value>

  </resheader>

  <resheader name="version">

    <value>2.0</value>

  </resheader>

  <resheader name="reader">

    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>

  </resheader>

  <resheader name="writer">

    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>

  </resheader>

</root>

(I have removed some unnecessary details from the original resx file here)

 

I created this Strings class –

#region Using directives

 

using System;

using System.Collections.Generic;

using System.Text;

using ConsoleApplication1.Properties;

 

#endregion

 

namespace ConsoleApplication1

{

    public class Strings

    {

 

//start

//stop

 

    }

}

 

This is what happens when you run the strings.rb script –

C:\work\vcsexpress\Sample1\Sample1>strings

Error reading skip data! continuing with no skip data.

HelloString = hello world

EscString = escape sequences  \n\n\t\\\"

Program.cs:0:n++#region Using directives

Program.cs:1:

Program.cs:2:using System;

Program.cs:3:using System.Collections.Generic;

Program.cs:4:using System.Text;

Program.cs:5:

Program.cs:6:#endregion

Program.cs:7:

Program.cs:8:namespace ConsoleApplication1

Program.cs:9:{

Program.cs:10:    class Program

Program.cs:11:    {

Program.cs:12:        static void Main(string[] args)

Program.cs:13:        {

Program.cs:14:            string a = "hello world";

"hello world">?

Help ----------

        =<name> = the string will be externalised as <name>

        sf = skip file : file will not processed on next run

        if = ignore file : file will be processed on next run

        sl = skip line : line will be processed on next run

        il = ignore line : line will be processed on next run (default)

        x, exit = exit script

        all skip information in stored in "skip_list.txt"

Program.cs:14:            string a = "hello world";

"hello world">=HelloString

            string a = Strings.HelloString;

Program.cs:15:            string x = "skip this line";

"skip this line">sl

Program.cs:16:            string b = "escape sequences  \n\r\t\\\"";

"escape sequences  \n\r\t\\\"">=EscString

            string b = Strings.EscString;

Program.cs:17:            string c = @"cant handle this one";

Program.cs:18:        }

Program.cs:19:    }

Program.cs:20:}

Writing Resource File "properties/Resources.resx" : done

Writing Strings class "Strings.cs" : done

Writing Skip data "skip_list.txt" : done

 

Effectively you can see the script run through the source file (actually it runs through all the cs files) and prompt you with each string. It also shows a little help on the actions possible.

 

To replace a string, you need to give it a name. Simply type =<name> and the string will get replaced.

 

If you don’t want to do anything about a particular line, type ‘sl’ for skip line and it will skip that line. It also adds the line to a file called skip_file.txt so that in subsequent runs of strings.rb it will not keep prompting you to patch the same line.

 

You can similarly choosing skip a file using the ‘sf’ option. You may typically want to skip the *.designer.cs files, the strings.cs file etc.

 

All skip information is human readable and is stored in a text file called skip_list.txt.

 

Strings.rb is deisgned to be run multiple times over the sample project through its development so that it can catch new strings as they appear in your code base, incrementally. The resx and strings.cs files are recreated at each run.

 

To show you the output of the process, this is what happened.

 

This is the new Program.cs file –

#region Using directives

 

using System;

using System.Collections.Generic;

using System.Text;

 

#endregion

 

namespace ConsoleApplication1

{

    class Program

    {

        static void Main(string[] args)

        {

            string a = Strings.HelloString;

            string x = "skip this line";

            string b = Strings.EscString;

            string c = @"cant handle this one";

        }

    }

}

 

This is the new resx file –

<?xml version="1.0"?>

<root>

  <resheader name="resmimetype">

    <value>text/microsoft-resx</value>

  </resheader>

  <resheader name="version">

    <value>2.0</value>

  </resheader>

  <resheader name="reader">

    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>

  </resheader>

  <resheader name="writer">

    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>

  </resheader>

  <data name="HelloString">

    <value xml:space="preserve">hello world</value>

  </data>

  <data name="EscString">

    <value xml:space="preserve">escape sequences 

 

       \"</value>

  </data>

</root>

 

Notice that the two strings have appeared here.

 

And this is the new Strings.cs file –

#region Using directives

 

using System;

using System.Collections.Generic;

using System.Text;

using ConsoleApplication1.Properties;

 

#endregion

 

namespace ConsoleApplication1

{

    public class Strings

    {

 

//start

              // "escape sequences  \n\r\t\\\""

              public static string EscString { get { return Resources.ResourceManager.GetString("EscString"); } }

 

              // "hello world"

              public static string HelloString { get { return Resources.ResourceManager.GetString("HelloString"); } }

 

//stop

 

    }

}

 

Also, if you are interested in seeing the skip data, this is the skip_list.txt that got created –

Program.cs:::string x = "skip this line";

 

Limitations

1) The string matching that is done by the script is fairly limited. Basically it identifies strings in the the c# code by comparing with the following regex –

strings.rb:15:$string_pattern = /[^@]("(\\.|[^\\"])*")/

This does not cleanly cover all sorts of escape sequences that a string can have. It also does not support @””. But .. well… this covers large number of strings that you would face, so its good enough to get along. Also if you can get me a better pattern match, I would be happy.

 

The script iterates over all strings on a line of cs code using –

      line.scan($string_pattern).each {|str,e1|

            //str is the string

      }

 

 

2) The resx file tags that are generated by script are those that are valid for Visual C# Express Edition Beta 1 format. I don’t know if this resx format is valid for other versions of studio. I would expect that it is. Even if it is not, you can easily patch it for you version of studio. This is how –

 

The resx file has a tag added for each string definition that looks like this –

  <data name="HelloString">

    <value xml:space="preserve">Hello world</value>

  </data>

 

If your studio generates tags like this, then you are ok. If you are not just patch the following block of ruby code to generate your tags. It’s fairly easy –

            el = doc.root.add_element "data"

            el.add_attribute("name", key)

            val = el.add_element("value")

            val.add_attribute("xml:space","preserve")

            val.text = remove_esc_seq($map[key])

This is part of the writeresx() function.

 

3) The escape sequence handling in the script is a hack – its funny – it’s limited. It’s actually a little sad:

def add_esc_seq(str)

       str.gsub("\\", "<double_back_slash>").gsub("\"", "\\\"").gsub("\n", "\\n").gsub("\t", "\\t").gsub("\r", "\\r").gsub("<double_back_slash>", '\\\\\\')

end

 

def remove_esc_seq(str)

       str.gsub("\\\\","<back_slash>").gsub("\\n", "\n").gsub("\\t", "\t").gsub("\\r", "\r").gsub("\\\"", "\"").gsub("<back_slash>","\\")

end

 

These are however good enough for \r \n \t \\ \” etc.

 

4) The resx XML doesn’t look too nice. It works however. This is because the REXML library produces badly formatted XML. You can download the XML Pretty Printing program on mine and run it on the output resx file for pretty XML formatting.

 

5) “The setup is a little contrived and all this requires me to know ruby programming “

If you actually said that then this script is not for you. For the simple reason that this is something home-grown and not meant to be a polished product in any way. You don’t need to know ruby much to just get it working. You need to know ruby only if you need to extend it in non-obvious ways. Secondly the setup isn’t that contrived if you have been using ruby. You would, most likely, have most of the tools in place already.

 

Finally, Why Ruby?

My only real answer to the question is that I wanted to get the job done. For an example take a look at the engine code and peaceful separation that it gives me from the prompt/ui code.  

 

That’s it. So if you are geeky enough and consider it below your dignity to get down to doing a menial job of looking through source files and copying out strings to the resx files – then this script might help you.

 

Download Strings.rb

 

Ps. It’s a lot of effort documenting any ruby program that is more that 200 lines. It just does too many things.

 

Monday, January 17, 2005 8:40:18 AM (Eastern Standard Time, UTC-05:00)  #    Comments [9]  | 

Ever had badly formatted XML that you wanted to have looking clean? Here is a little bit of C# that cleans up the XML indentation and makes a pretty printed XML for you.

 

using System;

using System.IO;

using System.Xml;

 

 

class CMain

{

    static void Main(string[] files)

    {

        if (files.Length == 0)

            Console.WriteLine("Syntax:\n\txmlpp <filename> [<outfilename>]");

      

        XmlDocument doc = new XmlDocument();

 

        XmlTextReader rd = new XmlTextReader(files[0]);

        rd.WhitespaceHandling = WhitespaceHandling.None;

        doc.Load(rd);

        rd.Close();

 

        XmlTextWriter wr = new XmlTextWriter(files.Length == 1 ? files[0] : files[1], null);

        wr.Formatting = Formatting.Indented;

        doc.Save(wr);

        wr.Close();

    }

}

 

I wrote this down because I was doing some XML manipulation with the REXML library for Ruby yesterday and REXML seemed to dump relatively ugly XMLs no matter what formatting options I gave it.

 

Usage Examples:

            xmlpp file.xml

            xmlpp file.xml outfile.xml

 

Download src and binary

Monday, January 17, 2005 4:26:56 AM (Eastern Standard Time, UTC-05:00)  #    Comments [3]  | 
 Sunday, January 09, 2005

The little public information about Vulcan –

 

MSR-TR-2001-50

Vulcan: Binary transformation in a distributed environment

Andrew Edwards; Amitabh Srivastava; Hoi Vo

April 2001

http://research.microsoft.com/research/pubs/view.aspx?type=Technical%20Report&id=455

 

Sunday, January 09, 2005 11:41:30 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  | 
 Thursday, January 06, 2005

I now have what is advertised to be one of the world’s smallest 7.2 megapixel cameras – The Sony Cybershot P150

 

 

Reviews –

http://www.dcresource.com/reviews/sony/dsc_p150-review/index.shtml

http://www.dpreview.com/reviews/sonydscp150/

http://www.megapixel.net/reviews/sony-p150/p150-review.html

http://www.imaging-resource.com/PRODS/P150/P15A.HTM

http://www.steves-digicams.com/2004_reviews/p150.html

and even the register - http://www.theregister.co.uk/2004/11/30/review_sony_p150/

 

 

And here is are some humble beginnings –

 

 

 

These are shot at the Microsoft office at Cyber towers, Hitech City.

 

 This should give you an idea of the detail this captures -

 

And some shots from my terrace –

 

 

Thursday, January 06, 2005 12:59:22 AM (Eastern Standard Time, UTC-05:00)  #    Comments [6]  | 
 Friday, December 24, 2004

I have been having this for a while now, so I am sharing this out.

 

C:\>hexv

HexViewer A command line Hex Viewing Utility

(c) Spark (spark@mvps.org), March 2004.

 

Syntax: hexv <filename> [options]

(Default - Displays 1244872 lines in byte format)

 

Options:

        -byte           Show content as hex bytes (default)

        -word           Show content as hex words

        -dword          Show content as hex dwords

        @<int>          Displays contents from given offset

        @x<hex>         Displays contents from given hex offset

        -lines:<int>    Displays specified number of lines

        -all            Displays the whole file

 

Other usage:

        -ascii          Displays the ASCII table

        -help           Show this help

        /?              Show this help

 

Dedicated to all the frustrating times when I just wanted a

hex dump and had no option

 

I have written much grander hex viewers and all sorts of other viewers in the past, but this little thing stuck on due to its simplicity.

 

C:\>hexv mmc.exe

 

0000:0000│ 4D 5A 90 00 03 00 00 00 │ 04 00 00 00 FF FF 00 00 │ MZÉ▒♥▒▒▒│♦▒▒▒  ▒▒

0000:0010│ B8 00 00 00 00 00 00 00 │ 40 00 00 00 00 00 00 00 │ ╕▒▒▒▒▒▒▒│@▒▒▒▒▒▒▒

0000:0020│ 00 00 00 00 00 00 00 00 │ 00 00 00 00 00 00 00 00 │ ▒▒▒▒▒▒▒▒│▒▒▒▒▒▒▒▒

0000:0030│ 00 00 00 00 00 00 00 00 │ 00 00 00 00 08 01 00 00 │ ▒▒▒▒▒▒▒▒│▒▒▒▒▒☺▒▒

0000:0040│ 0E 1F BA 0E 00 B4 09 CD │ 21 B8 01 4C CD 21 54 68 │ ♫▼║♫▒┤▒═│!╕☺L═!Th

0000:0050│ 69 73 20 70 72 6F 67 72 │ 61 6D 20 63 61 6E 6E 6F │ is progr│am canno

 

C:\>hexv mmc.exe -word

 

0000:0000 5A4D 0090 0003 0000 | 0004 0000 FFFF 0000

0000:0008 00B8 0000 0000 0000 | 0040 0000 0000 0000

0000:0010 0000 0000 0000 0000 | 0000 0000 0000 0000

0000:0018 0000 0000 0000 0000 | 0000 0000 0108 0000

0000:0020 1F0E 0EBA B400 CD09 | B821 4C01 21CD 6854

 

C:\>hexv mmc.exe -dword

 

0000:0000 00905A4D 00000003 | 00000004 0000FFFF

0000:0004 000000B8 00000000 | 00000040 00000000

0000:0008 00000000 00000000 | 00000000 00000000

0000:000C 00000000 00000000 | 00000000 00000108

0000:0010 0EBA1F0E CD09B400 | 4C01B821 685421CD

0000:0014 70207369 72676F72 | 63206D61 6F6E6E61

0000:0018 65622074 6E757220 | 206E6920 20534F44

 

C:\>hexv mmc.exe @x40

 

0000:0040│ 0E 1F BA 0E 00 B4 09 CD │ 21 B8 01 4C CD 21 54 68 │ ♫▼║♫▒┤▒═│!╕☺L═!Th

0000:0050│ 69 73 20 70 72 6F 67 72 │ 61 6D 20 63 61 6E 6E 6F │ is progr│am canno

0000:0060│ 74 20 62 65 20 72 75 6E │ 20 69 6E 20 44 4F 53 20 │ t be run│ in DOS

0000:0070│ 6D 6F 64 65 2E 0D 0D 0A │ 24 00 00 00 00 00 00 00 │ mode.▒▒▒│$▒▒▒▒▒▒▒

0000:0080│ 05 5E C8 CB 41 3F A6 98 │ 41 3F A6 98 41 3F A6 98 │ ♣^╚╦A?ªÿ│A?ªÿA?ªÿ

 

Finally something unrelated –

 

C:\>hexv -ascii

 000 x00 = ( )  │ 001 x01 = (☺) │ 002 x02 = (☻) │ 003 x03 = (♥)

 004 x04 = (♦)  │ 005 x05 = (♣) │ 006 x06 = (♠) │ 007 x07 = bell

 008 x08 = bksp │ 009 x09 = tab │ 010 x0A = LF  │ 011 x0B = (♂)

 012 x0C = (♀)  │ 013 x0D = CR  │ 014 x0E = (♫) │ 015 x0F = (☼)

 016 x10 = (►)  │ 017 x11 = (◄) │ 018 x12 = (↕) │ 019 x13 = (‼)

 020 x14 = (¶)  │ 021 x15 = (§) │ 022 x16 = (▬) │ 023 x17 = (↨)

 024 x18 = (↑)  │ 025 x19 = (↓) │ 026 x1A = (→) │ 027 x1B = (←)

 

As always download binaries and source

Friday, December 24, 2004 1:28:13 AM (Eastern Standard Time, UTC-05:00)  #    Comments [6]  | 
 Friday, December 17, 2004

There must be some way out of here," said the joker to the thief,

"There's too much confusion, I can't get no relief.

Businessmen, they drink my wine, plowmen dig my earth,

None of them along the line know what any of it is worth."

 

"No reason to get excited," the thief, he kindly spoke,

"There are many here among us who feel that life is but a joke.

But you and I, we've been through that, and this is not our fate,

So let us not talk falsely now, the hour is getting late."

 

All along the watchtower, princes kept the watch

While all the women came and went, barefoot servants, too.

 

Outside in the distance a wildcat did growl,

Two riders were approaching, the wind began to howl.

 

            All Along the Watchtower, Bob Dylan 1967.

  

And I am thinking that songs like this are not written or authorized by committees. Committees are about filtering out the insanity of individuals into the sanity of the collective. The whole is greater than the sum of the parts. Or so they said.

 

How does it feel

How does it feel

To be on your own

With no direction home

Like a complete unknown

Like a rolling stone?

           

            Like a Rolling Stone, Bob Dylan 1965

 

 

THE MYTH OF DAEDALUS & ICARUS

 

Daedalus was a highly respected and talented Athenian artisan descendent from the royal family of Cecrops, the mythical first king of Athens. He was known for his skill as an architect, sculpture, and inventor, and he produced many famous works. Despite his self-confidence, Daedalus once committed a crime of envy against Talus, his nephew and apprentice. Talus, who seemed destined to become as great an artisan as his uncle Daedalus, was inspired one day to invent the saw after having seen the way a snake used its jaws. Daedalus, momentarily stricken with jealousy, threw Talus off of the Acropolis. For this crime, Daedalus was exiled to Crete and placed in the service of King Minos, where he eventually had a son, Icarus, with the beautiful Naucrate, a mistress-slave of the King.

Minos called on Daedalus to build the famous Labyrinth in order to imprison the dreaded Minotaur. The Minotaur was a monster with the head of a bull and the body of a man. He was the son of Pasiphae, the wife of Minos, and a bull that Poseidon had sent to Minos as a gift. Minos was shamed by the birth of this horrible creature and resolved to imprison the Minotaur in the Labyrinth where it fed on humans, which were taken as "tribute" by Minos and sacrificed to the Minotaur in memory of his fallen son Androgenos.

 

Theseus, the heroic King of Athens, volunteered himself to be sent to the Minotaur in the hopes of killing the beast and ending the "human tribute" that his city was forced to pay Minos. When Theseus arrived to Crete, Ariadne, Minos's daughter, fell in love with him and wished to help him survive the Minotaur. Daedalus revealed the mystery of the Labyrinth to Ariadne who in turn advised Theseus, thus enabling him to slay the Minotaur and escape from the Labyrinth. When Minos found out what Daedalus had done he was so enraged that he imprisoned Daedalus & Icarus in the Labyrinth themselves.

 

Daedalus conceived to escape from the Labyrinth with Icarus from Crete by constructing wings and then flying to safety. He built the wings from feathers and wax, and before the two set off he warned Icarus not to fly too low lest his wings touch the waves and get wet, and not too high lest the sun melt the wax. But the young Icarus, overwhelmed by the thrill of flying, did not heed his father's warning, and flew too close to the sun whereupon the wax in his wings melted and he fell into the sea. Daedalus escaped to Sicily and Icarus' body was carried ashore by the current to an island then without a name. Heracles came across the body and recognized it, giving it burial where today there still stands a small rock promontory jutting out into the Aegean Sea, and naming the island and the sea around it after the fallen Icarus.

 

 

Icarus by frank wright

 

The labyrinth from which Theseus escaped by means of the clew of Ariadne was built by Daedalus, most skillful artificer. It was an edifice with numberless winding passages and turnings opening into one another, and seeming to have neither beginning nor end, like the river Maeander, which returns on itself, and flows now onward, now backward, in its course to the sea. Daedalus built the labyrinth for King Minos, but afterward lost the favor of the king, and was shut up in a tower. He contrived to make his escape from his prison, but could not leave the island by sea, as the king kept strict watch on all the vessels and permitted none to sail without being carefully searched. "Minos may control the land and sea," said Daedalus, "but not the regions of the air. I will try that way."

So he set to work to fabricate wings for himself and his young son Icarus. He wrought feathers together, beginning with the smallest and adding larger, so as to form an increasing surface. The larger ones he secured with thread and the smaller ones with wax, and gave the whole a gentle curvature like the wings of a bird. Icarus, the boy, stood and looked on, sometimes running to gather up the feathers which the wind had blown away, and then handling the wax and working it over with his fingers, by his play impeding his father in his labors. When at last the work was done, the artist, waving his wings, found himself buoyed upward and hung suspended, poising himself on the beaten air. He next equipped his son in the same manner and taught him how to fly, as a bird tempts her young ones from the lofty nest into the air. When all was prepared for flight he said, "Icarus, my son, I charge you to keep at a moderate height, for if you fly too low the damp will clog your wings, and if too high the heat will melt them. Keep near me and you will be safe."

 

While he gave him these instructions and fitted the wings to his shoulders, the face of the father was wet with tears, and his hands trembled. He kissed the boy, not knowing it was for the last time. Then rising on his wings he flew off, and looked back from his own flight to see how his son managed his wings. As they flew the plowman stopped his work to gaze, and the shepherd leaned on his staff and watched them, astonished at the sight, and thinking they were gods who could thus cleave the air.

 

They passed Samos and Delos on the left and Lebynthos on the right, when the boy, exulting in his career, began to leave the guidance of his companion and soar upward as if to reach heaven. The nearness of the blazing sun softened the wax which held the feathers together, and they came off. He fluttered with his arms, but no feathers remained to hold the air. While his mouth uttered cries to his father it was submerged in the blue waters of the sea, which was thenceforth called by his name. His father cried, "Icarus, Icarus, where are you?" At last he saw the feathers floating on the water, and bitterly lamenting his own arts, he buried the body and called the land Icaria in memory of his child. Daedalus arrived safe in Sicily, where he built a temple to Apollo and hung up his wings, an offering to the god.

 

Friday, December 17, 2004 9:41:02 AM (Eastern Standard Time, UTC-05:00)  #    Comments [5]  | 
 Monday, December 13, 2004

Frodo: What are we holding on to Sam?
Sam: That there's some good in this world, Mr. Frodo... and it's worth fighting for.

My blog just crossed 10 thousand unique visitors. Yippie!

Monday, December 13, 2004 3:30:52 PM (Eastern Standard Time, UTC-05:00)  #    Comments [20]  | 
 Monday, December 06, 2004

With unknown consciousness, I possessed in my grip

A magnificent mantelpiece, though its heart being chipped,

Noticing not that I'd already slipped

To a sin of love's false security.

 

From silhouetted anger to manufactured peace,

Answers of emptiness, voice vacancies,

Till the tombstones of damage read me no questions but, "Please,

What's wrong and what's exactly the matter?"

 

And so it did happen like it could have been foreseen,

The timeless explosion of fantasy's dream.

At the peak of the night, the king and the queen

Tumbled all down into pieces.

 

Listening to Dylan again

 

Ah, my friends from the prison, they ask unto me,

"How good, how good does it feel to be free?"

And I answer them most mysteriously,

"Are birds free from the chains of the skyway?"

 

                        Bob Dylan, Ballad in Plain D, 1964

Monday, December 06, 2004 1:17:42 AM (Eastern Standard Time, UTC-05:00)  #    Comments [7]  |