Wednesday, September 29, 2004

213.aspx

egilh project #9: Windows 95

What: I started translating but passed through managing external translation vendors before I ended up doing what I liked best; technical specialist. The way we translated Windows 95 was drastically different from the previous translation work; instead of editing include and resource files, we modified the resource sections in the final English version (i.e. directly in the .dll or .exe). Translating the resource files gave fast turn-around as the change was visible immediately. It was also a mess some times as some times the word "Desktop" should be translated, other times it’s the internal name in Windows for the desktop and everything boke if you translated it.


The tools for translating were, as usual, pretty bad so I spent some time writing tools that automated the process (more posts later on these later).


When: mid 90s :-)


Lessons learned:



  • Installing and using Windows 95 "blindfolded". Seeing the characters doesn't really make much of a difference when you try to troubleshoot a problem in Greek, Russian and Turkish….

  • Patience. I did a lot, but a lot, of builds of Windows 95. It came in tons of flavors; 5 1/4 floppies, 3 1/2 floppies (small and large build), CDs, ... Each build took the best part of the day as the new .CAB building tool optimized the organization of the files etc. In the few weeks after the US team RTMed I worked nights (and days) to build the most critical languages (French/Spanish)

  • Work smarter not harder:  You can do a lot of stuff if you mange your "dead time" well. The next bunch of projects are internal projects I worked on while installing/building etc

  • Working 2 years  on a "never ending" project is not for me. I hope it is better working in the Redmond dev team or I feel really sorry for the Longhorn developers

  • Brad Silverberg sounds a lot like "Brat Silverberg" (a -very- good friend almost made the mistake to his face)

  • Microsoft really knows how to throw a release party. I had the pleasure of attending both the internal one and the public one with Jay Leno.

  • The Windows 95 T-shirts are incredibly strong. I still have, and use, a few of them while working on the house/garden.

  • Writing software that can be translated/localized. The string "%s printing on %s" should have been translated to "Printing %s on %s" in some languages but it was impossible in Windows 95 (which explains the funny wording in some localized versions). This is one of the things they got right in .NET. Format strings now use positionsl, so "%1 printing  %2" can -finally- be translated to "Printing %2 on %1" without changing the software

Tuesday, September 28, 2004

210.aspx

Using the POOM from .NET CF 1.0

I organize my work (and a fair bit of my life) with the Outlook task list. In Outlook I have a customized view that shows all tasks due today, grouped by priority. This feature does not exist on the Pocket PC so I implemented a simple task manager with embedded VB which I used a lot on my old iPAQ. I didn't want to install the VB runtime on my new iPAQ 4150 so I decided to rewrite it in .NET CF.


I didn't get far before I hit the first hurdle though: accessing Pocket Outlook with .NET CF.


The problem is that Pocket Outlook is only available via the IPOutlookApp COM interface and .NET CF does not support calling COM components. The latest news I have from Microsoft is that this will be fixed in the next version. I quickly found the commercial PocketOutlook In The Hand component from InTheHand for accessing POOM. Both The Windows Mobile Team Blog and Omar Shahine refer to the InTheHand component as the way to go. But, in the end, I decided to continue on my DIY quest for several reasons;



  • I wanted to learn how to access COM components from .NET CF
  • I didn't feel like paying $40 for a component I will only use on a personal project

The only way to call a COM component with .NET CF is to write a standard DLL that wraps the COM methods. A lot of work, as POOM has a lot of objects, methods and properties. The great news is that you can find all the free tools and source code you need on the Microsoft web site(s):



The POOM C++ wrapper support all the objects (at least the ones I have checked). It also comes with a .NET CF client that shows how to access the Pocket Outlook contacts.  The .NET CF client is fairly limited as it only imports some of the C++ managed DLL methods. It is very simple to extend as you only have to add new DllImport's. I added the methods (get and set) for accessing the DueDate and it compiled like a charm but bombed on the Pocket PC when I tried to set the DueDate. I found the problem after having a closer look at the C++ code. The (put) DueDate method signature was:


HRESULT ITask_put_DueDate(ITask* thisPtr,


           DATE st)


{


  return thisPtr->put_DueDate(st);


}


 


The problem is the st argument. It passes an OLE Automation DATE which is 8 bytes.  .NET CF doesn't support arguments larger than 4 bytes (32 bit) so the source code has to be changed to pass a pointer (4 bytes) to a date:


HRESULT ITask_put_DueDate(ITask* thisPtr,


           DATE* st)


{


  return thisPtr->put_DueDate(*st);


}


 


The C# code has to be fixed as well. The correct DllImports are:


[ DllImport("PocketOutlook.dll", EntryPoint="ITask_get_DueDate") ]


private static extern int do_get_DueDate(IntPtr self,


                                          ref double dueDate);


 


[ DllImport("PocketOutlook.dll", EntryPoint="ITask_put_DueDate") ]


private static extern int do_put_DueDate(IntPtr self,


                                          ref double dueDate);


 



Almost there, one more thing do do: add a C# property wrapper for the DllImports


public System.DateTime DueDate


{    


      get


      {                      


            double doubleDate = 0.0;


            PocketOutlook.CheckHRESULT(do_get_DueDate(this.RawItemPtr, ref doubleDate));                   


            return PocketOutlook.OleDateToDateTime(doubleDate);


      }    


 


      set


      {                      


            double doubleDate = PocketOutlook.DateTimeToOleDate(value);


            PocketOutlook.CheckHRESULT(do_put_DueDate(this.RawItemPtr, ref doubleDate));


      }


}


 


The code uses the .NET 1.0 CF Date conversion source code I posted earlier to convert the DATE arguments to System.DateTime


Fix the bugs in the Microsoft code you have a free .NET CF POOM client. Cool Or What?

Monday, September 27, 2004

208.aspx

GPS programming

Writing Your Own GPS Applications has a good intro to GPS programming. It covers the basic GPS commands and explains the terms you need to know when working with GPS. Examples in VB.NET with plenty of comments.


Not sure if I manage to resist the temptation of buying a Bluetooth Tom Tom much longer. Maybe I can integrate it with the SMS Bluetooth manager I wrote earlier this year? Or write a client on my laptop that automagically configures the IP depending on my location?


 

Friday, September 24, 2004

207.aspx

VB/OLE DATE conversion in .NET CF 1.0

For a  .NET CF 1.0 program I'm working I have to use a VB/OLE Automation DATE from C#. The .NET methods FromOADate and ToOADate are not available on .NET CF 1.0 so I ported the VB.NET implementation of FromOADate and ToOADate to C#


 


 


public static System.DateTime OleDateToDateTime(double date)


{


      const Int32 hex1 = 86400000;              //0x5265c00


      const Int64 hex2 = 59926435200000;        //0x3680b5e1fc00


      const Int64 hex3 = 315537897600000;       //0x11efae44cb400


      const Int32 hex4 = 10000;                       //0x2710


      const double real1 = 86400000;     


      const double real2 = 2958466;


      const double real3 = -657435;


     


      if (date >= real2 || date <= real3)


      {


            throw new ArgumentException("Arg_OleAutDateInvalid");


      }


 


      double toAdd = date >= 0 ? 0.5 : -0.5;


 


      long loc0 = (long) (date * real1 + toAdd);


      if (loc0 < 0)


      {    


            loc0 -= (2 * getReminder(loc0, hex1));


      }


      loc0 += hex2;


     


      if (loc0 < 0 || loc0 >= hex3)


      {


            throw new ArgumentException("Arg_OleAutDateScale");


      }


 


      return new DateTime(loc0 * hex4);        


}


 


public static double DateTimeToOleDate(System.DateTime date)


{


      const Int32 hex1 = 86400000;              // '0x5265c00


      const Int64 hex2 = 599264352000000000;    // '0x85103c0cb83c000


      const Int64 hex3 = 31241376000000000;     // '0x6efdddaec64000


      const Int32 hex4 = 10000;                       // '0x2710


      const Int64 hex5 = 864000000000;          // '0xc92a69c000


      const double real1 = 86400000;     


 


      long ticks = date.Ticks;


 


      if (0 == ticks)


      {


            return 0.0;


      }


     


      if (ticks < hex5)


      {


            ticks += hex2;


      }


 


      if (ticks < hex3)            


      {


            throw new ArgumentException("Arg_OleAutDateInvalid");


      }


 


      long loc1;


      long loc0 = (long) ((ticks - hex2) / hex4);


 


      if (loc0 < 0)


      {


            loc1 = getReminder(loc0, hex1);


            if (0 != loc1)


            {


                  loc0 -= (hex1 + loc1) * (2);


            }                


      }


     


      return ((double) loc0) / real1;


}


 


 


private static long getReminder(long value1, long value2)


{


      long res;


      res = value1 - value2 * (value1 / value2); 



      return res;      


}

Saturday, September 18, 2004

205.aspx

egilh project #8: DAO/RDO

What: DAO/RDO . Well, almost :-(
I got the job and went back to Dublin to celebrate with a few pints with the lads only to discover that the lawyers couldn't get me a work permit. 6 months more work experience and the job would have been mine...


When: mid 90s


Lessons learned:



  • I hate lawyers
  • First time on a 10 hour flight (BA business class via London Heathrow, 3 movies and great food/junk)
  • First time in the USA
  • First time driving a car with automatic gear
  • First jet lag
  • First, but not last, time on Microsoft campus
  • First time I had 7 job interviews for 1 job. (The future boss and 6 future colleagues)

I had great fun during the interviews. Some issues were pretty basic like create a C++ object representing a person but there were more fun ones;



  • You have X coins. One of them is heavier than the other ones. How many times do you have to weight them to find out which coin is the heaviest?
  • In the reception of the building I had my interview there were two stones  showing the current day (01..31) of the month. What is the minimal number of sides needed on each of the stones?
  • Philosophical discussion over atol(); how does it return errors and how would I return errors if I had designed the API
  • Discussing fast cars over a Mexican lunch

Friday, September 17, 2004

204.aspx

egilh project #7: Excel 95

What: Started the translation work on Excel 95 but I quickly moved on to Windows 95 as I got the chance to work on technical issues instead of translations. One of the few things I accomplished was to improve the slow Excel macros. Version 1 first sorted the list and then used a binary lookup to make it many, many, times faster as the lists were large. The second version skipped macros altogether and used a binary tree in C to translate flat text files.


When: mid 90s


Lessons learned:



  • Marketing people don't understand programmers. They insisted on translating Visual Basic for Applications. if then/else is a 'universal' language as far as I'm concerned. At least they had the common sense not to repeat the mistake with the more serious languages.

  • The Dutch make lasagna with bananas (!) and the Irish serve French Fries with theirs

  • You can learn a lot from Dr. Dobbs

Thursday, September 16, 2004

203.aspx

An even wetter Wednesday

The soft rain continued so we decided to go to Firenze. Long queues in front of the most famous museums like 'Galleria di Uffizi'. Or at least they looked long to me. I was told the can get many times longer during high season. Got a great view from piazza Michelangiolo, but all things considered I wasn't impressed with Firenze. It's a big town and the country side in Toscana has more to offer if you ask me. Guess I had too high expectations going there.


Nice places attract tourists which in turn attract illegal parking attendants (don't pay anybody, use the automatic ticket machines) and pick pockets (one backpack opened but nothing important stolen as the valuables were well hidden). I just can't help it: thieves bug me in a major way. The pick pockets reminded me of something I saw in an English TV series decades ago: a guy had fastened fish hooks inside his jacket pocket. Put the hand in the wrong pocket and you're stuck. Wonder if it is legal to go 'fishing' like this in Italy? Guess it's safer not to though: catch the wrong fish and you could wake up with the head of a horse in bed...


(Update: formatting changes)