I've been doing some tweaks lately to further polish Iconographer (this is what version 1.0 should have been, but I kind of rushed it in the end, as in 1.0a1 got turned into the final release). For example, towards the end of summer I added an option to use the Windows system palette (as opposed to the Mac one) when dealing with 4-bit icons (a user had requested this). However, after I implemented the basic functionality, I totally forgot about hooking it up to the rest of the interface (as in, the command couldn't be undone, icons weren't converted automatically when saving one with the windows colors in the mac format, etc.) A couple of weeks ago someone complained about the windows -> mac color issue, so I implemented a quick fix for it. However, this last week while I was trying to figure out why people were reporting crashes when converting icons, I discovered that the app would crash all the time now when converting between mac and windows 4-bit icons. As it turned out the quick-fix wasn't the root of my problems, it was just another thing that I had induced recently. That's also when I realized the problem that I had with not being to undo the command.
I realized that implementing the undo wasn't quite as easy, since I was creating a totally new
PixMap with a new color table and disposing of the old one. Until now, each saved drawing state had stored with it the name, pointer to the
GWorld and handle to the
PixMap that were being saved (and thus should be eventually restored to). But now that I couldn't depend on the pointers and handles remaining unchanged, I had to figure out another way of deciding where to restore the saved data (which by the way is compressed, I realized that I could reuse the icon compression code to save space (e.g. a 6K blank canvas is now around 800 bytes, for fancier drawings the final size is usually still smaller than 3K)). I realized that the name could also give me pointer and handle, with a simple case statement. So I added a
GetGWorldAndPixMap method to the icnsEditorClass and everything seemed to work (that is I could draw something in the 4-bit icon, convert it to windows colors, draw some more, and then undo all the way back to when it used the mac os colors). However, I ran into a very weird bug. If I undid it all the way back to the original blank canvas created when making a new icon, redo wouldn't work properly. When getting to the 4-bit icon, it would pause for a while, and eventually the canvas would be partially the color of the desktop, and otherwise empty. What was even more annoying was that I couldn't get this to happen all the time. After setting some breakpoints, I discovered that the
GetGWorldAndPixMap function I had mentioned before was returning NULL. However, it covered all the possible cases of the names, and adding a default case didn't help (it didn't get called with it). After much annoyance, I finally discovered the source of the problem. When I was saving the initial state (the blank icon created at the beginning), the
colors variable (which determined which palette to use, the mac or windows one) was uninitialized, and thus when attempting to restore the state the color conversion function would screw up, which would set into motion another weird chain of events. The fix simply required to swap the order of two lines. I'm not really sure what I could have done, I guess the CodeWarrior pre-processor isn't quite smart enough yet to discover usage of uninitialized variables when it happens across classes and files.