home *** CD-ROM | disk | FTP | other *** search
- Using the X11 C library from Scheme->C
- --------------------------------------
-
- One of the goals of the Scheme->C project has been to produce a Lisp which is
- able to co-exist with other languages. One use for such a language is as
- "glue" for constructing X window applications. As a first step down this path,
- a set of interfaces to X11's Xlib have been generated. These allow a Scheme
- programmer to execute X applications written in Scheme within the Scheme
- interpreter, or as stand-alone Scheme programs.
-
-
- An Example
- ----------
-
- Before going into any detail, an example is in order. This example is a Scheme
- version of the initial sample program from Oliver Jones' book, "Introduction to
- the X Window System":
-
- (module hello
- (main main)
- (with xlib))
-
- (define (HELLO-WORLD)
- (let* ((hello "Hello, World")
- (hi "Hi!")
- (dpy (let ((x (xopendisplay "")))
- (if (null-pointer? x)
- (error 'hello-world "DISPLAY is not defined"))
- x))
- (screen (xdefaultscreen dpy))
- (background (xwhitepixel dpy screen))
- (foreground (xblackpixel dpy screen))
- (window (xcreatesimplewindow dpy (xdefaultrootwindow dpy)
- 200 300 350 250 5 foreground background))
- (gc (xcreategc dpy window 0 (make-xgcvalues)))
- (event (make-xevent)))
- (xstorename dpy window "Hello, World in Scheme->C using Xlib")
- (xseticonname dpy window "hello")
- (xsetbackground dpy gc background)
- (xsetforeground dpy gc foreground)
- (xselectinput dpy window (+ buttonpressmask
- (+ keypressmask exposuremask)))
- (xmapraised dpy window)
- (let loop ()
- (ynextevent dpy event)
- (cond ((eq? (xevent-type event) expose)
- (xdrawimagestring (xevent-xexpose-display event)
- (xevent-xexpose-window event) gc 50 50
- hello (string-length hello))
- (loop))
- ((eq? (xevent-type event) mappingnotify)
- (xrefreshkeyboardmapping event)
- (loop))
- ((eq? (xevent-type event) buttonpress)
- (xdrawimagestring (xevent-xbutton-display event)
- (xevent-xbutton-window event) gc
- (xevent-xbutton-x event) (xevent-xbutton-y event)
- hi (string-length hi))
- (loop))
- ((and (eq? (xevent-type event) keypress)
- (equal? (ylookupstring+ event) "q"))
- (xfreegc dpy gc)
- (xdestroywindow dpy window)
- (xclosedisplay dpy))
- (else (loop))))))
-
- (define (MAIN clargs) (hello-world))
-
- The window system operations are confined to the procedure HELLO-WORLD. It
- starts with a LET* construct which sequentially binds variables. DPY is bound
- to the display pointer returned by xopendisplay, which is an interface
- procedure to XOpenDisplay. As with other Xlib interfaces to Scheme, the caller
- provides a Scheme string when a null-terminated string is expected. Since
- XOpenDisplay returns a single value, it is returned as the value of
- xopendisplay. Where possible, the values returned by the Xlib interfaces are
- type tagged to allow runtime type checking. Thus on a successful call to
- xopendisplay, one gets back a dotted-pair of the form: (DISPLAYP . 272961004).
- If the display couldn't be opened, then xopendisplay would return (DISPLAYP .
- 0) and the predicate NULL-POINTER? would return #T.
-
- The creation of the graphics context GC shows two more facets of the Xlib
- interface. First, since all interfaces are type checked as much as possible,
- xcreategc wants not just any pointer, but a pointer to an XGCValues struct as
- one of its arguments. In order to create an instance of that struct, one calls
- make-xgcvalues which returns a dotted pair of the form: (XGCVALUESP . "").
- There, the identifier identifies the type of object, and the string is the
- object.
-
- Following the creation of an XEvent struct, the window is decorated, events
- selected, and then the window is mapped. In the call to xselectevent, one can
- see the one-to-one translation between Xlib constants and case-insensitive
- Scheme globals.
-
- Following this setup is the event loop. Here, one can see structure access in
- action. The function xevent-type extracts the type from an XEvent structure.
- Once the particular event type has been discovered, the appropriate access
- functions can be used. Thus on a button press event, the coordinates of the
- button can be extracted by xevent-xbutton-x and xevent-xbutton-y. It also
- contains one example of the use of an augmented interface, the call to
- ylookupstring. Here, a simplified version of XLookupString returns the key
- string in a straight-forward manner. To differentiate such functions from the
- standard Xlib interfaces, they have the x in their name replaced by y.
-
-
- Xlib Constants
- --------------
-
- Having given a flavor of the Xlib interfaces in this example, it is now
- appropriate to examine their translation to Scheme in detail. The simplest
- items are those which are unsigned integer constants. These are found in such
- files as X.h, Xatom.h, and Xutil.h. These are translated on a one-to-one basis
- to top level Scheme values which have the same name and value. Inspite of the
- fact that Scheme is insensitive to case, this translation has only caused
- problems in translating the constants found in Xkeysym.h. There, there are
- symbols for upper case letters of the form XK_A and symbols for lower case
- letters of the form XK_a. In order to get around this, XK_A is represented as
- xk_a and XK_a is represented as xk_lca.
-
-
- Simple Data Types
- -----------------
-
- Many objects in Xlib are defined by the type XID which in turn is defined as an
- unsigned long value. Examples of such objects are Window, Drawable, Font,
- Pixmap, Cursor, Colormap, GContext, and KeySym. These are represented in
- Scheme as positive integers.
-
-
- Unions and Structs
- ------------------
-
- The Scheme interfaces provide functions to create and access user visible Xlib
- structs and unions. For example, Xcolor which is defined as:
-
- typedef struct{
- unsigned long pixel;
- unsigned short red, green, blue;
- char flags;
- char pad;
- } XColor;
-
- is handled within Scheme as follows. An instance of an XColor struct is
- represented by a pair consisting of the type tag XCOLORP (denoting a pointer to
- an XColor struct) and either a string or a number. The first form is used to
- represent an XColor structure within the Scheme system, and the second is used
- to denote one within Xlib.
-
- An instance of XColor is created by the function:
-
- (MAKE-XCOLOR)
-
- which returns a pair of the form: (XCOLORP . ""). Any object may be tested to
- see if it is a pointer to an XColor struct by:
-
- (ISA-XCOLORP? <any>)
-
- For example, (ISA-XCOLORP? (MAKE-XCOLOR)) evaluates to #T.
-
- Fields within an XColor struct may be accessed by the following functions:
-
- (XCOLOR-PIXEL <xcolor>)
- (XCOLOR-RED <xcolor>)
- (XCOLOR-GREEN <xcolor>)
- (XCOLOR-BLUE <xcolor>)
- (XCOLOR-FLAGS <xcolor>)
- (XCOLOR-PAD <xcolor>)
-
- Fields within an XColor struct may be set by:
-
- (XCOLOR-PIXEL! <xcolor> <value>)
- (XCOLOR-RED! <xcolor> <value>)
- (XCOLOR-GREEN! <xcolor> <value>)
- (XCOLOR-BLUE! <xcolor> <value>)
- (XCOLOR-FLAGS! <xcolor> <value>)
- (XCOLOR-PAD! <xcolor> <value>)
-
-
- Simple Arrays
- -------------
-
- A simple array is an array whose elements are not union or struct objects.
- Such array types have names ending in A. For example, UNSIGNEDA is type of an
- array of unsigned integers. One can make an new instance of an array of
- unsigned integers by:
-
- (MAKE-UNSIGNEDA <length>)
-
- test if an object is a pointer to such an array by:
-
- (ISA-UNSIGNEDAP? <any>)
-
- and determine the number of objects in the array by:
-
- (UNSIGNEDA-LENGTH <unsignedap>)
-
- Entries in such an array can be accessed by:
-
- (UNSIGNEDA <unsignedap> <index>)
-
- and values set in entries by:
-
- (UNSIGNEDA! <unsignedap> <index> <value>)
-
- Finally, one can convert between lists and arrays by:
-
- (UNSIGNEDA->UNSIGNED-LIST <unsignedap>)
- (UNSIGNED-LIST->UNSIGNEDA <list of unsigned numbers>)
-
- Another type of array often used with Xlib is CHARA which is an array of
- unsigned 8-bit integers. Similar creation and access procedures exist for it.
-
-
- Arrays of Struct and Union types
- --------------------------------
-
- Functions for operating on arrays of structures are defined in a similar
- manner. Here though, functions are not defined which allow access to fields in
- the structures while they are in the array. Thus for the type XColor, the
- following functions are defined:
-
- (XCOLORA-LENGTH <xcolorap>)
- (XCOLORA->XCOLOR-LIST <xcolorap>)
- (XCOLOR-LIST->XCOLORA <list of xcolorp>)
-
-
- Available X11 Data Definitions
- ------------------------------
-
- Using these techniques, the data definitions found in the following files have
- been converted:
-
- X.h
- Xatom.h
- Xlib.h
- Xresource.h
- Xutil.h
- cursorfont.h
- keysymdef.h (LATIN1 and DEC Private are only options)
-
-
- Utility Functions
- -----------------
-
- Several utility functions have been constructed to assist the user in
- manipulating pointers and bit masks for the Xlib interfaces. They are:
-
- (NULL-POINTER? <x>)
- predicate which returns #T iff <x> is a null pointer.
-
- (POINTER-TYPE <x>)
- returns the type name of the pointer <x>.
-
- (POINTER-VALUE <x>)
- returns the pointer value of the pointer <x>.
-
- (TYPE/VALUE->POINTER type value)
- constructs a pointer with type <type> and value <value>. This
- function is commonly used to construct "magic" pointer values, such
- as visual pointer with the value copyfromparent for a call to
- xcreatewindow.
-
-
- Xlib Procedure Interfaces
- -------------------------
-
- Having described the data representation conventions, it is now appropriate to
- turn to the procedure interfaces. Using a few simple conventions, access to
- all procedures defined in the book "X Window System" by Gettys, Newman, and
- Scheifler has been provided from Scheme. Efforts have been made to not change
- how these functions act so that existing documentation can be used.
-
- The argument passing conventions are:
-
- - Xlib arguments which are null terminated strings can be
- supplied as Scheme strings.
-
- - Xlib arguments which return a value of known size are
- omitted. For example, one does not call xnextevent with a
- pointer to an XEvent object. However, one must provide the
- the return arguments for XAllocColorCells as the array and
- its length are computed at runtime.
-
- - Xlib arguments which are pointers to some object must be of
- the correct object type.
-
- The value return conventions are:
-
- - Xlib procedures which do not return a value, return #F.
-
- - Xlib procedures which return a single value, return it.
-
- - Xlib procedures which return multiple values return them as
- a list.
-
- - Xlib procedures which return a pointer to a null terminated
- string return a Scheme string, unless the user must call to
- XFree to return the string in which case a charAP pointer is
- returned.
-
-
- Augmented Xlib Procedure Interfaces
- -----------------------------------
-
- As earlier noted, a few functions have been augmented by adding additional
- procedural interfaces. These procedures are identified by the fact that their
- names start with Y rather than X. In some cases, the Xlib versions still
- exist, but in others they do not as the interface was not appropriate for
- access from Scheme. The functions that exist to date are:
-
- (YFREE <any-pointer>)
- returns storage, where <any-pointer> is either a tagged or
- untagged pointer.
-
- (YQUERYTREE <display-ptr> <window>)
- returns a list of three elements: the root window, the parent
- window of <window>, and a list of the children of <window>.
-
- (YGETATOMNAME <display-ptr> <atom>)
- returns a string which is the name of <atom>.
-
- (YLISTPROPERTIES <display-ptr> <window>)
- returns a list of atoms which indicate the properties that are
- associated with <window>.
-
- (YLISTFONTS <display-ptr> <pattern> <maxnames>)
- returns a list of font names (less than or equal to <maxnames>
- in length) which match <pattern>.
-
- (YLISTFONTSWITHINFO <display-ptr> <pattern> <maxnames>)
- returns a list of lists (less than or equal to <maxnames> in
- length) which match <pattern>. Each list element is a list
- of a font name and an XFontstruct.
-
- (YSETFONTPATH <display-ptr> <directories>)
- sets the font search path to the list of strings
- <directories>.
-
- (YGETFONTPATH <display-ptr>)
- returns the list of directories which is the current font
- search path.
-
- (YLISTINSTALLEDCOLORMAPS <display-ptr> <window>)
- returns a list of the currently installed colormaps.
-
- (YNEXTEVENT <display-ptr> <event>)
- returns the next event in the event structure <event>.
-
- (YSELECT <display-ptr> <input-port>... <seconds> <microseconds>)
- waits up to <seconds> <microseconds> for events for <display-ptr>
- or input on one of the <input-port>'s. If events arrive then
- <display-ptr> is returned, if input arrives then the appropriate
- <input-port> is returned, otherwise #F is returned.
-
- (YGETMOTIONEVENTS <display-ptr> <window> <start> <stop>)
- returns a list of motion events. Each event is a list of
- three elements: time, x-position, and y-position.
-
- (YSETSTANDARDPROPERTIES <display-ptr> <window> <name> <icon_string>
- <icon_pixmap> <commands> <hints>)
- sets the <window>'s standard properties. Arguments are as
- expected by XSetStandardProperties, except that <commands> is
- a list of strings.
-
- (YFETCHNAME <display-ptr> <window>)
- returns the <window>'s name or #F if it is unnamed.
-
- (YGETICONNAME <display-ptr> <window>)
- returns the <window> icon's name or #F if it is unnamed.
-
- (YSETCOMMAND <display-ptr> <window> <commands>)
- sets the <window>'s commands to the list of strings
- <commands>.
-
- (YGETWMHINTS <display-ptr> <window>)
- returns either the XWMHints for <window> or #F when no hints
- have been provided.
-
- (YSETICONSIZES <display-ptr> <window> <iconsizelist>)
- sets the icon sizes to the list of XIconSize structures.
-
- (YGETICONSIZES <display-ptr> <window>)
- returns either a list of XIconSize hints, or #F when no hints
- have been provided.
-
- (YSETCLASSHINT <display-ptr> <window> <name-class>)
- sets the <window> class hint to the list of two strings
- <name-class>.
-
- (YGETCLASSHINT <display-ptr> <window>)
- returns either a list of <window> name and class, or #F when
- no class hints have been supplied.
-
- (YLOOKUPSTRING <event>)
- returns the keyboard string associated with the event.
-
- (YLOOKUPSTRING <event> #T)
- (YLOOKUPSTRING <event> #T <xcomposestatus>)
- returns a list consisting of the keyboard string and the
- KeySym associated with the event.
-
- (YLOOKUPSTRING <event> #F <xcomposestatus>)
- returns a list of the keyboard string associated with the
- event and #F.
-
-
- Availability
- ------------
-
- The Xlib interfaces are found in Scheme->C interpreters named scixl. Libraries
- containing the interfaces scxl.a. In order to correctly link with the
- interfaces, a compiled program must include a (with xlib) clause in its module
- expression. When a program is compiled which uses these interfaces, warnings
- will be generated as there are no external declarations. Stand-alone programs
- produced in this manner are large as they contain all the Xlib interfaces.
-
- Smaller programs can be produced by having the application include the inline
- versions of the interfaces found in the .sch files and then linking with the
- appropriate object files.
-