```

     CONTROL(2)						    CONTROL(2)

     NAME
	  Control, Controlset, activate, closecontrol,
	  closecontrolset, controlcalled, controlwire, createbox,
	  createboxbox,	createbutton, createcolumn, createentry,
	  createkeyboard, createlabel, createmenu, createradiobutton,
	  createrow, createscribble, createslider, createstack,
	  createtab, createtext, createtextbutton, ctlerror,
	  ctlmalloc, ctlrealloc, ctlstrdup, ctlprint, deactivate,
	  freectlfont, freectlimage, initcontrols, namectlfont,
	  namectlimage,	newcontrolset, resizecontrolset	- interactive
	  graphical controls

     SYNOPSIS
	  #include <u.h>
	  #include <libc.h>
	  #include <draw.h>
	  #include <thread.h>
	  #include <keyboard.h>
	  #include <mouse.h>
	  #include <control.h>
	  typedef struct Control Control;
	  typedef struct Controlset Controlset;
	  struct Control
	  {
	      char	  *name;
	      Rectangle	  rect;	  /* area on screen */
	      Rectangle	  size;	  /* min/max Dx, Dy (not a rect) */
	      Channel *event; /* chan(char*) to	client */
	      Channel *data;  /* chan(char*) to	client */
	      ...
	  };
	  struct Controlset
	  {
	      ...
	      Channel	  *ctl;
	      Channel	  *data;
	      ...
	      int clicktotype;
	      ...
	  };
	  void	      initcontrols(void)
	  Controlset* newcontrolset(Image *i, Channel *kc, Channel *mc,	Channel	*rc)
	  void	      closecontrolset(Controlset *cs)
	  int	  namectlfont(Font *font, char *name)
	  int	  freectlfont(char *name)
	  int	  namectlimage(Image *image, char *name)
	  int	  freectlimage(char *name)
	  Control*    createbox(Controlset *cs,	char *name)
	  Control*    createboxbox(Controlset *cs, char	*name)
	  Control*    createbutton(Controlset *cs, char	*name)
	  Control*    createcolumn(Controlset*,	char*)
	  Control*    createentry(Controlset *cs, char *name)
	  Control*    createkeyboard(Controlset	*cs, char *name)
	  Control*    createlabel(Controlset *cs, char *name)
	  Control*    createmenu(Controlset *cs, char *name)
	  Control*    createradiobutton(Controlset *cs,	char *name)
	  Control*    createrow(Controlset*, char*)
	  Control*    createscribble(Controlset	*cs, char *name)
	  Control*    createslider(Controlset *cs, char	*name)
	  Control*    createstack(Controlset*, char*)
	  Control*    createtab(Controlset*, char *)
	  Control*    createtext(Controlset *cs, char *name)
	  Control*    createtextbutton(Controlset *cs, char *name)
	  void	      closecontrol(Control *c)
	  int	  ctlprint(Control*, char*, ...);
	  void	      ctlerror(char *fmt, ...)
	  Control*    controlcalled(char *name)
	  void	      controlwire(Control *c, char *cname, Channel *ch)
	  void	      activate(Control *c)
	  void	      deactivate(Control *c)
	  void	      resizecontrolset(Controlset *cs)
	  void*	      ctlmalloc(uint n)
	  void*	      ctlrealloc(void *p, uint n)
	  char*	      ctlstrdup(char *s)
	  int	  ctldeletequits;

     DESCRIPTION
	  This library provides	a set of interactive controls for
	  graphical displays: buttons, sliders,	text entry boxes, and
	  so on.  It also provides aggregator Controls:	boxes,
	  columns, rows	and stacks of Controls.	 A stack is a collec-
	  tion of co-located Controls, of which	one is normally	visi-
	  ble.	A Controlset collects a	group of Controls that share
	  mouse	and keyboard.  Each Controlset has a separate thread
	  of control that processes keyboard and mouse events as well
	  as commands to be passed on to the Controls.	Since each
	  Controlset uses a thread, programs using the control library
	  must be linked with the thread library, thread(2).

	  Controls are manipulated by reading and writing to the con-
	  trol channel,	ctl, of	their Controlset.  Channels are
	  defined in thread(2).	Each Control has two output channels:
	  Event	delivers messages about	actions	within the control
	  (such	as a button press) and data delivers (if requested by
	  an appropriate write to ctl) control-specific	data such as
	  the contents of a field.

	  The library provides a simple	mechanism for automatic	lay-
	  out: the minimum and maximum sizes of	each simple control
	  can be specified.  Boxbox, row, column and stack Controls
	  then use these sizes to lay out their	constituent Controls
	  when called upon to do so.  See the description of these
	  grouping Controls for	further	details.

	Message	format
	  All messages are represented as UTF-8	text.  Numbers are
	  formatted in decimal,	and strings are	transmitted in the
	  quoted form of quote(2).

	  Messages sent	to a Controlset	are of the form,

	       sender: destination verb	[argument ... ]

	  The sender (and the colon following it) may be omitted.  For
	  example, the initial field of	a text entry control called
	  entry	could be set by	sending	the message,

	       entry value 'Hello, world!'

	  to its Controlset's ctl file.	 This message contains the
	  verb value and the single argument Hello, world!

	  To make it easy to write messages, the function chanprint
	  (see thread(2)) can be used to print formatted text to a
	  Controlset's channel.

	  The %q and %Q	formats	are convenient for properly quoting
	  string arguments, as in

	       chanprint(e->event, "value %q", "Don't touch!");

	  It is	wise to	use %q always instead of %s when sending mes-
	  sages, and avoid dealing with	the quoting explicitly.	 In
	  the other direction, tokenize	(see getfields(2)) parses
	  these	messages and interprets	the quotes correctly.

	  The destination of a message can be a	named control, or a
	  set of controls identified by	name or	type.  The command

	       'entry slider' show

	  (note	the quotation) sends the `show'	command	to the entry
	  named	entry and all controls of type slider. If there	were a
	  control whose	name was slider	that control would also	be
	  shown.

	  Note that we are still experimenting with destination	names.
	  One proposal is that a destination of	the form "`name1 name2
	  ⋯ type1 type2 ⋯' selects all controls of the named types in
	  the control hierarchies (of columns, rows and	stacks)	whose
	  names	precede	the types.

	  Messages sent	by a control on	its event channel are of the
	  form

	       sender: event

	  The sender is	the name of the	control	sending	the message;
	  the event describes the event.  Its format can often be con-
	  trolled by setting the Control's format string. For example,
	  when the user	types a	newline	at a text entry	Control	named
	  entry, the control sends the message

	       entry: value 'Hello again!' on its event	channel.

	Initialization and Control sets
	  After	initdraw (see graphics(2)) is called, the function
	  initcontrols should be called	to initialize the library.  It
	  calls	quotefmtinstall	to install the %q and %Q formats; see
	  quote(2).

	  Each control is represented by a Control data	structure and
	  is associated	with a Controlset that groups a	set of con-
	  trols	sharing	mouse, keyboard, and display.  Most applica-
	  tions	will need only one Controlset; only those with multi-
	  ple windows or unusual configurations	will need more than
	  one.	The function newcontrolset creates a Controlset.  Its
	  arguments are	the image (usually a window) on	which its con-
	  trols	will appear, typically the screen variable in the draw
	  library, and three channels: kc, a channel of	Runes from the
	  keyboard; mc,	a channel of Mouse structures from the mouse;
	  and rc, a channel of int that	indicates when the window has
	  been resized.	 Any of	the channels may be nil, in which case
	  newcontrolset	will call initkeyboard and/or initmouse	(see
	  keyboard(2) and mouse(2)) to initialize the keyboard and
	  mouse	and connect them to the	control	set.  The mouse	and
	  resize channels must both be nil or both be non-nil.

	  The function closecontrolset frees all the controls in the
	  control set and tears	down all the associated	threads.  It
	  does not close the mouse and keyboard.

	  The public elements of a Controlset are the flag
	  clicktotype, and the ctl and data channels.

	  Clicktotype is zero by default.  If it is set	to non-zero,
	  the controls in the set will acquire `focus' by the click-
	  to-type paradigm.  Otherwise,	focus is always	given to the
	  control under	the mouse.

	  Commands for controls	are sent through the Controlset's ctl
	  channel.  One	special	command	is recognized by the
	  Controlset itself:  Sending the string sync to the ctl chan-
	  nel causes that string to be echoed to the Controlset's data
	  channel when all commands up to the sync command have	been
	  processed.  The string is allocated and must be freed	(see
	  malloc(2)). Synchronization is necessary between sending a
	  command, for example,	to resize all controls,	and using
	  their	rect fields.

	  The function resizecontrolset	must be	provided by the	user.
	  When the associated window is	resized, the library will call
	  resizecontrolset with	the affected Controlset; the function
	  should reconnect to and redraw the window.

	  If all windows are organized in a hierachy of	boxboxes,
	  columns, rows	and stacks, and	minimum	and maximum sizes have
	  already been supplied, only the top control needs to be
	  resized (see the rect	command	below).

	Fonts and images
	  Fonts	and images must	be given names so they may be refer-
	  enced	in messages.  The functions namectlfont	and
	  namectlimage associate a (unique) name with the specified
	  font or image.  The association is removed by	freectlfont
	  and freectlimage. The	font or	image is not freed by these
	  functions, however.

	  The function initcontrols establishes	name bindings for all
	  the colors mentioned in <draw.h>, such as black, white, red,
	  yellow, etc.,	as well	as masks transparent and opaque.  It
	  also sets the	name font to refer to the default font vari-
	  able set up by initdraw.

	Creation
	  Each type of control has an associated creation function:
	  createbutton,	createentry, etc., whose arguments are the
	  Controlset to	attach it to and a globally unique name	for
	  it.  A control may be	destroyed by calling closecontrol.

	  The function controlcalled returns a pointer to the Control
	  with the given name, or nil if no such control exists.

	Configuration
	  After	a control is created, it must be configured using the
	  control-specific commands documented below.  Commands	are
	  sent to the ctl channel of the Controlset.  Multiple com-
	  mands	may be sent in a single	message; newline characters
	  separate commands.  For an example, see the implementation
	  of resizecontrolset in the EXAMPLES section.	Note that new-
	  line is a separator, not a terminator; the final command
	  does not need	a newline.

	  Messages sent	to the ctl channel are delivered to all	con-
	  trols	that match the destination field.  This	field is a set
	  of names separated by	spaces,	tabs or	newlines.  A control
	  matches the destination if its name or its type is among the
	  set.

	  The recipient	of a message ignores the initial sender: field
	  of the message, if present, making it	possible to send mes-
	  sages	generated on an	event channel directly to another
	  control's ctl	channel.

	Activation
	  When they are	created, controls are disabled:	they do	not
	  respond to user input.  Not all controls need	to be respon-
	  sive;	for example, labels are	static and a text display
	  might	show a log of messages but not be useful to edit.  But
	  buttons, entry boxes,	and other text displays	should be
	  active.

	  To enable a control, call the	activate function, which
	  specifies that the Control c should respond to mouse and
	  keyboard events; deactivate turns it off again.

	  Controls can be either revealed (default) or hidden. When a
	  control is hidden, it	will not receive mouse or keyboard
	  events and state changes or show commands will be ignored
	  until	the control is once again revealed. Control hiding is
	  particularly useful when different controls are overlayed,
	  revealing only the `top' one.

	  The function controlwire permits rearrangement of the	chan-
	  nels associated with a Control.  The channel cname (one of
	  "data" or "event") of	Control	c is reassigned	to the channel
	  ch. There are	several	uses for this operation: one may reas-
	  sign all the event channels to a single channel, in effect
	  multiplexing all the events onto a single channel; or	con-
	  nect the event channel of a slider to	the ctl	channel	for
	  delivery to a	text display (after setting the	format for the
	  slider's messages to name the	destination control and	the
	  appropriate syntax for the rest of the command) to let the
	  slider act as	a scroll bar for the text without rerouting
	  the messages explicitly.

	Controls
	  The following	sections document the individual controls in
	  alphabetical order.  The layout of each section is a brief
	  description of the control's behavior, followed by the mes-
	  sages	it sends on event, followed by the messages it accepts
	  via the ctl channel.	The event messages are triggered only
	  by mouse or keyboard action; messages	to the ctl file	do not
	  cause	events to be generated.

	  All controls accept the following messages:

	  rect minx miny maxx maxy
		  Set the bounding rectangle for the control on	the
		  display.  The	syntax generated by the	%R print for-
		  mat of the draw library is also acceptable for the
		  coordinates.
	  size [ minΔx	minΔy maxΔx maxΔy ]
		  Set the minimum and maximum size for automatic lay-
		  out in columns, rows and stacks. Without its four
		  arguments, this command is ignored by	primitive con-
		  trols	and used by grouping controls to calculate
		  their	minimum	and maximum sizes by examining those
		  of their constituent members.	 If all	primitive con-
		  trols	have been assigned a size, a single size
		  request addressed to the top of a layout hierarchy
		  will assign sizes to all grouping Controls.
	  hide	  Disable drawing of the control and ignore mouse and
		  keyboard events until	the control is once again
		  revealed.  Grouping Controls (column,	row, and
		  stack) pass the request down to their	constituent
		  Controls.
	  reveal  This is the opposite of hide:	the Control is
		  displayed and	mouse and keyboard operations resume.
		  Grouping Controls (column, row, and stack) pass the
		  request down to their	constituent Controls.  The
		  reveal command for stacks takes an optional argument
		  naming the Control to	be revealed; all other
		  Controls will	be hidden.
	  show	  Display the Control on its screen if not hidden.
		  Some actions will also cause the Controls to show
		  themselves automatically (but	never when the control
		  is hidden).  Grouping	Controls (column, row, and
		  stack) pass the request down to their	constituent
		  Controls.

	  Many messages	are common between multiple Controls.  Such
	  messages are described in detail here	to avoid repetition.
	  In the individual descriptions, only the syntax is
	  presented.

	  align	n     Specify the alignment of (some part of) the
		      Control's	display	within its rectangle.  For
		      textual controls,	the alignment specifies	where
		      the text should appear.  For multiline text, the
		      alignment	refers to each line within its box,
		      and only the horizontal part is honored.	For
		      other Controls, the alignment affects the
		      appearance of the	display	in a reasonable	way.
		      The valid	alignments are words with obvious
		      interpretations: upperleft, uppercenter,
		      upperright, centerleft, center, centerright,
		      lowerleft, lowercenter, and lowerright.
	  border n    Inset the	Control	(or separate constituent
		      Controls in boxbox, column and row Controls
		      after the	next rect command) within its rectan-
		      gle by n pixels, default zero.
	  bordercolor name
		      Paint the	border of the control with the named
		      color, default black.
	  focus	n     The Control now has (if n	is non-zero) or	does
		      not have ( if n is zero) focus.  Most Controls
		      ignore the message; there	are plans to make them
		      react.
	  format fmt  Set the format of	`value'	messages sent on the
		      event channel.  By default, the format is	"%q:
		      value %q"	for string-valued Controls, "%q: value
		      %d" for integer-valued Control s such as but-
		      tons, and	"%q: value 0x%x" for the keyboard and
		      scribble Controls.  The %q prints	the name of
		      the Control; the rest the	value.	Any supplied
		      format string must be type-equivalent to the
		      default for that Control.
	  image	name
	  light	name
	  mask name   Many controls set	a background image or color
		      for display.  The	image message sets the image.
		      The mask and light images	together specify how
		      the Control shows	it is enabled: the light is
		      printed through the mask when the	state is `on'
		      or `pressed'.  Otherwise,	the image appears
		      unmodified.  The default image is	white; mask
		      opaque; light yellow.
	  font name
	  textcolor name
		      These commands set the font and color for
		      displaying text.	The defaults are the default
		      font set up by the draw library, and black.
	  value	v     Set the value of the Control.  Textual images
		      accept an	arbitrary string; others an integral
		      value.

	Box
	  A box	is a trivial control that does nothing more than pass
	  keyboard, mouse, and focus messages back on its event	chan-
	  nel.	Keyboard characters are	sent in	the format

	       boxname:	key 0xnn

	  where	nn is the hexadecimal value of the character.  Mouse
	  messages are sent in the format

	       boxname:	mouse [x y] but	msec

	  where	x, y, but, and msec are	the various fields of the
	  Mouse	structure.  The	focus message is just

	       boxname:	focus n

	  where	n is 0 if the box has lost focus, 1 if it has acquired
	  it.

	  The box displays within its rectangle	an image, under	mask,
	  with specified alignment.  The control messages it accepts
	  are:

	  align	a  Controls the	placement of the image in the rectan-
		   gle (unimplemented).
	  border b
	  bordercolor name
	  focus	n
	  hide
	  image	name
	  rect minx miny maxx maxy
	  reveal
	  show
	  size minΔx minΔy maxΔx maxΔy

	Boxbox
	  A boxbox allows a set	of controls (``boxes'')	to be
	  displayed in rows and	columns	within the rectangle of	the
	  boxbox. The maximum of the minimum heights of	the consti-
	  tuent	controls determines the	number of rows to be
	  displayed.  The number of columns is the minimum that	allows
	  all Controls to be displayed.	 This aggregator works well
	  for collections of buttons, labels, or textbuttons that all
	  have a fixed height.

	  add name ...	adds the named control to the box of controls.
			The display order is determined	by the order
			of adding.  The	first named control is top
			left, the second goes below it,	etc.  It is
			possible to add	one control to multiple	group-
			ing controls but the layout of the result will
			be quite unpredictable.
	  border width
	  bordercolor color
	  hide		This command is	passed on to the member	con-
			trols.
	  image	color	Background color displayed between member con-
			trols.
	  reveal	This command is	passed on to the member	con-
			trols.
	  separation width
			Set the	separation between member controls to
			n pixels.
	  rect minx miny maxx maxy
			The member controls are	layed out within the
			given rectangle	according to the minimum and
			maximum	sizes given.  If the rectangle is not
			large enough for the minimum a fatal error is
			currently generated.  If the controls at their
			maximum	size are not big enough	to fit,	they
			are top-left justified at their	maximum	size
			in the space given.  Otherwise,	controls will
			get their minimum size and be enlarged propor-
			tional to the extra size given by the maximum
			until they fit given rectangle.	 The members
			are separated by borders of the	width esta-
			blished	by borderwidth.
	  remove name	Remove the named control from the box.
	  show		This command is	passed on to the member	con-
			trols.	Show also (re)displays background and
			borders.
	  size minΔx minΔy maxΔx maxΔy

	Button
	  A button is a	simple control that toggles its	state when
	  mouse	button 1 is pressed on its rectangle.  Each state
	  change triggers an event message:

	       buttonname: value n
	       where n encodes the mouse buttons used to make the
	       selection.

	  The button displays an image (which may of course be a sim-
	  ple color) and illuminates in	the standard way when it is
	  `on'.	 The control messages it accepts are:

	  align	a   Controls the placement of the image	in the rectan-
		    gle	(unimplemented).
	  border b
	  bordercolor name
	  focus	n
	  format fmt
	  hide
	  image	name
	  light	name
	  mask name
	  rect minx miny maxx maxy
	  reveal
	  show
	  size minΔx minΔy maxΔx maxΔy
	  value	n   Set	the button to `on' (if n is non-zero) or `off'
		    (if	n is zero).

	Column
	  A column is a	grouping control which lays out	its members
	  vertically, from top to bottom.  Currently, columns ignore
	  mouse	and keyboard events, but there are plans to allow
	  dragging the borders (when they have non-zero	width) between
	  constituent members.

	  add name ... adds the	named control to the column of con-
		       trols.  The vertical order is determined	by the
		       order of	adding.	 The first named control goes
		       at the top.  It is possible to add one control
		       to multiple grouping controls but the layout of
		       the result will be quite	unpredictable.
	  border width Set the border between members to the width
		       given.
	  bordercolor color
	  hide
	  image	color  Background color	displayed between member con-
		       trols.
	  reveal
	  separation width
		       Set the separation between member controls to n
		       pixels.
	  show	       These three commands are	passed on to the
		       member controls.	 Show also (re)displays	the
		       borders between members.
	  rect minx miny maxx maxy
		       The member controls are layed out within	the
		       given rectangle according to the	minimum	and
		       maximum sizes given.  If	the rectangle is not
		       large enough for	the minimum a fatal error is
		       currently generated.  However, see the example
		       at the end of this man page.  If	the controls
		       at their	maximum	size are not big enough	to
		       fit, they are centered at their maximum size in
		       the space given.	 Otherwise, controls will get
		       their minimum size and be enlarged proportional
		       to the extra size given by the maximum until
		       they fit	given rectangle.  The members are
		       separated by borders of the width established
		       by borderwidth.
	  remove name  Remove the named	control	from the column.
	  size [ minΔx	minΔy maxΔx maxΔy ]
		       Without arguments, this command computes	the
		       minimum and maximum size	of a column by adding
		       the minimum and maximum heights to set minΔy
		       and maxΔy, and it finds	the largest minimum and
		       maximum widths to set minΔy and	maxΔy.	When
		       called with arguments, it simply	sets the
		       minimum and maximum sizes to those given.

	Entry
	  The entry control manages a single line of editable text.
	  When the user	hits a carriage	return anywhere	in the text,
	  the control generates	the event message,

	       entryname: value	s

	  with s the complete text of the entry	box.

	  The cursor can be moved by clicking button 1;	at the moment,
	  there	is no way to select characters,	only a typing posi-
	  tion.	 Some control characters have special actions:
	  control-H (backspace)	deletes	the character before the cur-
	  sor; control-U clears	the line; and control-V	pastes the
	  snarf	buffer at the typing position.	Most important,	car-
	  riage	return sends the text to the event channel.

	  To enter passwords and other secret text without displaying
	  the contents,	set the	font to	one in which all characters
	  are the same.	 The easiest way to do this is to make a font
	  containing only one character, at position 0 (NUL), since
	  that position	is used	to render all characters not otherwise
	  defined in the font (see draw(2)). The file
	  /lib/font/bit/lucm/passwd.9.font defines such	a font.

	  The control messages the entry control accepts are:

	  align	a   Controls the placement of the text in the rectan-
		    gle.
	  border b
	  bordercolor name
	  data	    After receiving this message, the entry will send
		    its	value to its data channel as an	unadorned,
		    unquoted string.
	  focus	n   When it receives focus, the	entry box displays a
		    typing cursor.  When it does not have focus, the
		    cursor is not displayed.
	  font name
	  format fmt
	  hide
	  image	name
	  rect minx miny maxx maxy
	  reveal
	  show
	  size minΔx minΔy maxΔx maxΔy
	  textcolor name
	  value	s   Set	the string displayed in	the entry box.

	Keyboard
	  The keyboard control implements a simulated keyboard useful
	  on palmtop devices.  Keystrokes, generated by	mouse button 1
	  on the simulated keys, are sent as event messages:

	       keyboardname: value 0xnn

	  where	nn is the hexadecimal Unicode value of the character.
	  Shift, control, and caps lock	are handled by the keyboard
	  control itself; shift	and control affect only	the next regu-
	  lar keystroke.  The Alt key is unimplemented;	it will	become
	  equivalent to	the standard Plan 9 key	for synthesizing non-
	  ASCII	characters.

	  There	are two	special	keys, Scrib and	Menu, which return
	  values 0x10000 and 0x10001.

	  The image, mask, light rules are used	to indicate that a key
	  is pressed, but to aid clumsy	fingers	the keystroke is not
	  generated until the key is released, so it is	possible to
	  slide	the pointer to a different key to correct for bad aim.

	  The control messages the keyboard accepts are:

	  border b
	  bordercolor name
	  focus	n
	  font name1 name2
		Sets the font for the keys.  If	only one font is
		named, it is used for all keys.	 If two	are named, the
		second is used for key caps with special names such as
		Shift and Enter.  (Good	choices	on the Bitsy are
		/lib/font/bit/lucidasans/boldlatin1.6.font for the
		first and /lib/font/bit/lucidasans/unicode.6.font for
		the second argument.)  If neither is specified,	both
		will be	set to the default global font.
	  format fmt
	  hide
	  image	name
	  light	name
	  mask name
	  rect minx miny maxx maxy
	  reveal
	  show
	  size minx miny maxx maxy

	Label
	  A label is like a textbutton (q.v.)  that does not react,
	  but whose value is the text it displays.  The	control	mes-
	  sages	it accepts are:

	  align	a  Controls the	placement of the image in the rectan-
		   gle.
	  border b
	  bordercolor name
	  focus	n
	  font name
	  hide
	  image	name
	  rect minx miny maxx maxy
	  reveal
	  show
	  size minx miny maxx maxy
	  textcolor name
	  value	s  The value is	a string that can be modified only by
		   sending this	message	to the ctl file.

	Menu
	  A menu is a pop-up window containing a set of	textual	selec-
	  tions.  When a selection is made, it removes itself from the
	  screen and reports the selection by value:

	       menuname: value n

	  If no	selection is made, no message is reported.  Because it
	  creates a window, programs using a menu must have their
	  screen variable (see graphics(2) and window(2)) set up to be
	  refreshed properly.  The easiest way to do this is to	call
	  getwindow with refresh argument Refbackup (see graphics(2));
	  most programs	use Refnone.

	  The control messages accepted	by a menu are:

	  add text  Add	a line of text to the end of the menu.
	  align	a   Controls the left-right placement of the text in
		    its	rectangle.
	  border b
	  bordercolor name
	  focus	n
	  font name
	  format fmt
	  hide
	  image	name
	  rect minx miny maxx maxy
	  reveal
	  size minx miny maxx maxy
		    Only the origin of the rectangle is	significant;
		    menus calculate the	appropriate size.
	  selectcolor name
		    Set	the color in which to highlight	selected
		    lines; default yellow.
	  selecttextcolor name
		    Set	the color in which to draw the text in
		    selected lines; default black.
	  show	    Display the	menu. Not usually needed unless	the
		    menu is changed while visible; use window instead.
	  window
	  window n  With no arguments, toggle the menu's visibility;
		    otherwise make it visible (1) or invisible (0).
		    When the selection is made,	the menu will remove
		    its	window automatically.

	Radiobutton
	  The radiobutton assembles a group of buttons or textbuttons
	  into a single	control	with a numeric value.  Its value is -1
	  if none of the constituent buttons is	pressed; otherwise it
	  is the index,	starting at zero, of the button	that is
	  pressed.  Only one button may	be pressed; the	radiobutton
	  manipulates its buttons to guarantee this.  State changes
	  trigger an event message:

	       radiobuttonname:	value n

	  Buttons are added to the radio button	using the add message;
	  there	is no way to remove them, although they	may be turned
	  off independently using deactivate. The index	reported in
	  the value is defined by the order in which the buttons are
	  added.  The constituent buttons should be configured and
	  layed	out in the usual way; the rectangle of the radiobutton
	  is used only to `catch' mouse	events and should almost
	  always correspond to the bounding box	of the constituent
	  buttons.  In other words, the	geometry is not	maintained
	  automatically.

	  The control messages the radiobutton accepts are:

	  add name  Add	the control with the specified name to the
		    radiobutton.
	  focus	n
	  format fmt
	  hide
	  rect minx miny maxx maxy
	  reveal
	  size minx miny maxx maxy
	  show
	  value	n

	Row
	  A row	groups a number	of member controls left	to right in a
	  rectangle.  Rows behave exactly like columns with the	roles
	  of x and y interchanged.

	  The control messages it accepts are:

	  add name ...
	  border width
	  bordercolor color
	  hide
	  image	color
	  rect minx miny maxx maxy
	  remove name
	  reveal
	  separation width
	  show
	  size [ minΔx	minΔy maxΔx maxΔy ]

	Scribble
	  The scribble control provides	a region in which strokes
	  drawn	with mouse button 1 are	interpreted as characters in
	  the manner of	scribble(2). In	most respects, including the
	  format of its	event messages,	it is equivalent to a keyboard
	  control.

	  The control messages it accepts are:

	  align	a	   Controls the	placement of the image in the
			   rectangle (unimplemented).
	  border b
	  bordercolor name
	  focus	n
	  font name	   Used	to display the indicia.
	  hide
	  image	name
	  linecolor name   The color in	which to draw the strokes;
			   default black.
	  rect minx miny maxx maxy
	  reveal
	  size minx miny maxx maxy
	  show

	Stack
	  A stack groups a number of member controls in	the same
	  shared rectangle.  Only one of these controls	will be	visi-
	  ble (revealed), the others are hidden.

	  The control messages it accepts are:

	  hide
	  rect minx miny maxx maxy
	  remove name
	  reveal [ n ]
		      Without argument,	reveal is the opposite of
		      hide: it makes its selected control visible
		      after it was hidden.  With an argument, it makes
		      the n'th added control visible, hiding all oth-
		      ers.
	  show
	  size [ minΔx	minΔy maxΔx maxΔy ]
		      Without argument,	size computes the maximum of
		      the minimum and maximum sizes of its constituent
		      controls.	 With arguments, it sets the size to
		      the given	values.

	Slider
	  A slider controls an integer value by	dragging the mouse
	  with a button.  Configured appropriately, it can serve as a
	  scroll bar with the standard Plan 9 behavior.	 When the
	  value	changes, an event message is sent:

	       slidername: value n

	  The slider is	a good candidate for connecting	to another
	  control by setting its format	and rewiring its event channel
	  to the other's ctl channel.

	  The geometry of the slider is	defined	by three numbers: max
	  is a number representing the range of	the slider; vis	is a
	  number representing how much of what is being	controlled is
	  visible; and value is	a number representing the value	of the
	  slider within	its range.  For	example, if the	slider is
	  managing a textual display of	1000 lines, with 18 visible,
	  and the first	visible	line (numbered starting	form 0)	is
	  304, max will	be 1000, vis will be 18, and value will	be
	  304.	The indicator is the visual representation of the vis
	  portion of the controlled object.

	  The control messages the slider accepts are:

	  absolute n  If n is zero, the	slider behaves like a Plan 9
		      scroll bar: button 2 sets	absolute position,
		      button 1 decreases the value, and	button 3
		      increases	it.  If	n is non-zero, all buttons
		      behave like button 2, setting the	absolute
		      value.
	  border b
	  bordercolor name
	  clamp	end n The end is either	the word high or low; n	sets
		      whether that end is clamped or not.  If it is
		      clamped, that end	of the indicator is always at
		      its supremum.  A standard	scroll bar has neither
		      end clamped; a volume slider would have its low
		      end clamped.  If the low end is clamped, the
		      value of the slider is represented by the	high
		      end of the indicator; otherwise it is
		      represented by the low end.
	  focus	n
	  format fmt
	  hide
	  image	name
	  indicatorcolor name
		      Set the color in which to	draw the indicator;
		      default black.
	  max n	      Set the maximum value of the range covered by
		      the slider.
	  orient dir  The string dir begins either hor or ver to
		      specify the orientation of the slider.  The
		      default is vertical.  The	value always increases
		      to the right for horizontal sliders and down-
		      wards for	vertical sliders.
	  rect minx miny maxx maxy
	  reveal
	  size minx miny maxx maxy
	  show
	  value	n
	  vis n	      Set the visible area shown by the	indicator.

	Tab
	  A tab	control	combines radiobottuns with a stack of windows
	  giving the appearance	of tabbed controls.  Currently,	the
	  tabs are positioned at the top of the	stack.	The radiobut-
	  ton consists of textbuttons, the stack can be	composed of
	  any type of control.

	  Control messages are

	  add button control button control ...
		      Adds a button to the radiobutton,	and an associ-
		      ated control to the stack.  Buttons and controls
		      are numbered in the order	of addition.  There is
		      no remove	operation.
	  border b
	  bordercolor color
	  focus	n
	  format fmt  When a format string is defined, the tab control
		      reports which tab	is selected using the format
		      string (which must print a char* and an int).
	  image	color Color between member controls.
	  separation n
		      Spacing between buttons in the radiobutton and
		      between the row of buttons and the stack below
		      it.
	  rect n n n n
	  hide
	  reveal
	  size n n n n
	  show
	  value	n     Value must be an integer indicating which	tab to
		      bring to the top.

	Text
	  A text control presents a set	of lines of text.  The text
	  cannot be edited with	the keyboard, but can be changed by
	  control messages.  (A	more interactive text control will be
	  created eventually.)	The mouse can be used to select	lines
	  of text.  The	only event message reports a state change in
	  the selection	of a line:

	       textname: select	n s

	  states that line n has changed its selection state to	s,
	  either zero (unselected) or non-zero (selected).  The	non-
	  zero value encodes the mouse buttons that were down when the
	  selection occurred.

	  The control messages the text	control	accepts	are:

	  accumulate s
	  accumulate n s
	  add s
	  add n	s	 With one argument, append the string s	as a
			 new last line of the control; if n is speci-
			 fied, add the line before the current line n,
			 making	the new	line number n. The lines are
			 zero indexed and n can	be no greater than the
			 current number	of lines.  Add refreshes the
			 display, but accumulate does not, to avoid
			 n-squared behavior when assembling a piece of
			 text.
	  align	a	 Controls the placement	of each	line of	text
			 left-to-right in its rectangle.  Vertically,
			 lines are tightly packed with separation set
			 by the	font's interline spacing.
	  border b
	  bordercolor name
	  clear		 Delete	all text.
	  delete n	 Delete	line n.
	  focus	n
	  font name
	  image	name
	  rect minx miny maxx maxy
	  replace n s	 Replace line n	by the string s.
	  reveal
	  scroll n	 If n is non-zero, the text will automatically
			 scroll	so the last line is always visible
			 when new text is added.
	  select n m	 Set the selection state of line n to m.
	  selectcolor name
			 Set the color in which	to highlight selected
			 lines;	default	yellow.
	  selectmode s	 The string s is either	single or multi.  If
			 single, the default, only one line may	be
			 selected at a time; when a line is selected,
			 other lines are unselected.  If multi,	the
			 selection state of individual lines can be
			 toggled independently.
	  size minx miny maxx maxy
	  show
	  textcolor name
	  topline n	 Scroll	the text so the	top visible line is
			 number	n.
	  value	s	 Delete	all the	text in	the control and	then
			 add the single	line s.

	Textbutton
	  A textbutton is a textual variant of a plain button.	Each
	  state	change triggers	an event message:

	       textbuttonname: value n

	  where	n encodes the mouse buttons used to make the selec-
	  tion.

	  Like a regular button, the value of a	textbutton is an
	  integer; the text is the string that appears in the button.
	  It uses the image, light, mask method	of indicating its
	  state; moreover, the color of	the text can be	set to change
	  when the button is pressed.  The control messages it accepts
	  are:

	  align	a  Controls the	placement of the text in the rectan-
		   gle.
	  border b
	  bordercolor name
	  focus	n
	  font name
	  format fmt
	  hide
	  image	name
	  light	name
	  mask name
	  pressedtextcolor name
		   Set the color in which to display text when the
		   textbutton is pressed.
	  rect minx miny maxx maxy
	  reveal
	  size minx miny maxx maxy
	  show
	  text s   Set the text	displayed in the button.
	  textcolor name
	  value	n  Set the button to `on' (if n	is non-zero) or	`off'
		   (if n is zero).

	Helper functions
	  The function ctlerror	is called when the library encounters
	  an error.  It	prints the formatted message and exits the
	  program.

	  The functions	ctlmalloc, ctlrealloc, ctlstrdup, and
	  ctlrunestrdup	are packagings of the corresponding C library
	  functions.  They call	ctlerror if they fail to allocate
	  memory, and ctlmalloc	zeros the memory it returns.

	  Finally, for debugging, if the global	variable
	  ctldeletequits is set	to a non-zero value, typing a DEL will
	  cause	the program to call

	       ctlerror("delete");

	Caveat
	  This library is very new and is still	missing	a number of
	  important features.  The details are all subject to change.
	  Another level	of library that	handles	geometry and has sen-
	  sible	default	appearances for	the controls would be useful.

	  One unusual design goal of this library was to make the con-
	  trols	themselves easy	to implement.  The reader is
	  encouraged to	create new controls by adapting	the source to
	  existing ones.

     EXAMPLES
	  This example creates two entry boxes,	top and	bot, and
	  copies the contents of one to	the other whenever a newline
	  is typed.

	  #include <u.h>
	  #include <libc.h>
	  #include <thread.h>
	  #include <draw.h>
	  #include <mouse.h>
	  #include <keyboard.h>
	  #include <control.h>
	  Controlset *cs;
	  int ctldeletequits = 1;
	  void
	  resizecontrolset(Controlset*)
	  {
	      int i;
	      Rectangle	r, r1, r2;
	      if(getwindow(display, Refnone) < 0)
		  sysfatal("resize failed: %r");
	      r	= insetrect(screen->r, 10);
	      r1 = r;
	      r2 = r;
	      r1.max.y = r1.min.y+1+font->height+1;
	      r2.min.y = r1.max.y+10;
	      r2.max.y = r2.min.y+1+font->height+1;
	      chanprint(cs->ctl, "top rect %R\ntop show", r1);
	      chanprint(cs->ctl, "bot rect %R\nbot show", r2);
	  }
	  void
	  threadmain(int argc, char *argv[])
	  {
	      char *s, *args[3];
	      Channel *c;
	      Control *top, *bot;
	      int n;
	      initdraw(0, 0, "example");
	      initcontrols();
	      cs = newcontrolset(screen, nil, nil, nil);
	      cs->clicktotype =	1;
	      top = createentry(cs, "top");
	      chanprint(cs->ctl, "top image paleyellow");
	      chanprint(cs->ctl, "top border 1");
	      bot = createentry(cs, "bot");
	      chanprint(cs->ctl, "bot image paleyellow");
	      chanprint(cs->ctl, "bot border 1");
	      c	= chancreate(sizeof(char*), 0);
	      controlwire(top, "event",	c);
	      controlwire(bot, "event",	c);
	      activate(top);
	      activate(bot);
	      resizecontrolset(cs);
	      for(;;){
		  s = recvp(c);
		  n = tokenize(s, args,	nelem(args));
		  if(n==3 && strcmp(args[1], "value")==0){
		      if(strcmp(args[0], "top:") == 0)
			  chanprint(cs->ctl, "bot value	%q", args[2]);
		      else
			  chanprint(cs->ctl, "top value	%q", args[2]);
		  }
	      }
	      threadexitsall(nil);
	  }

	  A richer variant couples a text entry	box to a slider.
	  Since	the value of a slider is its numerical setting,	as a
	  decimal number, all that needs changing is the setup of bot:

	      bot = createslider(cs, "bot");
	      chanprint(cs->ctl, "bot border 1");
	      chanprint(cs->ctl, "bot image paleyellow");
	      chanprint(cs->ctl, "bot indicatorcolor red");
	      chanprint(cs->ctl, "bot max 100");
	      chanprint(cs->ctl, "bot clamp low	1");
	      chanprint(cs->ctl, "bot orient horizontal");

	  The rest is the same.	 Of course, the	value of the entry box
	  is only meaningful to	the slider if it is also a decimal
	  number.

	  Finally, we can avoid	processing events altogether by
	  cross-coupling the controls.	Replace	the rest of threadmain
	  with this:

	      chanprint(cs->ctl, "bot format %q", "%q: top value %q");
	      chanprint(cs->ctl, "top format %q", "%q: bot value %q");
	      controlwire(top, "event",	cs->ctl);
	      controlwire(bot, "event",	cs->ctl);
	      activate(top);
	      activate(bot);
	      resizecontrolset(cs);
	      for(;;)
		  yield();
	      threadexitsall(nil);

     SOURCE
	  /sys/src/libcontrol

     SEE ALSO
	  draw(2), frame(2), graphics(2), quote(2), thread(2)

     BUGS
	  The library is strict	about matters of formatting, argument
	  count	in messages, etc., and calls ctlerror in situations
	  where	it may be fine to ignore the error and continue.

```
