Ressurection #

This was the first program that I released publically, it's a simple tool to insert 'cicn' (color icon) resources into Kaleidoscope schemes (Kaleidoscope uses 'cicn's as its primary storage method, and the editor that ResEdit provides is limited (can't create icons with a size bigger than 64 x 64, can't import custom color tables) and broken (it thinks resources with a size above 32K are corrupted), so I made this free insertion tool (this is all happened in the beginning of the summer of 1998). Since then it had been pretty much left alone, since it seemed to cover everyone's needs, and as a freeware niche product it had no competition and I had no incentive to add features. After I had finished the initial work on Icon Mangler (as Iconographer was then known) I decided that it had fallen behind enough that it needed an upgrade (I had created a similar program, clip2icns, designed to insert and extract 32-bit icons, this one was shareware and did have competition so it was updated more often), so I merged the source code, so that it could have the UI-style that I had create for clip2icns. I had started on this in April, but got distracted after a few days, and forgot about the whole program until I got back from Stanford in August. Then someone asked me if I could fix a bug in it, and I realized that the new version that I had been working on had that fixed, so I finished it up and released it. I had thought that this would have been the end of it, especially since I gave the source code to some else who was working on a full Kaleidoscope editor.

Then last week someone contacted me about adding a feature (extracting 'cicn's to the clipboard, essentially the opposite of the current command which took the clipboard and put it in a 'cicn' resource). Considering that clip2icns already had a similar feature, and that Iconographer included full copy and paste support, I figured that I knew enough about the Scrap Manager (that's what's used to manage the clipboard) to do this. I opened up the clip2cicn CodeWarrior and its associated resource file, and added an Extract button to the dialog (this required a reorganization of the dialog layout, since it was getting rather wide) and then the relevant code so that it would beep when clicked (as a place holder for the eventual cicn2clip funnction). Then when I tried to compile and run it, I discovered that I got all these errors about functions that didn't exist in my commonFunctions.c shared file. Then I remembered that I had begun to convert my code to Carbon (which makes some structures, e.g. dialogs and controls), and so some of those functions didn't work with the standard Toolbox. In the end I had to create a special version of the Universal Headers (I have them precompiled so compile times are faster) with the Carbon flags turned off, and include that in clip2cicn. After this little hidrance, I implemented a basic version of the cicn2clip function. My main problem was that the resource contained a normal PixMap, but I couldn't use CopyBits with it, since the pointer to the pixel data was screwed up (when the PixMap is stored, the pointer becomes meaningless, since chances are very small that it'll be loaded in the exact same location in memory). I used the function PlotCIcon to draw it into a 32-bit GWorld, and the exported that to the clipboard. I sent off the new version to the user who had requested the feature, and he liked it, except that I wasn't extracting the custom color table. In the end I figured out how to fix the pixel data pointer (the 'cicn' handle included a part where the icon data was stored, so I set the pointer to the address of the resource plus the offset to the pixel data), and did a CopyBits straight from the icon into the picture I was putting in the clipboard, and that seems to work perfectly. Another user also asked me to fix/add some IDs in the pop-up menus I provide for the easy selection of the 'cicn' that should be inserted/extracted, so I did that too.

And now that I think about it the person I gave the source code to still hasn't done anything with it. I guess the moral of this long-winded, not-very-interesting story is that you should never throw any code away, or give up any project for dead.

Floating and Gloating #

Activity in this project is starting to resurge after a somewhat long break. Up until last week it was up to the point where I had started on several things, but hadn't finished them, and still had a bunch of stuff planned for version 1.1. First of all, there was the support for the 256 color Windows system palette. My main problem here was finding what the standard palette was. I downloaded three or four icon Windows icon editos, and looked at the palettes they used for their 256 color mode, and they were all different. This wasn't such a big issue as it would have been on the Mac, since Windows icons can include a custom palette, but there would have been no point if several of the supposedly standard colors were actually dithered when displayed in 256 colors. In the end I got that what the Eudora team used as the standard colors (at least according to Arlo), assuming that they knew what they were doing. Actually implementing this palette wasn't that hard, since I already had support for the 4-bit windows one, so it was a matter of marking the 8-bit depth as supporting the windows colors too, getting the color picker picture (my color picking function takes a picture as its parameter, it doesn't care what colors are actually contained and how they're arranged as long as they're divide by a special colors (0x01, 0x00, 0x00)) and making the Windows .ICO loading function use these new colors.

Then I worked on finishing up the new icon browser (the Finder-like list of all the icon resources contained within a file). I had started to allow it to use the arrow keys to scroll through the list, but I wasn't actually scrolling down when the user went below/above the icon visible at the current scrolling level. Also, if a user double-clicked on an icon that was already open, it would open up a new window instead of bringing to front the current one.

Then I worked on adding a Windows menu. I didn't really see it as being necessary, usually people edit one or two icons, and don't need a menu to toggle between them. The main reason I did this was to have a place from where the colors palette (see next paragraph) could be shown and hidden. I realized that I needed a way to attach a menu command to a certain editor that was open. I decided to assign each editor an ID when created (it would be released when closed), and then store the ID inside the menu (menu items can contain a user defined reference number), so that when a menu is selected I can get the ID, look up the editor and bring its window to the front. One of the more tricky things here was that I wanted the icon editors and icon browsers to be separated by a divider, and I didn't want any floating windows to be listed. In the end I used the the window type attribute of the window class to differentiate between them.

Afterwards I finally started to work on the floating color palette, since this is the last big thing before I can release version 1.1. Mac OS 8.5 and above include built-in support for floating windows (well, technically anyway, practically the implmentation in 8.5 is completely broken, and only 8.6 and above works), but that would have been too steep a requirement, since the rest of the program works with 8.0 and above. However implementing floating windows on older versions requires some kludging. The main problem is that you have to have more than one window active (all the floaters, and front most document window). The standard Mac OS Toolbox functions, such as SelectWindow automatically disable the other windows when they're called. You have to use lower level functions such as BringToFront, SendBehind, and HiliteWindow to perform window manipulation. Also, getting the front-most window can't be done with FrontWindow, since the floaters are above everything else. This is where it become very advantageous that I had decided to use classes for each window (I have a MWindow class, and the icon editor, icon browser and floaters are all derived from it). I added some static functions to the MWindow class (so that they didn't require an instance to be called) to replace all the standard Toolbox functions that I had used so far. I also had to add additional calls since the floaters have to be hidden when the application is put in the background. The current status is that I have a floater which can be hidden or shown at will, and actually behaves as a floater. It doesn't have anything in it yet (it just beeps when clicked on, as a simple test that it can handle events).

As I was testing the floater implementation, I discovered some positioning problems. For the icon info dialog that's displayed, I set the "Center on parent window" bit. The parent window is determined as the window that was previously in the front, but the system does this for me, so it has no way of knowing that I don't want the floater to be considered as the actual front-most window. I added a CenterOnParent function to the MWindow class, so I used that to manually align the info window. However then I discovered that this problem extended to the "Do you want to save" dialog too, but here I can't tweak the position by hand, since I use a system function, StandardAlert to generate it. In the end I guess I'll have to rewrite the function myself, to make it center properly. I kinda had to do this anyway, since I couldn't use it to display the "You don't have the Appearance Manager installed" alert (the function is a part of the Appearance Manager), so things should be quite beneficial.

On a separate note, it greatly amuses me to see that Icon Factory are finally releasing the Pro version of their IconBuilder product (competition to my earlier 32-bit icon insertion tool, theirs is a $49 Photoshop plug-in vs. my $10 one-shot utility), with supports 48 x 48 icons and Windows importing and exporting. They promised this in Q2 1999, so they're a bit behind :p And of course, Iconographer has had these features since it was released (mid September 1999), along with a $15 price tag (their Pro version will cost extra), Photoshop integration, Mac OS X Server importing, etc.

JavaScript and Dates #

Heh, looks like I'm spending more time on the project than any of my other ones, and technically it's not even a programming class one (it's for InfoTech). But I guess this is mainly because it's something I use myself (the whole checking mail through a proxy/at school thing), so if it's an unstable/unusable state I feel it immediately. I've also noticed that the closer I get to making Grendel similar to the Netscape mail client, the less reluctant I get to download the mail locally and read it there. The current situation is that I read about half of my mail with Grendel, and then when I download I quickly page through it since I've seen it before. When I add the MIME parsing (for things like HTML mail and attachments) it'll prolly be even more tempting. However, even if I were to add things like local message storage (as in, getting the mail from the POP server and storing it somewhere in the cgi-bin directory) with message filtering, etc. I'm not so sure I want to use it as my primary email client. The perfect situation would be if the Netscape mail reader were to observe that certain messages were already marked as read on the server, so it shouldn't flag them as being new when downloading them.

The main thing that I've done with Grendel was do implement the hybrid JavaScript/Perl system. When getting the messages from the server, the script generates a JavaScript which creates new JavaScript objects like this:


print <<EOF
messages[$messageNo] = new Message($messageNo,
                                   "$headers{'Status'}",
                                   "$headers{'Subject'}",
                                   "$address",
                                   "$name",
                                   "$date");
EOF

which results in JavaScript code like this:

messages[2] = new Message(2,
                          "U",
                          "Re: 10,000 Triangles, 18 msec",
                          "hberriot@club-internet.fr", "Herv� BERRIOT",
                          "Sun, 12 Dec 1999 04:56:36 GMT-0800");

Then I have a local (on the user's side) array of JavaScript objects (the Message object is defined by me, JavaScript is object oriented, and close enough to C++ that learning it isn't very hard) which store all the messages (well, not quite, I don't have the message body too, that's only requested when the user asks for a message to read). To display them, I simply loop over them and call their Display method. The idea here is that if I want to change the sorting method (not implemented yet, but soon will be, after I learn how QuickSort works), I can do all of it locally, instead of having to go through the server. Things like deleting messages are faster too. Instead of having to get the new message list from the server, I can delete the specified array memeber locally, and then tell the server which messages has been deleted, and update the message view page with the next one.

I wasn't quite sure where to store all these JavaScript objects. I couldn't put them in the list frame, since that gets cleared when refreshing the message list. At first I thought I should put them in an invisible frame, and the things like rechecking the mail would simply reload that list. The main problem was that the invisible frame wasn't quite so invisible, since the border would still show. Then, when I was making a simple change and saving it to the server, the FTP process screwed up, and the local app crashed (this was on a PC). The end result was that the copy on the server was completely empty, and I had no loal copy (the text editor I was using supported direct save to FTP). The good thing was that I had saved a backup copy before doing the hybrid system, so I got to start again. This time I decided that I should store the objects in the buttons frame, since it didn't get reloaded or cleared.

The other big thing I did this week was to add parsing of the message timestamps. Now they are converted to the local user's time, whatever it might be. This is done with JavaScript, since it has a built-in date string parsing function (whereas Perl requires a third-party module, and I want Grendel to be as self-contained as possible), and Perl wouldn't have been able to do the automatic local time conversion anyway, since it's executed on the server. In the end, things worked pretty well, I added special cases for dates that were on the same day as today, the day before, and within the past week. My main problem now is that Netscape and Internet Explorer seem to behave differently when handling dates, that is Netscape seems to shift everything back by one (since I first implemented this at school, where I use IE, I'm assuming that Netscape is wrong). I'm not quite sure, the simple fix would be of course to add a an if statement to increase the date by one if netscape is detected, but I was hoping for a universal script, especially since JavaScript is supposed to be standardized.

I have a few of simpler things planned for Grendel, before I decide if I want to implement the local message storage or move on to something else. First of all, I want to add cookie support, so that it can remember the login/password combo for me at home. To edit that setting, I'll have to add a user settings page, where users can also change their POP server, password, etc. On the topic of passwords, Grendel as a whole isn't very secure yet. If someone were to go through the history at school and get the address for my message list, they could access it (my username and password (in a mangled form so that it's not immediately readable) are in the address string). Right now I'm thinking of using temporary cookies (which expire when the user quits the browser) to set when the user logs in, and the username/password validation would also check for the presence of those cookies. Another thing which I want to add is automatic mail checking. I can see how I could use a small toolbar/scrollbar/statusbar-less window which refreshes itself automatically every minute (or whatever the user prefers) and checks to see if there's new mail. If there is, it can play a sound, bring up an alert, or just start flashing, and when the user clicks on it grendel is brought to the foreground or started up if not alreay there. There's also the MIME parsing that I mentioned earlier, ideally with in-line viewing for images or things which the browser has plug-ins for. Finally, I want to add another column to the message view listing the message size, but so far that doesn't seem to be in the headers, and I don't want to download a whole message just to get its size, so I'll have to see about that.

Revulsion #

I really, really want to rewrite the whole application. I was adding more generic support for multiple formats, and it got really ugly. In the first place, I didn't foresee that it'll support multiple formats (the Windows and Mac OS X Server import/export stuff was added over the summer), and now that I treat the pre and post Mac OS 8.5 icon formats differently too, things are even messier. On the surface things look fine, so I think I'll manage to get version 1.1 in a resonable state and release it. However, I'm not sure if the fancier stuff like the floating color palette windows (which are torn off from the color picker) will make it. I guess the best thing would be to use Meshroom and the Apple icon thing (I just wrote to them, the idea of doing what they want as a separate application was favorably received, it's just that they (well the lawyers) want a stupid name like Apple Icon Tool, I proposed Apple Icon Assembler, since that's pretty much what it does) to improve MFrame (e.g. add built-in support for controls, floating windows, and a new way to handle icons, since Mac OS X introduces a new format of it's own, and there's still the Windows one too (they want to discourage people from using the Mac OS X Server one, so I'll just have TIFF importing)) and then use it to do a new version of Iconographer (2.0? perhaps). The thing is, this will probaly end up taking a while, and I still want to do interim releases of Iconographer, because otherwise people will simply think I dropped it. I guess I'll try to make the new features as modular as possible, so that they can be dropped into either version. Now that I'm done with the college applications, doing all this seems actually feasible :p

Who needs a database? #

I've started to work on the new user architecture. Now the users file (grendel.info) looks something like this:

user@example.com
server=mail.example.com
port=110
username=user
encryptedPassword=$1$Aa$N.1.KcWzIorULwFN/EgMA/
externalLinks=_top

This means that I'm able to check both my mscape.com and my AT&T WorldNet accounts, by simply signing in with the appropriate email address and password (I'm using the email address since it's the only thing which I could depend on to be unique and be easily remember, since a POP user name@POP Server scheme would have been harder to remember if, like in the case of my mscape.com account, the POP server is different from the server part of the address. You can also see that my two password are the same, since they yield the same encrypted string, but it still doesn't help you in figuring out what they are (this is what I was talking about before, when I was saying that I'm not actually storing the password on the server). What remains to be done is to implement a way for new users to sig-in, and then grendel is actually usable to people besides me.

I've also gotten the message deletion to work. In the end it turned out to be a very stupid thing. Since Perl is very flexible, it doesn't balk when you try to do things which would never get past the compilers of other languages. In my case, I had a function called POPLogIn, but when I called it, I spelled it as PopLogIn (Perl being case sensitive). Fixing it was obviously trivial. Now I can finally pre-emptively delete spam so that it never reaches my Netscape Messenger Inbox (perhaps in the future I'll add message filtering too, since Perl supports run-time creation and evaluation of regular expressions (pattern matching tools, like the thing I showed before which extracted the email address and name out of the From: field), but that's some ways out).

Drivers and Selections #

First of all, I'm happy to say that 3dfx has released OpenGL drivers for my Voodoo3 card, which unlike the Mesa (an open-source implementation of OpenGL for almost all platforms) drivers that I was using until now, support windowed rendering, so Meshroom is now accelerated. There's still some bugs (points aren't drawn, I'll have to make a simple program to see if they're not drawn at all, of if it's just a context thing in my program), and some other things I've observed when running some sample programs, but overall life is good. For unsupported software (the whole Voodoo3-on-a-Mac thing is unsupported, I'm guessing they're using this as a way to familiarize themselves with the Mac platform in anticipation of their next product, where it'll be official) this is getting pretty good too.

Other than that, I've started to work on implementing selections (as in, you can click on an object in the 3D view, and it'll be selected by showing it's bounding box with the corner handles). So far it's working pretty well, except I have to do some better parsing of the selection data that OpenGL returns to me (it gives me all the objects which occur at that point, even if they are hidden behind others, so I should parse the array and select the front-most one, but things get a bit more complicated when you have objects completely contained within one another). I'm also wondering whether I should implement multiple selections or not, in the end I guess I will, because it's more dynamic data structures for the IB, but I might wait until I make the switch to the Mac interface (I'm still using GLUT to prototype the underlying architecture, although making the initial switch shouldn't be that hard, things will get more complicated when I implement the proper UI, with the four views (top, left, front, and a 3D camera view) and the editing tools (this will probably require me to implement controls to the MFrame (my application framework), so far (in Iconographer) I've been implementing them by hand, but this doesn't go well with the whole flexible approach that I'm using with the factory method). Right now I'm thinking of having each control have an unique (four letter of course) code, and a pointer to the class which owns it, or a static function of it (e.g. the sphere tool would point to the sphere class), and each class would also include a method for initially loading the controls, etc.

Breaking Lines #

Something came up which prevented me from moving on to the new user log-in thing that I had planned before. So far, I've been using <PRE> </PRE> tags to delimit the message body, so that the spacing within it would be retained (HTML ignores more than two consecutive spaces, line breaks, tabs, etc.). However, I realized that this screwed up line wrapping (as in, if a line was longer than the width of the window, neither Netscape nor Internet Explorer would wrap it). In the end I decided I had to convert the message body to HTML too, since only then would the wrapping work. Converting line breaks and tabs was easy, it involved a simple substitution. However, I had problems with whitespace made out of the ' ' character. The closest HTML entity to it which isn't ignored when there's more tha none is &nbsp;, but that's a non-breakable space so I couldn't simply globally substitute &nbsp; for ' ', instead I would have to find places where there were two or more and then substitute for it. In the end, this yielded the following code:

while ($line =~ /( {2,})/)
{
	local($spaces) = '&nbsp;' x length($1);
	$line =~ s/$1/$spaces/; 
}

This can be interpreted as "while there are spaces surrounded by non-space characters and the length of the spaces is 2 or more, substitute the spaces by the string '&nbsp;' repeated as many times as there are spaces"

Another thing which I did that wasn't in the schedule was to deal with multiple recipients. The To: field can have multiple addresses in it, separated by commas and or line breaks. The realization that headers can be split across multiple lines caused me some problems, because I couldn't simply use the split to divide up each line into the key (the field name, e.g. From) and the contents (e.g. "User Foo <user@example.com>") by using ":" as the delimitor. Now I loop through each of the line, look for a <string:>:<string> pattern, if I find it I insert it into the headers associative array (basically, a hash table) and if I don't it append it to the entry of the previous field that I found. As for the multiple recipients themselves, I divide up the string by using the comma as the delimiter, and then use the name/address splitter function that I did earlier on each address.

I then wanted to move on to the delete function, and I got it to the point where it does actually delete messages (good for pre-emptive spam removal, that way I don't have to download them in my Inbox), but I'm still not getting it to refresh the message list or the message that's being displayed in the message view frame.

Template-based factory #

I'd mentioned earlier that I had implemented cameras unsing a factory method, and that it mostly required copying and pasting the object factory code and doing a search and replace, and that I would have to do a similar thing for the lights when I implemented them, and so it would be best if I could find a generic method (using templates) of implementing a factory for any kind of object. Well, on Wednesday I finally did this, and now the code is quite elegant. The Model3D class (which as its name suggests is used to take care of an entire model) has the following members:

public:

	...

	static MFactoryDatabase	objectDatabase;
	static MFactoryDatabase	cameraDatabase;
		
private:
	
	MFactory<Object3D>	objectFactory;
	MFactory<Camera3D>	cameraFactory;

pretty factories and boxesThe factory object uses a database (which is passed to it as a constructor parameter) and when asked for an object (through a four letter code) it finds the instatiator in the database, runs it, and inserts the new object into the (double) linked list inside it. To take care of object IDs and and previous/next pointers, an additional MFactoryObject class is required. It is assumed that all objects which the factory is designed to produce are derived from this one.

The separation of the factory from the database is quite logical. Each instance of the factory class must maintain its own linked list, while the object database should be shared across all objects (hence the static keyword). Making the database a static member of the MFactory class would not have worked since then the camera and object factory would have the same database, and then you couldn't tell in which one an object belonged.

Other than this, I've also added bounding boxes. This is a first step towards selections (when selected an object will display its bounding box and resize handles). It involved adding GetBoundingBox method to the base class which returns 2 3D points (for opposing corners of the parallelipiped), and then implementing it for each of the derived classes (the torus took a while, since it turns out that the z coordinate for it is constant, no matter what the inner and outer radii is, and for the teapot I didn't have the actual dimensions (the glutSolidTeapot function takes only a generic scale as a parameter) so I had to guess them, run the programs and tweak them). Then the Display method uses the returned values to draw the box. The picture is what the whole thing looks like right now.

Best of Both Worlds #

Nothing that special to say, except that I've started on the hybrid JavaScript/Perl solution. For example, I've added Next and Previous buttons. Since I use frames, I need a way for the buttons frame to determine which message the message view frame is showing and then move on the next one while also marking it as read in the message list. JavaScript makes this a lot easier, since a frame can access another frame's variables (since in this case they're siblings). So I simply store the ID of the current message as a variable in the message frame, and then get it in the buttons frame, increment/decrement it, and then call the Read function of the list frame with the new ID. This function (which is also used when clicking on a message in the list) sets the contents of the message view frame as appropriate and changes the image next to the message subject to reflect that it's read. I'm planning to implement a delete button in a similar way (except that the list will have to be completely reloaded for now, since I don't generate it from within JavaScript yet).

After the delete button is in, I want to add a new way to login and cookies. Although the current user info only allows me in (the user data isn't hard-coded, it's loaded from a file, but there's no way to edit it), ideally I wish for people to be able to set up an account, where they specify their email address, pop server, user name and password, and then they can log in with the email address (not the username, since it's not unique, e.g. 'mihai' at the pop3 server 'mail71.pair.com' is different from 'mihai' at the server 'mail.att.ne.jp') and password and have access to their email. Also on the same topic, I want the option of cookies to that people don't have to type in the email address/password all the time. This might not make sense when grendel is supposed to be an 'email-anywhere' web-application, but it's useful for those like me who also want to access their mail from behind a proxy and thus use their own computer (saving the username/password on a public computer isn't too good security-wise) but still need to use Grendel.

The full JavaScript-based threaded/sorted view of the message list will come later, since that's not a big a requirement as this (at least from my point of view, I'm getting tired of having to type in my name and password when checking my mail). Plus the new system will allow others to see on their what I'm up to (there ought to be no security worries, I store the password on the server in an encrypted form, and all I do when the user enters his password is compare the encrypted version of his with the encrypted version on the server, and if they're the same I allow the user in, this is the same system used by UNIX, and it makes sense because the administrator (or anyone else who has access to the password file) can't get all the password used in a system by simply looking at the password file).

Undo Tweaks #

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.

You're on Object3D Camera #

I've added camera support, so that the camera placement is loaded from the scene file as well. I support two kinds of cameras, perspective (which cause perspective distortions, e.g. parallel lines appear to converge) and orthographic (no distortion, used in architecture sketches to maintain proportion, etc.). Since cameras are treated differently from objects (they're not rendered, etc.) I can't store them in the same linked list, and thus I ended up having to copy and paste the functions and variables used to implement the factory method for the objects and replace all the occurrences of 'Object3D' with 'Camera3D' (the Camera3D class is still based on the Object3D class, but it itself serves as a base, for the PerspectiveCamera3D and OrthographicCamera3D objects). Obvviously this isn't the best way to go (and when I add lights, this would require another set of of linked lists and factory) so I'm thinking of using templates somehow to create a generic way of implementing the factory method. This ought to be fun, but I need some time to think about how this will work.

On a somewhat related note (i.e. also 3D related), a couple of days ago I found this cool OpenGL game (although it's more like a demo now, since you can't do that much except fly around) called glUFO. From the screenshots it looked really cool, except that it was for Windows. Fortunately, the source code was provided, and as it turned out the author used GLUT (Graphics Library Utility Toolkit) for the user-interface, so I figured I should try to port it. The first problem was that the author used GLUT 3.7 (a.k.a. GameGLUT, since it includes a bunch of functions for setting the resolution, etc. which are useful for games) which hasn't been ported yet to the Mac. Then I had to redo the key handling, since he'd used Windows specific code there (GLUT only supports one key down at a time, and provides no way to detect if a certain key has been released). This involved adding some #define's (my goal here was to modify the source code as little as possible, so most of the modifications were made in the header files) to map the KEY_DOWN macro to the appropriate function. Then I had to find all the key-codes, and #define their Mac counterparts. Finally, there were a bunch of compiler errors with the function calls, mostly that he'd define function a as 'void a(int)' and then called it with 'a();'. I guess Visual C++ is more forgiving than CodeWarrior, but fixing them didn't take that long.

Now the program finally compiled, but it would quit immediately. The fix for this was rather simple, I had forgotten to actually create a window to display the game in. The program then worked, except it was very slow. However, this was as expected, since I was using the software renderer. I added the fullscreen flag to the initialization options, so that the 3D accelerator would kick-in (the current drivers only support full-screen acceleration, although the hardware itself can do windowed rendering). To my dismay, nothing showed up on the screen. The main problem here is that since I was working in full-screen mode, it was very hard to debug. I obviously couldn't switch in to the Metrowerks debugger, but even MacsBug wouldn't display anything (the screen would go gray, but no text would show up on the screen). With a set of Debugger (which invokes the current debugger, whatever it may be) calls placed at various points throughout the code, and the use of the StdLog (which logs, among other things, the name of the current function) command typed blindly into MacsBug, I was able to determine that the code was indeed entering the main execution loop. After examining the code more carefully, I discovered a commented out call to glutPostRedisplay (which causes the display to be redrawn) in the idle function. After uncommenting this, and modifying the display function a bit, I finally got the app to show something on the screen. My theory is that when in software mode, the window was redrawn automatically the first time, but in full screen mode it wasn't, so I had to call it myself.

Although there was finally something on the screen, things still weren't quite right. The coulds, exhaust and bullets would show up as black rectangles, sign that there was something wrong with the transparency, and the mountains weren't textured at all. Fixing the transparency involved changing the destination alpha (the alpha channel being the transparency channel in an RGBA environment) from GL_DST_ALPHA to GL_ONE_MINUS_SRC_ALPHA. I guess the destination alpha was one value by default in software mode, and another when the 3D accelerator was enabled. The problem with the texture took me a while to figure out. As I was reading the release notes for the program, I saw something about Voodoo cards only being able to handle 256 x 256 textures (I already knew this) and that thus the 1024 x 1024 ground texture will appear rather blurry. I thought that perhaps the Mac driver, being still in development, doesn't do any scaling to make the textures fit, and rather simply rejetecs. I opened up the texture file in Photoshop (it was in a raw format) and scaled it down to 256 by 256. Finally, that worked too, and I was able to play around with the program as expected. If I can get it into a stable state (there's still some more issues with one other texture) I'll see about submitting the changes and the executable back to the author, so that he can provide a Mac version too.

Files #

Nothing earth-shattering happening here, but I'm slowly making everything come together. In version 1.0, the open menu item had a sub-menu, with three choices for each of the formats that Iconographer could open (Mac OS, Windows and Mac OS X icons). This was messy, both code-wise (since I had three very similar sets of functions) and user interface-wise (since the user had to know in advance what kind of file s/he wanted to open). The reason why I did this in the first place is because the Mac OS open dialog had to allow you to open folders as well, since folders can have icons too. For some reason I thought that this variant of the open dialog (NavChooseObject) couldn't be customized, so I couldn't add a pop-up menu with the format selections. Now that I've realized this, I've ripped out the old code and now I have a much cleaner way of handling files. The only thing remaining is to do the same for the old-style file open dialog. This is rather annoying actually, since all the StandardFile code will be obsolete with Carbon, and it has a totally different way of customizing the dialogs.

Also on the topic of file-handling, some people are reporting crashes when saving, and I can't reproduce them. I might have to resort to a clean-install, or perhaps trying to open and save a bunch of files.

Web Everywhere #

As it should no doubt be visible, I've changed the style of the journal. Now I'm using a CGI backend. This solves a few problems: people looking at it don't have to wait for everything to load, if they're only interested in a specific entry, and I don't have to upload a 35K (and growing file) for each change I make. Eventually, I'll make it so I can edit it online too, and then uploading will be just for pictures.

As it's no doubt visible, I'm staring make a lot of things with a Web-based interface (well, first there's Grendel, and now this). I guess the idea is that you can have access to a web browser almost anywhere, whereas your home setup might be miles away. It's not quite Constellation (Netscape's idea of a few years ago to have a Web desktop, whose contents would be stored on the server, thus accessible from anyhwere, with HTML/Java based apps), but it's good enough for my needs. When I have my own server in college (most likely a Qube) I should be able to do a lot more experiments. For more on using a web browser to create and edit content, see this DaveNet piece (among others on the same topic).

Perl: The Write-Only Language #

I've added extraction of email addresses (so that "User Foo <user@example.com>" is split up, and also variants of the form "user@example.com (User Foo)"). The code for this looks something like this:

if ($header =~ /^\s*([^<]*)<([^>]*)>\s*$/)
{
	$name = $1;
	$address = $2;
}
elsif ($header =~ /^\s*([^(]*)\(([^)]*)\)\s*$/)
{
	$address = $1;
	$name = $2;
}

Before I started to learn Perl, I said (to my dad, who uses (and likes it) a lot) that most Perl code it looks like someone held shift down and ran his fingers across the top and right side of the keyboard, and it looks like I wasn't far from the truth. But regular expressions (which are the statements to the right of the =~) are really cool, they let you do things which would take ages in C/C++ (actually the perl regexp engine is available as a C++ class too, but from what I heard the interface isn't that nice).

Other than that, I added the option to make the quoted part of a message appear in a different style (in my case, italics, and in a shade of gray). For the rest of the things that I have planned (threading, and sorting by the various columns) I have an idea of how I'm going to do it. Since they (especially sorting) simply require for the data to be arranged in a different way, it makes no sense to go back through the server to do this, instead, I can use JavaScript. So the plan is to have the Perl-based CGI backend to go generate a JavaScript script (which will mostly mean placing the header data within place-holders in the script) and then having the browser execute that script. When the user chooses a different sorting order, the JavaScript is executed again, with different parameters of course, but the server isn't involved at all. I'm also planning to use JavaScript for some of the other features, like having an automatic mail check option and for advancing through the messages (in the form of Next and Previous buttons in the toolbar at the top).

Coding Begins #

I've finally started to code. So far I'm doing the things I've spec'ed out. This basically means that I'm loading basic objects (spheres, teapots, cones, tori, and cubes) and displaying them. To give an example, the following file:

Sphr
0.0 0.0 0.0
0.0 0.0 0.0
1.0 1.0 1.0
1.0

Cone
-3.0 0.0 0.0
0.0 0.0 0.0
1.0 1.0 1.0
1.0 2.0

Tpot
3.0 0.0 0.0
0.0 0.0 0.0
1.0 1.0 1.0
1.0

Tors
0.0 3.0 0.0
0.0 0.0 0.0
1.0 1.0 1.0
1.0 2.0

Cube
0.0 -3.0 0.0
0.0 0.0 0.0
1.0 1.0 1.0
2.0

Meshroom Screenshot This results in the picture on the left. Although this might seem rather simplistic, the basic structure is quite extensible. First of all, the various object types that can be handled are registered (a four letter code is associated with a class). Then when the model attempts to load the file, it gets the code from the file, and calls the appropriate class. All of these classes (currently Sphere3D, Teapot3D, Cone3D, Torus3D, Cube3D) are derived from a base class (Object3D). The base class takes care of a few common things (when creating/destroying the object it takes care of maintaining the linked list, when loading, the first three sets of coordinates are the position, rotation and scale and when displaying it sets up the model matrix). The rest of the data represents object specific information.

When displaying, the list of objects is iterated through, and the Display function of each object is called in turn (the main class treats them all as being of type Object3D, but in reality the appropriate Display function is called). A similar appropach will be taken when dealing with user input.

There is no user interface right now, I'm just using GLUT (GL Utility Toolkit) for the windowing. My plan is to add camera control (right now it's hardcoded, I want to create a Camera3D class which I can manipulate in order to change the viewpoint, perhaps even create two sub-classes of that, PerspectiveCamera3D and OrthographicCamera3D, for the two projection types) and then implement the other half of the project, the window-based interface. This will require me to first learn about the Mac-specific OpenGL calls (which would be required for setting up a drawing context and rendering into a GWorld), and then figuring out the architecture of the UI (Iconographer's isn't very C++ like, but I'm not sure if I want to go as far as have each control be a separate class).

I also have to implement the mesh tool, which will be one of the harder parts, especially when it comes to editing it. But I'm delaying it until after I have an UI up, since it'll be a lot easier to debug when I can view it from different directions and manipulate it. And of course I musn't forget colors (I guess this will be another attribute that will be handled by the base class, since I'm not planning for texture mapping, although I might have the option of adding colors to each vertex of the mesh). The reason why I can get away with no texture mapping is because I'm only doing a modeler, not a fancy renderer, and besides texture mapping would be too slow in software rendering (which I have to use since the current (third-party, unsupported) OpenGL driver for my Voodoo3 doesn't do windowed or offscreen rendering, only on the whole screen).

Still Planning Away #

Haven't had that much time for this project lately. Unlike Sonar, Grendel and Iconographer, it's still in the early stages, and thus I can't just pick it up anytime, work for a bit, and then move on, rather it requires some concentrated thought. However, I am tempted to start to implement the architecture I described earlier for storing the models, and leave the user interface for later.

I'm starting to have an idea of how the user interface will work. First of all, when the user clicks, I have to determine which object was hit. This isn't quite as simple as it sounds, since the scene can be at a weird camera angle, with objects obstructing one another, etc. OpenGL has a picking/selection mode which allows you to see which object was clicked on. What you basically do is assign each object a distinct color, turn off lighting and other effcts, and render a very small area around the location that was clicked. Then by looking at the color, you can determine which object was hit. However, this doesn't tell you where exactly the click was. I thought I was going to have to get the inverse of the modelview and projection matrices, and do this myself, but apparently there's a function called gluUnproject which does this for me. Once I have the click transformed to be in terms of the hit object's coordinates, then I can actually process it.

One of the bug remaining issues is that of the tools. I've mentioned earlier how I had come up with a flexible and extensible architecture for handling various object types (geometric primitives, meshes, etc.). I'm thinking of extending this to the tools, but I'm not quite sure how it'll work yet. If each object type has a single tool associated with it, then things should work out pretty well, but I don't know if that will be the case. I guess I should draw up some mock-ups of how the user-interface should look, and then the class hierarchy behind it which would be used to implement it.

Once I get an idea of how the whole application will work, I can see two possible ways of starting. I can work on the back-end (the loading and rendering of models) and use GLUT as a temporary user interface until I get to that, or I can work on the user interface, and use simple placeholders (e.g. OpenGL has a teapot model built-in) for the actual models. Right now I'm leaning towards the first option, because it'll be more satisfying (3D models are cooler than the user interface), and I need to learn more about the rendering contexts.

Ro-bust! #

I've been making Iconographer more robust in low-memory conditions. Until now, if the memory was filling up as the user was drawing (since I'm saving the drawing state for multiple-undo support), Iconographer would not notice unless there was a selection active. Also, the checking when creating a new editor wasn't working as expected, since I wasn't initializing certain variables to NULL (why it worked when I was doing the testing for the IB dossier I'm not sure, perhaps the older version of CodeWarrior (especially the debugger) intialized the variables for me).

So far, I have three separate menu commands for opening the three icon types that Iconographer supports (Mac OS, Windows and Mac OS X Server). However, I just realized that I can customize the open dialog, and put in an "Icon Format" pop-up so that a single dialog can be used for all the formats. The reason why I didn't think of this earlier was that the Mac OS Icon open dialog is slightly different (since I need to be able to open folders too) and I didn't think it could be customized.

It's Alive! #

This is my new CGI project. I've decided that Sonar is functionally complete, and adding features on wouldn't have been quite as fun and instructive as working on something else.

Grendel is a web-based POP3 mail client. Although it might look a lot like Hotmail, you still need a separate account somewhere else to use it, it does no hosting of its own. The idea is that you are able to check your mail from anywhere you have a web browser, whereas before you would need to telnet in (if your ISP allows you to do so), or set up a mail client, but then you'd be leaving your settings and downloading your messages on a computer which wasn't yours. Additionally (and even more importantly to me), it allows you to get to your mail when access to the Internet is otherwise limited because of a proxy server.

Obviously this idea isn't new, Hotmail allows you to check an external POP3 account, and there are many free and commercial CGI scripts which are specifically designed to do this. But doing my own thing would allow me 1) to learn more about networking (which I've been meaning to do) and 2) customize it exactly to my needs (that is, make it look a lot like the Netscape mail reader).

I've found (a while ago actually) a simple script which displays a list of messages which you check off, and then they are all displayed for you to read. I've been using this script until now to read my mail when I have to go through a proxy (I switch to my ISP account when I want to download it locally), but it doesn't do all that I need it to do. I want a frames-based interface so that I can go between the messages easily, and I want the messages cleaned up, which means 1) not showing all the headers 2) making links so that they are clickable 3) not stripping out anything that begins with a < (which Netscape treats as the beginning of an HTML tag).

So far I have a working model of what I'm planning to do. I've implemented the frames based interface, as well as the basic header and link filtering within the body of the message. Parsing the headers was something that was very easy to do with Perl. The format of the headers is "<Header name>: <Header contents>". Perl has a split command which allows you to divide up a string based on a certain symbol (in this case I used ": "). Then I stored the split results in an associative array (which is somewhat like an array except the indices can be strings), so now I can access the various headers by using something like this: $headers{'From'}.

Since at the moment Grendel can only check my mail (the user info is stored in a file, but it's not modifiable at the moment), I can't just link to it to show how it works, so here is a screenshot of what it looks like. On the right there's the old mail interface I used:

Grendel Mail

The big things that are left now are handling of the author's email address (that is, separating the name from the email address, and turning it into a hyperlink), handling the date (I want to convert them all to JST, or whatever is set in the user settings file), displaying threads graphically and sorting of the inbox based on the various fields (these last two will require a reworking of the way in which I store the messages, right now they're just an array of strings).

And in case there is confusion about the name, there's a very simple reason behind it. A while ago (actually, there's some signs of revival with the Mozilla project) Netscape had a project to reimplement Navigator in Java. Although it never really got off the ground, the mail client was mostly complete. The codename of the mail client part was Grendel, and since I'm mimicking the Netscape mail client too, then I thought the name would be appropriate.

Mock me up #

The only actual programming that I've done so far is to make sure that the menu titles are highlighted properly when hierarchical menus are selected. Until now, selecting something such as Edit: Select: All would not highlight the Edit title as expected. It turned out that the Menu Manager was trying to hilight the title of the Select menu, but since it wasn't in the menu bar (being a submenu of the Edit menu), nothing would be seen. Right now I hilight the title by hand, because I haven't been able to find a way to get the parent menu's ID.

Somewhat more interestingly, I finally got the mockups and plans for what the Apple people (which from now out I ought to refer to as Matt (the UI designer, altho at Apple's he's just a lowly icon designer) and Arnaud/Arno (programmer, he designed the Icon Services in Mac OS 8.5, and I guess he's in charge of the icon stuff in Mac OS X, the second spelling of his name is to give a clue to the non-French speakers on how to pronounce his name).

What Matt has in mind goes reasonably well with the ideas I had for the next major release of Iconographer. This mainly includes going to a palette based interface. However, while I had thought of splitting everything up into floaters, trying to mimic Photoshop as much as possible, he's decided to down-play Iconographer actual editing capabilities, and instead treat more as an icon assembly tool. The main window will now be the Worktable (as opposed to the Drawing Board, as it is now, BTW, these terms are his, not mine). In the Worktable, all of the icon/mask sizes and depths will be visible. Double-clicking on one would open it up in the editor app that the user has chosen. Whether this is Iconographer's internal editor, or Photoshop, it's up to the user. There is also a separate floater for the previews and the icon states (in Mac OS X the user will be able to determine exactly how the icon looks when it is selected, openened, when another file is dragged onto it, etc.)

A couple of days ago I realized that since he's separated the editing portion (which is pretty much the current functionality) from the rest of the features (which will be mostly new additions to the current app), I could do what he's proposing as a separate app, which could optionally integrate with Iconographer. I'm not sure if this how the final (i.e. publically released) version will be, but at least during the development process this would make sense. Then I could keep adding features and releasing new versions of Iconographer in it's current state, while at the same time doing what Apple wants without having to maintain two separate codebases. If I use a common base (which is really the point of MFrame), then merging the two later on shouldn't be that hard.

Stick a fork in it #

I've redone the main thread view so that it displays properly. The problem was that the dotted lines which I was using to show the relationship between posts (idea copied from the Windows Explorer, but for some reason I always thought it looked cool, if somewhat useless) weren't being displayed right. In the end I used an array/stack (in Perl they're the same thing, since arrays can be grown dynamically by simply accessing an out-of-bounds index, and there's already push and pop functions built-in) to store the lines which needed to be displayed. In any case, it looks pretty now.

Oh, and I've decided to move on to other things, instead of extending sonar. Not quite sure what, but it'll come to me.

Re: Replies #

I've finally implemented replying (this involved learning about regular expressions, which are very useful when searching and substiting strings with somewhat complex patterns), and the main thread view displays the newest messages on top. As far as I can tell, the message board is feature complete (that is, you can browse, create and reply to posts). Now I can either move on to a different project (I'm thinking of doing either a web album thing where users can upload images, write commens and put them into collections, and browse the collections of others, or perhaps an e-card service) or further refining the message board (by adding searching, cookies to remember the user name, displaying only messages that are new since the last visit, etc.). Either way, I'll be further using and learning Perl, which is really the whole point.

Smooth as a baby's bottom #

While fooling around with the dragging between the various sizes, I noticed that drawing a 3 pixel thick border in the 48 x 48 size, and then dragging it over to the 16 x 16 slot (this involved scaling it down) yielded some reasonable looking anti-aliasing (this is because of the way QuickDraw implements copying when the source and target rectangle are of different sizes). Actually I'd kinda noticed this before, but I hadn't really thought about using it to add anti-aliasing.

In any case, as a quick test, I wrote a quick FrameOvalAA (as opposed to the normal FrameOval) function which drew an oval with a 3 x 3 pen and then copied it down to size. Everything seemed to work all right, but it order to get it to look exactly as it was meant, a bit more tweaking was required. The problem is that not only does the oval have to be anti-aliased, but it has to blend in with the background as well. What I ended up doing was to create an 8 bit mask which had the anti-aliased shape in it, and using that to composite the current icon contents and the foreground color. I was originally creating a few scratch GWorlds, but then I realized that I had the canvas gworld used by all the icns editors, so now I'm using different areas of it for the 3x version, the mask and the foreground color. Since it involves 2 additional CopyBits/CopyDeepMask passes, the function probably isn't fast enough for real-time anti-aliasing, so I left in the old (non anti-aliased) code for the oval that is drawn while the user is dragging the mouse.

I figured that since this worked out pretty well, I should do the line tool next. The base idea here was the same too, but it required a little bit more tweaking. The problem was that since, when the line has a thickness greater than 1, it extends beyond the starting and ending points (at least with the line drawing method that QuickDraw uses). I had to add some extra padding, and make sure that vertical and horizontal lines were still being drawn (since they would "fit" in a zero width/height rectangle).

The polygon tool shares some aspects with the line tool, so I moved on to that one. This also required some padding, and since I was using the built-in Mac OS data-type for sotoring them, I had to use some different functions (MapPolygon) to enlarge the polygon to 3x the size.

Then, going back I realized that filled ovals weren't quite behaving as expected. The problem was that the frame wasn't quite covering the edges of the filled center, so most of the anti-aliasing was lost (this was most noticeable when the fill and the frame were of the same color). Some additional hacking was required (and the current code is rather ugly), but the ovals now look good whether they're filled or not.

This lead me to notice two things: 1) a somewhat similar anomaly seems to be happening with the filled polygons too. 2) I was getting frequent freezes when attempting to use the pattern pop-up (the ovals can be filled with patterns too). I'll try to determine if this is because of the beta drivers I'm using for my graphics card (the freeze seems to take place in a function called TerminateGraphicsAcceleration), or if it's my fault. In any case, I'll be dealing with both of these tomorrow.

Anti-aliasing will be even more useful when I add the simultaneous icon and mask drawing. Then I have to combine the anti-aliased mask with the icon mask, and then color with the icon. Rather hard to explain, but much easier to demonstrate visually. I'll see about drawing up some mockups to show what the intended effect is.

No mail from the Apple person (they said they'd contact me by the 15th). If there still isn't anything by tomorrow, I'll email them asking what's up. They haven't been specific at all as to what exactly they want changed in Iconographer, and I'm really curious :p

I think that alternating back and forth between Meshroom and Iconographer is a good idea, because they're really projects at opposite ends of the spectrum. Meshroom (in it's current state) is still in the planning stages (yes, I'm actually trying to have a pretty detailed plan before I start coding) while Iconographer has a complete base and a large amount of features, and now I'm just adding things on (although a big restructuring might come in the future).

Basic Architecture #

Data storage

OpenGL includes the concept of vertex arrays. The idea is that instead of calling glVertex3f (and it's cousins) everytime a polygon is defined, you create a list of vertices (which can be stored in the 3D accelerator card for optimal perfomance) and then when displaying polygons, you simply make references to positions within that list. Parallel lists can be maintained for surface normals, colors, etc. or they can be put in the same array, and a "skip" value can be used to jump from one set of coordinates to another.

What I'm currently considering is to store all of the vertices used in a model in a central location, and then each of the objects make references to that central vertex array. In this way, sharing vertices between different objects will be very easy. The model file would then start off with a big list of points, followed by the actual objects (e.g. in the case of polygons there would be an enumeration of vertex numbers to define the corners of the polygon). As far as I know, this is how games such as Marathon store the world levels (which is why with the level editor you first lay down the points, and then in a separate step connect them).

As an alternative, I can store the vertices (still within a vertex array) within each object. The main advantage of this would be that when deleting or inserting vertices, I wouldn't have to search for the objects which make use of the vertices whose positions are affected and have to adjust the indices appropriately. There might be some wasted space (since there might be duplicate vertices), but there can't be that much. I really can't think of too many situations where you would want different objects to share a vertex (e.g. for a sphere's center to be attached to a corner of a polygon). For things such as triangle meshes, each vertex array will encompass the entire mesh (as opposed to a single triangle) so the big savings are still there. Actually, for things like spheres (which only need a single point and a scalar to be defined) there's no point in using vertex arrays. The only problem which I foresee is if there can be a limited number of distinct vertex arrays be loaded in memory at the same time. I don't mean limitations due to not enough memory, I mean limitations caused by OpenGL's implementation (similarly how some 3D accelerator cards can only handle 8 lights at a time). If that's the case, I'll have to implement an architecture which keeps track of the vertex arrays as they are loaded, and disposes of the least used one (or the one used the longest ago) if a new one is to be loaded but there isn't enough space.

Heh, looks like I totally eliminated the first choice. Well, this isn't quite the IB dossier write-up yet, so I can ramble on.

Classes

I'll be needing a base Object3D class which will a stub-like thing (that is, it'll never be used directly in the application, rather I'll be using classes which use Object3D as a base). It'll have basic fields (and the appropriate functions to set them, I'll try to have as little public variable as possible, and instead rely on accessor functions) for position, rotation. There'll be virtual functions for loading, displaying, scaling, etc.

For object identification, I plan to have both a name field, and a four letter code (which translates into a nice long) which shows the object type. Then the loading function could look at the four letter code in the file, and create the appropriate instace of the class and call it's loading function (which is virtual, remember).

First of all, I said "the appropriate instance" above. As implied by the fact that Object3D is a base class, I'll be having other classes layer on top of it. There'll be simple ones like Sphere3D, Cone3D, Cube3D, etc. and more complicated ones like Mesh3D. Since they share a base class, the rendering loop can treat them all like Object3Ds and call the display function. Things might get a little bit more complicated with the user interaction, but it's the same idea.

I want the program to be as flexible as possible. Ideally, if I wanted to add a new object type, I shouldn't have to chase down all of the case statements which involve the four letter object codes and add the new one. A plug-in architecture is overkill, but I can implement an way to "register" new object class types. Basically, there's a central "hub" which stores pointers to "mini hubs" for each object type. These "mini hubs" would share a base class which has a virtual function to create a new instace. The "mini hub" class is only a few lines really, since all it has is a "return new ". Perhaps it could also be done as a static function in the actual object class. In any case, all that would be required to add a new object type (once the class has been written) would be to "register" it with the "hub" (e.g. ObjectHub.Register('Cube', &CubeHub); or perhaps ObjectHub.Register('Cube', Cube3D::Instantiator)). Then, while reading the file, the main function would look up the four letter code, if it finds a function pointer then it calls it and assigns the value to an Object3D class pointer (in reality the class is of a specific, high level type, but the function doesn't care which one, as long as it can call the loading function, etc. which are virtual).

I'm not sure if the above is totally coherent. In any case, as far as I can tell (from what I've just been told) the process I'm describing is the factory method (as described in Design Patterns : Elements of Reusable Object-Oriented Software (I have this book, but I haven't really used it) and other places). My plan is to implement the architecture as best I can, and then read the relevant chapter(s) in the book. Then I can 1. make much better sense of what they're trying to say and 2. say to myself "that's how I should have done it."

Descriptions of All Current Projects #

Well, time to start the journal again this year. I had fun re-reading the entries from last year (all 26,381 words), so I figure this year's will be useful as well. So that future entries don't seem to come out of the blue, here are the projects I'm currently working on:

Iconographer: last year's IB Dossier project. It has now become a shareware icon editor (currently up to version 1.0.2). I have a bunch of things planned for it (planned versions are 1.1, 1.5 and 2.0), so I'll be working on it this year too. In addition, I'm working with some people at Apple to make it their official internal icon editor. I should be getting the specs to see what they want in a few days. Hopefully it'll be compatible with my plans, or better yet theirs will be better :p In any case, although I most major work is done, it'll still be taking up my time.

I'm also planning to use Iconographer as a codebase onto which to experiment with new concepts that I'm trying to learn. For example, I'm thinking of adding a plug-in architecture for Photoshop-like filter effects. Although a plug-in system for an icon editor in itself might be overkill, it'll still be useful in the future. Another thing which I've had any experience with whatsoever is networking. Therefore I'm planning to create a simple stream class, which I'll be using in Iconographer. Some applications (e.g. Transmit and Audion from Panic, a company I admire and would be proud to work for them) display a "Do you want to subscribe to the update mailing list for this product" dialog when they're first run. If the user clicks yes, then a message is sent out with the user's email address. Now this obviously requires networking (specifically the SMTP protocol) and I think that this small task would be appropriate for a first networking-related project (as opposed to say implementing a real-time 16 player Internet based game).

Meshroom: this year's IB Dossier project. Since I learned how to use OpenGL this summer, and want to further practice my skills, I think that this project will help me do that while at the same time fulfill all the IB requirements (yes, I know specifically where recursion will be involved, and it'll be in a very reasonable and relevant place). The idea is to create a simple 3D modeler. In my case, I'll define simple as basic 3D primitives (cubes, spheres, cones, etc.) and vertex meshes. If I have time, I'll add terrain map support (at least loading of grayscale maps into meshes) and whatever else comes to mind. Although I'll be using OpenGL, I still want to make it behave as a Mac application (I had initially considered doing my own controls, etc. and working in full screen mode, but using the Mac ones will be much easier, and they wouldn't have fulfilled any IB purpose anyway). I'm currently in the planning stages, I have a basic idea of the class nomenclature in my head and I need to get it down in order to make sure that it'll work (unlike Iconographer, where I only had two or three classes, this project will require several, and there'll be inheritance and polymorphism to think about). For the final aim of this project (as opposed to it being just a dossier thing) I don't see it being released as shareware or anything of that nature. I'm still quite an amateur when it comes to 3D things (especially concepts involving heavy math, which I really haven't had/don't remember). Instead it'll serve to:
1) further improve MFrame, a homegrown application framework which I've so far used in all my apps, but isn't quite coherent (e.g. I've only recently added a window class, even though this is a basic thing, and I still have no uniform policy for handling controls). My belief is that instead of using a ready-made framework such as PowerPlant, I'll learn much better the concepts involved when implementing them on my own. Even if in the end (that is, when I do real applications) I'll use PowerPlant/MacZoop/whatever, I think my experience will still be beneficial
2) when the project gets to a stable state (most likely when it'll be handed in to the IB) I plan to release the source code under the GPL (GNU General Public License, it basically says that you can do whatever you want with the source code, including modify it and redistribute it for money, but the source code and modifications must be available upon request. It's the license that Linux is distributed under). This is because I admire the power that the open source community has shown so far (the uninitiated should read The Cathedral and the Bazaar, a seminal paper on the subject). And if I'm lucky I'll learn something new, and besides, it's good to attempt to give back something to the community.

Sonar: a web based discussion board. This is actually a project for the Info Tech class, but since it involves programming (with Perl, I'm finally learning the language) it's also relevant here. Right now I have the basic functionality implemented (a threaded view of posts, reading of messages, and posting), and I'll be polishing it until the end of the quarter (when I'll most likely have to move on to another project, but I'll try to make sure that it also involves Perl, so that I can keep learning it). In any case, since this is a web-based program, it can be tested anywhere. The address is:

http://www.mscape.com/cgi-bin/sonar.cgi

The long term plans for the source base of Sonar involve turning it into a bug tracking system (I've found several ones with source code on the net, but all of them require root (administrator) access on the server, which I don't have). This actually explains why it's called Sonar: Apple's bug tracking system is called Radar, and Sonar is a word in the same vein.

IB Dossier Requirements #

I didn't have time to program today, but I can do the required 3 paragraphs on the required concepts for the IB dossier:

Dynamic data structures:

The main way in which I show this is through linked lists. Since there can be more than editor open at once, I keep track of them through a linked list. When a new editor is created, I add it onto the end of the list. When an editor is closed, I remove it from the list, and keep the links between the previous and the next element up to date. Also, within each editor I use a list to keep track of all the changes that user has done. When a drawing command is executed, the new state is saved to the end of the list. When the user wants to go back, I simply move to the previous stored state and restore it. If the user wants to go forward, I can move forward, and restore the state. If the user goes back, and then starts drawing again, the states that were ahead of it (if any) are disposed since they are not needed any more.

Advanced operations on data structures:

I'm not quite sure what they mean by this. I have a searching function, since I want to create a list of all the icons, sorted by ID (when I get them from the file, I get them in the order that they were stored in). So I insert into a sorted list.

Recursion:

See above.

The Usual Excuses #

Didn't have much time for work today, it was the second day of the JOs (swim meet). Only thing I did really was to fix a bug, I wasn't allocating the emergency memory chunk when the program was starting up, so the first dispose would cause weird things to happen since it wasn't allocated.

Stability Improvements & Future Plans #

Did some work on making Icon Mangler more stable (got distracted while I was commenting). Until now it was the icnsEditorClass's job to see if it was out of memory, and to deal with it (by calling delete this). However that was not a very good method, since the linked list was not nto maintained properly, and it was not a good separation between the main program and the class. The best solution would have been to use exceptions, but I don't have the time to learn them properly before the program is due. Instead I added another bit to the status field of the class (which was used to communicate with the main program anyway), outOfMemory. When that us set after the constructor has been called, we assume that the construction failed, and dispose of the editor. In places within the program too, we call this, when making temporary GWorlds and so on. Then in the DoIdle of the main program we check through all the editors if they're out of memory. If they are we dispose of their saved undo states (which can free up quite a bit of memory if the user has been working for a while). If we have already done that, and there still isn't enough memory then we must close the editor. We display an alert, and let the user save if they want to. In order to make sure that there is enough memory to display the error message and the save dialog (even though we are supposedly out of memory), I allocate a chunk in the beginning of the program (for emergencies like this) and dispose of it in order to free up memory, then when I'm done I allocate it again for future use.

So far this is working pretty well, except that the save dialog when using the Navigation Services wants about 100K of temporary memory, and making the emergency chunk that big is kind of a waste. This isn't an issue for the IB, but in the final program I think I can pre-load the Navigation Services library at the beginning of the program, and unload it at the end.

Also, I'm still not checking whether I have enough memory to save the drawing state, so I need to do some work there too.

On another note, I've thought about the future of Icon Mangler (post IB). I want to make it into a decent icon editor. One of the things that is lacking right now is the option to make only certain sizes/depths available. Right now if you add a 48 x 48 icon at a single depth, then when saving all the other depths are saved too, even though they are not used (so they are white). Also, when making a new icon, all the sizes/depths are allocated, even though they are not used. My solution for this (actually this would go in the base icnsClass, but it'll affect Icon Mangler too) is to have an array of pointers to the icon depth/sizes combinations. When the user adds a new size/depth then the respective pointer is allocated, and when saving only the ones that are used are actually saved. Deletion of depths/sizes should be easy too, since it's a simple matter of calling DisposePtr.

For the actual editor, I think I might have a separate editorClass, from which I make a derived class called icnsEditorClass (which also has as its parent the icnsClass, so we have multiple inheritance :p). The editor class would do its drawing actions on a pixmap/gworld called drawingPix/drawingGWorld. Then in the icnsEditorClass its simply a matter of setting the pixmaphandle/gworldptr to the current size/depth. I'm not doing this just because it sounds fancy, but because it could be useful in the future. For example I could make an editor for other graphical resource types too, and then I wouldn't have to rip out the editor out of the icnsEditorClass and replace the icns specific parts with something else (this would also be a headache when adding features). Or conceivably I could spin off the editorClass as a program of its own, to edit simple pictures (or complicated ones, if I get to that level :p).

Finally, I think that I could release the icnsClass (the newer version, not the current one) to the public as a library. Then developers interested in using the new 32 bit icons could use it without having to worry about learning the whole Icon Services API. In addition I already have my own functions for dealing with 32 bit icons under 8.1, so my class would provide compatibility there too (I could use a conditional statement to use the system functions on 8.5+ and my own functions for older systems, for maxium forward compatibility). Of course it would be free, perhaps even open source (although I doubt that I'd get much of a following).

Commenting++ #

I've commented some more of the Icon Mangler code. This is what's done so far:
- the icnsClass
- the main.cp (which handles the events, and passes them on to the icnsEditorClass)

The code that remains to be commented:
- the icnsEditorClass (longest one)
- the Icon Browser (must be included, since it uses a search function)
- the compression code (must impress IB people)
- the AppleEvents code (kinda messy, since originally it's not mine)
- the drag and drop code (messy too, even though it is mine :p)

I also fixed another bug in clip2icns, the window would not disable properly when put into the background. I'd known about this since when I was working on 1.5, but I could not figure out a way to fix it, without redrawing the window every second. I figured it out when I was commenting the Icon Mangler event loop; I remembered that when an app is put into the foreground/background it doesn't receive an activate event, rather an OS event. I don't plan to release a new version just for this, since it is only a visual glitch. Actually I think clip2icns has pretty much reached the end of its line, feature wise, unless the users have any more suggestions.

Mangler Documenting #

I've started to think about the documentation for Icon Mangler. I was originally going to do it in a DocMaker format (self contained docs, but the layout capabilities are the same as SimpleText's). But in the end I decided to use HTML for two reasons: 1) it provides much better layout control than TextEdit (the Toolbox Manager used by DocMaker/SimpleText) and 2) Apple's new help system uses HTML for the storing of the help files (and the Help Viewer is a mini local web browser), so conversion to the new format (when the SDK is released, still waiting for it) should be even easier, and then the help will be available within the application. Actually I can do that even now, by using AppleEvents to open the help file from a menu item in the app.

The only problem is that the Help Viewer, like most current browsers, has its own little quirks for displaying HTML. I want the end product to be visible in both the Viewer and in Netscape. But this is all secondary, since the IB people are not going to care about such issues.

I've started to work on the toolbar part of the help, where each tool is explained, along with the keyshorts/modifiers. So far so good.

Lamely Recursing #

YESSSSSS! I have recursion in program. Thanks to a tip from James, I've redone my fill function to use a recursive algorithm (instead of just calling the system function, SeedCFill). The actual algorithm is pretty simple, I start with the source pixel, and look and its neghbors, and at the neighbors' neighbors and so on. It's a classical example of recursion (I've found some class notes on it online, and its in the Computer Graphics: Principles and Practice book I have too). It's not the best solution (a scanline algorithm might work better, but it would be more complicated), but it's a legitimate use of recursion.

I had some problems with filling in selections, but it turned out that that was because my GetPixel/SetPixel functions assumed that the origin of the PixMap was at 0,0. However with selections, since they can be moved around, the origin varies. The fix was simple, all I had to do was to subtract from the passed x/y coordinates the coordinates of the origin.

Excuses #

No time for programming, various essays were due...

clip2icns pre-8.5 Hacking #

(argh, I've written this before, but I crashed, so I have to do it again)

Not much time for coding (big history rough draft was due, among other things). Major thing that happened was that I found (well, some users found, and they were registered so I had to pay attention) that clip2icns refused to work under pre 8.5 systems. It took me about a week to figure out why. The actual crash occured when I disposed of a PixMap in the Make1BitMask function. By selectively commenting out lines I had traced it to the call to CalcCMask (a system function). I beat my head against this for a few days, trying many things (including copying the source to a local PixMap, locking the source/target (again), taking out the customized color search function from CalcCMask, and other stuff). In the end I did a search at DejaNews (an archive of Usenet postings, including comp.sys.mac.programmer.*) and found my answer. It turns out that CalcCMask wants a real BitMap* for the target parameter. I was used to CopyBits, which also wants a BitMap*, but a casted PixMap* works too. Apparently this was changed in Mac OS 8.5, which is why I didn't happen while I was developing the function. And I didn't notice it before since I had used a different method of determining the mask (a much uglier one, which had been inhereted from clip2cicn, the first real (as in distributed) mac program I did, back in early June).

I also had to do a workaround, this time for a documented bug (which was fixed in Mac OS 8.5). Apparently calling CopyDeepMask when the target is a 8 bit (or less) GWorld will yield nothing in it. What I had to do was to use a temporary 32 bit GWorld which I then transferred to the 8 bit by using CopyBits. All of this went into clip2icns 1.5.1. Speaking of clip2icns, the number of registrations has topped 50, so I'm halfway to my (just established) goal of 100.

Misc. Cleanup, Releases #

Didn't have much time to work during these days. I've been commenting the code, and fixing miscellaneous bugs. It turns out that when I had cleaned up the icnsClass code, I had made some mistakes, which I found while working on clip2icns, so I fixed those (I was attempting to generate the mask before I had put anything in the source GWorld). I've also gotten around to releasing clip2icns 1.5 and Glypher 1.0 to the public. Then I added a check for the proper system version (current 8.5+, but in the version that will released publically they will most likely be 8.0+, or even 7.x with the Appearance Manager installed. I'll also most likely be stripping out the 68K specific code (mostly AppleEvents stuff), since it'll just confuse the IB people. The commenting is progressing well, I'm done with the function headers, and now I have to do the actual code (nothing fancy, just cleaning possibly confusing sections).

Compulsive Cleaning #

I couldn't stop myself, so I started to redo some things. First thing was my 1 bit mask generating function, which used a very messy code (it involved going through the color lookup table, which made it only work with indexed-color images, and setting all non-white colors to black). But now I've had more experience with CalcCMask system function (the lasso tool uses it), so I was able to rewrite it to be much more efficient. I also replaced some repeated code in the ImportFromClipboard function with calls to Make1BitMask, so the line size is down by quite a bit.

Then I worked on the saving functions, specifically the compression part. Until now each icon had three member variables, arrays of chars for the compressed data for all three sizes (huge, large and medium). However I realized that these were only used when saving, and were taking up memory the rest of the time. Looking around the compression code, I had also noticed that I had three special cases, for each size, when it could have obviously been turned into a generalized function. A similar thing also existed with the decompression, where I had three similar loops to decompress the data and merge the RGB channels, again one for each size. In the end I decided that what I needed were two functions, CompressPixMap and DecompressToPixMap, which would make the transitions between an uncompressed pixmap and the compressed data represented by an array of chars. I also spun-off the compression routines (the above two, plus two sub functions, PackData and UnpackData which are each called three times for each channel) into a separate file, since they make much more sense that way. When I was done everything the code looked much cleaner, and I had made each instance of the icnsClass (and thus the derived icnsEditorClass) take up around 15K less of memory.

The Great Commenting Begins #

I've started to comment the Icon Mangler code. The first step was do "function headers", where I described the input and output of each function, had a simple description of what it did and notes if there was anything that should be kept in mind when using it. Ideally this would have been done in the beginning, as part of my top-down design, but I couln't really since I was learning how to do an icon editor at the same time. Eitherway, this hasn't been too hard, the only problems that I've encountered (other than boredom) are than some of my early code (I've started the commenting process with the base icnsClass) is rather messy and inefficient, so I'm getting tempted to rewrite it.

Why do I even bother... #

[no time for programming today]

Templates 0wnz m3! #

Worked some more in the morning on the templated linked lists (I realized I had made some conceptual mistakes yesterday). However, still no luck, I still get errors I have no idea how to solve.

Undo Bugs, Swatches #

Main thing I did today was to remove (yet another) annoying undo bug. Actually it was a couple of bugs. One was when I was restoring the selection, I was using UpdateGWorld to reset the selection GWorld to the proper size. However, once in a while it simply wouldn't change the selection bounds, resulting in part of the selection being garbage. When I replace the UpdateGWorld with a DisposeGWorld and NewGWorld, everything worked. Weird, but in some ways the new is even better (since UpdateGWorld allocates temporary memory to save the current contents, but I didn't care about that).

The second bug was more of an error in thinking. When a selection was made, I didn't set the hasSelection bit of the status right away, instead that was in my DoIdle function, which periodically looked to see if the selection region was empty, and if it was then the bit would be set. However the storing of the state came before the DoIdle, so the status that was saved had the hasSelection bit off. Fixing this was rather simple, I added a check after the selection tools or commands were used, and this came before the state was saved.

Finally I tried to make the code look much more professional by using a generic linked list class. My idea was to use templates, and then to derive my icns editor and drawing state classes from that (they both use linked lists to keep track of the open editors/saved states). I got to the point where I had a basic framework, and as a simple test (before I went in and tore out all the old code) I was making a simple program to have a linked list of integers. However, it won't compile, and the error it gives is that the constructor of the linked list class is bad. The Metrowerks site says that CodeWarrior Pro 4 has soem new features/fixes relating to templates, so I'll try it again on Monday, with the newest version (and if it works then I guess I'll have to upgrade). Speaking of CW Pro4, earlier I had said that it wasn't fully Appearance Manager savvy. However it turns out I was wrong. Instead it's Kaleidoscope's fault, since it doesn't patch all the AM controls (which CW seems to be using).

Finally I worked on making the color swatch control more like Photoshop's. This meant adding the two little widgets in the top-right/bottom-left corners, the one to swap the fore/background colors and the one to reset them to black/white. This also involved adding icons (for the controls, with an active and inactive state each) to the statics structure (since they're shared by all the editors). All that remains now are the preferences, I hope.

Custom Event Filters Rock My World #

I only did a very simple thing today, but it'll aid me in testing. When the "Do you want to save..." dialog shows up, it has three buttons. The default is mapped to return/enter, cancel to escape, but the don't save one (which I'll most likely be using when testing has to be clicked manually). To get rid of this annoyance, I added a check in the custom dialog filter, to see if the the key being hit equaled the first letter of the third button, and if it did to simulate a click there. So now I can just hit the D key to click the "Don't Save" button. Very small, but otherwise when quitting i'd have to click thet button for each open editor.

Overlays #

I've noticed that when quitting, if you clicked cancel, it would just keep asking you if you wanted to save. So I added a simple check to continue with the quitting process if the CloseIcon function returned true, otherwise we go back into the EventLoop function.

Then I worked on improving the overlay. The overlay is used for the rectangle, line and lasso tools. Basically it provides another (temporary layer) for displaying stuff (ie for the rectangle it is used to show the size of the rectangle being drawn, and only when the user lets go is it actually drawn on the icon's pixmap). Until now, when I created the overlay I used the current depth and color table. However, I realized that this was unecessary. All it needed was to have a 2 color color table, with the foreground color, and the transparent one (actually until now I was using white for the transparent color, which caused problems when drawing white lines). The transparent color is the same one that's used for determining the shape of irregular selections pasted in from other programs, 0xFFFFFE.

Dragging: I 0wnz j00 #

I finally managed to squash the bug. When dragging, if there is a selection, I have to merge it with the current icon contents, and put that into the drag image. After the drag I had a check to see if the temporary gworld was created (which contained the merged data) and it would dispose of it. The check for this was whether or not there was a floated selection. However when dragging to the current gworld, a floated selection wold be always created, so it would attempt to dispose of the temporary gworld (which wasn't there, and it was grabbing the source).

Then I worked on one of the final human interface additions, the "Do you want to save...." alert. This was rather simple, I used the StandardAlert function to display a movable dialog, and specified the buttons as "Save", "Cancel", and "Don't Save". The hardest part was writing a string search and replace function, so that I could include the file name in the prompt string. I also made it so that these dialogs show up when quitting, if an icon hasn't been saved.

The Quest Continues... #

Tried to work some more on that bug some more, but the absence of the debugger prevented (I think it'll work once I install the 3.1 update, but it didn't finish downloading before class was over). Again, no time to work on it at home.

Curiouser and curiouser #

I've found this very weird drag and drop related bug. When dragging from a size to the current size, the source gworld would get set to null. This is very weird since I'm not supposed to be changing it at all. Debugging was rather hard at school (since the debugger doesn't work :p) and I didn't have any time to work on it at home.

Happy Birthday #

[15 years ago the Mac 128K was introduced]

I tweaked the state saving some more, so that when clicking on a different icon size, an undo would bring you back to your previous position.

Another Day, Another Bug(s) Squashed #

First thing I did today was to fix an undo bug. When switching between different sizes, the drawing area has to be resized (obviously). However, when undoing this change, the drawing area would not get resized. It turned out that when I redid the size switching part of the HandleContentClick function I changed the order in which the state was stored and the new size was set. While I was doing this I also removed some redundant MagnifySelectionRgn calls, and made the ones left in check to see if there was a selection in the first place.

Then I worked on removing leaks in clip2icns (it leaked about 1K for each icon viewed, and 5K when the current icon was exported to the clipboard). Using Spotlight it was rather easy, it turned out I wasn't disposing of the picture after I had placed it in the clipboard. I had also missed disposing a GWorld.