NDIALOG native functions
Author: orc@pell.chi.il.us

### New dialog functions

> Ndialog is built around a collection of display objects, built into chains and fed to the MENU() function. It supports editable strings, check buttons, pushbuttons, menu lists, checklists, radio checklists, readonly text boxes, and readonly help (html subset) boxes.

> To compile something with ndialog, you need to include the header file `ndialog.h` (if you also want to use the dialog compatability functions, you also need to include `dialog.h` header file.) When linking, you need to include libnd (libnd_g is the debugging version) and several other libraries, as so:

    	-lnd -lpanel -lncurses -lgpm

the MENU() function and object chains
Object operators
Object constructors
Widgets
List Arrays
Miscellaneous functions
Examples

### The MENU() function and object chains

`MENU(objchain,width,depth,title,prompt,flags)`

  The core function of ndialog is MENU, which takes an object chain, displays it, then lets the user type input into it. Object chains are built up from objects by the function ObjChain, and are disposed of by the function deleteObjChain

  The appearance of a MENU form can be slightly modified by passing a combination of the following flags to it:

  FANCY_MENU
    Make the window frame just a little bit fancier than normal.
  ALIGN_LEFT
    Align the prompt to the left side of the form
  ALIGN_RIGHT
    Align the prompt to the right side of the form
  ERROR_FLAG
    print the prompt in a special error color (red, on color terminals) to indicate that something bad has happened to it.

  MENU() has the following return codes:

  MENU_ERROR
    Something went wrong; look at errno for details.
  MENU_OK
    The menu processed okay and you can now use the results.
  MENU_CANCEL
    The user cancelled the menu.
  MENU_ESCAPE
    The user used Esc to cancel the menu.
`Error(fmt,...)`
  The MENU() error function. You can override this with your own error function, if you so desire.
`ObjChain(chain,obj)`
  Add an object to an object chain. If the chain is NULL, create a new object chain containing just the object.
`extractFromObjChain(chain,obj)`
  extract the given object from the object chain, returning a pointer to the new object chain or NULL if something went wrong.
`sortObjChain(chain)`
  Sort the object chain according to the (x,y) coordinates of the object in the chain.
`deleteObjChain(chain)`
  Delete an object chain and all the objects contained in it.

### Object operators

> Objects are created by calling one of the object constructors listed below. Once created, you can do a few things with them:

`copyObj(obj)`
  This makes an exact copy of an object (including X and Y position, so it's somewhat less than useful for application programmers.)
`drawObj(obj,display)`
  draw the object on the given display, which is pointer to a magic object created by MENU() that tells drawObj how to display itself.
`editObj(obj,display,event,byevent)`

  Does editing on the given object. Event is a pointer to an gpm MEVENT record, and byevent is set if there is an even pending. The way ndialog events work is that when a mouse event happens inside editObj, editObj returns eEVENT so the caller can find out where the mouse even happened, find out which object will get the event, then call that object with byevent set to true.

  editObj has the following return codes:
  eNOP
    Nothing particular happened.
  eERROR
    Something wicked happened. Errno may contain information about the fault.
  eCANCEL
    The user cancelled out of this field.
  eTAB
    The user pressed [Tab] to advance to the next field. The callback for this object will not be fired on a eTAB event, so it will need to be manually called when we're finished with processing and are ready to continue.
  eBACKTAB
    The user pressed backtab to advance to the previous field. Otherwise like eTAB.
  eRETURN
    The user pressed [Return] to advance to the next field. The callback for this object is called on a eRETURN event.
  eEVENT
    A mouse or similar event happened and the caller needs to figure out what it was. As with eTAB and eBACKTAB, the callback function will not be called.
  eESCAPE
    The user pressed Esc to cancel changes to this field.
  eREFRESH
    The object wants the caller to refresh the screen.
  eEXITFORM
    The user is finished with input and wishes to exit this form.

  editObj may, and probably will, call drawObj to refresh fields while it is running.

`deleteObj(obj)`
  This disposes of the given object, (hopefully) returning all resources to the operating system.

### Object constructors

> The object constructers use some, or all, of the following arguments.
> x,y
>   Place the object at (x,y) in the form. (x,y) is relative to the first line in the form after the prompt.
> width
>   This is the width of the editable field. Any prefixes are not included in this width, nor are any fancy borders around the object.
> depth
>   This is the depth of the editable field. The title is not counted in this depth, nor are any fancy borders around the object.
> prompt
>   If a prompt is given, it will be drawn immediately above the editable area in the object.
> prefix
>   A prefix is another type of prompt. It goes immediately to the left of the editable field, unless it contains a |, in which case it will be split into a prefix and a suffix (eg: a prefix of foo|bar will display as fooeditablebar).
> callback
>   All objects support callback functions which are called when the user uses [Enter] to finish editing that object. Callback functions are passed a two `void *` arguments -- a pointer to the object and a pointer to display information, which can be passed to `drawObj` or `editObj` -- and return an status flag (0 if the callback failed, 1 if the callback succeeded, or -1 if the callback succeeded and wants the caller to close up shop right now.
> help
>   This argument, if given, is the name of a helpfile that gives help for this object. Helpfiles are an html subset and are processed by a Help object. Helpfiles can be pathnames or filenames, though it's better to use setHelpRoot() to set the pathname instead of hardcoding it into the object.

`newString(x,y,width,size,bfr,prompt,prefix,callback,help)`

  Create a string object located at position x,y inside the window and that has a width column wide editing area.

`newPWString(x,y,width,size,bfr,prompt,prefix,callback,help`

  Creates a password string object, which is exactly like a normal string object except that input is not echoed.

`newCheck(x,y,prompt,prefix,bfr,callback,help)`

  Creates a check object. The state of the checkable item is in bfr[0], which is a character.

`newButton(number,label,callback,help)`

  Create a button object. Buttons are placed on a buttonbar at the bottom of the window, and are placed in order of their number argument (button #1 will be placed to the left of button #2, for example.) The text on the button is the label argument.

`newOKbutton(number,label,callback,help)`

  Create an OK button. An OK button is somewhat like a regular button, except that when it's pushed, and if the callback approves, MENU() will immediately return with a code of MENU_OK.

`newCancelButton(number,label,callback,help)`

  Create a Cancel button. It's exactly like an OK button, except that MENU() immediately returns with a code of MENU_CANCEL.

`newText(x,y,width,height,size,prompt,prefix,bfr,callback,help)`
  Create a Text object. This is a scrollable readonly field that contains size bytes of text in bfr.
`newHelp(x,y,width,height,document,callback,help)`
  Create a help text object. Document is a local html page (no file:, http:, url:, mailto:, or whatnot) which is formatted and displayed by this object. newHelp does not support a full html specification, but it supports enough of a subset to be able to read a lot of html legibly.
`newList(x,y,width,height,nritems,items,prompt,prefix,`
  flags,callback,help)

  Create a list object. Items is an array of ListItems (defined in `ndialog.h` as

      		typedef struct {
      		    char *id;
      		    char *item;
      		    char *help;
      		    char selected;
      		} ListItem;

  where the id field is the libdialog key field, and help is context-sensitive help for this ListItem.

  The flags argument is a bitmap determining how the list will be displayed.

  CHECK_SELECTED
    place a checkbox in front of each ListItem.
  HIGHLIGHT_SELECTED
    highlight selected items, and use arrow pointers to show the current item.
  MENU_SELECTION
    the list is a menu list; when you select an item, the list object will return control to the caller.
  SHOW_IDS
    When displaying each ListItem, show both the item and the id. (This is now libdialog works).
  NO_HOTKEYS
    Normally, a list will display with the first character in each item highlit, and you can type that character to jump to that item. If, for some reason, you don't want to be able to do that, you can use this flag.
  DEL_LIST
    Select items from this list when the user presses the DEL key, not when they double-click or press return.
  ALWAYS_HIGHLIT
    Always show the current item a MENU_SELECTION list.
  DONT_CLIP_ITEMS
    Fail if any of the items are too long to fit into the desired window.

  You can find out what items are selected inside the callback function by using `getObjList(void* obj)` to get a pointer to the array of ListItems, `getObjListSize(void *obj)` to get the number of items in the list, then walking the list looking for selected items.

`newRadioList(x,y,width,height,nritems,items,prompt,prefix,`
  flags,callback,help)

  Creates a radiolist object, which is like a list object except that only one item can be selected at a time.

`newMenu(x,y,width,height,nritems,items,prompt,prefix,`
  flags,callback,help)

  Creates a menu object, which is like a list object except that it returns to the caller as soon as an item is selected.

`newGauge(x,y,width,percent,prompt,prefix)`
  Creates a gauge object, which is a readonly progress gauge, that's displayed as percent filled.

### Widgets

> Widgets are multipart display objects; they are manipulated exactly the same as other objects, but have wads of additional complexity tossed into them.

List Widgets

  List widgets are made up of a string, a list, an ADD button, a DELETE button, and, optionally, a MODIFY button. They can be used for building lists of things, like, oh, dns servers, domains to search, and search order. The list they work on is a List Array object. You use the `newListWidget` or `newEditableList` functions to create a list widget.

  `newListWidget(x, y, width, height, list, prompt, insert callback, delete callback, dummy, help);`

  `newEditableList(x, y, width, height, list, prompt, insert callback, delete callback, update callback, help);`

  x,y
    The X and Y position of the widget on the form that displays it.
  width, height
    The width and the height of the list; this is NOT the width and the height of the entire widget. To compute that, add 12 to the width and 3 (4 if you give it a title) to the height.
  list
    The List Array that this widget works on.
  prompt
    A prompt string to go at the top of the widget.
  insert callback, delete callback
    These callbacks are called when you insert a new item into the list or delete an item from the list. They do not actually insert or delete items from the list; the list widget does that all by itself. All these callbacks do is validate the entry or deletion.
  update callback
    If this callback is nonzero, the list widget will have a MODIFY button that call it.
  help
    The helpfile.

### List Arrays

> A List Array is a way to encapsulate an array of ListItems. It is primarily used in widget sets, though you can use it to manage your own arrays. A List Array is called a `LIA`.

LIA functions

`LIA newLIA(ListItem *list, int nrlist)`
  Create a new LIA, initializing it from the given ListItem array. If you wish to create an empty LIA, pass 0 for the ListArray.
`void deleteLIA(LIA obj)`
  Delete a LIA.
`int addToLIA(LIA obj, char *id, char *name, char *help)`
  Add a ListItem to the LIA. We pass in the three useful fields of the listItem separately. Note that you must pass valid strings or 0 for the ListItem fields, because copies are made of these strings in the new row in LIA. `addToLIA` returns the number of rows in the list array.
`int delFromLIA(LIA obj, int row)`
  Delete the given row from the LIA. If the row cannot be deleted, it returns EOF, otherwise it returns the number of rows left in the LIA.
`int LIAcount(LIA obj)`
  Returns the number of rows in the LIA.
`ListItem* LIAlist(LIA obj)`
  Returns the ListItem array in the LIA.

### Miscellaneous functions

`setObjTitle(obj,title)`
  Set the title for the given object
`objTitle(obj)`
  Get the title of the given object
`setObjData(obj,...)`
  Set the data for the object. The arguments depend on the object:
  String
    setObjData(obj,string, length);
  List [Menu,Checklist,Radiolist]
    setObjData(obj,0L,items,nritems);
  Text [Help]
    setObjData(obj,text);
  Check
    setObjData(obj,check);
  all others
    setObjData(obj,data pointer);
`setObjHelp(obj,help)`
  Set the help for this object.
`objDataPtr(obj)`
  Return the data pointer for applicable objects (String, Check, Text)
`objHelp(obj)`
  Return the help for this object.
`objSize(obj,&width,&depth)`
  Return the area, including prompts, taken up by this object.
`objAt(obj,&x,&y)`
  Where is this object located in the window
`ObjDataAt(obj,&x,&y,&width,&depth)`
  Where is the data area of this object.
`objType(obj)`
  What type of object am I? I can be O_STRING, O_BUTTON, O_LIST, O_TEXT, or O_GAUGE
`objId(obj)`
  As above, except a string describing the object is returned.
`isOKButton(obj)`
  Am I an OK button?
`isCancelButton(obj)`
  Am I a CANCEL button?
`getObjList(obj)`
  Returns the array of ListItems that a list object contains.
`getObjListSize(obj)`
  Returns how many ListItemss that a list object contains.
`getObjCursor(obj)`
  return the current cursor position in an editable object
`setObjCursor(obj,cursor)`
  Set the current cursor position in an editable object
`setWritable(obj)`
  Make this object writable
`setReadonly(obj)`
  Make this object readonly
`writable(obj)`
  Tell us whether this object is writable
`hideObj(obj)`
  make this object invisible
`unhideObj(obj)`
  make this object visible
`touchObj(obj)`
  tell this object to redisplay itself the next time the window is redrawn
`untouchObj(obj)`
  tell this object not to redisplay itself the next time the window is redrawn.
`touched(obj)`
  Tell us if the object needs to be redrawn.
`getHelpTopic(obj)`
  Return the <TITLE> of a Help object
`currentHtmlTag(obj)`
  Return the currently selected html tag from a Help object
`setHelpRoot(directory)`
  Set the document root for helpfile lookups (qv: use_helpfile)
`getHelpCursor(obj)`
  Allocate a help cursor and return a pointer to it. Help cursors contain window positioning state and href linkages, so can't be accessed by the conventional getObjCursor() and setObjCursor() methods.
`setHelpCursor(obj,cursor)`
  Set the cursor in a help object to the specified location. If it cannot do this, setHelpCursor will return 0, otherwise it will return 1

### Example programs

Hello
  Hello, world using ndialog.
Fancyhello
  A somewhat fancier Hello, world using ndialog.
Login
  The user interface for /sbin/login, as a point and drool'ed app.

Written March 1998 by David Parsons