Tail recursion woes Friday, 20 November 2009  
Dr. Dobbs article

This is driving me nuts. GCC does tail recursion optimisation. That is very nice, and means that if we have something like:

int func(...)

func2(...); }

then the func2() call can be converted into a 'goto'.

The problem is that this means that if we put a breakpoint in gdb, or a printf, in the func2, we lose the stack frame for func(), and it appears that func2 is being called from the caller of func(), rather than func() itself.

I wish they wouldnt do these "nice" things. Makes debugging a pain, and am tempted to go back to earlier/very old versions of GCC to stop this warfare, where "what used to work", stops working and you have to fight the toolchain.

Posted at 21:42:29 by Paul Fox | Permalink
  Motif finishing up Friday, 20 November 2009  
After my last write up, of finishing the Motif rewrite for CRiSP, I have made more progress. This centers around the things I had forgotten.

For example, the 'Scale' widget which is used in the color selector dialog needed to be implemented (from scratch). That took about a day (nice when things go according to plan).

Then I hit some issues with the default size of a combo field. That is fixed.

Next up was the protocol manager for a shell widget. What is that you say? Think of XmAddWMProtocolCallback(). Without this, if you click on the window manager "X" at the top right of a window, then your app is quickly terminated (the TCP connection to the X server is severed).

Took me a while to figure out / remember how this all worked. But, suffice to say, that unless you post an Atom/Property on the window (WM_DELETE_WINDOW), then the window manager will not ask politely, but just brute force the termination of the app.

But to put a property on the application shell window is not quite so easy, especially when we normally call the XmAddWMProtocolCallback() against a *widget* and not a *window*. A widget may not exist on screen at the time we call it, and that is why there is complexity in the Motif library - you are allowed to register interest in these window manager protocol messages, before the window is 'realised' (i.e. before being mapped to the screen). When the window is mapped, the appropriate property is posted on the desktop to allow the window manager to see what is going on.

Of course, if you try to do something "later" in an application means creating some form of data structure for later use, and then, making sure we dont suffer a memory leak.

My implementation of window manager protocols isnt perfect, but sufficient for what I need.

Why do I bother? I dont know, but what I know is that CRiSP with Motif, statically linked, occupies 3MB of code memory. With the new Motif replacement, it is about 2MB.

When CRiSP was first written this was about the size of a large floppy disk (and 40MB - thats megabytes, not gigabytes) was huge. Now the size of CRiSP fits in the L2/L3 cache of a cpu.

Posted at 20:40:52 by Paul Fox | Permalink
  Menu updates Sunday, 15 November 2009  
My experiments to replace the Motif library code in CRiSP with native code hit a major stumbling block. The first few days of effort were extremely good - lots of progress and deterministic behavior.

But the menuing code has taken about 3 months - I hope this is now complete. Why?

Any number of reasons:

  • I am losing my 'touch'
  • It is difficult
  • There are lots of fiddly bits to get right

You choose. The issue with menus is the way input focus moves around from one widget to another. There are lots of scenarios to get right, and fixing one of them, would result in some existing feature suddenly breaking - like a see-saw as the code came together.

One problem I hit is that XtAddGrab/XtRemoveGrab doesnt handle double registration of a widget particularly well.

The code, whilst trying to be purist and object oriented, in the end had to be a little dirty - one class having too much intimate knowledge of what it is dealing with (a menu has menu items, which is mostly separators and buttons, for instance).

Heres some scenarios to consider:

  • Click and reclick the menu bar button (should dismiss menu)
  • Use keyboard to navigate a menu and popup sub menus, and then popdown submenus.
  • Use ESC to popdown a menu
  • Click outside the menu to dismiss it; click in another window to dismiss it too
  • Click on a menu item, and have the menu popdown, and the callback invoked

May seem like simple stuff, but getting it all working is difficult, especially when grabs are put in place - suddenly input goes to the wrong widget, and everything you had working, stops working.

Why bother ? Why not just use Qt or Gtk ?

Because I dont want to use them. As good as those toolkits are, they are not available everywhere, and I dont want dependencies on other toolkits - toolkits which have a very active development life.

This is akin to the dtrace problem: do you develop software for the latest and greatest kernel/distro out there, or do you go back to old releases and ensure your software works with them?

Posted at 18:51:03 by Paul Fox | Permalink