PLINIT(2) PLINIT(2)
NAME
Panel, Rtext, plpack, plmove, pldraw, plfree, plgrabkb,
plkeyboard, plmouse, plscroll, plentryval, plsetbutton,
plsetslider, pleget, plelen, plegetsel, plepaste, plesel,
plescroll, plgetscroll, plsetscroll, plplacelabel, plrtstr,
plrtbitmap, plrtpanel, plrtfree, plgetpostextview,
plsetpostextview - Panel manipulation functions
SYNOPSIS
#include <u.h>
#include <libg.h>
#include <panel.h>
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)
Page 1 Plan 9 (printed 11/2/25)
PLINIT(2) PLINIT(2)
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)
DESCRIPTION
The panel library assists in making simple graphical control
panels for interactive applications. 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 fea-
tures. 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 struc-
ture looks like this
typedef struct Panel Panel;
struct 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
provided so that user code can attach data to a Panel node.
The Points ipad, pad, and fixedsize may be set by user code
and are examined by plpack.
This manual page catalogs those panel library functions not
directly concerned with creating 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,
Page 2 Plan 9 (printed 11/2/25)
PLINIT(2) PLINIT(2)
illustrated with examples.
The plinit function initializes panel library data struc-
tures. Its argument is the ldepth of the bitmaps on which
panels will be drawn. The panel library draws things dif-
ferently 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 cre-
ated - see plbutton(2)), one of whose fields can have the
value PACKN, PACKE, PACKS or PACKW (default PACKN), specify-
ing from which side to cut the piece. Other flags are:
FILLX FILLY
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 rectan-
gle, 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
conjunction of FIXEDX and FIXEDY, which fix a Panel's
horizontal and vertical extent independently.
Page 3 Plan 9 (printed 11/2/25)
PLINIT(2) PLINIT(2)
MAXX MAXY
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 destination.
Pldraw displays its Panel argument in the given Bitmap.
Since each Panel's children are drawn nested inside it, pro-
grams can do partial screen updates by calling pldraw on
interior 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 stor-
age.
Three functions control how a Panel processes mouse and key-
board input:
plmouse 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 called.
plgrabkb 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 subse-
quent keyboard input to be ignored.
plkeyboard 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 (currently 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 control in that direc-
tion. Currently no panel responds to scrolling in x; that
option is for future expansion.
The rest of the functions test or set values hidden in
Page 4 Plan 9 (printed 11/2/25)
PLINIT(2) PLINIT(2)
certain Panel types or perform other miscellaneous manipula-
tions 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.
plegetsel stores in *start and *end the endpoints of the
edit window's current selection.
plepaste replaces the current selection with the text
pointed to by text, whose length is ntext Runes.
plesel sets the endpoints of the selection to start and
end.
plescroll scrolls the edit window so that the line contain-
ing 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 PLACECEN, PLACES, PLACEE, PLACEW,
PLACEN, PLACENE, PLACENW, PLACESE, or PLACESW. This func-
tion 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
Page 5 Plan 9 (printed 11/2/25)
PLINIT(2) PLINIT(2)
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;
struct 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 one.
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.
Page 6 Plan 9 (printed 11/2/25)
PLINIT(2) PLINIT(2)
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 these functions.
The plrtfree function will dispose of a Rtext list that is
no longer needed. The user's code is responsible for dis-
carding any strings, bitmaps, panels, or user data that the
list may point to.
SOURCE
/sys/src/libpanel
SEE ALSO
plbutton(2), plinitbutton(2), graphics(2)
Tom Duff, ``A quick introduction to the panel library''.
Page 7 Plan 9 (printed 11/2/25)