Copyright: Obsolete Routines 22Jan97


Documentation for Obsolete IDL Routines

To improve the overall quality and functionality of IDL, Research Systems occasionally replaces existing routines with new, improved routines. In many cases, existing routines are improved without changing their existing behavior—through improvements of the underlying algorithms, for example, or by adding keyword functionality. In some cases, however, the improved methods are incompatible with the old. In these situations, we consider the routines that we have replaced to be obsolete. Routines that have become obsolete are documented in this help file.


DDE Routines

These routines are obsolete and should not be used in new IDL code.

Windows-Only Routines for Dynamic Data Exchange (DDE)

IDL for Windows supports DDE client capability for cold DDE links. The relevant system calls are documented below:

Result = DDE_GETSERVERS()

This function returns an array of service names for the currently-available DDE servers.

Result = DDE_GETTOPICS(server)

This function returns the topics list for the specified server. The server argument is a scalar string containing the name of the desired DDE server.

Result = DDE_GETITEMS(server)

This function returns the items list for the specified server. The server argument is a scalar string containing the name of the desired DDE server.

Result = DDE_REQUEST(server, topic, item)

This function returns the requested data in string format. The server, topic, and item arguments must be scalar strings.

DDE_EXECUTE, server, topic, command

This procedure causes the DDE server to execute the command for the specified topic. The server, topic, and command arguments must be scalar strings.


GETHELP

This routine is obsolete and should not be used in new IDL code.

The GETHELP function returns information on variables defined at the program level from which GETHELP is called. The function builds a string array that contains information that follows the format used by the IDL HELP command.

When called without an argument, GETHELP returns a string array that normally contains variable data that is in the same format as used by the IDL HELP procedure. The variables in this list are those defined for the routine (or program level) that called GETHELP. If there are no variables defined, or the specified variable does not exist, GETHELP returns a null string. Other information can be obtained by setting keywords.

This routine is written in the IDL language. Its source code can be found in the file gethelp.pro in the lib subdirectory of the IDL distribution.

Calling Sequence

Result = GETHELP([Variable])

Arguments

Variable

A scalar string that contains the name of the variable from which to get information. If this argument is omitted, GETHELP returns an array of strings where each element contains information on a separate variable, one element for each defined variable.

Keywords

FULLSTRING

Normally a string that is longer than 45 chars is truncated and followed by "..." just like the HELP command. Setting this keyword will cause the full string to be returned.

FUNCTIONS

Setting this keyword will cause the function to return all current IDL compiled functions.

ONELINE

If a variable name is greater than 15 characters it is usually returned as 2 two elements of the output array (Variable name in 1st element, variable info in the 2nd element). Setting this keyword will put all the information in one string, separating the name and data with a space.

PROCEDURES

Setting this keyword will cause the function to return all current IDL compiled procedures.

SYS_PROCS

Setting this keyword will cause the function to return the names of all IDL system (built-in) procedures.

SYS_FUNCS

Setting this keyword will cause the function to return the names of all IDL system (built-in) functions.

RESTRICTIONS: Due to the diffuculties in determining if a variable is of type associate, the following conditions will result in the variable being listed as a structure. These conditions are:

o Associate record type is structure. o Associated file is opened for update (openu). o Associate file is not empty.

Another difference between this routine and the IDL help command is that if a variable is in a common block, the common block name is not listed next to the variable name. Currently there is no method available to get the common block names used in a routine.

Example

To obtain a listing in a help "format" of the variables contained in the current routine you would make the following call:

HelpData = GetHelp()

The variable HelpData would be a string array containing the requested information.


HANDLE_CREATE

This routine is obsolete and should not be used in new IDL code.

The HANDLE_CREATE function creates a new handle. A "handle" is a dynamically-allocated variable that is identified by a unique integer value known as a "handle ID". Handles can have a value, of any IDL data type and organization, associated with them. This function returns the handle ID of the newly-created handle.

Because handles are dynamic, they can be used to create complex data structures. They are also global in scope, but do not suffer from the limitations of COMMON blocks. That is, handles are available to all program units at all times. (Remember, however, that IDL variables containing handle IDs are not global in scope and must be declared in a COMMON block if you want to share them between program units.)

Handle Terminology

The following terms are used to describe handles in the documentation for this function and other handle-related routines:

•	Handle ID: The unique integer identifier associated with a handle.

•	Handle value: Data of any IDL type and organization associated with a handle.

•	Top-level handle: A handle at the top of a handle hierarchy. A top-level handle can have children, but does not have a parent.

•	Parents, children, and siblings: These terms describe the relationship between handles in a handle hierarchy. When a new handle is created, it can be the start of a new handle hierarchy (a top-level handle) or it can belong to the level of a handle hierarchy below an existing handle. A handle created in this way is said to be a child of the specified parent. Parents can have any number of children. All handles that share the same parent are said to be siblings.

Calling Sequence

Result = HANDLE_CREATE([ID])

Arguments

ID

If this argument is present, it specifies the handle ID relative to which the new handle is created. Normally, the new handle becomes the last child of the parent handle specified by ID. However, this behavior can be changed by setting the FIRST_CHILD or SIBLING keywords.

Omit this argument to create a new top-level handle without a parent.

Keywords

FIRST_CHILD

Set this keyword to create the new handle as the first child of the handle specified by ID. Any existing children of ID become later siblings of the new first child (i.e., the existing first child becomes the second child, the second child becomes the third child, etc.).

NO_COPY

Usually, when the VALUE keyword is used, the source variable memory is copied to the handle value. If the NO_COPY keyword is set, the value data is taken away from the source variable and attached directly to the destination. This feature can be used to move data very efficiently. However, it has the side effect of causing the source variable to become undefined.

SIBLING

Set this keyword to create the new handle as the sibling handle immediately following ID. Any other siblings currently following ID become later siblings of the new handle. Note that you cannot create a handle that is a sibling of a top-level handle.

VALUE

The value to be assigned to the handle.

Every handle can contain a user-specified value of any data type and organization. This value is not used by the handle in any way, but exists entirely for the convenience of the IDL programmer. Use this keyword to set the handle value when the handle is first created.

If the VALUE keyword is not specified, the handle's initial value is undefined.

Handle values can be retrieved using the HANDLE_VALUE procedure.

Examples

The following commands create a top-level handle with 3 child handles. Each handle is assigned a different string value:

top = HANDLE_CREATE()	;Create top-level handle without an initial handle value.

first = HANDLE_CREATE(top, VALUE='First child')
;Create first child of the top-level handle.

second = HANDLE_CREATE(top, VALUE='Second child')
;Create second child of the top-level handle.

third = HANDLE_CREATE(first, VALUE='Another child', /SIBLING)
;Create a new sibling between first and second. This handle is also a child of the top-level handle.


HANDLE_FREE

This routine is obsolete and should not be used in new IDL code.

The HANDLE_FREE procedure frees an existing handle, along with any dynamic memory currently being used by its value. Any child handles associated with ID are also freed.

Calling Sequence

HANDLE_FREE, ID

Arguments

ID

The ID of the handle to be freed. Once the handle is freed, further use of it is invalid and causes an error to be issued.

Examples

To free all memory associated with the top-level handle top, and all its children, use the command:

HANDLE_FREE, top


HANDLE_INFO

This routine is obsolete and should not be used in new IDL code.

The HANDLE_INFO function returns information about handle validity and connectivity. By default, it returns True if the specified handle ID is valid. Keywords can be set to return other types of information.

Calling Sequence

Result = HANDLE_INFO(ID)

Arguments

ID

The ID of the handle for which information is desired. This argument can be scalar or array an array of IDs. The result of HANDLE_INFO has the same structure as ID, and each element gives the desired information for the corresponding element of ID.

Keywords

FIRST_CHILD

Set this keyword to return the handle ID of the first child of the specified handle. If the handle has no children, 0 is returned.

NUM_CHILDREN

Set this keyword to return the number of children related to ID.

PARENT

Set this keyword to return the handle ID of the parent of the specified handle. If the specified handle is a top-level handle (i.e., it has no parent), 0 is returned.

SIBLING

Set this keyword to return the handle ID of the sibling handle following ID. If ID has no later siblings, or if ID is a top-level handle, 0 is returned.

VALID_ID

Set this keyword to return 1 if ID represents a currently valid handle. Otherwise, zero is returned. This is the default action for HANDLE_INFO if no other keywords are specified.

Examples

The following commands demonstrate a number of different uses of HANDLE_INFO:

IF HANDLE_INFO(handle1) THEN PRINT, 'Valid handle.'
;Print a message if handle1 is a valid handle ID.

handle = HANDLE_INFO(top, /FIRST_CHILD)
;Retrieve the handle ID of the first child of top.

next= HANDLE_INFO(handle1, /SIBLING)
;Retrieve the handle ID of the next sibling of handle1.


HANDLE_MOVE

This routine is obsolete and should not be used in new IDL code.

The HANDLE_MOVE procedure moves a handle (specified by Move_ID) to a new location. This new position is specified relative to Static_ID.

Calling Sequence

HANDLE_MOVE, Static_ID, Move_ID

Arguments

Static_ID

The handle ID relative to which the handle specified by Move_ID is moved. By default, Move_ID becomes the last child of Static_ID. This behavior can be changed by specifying one of the keywords described below.

If Static_ID is set to 0, Move_ID becomes a top level handle without any parent. Static_ID cannot be a child of Move_ID.

Move_ID

The ID of the handle to be moved.

Keywords

FIRST_CHILD

Set this keyword to make Move_ID the first child of Static_ID. Any existing children of Static_ID become later siblings of the new first child (i.e., the existing first child becomes the second child, the second child becomes the third child, etc.).

SIBLING

Set this keyword to make Move_ID the sibling handle immediately following Static_ID. Any siblings currently following Static_ID become later siblings of the new handle. Note that you cannot move a handle such that is becomes a sibling of a top-level handle.

Example

top = HANDLE_CREATE()	;Create top-level handle.

child1 = HANDLE_CREATE(top)	;Create first child of top.

child2 = HANDLE_CREATE(top)	;Create second child of top.

HANDLE_MOVE, top, child1	;Move the first child to be the last child of top.


HANDLE_VALUE

This routine is obsolete and should not be used in new IDL code.

The HANDLE_VALUE procedure returns or sets the value of an existing handle.

Calling Sequence

HANDLE_VALUE, ID, Value

Arguments

ID

A valid handle ID.

Value

When using HANDLE_VALUE to return an existing handle value (the default), Value is a named variable in which the value is returned.

When using HANDLE_VALUE to set a handle value, Value is the new value. Note that handle values can have any IDL data type and organization.

Keywords

NO_COPY

By default, HANDLE_VALUE works by making a second copy of the source data. Although this technique is fine for small data, it can have a significant memory cost when the data being copied is large.

If the NO_COPY keyword is set, HANDLE_VALUE works differently. Rather than copy the source data, it takes the data away from the source and attaches it directly to the destination. This feature can be used to move data very efficiently. However, it has the side effect of causing the source variable to become undefined. On a retrieve operation, the handle value becomes undefined. On a set operation, the variable passed as Value becomes undefined.

SET

Set this keyword to assign Value as the new handle value. The default is to retrieve the current handle value.

Examples

The following commands demonstrate the two different uses of HANDLE_VALUE:

HANDLE_VALUE, handle1, current	;Retrieve the value of handle1 into the variable current.

HANDLE_VALUE,handle1,[2,3],/SET	;Set the value of handle1 to a 2-element integer vector.


INP, INPW, OUTP, OUTPW

These routines are obsolete and should not be used in new IDL code.

Windows-Only Routines for Hardware Ports

You can address the hardware ports of your personal computer directly using the following routines. In each case, Port is specified using the hexadecimal address of the hardware port. For example, if serial port #1 of your PC is at address 3F8, you would use the following IDL commands to read that port:

paddr = '3F8'x	Set paddr to hexadecimal value.

data = INPW(paddr)	Read data.

Result = INP(Port, [D1 . . . DN])

This function returns either one byte (if only the port number is specified) or an array (the dimensions of which are specified by D1 . . . DN) read from the specified hardware port. Port is the hardware port number. For example,

result = INP(paddr)

would read a single byte, and

result = INP(paddr, 2,4)

would read a two-element by four-element array.

Result = INPW(Port, [D1 . . . DN])

This function returns either one 16-bit word, as an integer (if only the port number is specified), or an array (the dimensions of which are specified by D1 . . . DN) from the specified hardware port. Port is the hardware port number.

OUTP, Port, Value

This procedure writes either one byte or an array of bytes to the specified hardware port. Port is the hardware port number. Value is the byte value or array to be written.

OUTPW, Port, Value

This procedure writes either one 16-bit word or an array of words to the specified hardware port. Port is the hardware port number. Value is the integer value or array to be written.


PICKFILE

This routine is obsolete and should not be used in new IDL code.

The PICKFILE function has been renamed but retains the same functionality it had in previous releases. See "DIALOG_PICKFILE" in the IDL Reference Guide.


SIZE Executive Command

This command is obsolete and is not necessary in new IDL code.

.SIZE Code_Size, Data_Size

The .SIZE command resizes the memory area used to compile programs. The default code and data area sizes are 32,768 and 8,192 bytes, respectively. These sizes represent a compromise between an unlimited program space and conservation of memory. User procedures and functions are compiled in this large program area. After successful compilation, a new memory area of the required size is allocated to contain the newly compiled program unit.

Resizing the code and data areas erases the currently compiled main program and all main program variables. For example, to extend the code and data areas to 30,000 and 5,000 bytes, respectively, use the following statement:

.SIZE 30000 5000

Each user-defined procedure, function, and main program has its own code area that contains the compiled code and constants. Although the maximum size of these areas is set by the .SIZE command, there is virtually no limit to the number of program units. Procedures or functions that run out of code area space should be broken into multiple program units.

The data area contains information describing the user-defined variables and common blocks for each procedure, function, or main program. Note that the "data area" is not the space available for variable storage, but the space available for that program unit's symbol table.

Caution	Users are sometimes confused about the nature of the code and data areas. Note that there are separate code and data areas for each compiled function, routine, or main program. The HELP command can be used to see the current sizes of the code and data areas for the program unit in which the HELP function is called. For example, to see the sizes of the code and data areas for the main program level, enter:

HELP

at the IDL prompt.

Each compiled function and procedure has its own code and data areas. If the compiled routine does not use the full amount of code space allocated by the default code area size, the code area "shrinks" to just the size the routine needs. For example, enter and compile a simple procedure from the IDL prompt by entering:

.RUN

- PRO EXAMPLE

- PRINT, "Here are the code and data areas for this procedure:"

- HELP

- END

Call the EXAMPLE procedure from the command line to see the result:

EXAMPLE

The third line of output from the HELP procedure displays:

Code area used: 100.00% (100/100), Data area used: 2.02% (2/99)

Note that the code area for the EXAMPLE procedure is completely filled and that the total size of the code area is just 100 bytes.


TIFF_DUMP

This routine is obsolete and should not be used in new IDL code.

The TIFF_DUMP procedure dumps the Image File Directories of a TIFF file directly to the terminal screen. Each TIFF Image File Directory entry is printed. This procedure is used mainly for debugging.

Note that not all of the tags have names encoded. In particular, Facsimile, Document Storage and Retrieval, and most no-longer-recommended fields are not encoded.

This routine is written in the IDL language. Its source code can be found in the file tiff_dump.pro in the lib subdirectory of the IDL distribution.

Calling Sequence

TIFF_DUMP, File

Arguments

File

A scalar string containing the name of file to read.


TIFF_READ

This routine is obsolete and should not be used in new IDL code.

The TIFF_READ function has been renamed but retains the same functionality it had in previous releases. See "READ_TIFF" in the IDL Reference Guide.

The TIFF_READ function reads 8-bit or 24-bit images in TIFF format files (classes G, P, and R) and returns the image and color table vectors in the form of IDL variables. Only one image per file is read. TIFF_READ returns a byte array containing the image data. The dimensions of the result are the same as defined in the TIFF file (Columns, Rows).

For TIFF images that are RGB interleaved by pixel, the output dimensions are (3, Columns, Rows).

For TIFF images that are RGB interleaved by image, TIFF_READ returns the integer value zero, sets the variable defined by the PLANARCONFIG keyword to 2, and returns three separate images in the variables defined by the R, G, and B arguments.

This routine is written in the IDL language. Its source code can be found in the file tiff_read.pro in the lib subdirectory of the IDL distribution.

Calling Sequence

Result = TIFF_READ(File [, R, G, B])

Arguments

File

A scalar string containing the name of file to read.

R, G, B

Named variables that will contain the Red, Green, and Blue color vectors extracted from TIFF Class P, Palette Color images. For TIFF images that are RGB interleaved by image (when the variable specified by the PLANARCONFIG keyword is returned as 2) the R, G, and B variables each hold an image with the dimensions (Columns, Rows).

Keywords

ORDER

Set this keyword to a named variable that will contain the order parameter from the TIFF File. This parameter is returned as 0 for images written bottom to top, and 1 for images written top to bottom. If the Orientation parameter does not appear in the TIFF file, an order of 1 is returned.

PLANARCONFIG

Set this keyword to a named variable that will contain the interleave parameter from the TIFF file. This parameter is returned as 1 for TIFF files that are GrayScale, Palette, or RGB color interleaved by pixel, or as 2 for RGB color TIFF files interleaved by image.

Example

Read the file my.tif in the current directory into the variable image, and save the color tables in the variables, R, G, and B by entering:

image = TIFF_READ('my.tif', R, G, B)

To view the image, load the new color table and display the image by entering:

TVLCT, R, G, B

TV, image


TIFF_WRITE

This routine is obsolete and should not be used in new IDL code.

The TIFF_WRITE procedure has been renamed but retains the same functionality it had in previous releases. See "WRITE_TIFF" in the IDL Reference Guide.

The TIFF_WRITE procedure writes 8- or 24-bit images to a TIFF file. Files are written in a single strip, or in three strips when the PLANARCONFIG keyword is set to 2.

This routine is written in the IDL language. Its source code can be found in the file tiff_write.pro in the lib subdirectory of the IDL distribution.

Calling Sequence

TIFF_WRITE, File, Array [, Orientation]

Arguments

File

A scalar string containing the name of file to create.

Array

The image data to be written. If not already a byte array, it is made a byte array. Array may be either an (n, m) array for Grayscale or Palette classes, or a (3, n, m) array for RGB full color, interleaved by image. If the PLANARCONFIG keyword is set to 2 then the Array parameter is ignored (and may be omitted).

Orientation

This parameter should be 0 if the image is stored from bottom-to-top (the default). For images stored from top-to-bottom, this parameter should be 1.

Warning: not all TIFF readers are capable of reversing the scan line order. If in doubt, first convert the image to top-to-bottom order (use the REVERSE function), and set Orientation to 1.

Keywords

RED, GREEN, BLUE

If you are writing a Class P, Palette color image, set these keywords equal to the color table vectors, scaled from 0 to 255.

If you are writing an image that is RGB interleaved by image (i.e., if the PLANARCONFIG keyword is set to 2), set these keywords to the names of the variables containing the 3 color component image.

PLANARCONFIG

Set this keyword equal to 2 if writing an RGB image that is contained in three separate images (color planes). The three images must be stored in the variables specified by the RED, GREEN, and BLUE keywords. Otherwise, omit this parameter (or set it to 1).

XRESOL

The horizontal resolution, in pixels per inch. The default is 100.

YRESOL

The vertical resolution, in pixels per inch. The default is 100.

Examples

Four types of TIFF files can be written:

TIFF Class G, Grayscale.

The variable array contains the 8-bit image array. A value of 0 is black, 255 is white. The Red, Green, and Blue keywords are omitted.

TIFF_WRITE, 'a.tif', array

TIFF Class P, Palette Color.

The variable array contains the 8-bit image array. The keyword parameters RED, GREEN, and BLUE contain the color tables, which can have up to 256 elements, scaled from 0 to 255.

TIFF_WRITE, 'a.tif', array, RED = r, GREEN = g, BLUE = b

TIFF Class R, RGB Full Color, color interleaved by pixel.

The variable array contains the byte data, and is dimensioned (3, cols, rows).

TIFF_WRITE, 'a.tif', array

TIFF Class R, RGB Full Color, color interleaved by image.

Input is three separate images, provided in the keyword parameters RED, GREEN, and BLUE. The input argument Array is ignored. The keyword PLANARCONFIG must be set to 2 in this case.

TIFF_WRITE, 'a.tif', RED = r, GREEN = g, BLUE = b, PLAN = 2


WIDED

This routine is obsolete and should not be used in new IDL code.

The WIDED procedure invokes IDL's graphical user interface designer, known as the Widget Builder. Complete documentation for the Widget Builder can be found in Chapter 22 of the <Italics>IDL User's Guide.

Calling Sequence

WIDED


WIDGET_MESSAGE

This routine is obsolete and should not be used in new IDL code.

The WIDGET_MESSAGE function has been renamed but retains the same functionality it had in previous releases. See "DIALOG_MESSAGE" in the IDL Reference Guide.


Widget Builder
1	Widget Builder

Chapter Overview

The Widget Builder is an IDL widget application that allows you to rapidly prototype graphical user interfaces. Interfaces in progress can be saved and edited later. Once an interface is complete, the Widget Builder can generate the IDL code that creates that interface along with a basic widget event handler.

While even non-programmers can use the Widget Builder to explore user interface design, a knowledge of IDL widget programming is required to turn Widget Builder output into usable widget applications. For more information on learning to program with IDL widgets, see Building IDL Applications.


Starting the Widget Builder

To start the Widget Builder, enter the following command at the IDL prompt:

WIDED

The Widget Builder is a complicated application and can take some time to compile. Once the code has been compiled, two windows appear: the Widget Builder main window (titled "Widget Builder") and a small window titled "idl". The small window is a new widget interface that consists of only a base. This preview window actually shows an example of the interface that you are currently building. Other widgets can be added to the base using the tools provided in the main Widget Builder window.

Getting Started with the Widget Builder

If you are running the Widget Builder for the first time, you should go through the tutorial that begins with the "Widget Builder Tutorial". This tutorial shows how to build and edit a simple widget interface.


Widget Builder Menu Hierarchy

The Widget Builder main window has a group of pulldown menus along its top. These menus are described below.

The following hypertext links can be used to jump to the menu items described in this section:

The File Menu

The File menu controls input to and output from the Widget Builder. This menu allows you to save and restore widget interfaces as well as generate IDL program files.

New

Select this option to start a new widget interface. If an unsaved widget interface is currently open, you are asked if you want to save it before starting a new one.

Open

Select this option to open previously-saved widget interfaces. The default extension for these files is .wid.

Save

Select this option to save the current widget interface in the Widget Builder's .wid format. These files can be restored at a later time with the "Open" option.

Create .PRO

Select this option to reveal a cascading menu of options for turning the current widget interface into IDL code. The Widget Builder writes a single file with three sections: a documentation header template, a basic event handler routine, and a widget creation routine.

Note that this option is usually used only when your prototype widget interface is complete. Then the programmer makes modifications to the resulting .pro file to create a usable widget application, making no further use of the Widget Builder. However, by using the "Normal" option, you can allow the Widget Builder to make changes to the widget creation section of a previously-saved .pro file (while retaining your edits to the widget event handler or documentation sections of the file).

Caution: Creating a .pro file is not the same as saving a .wid file (by selecting "Save" from the File menu). A .wid file can be read back into the Widget Builder, but a .pro file cannot. Creating a .pro file from a preview does not save your work. If you quit without saving the preview as a .wid, you will not be able to read your work back into the Widget Builder.

Select "Normal" to write any changes to the widget creation routine of an existing .pro file without changing the event handler and header.

Select "Rewrite Everything" to write a new .pro file or rewrite all parts of an existing .pro file. Any changes made previously are lost.

Select "Without Header" to write a .pro file without a documentation header. Otherwise, this option behaves exactly as the "Normal" option.

Show Object Tree

Select this option to display a window that shows the a textual representation of the current widget interface. The widget tree begins with the top-level base (called MAIN). Any widgets that belong to MAIN are shown indented. Each new sub-base is shown as a new indent level. Any titles or names that you have assigned to the widgets are shown in parentheses.

Quit

Select this option to exit the Widget Builder and return control to the IDL command line. If the current widget interface has unsaved changes, you are prompted before exiting.

The Edit Menu

The options in this pulldown menu allow you to edit parts of the current widget interface.

Cut

Select this option to remove a previously-created widget from the current interface. The "Cut Widget" dialog  appears. Click on the name of the widget to be cut, then click the "Cut Child" button to remove that widget from the current widget interface. Once cut, the widget is placed on the Widget Builder's "clipboard". The clipboard can contain up to 10 widget subtrees at one time.

If the widget you want to cut resides in a sub-base of the main base, click on the name of the sub-base, then click "Show Children". The Cut Widget dialog changes to show the children of that sub-base. To return to a display of widgets in the previous base, click "Show Parent Base".

Once you have cut a widget, the "Paste Widget" dialog can be displayed by clicking "Show Paste Dialog".

Click "Done" to dismiss the Cut Widget dialog.

Note that you must click "Rebuild" on the Widget Builder main window to see your changes to the current widget preview.

Copy

Select this option to copy a previously-created widget to the Widget Builder clipboard. The "Copy Widget" dialog appears. This dialog has the same functions as the "Cut Widget" dialog described above, except that copied widgets are not removed from the current widget interface.

Paste

Select this option to paste widgets from the Widget Builder clipboard to new positions in the current widget interface. The "Paste Widgets" dialog appears.

This dialog features two lists. The list on the left (titled "Clipboard") shows the widgets that have been cut or copied to the clipboard. The list on the right (titled "Children of...") represents the current widget tree. To paste a widget from the clipboard to a new position in the widget tree, click on the name of the widget to be pasted in the "Clipboard" list. Then click on a widget in the "Children of..." list. Click the "Paste After" button to paste the selected "Clipboard" widget into the widget tree in the position after the selected "Children of..." widget.

If the widget you want to paste after resides in a sub-base of the main base, click on the name of the sub-base in the "Children of..." list, then click "Show Children". The "Children of..." list changes to show the children of that sub-base. To return to a display of widgets in the previous base, click "Show Parent Base".

Click "Delete Widget" to delete the currently selected "Clipboard" widget from the clipboard. Click "Done" to dismiss the Paste Widgets dialog.

Note that you must click "Rebuild" on the Widget Builder main window to see your changes to the current widget preview.

Edit Child

Select this option to edit the attributes of a previously-created widget. The "Edit Widget" dialog appears. To edit a widget, click on its name in the list, then click on "Edit Child". The appropriate widget editing menu will appear. These menus are the same as the menus used to create widgets. See "The Add Menu" on page 30.

If the widget you want to edit resides in a sub-base of the main base, click on the name of the sub-base, then click "Show Children". The Edit Widget dialog changes to show the children of that sub-base. To return to a display of widgets in the previous base, click "Show Parent Base".

Click "Done" to dismiss the Edit Widget dialog.

The Add Menu

The options on this menu are used to add widgets to the current widget interface. Note that many of the options selectable from the Add menu can also be selected through the Widget Builder "button bar"—a row of graphic-labeled buttons below the main menu. Individual menu items are described below.

Newly-created widgets are added to the end of the current widget tree. Therefore, new widgets fill row bases in left-to-right order and column bases in top-to-bottom order. Note that after they are created, widgets can be cut, copied, and pasted to arbitrary positions in the widget tree using the options in the Edit menu.

Common Features of the Add Widget Dialogs

The Add widget dialogs are graphical interfaces to IDL's widget-creation routines (e.g., WIDGET_BASE, WIDGET_BUTTON, etc.). Since these creation routines have many common keywords, the Add widget dialogs have many common controls. These features are described below.

•	Done and Cancel: All of the Add widget dialogs have "Done" and "Cancel" buttons. Click "Done" to dismiss the dialog and add the widget to the widget tree. Note that you must click "Rebuild" to see the changes reflected in the widget preview. Click "Cancel" to dismiss the dialog without adding the widget to the widget tree.

•	Font: Any widgets that have text elements can also be assigned fonts other than the default. Note, however, that different systems (and different types of platforms) may not have access to the same fonts. If you are building interfaces that will be used on many different platforms, it is best not to specify special fonts (if a specified font is not available, the system uses the default font). To specify a special font, enter a string in the format accepted by the FONT keyword to the DEVICE routine.

On Windows and Macintosh systems, this string has the following format:

font*modifier1*modifier2*...modifiern

where font is the full name of any display font installed in your system. For example, to set the text for a widget to 24 point Times italic, you would enter the following string in the "Font:" field:

times*24*italic

On X Windows systems, this string can be the name of any font that is displayed when the Unix xlsfonts command is invoked. X Windows Widget Builder users can also click on the "XFont" button next to the "Font:" field to invoke IDL's XFONT routine that shows the available fonts.

•	Name: All widgets created with the Add widget dialogs can be assigned a name. This name is not the title string for the widget. Instead, this is a descriptor that shows up in Widget Editor dialogs (such as the Cut, Edit, Paste, and Show Object Tree dialogs) next to the widget description (e.g., BUTTON4). In the .pro files generated by the Widget Builder, the contents of the name field become the text that is printed when an event is received for this widget. If you use the Name field, take care not to give different widgets identical names.

•	Frame Size: This field accepts an integer value that specifies the width of a frame (or border) to be put around the widget. Note that this is simply a hint to the window manager. Many systems will not display frames of different thicknesses—all you can specify is whether or not the widget has a frame. If this field is empty, the widget has no frame around it.

•	User Value: All IDL widgets can contain a user-specified value of any data type and organization. This value is not used by the widget in any way, but exists entirely for the convenience of the IDL programmer. You can enter any value in this field. When a .pro file is generated, this value becomes the initial user value for the widget (specified with the UVALUE keyword to the appropriate widget creation function). Note that this field has no function inside the Widget Builder application. If you use the User Value field, take care not to give different widgets identical User Values, or the event handler routine (in the generated .pro file) will not be able to identify the widget that caused the event.

•	X Size and Y Size: The width (X Size) and height (Y Size) of the widget (in pixels for most widgets, in characters for text widgets). Note that it is best to let most widgets size themselves.

•	X Offset and Y Offset: The horizontal (X Offset) and vertical (Y Offset) offset of the widget (in pixels) relative to its parent. Note that it is best to let most widgets position themselves.

Hide/Show Tool Bar

Select this options to toggle display of the button bar on and off.

Base

Select this option to create a new base. The Base dialog appears. This dialog has the same controls as the Widget Builder main window, except that it only has an "Add" menu. This menu is used to add new widgets to the new sub-base.

For descriptions of the other controls on this dialog, see "Common Features of the Add Widget Dialogs" on page 30. Note that the Add Base Dialog does not have a "Cancel" button. To remove an accidentally-added base, use the "Cut" option from the Edit menu. The Base dialog is an interface to IDL's WIDGET_BASE function.

Button

Select this option to create a new button with a text label. The Button dialog appears. Features unique to this dialog are described below.

•	Button Text: This field accepts a string to be used as the button label.

For descriptions of the other controls on this dialog, see "Common Features of the Add Widget Dialogs" on page 30. The Button dialog is an interface to IDL's WIDGET_BUTTON function.

Bitmap Button

Select this option to create a new button with a bitmap label. The Bitmap Button dialog appears This dialog is used to create black and white bitmap labels for the button. Controls unique to this dialog are described below.

•	Gridded Draw Widget: Click inside this draw widget to draw the bitmap label. Each square represents a pixel in the final bitmap. Clicking on a white square turns it black. Clicking on a black square turns it white. Hold the mouse button down to draw continuous lines. On X Windows systems, an actual-size bitmap button appears next to the draw widget.

•	Bitmap Size: Click on one of these buttons to select the size of the bitmap button. There are three choices: 16, 32, and 64 pixels square.

•	Invert: Click this button to turn all white pixels black and vice-versa.

For descriptions of the other controls on this dialog, see "Common Features of the Add Widget Dialogs" on page 30. The Bitmap Button dialog is an interface to IDL's WIDGET_BUTTON function.

Button Group

Select this option to create a "button group" compound widget. Button groups can be used to create a number of buttons that share the same sub-base. They can also be used to create menus of exclusive and non-exclusive "radio" buttons. The BGROUP dialog appears. Controls unique to this dialog are described below.

•	BGROUP Widget Value: This multi-line text widget at the top of the dialog is used to enter the labels for the buttons. Each line is a separate label. Take care not to enter a "Return" after the last button label, or you will end up with an extra button with a blank label.

•	Base Type, Child Spacing, Padding: Select the type of base to be used to hold the buttons. Buttons can be organized in a row, column, or bulletin-board base. You can also select spacing between children and X and Y padding.

•	Base Type: This menu allows you to select the type of buttons in the button group. To create the default style buttons (like the "Done" and "Cancel" buttons on this dialog), select "Normal Base". To create an exclusive menu (i.e., a menu of radio buttons wherein only one button can be selected at a time), select "Exclusive". To create a non-exclusive menu (i.e., a menu of radio buttons wherein any number of buttons can be selected), select "Non-Exclusive".

•	Top Title, Left Title: Button groups can have label titles at the very top and/or on the left side of the group.

•	X Scroll Size, Y Scroll Size: Entering values in these fields makes the base that holds the buttons a scrolling base. The values represent the size of the scrollable region, in pixels.

For descriptions of the other controls on this dialog, see "Common Features of the Add Widget Dialogs" on page 30. The Button Group dialog is an interface to IDL's CW_BGROUP function.

Draw

Select this option to create a draw widget. The Draw dialog appears. Controls unique to this dialog are described below.

•	X Size, Y Size: The size of the draw widget in pixels.

•	Accept Button Events: Select this button to create a draw widget that returns button presses inside the drawing region.

•	Accept Motion Events: Select this button to create a draw widget that returns motion events inside the drawing region.

•	Backing Store: This menu provides an interface to the RETAIN keyword. Click "None" to create a draw widget without backing store. Click "Server" to request backing store from the window manager. Click "IDL" to have IDL manage backing store for the widget.

•	X Scroll Size, Y Scroll Size: Entering values in these fields creates a scrolling draw widget. The values represent the size of the scrollable region, in pixels.

For descriptions of the other controls on this dialog, see "Common Features of the Add Widget Dialogs" on page 30. The Draw dialog is an interface to IDL's WIDGET_DRAW function.

Field w/Label

Select this option to create an "input field" compound widget. The FIELD dialog appears. Input fields combine a text widget with a label. Controls unique to this dialog are described below:

•	FIELD Widget Value: The initial contents of the text widget.

•	Title: The text string for the label part of the input field.

•	Field Type: Input fields are "smart" in that they automatically convert input to the text widget to the appropriate type. Select from "String", "Float", "Int", and "Long" types.

•	Field Events: Use this menu to select the type of events the input field will return. By default, fields only return their value on a call to WIDGET_CONTROL, /GET_VALUE. However, you can modify this behavior by clicking "Event on <CR>" (return an event whenever Return is pressed in the text field) or "All Events" (similar to "All Events" for text widgets).

•	Field text Fixed: Click this button to make the text widget non-editable.

•	Field is Vertical: Click this button to put the label above the text widget. By default, the label is to the left of the text widget.

For descriptions of the other controls on this dialog, see "Common Features of the Add Widget Dialogs" on page 30. The FIELD dialog is an interface to the CW_FIELD function.

Label

Select this option to create a new label widget. The LABEL Dialog appears. Controls unique to this dialog are described below.

•	Label Text: Enter the text string to be used as a label in this field.

For descriptions of the other controls on this dialog, see "Common Features of the Add Widget Dialogs" on page 30. The LABEL dialog is an interface to the WIDGET_LABEL function.

List

Select this option to add a new list widget. The LIST Dialog appears. Controls unique to this dialog are described below.

•	List Widget Value: This multi-line text widget at the top of the dialog is used to enter the list items. Each line is a separate element in the list. Take care not to enter a "Return" after the last list item, or you will end up with an extra list element that is blank.

•	Y Size: The number of list items shown at one time.

For descriptions of the other controls on this dialog, see "Common Features of the Add Widget Dialogs" on page 30. The LIST Dialog is an interface to IDL's WIDGET_LIST function.

Pull Down Menu

Select this option to create a new pulldown menu. The PDMENU Dialog appears. Controls unique to this dialog are described below.

•	List of Items: The list in the upper-left corner of the dialog shows the items in the pulldown menu. When creating a new pulldown menu, this list shows the top-level menu buttons. To create the sub-menu items (the elements that are shown when the menu is pulled down), click on an item in this list and click "Edit as a SubMenu". Another PDMENU dialog is displayed. Items in the list that have sub-menu items have an asterisk (*) to the left of their names.

•	Button Value: To add a new pulldown menu item, enter the text for the pulldown item and click on "Add" or press Return.

•	Edit as a Submenu: Use this button to create new submenus in your pulldown menu. When a new pulldown menu is created, the PDMENU dialog allows you to create the top-level menu buttons. To create the sub-menu items (the options that are shown when the menu is pulled down), click on an item in the list, and click "Edit as a SubMenu". A new PDMENU dialog appears. Here you can enter the items to be shown in the pulldown list. If you click on one of these items and click "Edit as a SubMenu", yet another PDMENU dialog appears. Elements entered in this dialog would become cascading menu options of the selected pulldown menu option.

•	Delete: To delete an item from the list, click on the item name, then click the "Delete" button.

•	Add: Click on this button to put the current entry in the "Button Value" field into the list of menu items.

For descriptions of the other controls on this dialog, see "Common Features of the Add Widget Dialogs" on page 30. The PDMENU Dialog is an interface to the CW_PDMENU function. .

Slider

Select this option to create a new slider widget. The SLIDER Dialog appears. Unique controls for this dialog are described below:

•	Slider Title: This field accepts a string to be used as the slider's title.

•	Minimum: An integer minimum value for the slider. The default is 0.

•	Initial: The initial value for the slider to be set to. The default is the minimum value.

•	Maximum: An integer maximum value for the slider.

•	Generate Drag Events: Click this button to make the slider return widget events while it is being repositioned.

•	Vertical Slider: Click this button to make the slider vertical. By default sliders are horizontal.

•	Suppress display of current value: Click this button to create a slider without a number field that reports the current value of the slider.

For descriptions of the other controls on this dialog, see "Common Features of the Add Widget Dialogs" on page 30. The SLIDER dialog is an interface to IDL's WIDGET_SLIDER function.

Floating Pt. Slider

Select this option to create a floating-point slider widget. The FSLID dialog appears. Controls unique to this dialog are described below.

•	Slider Title: This field accepts a string to be used as the slider's title.

•	Minimum: A floating-point minimum value for the slider. The default is 0.

•	Initial: The initial value for the slider to be set to. The default is the minimum value.

•	Maximum: A floating-point maximum value for the slider.

•	Generate Drag Events: Click this button to make the slider return widget events while it is being repositioned.

•	Vertical Slider: Click this button to make the slider vertical. By default sliders are horizontal.

•	Suppress display of current value: Click this button to create a slider without a number field that reports the current value of the slider.

For descriptions of the other controls on this dialog, see "Common Features of the Add Widget Dialogs" on page 30. The FSLID dialog is an interface to the CW_FSLIDER function.

Text

Select this option to create a new text widget. The TEXT Dialog appears. Controls unique to this dialog are described below.

•	TEXT Widget Value: This multi-line text widget can be used to enter the initial text to be shown in the text widget.

•	Text Editable: Select this button to create an editable text widget. The EDITABLE keyword is set for this widget when a .pro file is generated.

•	Process All Events: Selecting this button causes the text widget to return a full set of text events. The ALL_EVENTS keyword is set for this widget when a .pro file is generated. Note that the ALL_EVENTS and EDITABLE keywords interact in complex ways, as described in the documentation for WIDGET_TEXT in the IDL Reference Guide.

•	No Auto-Newline: Select this button to suppress the automatic addition of newline characters when setting the value of a multi-line text widget. The NO_NEWLINE keyword is set for this widget when a .pro file is generated.

•	Add Scrollbars: Select this button to make the text widget scrollable.

For descriptions of the other controls on this dialog, see "Common Features of the Add Widget Dialogs" on page 30. The TEXT dialog is an interface to IDL's WIDGET_TEXT function.

Dependent Base

Select this option to create a new, free-floating base (i.e., the base has its own frame). Caution: Dependent bases cannot be cut or copied from within the Widget Builder—be sure you want to add a dependent base before selecting this option. The Dependent Base Dialog appears. This dialog is identical to the Add Base dialog except that it creates and modifies "dependent" bases.

The Rebuild Button

Click on the "Rebuild" button to redraw the current widget preview, reflecting any changes made since the last rebuild. This is the only way to see the effect of your changes to the current widget preview. The Widget Builder application never rebuilds the interface automatically.

When "Rebuild" is pressed, any changes made since the last time "Rebuild" was pressed are made to the preview. Note also that any open Add or Edit dialogs also influence the look of the rebuilt preview. Settings for any open Add or Edit dialogs are read by the Widget Builder and added to the preview.

The Help Button

Click this button to display information about the Widget Builder.


Widget Builder Tutorial

This brief tutorial shows how to use the Widget Builder to create a simple widget interface.

Start the Widget Builder

If you have not already done so, start the Widget Builder by entering the following command at the IDL prompt:

WIDED

After compiling, the Widget Builder main window and preview window appear.

The Main Window and Widget Preview

When first starting to use the Widget Builder, many users wonder what that little empty window is that pops up with the Widget Builder main window. That is the preview of your current widget tree. It shows the current state of the widgets as you add and/or change them. The preview is only updated when you click on the "Rebuild" button in the Widget Builder main window. This button is probably the most used button in the entire interface.

When your first start the Widget Builder, or after you have started a new widget interface by selecting "New" from the File menu, the entire preview consists of only an empty top level base widget. This little window is the widget that would be created if you entered the command:

B=WIDGET_BASE()& WIDGET_CONTROL, B, /REALIZE

at the IDL prompt.

The Widget Builder main window is used to select, configure, and edit widget elements. It controls the operation of the Widget Builder itself, and also controls the characteristics of the top-level widget base of the widget interface that you are building. Unlike the other Widget Builder dialogs, it cannot be dismissed without quitting the Widget Builder application.

A Simple Widget Interface

In the steps that follow, we'll create a simple widget interface as shown below.

Create a Title for the Top-Level Base

First, set the title for our new widget interface to "My Widget" by typing that into the "Title:" field in the Widget Builder main window.

To see the change we have just made, we must click on the "Rebuild" button.

Note that since we haven't put anything into the top-level base, part of the title will not be visible until we resize the preview window.

Add a New Sub-Base and Pulldown Menu

Now we need to add some children to the main base. First, add a new sub-base widget by selecting "Base" from the Add menu on the main window. A BASE dialog appears. Ignore this dialog for now and add a pulldown menu by selecting "Pull Down Menu" from the Add menu on the main window. A PDMENU dialog appears.

The Add/Edit Dialogs

A new dialog appears for each element you select from the Add menu. The windows are titled to give you an indication of which element you are working on at any given time. For example, when you select "Pull Down Menu", a new control panel with a title something like "PDMENU614 (Child of Top Base)" appears. This title tells you what type of widget element is being created (a PD menu), and which widget is the parent of this widget. The number, (614 in this example) is a unique identifier for the widget element and is used to distinguish between similar elements. You can change the name of any object except the Top Base by entering a string in the "Name:" field of its dialog. As you fill in information about a widget, the Widget Builder refers to that widget in a clearer way based on that information—titles, values, user values, and names, are used in preference to automatically generated numbers.

Configure the Pulldown Menu

Now let's configure the pulldown menu. Select the control panel titled "PDMENUxxx (Child of Top Base)". To add an entry to the menu, simply type the entry in the "Button Value:" field and press Return. Create three buttons in the top-level of the pulldown menu by typing:

One	Now press Return.

Tow	Press Return. Yes, I'm sure you noticed its misspelled, but play along for now!

Three	Press Return again.

Rebuild your preview (by clicking "Rebuild" on the main window) if you like. The PDMENU dialog should now look something like this:

Correct the Error

As you probably noticed earlier, the second button has a misspelled label. To correct it, click on the "Tow" entry in the list, then click the "Delete" button. Now add the correct version clicking on the "One" entry in the list, typing "Two" into the "Button Value:" field, and pressing Return or clicking on the "Add" button. The "Two" entry is added after "One". A menu entry is always added to the list immediately after the currently selected entry or at the end of the list if there is no current selection. Select "<Top of List>" to add an entry as the first item in the menu.

Add Another Level to the Pulldown Menu

The pulldown menu items we just added represent the top-level buttons of the pulldown menu. Currently, these buttons do not reveal pulldown menu lists because we haven't specified any items for them.

Let's add some pulldown items to the "Two" menu button. Select "Two" in the list and click the "Edit as a Submenu" button. A dialog titled "Submenu Two" appears. This dialog looks very similar to the PDMENU dialog that popped up when you first added a pulldown menu widget.

Fill in the submenu with the entries "Four", "Five", and "Six" by entering those names in the "Button Value:" field of this new dialog just like we did for the first three buttons in the previous dialog. Click on the "Done" button for both the submenu dialog ("Submenu Two") and the pulldown menu dialog ("PDMENUx (Child of Top Base)").

Click the "Rebuild" button to preview our progress. You can see the submenu for the "Two" button by clicking on that button in the preview.

Configuring the Sub-Base

Now let's work on the sub-base we created earlier. Find the sub-base dialog. It should have a title like "BASE2 (Child of Top Base)". If you can't find the dialog easily (or if you accidentally dismissed the dialog earlier) you can instead use the "Edit Child" option in the Edit menu of the Widget Builder main window. Select the base in the list that appears and click on the "Edit Child" button. The dialog will be re-created if it had been destroyed or will pop to the top of the display if it is hidden beneath other windows.

Note that the BASE dialog is very similar to the Widget Builder main window. Don't get them confused!

Add a Draw Widget to the Sub-Base

Go to the "Add" menu on the base dialog and select "Draw". A DRAW dialog appears. In this dialog, set the "X Size" field to 400, and the "Y Size" field to 200. Make IDL handle the backing store for the draw window by clicking on the "IDL" choice in the "Backing Store:" menu. Click on the "Done" button when you are finished.

Add a Label to the Sub-Base

Now add a label widget to the sub-base by choosing the "Label" option from the sub-base dialog's "Add" menu. A label dialog appears. Set the "Label Text:" field to "Some *Really* Great Data" and press the "Done" button. Now click "Rebuild" in the main window to update the preview. Your preview should look like this:

Finishing Touches

This is close to our goal, but not quite! In the finished interface, the widgets are arranged in columns, not rows. To make this change, click on the "Column" button in the "Base Type" sections of both the sub-base dialog and the Widget Builder main window. Click on "Rebuild".

Reposition the Label

Now things are close to being right except that the label should be above the draw widget:

We'll need to cut the label and paste it into the proper position. Select "Cut" from the main window's Edit menu. The Cut dialog appears. You may have noticed that the label widget and draw widget seem to be missing from this list. They are not shown in this list because they are children of the sub-base that we created.

To see the children of the sub-base, click on the name of the sub-base in the Cut dialog's list. Now click on the Show Children button. The Cut dialog changes to show the children—the draw and label widgets. Click on the label in the new list, then click on "Cut Child". Click on "Done" to dismiss the Cut dialog. Though it hasn't been reflected in the preview yet, the label widget has been removed from the widget tree and placed on the Widget Builder's clipboard.

Select "Paste" from the Widget Builder's Edit menu. The Paste dialog appears.

We want to paste the label back into the sub-base, but before the draw widget. To accomplish this, click on the name of the base in the list on the right. Now click on "Show Children". The list changes to show the contents of the sub-base (currently, just the draw widget). Note that the highlight in the new list is on "<Top of List>". Now click "Paste After" and the label is pasted into the list after "<Top of List>" and before the draw widget.

The Final Rebuild

Click on "Rebuild" one last time to ensure that everything is correct.

Save the Current Widget Tree

Now we save our work. Choose "Save" from the main window's File menu. A file saving dialog appears. Choose a file in which to save your widget tree. For example, you might want to call it great.wid. The widget tree is saved in a special format that can be read by the Widget Builder (by selecting "Open" from the file menu) at a later time.

Create an IDL Program File

You may also want the Widget Builder to write the IDL code it would take to create the widget tree. This code could then be modified to create a fully-functional application. Select "Create .PRO" from the Widget Builder's File menu. A cascading list of options appears—select "Normal". A file selection dialog appears. Create a file named great.pro. Quit the Widget Builder (by selecting "Quit" from the File menu) and try running great.pro by entering great at the IDL prompt. A running copy of the widget tree we just built should appear. Note that manipulating the widgets causes messages to be printed in the IDL log window. You can examine the contents of great.pro with a text editor to see how its event handler is turning widget events into actions in IDL.


Remote Procedure Calls
2	Remote Procedure Calls

Chapter Overview

Remote Procedure Calls (RPCs) allow one process (the client process) to have another process (the server process) execute a procedure call just as if the caller process had executed the procedure call in its own address space. Since the client and server are separate processes, they can reside on the same machine or on different machines. RPC libraries allow the creation of network applications without having to worry about underlying networking mechanisms.

IDL supports RPCs so that other applications can communicate with IDL. A library of C language routines is included to handle communication between client programs and the IDL server. Note that remote procedure calls are supported only on Unix platforms.

The current implementation allows IDL to be run as an RPC server and your own program to be run as a client. IDL commands can be sent from your application to the IDL server, where they are executed. Variable structures can be defined in the client program and then sent to the IDL server for creation as IDL variables. Similarly, the values of variables in the IDL server session can be retrieved into the client process.


Topics in Remote Procedure Calls Chapter
2

This chapter describes IDL's remote procedure call capabilities.

Topics Covered:

xxxxxx

Jump forward to 28

Jump backward to x


Using IDL as an RPC Server

The IDL RPC Directory

All of the files related to using IDL's RPC capabilities are found in the rpc subdirectory of the external subdirectory of the main IDL directory. The main IDL directory is referred to here as idldir.

Running IDL in Server Mode

To use IDL as an RPC server, run IDL in server mode by using the -server command line option. This option can be invoked one of two ways:

idl -server process_id

or

idl -server=server_number process_id

where server_number is the hexadecimal server ID number (between 0x20000000 and 0x3FFFFFFF) for IDL to use. For example, to run IDL with the server ID number 0x20500000, use the command:

idl -server=20500000

If a server ID number is not supplied, IDL uses the default, IDL_DEFAULT_ID, defined in the file idldir/external/rpc/rpc_idl.h. This value is originally set to 0x2010CAFE.

The process_id argument is an optional argument that specifies the process ID of a Unix process that should be contacted when IDL has finished running in interactive mode. If the IDL rpc server is placed in interactive mode and a process ID has been supplied on the command line, IDL sends the Unix signal SIGUSR1 to the specified process. This signal allows the client program to know when it can continue to communicate with the rpc server.

Creating the IDL RPC Library

The machine that runs the client program must have its own version of the IDL RPC library. The make file for this library is contained in the directory idldir/external/rpc. If the machine that runs the client program is not licensed to run IDL, simply copy the contents of the IDL rpc directory to an appropriate location on the client machine.

To build the IDL RPC library, copy the IDL rpc directory to a new directory, change to that directory, and enter the make command:

cp -R idldir/external/rpc newrpcdir
cd newrpcdir
make

The created library is contained in the file newrpcdir/rpcidl.a. The functions contained in the library are described in "The IDL RPC Library" on page 2-57.

Linking your Client Program

Your client program must include the file idldir/external/rpc/rpc_idl.h.

You must also link the application that communicates with IDL with the IDL RPC library. For example, to compile and link a program with the IDL RPC library, you might enter:

cc -c rpcclient.c
cc -o rpcclient.o idldir/external/rpc/rpcidl.a

where rpcclient.c is the name of your program. Note that your actual command lines and flag settings may be different than the ones shown above, depending upon your C compiler. The Makefile contains details on modifications for various systems.


The IDL RPC Library

The IDL RPC library contains several C language interface functions that facilitate communication between your application and IDL. There are functions to register and unregister clients, set timeouts, get and set the value of IDL variables, send commands to the IDL server, and cause the server to exit. These functions are described below.

free_idl_variable

Calling Sequence

void free_idl_var(varinfo_t* var);

Description

This function frees all dynamic memory associated with the given variable. Attempts to free a static variable are silently ignored. (See "Notes on Variable Creation and Memory Management" on page 2-66.)

Parameters

var

The address of the varinfo_t structure that contains the information about the variable to be freed.

Return Value

None.

get_idl_variable

Calling Sequence

int get_idl_variable(CLIENT* client, char* name, varinfo_t* var,
     int typecode)

Description

Call this function to retrieve the value of an IDL variable in the IDL session referred to by client. Any scalar or array variable type can be retrieved. Variables can be retrieved only from the main program level.

Note that it is not possible to get the value of an IDL structure. To retrieve values from an IDL structure, "decompose" the structure into regular variables in IDL, then use this function to get the values of those individual variables.

It is not possible to get the value of IDL system variables directly. To retrieve the value of an IDL system variable, first copy it to a regular IDL variable. The value of the regular variable can then be retrieved with get_idl_variable. For example:

varinfo_t pt;	/* Declare variable pt */
send_idl_command(client, "X = !P.T");
get_idl_variable(client, "X", &pt, 0);

Parameters

client

A pointer to the CLIENT structure that corresponds to the desired IDL session.

name

A null terminated string that contains the name of the IDL variable to be retrieved. Only the first MAXIDLEN characters of this string are used. MAXIDLEN is defined in the file idldir/external/rpc/rpc_idl.h.

var

The address of a varinfo_t structure in which to store the returned variable information. Upon return, the Name field of the var structure contains the name of the variable as found in IDL. If the name supplied is an illegal IDL variable name, the Name field is set to <ILLEGAL_NAME>. If the variable is a structure or associated variable, the Name field is set to <BAD-VAR-TYPE>.

typecode

If you want IDL to typecast a variable (i.e., guarantee the value to be of a particular type) before it is transported, set typecode to one of the following values (defined in the file export.h):

IDL_TYP_BYTE, IDL_TYP_INT, IDL_TYP_LONG, IDL_TYP_FLOAT, IDL_TYP_DOUBLE, IDL_TYP_STRING, IDL_TYP_COMPLEX, IDL_TYP_DCOMPLEX

For example, the command:

get_idl_variable(client, "x", &xv, IDL_TYP_LONG)

guarantees that the value in x is returned as a 32-bit integer.

If typecode is 0, the variable is transferred with whatever data type it has in the server. Typecasting only affects the variables in the client - the server side is not affected.

Return Value

This function returns a status value that denotes the success or failure of this function as described below.

-1	Failure: bad arguments supplied (e.g., name or var is NULL).

 0	RPC mechanism failed (an error message may also be printed).

 1	Success

-2	Illegal variable name (e.g., "213xyz", "#a", "!DEVICE")

-3	Variable not transportable (e.g., the variable is a structure or associated
variable)

idl_server_interactive

Calling Sequence

int idl_server_interactive(CLIENT*client)

Description

Call this function to cause the IDL server to become an interactive IDL session. It is likely that this command will time out. Some alternative mechanism for determining when the server is finished should be implemented. See the example server.c in the idldir/examples/rpc directory.

Parameters

client

A CLIENT structure that corresponds to the desired IDL session.

Return Value

This function returns TRUE if the interactive IDL session did not time out. FALSE is returned if the session times out or otherwise fails.

kill_server

Calling Sequence

int kill_server(CLIENT*client)

Description

Call this function to kill the IDL RPC server.

Parameters

client

The pointer to a CLIENT structure registered with the server to be killed.

Return Value

This function returns TRUE if the server was successfully killed. FALSE is returned otherwise.

register_idl_client

Calling Sequence

CLIENT* register_idl_client(long server_id, char* hostname,
     struct timeval* timeout)

Description

Call this function to register your program as a client of an IDL server. Note that a program can be the client of a number of different servers at the same time and a single server can have multiple clients.

Parameters

server_id

The ID number of the IDL server that the program is to be registered with. If this value is 0, the default server ID (0x2010CAFE) is used.

hostname

The name of the machine where the IDL server is running. If this value is NULL or "", the default, localhost, is used.

timeout

A pointer to the timeout value for all communication with IDL servers. If this value is NULL or 0, the default timeout, 60 seconds, is used.

Return Value

A pointer to the new CLIENT structure is returned. This function returns NULL if it is unsuccessful.

send_idl_command

Calling Sequence

int send_idl_command(CLIENT* client, char* command);

Description

Call this function to send an IDL command to the IDL server referred to by client. The command is executed just as if it had been entered from the IDL command line.

This function cannot be used to send multi-line commands. If the first part of a multi-line command is sent, for example:

send_idl_command(client, "FOR I=1,5 DO $");

IDL spawns an interactive session and may hang. In any case, subsequent commands are not executed.

Parameters

client

A pointer to the CLIENT structure that corresponds to the desired IDL session.

command

A null-terminated string with no more than MAX_STRING_LEN characters. MAX_STRING_LEN is defined in the file idldir/external/rpc/rpc_idl.h.

Return Value

This function returns a status value that denotes success or failure as described below.

-1	RPC communication failure (an error message is also printed).

 0	Command is NULL.

 1	Success.

For all other errors, the error number is returned. This number could be passed as an argument to STRMESSAGE();.

set_idl_timeout

Calling Sequence

int set_idl_timeout(struct timeval* timeout)

Description

Call this function to replace the current timeout used by the RPC mechanism with the given timeout.

Parameters

timeout

A pointer to the new timeout value to be used. This parameter has no default.

Return Value

This function returns TRUE if the timeout was replaced. FALSE is returned if the timeout value was NULL or zero.

set_idl_variable

Calling Sequence

int set_idl_variable(CLIENT* client, varinfo_t* var);

Description

Call this function to assign a value to an IDL variable in the IDL session referred to by client. The address var points to a varinfo_t structure that contains information about the variable to be set. The "helper" functions can be used to build var. (See "The varinfo_t Structure" on page 2-63.) Any scalar or array variable type can be set. Variables can be set only in the main IDL program level.

Note that it is not possible to set the value of an IDL structure. To set values in an IDL structure, set the individual elements of the structure to scalar IDL variables, then use the send_idl_command function to create the structure in IDL.

It is not possible to set the value of IDL system variables directly. To set the value of an IDL system variable, first set the value of a regular IDL variable. The value of the regular variable can then be assigned to the system variable. For example:

set_idl_variable(client, &newvar); /* newvar describes the */
                                  /* IDL variable "NEW" */
send_idl_command(client, "!P.T = NEW");

Parameters

client

A pointer to the CLIENT structure that corresponds to the desired IDL session.

var

The address of the varinfo_t structure that contains information about the variable to be set.

Return Value

This function returns a status value that denotes the success or failure of this function as described below.

-1	Failure: bad arguments supplied (e.g., var is NULL).

 0	RPC mechanism failed (an error message is also printed).

 1	Success

set_rpc_verbosity

Calling Sequence

void set_rpc_verbosity(verbosity)

Description

This function controls the printing of error messages by RPC library routines. If verbosity is TRUE, error messages will be printed by the various RPC routines to explain what failed. If verbosity is FALSE, return codes continue to indicate success or failure, but no error messages are printed.

Parameters

verbosity

An int specifying TRUE or FALSE as explained above.

Return Value

None.

unregister_idl_client

Calling Sequence

void unregister_idl_client(CLIENT* client)

Description

Call this function to release the resources associated with the given CLIENT structure. The operating system automatically releases the resources associated with all CLIENT structures when your program exits. This function does not affect the IDL server.

Parameters

client

The pointer to the CLIENT structure to be unregistered.

Return Value

None.


The varinfo_t Structure

The varinfo_t structure is used to pass variables to and from the IDL server.

The varinfo_t structure is defined in the idldir/external/rpc/rpc_idl.h file. The structure is:

typedef struct _VARINFO {
char Name[MAXIDLEN+1];
IDL_VPTR Variable;
IDL_LONG Length;
} varinfo_t;

Variable Creation Functions

A number of functions are provided to help build varinfo_t structures. These functions are contained in the file idldir/external/rpc/helper.c.

The variable creation functions are described below. Unless otherwise noted, all of the following functions return TRUE if variable creation is successful and FALSE otherwise. When passing a varinfo_t structure pointer, if the Variable field is NULL, the variable creation functions attempt to allocate that field.

v_make_byte

Calling Sequence

int v_make_byte(varinfo_t* var_struct, char* var_name,
     unsigned value)

Description

Create an IDL byte variable with the given name and value.

v_make_complex

Calling Sequence

int v_make_complex(varinfo_t* var_struct, char* var_name,
     double real_value, double imag_value)

Description

Create an IDL complex variable.

v_make_dcomplex

Calling Sequence

int v_make_dcomplex(varinfo_t* var_struct, char* var_name,
     double real_value, double imag_value)

Description

Create an IDL double-precision complex variable.

v_make_double

Calling Sequence

int v_make_double(varinfo_t* var_struct, char* var_name,
     double value)

Description

Create an IDL double-precision, floating-point variable.

v_make_float

Calling Sequence

int v_make_float(varinfo_t* var_struct, char* var_name,
     double value)

Description

Create an IDL single-precision, floating-point variable.

v_make_int

Calling Sequence

int v_make_int(varinfo_t* var_struct, char* var_name, int value)

Description

Create an IDL (16-bit) integer variable.

v_make_long

Calling Sequence

int v_make_long(varinfo_t* var_struct, char* var_name,
     IDL_LONG value)

Description

Create an IDL long variable.

v_make_string

Calling Sequence

int v_make_string(varinfo_t* var_struct, char* name,
     char* value)

Description

Create an IDL string variable.

v_fill_array

Calling Sequence

int v_fill_array(varinfo_t* var, char* name, int type,
     int ndimension, IDL_LONG dims[], UCHAR* value,
     IDL_long length)

Description

Create an IDL array variable. The type argument should be one of the following values (defined in the file export.h):

IDL_TYP_BYTE, IDL_TYP_INT, IDL_TYP_LONG, IDL_TYP_FLOAT, IDL_TYP_DOUBLE, IDL_TYP_STRING, IDL_TYP_COMPLEX, IDL_TYP_DCOMPLEX

This function allocates var->Variable->value.arr.

If value is NULL then var->Variable->value.arr->data is allocated.

The dims[] argument should have at least ndimension valid elements.

If value is supplied but length is 0, var->Length is filled with the computed size of the array (in bytes) and value is assumed to point to at least that many bytes of memory. If value and length are supplied, length is assumed to be the size (in bytes) of the region of memory that value points to. (See "Notes on Variable Creation and Memory Management" on page 2-66.)


More Variable Manipulation Macros

The following macros can be used to get information from varinfo_t structures. Like the variable creation functions, these macros are defined in the file rpc_idl.h.

All of these macros accept a single argument v of varinfo_t type.

GetArrayData(v)

This macro returns a pointer to the array data described by the varinfo_t structure.

GetArrayDimensions(v)

This macro returns the dimensions of the array described by the varinfo_t structure. The dimensions are returned as long dimensions[].

GetArrayNumDims(v)

This macro returns the number of dimensions of the array.

GetVarByte(v)

This macro returns the value of a 1-byte, unsigned char variable.

GetVarComplex(v)

This macro returns the value (as a struct, not a pointer) of a complex variable.

GetVarDComplex(v)

This macro returns the value (as a struct, not a pointer) of a double-precision, complex variable.

GetVarDouble(v)

This macro returns the value of a double-precision, floating-point variable.

GetVarFloat(v)

This macro returns the value of a single-precision, floating point variable.

GetVarInt(v)

This macro returns the value of a 2-byte integer variable.

GetVarLong(v)

This macro returns the value of a 4-byte integer variable.

GetVarString(v)

This macro returns the value of a string variable (as a char*).

GetVarType(v)

This macro returns the type of the variable described by the varinfo_t structure. The type is returned as IDL_TYP_XXX as described under the documentation for the get_idl_variable function.

VarIsArray(v)

This macro returns non-zero if v is an array variable.


Notes on Variable Creation and Memory Management

This section contains miscellaneous notes about variable creation.

Freeing Resources

The variable creation functions (i.e., v_make_xxx) do not free resources associated with a variable before placing new information there. Your programs should free resources (if there are any) associated with the varinfo_t structure being passed.

To prevent memory leakage, memory associated with a variable is freed before new memory is allocated. You should make sure that the varinfo_t structure passed to the get_idl_variable function contains valid information or has been cleared (to zeroes) first. If an array of the same size, dimensions, and type is being read into the existing array variable, no allocation is performed and the same space is re-used. For example:

/* Assume that:
   X = FLTARR(1000, 1000)
   Y = FLTARR(1000, 1000)
   Z = LONARR(1000, 1000)	same size, different type
*/

bzero(&vinfo, sizeof(vinfo));
get_idl_variable(client, "X", &vinfo, 0); /* array allocated */
...
get_idl_variable(client, "Y", &vinfo, 0); /* memory re-used */
...
get_idl_variable(client, "Z", &vinfo, 0); /* array allocated */
free_idl_var(&vinfo);

The get_idl_variable function calls free_idl_var before doing any allocation. So, in the example above, we only needed to free Z. X and Y were freed when we re-used vinfo.

Creating a Statically-Allocated Array

It is possible to create a statically-allocated array for receiving information from the server without having the overhead of memory reallocation every time information is received.

If the Length field of the varinfo_t structure is not zero, it is assumed to be the size of the array data. The free_idl_var function will not do anything to a variable where length is non-zero. It is up to the programmer to do their own memory management if this is the case. Storing a scalar in a static variable (i.e., a variable that has a non-zero Length field) fails as does attempting to store an array that does not fit the statically-allocated array. For example:

/* X = FLTARR(10)     40 bytes of data (10*4)
   Y = LONARR(2,2,2)  32 bytes of data(2*2*2*4)
   Z = BYTARR(50)     50 bytes of data
   W = 12             scalar
*/

char       buf[40]
varinfo_t  v;
VARIABLE   var;
ARRAY      arr;

/* Build a static array. Fill in the minimum amount of */
/* information required.                              */

v.Variable    = &var;
v.Length      = 40;
var.type      = IDL_TYP_BYTE;
var.flags     = V_ARR;
var.value.arr = &arr;
arr.data      = buf;

get_idl_variable(client, "X", &v, 0);  /* ok */
get_idl_variable(client, "Y", &v, 0);  /* ok */
get_idl_variable(client, "Z", &v, 0);  /* fails — too big */
get_idl_variable(client, "W", &v, 0);  /* fails — scalar */

Allocating Space for Strings

All space for strings is assumed to be obtained via malloc(3). This fact is important only when receiving variables (using the get_idl_variable function). For example, the following code fragment is valid:

v_make_string(&foo, "UGH", "blug");
set_idl_variable(client, &foo);

Here is an example of code that will crash your program:

v_make_string(&foo, "UGH", "blug");
set_idl_variable(me, &foo);
send_idl_command(me, "UGH='hello world'");
get_idl_variable(me, "UGH", &foo, 0);

In this case, the get_idl_variable function attempts to free the old resources before allocating new storage. Freeing the constant blug results in an error. You could achieve the desired result without an error by changing the first line to:

v_make_string(&foo, "UGH", strdup("blug"));


RPC Examples

A number of example files are included in the idldir/external/examples/rpc directory. A Makefile for these examples is also included. These short C programs demonstrate the use of the IDL RPC library.

Jump forward to 28

Jump backward to x