Appendix B. X10 Compatibility

X11 includes a conversion library, so that X10.4 applications can be easily ported to X11, albeit with a loss of performance. In addition, there are a few X10 routines that provide functionality missing in X11, which may still be used. This appendix discusses XDraw ()and related commands and association table routines for data management.

These functions are provided for compatibility with X Version 10. They are considered a part of Xlib even though they exist in a separate library. They can be used by including the file <X11/X10.h> and linking with the -loldX library.

X Version 11 XDraw now provides all the functionality of the X Version 10 routines XDraw, XDrawDashed, and XDrawPatterned. X Version 11 XDrawFilled() now provides the functionality of the old XDrawFilled() and XDrawTiled. These routines now use the GC to specify the fill, tile or stipple, line styles, etc.

The association table routines are described next in this appendix. They are also carried over from X10, although their functionality is also provided by the context manager routines described in Chapter 15, “Other Programming Techniques” However, there are no performance penalties for using association tables if you prefer them.

See Volume Two, for complete information on using any X10 compatibility function.

XDraw and XDrawFilled()

XDraw and XDrawFilled() call other Xlib routines, not the server directly. If you just have straight lines to draw, using XDrawLines() or XDrawSegments() is much faster. If you want to draw spline curves in a portable fashion, you currently have no choice but to use XDraw until a standard spline extension is adopted.

XDraw draws an arbitrary polygon or curve. The figure drawn is defined by a list of vertices (vlist). The points are connected by lines as specified in the flags in the vertex structure. In X Version 11, XDraw provides all the functionality of the X Version 10 routines XDraw, XDrawDashed, and XDrawPatterned. XDrawFilled() now provides the functionality of the old XDrawFilled() and XDrawTiled. The fill, pattern, line_style, and tile are all controlled by the graphics context. Lines are properly joined according to the GC if they connect and make a closed figure.

The error status returned is the opposite of what it was under X Version 10, conforming to the X Version 11 standard that 0 indicates failure. The VertexDrawLastPoint flag and the routines XAppendVertex and XClearVertexFlag from X Version 10 are not supported.

The vlist and vcount arguments of XDraw and XDrawFilled() control the line or area that is drawn:

vlist 

Specifies a pointer to the list of vertices which indicate what to draw.

vcount 

Specifies how many vertices are in vlist.

Each Vertex, as defined in <X11/Xlib.h>, is a structure with the following members:

Example B-1. The Vertex structure for XDraw

typedef struct _Vertex {
   short x,y;
   unsigned short flags;
} Vertex;

The x and y members are the coordinates of the vertex. These coordinates are interpreted according to the flags.

The flags member, as defined in Xlib.h, is a mask made by ORing the symbols listed in Table B-1.

Table B-1. Vertex Flags

Flag

Bit

If Not Set

VertexRelative

0

Absolute

VertexDontDraw

1

Draw

VertexCurved

2

Straight

VertexStartClosed

3

Not closed

VertexEndClosed

4

Not closed

XDraw fails (returns 0) only if it runs out of memory or is passed a Vertex list which has a vertex with VertexStartClosed set not followed by a vertex with VertexEndClosed set. The x and y coordinates in Vertex are relative to the upper-left inside corner of the drawable if VertexRelative is not specified in flags or to the previous vertex if VertexRelative is specified. The first vertex must be an absolute vertex.

If VertexDontDraw is specified in flags, no line or curve is drawn from the previous vertex to this one. This is analogous to picking up the pen and moving it to another place before drawing another line.

If VertexCurved is specified in flags, a spline algorithm is used to draw a smooth curve from the previous vertex through the current one to the next vertex. Otherwise, a straight line is drawn from the previous vertex to the current one. You should set VertexCurved in flags only if a previous and next vertex are both defined, either explicitly or through the definition of a closed curve. If VertexStartClosed is specified, then this point marks the beginning of a closed curve. This vertex must be followed later in the array by another vertex whose absolute coordinates are identical and which has VertexEndClosed specified in its flags.

It is permissible for both the VertexDontDraw and the VertexCurved bits to be 1. This is useful to define the previous point for the smooth curve, without drawing until the current point.

Example B-2 shows a routine that draws a box on the root window for use by the window manager described in Chapter 16, “Window Management” Of course, you would want to create the GC in the calling routine if draw_box were to be called more than once.

Example B-2. draw_box implemented with X Version 10 XDraw

draw_box(display, screen_num, left,top,right,bottom)
Display *display;
int screen_num;
int left,top,right,bottom;
   {
   Vertex corner[5];
   int vertexcount = 5;
   int planes = FIRST_PLANE;
   GC gc;
   /* Create graphics context */
   /* Ignore XGCvalues and use defaults */
   gc = XCreateGC(display, RootWindow(display, screen_num), 0,
         NULL);
   /* Set graphics context to include font */
   XSetFunction(display, gc, GXxor);
   XSetForeground(display, gc, BlackPixel(display,screen_num));
   XSetPlaneMask(display, gc, planes);

   corner[0].x = left;
   corner[0].y = top;
   corner[0].flags = 0;

   corner[1].x = left;
   corner[1].y = bottom;
   corner[1].flags = 0;
   corner[2].x = right;
   corner[2].y = bottom;
   corner[2].flags = 0;

   corner[3].x = right;
   corner[3].y = top;
   corner[3].flags = 0;

   corner[4].x = left;
   corner[4].y = top;
   corner[4].flags = 0;

   XDraw(display, RootWindow(display, screen_num), gc, corner,
         vertexcount);
   XFlush();
   }


Association Tables

Association tables provide a fast lookup table for data that must be searched frequently. They are implemented as a linked list of structures. To use these functions, you must link in -loldX, the X10 compatibility library.

Association tables associate arbitrary information with resource IDs. This is similar to the context manager, but the resource IDs used with association tables are existing resources, not created for the purpose of storing data for later retrieval.

An XAssocTable can be used to type X resources. For example, the user may wish to have three or four “types” of windows, each with different properties. This can be accomplished by associating each X window ID with a pointer to a window property data structure defined by the programmer. The generic type for resource IDs is XID.

There are a few guidelines that should be observed when using an XAssocTable:

  • All XIDs are relative to the currently active display. Therefore, if you are using multiple displays, you need to be sure the correct display is active before performing an XAssocTable operation. XAssocTable imposes no restrictions on the number of XIDs per table, the number of XIDs per display, or the number of displays per table.

  • Because of the hashing scheme used by the association mechanism, the following rules for determining the size of XAssocTables should be followed. Associations will be made and looked up more efficiently if the table size (number of buckets in the hashing system) is a power of two and if there are not more than eight XIDs per bucket.

XCreateAssocTable() creates an association table. To create an entry in a specific XAssocTable, use XMakeAssoc(). Some size suggestions might be: use 32 buckets per 100 objects; a reasonable maximum number of objects per buckets is 8. XMakeAssoc() inserts data into an XAssocTable keyed on an XID. XDeleteAssoc() deletes an association in an XAssocTable keyed on its XID. Data is inserted into the table only once. Redundant inserts are meaningless and cause no problems. The queue in each association bucket is sorted from the lowest XID to the highest XID. Redundant deletes (and deletes of nonexistent XIDs) are meaningless and cause no problems. Deleting associations in no way impairs the performance of an XAssocTable.

XLookUpAssoc() retrieves the data stored in an XAssocTable by its XID. If an appropriately matching XID can be found in the table, the routine will return the data associated with it. If the XID cannot be found in the table, the routine will return NULL.

XDestroyAssocTable() frees the memory associated with a specific XAssocTable. Using an XAssocTable after it has been destroyed is guaranteed to have unpredictable and probably disastrous consequences!