About Andrew Choi
MIDI File Player (External Device)
Cocoa Sample Programs
A blog where I will write mostly about programming in Cocoa and CoreMIDI, and experiences from my ports of Emacs and XEmacs to the Mac OS.
Wrote some code to draw bevels today so Carbon XEmacs can now draw modelines and vertical dividers more correctly. A vertical divider separates the two windows resulting from splitting a window horizontally. Herere a number of windows created by a series of
Windows are really historical artifacts from the days of tty terminals. In any case XEmacs has them. Throughout Apples Human Interface Guidelines, bevels are really only used around input text boxes. The default settings of XEmacs draw modelines and vertical dividers that look like this:
That looks a little out of place with other Aqua stuffs. The following settings:
(set-specifier vertical-divider-shadow-thickness 0) (set-specifier vertical-divider-line-width 1) (set-specifier vertical-divider-spacing 2) (set-specifier modeline-shadow-thickness 1)make it look a little more modern:
Let me explain the problem with the ability of ATSUI to use fractional text measurements and XEmacss to use only integral ones. The two lines below were drawn by Quartz 2D. The first was drawn in three parts: aff, i, and rmation. The second part is enclosed in a rectangle. Essentially this is how XEmacs draws a line with the cursor in it. The entire string on the second line was drawn at once.
Obviously, as the example shows, if ligatures are used, the spacing of the line will change when the cursor moves on and off the line. Even without ligatures, the two lines will be different because XEmacs specifies the locations of the three parts in the first line to ATSUI using integer coordinates. Spacing differences are also introduced by kerning. Here are what one can do in this situation (same thing applies if youre say writing a terminal emulator).
Ive worked out the support for bold and italic fonts in Carbon XEmacs today. In ATSUI, all fonts have bold, italic, and bold-italic variants. Some fonts, like Times Roman, have separate font files for variants: Times Bold, Times Italic, and Times Bold Italic. Other fonts, like the ever popular Monaco and Andale Mono dont, and their variants are generated algorithmically (like it was done in QuickDraw). Heres a screen shot of part of a source file in c-mode and font-lock-mode, displayed in Andale Mono:13. Notice that the comment is in italics and keywords are in boldface.
A Carbon font spec has the form
Thanks to ATSUIs use of Unicode, my port can already display characters in different encodings. Heres an example of a few big-5 characters:
The spacing of characters still needs work. Currently when Roman and CJK characters are in the same frame, either one or the other is too bunched together.
Just a new screen shot of Carbon XEmacs to show what Ive done today. The Carbon native font instances have obviously been working (at least partially) since I initially got XEmacs to run last weekend. What I didnt tell you was all fonts seem to be displayed a little crooked except my default font, which is Monaco:10 (BTW, this is how a font is specified in Carbon XEmacs). Ive fixed this problem today. It turns out to come from Quartz 2Ds use of fractional values for character and text measurements and XEmacss use of integral values. Monaco:10 characters are very close to 6 pixels wide so the problem doesnt show up for them. For now each character will just be printed in the bounding box designated for them. Note that this should still allow fonts to be mixed in the same frame. Proportional-width fonts have never look quite right to me in Emacs anyway.
Ive also worked on the handling of Carbon window events. Move, resize, and iconify (collapse windows) are provided by standard event handlers, compliments of Carbon. Resize requires a little more work than others because the size change must also be conveyed to the internal frame representation. Implementing event handling for XEmacs is a little tricky (as it was for Emacs). Currently I only have very simple implementations of the two callbacks the XEmacs code uses to check for presence of events and to fetch them. The response to characters typed at the keyboard currently seems a little sluggish. Ill need to look at this next. Perhaps Ill also look at whether I can provide a solution to the infamous
Heres a screen shot of XEmacs running with two frames. The one on the left is doing Gnus, reading an article in comp.emacs.xemacs! Because my implementation of color instances was already working, all I needed to do to get the color display was to set the class of the Carbon device to color.
Ive been asked quite often how one goes about porting a big program such as Emacs. I guess everyone is always looking for some shortcuts or sure-fire recipe for success. The truth is there arent any. Every situation in which you port a program presents different solutions. You need the instinct to pick good ones and the courage (or foolhardiness?) to proceed with them. Being a simple person like myself helps because youll come up with simple solutions :-). In many ways, porting is much easier than, say, design, because the objective is very clear: to make the program work on the new platform. Ill highlight some of what Ive done in the past two weeks in getting XEmacs to run on Mac OS X. These are techniques that have worked well in this case.
This may sound backward, but I really started by thinking about how I might debug the display code (and other code) once it is written. So one of my first steps was to make XEmacs into an Xcode project, so I can use Xcodes GUI to gdb to debug it. There is one complication because the creation of the XEmacs executable requires a "dumping", or "unexec", step after compile and link: the loading of Lisp files and "freeze-drying" the resulting memory state so the final XEmacs executable can run without reloading them. For a number of reasons, Ive decided to skip this step while XEmacs is being debugged. Running (and debugging) a pre-dumped XEmacs is made possible by using its run-temacs option. After fixing up a few paths (because the executable built by an Xcode project doesnt end up in its usual place), I have a tty XEmacs that can be run and debugged in Xcode.
Then I needed to come up with the list of functions I had to write. I did this by reading a lot of code. Especially useful were the recent ports of XEmacs to BeOS and Qt, and to some extent the one to GTK. These are less complex than the well-established X and MSW code, which I also referred to at different times. Again my objective was not to understand the code in the other ports in detail, but to identify the files and functions I had to implement for the Carbon port. I also found it very useful to read diff files for the two simpler ports because they helped me identify places I had to change in the main distribution to make use of the added functions. I identified six new files that I had to write, each containing about ten functions, and about twenty places I needed to change in the source distribution. Of course once I started debugging, Ive found more places where code must be added or changed. But armed with the initial list I compiled, I had a very good idea of where to begin.
Now comes the hard part of coding. It is hard because for a port of this size, one must write a lot of code before testing of the code can begin. In this case the six new files amount to about 3000 lines of code. The less-experienced may consider inserting stubs that print the values of the input parameters and proceed incrementally. But of course doing so will increase the time needed to do the port. I found it helpful to write small test programs to try out certain functions of an API, especially if Im using them for the first time. This is the case for me with functions in ATS, ATSUI, Quartz 2D, and Carbon events.
In debugging XEmacss redisplay code, I found the Quartz 2D call
What news would you consider worthy of being reported in the first 2005 entry of a pretty good programming blog :-)? How about this: I have ported XEmacs to Mac OS X!
In case youre wondering, this port is an entirely new effort and bears no relationship to the Carbon branch in the XEmacs CVS.
Why am I working on this? Havent I already ported Emacs to Mac OS X (and OS 8)? Well, I really dont have a good answer for this. I was kind of playing with with the XEmacs source code after Christmas (eating lots of turkey sandwiches) and one thing led to another :-). Regular readers of this blog already know I dont work on GNU Emacs any more because I was finding it difficult to work with Emacs developers and deal with Emacs users. Ill probably find myself in the same kind of trouble again when this code for XEmacs is ready for release :-). Anyway Ill worry about that later.
Id say this however. Seeing that splash screen come up for the first time was just as exciting as when it did for Emacs 20 a few years ago. I was dancing around my iMac :-)!
Technologically, this new port will have many advantages over Carbon Emacs (remember, I also wrote that so Im not bashing other people). It uses the ATSUI, ATS, and Quartz 2D APIs, which will allow very interesting things to be done: e.g., transparency and Unicode fonts, just to name two! XEmacs is much better structured than Emacs and the port will be a lot cleaner and easier to extend and improve on. I also know a little more so I can write better code. The disadvantage is there seem to be fewer people using XEmacs than Emacs. Lets try to change that :-).
Less-Known Facts About Emacs
Less-Known Facts About Emacs
|Copyright © 2003, 2004, 2005 Andrew Choi (Contact Information).||Created with FCBlog|