@node Part IV Drawing Objects
@chapter Drawing Objects

An important aspect of a new object class (or a free object) is how to
draw it. As indicated above this should happen when the event
@code{FL_DRAW} is received by the object. The place, i.e.@: bounding
box, where the object has to be drawn is indicated by the fields
@code{obj->x}, @code{obj->y}, @code{obj->w} and @code{obj->h}. Forms
are drawn in the Forms Library default visual or the user requested
visual, which could be any of the X supported visuals. Hence,
preferably your classes should run well in all visuals. The Forms
Library tries to hide as much as possible the information about
graphics mode and, in general, using the built-in drawing routines is
the best approach. Here are some details about graphics state in case
such information is needed.

All state information is kept in a global structure of type
@tindex FL_State
@code{FL_State} and there is a total of six such structures,
@code{fl_state[6]}, each for every visual class.

The structure contains among others the following members:
@table @code
@item XVisualInfo *xvinfo
Many properties of the current visual can be obtained from this
member.
@item int depth
The depth of the visual. Same as what you get from @code{xvinfo}.
@item int vclass
The visual class, @code{PseudoColor}, @code{TrueColor} etc.
@item Colormap colormap
Current active colormap valid for the current visual for the entire
Forms Library (except @code{FL_CANVAS}). You can allocate colors from
this colormap, but you should never free it.
@item Window trailblazer
This is a valid window resource ID created in the current visual with
the colormap mentioned above. This member is useful if you have to
call, before the form becomes active (thus don't have a window ID),
some Xlib routines that require a valid window. A macro,
@findex fl_default_window()
@anchor{fl_default_window()}
@code{fl_default_window()}, is defined to return this member and use
of the macro is encouraged.
@item GC gc[16 ]
A total of 16 GCs appropriate for the current visual and depth. The
first (@code{gc[0]}) is the default @code{GC} used by many internal
routines and should be modified with care. It is a good idea to use
only the top 8 @code{GC}s (8-15) for your free object so that future
Forms Library extensions won't interfere with your program. Since many
internal drawing routines use the Forms Library's default @code{GC}
(@code{gc[0]}), it can change anytime whenever drawing occurs.
Therefore, if you are using this GC for some of your own drawing
routines make sure to always set the proper value before using it.
@end table

The currently active visual class (@code{TrueColor},
@code{PseudoColor} etc.) can be obtained by the following
function/macro:
@findex fl_get_form_vclass()
@anchor{fl_get_form_vclass()}
@findex fl_get_vclass()
@anchor{fl_get_vclass()}
@example
int fl_get_form_vclass(FL_FORM *form);
int fl_get_vclass(void);
@end example
@noindent
The value returned can be used as an index into the array
@code{fl_state} of @code{FL_State} structures. Note that
@code{@ref{fl_get_vclass()}} should only be used within a class/new
object module where there can be no confusion what the "current" form
is.

Other information about the graphics mode can be obtained by using
visual class as an index into the @code{fl_state} structure array. For
example, to print the current visual depth, code similar to the
following can be used:
@example
int vmode = fl_get_vclass();
printf("depth: %d\n", fl_state[vmode].depth);
@end example
@noindent
Note that @code{fl_state[]} for indices other than the currently
active visual class might not be valid. In almost all Xlib calls, the
connection to the X server and current window ID are needed. The Forms
Library comes with some utility functions/macros to facilitate easy
utilization of Xlib calls. Since the current version of Forms Library
only maintains a single connection, the global variable
@w{@code{Display *fl_display}} can be used where required. However, it
is recommended that you use
@findex fl_get_display()
@anchor{fl_get_display()}
@code{fl_get_display()} or
@findex FL_FormDisplay(form)
@anchor{FL_FormDisplay(form)}
@code{FL_FormDisplay(form)} instead since the function/macro version
has the advantage that your program will remain compatible with future
(possibly multi-connection) versions of the Forms Library.

There are a couple of ways to find out the "current" window ID,
defined as the window ID the object receiving dispatcher's messages
like @code{FL_DRAW} etc.@: belongs to. If the object's address is
available, @code{FL_ObjWin(obj)} will suffice. Otherwise the function
@code{@ref{fl_winget()}} (see below) can be used.

There are other routines that might be useful:
@findex fl_win_to_form()
@anchor{fl_win_to_form()}
@example
FL_FORM *fl_win_to_form(Window win);
@end example
@noindent
This function takes a window ID win and returns the form the window
belongs to or @code{None} on failure.

As mentioned earlier, Forms Library keeps an internal colormap,
initialized to predefined colors. The predefined colors do not
correspond to pixel values the server understands but are indexes into
the colormap. Therefore, they can't be used in any of the @code{GC}
altering or Xlib routines. To get the actual pixel value the X server
understands, use the following routine
@findex fl_get_pixel()
@anchor{fl_get_pixel()}
@example
FL_COLOR fl_get_pixel(FL_COLOR color);
@end example
@noindent
To e.g.@: get the pixel value of the red color, use
@example
unsigned long red_pixel;
red_pixel = fl_get_pixel(FL_RED);
@end example

To change the foreground color in the Forms Library's default
@code{GC} (@code{gc[0]}) use
@findex fl_color()
@anchor{fl_color()}
@example
void fl_color(FL_COLOR col);
@end example

To set the background color in the default @code{GC} use instead
@findex fl_bk_color()
@anchor{fl_bk_color()}
@example
void fl_bk_color(FL_COLOR color);
@end example

To set foreground or background in @code{GC}s other than the Forms
Library's default, the following functions exist:
@findex fl_set_foreground()
@anchor{fl_set_foreground()}
@findex fl_set_background()
@anchor{fl_set_background()}
@example
void fl_set_foreground(GC gc, FL_COLOR color);
void fl_set_background(GC gc, FL_COLOR color);
@end example
@noindent
which is equivalent to the following Xlib calls
@example
XSetForeground(fl_get_display(), gc, fl_get_pixel(color));
XSetBackground(fl_get_display(), gc, fl_get_pixel(color));
@end example

To free allocated colors from the default colormap, use the following
routine
@findex fl_free_colors()
@anchor{fl_free_colors()}
@example
void fl_free_colors(FL_COLOR *cols, int n);
@end example
@noindent
This function frees the @code{n} colors stored in the array of
colormap indices @code{cols}. You shouldn't do that for the reserved
colors, i.e.@: colors with indices below @code{FL_FREE_COL1}.

In case the pixel values (instead of the index into the colormap) are
known, the following routine can be used to free the colors from the
default colormap
@findex fl_free_pixels()
@anchor{fl_free_pixels()}
@example
void fl_free_pixels(unsigned long *pixels, int n);
@end example
@noindent
Note that the internal colormap maintained by the Forms Library is not
updated. This is in general harmless.

To modify or query the internal colormap, use the following routines:
@findex fl_mapcolor()
@anchor{fl_mapcolor()}
@findex fl_mapcolorname()
@anchor{fl_mapcolorname()}
@findex fl_getmcolor()
@anchor{fl_getmcolor()}
@example
unsigned long fl_mapcolor(FL_COLOR color, int red, int green, int blue)
long fl_mapcolorname(FL_COLOR color, const char *name);
unsigned long fl_getmcolor(FL_COLOR color,
                           int *red, int *green, int *blue);
@end example
@noindent
The first function, @code{@ref{fl_mapcolor()}} sets a the color
indexed by @code{color} to the color given by the @code{red},
@code{green} and @code{blue}, returning the colors pixel value.

The second function, @code{@ref{fl_mapcolorname()}}, sets the color in
the colormap indexed by @code{color} to the color named @code{name},
where @code{name} must be a valid name from the system's color database
file @file{rgb.txt}. It also returns the colors pixel value or -1 on
failure.

The last function, @code{@ref{fl_getmcolor()}}, returns the RGB values
of the color indexed by @code{color} in the second to third argument
pointers and the pixel value as the return value (or -1, cast to
@code{unsigned long}, on failure).


The coordinate system used corresponds directly to that of the screen.
But object coordinates are relative to the upper-left corner of the
form the object belongs to.

To obtain the position of the mouse relative to a certain form or
window, use the routines
@findex fl_get_form_mouse()
@anchor{fl_get_form_mouse()}
@findex fl_get_win_mouse()
@anchor{fl_get_win_mouse()}
@example
Window fl_get_form_mouse(FL_FORM *form, FL_Coord *x, FL_Coord *y,
                         unsigned *keymask)
Window fl_get_win_mouse(Window win, FL_Coord *x, FL_Coord *y,
                        unsigned *keymask);
@end example
@noindent
The functions return the ID of the window the mouse is in. Upon return
@code{x} and @code{y} are set to the mouse position relative to the
form or window and @code{keymask} contains information on modifier
keys (same as the the corresponding @code{XQueryPointer()} argument).

A similar routine exists that can be used to obtain the mouse location
relative to the root window
@findex fl_get_mouse()
@anchor{fl_get_mouse()}
@example
Window fl_get_mouse(FL_Coord *x, FL_Coord *y, unsigned *keymask);
@end example
@noindent
The function returns the ID of the window the mouse is in.

To move the mouse to a specific location relative to the root window,
use the following routine
@findex fl_set_mouse()
@anchor{fl_set_mouse()}
@example
void fl_set_mouse(FL_Coord x, FL_Coord y);
@end example
@noindent
Use this function sparingly, it can be extremely annoying for the user
if the mouse position is changed by a program.

To avoid drawing outside a box the following routine exists:
@findex fl_set_clipping()
@anchor{fl_set_clipping()}
@example
void fl_set_clipping(FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h);
@end example
@noindent
It sets a clipping region in the Forms Library's default @code{GC}.
@code{x}, @code{y}, @code{w} and @code{h} define the area drawing is
to restrict to and are relative to the window/form that will be drawn
to. In this way you can prevent drawing over other objects.

When finished with drawing always use
@findex fl_unset_clipping()
@anchor{fl_unset_clipping()}
@example
void fl_unset_clipping(void);
@end example
@noindent
to stop clipping.

Similar functions are available to set the clipping for a specific @code{GC}:
@findex fl_set_gc_clipping()
@anchor{fl_set_gc_clipping()}
@findex fl_unset_gc_clipping()
@anchor{fl_unset_gc_clipping()}
@example
void fl_set_gc_clipping(GC gc, FL_Coord x, FL_Coord y,
                        FL_Coord w, FL_Coord h);
void fl_unset_gc_clipping(GC gc);
@end example

To obtain the bounding box of an object with the dimension and
location of the label taken into account (compare with
@code{@ref{fl_get_object_geometry()}} the following routine exists:
@findex fl_get_object_bbox()
@example
void fl_get_object_bbox(FL_OBJECT *obj, FL_Coord *x, FL_Coord *y,
                        FL_Coord *w, FL_Coord *h);
@end example

To set clippings for text, which uses a different GC, the following
routine should be used
@findex fl_set_text_clipping()
@anchor{fl_set_text_clipping()}
@findex fl_set_untext_clipping()
@anchor{fl_set_untext_clipping()}
@example
void fl_set_text_clipping(FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h);
void wfl_unset_text_clipping(void);
@end example

For drawing text at the correct places you will need some information
about the sizes of characters and strings. The following routines are
provided:
@findex fl_get_char_height()
@anchor{fl_get_char_height()}
@findex fl_get_char_width()
@anchor{fl_get_char_width()}
@example
int fl_get_char_height(int style, int size, int *ascend, int *descend)
int fl_get_char_width(int style, int size);
@end example
@noindent
These two routines return the maximum height and width of the font
used, where size indicates the point size for the font and style is
the style in which the text is to be drawn. The first function,
@code{@ref{fl_get_char_height()}}, also returns the height above and
below the baseline of the font via the @code{ascend} and
@code{descend} arguments. A list of valid styles can be found in
Section 3.11.3.

To obtain the width and height information on a specific string, use
the following routines
@findex fl_get_string_width()
@anchor{fl_get_string_width()}
@findex fl_get_string_height()
@anchor{fl_get_string_height()}
@example
int fl_get_string_width(int style, int size, const char *str,
                        int len);
int fl_get_string_height(int style, int size, const char *str,
                         int len, int *ascend, int *descend);
@end example
where @code{len} is the length of the string @code{str}. The functions
return the width and height of the string, respectively. The second
function also returns the height above and below the fonts baseline.

There exists also a routine that returns the width and height of a
string in one call. In addition, the string passed can contain
embedded newline characters @code{'\n'} and the routine will make
proper adjustment so the values returned are (just) large enough to
contain the multiple lines of text
@findex fl_get_string_dimension()
@anchor{fl_get_string_dimension()}
@example
void fl_get_string_dimension(int style, int size, const char *str,
                             int len, int *width, int *height);
@end example

Sometimes it can be useful to get the X font structure for a
particular size and style as used in the Forms Library. For this
purpose, the following routine exists:
@findex fl_get_fontstruct()
@anchor{fl_get_fontstruct()}
@example
[const] XFontStruct *fl_get_fontstruct(int style, int size);
@end example
@noindent
The structure returned can be used in, say, setting the font in a
particular @code{GC}:
@example
XFontStruct *xfs = fl_get_fontstruct(FL_TIMESBOLD_STYLE, FL_HUGE_SIZE);
XSetFont(fl_get_display(), mygc, xfs->fid);
@end example
@noindent
The caller should not free the structure returned by
@code{@ref{fl_get_fontstruct()}}.

There are a number of routines that help you draw objects on the
screen. All XForms's internal drawing routine draws into the "current
window", defined as the window the object that uses the drawing
routine belongs to. If that's not what you need, the following
routines can be used to set or query the current window:
@findex fl_winset()
@anchor{fl_winset()}
@findex fl_winget()
@anchor{fl_winget()}
@example
void fl_winset(Window win);
Window fl_winget(void);
@end example
@noindent
One caveat about @code{@ref{fl_winget()}} is that it can return
@code{None} if called outside of an object's event handler, depending
on where the mouse is. Thus, the return value of this function should
be checked when called outside of an object handler.

It is important to remember that unless the following drawing commands
are issued while handling the @code{FL_DRAW} or @code{FL_DRAWLABEL}
event (which is not generally recommended), it is the application's
responsibility to set the proper drawable using
@code{@ref{fl_winset()}}.

The most basic drawing routines are for drawing rectangles:
@findex fl_rectf()
@anchor{fl_rectf()}
@findex fl_rect()
@anchor{fl_rect()}
@example
void fl_rectf(FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h,
              FL_COLOR c);
void fl_rect(FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h,
             FL_COLOR c);
@end example
@noindent
Both draw a rectangle on the screen in color @code{col}. The
difference is that @code{@ref{fl_rectf()}} draws a filled rectangle
while @code{@ref{fl_rect()}} just draws an outline.

To draw a filled rectangle with a black border use
@findex fl_rectbound()
@anchor{fl_rectbound()}
@example
void fl_rectbound(FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h,
                  FL_COLOR c);
@end example

To draw a rectangle with rounded corners (filled or just the outline)
employ
@findex fl_roundrectf()
@anchor{fl_roundrectf()}
@findex fl_roundrect()
@anchor{fl_roundrect()}
@example
void fl_roundrectf(FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h,
                   FL_COLOR col);
void fl_roundrect(FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h,
                  FL_COLOR col);
@end example


To draw a general polygon, use one of the following routines
@tindex FL_POINT
@findex fl_polyf()
@anchor{fl_polyf()}
@findex fl_polyl()
@anchor{fl_polyl()}
@findex fl_polybound()
@anchor{fl_polybound()}
@example
typedef struct @{
    short x,
          y;
@} FL_POINT;

void fl_polyf(FL_POINT *xpoint, int n, FL_COLOR col);
void fl_polyl(FL_POINT *xpoint, int n, FL_COLOR col);
void fl_polybound(FL_POINT *xpoint, int n, FL_COLOR col);
@end example
@noindent
@code{@ref{fl_polyf()}} draws a filled polygon defined by @code{n}
points, @code{@ref{fl_polyl()}} the ouline of a polygon and
@code{@ref{fl_polybound()}} a filled polygon with a black outline.
Note all polygon routines @strong{require} that the array
@code{xpoint} has to have enough spaces to hold @code{n+1} points!

To draw an ellipse. either filled or open, the following routines can
be used (use @code{w} equal to @code{h} to get a circle):
@findex fl_ovalf()
@anchor{fl_ovalf()}
@findex fl_ovall()
@anchor{fl_ovall()}
@findex fl_ovalbound()
@anchor{fl_ovalbound()}
@example
void fl_ovalf(FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h,
              FL_COLOR c);
void fl_ovall(FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h,
              FL_COLOR c);
void fl_ovalbound(FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h,
                  FL_COLOR c);
@end example

To draw circular arcs, either open or filled, the following routines
can be used
@findex fl_arc()
@anchor{fl_arc()}
@findex fl_arcf()
@anchor{fl_arcf()}
@example
void fl_arc(FL_Coord x, FL_Coord y, FL_Coord radius,
            int start_theta, int end_theta, FL_COLOR col);
void fl_arcf(FL_Coord x, FL_Coord y, FL_Coord radius,
             int start_theta, int end_theta, FL_COLOR col);
@end example
where @code{start_theta} and @code{end_theta} are the starting and
ending angles of the arc in units of tenths of a degree (where 0
stands for a direction of 3 o'clock, i.e.@: the right-most point of a
circle), and @code{x} and @code{y} are the center of the arc. If the
difference between @code{theta_end} and @code{theta_start} is larger
than 3600 (360 degrees), drawing is truncated to 360 degrees.

To draw elliptical arcs the following routine should be used:
@findex fl_pieslice()
@anchor{fl_pieslice()}
@example
void fl_pieslice(int fill, FL_Coord x, FL_Coord y, FL_Coord w,
                 FL_Coord h, int start_theta, int end_theta,
                 FL_COLOR col);
@end example
@noindent
The center of the arc is the center of the bounding box specified by
@code{x}, @code{y}, @code{w}, @code{h}, @code{w} and @code{h}
specifing the axes of the ellipse.. @code{start_theta} and
@code{end_theta}, to be given in tenth of a degree, specify the
starting and ending angles measured from zero degrees (3 o'clock).

Depending on circumstance, elliptical arc may be more easily drawn
using the following routine
@findex fl_ovalarc(
@anchor{fl_ovalarc(}
@example
void fl_ovalarc(int fill, FL_Coord x, FL_Coord y, FL_Coord w,
                FL_Coord h, int theta, int dtheta, FL_COLOR col);
@end example
@noindent
Here @code{theta} specifies the starting angle (again measured in
tenth of a degree and with 0 at the 3 o'clock position), and
@code{dtheta} specifies both the direction and extent of the arc. If
@code{dtheta} is positive the arc is drawn in counter-clockwise
direction from the starting point defined by @code{theta}, otherwise
in clockwise direction. If @code{dtheta} is larger than 3600 it is
truncated to 3600.

To connect two points with a straight line, use
@findex fl_line()
@anchor{fl_line()}
@example
void fl_line(FL_Coord x1, FL_Coord y1,
             FL_Coord x2, FL_Coord y2, FL_COLOR col);
@end example

There is also a routine to draw a line along the diagonal of a box (to
draw a horizontal line set @code{h} to 1, not to 0):
@findex fl_diagline()
@anchor{fl_diagline()}
@example
void fl_diagline(FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h,
                 FL_COLOR col);
@end example

To draw connected line segments between @code{n} points use
@findex fl_lines()
@anchor{fl_lines()}
@example
void fl_lines(FL_POINT *points, int n, FL_COLOR col);
@end example
@noindent
All coordinates in points are relative to the origin of the drawable.

There are also routines to draw one or more pixels
@findex fl_point()
@anchor{fl_point()}
@findex fl_points()
@anchor{fl_points()}
@example
void fl_point(FL_Coord x, FL_Coord y, FL_COLOR col);
void fl_points(FL_POINT *p, int np, FL_COLOR col);
@end example
@noindent
As usual, all coordinates are relative to the origin of the drawable.
Note that these routines are meant for you to draw a few pixels, not
images consisting of tens of thousands of pixels of varying colors.
For that kind of drawing @code{XPutImage(3)} should be used. Or better
yet, use the image support in the Forms Library (see @ref{Part VI
Images, , Images}). Also it's usually better when drawing multiple
points to use fl_points(), even if that means that the application
program has to pre-sort and group the pixels of the same color.

To change the line width or style, the following convenience functions
are available
@findex fl_linewidth()
@anchor{fl_linewidth()}
@findex fl_linestyle()
@anchor{fl_linestyle()}
@example
void fl_linewidth(int lw);
void fl_linestyle(int style);
@end example
@noindent
Set @code{lw} to 0 to reset the line width to the servers default.
Line styles can take on the following values (also see
@code{XChangeGC(3)})
@table @code
@tindex FL SOLID
@item FL SOLID
Solid line. Default and most efficient.
@tindex FL DOT
@item FL DOT
Dotted line.
@tindex FL DASH
@item FL DASH
Dashed line.
@tindex FL DOTDASH
@item FL DOTDASH
Dash-dot-dash line.
@tindex FL LONGDASH
@item FL LONGDASH
Long dashed line.
@tindex FL USERDASH
@item FL USERDASH
Dashed line, but the dash pattern is user definable via
@code{@ref{fl_dashedlinestyle()}}. Only the odd numbered segments are
drawn with the foreground color.
@tindex FL USERDOUBLEDASH
@item FL USERDOUBLEDASH
Similar to @code{FL_LINE_USERDASH} but both even and odd numbered
segments are drawn, with the even numbered segments drawn in the
background color (as set by @code{@ref{fl_bk_color()}}).
@end table

The following routine can be used to change the dash pattern
for @code{FL_USERDASH} and @code{FL USERDOUBLEDASH}:
@findex fl_dashedlinestyle()
@anchor{fl_dashedlinestyle()}
@example
void fl_dashedlinestyle(const char *dash, int ndashes)
@end example
Each element of the array @code{dash} is the length of a segment of
the pattern in pixels. Dashed lines are drawn as alternating segments,
each with the length of an element in @code{dash}. Thus the overall
length of the dash pattern, in pixels, is the sum of all elements of
@code{dash}. When the pattern is used up but the line to draw is
longer it used from the start again. The following example code
specifies a long dash (9 pixels) to come first, then a skip (3
pixels), a short dash (2 pixels) and then again a skip (3 pixels).
After this sequence, the pattern repeats.
@example
char ldash_sdash[] = @{9, 3, 2, 3@};
fl_dashedlinestyle(ldash_sdash, 4);
@end example

It is important to remember to call @code{@ref{fl_dashedlinestyle()}}
whenever @code{FL_USERDASH} is used to set the dash pattern, otherwise
whatever the last pattern was will be used. To use the default dash
pattern you can pass @code{NULL} as the dash parameter to
@code{@ref{fl_dashedlinestyle()}}.

By default, all lines are drawn so they overwrite the destination
pixel values. It is possible to change the drawing mode so the
destination pixel values play a role in the final pixel value.
@findex fl_drawmode()
@anchor{fl_drawmode()}
@example
void fl_drawmode(int mode);
@end example
@noindent
There are 16 different possible settings for @code{mode} (see a Xlib
programming manual for all the gory details). A of the more useful
ones are
@table @code
@item GXcopy
Default overwrite mode. Final pixel value = Src
@item GXxor
Bitwise XOR (exclusive-or) of the pixel value to be drawn with the
pixel value already on the screen. Useful for rubber-banding.
@item GXand
Bitwise AND of the pixel value to be drawn with the
pixel value already on the screen.
@item GXor
Bitwise OR of the pixel value to be drawn with the
pixel value already on the screen.
@item GXinvert
Just invert the pixel values already on the screen.
@end table

To obtain the current settings of the line drawing attributes use the
following routines
@findex fl_get_linewidth()
@anchor{fl_get_linewidth()}
@findex fl_get_linestyle(()
@anchor{fl_get_linestyle(()}
@findex fl_get_drawmode(()
@anchor{fl_get_drawmode(()}
@example
int fl_get_linewidth(void);
int fl_get_linestyle(void);
int fl_get_drawmode(void);
@end example

There are also a number of high-level drawing routines available. To
draw boxes the following routine exists. Almost any object class will
use it to draw the bounding box of the object.
@findex fl_drw_box()
@anchor{fl_drw_box()}
@example
void fl_drw_box(int style, FL_Coord x, FL_Coord y,
                FL_Coord w, FL_Coord h,
                FL_COLOR col, int bw);
@end example
@noindent
@code{style} is the type of the box, e.g.@: @code{FL_DOWN_BOX}.
@code{x}, @code{y}, @code{w}, and @code{h} indicate the size of the
box. @code{col} is the color and @code{bw} is the width of the
boundary, which typically should be given the value @code{obj->bw} or
@code{FL_BOUND_WIDTH}. Note that a negative border width indicates a
"softer" up box. See the demo program @file{borderwidth.c} for the
visual effect of different border widths.

There is also a routine for drawing a frame:
@findex fl_drw_frame()
@anchor{fl_drw_frame()}
@example
void fl_drw_frame(int style, FL_Coord x, FL_Coord y,
                  FL_Coord w, FL_Coord h, FL_COLOR col, int bw)
@end example
@noindent
All parameters have the usual meaning except that the frame is drawn
outside of the bounding box specified.

To draw a slider of various types and shapes use
@findex fl_drw_slider)
@anchor{fl_drw_slider)}
@example
void fl_drw_slider(int boxtype, FL_Coord x, FL_Coord y,
                   FL_Coord w, FL_Coord h, FL_COLOR col1,
                   FL_COLOR col2, int slider_type,
                   double slider_size, double slider_value,
                   char *label, int parts, int inverted, FL_Coord bw);
@end example
@noindent
where @code{slider_type} is one of the different slider types like
@code{FL_VERT_SLIDER} etc., see @ref{Slider Object}, for a complete list.
Other parameters have the obvious meaning except for @code{parts},
which can be one of the following
@table @code
@item FL_SLIDER_NONE
Don't draw anything.
@item FL_SLIDER_BOX
Draw the bounding box only.
@item FL_SLIDER_KNOB
Draw the knob only.
@item FL_SLIDER_ALL
Draw the entire slider.
@end table

For drawing text there are two routines:
@findex fl_drw_text()
@anchor{fl_drw_text()}
@findex fl_drw_text_beside()
@anchor{fl_drw_text_beside()}
@example
void fl_drw_text(int align, FL_Coord x, FL_Coord y, FL_Coord w,
                 FL_Coord h, FL_COLOR col, int style, int size,
                 const char *str);
void fl_drw_text_beside(int align, FL_Coord x, FL_Coord y,
                        FL_Coord w, FL_Coord h, FL_COLOR col,
                        int style, int size, const char *str);
@end example
@noindent
where @code{align} is the alignment, namely, @code{FL ALIGN LEFT},
@code{FL ALIGN CENTER} etc. @code{x}, @code{y}, @code{w} and @code{h}
indicate the bounding box, @code{col} is the color of the text,
@code{size} is the size of the font to use (in points) and
@code{style} is the font style to be used (see @ref{Label Attributes
and Fonts}, for valid styles). Finally, @code{str} is the string
itself, possibly containing embedded newline characters.

@code{@ref{fl_drw_text()}} draws the text inside the bounding box
according to the alignment requested while
@code{@ref{fl_drw_text_beside()}} draws the text aligned outside of
the box. These two routines interpret a text string starting with the
character @code{@@} differently in drawing some symbols instead. Note
that @code{@ref{fl_drw_text()}} puts a padding of 5 pixels in vertical
direction and 4 in horizontal around the text. Thus the bounding box
should be 10 pixels wider and 8 pixels higher than required for the
text to be drawn.

The following routine can also be used to draw text and, in addition, a
cursor can optionally be drawn
@findex fl_drw_text_cursor()
@anchor{fl_drw_text_cursor()}
@example
void fl_drw_text_cursor(int align, FL_Coord x, FL_Coord y,
                        FL_Coord w, FL_Coord h, FL_COLOR col,
                        int style, int size, char *str,
                        int FL_COLOR ccol, int pos);
@end example
@noindent
where @code{ccol} is the color of the cursor and @code{pos} is its
position which indicates the index of the character in @code{str}
before which to draw the cursor (-1 means show no cursor). This
routine does no interpretion of the special character @code{@@} nor
does it add padding around the text.

Given a bounding box and the size of an object (e.g.@: a label) to
draw, the following routine can be used to obtain the position of
where to draw it with a certain alignment and including padding:
@findex fl_get_align_xy()
@anchor{fl_get_align_xy()}
@example
void fl_get_align_xy(int align, int x, int y, int w, int h,
                     int obj_xsize, int obj_ysize,
                     int xmargin, int ymargin,
                     int *xpos, int *ypos);
@end example
@noindent
This routine works regardless if the object is to be drawn inside or
outside of the bounding box specified by @code{x}, @code{y}, @code{w}
and @code{h}. @code{obj_xsize} and @code{obj->ysize} are the width
and height of the object to be drawn and @code{xmargin} and
@code{ymargin} is the additional padding to use. @code{xpos} and
@code{ypos} return the position to be used for drawing the object.

For drawing object labels the following routines might be more convenient:
@findex fl_draw_object_label()
@anchor{fl_draw_object_label()}
@findex fl_draw_object_label_outside()
@anchor{fl_draw_object_label_outside()}
@example
void fl_draw_object_label(FL_OBJECT *obj)
void fl_draw_object_label_outside(FL_OBJECT *obj);
@end example
@noindent
Both routines assume that the alignment is relative to the full
bounding box of the object. The first routine draws the label
according to the alignment, which could be inside or outside of the
bounding box. The second routine will always draw the label outside of
the bounding box.

An important of aspect of (re)drawing an object is efficiency which
can result in flicker and non-responsiveness if not handled with
care. For simple objects like buttons or objects that do not have
"movable parts", drawing efficiency is not a serious issue although
you can never be too fast. For complex objects, especially those that
a user can interactively change, special care should be taken.

The most important rule for efficient drawing is not to draw if you
don't have to, regardless how simple the drawing is. Given the
networking nature of X, simple or not depends not only on the
host/server speed but also the connection. What this strategy entails
is that the drawing should be broken into blocks and depending on the
context, draw/update only those parts that need to.
