     [file version.texi not included]

The libRUIN Manual
******************

This manual describes the libRUIN rendering library.

Copyright © UPDATED Julian Graham.

     Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.  A copy of the license is included in the section entitled ``GNU Free Documentation License''.

This reference manual documents libRUIN, a C library that performs rendering for XML user-interface documents using the Ncurses terminal control library.

Introduction
************

libRUIN is a Renderer for User Interfaces in Ncurses. It is a library that can be embedded in arbitrary applications that allows developers to design user interfaces in any of several XML dialects that are suitable for interface mark-up and will display these interfaces and manage input handling for them using the Ncurses terminal control library.

This manual expects a basic familiarity with the C and Scheme programming languages. New users may wish to read the chapter Application design with libRUIN, as this covers the basic requirements for use and gives an overview of design considerations.

Application design with libRUIN
*******************************

libRUIN is intended to vastly simplify the task of user interface management, which can often be the most frustrating aspect of application development. Even so, there are a few guidelines developers should follow to get the most out of libRUIN.

Integration with GNU Guile
==========================

libRUIN depends heavily on the GNU Guile Scheme interpreter for looking up document information and handling event flows.

Whether or not your application already uses Guile for other reasons, you will need to link your application with libguile and initialize Guile using one of Guile's initialization mechanisms. See the Guile documentation for more information.

Integration with GNU Ncurses
============================

The ruinview example application
================================

libRUIN is distributed with ruinview, a small example application that demonstrates how to initialize and use libRUIN. ruinview accepts two command-line arguments: the name of a file containing an XML user interface description to render, and a string giving the name of the XML dialect to use to render it (either ``xul'' or ``xhtml'').

The salient calls are as follows:

     ruin_init();

This prepares libRUIN for use by loading the relevant Scheme modules and stylesheets and initializing some internal data structures.

     w = ruin_window_new(stdscr, log);

Here we create a new ruin_window_t, initializing it with the default Ncurses WINDOW, ``stdscr,'' and using the log file handle that we opened a few lines earlier.

     ruin_draw_file(w, argv[1]);

These two calls (depending on which dialect is in use) actually do the painting of the window represented by ``w.''

     ruin_input_send(w, ch);

This call is made inside a loop that accepts input from the user and feeds it directly to the window for event handling. (A more sophisticated application might send only selected keystrokes to the window...)

Threading concerns
==================

While libRUIN itself is designed to be highly thread-safe, the libraries it depends on most heavily, Ncurses and Guile, bring a few issues to bear when it comes to writing a multi-threaded program.

Ncurses is not thread-safe. This means that all calls to Ncurses rendering functions -- including Ncurses initialization calls and the rendering calls made by libRUIN -- must originate from the same thread. Applications that already use Ncurses will already meet this requirement, but if you are designing a new application, keep this in mind.

The thread-safety of Guile is not well-tested at the moment, and certain older versions of Guile are known to be decidedly un- thread-safe. libRUIN expects to have normal access to the Guile API, so depending on the version of Guile you are using in your application, you may need to limit your use of Guile, Ncurses, and libRUIN to the same thread (recent versions of Guile claim to allow developers to make calls to Guile's API from more than one thread).

C API reference
***************

The principal mechanism for interacting with libRUIN is through its C API. The functions in the API fall into the following categories.

Utility functions
=================

The following functions should be used to start up and shut down libRUIN and initialize new window structures.

 -- Function: int ruin_init ()

     This function prepares libRUIN for use and must be called before any other parts of the libRUIN API are called. In particular, it loads and configures several important Scheme modules and parts of the Scheme<->C bridge. This function should be called only AFTER Guile has been initialized for the calling thread.

 -- Function: void ruin_shutdown ()

     Frees the memory used by libRUIN's internal bookkeeping structures. After calling ruin_shutdown, no parts of the libRUIN API may be used until ruin_init has been called again.

 -- Function: ruin_window_t* ruin_window_new (WINDOW *w, FILE *f)

     Allocates a new libRUIN window structure, initializing it with the Ncurses window structure W and a handle to a file F to which log messages related to rendering and event handling should be written. F may be NULL, in which no logging will take place.

 -- Function: void ruin_window_free (ruin_window_t *w)

     Frees the memory used by the libRUIN window structure W and removes W from libRUIN's internal bookkeeping structures.

Rendering interface
===================

The following functions can be used to paint windows that are being managed by libRUIN. The document to be rendered may be specified as SXML/SDOM, a C string, or the name of a file containing the document. Which function you choose should be determined by the format your document is in.

 -- Function: int ruin_draw (ruin_window_t *w, SCM xml)

     Paints the window given by W with the user interface markup given by XML. XML must be a Guile Scheme object containing an SXML or SDOM representation of an XML document.

 -- Function: int ruin_draw_string (ruin_window_t *w, char *xml)

     Paints the window given by W with the user interface markup given by XML. XML must be a NULL-terminated C string containing an XML document which will be parsed by libRUIN before being rendered.

 -- Function: int ruin_draw_file (ruin_window_t *w, char *filename)

     Paints the window given by W with the user interface markup given by XML. XML must be a NULL-terminated C string giving the name of a file containing an XML document which will be read and parsed by libRUIN before being rendered.

Input management functions
==========================

The following functions can be used to send input to a window that is being managed by libRUIN so that any event handlers registered on the document for user input can be executed.

 -- Function: void ruin_input_send (ruin_window_t *w, int c)

Scheme API reference
********************

The Scheme expressions that you register as handlers for UI events in your libRUIN application can draw from any loaded modules (those that you load yourself, via use-modules, or ones that are loaded automatically by libRUIN, such as SSAX, SDOM, and SCSS). libRUIN also provides a small Scheme API, described below, for accessing functionality that would not normally be available from Scheme.

Style manipulation functions
============================

 -- Function: ruin:get-style node property

 -- Function: ruin:set-style! node property value

Window manipulation functions
=============================

 -- Function: ruin:render node

 -- Function: ruin:focus-next node

     Sends the keyboard focus to the next element in the list of focusable elements for the libRUIN window structure to which the SXML/SDOM node NODE belongs. Note that NODE is used only to determine the identity of the window; to send focus to a particular element, use RUIN:FOCUS.

 -- Function: ruin:focus-prev node

     Sends the keyboard focus to the previous element in the list of focusable elements for the libRUIN window structure to which the SXML/SDOM node NODE belongs. Note that NODE is used only to determine the identity of the window; to send focus to a particular element, use RUIN:FOCUS.

 -- Function: ruin:focus node

     Sends the keyboard focus to the element given by NODE with respect to the libRUIN window structure to which the SXML/SDOM node NODE belongs.

SDOM/SCSS integration
=====================

As described earlier, libRUIN depends heavily on two Guile Scheme modules, SDOM and SCSS, which handle, respectively, the Document Object Model and Cascading Style requirements related to parsing and rendering XML documents. The following notes may be useful for understanding how to use these modules in Scheme code that you write that is accessed by libRUIN.

SCSS

For the most part, when you want to modify style information that applies to a node in your document, you should use the style management functions described earlier in libRUIN's Scheme API. However, you might also want to modify the cascade directly. If so, you will need to notify libRUIN that it should update its internal cache of style information for the node or document to which you think your updated style information will apply. To do this, call the following function after you have made your modifications.

 -- Function: ruin:clear-style-cache! node

     If NODE is a node in a document being managed by libRUIN, clear libRUIN's style cache for that node, ensuring that style lookups for this node will return updated style information. To force a cache clear for the entire document using the updated stylesheet, pass the SXML/SDOM document node (which you can obtain from the element itself) as NODE.

SDOM

CSS compliance
**************

The CSS recommendation was written with user agents in mind that support rasterized images, variable-width fonts, and a host of other entities that do not exist in the types of terminals supported by Ncurses. Although many aspects of the visual formatting model thus cannot be supported by libRUIN, attempts have been made to compensate via the mechanisms below. Where necessary, rationale for libRUIN's rendering quirks has been provided.

Lengths
=======

There are several different units of width defined in CSS, but libRUIN only supports two of them in a way that could be called ``natively.'' These are ``ex'' and ``em,'' and they are mapped, respectively, to the height and width of a single terminal character. The other units are established as follows:

Table TK

Fonts and text
==============

     [file fdl.texi not included]