# 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:

- `libDtHelp`

- `libDtSvc`

- `libX11`

- `libXm`

- `libXt`

- `libtt`

### 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`.

- All widget and gadget Classes:

  - Any fontlist resource *

  - Any pixmap resource *

- Composite:

  - `insertPosition`

  - `children`

- Core:

  - `accelerators`

  - `translations` *

  - `colormap`

- `XmText`:

  - `selectionArray`

  - `selectionArrayCount`

- `ApplicationShell`:

  - `argv`

- `WMShell`:

  - `iconWindow`

  - `windowGroup`

- `Shell`:

  - `createPopupChildrenProc`

- `XmSelectionBox`:

  - `textAccelerators`

- `Manager`, `Primitive`, and `Gadget` Subclasses:

  - `userData`

- `XmFileSelectionBox`:

  - `dirSearchProc`

  - `fileSearchProc`

  - `qualifySearchDataProc`

### 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:

- `XmDIALOG_COMMAND_TEXT` becomes `DIALOG_COMMAND_TEXT`

- `XtATTACH_FORM` becomes `ATTACH_FORM`

#### 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:

- `XtInitialize()`

- `XtCreateApplicationShell()`

- `XtCreatePopupShell()`

- `XtCreateManagedWidget()`

- `XtCreateWidget()`

- All commands of the form:

      XmCreate...()

- Most commands of the form:

      tt_...()

## 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:

- `XtCreateWidget` variable name widgetclass $parent [resource:value ...]

- `XmCreatePushButton` variable $parent name [resource:value ...]

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`:

- `XtCreateManagedWidget FORM name XmForm $PARENT`

- `XmCreateForm FORM $PARENT name`

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

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 `X` `tSetValues $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:

- `CB_CALL_DATA.DOIT`

- `CB_CALL_DATA.STARTPOS`

- `CB_CALL_DATA.TEXT.PTR`

- `CB_CALL_DATA.TEXT.LENGTH`

- `CB_CALL_DATA.TEXT.FORMAT`

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

- `CB_CALL_DATA.DOIT=”false”`

- `CB_CALL_DATA.TEXT.PTR=”*”`

- `CB_CALL_DATA.TEXT.LENGTH=1`