For instance, your application might test the status of certain modes or settings to determine the appropriate help topic. Or, it might test the value of an input field and provide detailed help if the value is not valid, and general help if the value is valid.
From the author's point of view, entry points are established by assigning IDs at the appropriate places within the help volume. From the programmer's point of view, entry points are created by enabling the user to request help and using the appropriate ID when a particular request is made.
There are four general ways for users to request help:
Most requests display help topics that are part of the application's help volume. But, the Help System's help dialogs are also capable of displaying man pages, text files, and simple text strings.
The Help System's help dialogs are based exclusively on Xt Intrinsics and OSF/Motif programming, so you change the values within a help dialog just like any other widget: by setting resources.
The DtNhelpType resource determines what type of information is displayed. It can be set to any of these values:
Dt
NlocationId
resource.
ac = 0;
XtSetArg (al[ac], DtNhelpType, DtHELP_TYPE_TOPIC); ac++;
XtSetArg (al[ac], DtNhelpVolume, "MyVolume"); ac++;
XtSetArg (al[ac], DtNlocationId, "getting-started"); ac++;
XtSetArg (al[ac], DtNcolumns, 40); ac++;
XtSetArg (al[ac], DtNrows, 12); ac++;
XtSetValues (helpDialog, al, ac);
XtManageChild (helpDialog);
If the help volume MyVolume is not registered, then a complete path to the MyVolume.sdl file is required for the value of DtNhelpVolume. You can use a general help dialog to display string data, but this isn't recommended because most of its features do not apply to string data.
ac = 0;
XtSetArg (al[ac], DtNhelpType, DtHELP_TYPE_DYNAMIC_STRING); ac++;
XtSetArg (al[ac], DtNstringData, (char *)descriptionString); ac++;
XtSetValues (quickHelpDialog, al, ac);
XtManageChild (quickHelpDialog);
If the string is no longer needed within the application, the memory can be freed, because the help dialog makes its own copy of the data.
XtFree (descriptionString);
You can use a general help dialog to display a text file, but this isn't recommended because most of its features are useful only for standard help topics.
ac = 0;
XtSetArg (al[ac], DtNhelpType, DtHELP_TYPE_FILE); ac++;
XtSetArg (al[ac], DtNhelpFile, "/tmp/printer.list"); ac++;
XtSetArg (al[ac], DtNcolumns, 80); ac++;
XtSetArg (al[ac], DtNrows, 20); ac++;
XtSetValues (quickHelpDialog, al, ac);
XtManageChild (quickHelpDialog);
You can use a general help dialog to display a man page, but this isn't recommended because most of its features are useful only with standard help topics.
ac = 0;
XtSetArg (al[ac], DtNhelpType, DtHELP_TYPE_MAN_PAGE); ac++;
XtSetArg (al[ac], DtNmanPage, "grep"); ac++;
XtSetArg (al[ac], DtNcolumns, 80); ac++;
XtSetArg (al[ac], DtNrows, 20); ac++;
XtSetValues (quickHelpDialog, al, ac);
XtManageChild (quickHelpDialog);
Within your application, you should add a help callback to each widget where you want a unique entry point into help. The help callback mechanism automatically "walks" up the widget hierarchy (up to the shell widget) until it finds a widget with a help callback, then invokes that callback.
If you add a help callback to a manager widget, when the help key is pressed for any of its children, the manager's help callback is invoked (unless the child widget has a help callback of its own).
- XtAddCallback (
Widget widget,
String DtNhelpCallback,
XtCallbackProc HelpRequestCB,
XtPointer clientData );
If no help callbacks are found, nothing happens. Therefore, it is recommended that you add a help callback to each shell in your application. This ensures that no user requests for help are lost.
Adding a help callback to a dialog shell automatically enables the Help button on the dialog to invoke the help callback.
For this example, assume that the application's user interface is just a main window with three input fields: Name, Address, and Telephone Number. Here's what the HelpEntryIds.h file would contain:
Within the part of the application that initially creates the widgets, a help callback is added to each widget as follows:#define HELP_volumeName "MyVolume" #define HELP_MainWindow 100 #define HELP_MainWindow_ID "basic-tasks" #define HELP_MainWindow_ITEM_ID "main-window-desc"
#define HELP_NameField 101 #define HELP_NameField_ID "specifying-a-name" #define HELP_NameField_ITEM_ID "name-field-desc"
#define HELP_AddressField 102 #define HELP_AddressField_ID "specifying-an-address" #define HELP_AddressField_ITEM_ID "address-field-desc"
#define HELP_PhoneField 103 #define HELP_PhoneField_ID "specifying-a-phone-no" #define HELP_PhoneField_ITEM_ID "phone-field-desc"
XtAddCallback (mainWindow, DtNhelpCallback,
HelpRequestCB, HELP_MainWindow);
XtAddCallback (nameField, DtNhelpCallback,
HelpRequestCB, HELP_NameField);
XtAddCallback (addressField, DtNhelpCallback,
HelpRequestCB, HELP_AddressField);
XtAddCallback (phoneField, DtNhelpCallback,
HelpRequestCB, HELP_PhoneField);
Within the HelpRequestCB()
function, the clientData
parameter is used to dispatch the help requests (through a switch()
statement). Within each case, the value of a global flag itemHelp
is tested to see if the help callback was invoked by the F1 key (the flag is "false") or by the user picking the widget in item help mode (the flag is "true").
XtCallbackProc HelpRequestCB (
Widget w,
XtPointer clientData,
XtPointer callData )
{
char *topicToDisplay;
Boolean useQuickHelpDialog;
/* Determine the topic ID for the given ` clientData.' */
switch ((int)clientData)
{
case HELP_MainWindow:
useQuickHelpDialog = False;
if (itemHelpFlag)
topicToDisplay = HELP_MainWindow_ITEM_ID;
else
topicToDisplay = HELP_MainWindow_ID;
break; case HELP_NameField:
useQuickHelpDialog = True;
if (itemHelpFlag)
topicToDisplay = HELP_NameField_ITEM_ID;
else
topicToDisplay = HELP_NameField_ID;
break; case HELP_AddressField:
useQuickHelpDialog = True;
if (itemHelpFlag)
topicToDisplay = HELP_AddressField_ITEM_ID;
else
topicToDisplay = HELP_AddressField_ID;
break; case HELP_PhoneField:
useQuickHelpDialog = True;
if (itemHelpFlag)
topicToDisplay = HELP_PhoneField_ITEM_ID;
else
topicToDisplay = HELP_PhoneField_ID;
break; default:
/* An unknown clientData was received. */
/* Put your error handling code here. */
return;
break;
}
/* Display the topic. */
ac = 0;
XtSetArg (al[ac], DtNhelpType, DtHELP_TYPE_TOPIC); ac++;
XtSetArg (al[ac], DtNhelpVolume, HELP_volumeName); ac++;
XtSetArg (al[ac], DtNhelpType, topicToDisplay); ac++;
if (useQuickHelpDialog)
{
XtSetValues (mainQuickHelpDialog, al, ac);
XtManageChild (mainQuickHelpDialog);
}
else
{
XtSetValues (mainHelpDialog, al, ac);
XtManageChild (mainHelpDialog);
}
/* Clear the ` item help' flag. */
itemHelpFlag = False;
}
The preceding function assumes that the application uses two help dialogs for all help requests (mainHelpDialog
and mainQuickHelpDialog
), and that those dialogs have already been created. It also assumes that al
and ac
(used in assembling Xt argument lists) are declared elsewhere. The most important commands include:
The convenience function, DtHelpReturnSelectedWidgetId() , changes the pointer to a question mark and waits for the user to pick a widget. The ID of the selected widget is returned. This function is similar to the XmTrackingLocate() function except that DtHelpReturnSelectedWidgetId() returns NULL if the user presses Escape to cancel the operation.
To display help on the selected item, your application can simply invoke the help callback for the returned widget. This is equivalent to the user pressing F1 while using that widget.
If you want the application to differentiate between item help and F1 help, you can set a flag before calling the widget's help callback. The help callback procedure can then use that flag to determine that the callback was invoked as a result of item help and alter its response accordingly.
ProcessOnItem
Help() function that would be invoked by choosing On Item from the Help menu.
void ProcessOnItemHelp(
Widget widget)
{
/* Declare a variable for the selected widget. */
Widget selWidget=NULL;
int status=DtHELP_SELECT_ERROR;
/* Get an application shell widget from our widget hierarchy to
* pass into DtHelpReturnSelectedWidgetId().
*/
while (!XtIsSubclass(widget, applicationShellWidgetClass))
widget = XtParent(widget);
status = DtHelpReturnSelectedWidgetId(widget, NULL, &selWidget);
switch ((int)status)
{
case DtHELP_SELECT_ERROR:
printf("Selection Error, cannot continue\n");
break;
case DtHELP_SELECT_VALID:
/* We have a valid widget selection, now let's look for a registered help
* callback to invoke.
*/
while (selWidget != NULL)
{
if ((XtHasCallbacks(selWidget, XmNhelpCallback)
== XtCallbackHasSome))
{
/* Found a help callback, so just call it */
XtCallCallbacks((Widget)selWidget,
XmNhelpCallback,NULL);
break;
}
else
/* No help callback on current widget, so try the widget's parent */
selWidget = XtParent(selWidget);
}
break;
case DtHELP_SELECT_ABORT:
printf("Selection Aborted by user.\n");
break;
case DtHELP_SELECT_INVALID:
printf("You must select a component within your app.\n");
break;
}
}