mss+@ANDREW.CMU.EDU (Mark Steven Sherman) (03/21/88)
"It turns out to be a bad interaction between buggy server code and brain-damaged ATK code." I could dreg up a whole series of related messages from the alpha and beta times of X that contain the phrase "brain-damaged" but instead, I will just relate the story and ask for a rational strategy. In the beginning, calls like XLoadFont and XLoadQueryFont were synchronous, returning a null pointer if the font was not usuable, e.g., did not exist. Life was simple and we in fact used your suggestion. A new tape came in the mail and Xlib kept crapping out. Examination of the problem showed that these calls were now considered asychronous and always returned immediately with a token for later use. Of course, when the token was used later, Xlib was unhappy that the font did not exist. After much nashing of teeth (see introductory remark), the official word was "you must *know* that your font exists before you start loading it. If you want to know, use XListFonts. It is simply too slow to require a synchronous server round trip for loading fonts." Thus the choice became either using XListFonts or trying to intercept the error that Xlib came back with. We pleaded for a simple way to intercept such an error, perhaps a way to make an arbitrary Xlib call synchronous with a return code (somewhere) that indicated if a problem occurred. Unforutnately, XSynch would not do the job. We were told how unreasonable we were and that I should set up a global error handler that would track all of the requests that I had suspicions about and watch for sequence numbers of replies coming back to ensure that an operation either succeeded or failed, since "obviously" an error would require a global strgatey to recover. Besides blowing modularity to hell, this required us getting into the internals of Xlib which we were assured were going to change as a natural consequence of evolution. Hence we came to use XListFont as a first approximation that a font exists (as you especially know well, our sequence of operations is not atomic, and just because we listed the font one statement ago, there is no guarantee that the font will be there during the next statement with the XLoadQuery call -- servers and networks go down, etc. We thought we were making a reasonable compromise. I will warn you now: there are several places where we have the same kind of problem. For example, it is nearly impossible to guarantee that you can read a bitmap from a window in the presence of window managers. Between the time you verify that it is present and the time you actually try to read it, the window manager could have closed the window. Again, it would be nice if we could just make that call synchronous and handle the error locally, but ...) Which brings us to the issue of font substitution. There are a number of questions. First, why do we do font substitution when an unavailable font is requested? Because our human factors people tell us that people like uniform fonts, eg., if they can say family F and size S, then we should not arbitrarily restrict them to whatever bitmaps we have on line (and crap out with "font unavailable, core dumped), but let them specifiy whatever they want and sometimes they will get it and sometimes an approximation. Why don't we report font substitutions? Again, our human factors people tell us that users don't like such messages coming out at them -- they are confused by something which they don't want to be bothered with. I have moved that code in and out several times now. Don't continue to flame at me, it won't help. When your human factors study shows that it's better to print out a message (for users, not system installers like us), then something might be done. Note: the Macintosh does it the same way, although I admit I also hate not knowing when funny things are happening in my system. Why do we set the fontpath? Because we are trying to correct a situation when we could not find a font. One of the reasons why a font might not have been found is that the path was reset by some other non-cooperating program. We set the path only when a font is not found. So we try to perform error recovery using guesses as to what happened. We append our path name to the end of list. How do you recommend programs that are not officially blessed get their application specific fonts? Or should everyone have to install their fonts in the one font directory? Or do you want to tell every user of a random X program, "before you start, type xsetroot -fp whatever, just do it and take my word for it". Most users around here don't stand for that. Why do we keep setting the font path so often? Because we naively hope that if the font wasn't there the first time, it might come back when a file server returns, network traffic is reduced, whatever the next time we try -- we could just do the substitution the first time and flag it as unavailable every other time it is used. Finally, how do we generate names for the substitiution? Empirically. We try first the exact name, under one of four different conventions that distributed X fonts come with. We have no control over the fact that different people chose different ways to name their fonts. All ATK knows about is a family, a size and a face code. From that it has to figure out a font name. If X had a standard way to name fonts, we would use it and be a lot better off. It doesn't and so we have to make our best guess. Note: if the matching algorithm worked correctly, we should never have an unavailable font, since we eventually fall back to either variable or fixed, which comes on the distribution. I admit: I didn't add any code to deal specifically with possible bugs in the matching algorithm. At some point I believe the documentation. I no longer maintain that code and I haven't looked at the latest Xlib doucmentation, but out of curiousity, is there an easy way to handle a 0-length font on the client side? -Mark
RWS@ZERMATT.LCS.MIT.EDU (Robert Scheifler) (03/25/88)
Date: Mon, 21 Mar 88 10:24 EST From: Mark Steven Sherman <mss+@andrew.cmu> In the beginning, calls like XLoadFont and XLoadQueryFont were synchronous, returning a null pointer if the font was not usuable, e.g., did not exist. I didn't see the beginning of this conversation, but as far as I know, XLoadQueryFont has always been and still is synchronous, returning a null pointer if the font doesn't exist. I am thus at a loss to understand both your gnashing of teeth and your lengthy message. I no longer maintain that code and I haven't looked at the latest Xlib doucmentation, but out of curiousity, is there an easy way to handle a 0-length font on the client side? I don't understand the question.