Common Desktop Environment: Desktop KornShell User's Guide

Chapter 1 Introduction to Desktop KornShell

Desktop KornShell(ldtksh) provides kshell scripts with the means for easily accessing most of the existing Xt and Motif functions. dtksh is based on ksh-93, which provides a powerful set of tools and commands for the shell programmer, and which supports the standard set of kshell programming commands.

dtksh supports all the features and commands provided by ksh-93. In addition, dtksh supports a large selection of the libDt functions, most of the widget-related Motif functions, a large subset of the Xt Intrinsics functions, and a small subset of the Xlib functions. All the supported functions are listed in Appendix A.

Using Desktop KornShell to Create Motif Applications

This section describes how to use dtksh to create Motif applications. To successfully use dtksh, you should have experience with Xlib, the Xt Intrinsics, the Motif widgets, and KornShell programming. It is also helpful to know the C programming language. If you are not familiar with any of these, you should refer to the appropriate documentation. Even if you are familiar with these systems, you should have access to the applicable man pages for reference.

In addition, your system should have these libraries:

Resources

Resources are widget variables that you use to define attributes such as size, location, or color. Each widget usually has a combination of its own resources, plus resources it inherits from higher level widgets. Xt Intrinsics and Motif resource names consist of a prefix (XtN or XmN) followed by the base name. The first letter of the base name is always lowercase, and the first letter of subsequent words within the base name is always uppercase. The convention for resource names in dtksh scripts is to delete the prefix and use the base name. Thus, the resource XmNtopShadowColor becomes topShadowColor.

Some Xt and Motif commands allow the shell script to pass in a variable number of parameters, representing resource-value pairs. This is similar to the argument list passed to the corresponding Xt or Motif C function. Examples include any of the commands used to create a widget, plus the XtSetValues command. In dtksh, resources are specified by a string with the following syntax:

resource:value

where resource is the name of the resource and value is the value assigned to the resource. dtksh automatically converts the value string to an appropriate internal representation. For example:

XtSetValues $WIDGET height:100 width:200 resizePolicy:RESIZE_ANY
XmCreateLabel LABEL $PARENT myLabel labelString:"Close Dialog"

When you retrieve widget resource values using XtGetValues, the return value is placed in an environment variable. Thus, unlike the Xt Intrinsics, the dtksh version of XtGetValues uses a name:(environment) variable pair, rather than a name:value pair. For example:

XtGetValues $WIDGET height:HEIGHT resizePolicy:POLICY             
		sensitive:SENSITIVE  echo $HEIGHT  echo $POLICY  echo

$SENSITIVE

The preceding dtksh segment might produce this output:

100  RESIZE ANY 
TRUE

Certain types of resource values, including string tables and bit masks, have special representation. For example, the List widget allows a string table to be specified for both the items and selectedItems resources. In dtksh, a string table is represented as a comma-separated list of strings, which is similar to how Motif treats them. When a resource that returns a string table is queried using XtGetValues, the resulting value is a comma-separated set of strings.

A resource that expects a bit mask value to be passed to it expects the mask to be specified as a string composed of the various mask values separated by the |(bar) character. When a resource that returns a bit mask is queried, the return value is a string representing the enabled bits, separated by the | character. For example, you could use the following command to set the mwmFunctions resource for the VendorShell widget class:

XtSetValues mwmFunctions: MWM_FUNC_ALL|MWM_FUNC_RESIZE

Unsupported Resources

dtksh supports most of the Motif resources. The following lists unsupported resources. Resources with an * (asterisk) can be specified at widget creation time by using XtSetValues, but can't be retrieved using XtGetValues.

dtksh app-defaults File

The dtksh app-defaults file, named Dtksh, is found in a location based on the following path description:

/usr/dt/app-defaults/<LANG>

The only information contained in this app-defaults file is the inclusion of the standard Dt base app-defaults file. The following is a listing of the dtksh app-defaults file:

#include
"Dt"

The file Dt is also located in /usr/dt/app-defaults/<LANG> and is shown in the following listing.

*foregroundThreshold: 
70   
!###  
!#  
!#   Help system specific resources  
!#  
!###   
!#  
!#  Display Area Colors  
!#  
!#     These resources set the colors for the display area(where  
!#     actual help text is displayed).  The resources are complex  
!# 	 because they have to override the standard color resources  
!#     in all cases.  
!#  
*XmDialogShell.DtHelpDialog*DisplayArea.background: White 
*XmDialogShell*XmDialogShell.DtHelpDialog*DisplayArea.background: White 
*XmDialogShell.DtHelpDialog*DisplayArea.foreground: Black 
*XmDialogShell*XmDialogShell.DtHelpDialog*DisplayArea.foreground: Black   
!# 

!#  Menu Accelerators  
!#  
!#     The following resources establish keyboard accelerators  
!#     for the most frequently accessed menu commands.  
!#  

*DtHelpDialogWidget*searchMenu.keyword.acceleratorText: Ctrl+I 
*DtHelpDialogWidget*searchMenu.keyword.accelerator:  Ctrl<Key>i 
*DtHelpDialogWidget*navigateMenu.backTrack.acceleratorText: Ctrl+B 
*DtHelpDialogWidget*navigateMenu.backTrack.accelerator:  Ctrl<Key>b 
*DtHelpDialogWidget*navigateMenu.homeTopic.acceleratorText: Ctrl+H 
*DtHelpDialogWidget*navigateMenu.homeTopic.accelerator:  Ctrl<Key>h 
*DtHelpDialogWidget*fileMenu.close.acceleratorText:      Alt+F4 
*DtHelpDialogWidget*fileMenu.close.accelerator: Alt<Key>f4

Variable Values

This section describes the types of values for some of the variables in a dtksh app-defaults file.

Defined Values

The C bindings of the interfaces to X, Xt and Motif include many nonstring values that are defined in header files. The general format of such values consists of an Xt or Xm prefix followed by a descriptive name. For example, one of the constraint values for a child of a form widget is XmATTACH_FORM. Equivalent values are specified in dtksh by dropping the prefix, just as in a Motif defaults file:

Boolean Values

You can specify a Boolean value as a parameter to a dtksh command using the words True or False; case is not significant. A Boolean result is returned as either True or False, using all lowercase letters.

Return Values

Graphical commands in dtksh fall into one of four categories, based on the definition of the corresponding C function:

  1. The function is void and returns no values. Example: XtMapWidget()

  2. The function is void, but returns one or more values through reference parameters. Example: XmGetColors()

  3. The function returns a non-Boolean value. Example: XtCreateManagedWidget()

  4. The function returns a Boolean value. Example: XtIsSensitive()

Category 1

A dtksh category 1 command follows the calling sequence of its corresponding C function. The number and order of parameters can be determined by looking at the standard documentation for the function. Example:

XtMapWidget $FORM

Category 2

A dtksh category 2 command also generally follows the calling sequence of its corresponding C function. It returns a value in an environment variable, instead of passing a pointer to a return variable. Example:

XmGetColors $FORM $BG FOREGROUND TOPSHADOW BOTTOMSHADOW SELECT  
echo "Foreground color = " $FOREGROUND

Category 3

A dtksh category 3 command differs slightly from its corresponding C function. Where the C function returns its value as the value of the procedure call, a dtksh command requires an additional parameter. This parameter is the name of an environment variable into which the return value is to be placed. It is always the first parameter. Example:

XmTextGetString TEXT_VALUE $TEXT_WIDGET  
echo "The value of the text field is "$TEXT_VALUE

Category 4

A dtksh category 4 command returns a value that can be used in a conditional expression just as in C. If the C function also returns values through reference variables (as in category 2), the dtksh command also uses variable names for the corresponding parameters. Example:

if XmIsTraversable $PUSH_BUTTON; then  
echo "The pushbutton is traversable"  
else 
echo "The pushbutton is not traversable"  fi

Generally, the order and type of parameters passed to a command matches those passed to the corresponding C function, except as noted for category 3 commands.

Immediate Return Value

Many of the category 3 commands return a single value using an environment variable specified as the first parameter to the command (for these special commands, the first parameter has the name variable). If this return value is immediately used in an expression, the special environment variable "-" may be used in place of a variable name. When dtksh encounters "-" as the name of the environment variable in which the return value is to be returned, it instead returns the result as the value of the command. This allows the shell script to embed the command call in another command call. This feature only works for commands that return a single value, and the value is returned in the first parameter. For example:

XtDisplay DISPLAY $FORM 
XSync $DISPLAY true

can be replaced by the equivalent statement:

XSync $(XtDisplay "-" $FORM) true

The reference to $DISPLAY is replaced with the value returned by the call to XtDisplay.

This capability is available for all category 3 commands except those that create a widget, those that return more than a single value, and those whose first parameter is not a named variable. Commands that do not accept "-" as the environment variable name include the following:

Initializing the Xt Intrinsics

A dtksh script must first initialize the Xt Intrinsics before it can call any of the Xlib, Xt, Motif, or libDt commands. You accomplish this by invoking the XtInitialize command, which returns an application shell widget. As is true for all dtksh commands that return a widget ID, XtInitialize returns the widget ID in the environment variable that is the first argument. For example, in:

XtInitialize TOPLEVEL myShellName Dtksh $0 "$@"

the widget ID is returned in the environment variable TOPLEVEL.

dtksh provides a default app-defaults file, which is used if the call to XtInitialize specifies an application class name of Dtksh. This app-defaults file contains the standard set of Dt application default values, so dtksh applications have a consistent look with other Dt applications.

Creating Widgets

There are several commands you can use to create widgets:

XtCreateWidget

Creates an unmanaged widget.

XtCreateManagedWidget

Creates a managed widget.

XtCreateApplicationShell

Creates an application shell.

XtCreatePopupShell

Creates a pop-up shell.

XmCreate<widgettypes>

Creates an unmanaged widget.

There is a specific format for each of these commands that you must follow. For example, suppose you want to create an unmanaged push button widget as a child of the top-level widget. You can use either XtCreateWidget or XmCreatePushButton. The formats for these commands are:

The actual commands to create a push button widget are:

XtCreateWidget BUTTON button XmPushButton $TOPLEVEL 
XmCreatePushButton BUTTON $TOPLEVEL button

Each of the preceding commands do exactly the same thing: create an unmanaged push button. Note that no resource values are set. Suppose that you want the background color of the push button to be red, and the foreground color to be black. You can set the values of these resources this way:

XtCreateWidget BUTTON button XmPushButton $TOPLEVEL \
  background:Red \
  foreground:Black 

XmCreatePushButton BUTTON $TOPLEVEL button\
  background:Red \ 
	  foreground:Black

All of the C functions that create a widget return a widget ID, or ID. The corresponding dtksh commands set an environment variable equal to the widget ID. These are category 3 commands, so the first argument is the name of the environment variable in which to return the widget ID. The widget ID is an ASCII string used by dtksh to access the actual widget pointer. Either of the following commands could be used to create a new form widget; however, in each case the widget ID for the new form widget is returned in the environment variable FORM:

After either of these commands, you can use $FORM to reference the new form widget. For example, you could use this command to create a label widget within the new form widget:

XmCreateLabel LABEL $FORM name\
  labelString:"Hi Mom" \
CH_FORM \ 
leftAttachment:ATTACH_FORM

Note -

There is a special widget ID called NULL, provided for cases where a shell script may need to specify a NULL widget. For example, to disable the defaultButton resource for a form widget, use the command XtSetValues $FORM defaultButton:NULL


Using a Callback

A callback is a function or procedure that is executed when an event or combination of events occurs. For example, a callback is used to achieve the desired result when a push button is "pressed." It is easy for a dtksh shell script to assign a command to be activated whenever a particular callback is invoked for a widget. The command could be as simple as a string of commands blocked together, or the name of the shell function to invoke.

Registering a Callback

An application registers a callback with a widget to specify a condition in which it is interested and to specify what action should occur when that condition occurs. The callback is registered using XtAddCallback. The action can be any valid dtksh command. For example:

XtAddCallback $WIDGET activateCallback "ActivateProc" 
XtAddCallback $WIDGET activateCallback \    
     "XtSetSensitive $BUTTON false"

Passing Data to a Callback

A callback needs to be passed context information, so it can determine what condition led to its call. For a C procedure, this information is typically passed in a callData structure. For example, a scale widget invoking a valueChangedCallback passes an instance of the following structure in callData:

typedef struct {
             int  reason;
             XEvent event;
             int value; 
}XmScaleCallbackStruct;

The C application's callback then does something like:

if (scaleCallData->reason == XmCR_VALUE_CHANGED)  
{
     eventType =scaleCallData->event->type;
     display =scaleCallData->event->xany.display;  
}

Similarly, when a callback is invoked in dtksh, the following special environment variable is set up before the callback command executes:

CB_WIDGET

This is set to the widget ID for the widget that is invoking the callback.

CB_CALL_DATA

This is set to the address of the callData structure passed by the widget to the callback.

The CB_CALL_DATA environment variable represents a pointer to a structure, and access to its fields uses a syntax similar to that of C. Nested environment variables are defined, named the same as the fields of the structure (but all in uppercase), and a dot is used to indicate containment of an element in a structure. Thus, the previous C code to access the callData provided by the scale widget translates to:

if [ ${CB_CALL_DATA.REASON} = "CR_VALUE_CHANGED" ]; then    
		eventType=${CB_CALL_DATA.EVENT.TYPE}    
		display=${CB_CALL_DATA.EVENT.XANY.DISPLAY}  
fi

The same is true of the event structure within the callData structure.

For most callback structures, the shell script is able to reference any of the fields defined for the particular callback structure, using the technique described earlier. In most cases, the shell script is not able to alter the values of the fields within these structures. The exception to this is the XmTextVerifyCallbackStruct, which is available during the losingFocusCallback, the modifyVerifyCallback and the motionVerifyCallback for the text widget. dtksh supports the modification of certain fields within this structure, to the extent that it is supported by Motif. The following fields within the callback structure are capable of being modified:

This is an example of how one of these fields can be modified: