1@node Part V Some Useful Functions
2@chapter Some Useful Functions
3
4@ifnottex
5@menu
6* Misc. Functions::
7* Windowing Support::
8* Cursors::
9* Clipboard::
10@end menu
11
12@end ifnottex
13
14
15@node Misc. Functions
16@section Misc. Functions
17
18The following routine can be used to sound the keyboard bell (if
19capable):
20@findex fl_ringbell()
21@anchor{fl_ringbell()}
22@example
23void fl_ringbell(int percent);
24@end example
25@noindent
26where @code{percent} can range from -100 to 100 with 0 being the
27default volume setting of the keyboard. A value of 100 indicates
28maximum volume and a value of -100 minimum volume (off). Note that not
29all keyboards support volume variations.
30
31To get the user name who's running the application you can use the
32routine
33@findex fl_whoami()
34@anchor{fl_whoami()}
35@example
36const char *fl_whoami(void);
37@end example
38
39To get a string form of the current date and time, the following
40routine is available:
41@findex fl_now()
42@anchor{fl_now()}
43@example
44const char *fl_now(void);
45@end example
46@noindent
47The format of the string is of the form @code{"Wed Jun 30 21:49:08
481993"}.
49
50The following time related routine might come in handy
51@findex fl_gettime()
52@anchor{fl_gettime()}
53@example
54void fl_gettime(unsigned long *sec, unsigned long *usec);
55@end example
56@noindent
57Upon function return @code{sec} and @code{usec} are set to the current
58time, expressed in seconds and microseconds since 00:00 GMT January,
591970. This function is most useful for computing time differences.
60
61Th function
62@findex fl_mode_capable()
63@anchor{fl_mode_capable()}
64@example
65int fl_mode_capable(int mode, int warn);
66@end example
67@noindent
68allows to determine the visual classes the system is capable of.
69@code{mode} must be one of @code{GrayScale}, @code{StaticGray},
70@code{PseudoColor}, @code{StaticColor}, @code{DirectColor} and
71@code{TrueColor} and the function returns 1 if the system is capable
72of displaying in this visual class and 0 otherwise. If @code{warn} is
73set a warning is printed out in case the capability asked for isn't
74available.
75
76To find out the "depth" of the current display (basically the number
77of bits used for colors) use the function
78@findex fl_get_visual_depth
79@anchor{fl_get_visual_depth}
80@example
81int fl_get_visual_depth(void);
82@end example
83
84Finally
85@findex fl_msleep()
86@anchor{fl_msleep()}
87@example
88int fl_msleep(usigned long msec);
89@end example
90@noindent
91allows to wait for a number of milli-seconds (with the best resolution
92possible on your system).
93
94
95@node Windowing Support
96@section Windowing Support
97
98Some of the following routines are also used internally by the Forms
99Library as an attempt to localize window system dependencies and may
100be of some general use. Be warned that these routines may be subject
101to changes, both in their API and/or functionality.
102
103You can create and show a window with the following routines
104@findex fl_wincreate()
105@anchor{fl_wincreate()}
106@findex fl_winshow()
107@anchor{fl_winshow()}
108@example
109Window fl_wincreate(const char *name);
110Window fl_winshow(Window win);
111@end example
112@noindent
113where the parameter @code{win} of @code{@ref{fl_winshow()}} is the
114window ID returned by @code{@ref{fl_wincreate()}}. The title of the
115window is set by the @code{name} argument.
116
117Between the creation and showing of the window other attributes of the
118window can be set. Note that a window opened this way is always a top
119level window and uses all the Forms Library's defaults (visual, depth
120etc.). Another thing about @code{@ref{fl_winshow()}} is that it will
121wait for and gobble up the first @code{Expose} event and you can draw
122into the window immediately after the function returns.
123
124It is sometimes more convenient to create and show a window in a
125single call using
126@findex fl_winopen()
127@anchor{fl_winopen()}
128@example
129Window fl_winopen(const char *name);
130@end example
131@noindent
132This will open a (top-level) window with the title @code{name}. A
133window so opened can be drawn into as soon as the function returns,
134i.e., @code{@ref{fl_winopen()}} waits until the window is ready to be
135drawn to.
136
137The newly opened window will have the following default attributes
138@table @code
139@item event_mask
140@code{ExposureMask}, @code{KeyPressMask}, @code{KeyReleaseMask},
141@code{ButtonPressMask}, @code{ButtonReleaseMask},
142@code{OwnerGrabButtonMask}, @code{ButtonMotionMask},
143@code{PointerMotionMask}, @code{PointerMotionHintMask},
144@code{StructureNotifyMask}
145@item backing_store
146as set by @code{fl_cntl.backingStore}
147@item class
148@code{InputOutput}
149@item visual
150same as Forms Library's default
151@item colormap
152same as Forms Library's default
153@end table
154
155To make a top-level window a sub-window of another window use the
156following routine
157@findex fl_winreparent()
158@anchor{fl_winreparent()}
159@example
160int fl_winreparent(Window win, Window new_parent);
161@end example
162@noindent
163The origin of the window @code{win} will be at the origin of the
164parent window @code{new_parent}. At the time of the function call,
165both the window and the parent window must be valid windows.
166
167By default, a newly opened window will have a size of 320 by 200
168pixels and no other constraints. You can modify the default or
169constraints using the following routines prior to calling
170@code{@ref{fl_winopen()}}:
171@findex fl_initial_winsize()
172@anchor{fl_initial_winsize()}
173@findex fl_winsize()
174@anchor{fl_winsize()}
175@example
176void fl_initial_winsize(FL_Coord w, FL_Coord h);
177void fl_winsize(FL_Coord w, FL_Coord h);
178@end example
179@noindent
180These two routines set the preferred window size. @code{w} and
181@code{h} are the width and height of the window in pixels.
182@code{@ref{fl_winsize()}} in addition will make the window
183non-resizeable (but you can still resize the window programmatically)
184by setting the minimum and maximum window size to the requested size
185via @code{WMHints}. The effect of a window having this property is
186that it can't be interactively resized (provided the window manager
187cooperates).
188
189Also the state of the window when opening it can be influenced
190by the function
191@findex fl_initial_winstate()
192@anchor{fl_initial_winstate()}
193@example
194void fl_initial_winstate(int state);
195@end example
196where @code{state} is on of the XLib constants @code{NormalState} (the
197default) or @code{IconicState}, which will result in the opened window
198being iconified. The third possible constant, @code{WithdrawnState},
199doesn't make much sense in this context.
200
201It is sometimes desirable to have a window that is resizeable but only
202within a useful range. To set such a constraint use the following
203functions:
204@findex fl_winminsize()
205@anchor{fl_winminsize()}
206@findex fl_winmaxsize()
207@anchor{fl_winmaxsize()}
208@example
209void fl_winminsize(Window window, FL_Coord minw, FL_Coord minh);
210void fl_winmaxsize(Window window, FL_Coord maxw, FL_Coord maxh);
211@end example
212@noindent
213These two routines can also be used after a window has become visible.
214For windows still to be created/opened, use @code{None} for the window
215parameter. For example, if we want to open a window of 640 by 480
216pixels and have it remain resizeable but within a permitted range,
217code similar to the following can be used:
218@example
219fl_initial_winsize(640, 480);
220fl_winminsize(None, 100,100);
221fl_winmaxsize(None, 1024,768)
222win = fl_winopen("MyWin");
223@end example
224
225In addition to the window size preference you can also set the
226preferred position of a window to be opened:
227@findex fl_winposition()
228@anchor{fl_winposition()}
229@example
230void fl_winposition(FL_Coord x, FL_Coord y);
231@end example
232@noindent
233where @code{x} and @code{y} are the coordinates of the upper-left
234corner of the window relative to the root window.
235
236Alternatively, you can set the geometry (position and size) in a
237single function call:
238@findex fl_initial_wingeometry()
239@anchor{fl_initial_wingeometry()}
240@findex fl_wingeometry()
241@anchor{fl_wingeometry()}
242@example
243void fl_initial_wingeometry(FL_Coord x, FL_Coord y,
244                            FL_Coord w, FL_Coord h);
245void fl_wingeometry(FL_Coord x, FL_Coord y,
246                    FL_Coord w, FL_Coord h);
247@end example
248@noindent
249Again, windows for which @code{@ref{fl_wingeometry()}} had been
250created will not allow interactive resizing later on.
251
252There are further routines that can be used to change other aspects of
253the window to be created:
254@findex fl_winaspect()
255@anchor{fl_winaspect()}
256@example
257void fl_winaspect(Window win, FL_Coord x, FL_Coord y);
258@end example
259@noindent
260This will set the aspect ratio of the window for later interactive
261resizing.
262
263To change the window title (and its associated icon title) use
264@findex fl_wintitle()
265@anchor{fl_wintitle()}
266@findex fl_wintitle_f()
267@anchor{fl_wintitle_f()}
268@example
269void fl_wintitle(Window win, const char *title);
270void fl_wintitle_f(Window win, const char *fmt, ...);
271@end example
272@noindent
273While the first function only accepts a simple string for the window
274title the second one allows to pass a format string just like the one
275used for @code{printf()} etc. and an appropriate number of further
276arguments which are used to construct the title.
277
278To change the icon title only use the routines
279@findex fl_winicontitle()
280@anchor{fl_winicontitle()}
281@findex fl_winicontitle_f()
282@anchor{fl_winicontitle_f()}
283@example
284void fl_winicontitle(Window win, const char *title);
285void fl_winicontitle_f(Window win, const char *fmt, ...);
286@end example
287
288To install an icon for the window use
289@findex fl_winicon()
290@anchor{fl_winicon()}
291@example
292void fl_winicon(Window win, Pixmap icon, Pixmap mask);
293@end example
294
295You can suppress the window manager's decoration or make a window a
296transient one by using the following routines prior to creating the
297window
298@findex fl_noborder()
299@anchor{fl_noborder()}
300@findex fl_transient()
301@anchor{fl_transient()}
302@example
303void fl_noborder(void);
304void fl_transient(void);
305@end example
306
307You can also set the background of the window to a certain color using
308the following call
309@findex fl_winbackground()
310@anchor{fl_winbackground()}
311@example
312void fl_winbackground(Window win, unsigned long pixel);
313@end example
314
315It is possible to set the steps by which the size of a window can be
316changed by using
317@findex fl_winstepsize()
318@anchor{fl_winstepsize()}
319@example
320void fl_winstepsize(Window win, int xunit, int yunit);
321@end example
322@noindent
323where @code{xunit} and @code{yunit} are the number of pixels of
324changes per unit in x- and y- directions, respectively. Changes to
325the window size will be multiples of these units after this call.
326Note that this only applies to interactive resizing.
327
328To change constraints (size and aspect ratio) on an active window, you
329can use the following routine
330@findex fl_reset_winconstraints()
331@anchor{fl_reset_winconstraints()}
332@example
333void fl_reset_winconstraints(Window win);
334@end example
335
336The following routines are available to get information about an
337active window win:
338@findex fl_get_winsize()
339@anchor{fl_get_winsize()}
340@findex fl_get_winorigin()
341@anchor{fl_get_winorigin()}
342@findex fl_get_wingeometry()
343@anchor{fl_get_wingeometry()}
344@example
345void fl_get_winsize(Window win, FL_Coord *w, FL_Coord *h);
346void fl_get_winorigin(Window win, FL_Coord *x, FL_Coord *y);
347void fl_get_wingeometry(Window win, FL_Coord *x, FL_Coord *y,
348                        FL_Coord *w, FL_Coord *h);
349@end example
350@noindent
351All values returned are in pixels. The origin of a window is measured
352from the upper left hand corner of the root window.
353
354To change the size of a window programmatically the following function
355is available:
356@findex fl_winresize()
357@anchor{fl_winresize()}
358@example
359void fl_winresize(Window win, FL_Coord neww, FL_Coord newh);
360@end example
361@noindent
362Resizing will not change the origin of the window (relative to the
363root window). While the window gets resized originally set restraints
364will remain unchanged. E.g., if a window was not permitted to be
365resized interactively it will continue to remain unresizeable by the
366user.
367
368To move a window without resizing it use the following function:
369@findex fl_winmove()
370@anchor{fl_winmove()}
371@example
372void fl_winmove(Window win, FL_Coord newx, FL_Coord newy);
373@end example
374
375 To move and resize a window, use the following routine
376@findex fl_winreshape()
377@anchor{fl_winreshape()}
378@example
379void fl_winreshape(Window win, FL_Coord newx, FL_Coord newy,
380                   FL_Coord neww, FL_Coord newh);
381@end example
382
383The following routine is available to iconify a window
384@findex fl_iconify()
385@anchor{fl_iconify()}
386@example
387int fl_iconify(Window win);
388@end example
389@noindent
390The return value is nonzero when the message, asking for iconification
391of the window, was send successfully to the window manager, otherwise
392zero (but this may not be taken as a sure sign that the window was
393really iconified).
394
395To make a window invisible use
396@findex fl_winhide()
397@anchor{fl_winhide()}
398@example
399void fl_winhide(Window win);
400@end example
401@noindent
402A window hidden this way can be shown again later using
403@code{@ref{fl_winshow()}}.
404
405To hide and destroy a window, use the following calls
406@findex fl_winclose()
407@anchor{fl_winclose()}
408@example
409void fl_winclose(Window win);
410@end example
411@noindent
412There will be no events generated from @code{@ref{fl_winclose()}},
413i.e., the function waits and gobbles up all events for window
414@code{win}. In addition, this routine also removes all callbacks
415associated with the closed window.
416
417The following routine can be used to check if a window ID is valid or not
418@findex fl_winisvalid()
419@anchor{fl_winisvalid()}
420@example
421int fl_winisvalid(Window win);
422@end example
423@noindent
424Note that excessive use of this function may negatively impact
425performance.
426
427 Usually an X application should work with window managers and accepts
428the keyboard focus assignment. In some special situations, explicit
429override of the keyboard focus might be warranted. To this end, the
430following routine exists:
431@findex fl_winfocus()
432@anchor{fl_winfocus()}
433@example
434void fl_winfocus(Window win);
435@end example
436@noindent
437After this call keyboard input is directed to window @code{win}.
438
439@node Cursors
440@section Cursors
441
442XForms provides a convenience function to change the cursor shapes:
443@findex fl_set_cursor()
444@anchor{fl_set_cursor()}
445@example
446void fl_set_cursor(Window win, int name);
447@end example
448@noindent
449where @code{win} must be a valid window identifier and @code{name} is
450one of the symbolic cursor names (shapes) defined by standard X or the
451integer values returned by @code{@ref{fl_create_bitmap_cursor()}} or
452one of the Forms Library's pre-defined symbolic names.
453
454The X standard symbolic cursor names (all starts with @code{XC_}) are
455defined in @code{<X11/cursorfont.h>} (you don't need to explicitly
456include this as @code{<forms.h>} already does this for you). For
457example, to set a watch-shaped cursor for form @code{form} (after the
458form is shown), the following call may be made
459@example
460fl_set_cursor(form->window, XC_watch);
461@end example
462
463The Forms Library defines a special symbolic constants,
464@tindex FL_INVISIBLE_CURSOR
465@code{FL_INVISIBLE_CURSOR} that can be used to hide the cursor for
466window @code{win}:
467@example
468fl_set_cursor(win, FL_INVISIBLE_CURSOR);
469@end example
470
471Depending on the structure of the application program, a call of
472@code{XFlush(fl_get_display());} may be required following
473@code{@ref{fl_set_cursor()}}.
474
475To reset the cursor to the XForms's default (an arrow pointing
476northwest), use the following routine
477@findex fl_reset_cursor()
478@anchor{fl_reset_cursor()}
479@example
480void fl_reset_cursor(Window win);
481@end example
482
483To change the color of a cursor use the following routine
484@findex fl_set_cursor_color()
485@anchor{fl_set_cursor_color()}
486@example
487void fl_set_cursor_color(int name, FL_COLOR fg, FL_COLOR bg);
488@end example
489@noindent
490where @code{fg} and @code{bg} are the foreground and background color
491of the cursor, respectively. If the cursor is being displayed, the
492color change is visible immediately.
493
494It is possible to use cursors other than those defined by the standard
495cursor font by creating a bitmap cursor with
496@findex fl_create_bitmap_cursor()
497@anchor{fl_create_bitmap_cursor()}
498@example
499int fl_create_bitmap_cursor(const char *source, const char *mask,
500                            int w, int h, int hotx, int hoty);
501@end example
502@noindent
503where @code{source} and @code{mask} are two (x)bitmaps. The mask
504defines the shape of the cursor. The pixels set to 1 in the mask
505define which source pixels are displayed. If @code{mask} is
506@code{NULL} all bits in @code{source} are displayed. @code{hotx} and
507@code{hoty} are the hotspot of the cursor (relative to the source's
508origin). The function returns the cursor ID which can be used in calls
509of @code{@ref{fl_set_cursor()}} and @code{@ref{fl_set_cursor_color()}}
510etc.
511
512Finally, there is a routine to create animated cursors where several
513cursors are displayed one after another:
514@findex fl_create_animated_cursor()
515@anchor{fl_create_animated_cursor()}
516@example
517int fl_create_animated_cursor(int *cur_names, int interval);
518@end example
519@noindent
520The function returns the cursor name (ID) that can be shown later via
521@code{@ref{fl_set_cursor()}}. In the function call @code{cur_names} is
522an array of cursor names (either X standard cursors or cursor names
523returned by @code{@ref{fl_create_bitmap_cursor()}}), terminated by -1.
524Parameter @code{interval} indicates the time each cursor is displayed
525before it is replaced by the next in the array. An interval about
526@w{150 msec} is a good value for typical uses. Note that there is
527currently a limit of 24 cursors per animation sequence.
528
529Internally animated cursor works by utilizing the timeout callback.
530This means that if the application blocks (thus the main loop has no
531chance of servicing the timeouts), the animation will stop.
532
533See demo program @file{cursor.c} for an example use of the cursor
534routines.
535
536
537@node Clipboard
538@section Clipboard
539
540Clipboard is implemented in the Forms Library using the X selection
541mechanism, more specifically the @code{XA_PRIMARY} selection. X
542selection is a general and flexible way of sharing arbitrary data
543among applications on the same server (the applications are of course
544not necessarily running on the same machine). The basic (and
545over-simplified) concept of the X selection can be summarized as
546follows: the X Server is the central point of the selection mechanism
547and all applications running on the server communicate with other
548applications through the server. The X selection is asynchronous in
549nature. Every selection has an owner (an application represented by a
550window) and every application can become owner of the selection or
551lose the ownership.
552
553The clipboard in Forms Library is a lot simpler than the full-fledged
554X selection mechanism. The simplicity is achieved by hiding and
555handling some of the details and events that are of no interests to
556the application program. In general terms, you can think of a
557clipboard as a read-write buffer shared by all applications running on
558the server. The major functionality you want with a clipboard is the
559ability to post data onto the clipboard and request the content of the
560clipboard.
561
562To post data onto the clipboard, use the following routine
563@tindex FL_LOSE_SELECTION_CB
564@findex fl_stuff_clipboard()
565@anchor{fl_stuff_clipboard()}
566@example
567typedef int (*FL_LOSE_SELECTION_CB)(FL_OBJECT *obj, long type);
568
569int fl_stuff_clipboard(FL_OBJECT *obj, long type,
570                       const void *data, long size,
571                       FL_LOSE_SELECTION_CB callback);
572@end example
573@noindent
574where @code{size} is the size (in bytes) of the content pointed to by
575@code{data}. If successful, the function returns a positive value and
576the data will have been copied onto the clipboard. The callback is the
577function that will be called when another application takes ownership
578of the clipboard. For textual content the application that loses the
579clipboard should typically undo the visual cues about the selection.
580If no action is required when losing the ownership a @code{NULL}q
581callback can be passed. The @code{obj} argument is used to obtain the
582window (owner) of the selection. @code{type} is currently unused. At
583the moment the return value of @code{lose_selection_callback()} is
584also unused. The data posted onto the clipboard are available to all
585applications that manipulate @code{XA_PRIMARY}, such as xterm etc.
586
587To request the current clipboard content use the following routine
588@tindex FL_SELECTION_CB
589@findex fl_request_clipboard()
590@anchor{fl_request_clipboard()}
591@example
592typedef int (*FL_SELECTION_CB)(FL_OBJECT *obj, long type,
593                               const void * data, long size);
594
595int fl_request_clipboard(FL_OBJECT *obj, long type,
596                         FL_SELECTION_CB callback);
597@end example
598@noindent
599where @code{callback} is the callback function that gets called when
600the clipboard content is obtained. The content @code{data} passed to
601the callback function should not be modified.
602
603One thing to remember is that the operation of the clipboard is
604asynchronous. Requesting the content of the clipboard merely asks the
605owner of the content for it and you will not have the content
606immediately (unless the asking object happens to own the selection).
607XForms main event loop takes care of the communication between the
608requesting object and the owner of the clipboard and breaks up and
609re-assembles the content if it exceeds the maximum protocol request
610size (which has a guaranteed minimum of @w{16 kB}, but typically is
611larger). If the content of the clipboard is successfully obtained the
612main loop invokes the lose selection callback of the prior owner and
613then the requesting object's callback function.
614
615The function returns a positive number if the requesting object owns
616the selection (i.e., the callback could beinvoked before the function
617returned) and 0 otherwise.
618
619If there is no selection the selection callback is called with an
620empty buffer and the length of the buffer is set to 0. In that case
621@code{@ref{fl_request_clipboard()}} returns -1.
622