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