% ndialog -- native functions % Jessica L. Parsons % Wed Jan 16 09:00:33 PST 2008 #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](helpfile.html)) 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](#CHAIN) * [Object operators](#OBJECTS) * [Object constructors](#CREATE) * [Widgets](#WIDGETS) * [List Arrays](#LIA) * [Miscellaneous functions](#MISC) * [Examples](#EXAMPLES) ##[The MENU() function and object chains](id:CHAIN) =MENU()= [MENU(objchain,width,depth,title,prompt,flags)](class:example) The core function of ndialog is `MENU()`, which takes an [object chain](#OBJCHAIN), 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,...)](class:example) The `MENU()` error function. You can override this with your own error function, if you so desire. =[ObjChain()](id:OBJCHAIN)= [ObjChain(chain,obj)](class:example) 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)](class:example) 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)](class:example) Sort the object chain according to the (`x,y`) coordinates of the object in the chain. =deleteObjChain()= [deleteObjChain(chain)](class:example) Delete an object chain and all the objects contained in it. ##[Object operators](id:OBJECTS) Objects are created by calling one of the [object constructors](#CREATE) listed below. Once created, you can do a few things with them: =copyObj()= [copyObj(obj)](class:example) 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)](class:example) 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)](class:example) 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)](class:example) This disposes of the given object, (hopefully) returning all resources to the operating system. ##[Object constructors](id:CREATE)## > 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 > `foo`editable`bar`). > > =callback= > All objects support [callback functions](id:CALLBACK) > 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](helpfile.html) 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)](class:example) 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](class:example) 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)](class:example) Creates a check object. The state of the checkable item is in `bfr[0]`, which is a character. =newButton()= [newButton(number,label,callback,help)](class:example) 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)](class:example) 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)](class:example) 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)](class:example) 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)](class:example) 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](helpfile.html) to be able to read minimal pages legibly. =[newList](id:LIST)= [newList(x,y,width,height,nritems,items,prompt,prefix,flags,callback,help)](class:example) Create a `list` object. `Items` is an array of [`ListItem`](id: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 as `percent` filled. ##[Widgets](id: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);](class:example) [newEditableList(x, y, width, height, list, prompt, insert_callback, delete_callback, update_callback, help);](class:example) 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](id:LIA) A `List Array` is a way to encapsulate an array of [ListItems](#ListItem). 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)](class:example) 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)](class:example) Delete a LIA. =addToLIA()= [int addToLIA(LIA obj,char \*id,char \*name,char \*help)](class:example) 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)](class:example) 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)](class:example) Returns the number of rows in the LIA. =LIAlist()= [ListItem \*LIAlist(LIA obj)](class:example) Returns the ListItem array in the LIA. ##[Miscellaneous functions](id:MISC)# =setObjTitle()= [setObjTitle(obj,title)](class:example) Set the title for the given object =objTitle()= [objTitle(obj)](class:example) Get the title of the given object =setObjData()= [setObjData(obj,...)](class:example) 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)](class:example) Set the help for this object. =objDataPtr()= [objDataPtr(obj)](class:example) Return the data pointer for applicable objects (String, Check, Text) =objHelp()= [objHelp(obj)](class:example) Return the help for this object. =objSize()= [objSize(obj,&width,&depth)](class:example) Return the area, including prompts, taken up by this object. =objAt()= [objAt(obj,&x,&y)](class:example) Where is this object located in the window =ObjDataAt()= [ObjDataAt(obj,&x,&y,&width,&depth)](class:example) Where is the data area of this object. =objType()= [objType(obj)](class:example) What type of object am I? I can be `O_STRING, O_BUTTON, O_LIST, O_TEXT,` or `O_GAUGE` =objId(obj)= [objId(obj)](class:example) As above, except a string describing the object is returned. =isOKButton()= [isOKButton(obj)](class:example) Am I an OK button? =isCancelButton()= [isCancelButton(obj)](class:example) Am I a CANCEL button? =getObjList()= [getObjList(obj)](class:example) Returns the array of `ListItem`s that a list object contains. =getObjListSize()= [getObjListSize(obj)](class:example) Returns how many `ListItems`s that a list object contains. =getObjCursor()= [getObjCursor(obj)](class:example) return the current cursor position in an editable object =setObjCursor()= [setObjCursor(obj,cursor)](class:example) Set the current cursor position in an editable object =setWritable()= [setWritable(obj)](class:example) Make this object writable =setReadonly()= [setReadonly(obj)](class:example) Make this object readonly =writable()= [writable(obj)](class:example) Tell us whether this object is writable =hideObj()= [hideObj(obj)](class:example) make this object invisible =unhideObj()= [unhideObj(obj)](class:example) make this object visible =touchObj()= [touchObj(obj)](class:example) tell this object to redisplay itself the next time the window is redrawn =untouchObj()= [untouchObj(obj)](class:example) tell this object `not` to redisplay itself the next time the window is redrawn. =touched()= [touched(obj)](class:example) Tell us if the object needs to be redrawn. =getHelpTopic()= [getHelpTopic(obj)](class:example) Return the `` of a Help object =currentHtmlTag()= [currentHtmlTag(obj)](class:example) Return the currently selected html tag from a Help object =setHelpRoot()= [setHelpRoot(directory)](class:example) Set the document root for helpfile lookups (qv: `use_helpfile`) =getHelpCursor()= [getHelpCursor(obj)](class:example) 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)](class:example) 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` </DL> ##[Example programs](id:EXAMPLES)## * [Hello, world](hello.html) using ndialog. * A [somewhat fancier](fancyhello.html) `Hello, world` using ndialog. * A [A user interface](login.html) for `/sbin/login`.