Panel, Rtext, plpack, plmove, pldraw, plfree, plgrabkb, plkeyboard, plmouse, plscroll,
plentryval, plsetbutton, plsetslider, pleget, plelen, plegetsel, plepaste, plesel, ple-
scroll, plgetscroll, plsetscroll, plplacelabel, plrtstr, plrtbitmap, plrtpanel, plrtfree,
plgetpostextview, plsetpostextview - Panel manipulation functions
int plinit(int ldepth)
int plpack(Panel *p, Rectangle r)
void plmove(Panel *p, Point loc)
void pldraw(Panel *p, Bitmap *b)
void plfree(Panel *p)
void plgrabkb(Panel *p)
void plkeyboard(Rune c)
void plmouse(Panel *p, Mouse m)
void plscroll(Panel *scrollee, Panel *xscroller, Panel *yscroller)
char *plentryval(Panel *entry)
void plsetbutton(Panel *button, int value)
void plsetslider(Panel *slider, int value, int range)
Rune *pleget(Panel *edit)
int plelen(Panel *edit)
void plegetsel(Panel *edit, int *start, int *end)
void plepaste(Panel *edit, Rune *text, int ntext)
void plesel(Panel *edit, int start, int end)
void plescroll(Panel *edit, int index)
Scroll plgetscroll(Panel *p)
void plsetscroll(Panel *p, Scroll s)
void plplacelabel(Panel *p, int loc)
Rtext *plrtstr(Rtext **head, int space, int indent,
Font *font, char *str, int hot, void *user)
Rtext *plrtbitmap(Rtext **head, int space, int indent,
Bitmap *image, int hot, void *user)
Rtext *plrtpanel(Rtext **head, int space, int indent,
Panel *panel, int hot, void *user)
void plrtfree(Rtext *text)
Rtext *plgetpostextview(Panel *view)
void plsetpostextview(Panel *view, Rtext *text)
The panel library assists in making simple graphical control panels for interactive appli-
cations. As drawn on the screen, a panel is a collection of nested rectangles with things
drawn in them, representing labels, buttons, editable text displays, scroll bars, and
other user interface features. Corresponding to the nest of boxes is a tree of Panel
structures. A node's children are drawn nested inside their parent. The publicly visible
part of a Panel structure looks like this
typedef struct Panel Panel;
Point ipad, pad; /* extra space inside and outside */
Point fixedsize; /* size of Panel, if FIXED */
int user; /* available for user */
void *userp; /* available for user */
Rectangle r; /* where the Panel goes */
... /* more private fields follow */
Rectangle r is the box containing this Panel node and its children. Its value is computed
by plpack. The user and userp fields are not used by the panel library. They are pro-
vided so that user code can attach data to a Panel node. The Points ipad, pad, and fixed-
size may be set by user code and are examined by plpack.
This manual page catalogs those panel library functions not directly concerned with creat-
ing or reinitializing Panel data structures. See plbutton(2) and plinitbutton(2) for
those. The Panel library memo in Volume 2 of this manual contains a more detailed
description of these functions, illustrated with examples.
The plinit function initializes panel library data structures. Its argument is the ldepth
of the bitmaps on which panels will be drawn. The panel library draws things differently
on one-bit and multi-bit-per-pixel displays.
There is usually no need to specify exact sizes and screen locations of Panel nodes.
Screen layout is computed by plpack, whose arguments are a pointer to a Panel tree and a
Rectangle in which the layout should fit. Plpack returns 1 if it could fit everything
into the rectangle, and 0 if it could not. Briefly, plpack processes a Panel tree in two
passes. The first, bottom-up pass computes the amount of space required to house the
children of each panel. The second pass proceeds top-down and divides the space available
to each panel among its children. Every Panel has some minimum space requirement -- for
example, a button must be big enough to fit its label inside its border, and a group must
be large enough to hold its children. Space is allocated to a Panel's children in eldest
to youngest order by slicing an appropriately sized piece off one of the four sides of the
available rectangle. Each Panel has a flag word (specified when the Panel is created --
see plbutton(2)), one of whose fields can have the value PACKN, PACKE, PACKS or PACKW
(default PACKN), specifying from which side to cut the piece. Other flags are:
The rectangle that plpack slices off for a Panel may be larger than the Panel
needs. For example, if a small button with PACKW set is packed inside a large rec-
tangle, plpack will slice off a piece that fits snugly in the x direction, but that
will likely be too big in the y direction. Specifying instead PACKW|FILLY will
grow the button in the y direction to fill the extra space.
PLACECEN PLACES PLACEE PLACEW PLACEN
PLACENE PLACENW PLACESE PLACESW
If a Panel is not expanded to fill the slack, these flags can specify where in the
available space to place it. The default is PLACECEN, which centers the panel in
the space allocated for it. The other PLACE flags place the Panel at one of the
eight compass points.
FIXED FIXEDX FIXEDY
A user's code can override whatever size calculation plpack performs by setting the
FIXED flag and storing a value in the Panel's fixedsize field. FIXED is the con-
junction of FIXEDX and FIXEDY, which fix a Panel's horizontal and vertical extent
If either of these flags is set, the Panel's x or y size requirement is increased
to be equal to that of its largest sibling.
Once a Panel tree is packed, it can be moved to a different location by calling plmove,
whose arguments are the panel to be moved and the upper left-hand corner of its destina-
Pldraw displays its Panel argument in the given Bitmap. Since each Panel's children are
drawn nested inside it, programs can do partial screen updates by calling pldraw on inte-
rior nodes of a Panel tree. For example, after calling plinitlabel to change the text of
a label, calling pldraw on the label will redisplay it, without having to update the rest
of the display. An application that wishes to discard a Panel tree should pass it to
plfree to release the storage.
Three functions control how a Panel processes mouse and keyboard input:
takes two arguments, a Panel pointer and a Mouse structure as returned by emouse
(see event(2)). Plmouse determines which node of the Panel tree should receive the
mouse event and calls panel-specific code to process the event. That code may in
turn call back to user-supplied functions to register button hits, slider movement,
etc. Hit routines are generally specified when panel-creation functions are
takes one argument, a pointer to a Panel to which keyboard input should be
directed. We say that this panel ``has the keyboard focus.'' Passing a null
pointer to plgrabkb causes subsequent keyboard input to be ignored.
takes one argument, a Rune, presumably obtained from ekbd or its equivalent and
sends it to the panel that has the keyboard focus, if any.
Programs that use scroll bars created with plscrollbar to control scrollable panels (cur-
rently pledit, pllist, and pltextview panels) must call plscroll to indicate to the panel
library which scroll bar adjusts which panel. Its arguments are three pointers to panels:
the panel to be scrolled, the panel that scrolls it in the x direction, and the panel that
scrolls it in the y direction. Either of the latter two may be null, indicating no con-
trol in that direction. Currently no panel responds to scrolling in x; that option is for
The rest of the functions test or set values hidden in certain Panel types or perform
other miscellaneous manipulations such as saving and restoring scroll points.
The plentryval entry returns a pointer to the string entered into a plentry panel (q.v.).
Its argument is the panel in question.
Plsetbutton takes two arguments. The first must point to a plcheckbutton or plradiobutton
panel. The function sets or clears the button's checkmark, depending on whether its sec-
ond argument is 0 or 1.
Plsetslider adjusts the position of the slider, its first argument. The value argument
gives the setting, in units such that the range argument gives full scale. For example
plsetslider(s, 50, 100);
plsetslider(s, 1, 2);
plsetslider(s, 17, 34);
each set slider s to the 50% mark.
The following functions all manipulate the editable text panels created by pledit. The
first argument of each is a pointer to the edit panel.
pleget returns a pointer to an array of Runes containing the edit window's text.
plelen returns the number of Runes in the text.
stores in *start and *end the endpoints of the edit window's current selection.
replaces the current selection with the text pointed to by text, whose length is
plesel sets the endpoints of the selection to start and end.
scrolls the edit window so that the line containing the Rune with the given index
is at the top of the screen.
The arguments of plplacelabel are a pointer to a pllabel panel and one of the flags PLACE-
CEN, PLACES, PLACEE, PLACEW, PLACEN, PLACENE, PLACENW, PLACESE, or PLACESW. This function
indicates where in the space allocated for the label the label's text should be drawn.
The text is centered by default.
The argument of plgetscroll should point to a scrollable Panel. The return value is a
magic cookie (of type Scroll) that indicates where it is scrolled to. When the panel
pointer and the cookie are passed to plsetscroll, it will scroll the panel back to the
place it was at when plgetscroll was called. The magic cookie encodes the scroll position
on a percentage basis, so all bets are off if the contents of the panel are different at
the calls to plgetscroll and plsetscroll.
Plgetpostextview and plsetpostextview perform a similar function, but they only work on
pltextview panels. However, since plgetpostextview returns a pointer to the Rtext that is
displayed in the upper left-hand corner of the panel and plsetpostextview scrolls the
given Rtext back to the upper left-hand corner, the caveat mentioned above does not apply.
Finally, there is a group of functions that create the Rtext lists that are displayed by
pltextview panels. Line breaks can occur only between the members of an Rtext list. An
individual Rtext structure describes a bitmap, or a string of text to be drawn in a single
call to string (see bitblt(2)), or a Panel to be drawn inline. The publicly visible parts
of an Rtext look like this:
typedef struct Rtext Rtext;
int hot; /* responds to hits? */
void *user; /* user data */
int space; /* how much space before, if no break */
int indent; /* how much space before, after a break */
Bitmap *b; /* what to display, if nonzero */
Panel *p; /* what to display, if nonzero and b==0 */
Font *font; /* font in which to draw text */
char *text; /* what to display, if b==0 and p==0 */
Rtext *next; /* next piece */
... /* more private fields follow */
The fields are:
hot indicates whether or not this Rtext is sensitive to mouse hits.
user points to user data not used by the panel library. User code may use this pointer
to annotate an Rtext.
space how much space to leave to the left of this Rtext if it appears on the same line as
the previous one. To allow the display of words with internal font changes, if
space is zero, there will never be a line break between this Rtext and the previous
indent How much space to leave between this Rtext and the left margin, if it is the first
one on the line.
b a bitmap to be displayed, if non-null.
p a panel to be displayed, if non-null and b==0.
font the font in which text is to be drawn.
text the string to be displayed, if b==0 and p==0.
next the next Rtext on the list.
The functions plrtstr, plrtbitmap, and plrtpanel create nodes in an Rtext list, returning
a pointer to the newly created node. For all three functions, the space, indent, hot, and
user arguments initialize the corresponding field of the Rtext, and head points to a
pointer to the head of the list, which the functions will update appropriately. The
pointer in *head should be initialized to a null pointer before the first call to any of
The plrtfree function will dispose of a Rtext list that is no longer needed. The user's
code is responsible for discarding any strings, bitmaps, panels, or user data that the
list may point to.
plbutton(2), plinitbutton(2), graphics(2)
Tom Duff, ``A quick introduction to the panel library''.