Some Useful Functions
*********************

Misc. Functions
===============

The following routine can be used to sound the keyboard bell (if capable):

     void fl_ringbell(int percent);

where percent can range from -100 to 100 with 0 being the default volume setting of the keyboard. A value of 100 indicates maximum volume and a value of -100 minimum volume (off). Note that not all keyboards support volume variations.

To get the user name who's running the application you can use the routine

     const char *fl_whoami(void);

To get a string form of the current date and time, the following routine is available:

     const char *fl_now(void);

The format of the string is of the form "Wed Jun 30 21:49:08 1993".

The following time related routine might come in handy

     void fl_gettime(unsigned long *sec, unsigned long *usec);

Upon function return sec and usec are set to the current time, expressed in seconds and microseconds since 00:00 GMT January, 1970. This function is most useful for computing time differences.

Th function

     int fl_mode_capable(int mode, int warn);

allows to determine the visual classes the system is capable of. mode must be one of GrayScale, StaticGray, PseudoColor, StaticColor, DirectColor and TrueColor and the function returns 1 if the system is capable of displaying in this visual class and 0 otherwise. If warn is set a warning is printed out in case the capability asked for isn't available.

Finally

     int fl_msleep(usigned long msec);

allows to wait for a number of milli-seconds (with the best resolution possible on your system).

Windowing Support
=================

Some of the following routines are also used internally by the Forms Library as an attempt to localize window system dependencies and may be of some general use. Be warned that these routines may be subject to changes, both in their API and/or functionality.

You can create and show a window with the following routines

     Window fl_wincreate(const char *name);
     Window fl_winshow(Window win);

where the parameter win of fl_winshow() is the window ID returned by fl_wincreate(). The title of the window is set by the name argument.

Between the creation and showing of the window other attributes of the window can be set. Note that a window opened this way is always a top level window and uses all the Forms Library's defaults (visual, depth etc.). Another thing about fl_winshow() is that it will wait for and gobble up the first Expose event and you can draw into the window immediately after the function returns.

It is sometimes more convenient to create and show a window in a single call using

     Window fl_winopen(const char *name);

This will open a (top-level) window with the title name. A window so opened can be drawn into as soon as the function returns, i.e. fl_winopen() waits until the window is ready to be drawn to.

The newly opened window will have the following default attributes

event_mask
     ExposureMask, KeyPressMask, KeyReleaseMask, ButtonPressMask, ButtonReleaseMask, OwnerGrabButtonMask, ButtonMotionMask, PointerMotionMask, PointerMotionHintMask, StructureNotifyMask

backing_store
     as set by fl_cntl.backingStore

class
     InputOutput

visual
     same as Forms Library's default

colormap
     same as Forms Library's default

To make a top-level window a sub-window of another window use the following routine

     int fl_winreparent(Window win, Window new_parent);

The origin of the window win will be at the origin of the parent window new_parent. At the time of the function call, both the window and the parent window must be valid windows.

By default, a newly opened window will have a size of 320 by 200 pixels and no other constraints. You can modify the default or constraints using the following routines prior to calling fl_winopen():

     void fl_initial_winsize(FL_Coord w, FL_Coord h);
     void fl_winsize(FL_Coord w, FL_Coord h);

These two routines set the preferred window size. w and h are the width and height of the window in pixels. fl_winsize() in addition will make the window non-resizeable (but you can still resize the window programmatically) by setting the minimum and maximum window size to the requested size via WMHints. The effect of a window having this property is that it can't be interactively resized (provided the window manager cooperates).

It is sometimes desirable to have a window that is resizeable but only within a useful range. To set such a constraint use the following functions:

     void fl_winminsize(Window window, FL_Coord minw, FL_Coord minh);
     void fl_winmaxsize(Window window, FL_Coord maxw, FL_Coord maxh);

These two routines can also be used after a window has become visible. For windows still to be created/opened, use None for the window parameter. For example, if we want to open a window of 640 by 480 pixels and have it remain resizeable but within a permitted range, code similar to the following can be used:

     fl_initial_winsize(640, 480);
     fl_winminsize(None, 100,100);
     fl_winmaxsize(None, 1024,768)
     win = fl_winopen("MyWin");

In addition to the window size preference you can also set the preferred position of a window to be opened:

     void fl_winposition(FL_Coord x, FL_Coord y);

where x and y are the coordinates of the upper-left corner of the window relative to the root window.

Alternatively, you can set the geometry (position and size) in a single function call:

     void fl_initial_wingeometry(FL_Coord x, FL_Coord y,
                                 FL_Coord w, FL_Coord h);
     void fl_wingeometry(FL_Coord x, FL_Coord y,
                         FL_Coord w, FL_Coord h);

Again, windows for which fl_wingeometry() had been created will not allow interactive resizing later on.

There are further routines that can be used to change other aspects of the window to be created:

     void fl_winaspect(Window win, FL_Coord x, FL_Coord y);

This will set the aspect ratio of the window for later interactive resizing.

To change the window title (and its associated icon title) use

     void fl_wintitle(Window win, const char *title);

To change the icon title only use the routine

     void fl_winicontitle(Window win, const char *title);

To install an icon for the window use

     void fl_winicon(Window win, Pixmap icon, Pixmap mask);

You can suppress the window manager's decoration or make a window a transient one by using the following routines prior to creating the window

     void fl_noborder(void);
     void fl_transient(void);

You can also set the background of the window to a certain color using the following call

     void fl_winbackground(Window win, unsigned long pixel);

It is possible to set the steps by which the size of a window can be changed by using

     void fl_winstepsize(Window win, int xunit, int yunit);

where xunit and yunit are the number of pixels of changes per unit in x- and y- directions, respectively. Changes to the window size will be multiples of these units after this call. Note that this only applies to interactive resizing.

To change constraints (size and aspect ratio) on an active window, you can use the following routine

     void fl_reset_winconstraints(Window win);

The following routines are available to get information about an active window win:

     void fl_get_winsize(Window win, FL_Coord *w, FL_Coord *h);
     void fl_get_winorigin(Window win, FL_Coord *x, FL_Coord *y);
     void fl_get_wingeometry(Window win, FL_Coord *x, FL_Coord *y,
                             FL_Coord *w, FL_Coord *h);

All returned values are in pixels. The origin of a window is measured from the upper left corner of the root window.

To change the size of window programmatically the following routine is available:

     int fl_winresize(Window win, FL_Coord neww, FL_Coord newh);

In addition to resizing the window, this routine will keep the original constraints. For example, if a window was not permitted to be interactively resized it will remains unresizeable after the resize. Resizing is done by keeping the origin constant relative to the root window.

To move a window without resizing it, use the following call

     void fl_winmove(Window win, FL_Coord newx, FL_Coord newy);

To move and resize a window, use the following routine

     void fl_winreshape(Window win, FL_Coord newx, FL_Coord newy,
                        FL_Coord neww, FL_Coord newh);

The following routine is available to iconify a window

     void fl_iconify(Window win);

To make a window invisible use

     void fl_winhide(Window win);

A window hidden this way can be shown again later using fl_winshow().

To hide and destroy a window, use the following calls

     void fl_winclose(Window win);

There will be no events generated from fl_winclose(), i.e. the function waits and gobbles up all events for window win. In addition, this routine also removes all callbacks associated with the closed window.

The following routine can be used to check if a window ID is valid or not

     int fl_winisvalid(Window win);

Note that excessive use of this function may negatively impact performance.

Usually an X application should work with window managers and accepts the keyboard focus assignment. In some special situations, explicit override of the keyboard focus might be warranted. To this end, the following routine exists:

     void fl_winfocus(Window win);

After this call keyboard input is directed to window win.

Cursors
=======

XForms provides a convenience function to change the cursor shapes:

     void fl_set_cursor(Window win, int name);

where win must be a valid window identifier and name is one of the symbolic cursor names (shapes) defined by standard X or the integer values returned by fl_create_bitmap_cursor() or one of the Forms Library's pre-defined symbolic names.

The X standard symbolic cursor names (all starts with XC_) are defined in <X11/cursorfont.h> (you don't need to explicitly include this as <forms.h> already does this for you). For example, to set a watch-shaped cursor for form form (after the form is shown), the following call may be made

     fl_set_cursor(form->window, XC_watch);

The Forms Library defines a special symbolic constants, FL_INVISIBLE_CURSOR that can be used to hide the cursor for window win:

     fl_set_cursor(win, FL_INVISIBLE_CURSOR);

Depending on the structure of the application program, a call of XFlush(fl_get_display()); may be required following fl_set_cursor().

To reset the cursor to the XForms's default (an arrow pointing northwest), use the following routine

     void fl_reset_cursor(Window win);

To change the color of a cursor use the following routine

     void fl_set_cursor_color(int name, FL_COLOR fg, FL_COLOR bg);

where fg and bg are the foreground and background color of the cursor, respectively. If the cursor is being displayed, the color change is visible immediately.

It is possible to use cursors other than those defined by the standard cursor font by creating a bitmap cursor with

     int fl_create_bitmap_cursor(const char *source, const char *mask,
                                 int w, int h, int hotx, int hoty);

where source and mask are two (x)bitmaps. The mask defines the shape of the cursor. The pixels set to 1 in the mask define which source pixels are displayed. If mask is NULL all bits in source are displayed. hotx and hoty are the hotspot of the cursor (relative to the source's origin). The function returns the cursor ID which can be used in calls of fl_set_cursor() and fl_set_cursor_color() etc.

Finally, there is a routine to create animated cursors where several cursors are displayed one after another:

     int fl_create_animated_cursor(int *cur_names, int interval);

The function returns the cursor name (ID) that can be shown later via fl_set_cursor(). In the function call cur_names is an array of cursor names (either X standard cursors or cursor names returned by fl_create_bitmap_cursor()), terminated by -1. Parameter interval indicates the time each cursor is displayed before it is replaced by the next in the array. An interval about 150 msec is a good value for typical uses. Note that there is currently a limit of 24 cursors per animation sequence.

Internally animated cursor works by utilizing the timeout callback. This means that if the application blocks (thus the main loop has no chance of servicing the timeouts), the animation will stop.

See demo program cursor.c for an example use of the cursor routines.

Clipboard
=========

Clipboard is implemented in the Forms Library using the X selection mechanism, more specifically the XA_PRIMARY selection. X selection is a general and flexible way of sharing arbitrary data among applications on the same server (the applications are of course not necessarily running on the same machine). The basic (and over-simplified) concept of the X selection can be summarized as follows: the X Server is the central point of the selection mechanism and all applications running on the server communicate with other applications through the server. The X selection is asynchronous in nature. Every selection has an owner (an application represented by a window) and every application can become owner of the selection or lose the ownership.

The clipboard in Forms Library is a lot simpler than the full-fledged X selection mechanism. The simplicity is achieved by hiding and handling some of the details and events that are of no interests to the application program. In general terms, you can think of a clipboard as a read-write buffer shared by all applications running on the server. The major functionality you want with a clipboard is the ability to post data onto the clipboard and request the content of the clipboard.

To post data onto the clipboard, use the following routine

     typedef int (*FL_LOSE_SELECTION_CB)(FL_OBJECT *obj, long type);

     int fl_stuff_clipboard(FL_OBJECT *obj, long type,
                            const void *data, long size,
                            FL_LOSE_SELECTION_CB callback);

where size is the size (in bytes) of the content pointed to by data. If successful, the function returns a positive value and the data will have been copied onto the clipboard. The callback is the function that will be called when another application takes ownership of the clipboard. For textual content the application that loses the clipboard should typically undo the visual cues about the selection. If no action is required when losing the ownership a NULLq callback can be passed. The obj argument is used to obtain the window (owner) of the selection. type is currently unused. At the moment the return value of lose_selection_callback() is also unused. The data posted onto the clipboard are available to all applications that manipulate XA_PRIMARY, such as xterm etc.

To request the current clipboard content use the following routine

     typedef int (*FL_SELECTION_CB)(FL_OBJECT *obj, long type,
                                    const void * data, long size);

     int fl_request_clipboard(FL_OBJECT *obj, long type,
                              FL_SELECTION_CB callback);

where callback is the callback function that gets called when the clipboard content is obtained. The content data passed to the callback function should not be modified.

One thing to remember is that the operation of the clipboard is asynchronous. Requesting the content of the clipboard merely asks the owner of the content for it and you will not have the content immediately (unless the asking object happens to own the selection). XForms main event loop takes care of the communication between the requesting object and the owner of the clipboard and breaks up and re-assembles the content if it exceeds the maximum protocol request size (which has a guaranteed minimum of 16 kB, but typically is larger). If the content of the clipboard is successfully obtained the main loop invokes the lose selection callback of the prior owner and then the requesting object's callback function.

The function returns a positive number if the requesting object owns the selection (i.e. the callback could beinvoked before the function returned) and 0 otherwise.

If there is no selection the selection callback is called with an empty buffer and the length of the buffer is set to 0. In that case fl_request_clipboard() returns -1.