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 libcurses (or libncurses and libpanel)

The MENU() function and object chains

=MENU()= 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()= Error(fmt,…) The MENU() error function. You can override this with your own error function, if you so desire.

=ObjChain()= 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()= 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()= sortObjChain(chain) Sort the object chain according to the (x,y) coordinates of the object in the chain.

=deleteObjChain()= 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()= 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()= drawObj(obj,display) draw the object on the given display, which is a pointer to a magic object created by MENU() that tells drawObj how to display itself. =editObj= 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](#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()= deleteObj(obj) This disposes of the given object, (hopefully) returning all resources to the operating system.

Object constructors

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()= 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()= 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()= 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()= 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()= 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()= 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()= 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()= 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 minimal pages legibly. =newList= newList(x,y,width,height,nritems,items,prompt,prefix,flags,callback,help) Create a list object. Items is an array of ListItem’s (defined in ndialog.h as

typdef 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 highlight the current item in 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 `ListItem`s, `getObjListSize(void \*obj)`
to get the number of items in the list, then walking the
list looking for `selected` items.

=newRadioList()= [newRadioList(x,y,width,height,nritems,items,prompt,prefix,flags,callback,help)](class:example) Creates a radiolist object, which is like a [list object](#LIST) except that only one item can be selected at a time. =newMenu()= [newMenu(x,y,width,height,nritems,items,prompt,prefix,flags,callback,help)](class:example) 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()= [newGauge(x,y,width,percent,prompt,prefix)](class:example) Creates a gauge object, which is a readonly progress gauge, that's displayed aspercent` 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.

=ListWidgets= 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);

List widgets are made up of a string, a list, an ADD button,
a DELETE button, and, optionally, a [MODIFY](#listWidgetModify)
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](#LIA) object.  You use the
`newListWidget` or `newEditableList` functions to create a list
widget.


=`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](#LIA) 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`](id:listWidgetModify)=
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

=newLIA()= 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. =deleteLIA()= void deleteLIA(LIA obj) Delete a LIA. =addToLIA()= 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. =delFromLIA()= 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. =LIAcount()= int LIAcount(LIA obj) Returns the number of rows in the LIA. =LIAlist()= ListItem *LIAlist(LIA obj) Returns the ListItem array in the LIA.

Miscellaneous functions

=setObjTitle()= setObjTitle(obj,title) Set the title for the given object =objTitle()= objTitle(obj) Get the title of the given object =setObjData()= setObjData(obj,…) Set the data for the object. The arguments depend on the object:

=`String`=
setObjData(obj,string, length);
=[`List`](id:menu "Menu,Checklist,Radiolist")=
setObjData(obj,0L,items,nritems);
=`Text` [`Help`]=
setObjData(obj,text);
=`Check`=
setObjData(obj,check);
=`all others`=
setObjData(obj,data pointer);

=setObjHelp()= setObjHelp(obj, help) Set the help for this object. =objDataPtr()= objDataPtr(obj) Return the data pointer for applicable objects (String, Check, Text) =objHelp()= objHelp(obj) Return the help for this object. =objSize()= objSize(obj,&width,&depth) Return the area, including prompts, taken up by this object. =objAt()= objAt(obj,&x,&y) Where is this object located in the window =ObjDataAt()= ObjDataAt(obj,&x,&y,&width,&depth) Where is the data area of this object. =objType()= objType(obj) What type of object am I? I can be O_STRING, O_BUTTON, O_LIST, O_TEXT, or O_GAUGE =objId(obj)= objId(obj) As above, except a string describing the object is returned. =isOKButton()= isOKButton(obj) Am I an OK button? =isCancelButton()= isCancelButton(obj) Am I a CANCEL button? =getObjList()= getObjList(obj) Returns the array of ListItems that a list object contains. =getObjListSize()= getObjListSize(obj) Returns how many ListItemss that a list object contains. =getObjCursor()= getObjCursor(obj) return the current cursor position in an editable object =setObjCursor()= setObjCursor(obj,cursor) Set the current cursor position in an editable object =setWritable()= setWritable(obj) Make this object writable =setReadonly()= setReadonly(obj) Make this object readonly =writable()= writable(obj) Tell us whether this object is writable =hideObj()= hideObj(obj) make this object invisible =unhideObj()= unhideObj(obj) make this object visible =touchObj()= touchObj(obj) tell this object to redisplay itself the next time the window is redrawn =untouchObj()= untouchObj(obj) tell this object not to redisplay itself the next time the window is redrawn. =touched()= touched(obj) Tell us if the object needs to be redrawn. =getHelpTopic()= getHelpTopic(obj) Return the <TITLE> of a Help object =currentHtmlTag()= currentHtmlTag(obj) Return the currently selected html tag from a Help object =setHelpRoot()= setHelpRoot(directory) Set the document root for helpfile lookups (qv: use_helpfile) =getHelpCursor()= 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()= 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