I have just spent many hours trying to get to the bottom of what has broken the x11 client and i am *very* sorry to say i feel the problem is *far* more serious than i first though it would be!
Sadly, the 'common' interface for the client's has started to become undermined in favour of the GTK client only (i will explain how/why later). The original idea of having a common interface was so that new clients *could* be written/ported to new toolkits, OS's, etc *easily* - WITHOUT having to do more than implement several (OS/toolkit specific) functions. This meant that whenever things were changed in the 'common' interface, they would be reflected in *all* the clients *without* much need for them to be changed drastically (ie: the 'toolkit' specific client was *only* responsible for display, user input, etc). This *was* a very sound idea, and whoever designed it this way, had abviously got a good idea of what they were doing (for a counter-example, look at the source for freeciv!).
Extract taken dirrectly from the source (x11.c & gx11.c):
/*
* This file handles mose of the windowing stuff. The idea is
* that all of it is in one file, so to port to different systems
* or toolkits, only this file needs to be updated. All windowing
* variables (display, gc's, windows, etc), should be stored in
* this file as statics.
* This file is largely a combination of the common/xutil.c and server/xio.c
* file. While I don't think this was a particulary great interface, the code
* was there, and I figured it was probably easier to re-use that
* code instead of writing new code, plus the old code worked.
*
*/
/* Most functions in this file are private. Here is a list of
* the global functions:
*
* draw_color_info(int color, char*buf) - draws text in specified color
* draw_info - draw info in the info window
* end_windows - used when exiting
* init_windows - called when starting up
* load_images - creates the bitmaps and pixmaps (if being used)
* create_pixmap - creates a pixmap from given file and assigns to
* the given face
* create_xpm - as create_pixmap, but does an XPM image
*
* draw_stats(int) - draws the stat window. Pass 1 to redraw all
* stats, not only those that changed
*
* draw_message_window(int) - draws the message window. Pass 1 to redraw
* all the bars, not only those that changed.
*
* draw_look, draw_inv: Update the look and inventory windows.
*
* NOTE: create_pixmap and create_xpm can be empty functions if the
* client will always use fonts - in that case, it should never
* request Bitmap or Pixmap data, and thus not need the create
* functions above
*
* Only functions in this file should be calling functions like
* draw_stats and draw_message_window with redraw set - functions
* in other files should always pass 0, because they will never have
* the information of whether a redraw is needed.
*/
Notice how it even *had* the idea of writting true 'rouge-like' (text-only) iterfaces etc!
I have looked into the client-side code quite seriously now, and as far as i can tell it *would* take very few man hours to write a new client using this clever (coding) interface... whether it was written in: raw X11R6, GTK, GDI, Direct-X, or any other toolkit/windowing system that was written to work/compile with C. I am very sorry to find that this is no longer the case, and the situation *will* only become worse over time - if this is not recified very quickly!
You may be asking yourself what the big problem is... I shall explain what *will* keep happening if this 'common' interface is not maintained:
1. Someone will write a new client, unable to use the features of the 'common' interface, they will copy large sections of the GTK client into their code.
2. The GTK code will get updated in parallel with server chages (as has just happened!).
3. The other clients will no longer work properly, until they copy the new code from the GTK client.
4. Eventually they will not be maintained, as the x11 client appears to be now, and they *will* become abandonware.
This scenario will happen *repeatedly* and eventually this code 'folking' will mean only the GTK client exists - leaving the future of cf down to the maintanance of GTK. You may well say "the GTK library is open source and will be maintained, so what is the problem?" - if you have been coding as long as i have, you will know this is simply not the case, and that libraries get obseleted and new (majour) versions are released to reflect hardware changes etc... This has happened repeatedly with comercial and non-comercial libraries and even X11R6 and the windows GDI libraries will go, but they have proved themselves and outlasted a lot of libraries over the yearsi (belive me!). For example, the cf cleint currenly uses v1.* of the GTK libs, and GTK2 *will* eventually take it's place, leaveing unmaintained v1.* code, and an *awfull* lot of work to eventualy convert the code, if not a total rewrite! For example:
Extract taken dirrectly from the source (gx11.c:void draw_info()):
/* draw_info adds a line to the info window. For speed reasons it will
* automatically freeze the info window when adding text to it, set the
* draw_info_freeze variable true and the actual drawing will take place
* during the next do_timeout at which point it is unfrozen again. That way
* we handle massive amounts of text addition with a single gui event, which
* results in a serious speed improvement for slow client machines (and
* above all it avoids a gui lockup when the client becomes congested with
* updates (which is often when you're in the middle of fighting something
* serious and not a good time to get slow reaction time)).
*
* MSW 2001-05-25: The removal of input from the text windows should
* work, and in fact does about 90% of the time. But that 10% it
* doesn't, the client crashes. The error itself is in the gtk library,
* to hopefully they will fix it someday. The reason to do this is
* to keep these buffers a reasonable size so that performance stays
* good - otherewise, performance slowly degrades.
*/
I would like to add that (in this case) it is NOT an "error itself is in the gtk library" (in this function at least), as i have disproved this by rewriteing this code to use terminal output (along with many other functions), in the hope of tracking down the reason the GTK client leaks 'X-server resources' (not a normal mem-leak), BUT i have not yet found the reason and it could well be and "error itself is in the gtk library" - in a totally differnt part of the code!
Now consider what would be the scenario if the 'common' (codeing) interface were maintained:
1. Someone will write a new client, useing the common interface to do most of the work (ie: only toolkit, window system or even terminal specific stuff).
2. The common iterface is updated, to add new features etc (such as the larger than 32x32 face stuff).
3. ALL the clients continue to work *without* the need for any copying of code from another interface, and most likely without the need for further alteration of eash individual client's code (assuming they are open-source, unlike DX...).
Now i shall explain the problem i have found:
The reason the x11 client has broken, is NOT because of it being unmaintained etc, it is simply because the common interface has not been properly used to add the large (>32x32) face/tile support... The x11 client will need major changes to add this feature, as it has no knowledge of this, eg:
Extract taken dirrectly from the source (gx11.h):
typedef struct {
void *icon_mask, *icon_image;
uint16 icon_width, icon_height;
void *map_mask, *map_image;
uint16 map_width, map_height;
void *fog_image;
} PixmapInfo;
Extract taken dirrectly from the source (map.c:void gtk_draw_map()):
if (the_map.cells[mx][my].tails[layer].face &&
pixmaps[the_map.cells[mx][my].tails[layer].face]->map_image) {
...
gdk_draw_pixmap(mapwindow, mapgc,
pixmaps[the_map.cells[mx][my].tails[layer].face]->map_image,
src_x, src_y, x * map_image_size, y * map_image_size,
map_image_size, map_image_size);
...
}
This could be fixed in the x11.c file, but this *will* result in the type of client 'folking' scenario i described above, and i *could* do it with only a few man hours of coding time (not an easy fix, but if the x11 client used the same structure elements, set properly, along with this test: it *would* work). BUT, why bother? This will only fix the x11 client until the next server/GTK client (paired) update is done, and the x11 client is doomed to either constant maintanance or abandonware... there is very little point in wasting valuable time on a problem which *could* have been avoided if care had been taken to maintain the 'common' (coding) interface, as the original authur had designed. Looking at this code, it *would* have taken very little effort to alter the x11.c code to use large face/tile support, if and only if the 'common' files had been updated properly.
This is only the begining of problems for future and current cf clients, and i know which scenario i would like to see happen, and if the ultimate aim of CF is to get to the stage of a single client relying on a single library such as GTK: please remember what i said here in 5 years time! I *have* seen, and suffered myself from, this sort of disaster before. I belive the original designer of the 'common' (coding) interface had great foresight and tried very hard to avoid this type of scenario!
Again, as with my last post on the metalforge update, i am sorry if i sound very 'to-the-point' and sorry if you read this as a non-coder (please don't get confused with user-interfaces and coding-interfaces etc!). Please feel free to copy this to the IRC channel, or post it to a more suitable forum (i am happy to explain futher the exact x11 problem and possible [temporay] fix, but see little point in making this post even larger!). Also i am sorry to point this problem out, and to the person who wrote the code i question here - don't feel bad about it, this is only the begining of future problems, and i only wish to see cf continue and thrive without ultimate disaster...
Thanks - Juk
