Rexx Programming Guide

Modifying the Rexx Program to Run in the Plug-in

This chapter describes the modifications or changes that need to be made to Rexx programs to enable them to run in the Rexx Plug-in. First the changes are described in the Requirements for All Rexx Programs section. Then specific examples and tips are given for each type of Rexx program in the sections that follow.

Requirements for All Rexx Programs

What do you have to do to a Rexx program to make it run in the plug-in? The answer ranges from nothing at all, to some minor modifications, depending on the type of Rexx program and what you want to do.

Rexx applications that run in their own window and do not use any services of the plug-in, do not need any modifications. These include both visual and command line type programs. Programmers writing those types of programs can skip the rest of this document and skip the Programming Reference document.

Rexx programs that need to interface with the plug-in, because they need to issue plug-in commands, get notification of plug-in window events, or because they are running as an applet, must be slightly modified to run in the plug-in. The following steps delineate the modifications that must be done, along with a few things to keep in mind as you are writing your Rexx programs.

Step 1 - Remove Window Control Widgets

This only applies to visual type Rexx programs that run as an applet of the plug-in.

Rexx programs that run as applets must be cognizant of how the application will appear on the HTML page. The Rexx application running as an applet is assigned an area on the HTML. That area is defined by the height and width parameters of the EMBED tag. The area does not change size when the browser window is resized. If the browser window is sized smaller than the plug-in area the browser creates scroll bars so that the plug-in area can be scrolled. Since the plug-in area is part of the HTML page, the plug-in area, and hence the Rexx application running in that area, is controlled by the browser: when the browser window is moved the plug-in area (Rexx application) is moved, when the browser window is minimized the Rexx application is minimized, when the browser window is closed the Rexx application is terminated, etc.

Therefor you must remove the controls from the Rexx application that allow the user to move, size, minimize or maximize, and terminate the application window. Those tasks are handled through the browser window. This means that Rexx applications running as an applet should not have

The Rexx Plug-in takes care of removing the entry for the Rexx application from the OS/2 window switch list.

Step 2 - Register Rexx Plug-in Functions

This step only applies to Rexx programs that run in a separate session.

Rexx programs that run in a separate session use the plug-in functions in the wdPlugin.dll module. (Rexx programs that run as macros use those same functions built-in to the plug-in and the Rexx functions are registered for them automatically by the plug-in.) The plug-in functions must be registered before they can be called by the Rexx program. The plug-in provides a function, wdPluginLoad(), that will register all the other plug-in functions, as shown in the example below.

call RxFuncAdd 'wdPluginLoad', 'wdPlugin', 'wdPluginLoad' call wdPluginLoad

While it is not necessary for Rexx programs that run as a macro of the plug-in to register the plug-in functions it will not do any harm if the functions are registered by a Rexx program running as a macro. The wdPluginLoad() function is smart enough to know what type of Rexx program is calling it and to adjust itself appropriately.

Generally you should not deregister the Rexx functions at the end of your program because there may be other programs currently running in the plug-in that are using the functions. You can use the query instances command to determine if any other Rexx programs are running. The instance count (or instances) is the count of the number of instances of the plug-in that are currently running. If instance=1 when you query instances you know that you are the only running Rexx program.

Step 3 - Parse Arguments - Initialize Environment

This step applies to all Rexx programs.

All Rexx programs that need to communicate with the plug-in must execute the wdParseArgs() function at the beginning of the Rexx program. The function wdParseArgs() initializes the plug-in Rexx environment and creates two Rexx stem variables: wdMainArgs. and wdEmbed. The example below shows how to call the wdParseArgs() function and how to check for errors.

rc = wdParseArgs() if (substr(rc,1,1) = '#' then do say rc exit end

GPF Rexx programs call wdParseArgs() in a different manner, as described below.

Step 4 - Size and Position the Application's Main Window

This only applies to visual type Rexx programs that run as an applet of the plug-in.

The Rexx Plug-in provides the dimensions of the plug-in area to the Rexx application in the Rexx stem variable wdMainArgs., which is created in the Rexx program by the function wdParseArgs(). These dimensions are used to size the Rexx application window.

Step 5 - Link to the Plug-in

This only applies to visual type Rexx programs that run as an applet of the plug-in.

Any Rexx programs that need to have the plug-in control its window, or to receive messages from the plug-in, must link to the plug-in using the Link command, as shown below.

call wdCommand 'link drrexx' or call wdCommand 'link gpfrexx' or call wdCommand 'link vxrexx'

Keep in Mind - wdMainArgs. Must be Visible

The plug-in environment for Rexx is stored in the Rexx stem variable wdMainArgs. , which is created by the wdParseArgs() function. This Rexx variable must be visible at all times in Rexx. Normally this is not a problem since Rexx variables are by default global to all routines in a single source file. The problems arise in

  1. Rexx routines that are declared PROCEDURE, since that hides all the variables from the Rexx variable pool.
  2. Rexx routines that are contained in a separate source file, since the Rexx variable pool is not shared across code in different source files.

The solution to the first problem, the PROCEDURE, is to EXPOSE the wdMainArgs. stem variable, making sure the include the trailing period at the end of the name. For example

myProcedure: procedure expose wdMainArgs. wdEmbed. wdPlugin. exposes all three plug-in Rexx stem variables. The wdMainArgs. stem variable is required to be exposed; the wdEmbed. and wdPlugin. only need to be exposed if you are using them in the procedure.

The solution to the second problem, Rexx code in a separate source file, is to call the plug-in Rexx function wdExposeArgs() at the top of the Rexx routine in the separate file. This exposes the wdMainArgs. and wdEmbed. Rexx variables to the routine. The wdPlugin. variable must be passed in manually, if it is needed. The example below shows how to do this.

Main program

call wdParseArgs ... ... do something here ... call myRoutine wdMainArgs.environment ... exit

MYROUTINE.COM

/* myRoutine */ rc = wdExposeArgs(arg(1)); ... ... exit

The value in wdMainArgs.environment is required by the function wdExposeArgs() in order to find the variables and set them in the variable pool. You must pass wdMainArgs.environment as one of the arguments to the routine in the external file in order to supply it to the wdExposeArgs() function.

Keep in Mind #2 - wdCommands() Only on Main Thread

The Rexx function wdCommand() can only be used on the main thread of your Rexx program. If the program is multi-threaded you must insure that wdCommand() is not called on any of the secondary threads. If you need to multitask routines that require plug-in commands put them in a separate Rexx program and start another plug-in instance to run that Rexx program. You can then use the interprocess communication facilities provided by the plug-in to communication between the two programs/plug-in instances.

Command Line Type Programs

Command line type Rexx programs can run either as a macro of the plug-in, or in a separate Command Prompt window that is run as a separate session. The MIME-Type value assigned to the Type parameter of the EMBED HTML tag determines whether the Rexx program runs as a macro of the plug-in or in a separate Command Prompt window. A value of x-warpdoctor/rexx runs the program as a macro of the plug-in. A value of x-warpdoctor/cmdrexx runs the program in a separate session, in a Command Prompt window.

The preferred method for running command line type Rexx programs is to run the program as a macro because the program output is integrated into the plug-in window and because the Rexx program can utilize more facilities of the plug-in for input and output. However certain types of Rexx command line programs must run in a Command Prompt window: for example Rexx programs that utilizes screen control functions such as SysTextScreenRead(), SysTextScreenSize(), SysCls(), etc.

Running as a Macro

When a Rexx program runs as a macro of the plug-in the plug-in creates an output window in the plug-in area of the HTML page to handle input and output display for the Rexx program. Output from the Rexx program, either by the Rexx SAY statement or with CHAR() or LINEOUT() statements routed to STDOUT, appear in the output window as shown below.


Output from Rexx program Displayed in Output Window

The output window is sized and positioned to match the plug-in area specified in the height and width tags of the EMBED HTML tag. The foreground and background colors used in the output window can be specified with the FGColor and BGColor parameters of the EMBED tag, or they can be set in the Rexx program using the Set command.

Input to the Rexx program from the PULL statement can be handled three ways:

  1. Using the standard SAY and PULL statements.
  2. Using the SayPrompt plug-in command and the Rexx PULL statement.
  3. Using the Prompt plug-in command in place of PULL.

When the plug-in encounters a PULL statement it sets the focus to the output window and changes the window from read-only to read/write. The user types the response directly into the output window. When the user presses the Enter key, the window changes back to read-only and the typed response is returned as the Rexx variable specified in the PULL statement.

The plug-in SayPrompt command works like the normal Rexx SAY command except that a carriage return and line feed are not output at the end of the text. This places the cursor at the end of the text in the SayPrompt command when the user starts typing a response.

The plug-in Prompt command displays a prompt dialog where the user types in the response. The text typed in the prompt dialog is returned in the return value from the command.

The behavior of the Rexx PULL statement can be altered by setting the PullAsPrompt plug-in variable. When PullAsPrompt=0 the PULL statement works as described above. When PullAsPrompt=1 or YES, the PULL statement causes the Prompt Dialog to be displayed for input; input typed in the dialog is returned in the Rexx variable specified in the PULL statement. The title in the prompt dialog is Input. When PullAsPrompt=2 the prompt dialog is displayed for the PULL statement, but the title in the prompt dialog is the text from the last SAY statement. For example:

call wdCommand 'set pullAsPrompt=2' say 'Enter your name' pull name

displays the following prompt dialog

PullAsPrompt is also an HTML EMBED tag parameter and can be set in the HTML EMBED tag that starts the Rexx program.

The output window can be disabled or "turned off" by setting the RexxOutputWindow=NO parameter in the EMBED HTML tag. This replaces the multiline edit control used for the output window with a blank rectangle of the same size. When the output window is turned off all SAY statements and STDOUT and STDERR output is discarded. PULL statements are handled as if PullAsPrompt=2, meaning that a PULL statement displays the prompt dialog for input with the last SAY statement used as the title to the dialog. Turning the output window off is not recommended for Rexx as macro programs but there are circumstances when it makes sense for Rexx as Command Prompt type programs.

Running in a Command Prompt Window

The plug-in runs x-warpdoctor/cmdrexx MIME-Type programs in a separate Command Prompt window by starting CMD.EXE and passing the name of the Rexx program. In addition to the separate Command Prompt window that is opened to run the Rexx program, the output window is also created in the plug-in area, as you can see in the figure below.


Command Prompt Window, with Rexx Output Window in the Background

The output window appears in the HTML page that contains the EMBED tag that starts the Rexx program/plug-in instance. That page/window must remain open the entire time the Rexx program is running; when the HTML page containing the EMBED tag is closed or destroyed the Rexx program is terminated and the Command Prompt window is closed. The page can be destroyed by the user clicking the Back button on the browser, or by typing a new URL.

Rexx input and output works as normal for Rexx programs running in the Command Prompt window, meaning for example that SAY statements are output in the Command Prompt window and the user types input for the PULL statement in the Command Prompt window. The output window on the HTML page, in the browser window that started the Rexx program/plug-in instance is displayed but generally will have no text in the window. The Command Prompt Rexx program can however output text in the output window using the plug-in SayToWin command. This could be used, for instance, to display a message in the output window telling the user to close that window when the Command Prompt Rexx program finishes running, as done in the Command Prompt example program.

It can be confusing to the user to have an output window displayed while the Rexx program runs in a separate window. To help avoid the confusion you can minimize the area allocated to the output window by sizing the output window to be very small by adjusting the height and width parameters of the EMBED tag to small values. (Note: the width and height values cannot be adjusted to less than 10 or the program will not run at all on some browsers.) Alternately you can set the EMBED tag parameter RexxOutputWindow=NO to prevent the MLE control from appearing and use the BGColor parameter of the EMBED tag to make the plug-in area blend into the background of the HTML page, essentially making the area invisible. To do this use the same setting for the BGColor parameter of the EMBED HTML tag that you use for the BGCOLOR of the HTML BODY tag. An example of this is shown below.

<html>
<BODY bgcolor="#A6CAF0">
<br>
<h3>Rexx Cmd Execution</h3>
<embed
 type='x-warpdoctor/cmdrexx'
 height=10
 width=10
 src='http://www.warpdoctor.org/helloWorld2.rex'
 RexxOutputWindow=NO
 bgcolor='#A6CAF0'
  >
</embed>
</body>
<html>

This example sizes the plug-in area to be 10 pixels by 10 pixels, turns off the output window, and sets the background color of the output window to the background color of the browser window (actually the HTML document in the browser window.)

Please note that this technique will only work when specifying colors in hexadecimal values; it will not work when specifying colors by name. The hexadecimal values for colors can be found in the Presentation Manager documentation or in HTML documentation. You can also determine the hex value for a color by using the Query Colors example program. With this example program you can drop a color from the Solid Color Palette (in the OS/2 Setup folder) on the output window and the program will return the corresponding hexadecimal value.

When the Rexx program finishes running the Command Prompt window (but not the HTML page containing the EMBED tag that started the Rexx program) is immediately closed, which can make it difficult for the user to read any output the Rexx program may have written to the window. You can set the CloseOnExit=NO plug-in variable from the Rexx program to prevent the Command Prompt window from closing when the Rexx program finishes running. CloseOnExit is also a parameter of the EMBED HTML tag and can be set from the HTML that starts the Rexx program/plug-in.

If you want the Rexx program to close the browser window containing the HTML page that started the program when the Rexx program is done, you can issue a CloseWindow command as the last line of the Rexx program. It only makes sense to do this if the plug-in instance is started in its own browser window, plus you must know the name of the browser window you want to close. See the Windows section below for more details on opening and closing browser windows.

Since Rexx programs that run in a Command Prompt window run in a separate session they use the plug-in Rexx functions contained in wdPlugin.dll, which means the functions must be registered before they can be used. The plug-in Rexx function wdPluginLoad() is provided to register all the other plug-in functions. The following code snippet shows how to load the plug-in Rexx functions

call RxFuncAdd 'wdPluginLoad', 'wdPlugin', 'wdPluginLoad' call wdPluginLoad

DrRexx

DrRexx programs run well in the Rexx Plug-in. The major difficulty in writing DrRexx programs is handling the sizing of the application window(s), and passing focus notification back to the browser window when the DrRexx application receives the focus. Both issues are addressed below.

DrRexx applications are identified to the Rexx Plug-in by a MIME-Type value of x-warpdoctor/drrexx in the Type parameter of the EMBED HTML tag. The plug-in starts DrRexx.exe in a separate session passing the name of the downloaded Rexx program as a parameter. Since DrRexx programs run in a separate session they use the plug-in Rexx functions contained in wdPlugin.dll. Both DrRexx.exe and wdPlugin.dll are included in the standard Rexx Plug-in installation package, so both files should be present on all client machines running the plug-in. The existence of both files is checked by the plug-in before the plug-in starts to run any DrRexx application.

Since DrRexx applications run in a separate session they must use the plug-in Rexx functions contained in the separate DLL (wdPlugin.dll) which means the functions must be registered before they can be used. The plug-in Rexx function wdPluginLoad() is provided to register all the other plug-in functions. The following code snippet shows how to load the plug-in Rexx functions

call RxFuncAdd 'wdPluginLoad', 'wdPlugin', 'wdPluginLoad' call wdPluginLoad

In addition (just as with all types of Rexx programs running in the plug-in) the wdParseArgs() function must be called before any other plug-in Rexx function. The best place to put initialization code like this is to create a DrRexx global procedure called INIT, which is called when the application starts, before any other procedure is run, as shown below.


DrRexx Global INIT Procedure

The Main Window

If the DrRexx application is to run as an applet on the HTML page the main window of the application must eliminate all the controls which can be used by a user to control the window. This means the title bar, system menu, minimize and maximize buttons must be removed, and the border changed from a sizing border to one which cannot be sized by the user. This is all done from the Style pop-up dialog for the main window.


Style Dialog

Removing the Sizing border from a DrRexx application is something of a catch-22 situation. DrRexx uses the presence or absence of the sizing border to determine whether it should automatically reposition and resize all the controls within a window: if a window has a Sizing border and there is no SIZE event code for that window DrRexx will reposition and resize the controls within the window. If the border is some type other than a sizing border, or if any Rexx code exists in the SIZE event for that window then DrRexx will not reposition or resize controls for that window. This means that if you remove the Sizing border to prevent users from trying to resize the application window you are obligated to handle all the resizing and reposition tasks yourself. You have three choices:

  1. Leave the Sizing border on the application and hope that your users don't try and resize the application. The Drives example program uses this approach, and the sizing issue isn't too bad for that application.
  2. Remove the Sizing border and size your application to exactly, or very closely, fit the plug-in area size specified in the EMBED tag height and width parameters. Then you do not have a resize issue since all the sizes match up to start with.
  3. Write Rexx code for the SIZE event that resizes and repositions the controls.

The figures below shows the Rexx code that handles resizing for the Message Pipe example program.

This figure shows the main window for the Message Pipe program. Notice that the text box under the cursor is named tb1. You can see this in the status line in the figure. All the text boxes are named td1, td2,td3, and the list box is named msgList. The main dialog window is called main


Message Pipe Example Program Main Window

This figure shows the Rexx code that handles Size events. The first line gets the current position and width and height of the main window into the variable x, y, width and height. Those values are then used to position and size the three text boxes and the list box. Position() is a DrRexx function that sets the current size and position of the control, or returns the size and position of a control if no arguments are passed.


Message Pipe Example Size Event Code

This figure shows how the Message Pipe example program looks in a on an HTML page.


Message Pipe Example Size Event Code

The other catch-22 associated with the Sizing border is that the Size event does not get fired when the plug-in initially sizes the application window to fit the plug-in area. The work-around for this is to size the main window manually, using values that are passed to the DrRexx application when the application starts.

The plug-in Rexx function wdParseArgs() decodes and parses a number of values passed to the Rexx program into the Rexx stem variable wdMainArgs. Among the values placed into wdMainArgs. are the position and size of the plug-in area, which can be used to size the DrRexx application main window. The follow statement shows how to do that, assuming the name of the main window is main

call main.position wdmainargs.winx,wdmainargs.winy,wdmainargs.winwidth,wdmainargs.winheight

This statement is best placed in the Init event for the main window. The Init event for a window gets executed when the window is created before any other event for that window.

Focus Issue

Since DrRexx applications run a separate process from the browser window events are not passed up the window chain from the DrRexx window to the browser. (Events are passed down the chain correctly by virtue of the parent-child relationship established by the plug-in to the DrRexx window and through PM window messages sent to the DrRexx window by the plug-in.) The most obvious manifestation of this appears when the application window is partly obscured by another window. Clicking in the application window does not bring the application (and browser) window above the obscuring window, because the application is a child of the browser window but the browser window never gets the focus event. (Clicking on the browser window frame, or any part of the browser window that is not in the plug-in area does move the browser window and application to the top of the z-order.)


Plug-in Application Obscured by Another Window

The work-around is to issue the plug-in command GotFocus command every time the the DrRexx application gets the focus. The figure below shows the GotFocus command in the DrRexx FOCUS event.


Plug-in GotFocus Command in Focus Event

This focus problem is not exclusive to DrRexx but also happens with GPF Rexx applications. VX-Rexx applications handle the focus event correctly.

Linking the DrRexx Application to the Plug-in

When running a DrRexx application as an applet, the application needs to be "linked" to the Rexx Plug-in with the plug-in Link DrRexx command. Linking the application to the plug-in tells the plug-in that the application is running as an applet and that it needs additional processing by the plug-in. The plug-in changes the parent of the DrRexx application from the desktop to the plug-in, and starts sending the DrRexx application window messages when needed. The Link command should be placed in the Init or Open event for the main window.

GPF Rexx

GPF Rexx programs run well in the Rexx Plug-in. The major drawback to using GPF Rexx for plug-in programs is that the programs can only be packaged as executables, adding approximately 25K to the size of the file that has to be downloaded. This can be partly mitigated by compressing the executable file.

GPF Rexx applications are identified to the Rexx Plug-in by a MIME-Type value of x-warpdoctor/gpfrexx in the Type parameter of the EMBED HTML tag.

The plug-in starts the Rexx program executable (created by GPF) in a separate session. Since GPF Rexx programs run in a separate session they use the plug-in Rexx functions contained in wdPlugin.dll. In addition the size of the executable created by GPF Rexx can be reduced by specifying that the program use a run-time DLL - GPFRRT01.DLL. The existence of this DLL, along with wdPlugin.dll, are checked on the client machine before the plug-in starts the GPF Rexx program. If you choose to not use the GPF Rexx run-time when you create your Rexx executable you need to run the GPF program as MIME-Type x-warpdoctor/generic, which will bypass the check for GPFRRT01.DLL by the plug-in.


Specifying the Run-Time When Building Executable

Main Window

If the GPF Rexx application is running as an applet the programmer must initially size and position the main window of the application, and remove all the controls that can be used to size, move or close that window.

The minimize, maximize, system menu, and title bar controls, along with the type of border can all be specified from this dialog for the main window.

This screen is also where you create a "user function object" that is called when the main window is initialized. A "user function object" is really a Rexx routine that is called when the Init action (event) happens. Pressing the Action button brings up a list of all the actions (or events) associated with the window. You can highlight an action and click on the add button to create a "user function object" (rexx routine). In that routine is where we will register the plug-in Rexx functions, initialize the plug-in environment and size the main window.

GPF Rexx applications are run in a separate session so they must use the plug-in Rexx functions contained in the DLL wdPlugin.dll. The functions must be registered before they can be used. The plug-in Rexx function wdPluginLoad() is provided to register all the other plug-in functions. The following code snippet shows how to load the plug-in Rexx functions

call RxFuncAdd 'wdPluginLoad', 'wdPlugin', 'wdPluginLoad' call wdPluginLoad

Parsing the Argument String

The plug-in function wdParseArgs() must be called before any other plug-in functions, and before using any of the plug-in provided Rexx variables. Since GPF Rexx handles arguments passed to the program differently than the "normal" Rexx standard, wdParseArgs() must be called differently for GPF. Normally wdParseArgs() will get the argument(s) passed to the Rexx program and parse that argument into the wdMainArgs. stem variable. In GPF Rexx the argument(s) passed to the executable must be obtained using the GPF provided function queryArg(), passing in the name of a Rexx stem variable to hold the argument(s). One of the tail variables of the stem passed into the queryArg() is then passed to wdParseArgs(), as shown below.

queryArg('argvar.') rc = wdParseArgs(argvar.2) if (substr(rc,1,1) = '#') then do sendMsgBox(rc) exit end

In the example above we are calling queryArgs() passing in the Rexx variable argvar.. GPF Rexx populates that stem variable with a number of values, the one of interest to us is in argvar.2 since it contains the value of the first (and only) argument passed to the GPF Rexx program from the plug-in. We then call wdParseArgs() passing in the argument string contained in argvar.2, check for errors and call the GPF supplied sendMsg() function to display any error message.

GPF Rexx applications are not sized automatically by the plug-in when they start up. Instead you must size the main window using values from the wdMainArgs. Rexx variable. That variable is created by the wdParseArgs() plug-in Rexx function. The code for setting the window size and position is shown below, assuming the main window is called MainWindow

Swp._x = wdMainArgs.winX; Swp._y = wdMainArgs.winY Swp._cx = wdMainArgs.winWidth; Swp._cy = wdMainArgs.winHeight; setPositionAndSize('MainWindow','swp.')

Linking the GPF Application to the Plug-in

Finally we need to link the GPF application to the plug-in so that the plug-in can control the GPF application main window. We use the plug-in command Link GPF to tell the plug-in that the GPF application is running as an applet and to allow the plug-in to control the GPF application main window.

call wdCommand 'link GPFREXX'

Rexx/TK

Rexx/TK is a library of functions that provides an interface between Rexx and the TK graphical library. The TK graphical library is designed to run with the TCL language, and is normally known as TCL/TK. The Rexx/TK basically replaces most of the TCL language part of the TK interface with a Rexx interface. In order to run Rexx/TK you need both the Rexx functions DLL (rexxtk.dll) and the OS/2 Tcl/TK package installed on the client machines.

The TK library, as implemented in OS/2, has no provision for removing the title bar, system menu and minimize/maximize buttons from windows created with the library. Therefor RexxTK applications cannot run as applets in the plug-in. However they can run in the plug-in in a separate window.

Because the Rexx/TK application runs in a separate window the plug-in does not have a MIME-Type for Rexx/TK. You use either x-warpdoctor/rexx (recommended) or x-warpdoctor/cmdrexx.

VRexx

VRexx2 (also known as VRexx) is a library of functions which can be used to create Presentation Manager windows and dialog boxes. VRexx2 windows/applications cannot be run as applets in the plug-in because VRexx2 windows cannot be precisely positioned; the VRexx function to create the window takes arguments to position the window as percentages of the screen size. Because of this it is impossible to position the VRexx2 window in the plug-in area of an HTML page.

While VRexx2 applications cannot run as an applet in the plug-in, they can run in the plug-in in a separate window. Since the VRexx2 application is running in a separate window there is no special MIME-Type for the VRexx2 application; use either x-warpdoctor/rexx (recommended) or x-warpdoctor/cmdrexx.

VX-Rexx

VX-Rexx applications are identified to the Rexx Plug-in by a MIME-Type value of x-warpdoctor/vxrexx, or x-warpdoctor/vx-rexx in the Type parameter of the EMBED HTML tag, depending on how the application is to be run by the plug-in. When using the x-warpdoctor/vx-rexx MIME-Type the plug-in starts wdRunRx.exe in a separate session, which in turn runs the VX-Rexx application. When using the x-warpdoctor/vx-rexx MIME-Type the plug-in runs the application as a macro of the plug-in, meaning the plug-in itself runs the application. Running the VX-Rexx application as a macro of the plug-in is better than running it in a separate session; however there are certain VX-Rexx applications which do not terminate cleanly when run as a macro. For those applications you will have to run the application in a separate session, i.e. use the x-warpdoctor/vx-rexx MIME-Type. The main symptom for an application that does not terminate cleanly is for the VX-Rexx application to crash the browser when the application is terminated.

Applications made with VX-Rexx to run in the plug-in must be "packaged" by VX-Rexx as "macros" using the File - Make Macro menu option, which saves about 23K of size from the file(s) that must be downloaded.


Packaging a VX-Rexx Application as a Macro

When you use the Make Macro menu option in VX-Rexx two files are created: a *.VRM "macro" file and a *.VRW "window" file. Additional *.VRM files may be created by VX-Rexx, for instance if the application has a secondary thread the secondary thread will be put into its own *.VRM file.

The *.VRM and *.VRW files must be placed in the same location on the web server. The *.VRM file is specified in the SRC parameter of the EMBED tag. The plug-in automatically retrieves the *.VRW file associated with the *.VRM file from the same location on the web server as the *.VRM file.

If there are multiple *.VRM files, or multiple *.VRW files for a single VX-Rexx application, you must zip all the files together into an archive and specify the archive file name in the SRC parameter. See the Packaging section for more specifics.

Main Window

VX-Rexx applications that run as an applet of the plug-in must have all the controls removed from the main window that allow the user to move, size, close, minimize or maximize the window. That is done in VX-Rexx from the properties notebook for the window, on the Frame tab, as shown below. Notice that all the check boxes are unchecked.


Properties for the Main Window

VX-Rexx applications should have the STDIO redirection turned off when running in the plug-in. If STDIO is not redirected and a Rexx SAY command is issued, a separate window is displayed by the VX-Rexx application. This second window prevents the application from being closed by the plug-in when the browser window or HTML page is destroyed.

VX-Rexx applications that run in a separate session, i.e. MIME-Type x-warpdoctor/vx-rexx, must register the plug-in Rexx functions. VX-Rexx applications that run as a macro of the plug-in (x-warpdoctor/vxrexx) do not need to register the plug-in Rexx functions; however it does no harm to register the functions when not needed since the wdPluginLoad() function is smart enough to handle both situations correctly. The best place to put these Rexx statements is in the INIT section of the main window. The code example below shows the INIT section from the Calc example program; the additions required by the plug-in are shown in red.

/*:VRX */
Init:
    
    call VRRedirectStDIO "OFF"

    call RxFuncAdd "wdPluginLoad","wdplugin","wdpluginLoad"
    call wdPluginLoad

    call wdParseArgs
    
    /* Clear the calculator memory
    */

    memory_total = 0
    call pb_c_Click

    /* Create the window
    */

    window = VRWindow()
    
/**
    call VRMethod window, 'CenterWindow'
**/
    call vrset "window1" , "left" , wdmainargs.winx||"P"
    call vrset "window1" , "top" , wdmainargs.winy-wdmainargs.winHeight||"P"
    call vrset "window1" , "width" , wdmainargs.winWidth||"P"
    call vrset "window1" , "height" , wdmainargs.winHeight||"P"
    numeric digits 12
    call wdCommand "link vxrexx "|| x2d(substr(vrget("window1","hwnd"),6),10)
    
    call VRSet window, 'Visible', '1'
    call VRMethod window, 'Activate'

    drop window

What the code example shows is:

Linking the VX-Rexx Application to the Plug-in

LInking the Rexx application to the plug-in tells the plug-in the handle of the application's main window, and allows the plug-in to control the application window so that the application functions as an applet. For VX-Rexx applications this is done by calling Link and passing the parameters VXREXX (or VX-REXX) and the window handle. The window handle is returned by the VX-Rexx function vrget("window1","hwnd"), but the handle is returned in hexadecimal; the Link command wants the value in decimal. The Rexx function x2d() converts the hexadecimal into decimal. but we have to use the numeric digits 12 statement to prevent the value from being truncated. The two statements below show how this is done, assuming the main window is called window1.

numeric digits 12
call wdCommand "link vxrexx "|| x2d(substr(vrget("window1","hwnd"),6),10)

Focus Issue

VX-Rexx application correctly bring the browser window to the top of the z-order when the application window gets focus; there is no need to use the GotFocus() plug-in command.

Packaging the Rexx Application

When the browser encounters an EMBED HTML tag on a page of HTML the browser searches the tag for the Type and the Src parameters. The TYPE parameter specifies the MIME-Type associated with the EMBED tag which the browser uses to determine which plug-in to load for the tag. The SRC parameter specifies the file that is to be streamed to the plug-in.

In the case of the Rexx Plug-in the TYPE parameter tells the plug-in what type of Rexx program it is going to run: DrRexx, command line in a Command Prompt window, GPF Rexx, etc. The Rexx plug-in then executes the program streamed to it by the browser (from the SRC parameter) when the program is finished downloading. The method used by the plug-in to execute the program depends on the type of Rexx program being run.

Packaging the Rexx program means placing the file or files needed for the program to run in a location the web server can access, and specifying the correct file name on the SRC parameter of the EMBED tag, along with the correct TYPE. Creating the EMBED tag is covered in the following section. This section discusses packaging the program: which file to use for the program, what name to use for that file, and optionally compressing the file or files that make up the Rexx program.

Visual Rexx application built with DrDialog and VX-Rexx can be packaged either as an executable file, or as a "project" or macro type file. Visual Rexx applications built with GPF Rexx can only be packaged as an executable file. The file that you want to specify in the SRC parameter of the EMBED tag is shown in the table below for each type of Rexx program.
Rexx Application TypeProgram Source File
Command Rexx The file containing the Rexx source code, the *.CMD file
Rexx The file containing the Rexx source code, the *.CMD file
DrRexxThe DrDialog project file, *.RES
GPF RexxThe executable file created with the Toolkit - Builder - Build .Exe menu option of the Interface Builder
Rexx/TKThe file containing the Rexx source code, usually a *.CMD file.
VRexx2 The file containing the Rexx source code, the *.CMD file
VX-RexxThe files created with the File - Make Macro menu option, the *.VRM & *.VRW files.
WarpINThe *.WPI file. WarpIn is covered in Installing WarpIN Archives below.

File Extensions

The file name, or more specifically the file name extension, has an important impact on how the program runs. This is caused by situations where the browser loads a plug-in to handle a file (or data stream) when no EMBED has appeared in an HTML page. This happens, for example, when a use clicks on a link that points simply to a non-HTML file.

The way browsers should work is that they should use the MIME-Type specified for a data stream in the header of the HTTP message. The way browsers really work is that they use the extension of a file name in order to determine what MIME-Type the file contains when there is no MIME-Type specified. Or in the case of Mozilla the browser uses the file extension regardless of the MIME-Type specified in the HTTP message header - which is a bug.

Therefor it is important to use file name extensions for the Rexx program file that will not be confused with another MIME-Type or another plug-in by the browser. Likewise it is important for the Rexx Plug-in to register only file extensions that will not cause conflicts with other plug-ins or with other actions the user wants to perform on a file. To that end the Rexx Plug-in registers the file extension .WRP for its use for all MIME-Types handled by the plug-in. This file extension is not known to be used by an other application or plug-in. The Rexx Plug-in also exclusively uses the MIME-Type specified in the TYPE parameter of the EMBED regardless of the MIME-Type designated by the browser when streaming the data to the plug-in. This avoids potential conflicts with other files and it gets around the Mozilla bug of ignoring the TYPE parameter when ascertaining the MIME-Type. When necessary the plug-in renames a file to the correct extension when it is saved to the client disk based the type of Rexx program being run, i.e. based on the MIME-Type specified in the TYPE parameter.

It is recommended that you rename all program source files to an extension of .WRP when saving them to the web server, which (hopefully) avoids any conflict with other applications or plug-ins. Alternately you could compress the program source file into a zipped archive file which hides the program file extension from view of the browser and web server.

Compressing Rexx Sources

Rexx program file(s) can be compressed into a zipped archive file using any industry standard zip.exe program; we recommend Info-Zip's zip.exe. Compressing the file into a zip archive file not only hides the program file extension, it also significantly speeds up the download of the file to the client machine.

The program source files in the zipped archive should retain their original file names and extensions. The zipped archive file name extension however should be changed from .ZIP to .ZPP or .WRP. This prevents conflicts with browsers that treat *.ZIP files specially, and bugs in certain browsers.

The main name of the zip file - the part of the file name before the extension - must be the same as the source file contained within the archive. For example if you are zipping the DrRexx source file drives.res the zip file name must be drives.zpp or drives.wrp.

When you zip the program file(s) you must specify to the plug-in that the file is zipped. You do this by adding the ZippedFlag=1 parameter to the EMBED tag. When the Rexx Plug-in sees the zippedflag=1 parameter it unzips the streamed file (the file specified in the SRC parameter) in the client's temporary directory and executes the source file from the temporary directory with the name matching the archive file.

Visual Rexx type programs that use graphics - icons, bitmaps and such - must insure that the graphics are on the client machine. This can be done by the application downloading the graphics file(s) when it starts with the GetURL command, or it can be done by including the graphic file(s) in the same zipped archive file that contains the source or program file. When the plug-in downloads a zipped archive file specified in the SRC parameter it unzips the entire contents of the archive file in the temporary directory of the client machine before it starts the Rexx program. The Rexx program, when it starts, can utilize the graphics files from the temporary directory. To find out what the temporary directory is (where the graphic file(s) were unzipped) the Rexx program can either:

Rexx applications need to be careful when using the Query TEMPDIR command, since the location of the temporary directory can be changed by the program using the Set TEMPDIR command. If the temporary directory is changed the Query TEMPDIR command will no longer point to the location of the files from the zipped archive. The PARSE SOURCE Rexx statement will always point to the location of the files unzipped from the archive.

The example below shows how to use the PARSE SOURCE statement to find the location of a graphics file, and to tell the application to use that graphics file. The example is from the VX-Rexx Bouncing Global example program.

parse source with x ' ' y ' ' fileName globe_icon = substr(fileName,1,length(fileName)-3) || "ICO" /* set the picturepath to the file bounce.ico from the archive file */ call vrset "Globe", "picturepath", globe_Icon /* add the downloaded file to the deleteFileList */ call wdCommand 'addToDeleteList '||globe_icon

The line

parse source with x ' ' y ' ' fileName gets the fully qualified name of the Rexx program into the Rexx variable fileName

The line

globe_icon = substr(fileName,1,length(fileName)-3) || "ICO" creates Rexx variable globe_icon from the Rexx source file name by stripping off the extension of the file name and adding the extension ICO.

The line

call vrset "Globe", "picturepath", globe_Icon tells the VX-Rexx application to use the graphic from the file name in globe_icon as the bouncing globe.

The line

call wdCommand 'addToDeleteList '||globe_icon tells the plug-in to delete the globe graphic file unzipped from the archive file when the plug-in instance terminates, that is, when the program terminates. While the plug-in will automatically delete the program source file(s) contained in the archive, it does not read the contents of the archive and therefor has no knowledge of what other files are in the archive. It is the Rexx programmer's responsibility to delete any other files contained in the zipped archive when the program is finished. The command AddToDeletList is provided by the plug-in as a way to insure that files get "cleaned up" (deleted) when the program terminates.

Please note that deleting files that were extracted from the zipped archive does not delete the zipped archive file that was downloaded. That will remain in the browser's cache until the cache is cleared, which normally is the what you want. The zipped file is cached so that the next time the user executes the program the file will not have to be re-downloaded. If for some reason you do not want the zipped file, or the program file, to remain in the cache when the plug-in instance terminates you can specify the EraseOnExit=YES parameter on the EMBED tag.

Starting the Rexx Plug-in

In order to run your Rexx application on a client browser you must create a HTML page with an EMBED HTML tag in the page. The parameters to the EMBED specify the Rexx program file, the type of Rexx program, the size of the area allocated on the page to the plug-in (the plug-in window size), and other items that control how the plug-in area looks on the page and how the plug-in runs the Rexx program. The example below is a complete HTML page, including the EMBED tag, from the calculator example program.

<html>
<BODY bgcolor="white">
<br>
<h3>VX-Rexx Calculator</h3>
<embed
 type='x-warpdoctor/vxrexx'
 height=350
 width=310
 src='http://www.warpdoctor.org/calc.zpp'
 title='Calculator Sample Program'
 zippedFlag=1
  >
</embed>
</body>
<html>

When the browser reads an EMBED tag it searches for the TYPE parameter containing the MIME-Type. The browser then searches its list of registered MIME-Types/plug-ins to find the first entry that matches. The browser then loads the plug-in DLL, if it is not already loaded, and starts an instance of the plug-in. (Opera browsers load the plug-in DLL when the browser starts.)

If the MIME-Type is not found in the list of registered MIME-Types what happens depends on the browser. Netscape and Mozilla based browsers output the "install plug-in" graphic

If the PluginsPage parameter has been set to a URL, when the user clicks on the graphic the URL is displayed. The setting PluginsPage='http://www.warpdoctor.org/plugin_install.html' can be used to display the install page for the Rexx Plug-in.

When using Opera and the MIME-Type is not found what happens depends on the version of Opera being used, or rather on the build number since the only version of Opera available for OS/2 is version 5.12. For earlier builds of Opera, when the browser encounters a MIME-Type not found in the list of MIME-Types associated with plug-ins the browser just stops, it does not display the "click here to get the plugin" graphic. When using later builds, e.g. build 31, Opera displays a dialog box prompting the user to get the plug-in. Perhaps the best way to handle Opera browsers without writing overly complex HTML/JavaScript code is to use JavaScript to detect if the plug-in is installed and if Opera is being used to display the page. The following two lines, along with the file plugin_opera.js, will handle detecting whether the plug-in is installed, detecting if Opera is being used, and displaying an HTML with a link to install the plug-in or to cancel.

<script language="JavaScript" src="http://www.warpdoctor.org/plugin_install.js"></script>
<script>checkPlugin();</script>
The file plugin_install.js can be called from the WarpDoctor site, or you can copy the contents shown below to a file on your own site. Be sure to place the file in same location as your HTML files. // plugin_install.js - function for handling Opera plug-in install function checkPlugin() { var numPlugins = navigator.plugins.length; var foundFlag = 0 if (navigator.userAgent.search(/Opera/) > -1) { for (var i = 0; i < numPlugins; i++) { aa = navigator.plugins[i].filename.toUpperCase().split('\\'); if (aa[aa.length-1] == 'NPWRPDOC.DLL') foundFlag = 1 } if (foundFlag==0) window.open('plugin_install2.html','instWin','outerheight=400,outerwidth=400,scrollbars,resizeable') } } Contents of plugin_install.js

The example below adds the PluginsPage parameter and JavaScript code for handling Netscape, Mozilla based and Opera browsers.

<html>
<BODY bgcolor="white">
<script language="JavaScript" src="http://www.warpdoctor.org/plugin_install.js"></script>
<script>checkPlugin();</script>
<br>
<h3>VX-Rexx Calculator</h3>
<embed
 type='x-warpdoctor/vxrexx'
 height=350
 width=310
 src='http://www.warpdoctor.org/calc.zpp'
 title='Calculator Sample Program'
 zippedFlag=1 
 PluginsPage='http://www.warpdoctor.org/plugin_install.html'
  >
</embed>
</body>
<html>

When the browser starts a plug-in instance to handle the EMBED tag/area it passes to that instance all the parameters specified for the EMBED tag. Some of those parameters have special meaning to the browser: for instance the height and width parameters tell the browser how big to make the plug-in area on the HTML page, the border parameter tells the browser what kind of border to draw around the plug-in area, etc. The parameter that do not have meaning to the browser - those that are not in the HTML specification - are ignored by the browser. This allows parameters of the EMBED tag to be used to pass arguments to the Rexx program. The Rexx Plug-in makes the EMBED tag parameters available to the Rexx program two different ways.

Once the plug-in instance is started the browser retrieves the file or URL specified in the SRC parameter of the EMBED tag and streams the data to the plug-in. The URL must be a fully qualified URL rather than a relative URL, meaning that the URL must begin with http://, ftp://, or file://; the Rexx Plug-in will only run Rexx programs from http, ftp, or file type URLs. The data streamed to the plug-in from the URL specified in the SRC parameter is the Rexx program that is executed by the plug-in, or the WarpIN install file that is installed by the plug-in. The Rexx Plug-in always saves the initial data stream to a disk file on the client. If the data stream is not compressed the Rexx Plug-in executes the file; if the data stream is compressed (as determined by the ZippedFlag parameter) the plug-in unzips the archive file and executes the program file extracted from the archive file.

When non-zipped files are downloaded and saved to disk the file name assigned to the diskfile is a randomly generated name. The files are downloaded to the browser's cache so the browser assigns the file name to fit its caching scheme. When necessary the plug-in will fix the file name extension to make sure the file will execute correctly, but the main part of the file name is not changed. Normally this is not an issue, since most (Rexx) programs don't care, or even know, what their file name is. There are certain, rare occasions when it is important for the name of the file downloaded to the client's hard drive to match the name of the file on the server. For example the WarpIN install script for the Rexx Plug-in uses the WarpIn install file name to turn on or off install options depending on which browsers are on the user's machine. For this situations the MakeNameSame=YES EMBED parameter should be set to force the name on the client to be the same as the name on the server. MakeNameSame=YES is the default for x-warpdoctor/warpin programs, MakeNameSame=NO is the default for all other types of programs.

The Rexx Plug-in parses the URL in the SRC parameter to obtain the default value for the CGIURL variable. The CGIURL variable defines the URL of the CGI program wdPluginCgi.exe on the web server. The wdPluginCgi.exe CGI program is used by the plug-in to implement a number of commands and the plug-in must be able to execute wdPluginCgi.exe in order to function correctly. The plug-in sets the CGIURL value by parsing the domain out of the SRC URL and appending /cgi-bin/wdPluginCgi.exe to the domain. The domain is the part of the URL up to the first forward slash: for example the URL http://www.wonderfulSite.org/bigdir/myRexxProgram.cmd is parsed into http://www.wonderfulSite.org/cgi-bin/wdPluginCgi.exe. If the default value is not correct you must specify the CGIURL parameter with the correct value.

Each EMBED tag read by the browser causes the browser to start a unique plug-in instance to handle that tag. If multiple EMBED tags exist on a single page, or if the user opens multiple pages at the same time that have a EMBED tag, multiple instances of the plug-in will be running concurrently. If more than one of the EMBED tags specifies the same URL in the SRC parameter, multiple copies of the same Rexx program can be running concurrently. You can use the RunExclusive parameter to prohibit multiple copies of the same Rexx program from concurrently running, or to prevent other programs (URLs) from running while the program runs.

The Rexx Plug-in has a limit of 24 concurrent instances that can run at the same time.

Before the Rexx Plug-in starts a Rexx program it checks the security configuration file to see if the program has permission to run on the client. The URL value from the SRC parameter is parsed into a SiteURL that contains the site identity, and that site identity is compared to the approved sites from the security configuration file. If a match is not found the plug-in displays a dialog prompting the user for a determination of how to handle the program: cancel the program, run the program or run the program and add its site to the approved site list. The SiteURL is obtained from the SRC URL by truncating the URL at the last forward slash. For example the SRC URL http://www.wonderfulSite.org/bigdir/myRexxProgram.cmd becomes the SiteURL http://www.wonderfulSite.org/bigdir. If the Rexx program needs to retrieve additional files from the web server it should use the SiteURL to generate the URL of the file it needs to retrieve, for example the line below from a Rexx program

driveIcon = wdCommand('geturl ',wdCommand('query siteurl')||'\drives.bmp', '_file') retrieves the bitmap file drives.bmp from the same location of the Rexx program and puts the downloaded file name into the variable driveicon. Using the SiteURL avoids hardcoding a URL into the Rexx program making the program portable between sites.

Once the file in the SRC URL is downloaded the Rexx Plug-in executes the program. The method used by the Rexx Plug-in to run the program varies depending on the type of Rexx program. The type of the Rexx program is determined by the MIME-Type specified in the TYPE parameter. Some types of Rexx program are run directly by the plug-in as a macro of the plug-in, meaning the plug-in executes the RexxStart() function passing in the name of the downloaded file to the function. Other types of Rexx programs are run by starting a separate session and running the Rexx program in that session. For WarpIN programs ( TYPE=x-warpdoctor/warpin) the plug-in loads the WarpIN DLL and starts WarpIn.exe in a separate session and passes the downloaded file name as an argument.

When the HTML page is destroyed - by the user loading a new URL in the browser window or closing the browser window - the plug-in instance is destroyed and the Rexx program is stopped. (However when the Rexx program finishes the HTML page remains displayed - see the next paragraph.) If the Rexx program is running as a macro of the plug-in, the plug-in issues a HALT instruction for the program; if the program is running in a separate session the plug-in sends a WM_QUIT message to the application (if it is a visual application) and closes the session. The Rexx programmer can control how long the delay is between the plug-in sending the WM_QUIT message and closing the session by setting the ShutDownDelay value. ShutDownDelay is both an EMBED parameter and a plug-in variable. Rexx programs can also get notification of impending termination by opening a message pipe to the plug-in and listening for the shutdown message.

When the Rexx program terminates or finishes running, the HTML page containing the EMBED tag remains displayed. The Rexx program can close the window at the very end of the program with the CloseWindow command, or load a new URL into the window with the GetURL command. The AutoCloseWindow EMBED parameter can also be used to instruct the plug-in to close the window or load a new URL when the program terminates. See Closing Windows below for details.

Plug-in Window

Each type of Rexx application has a window on the HTML page. For visual Rexx applications that run as an applet the application's main window is sized and positioned to fit in the plug-in area allocated on the HTML page. For command line type applications (x-warpdoctor/rexx and x-warpdoctor/cmdrexx) the plug-in creates an output window in the plug-in area for displaying the output from the Rexx program. Command line programs can suppress the output window with the parameter RexxOutputWindow=NO. The plug-in area is still allocated on the page but a multiline edit control is not created in that area for displaying output. To make the area blend into the background of the page set the background color of the plug-in area equal to the background color of the body of the HTML page, with the BGColor parameter. The plug-in area can also be sized small to make it less noticeable, but the size should not be less than 10 pixels for either height or width, or the plug-in will not run on some browsers.

Plug-in Rexx Functions

The Rexx Plug-in provides a number of Rexx functions for the program to communication with the plug-in. The vast majority of Rexx program will utilize just three of those functions:

wdPluginLoad() is called by Rexx programs running in a separate session in order to register the other plug-in Rexx functions. Registering the functions make the function available to be used by the program. Rexx programs that run as a macro of the plug-in do not need to call wdPluginLoad() since the functions are registered automatically by the plug-in before it starts the program. Calling wdPluginLoad() from a Rexx program running as a macro will not cause any harm since wdPluginLoad() is written to recognize what type of program is executing it. This allows a Rexx program to be run either as a macro (x-warpdoctor/rexx, x-warpdoctor/vxrexx) or in a separate session (x-warpdoctor/cmdrexx, x-warpdoctor/vx-rexx) without being rewritten.

Error Handling

All the functions return an error string to indicate a failure or error in the function. The traditional way of programming is to check the return value of each function call for the error string indicator. All error return strings begin with the characters # Error . The Rexx program can simply check if the first character of the return string = '#' to determine if an error has occurred, as shown in the example below

rc = wdParseArgs() if (substr(rc,1,1) = "#") then do say rc exit end

An alternate method of error handling that requires less coding by the Rexx programmer is to instruct the plug-in Rexx functions to throw a syntax error if an error occurs and to pick up the error with a SIGNAL ON Rexx statement, as shown in the code snippet below.

/* Demo Error Handling */ signal on syntax name badjuju wdplugin.errorSwitch = 1 call wdParseArgs say 'version: ' wdCommand('query version') say 'zersion: ' wdCommand('query zersion') say 'here at end' return badJuju: say 'here in error section' say 'errorSwitch: ' wdplugin.errorSwitch say 'errorMessage:' wdplugin.errormessage

The Rexx variable wdPlugin.errorSwitch is used to control the error handling of the functions. When wdPlugin.errorSwitch=0 the functions return errors in the return value of the function - the normal, default behavior. When wdPlugin.errorSwitch=1 and an error in any of the functions causes the function to:

In the above example the line

say 'zersion: ' wdCommand('query zersion') causes an error - there is no query zersion command. Control jumps to the BadJuju: label where the error message is displayed by the say 'errorMessage:' wdplugin.errormessage

You can alter the error handling at any point in the Rexx program by changing the value of the wdPlugin.errorSwitch variable.

Manipulating Browser Windows

The Rexx Plug-in provides a number of commands for opening and closing browser windows. Since the Netscape Plug-in API provides a very limited feature set for manipulating browser windows the Rexx Plug-in uses JavaScript to do the window manipulation. However the Rexx Plug-in does not use the Netscape Live Connect feature for calling JavaScript from the plug-in, but rather implements its own interface. The Live Connect feature is not implemented in many other browsers and is not supported in Mozilla based versions of Netscape.

The Rexx Plug-in implements its JavaScript interface by creating a file containing an HTML page with the needed JavaScript code on the page, and opening the page in a browser window. The browser executes the JavaScript code as it is reading the page. The browser window is then immediately closed, since it is no longer needed. The advantage to this method is that it works with all browsers on all platforms. The disadvantage is that a browser window flashes on the screen while the browser is reading the HTML page. The flashing can be eliminated by specifying to the plug-in a browser window to use for displaying/reading the temporary HTML pages with the WorkWindowName EMBED parameter. The browser window so specified should already exist and be sized very small so that the user cannot see the window. The best way to do this is to use frames, with one frame sized very small (.25 pixels high for example) used as the "work window", and the other frame sized to fill the rest of the window used as the main display window. The example below shows how to do this.

<html>
<FRAMESET rows="*,.25" border=0 >
<FRAME NAME="cmd" SRC="plugin_cmdProcessor.html">
<FRAME NAME="workwincmd" SRC="javascript:'<html><body></body></html>'">
</FRAMESET>
</html>
The line
<FRAMESET rows="*,.25" border=0 >
creates vertical frameset with two frames, one above the other. Each frame spans the entire width of the page. The rows="*,.25" sizes the bottom frame .25 pixels high, and th top frame to occupy the remaining area of the browser window. The line
<FRAME NAME="cmd" SRC="plugin_cmdProcessor.html">
loads the file plugin_cmdProcessor.html into the top frame and names that frame/window cmd. The line
<FRAME NAME="workwincmd" SRC="javascript:'<html><body></body></html>'">
creates a blank document in the bottom frame/window and names that frame/window <b>workwincmd</b>. The plugin_cmdProcessor.html file, shown below, then sets the <a href='plugindoc_embedParms.html#WORKWINDOWNAME'>WorkWindowName</a> to <b>workwincmd</b> so that the plug-in will use the bottom frame when creating and displaying HTML pages with JavaScript.
<html>
<head>
<body bgcolor='white'>
<br>
<h3>WD Plug-in Command Processor</h3>
<embed
 type='x-warpdoctor/drrexx'
 height=550
 width=750
 src='http://www.warpdoctor.org/plugin_CmdProcessor.res'
 workwindowname=workwincmd
  >
</embed>
</body>
<html>

The two examples above create a window as shown below. Notice the very small figure at the lower right corner of the window. This is the scroll bars that Netscape is attempting to display for the lower window frame - the "work window".


Main Window with a Hidden Lower Work Window

Opening Windows

The Rexx Plug-in provides 6 commands that open new browser windows or change the contents displayed in an already open window. The commands are

  1. OpenWindow - opens a new, blank browser window. Arguments specify the name for the window, size and location of the window, etc. Once the window is created it can be used as the target window for the other commands listed below.
  2. GetURL - loads a URL into a new or existing window.
  3. OpenURL - combines the OpenWindow and GetURL commands, i.e. can load a URL into a window while also specifying the window size, location, name, etc in arguments to the command.
  4. CreatePage - creates an HTML page from a text argument, displaying that page in an existing or new window.
  5. PostURL - executes a CGI program, the output from the CGI program can be routed to a new or already existing window.
  6. JavaScript - JavaScript code can be used to create a new browser window, specifically the JavaScript window.open() method can create a new browser window.
To specify an already open window as a target to the CreatePage, GetURL, or PostURL commands you must know the name of the window. The only way to know the name of the window is to create the window in HTML using a FRAME tag, or with JavaScript using the window.open() method. The commands OpenWindow andOpenURL provide a way to create a window and specify the name of the window, allowing you to use that window as a target of other commands.

Closing Windows

The Rexx program knows the "name" of a browser window CloseWindow command can be used to close that window. CloseWindow can also be used to close the current window, but doing so will destroy the running plug-in instance and terminate the Rexx program. Likewise the GetURL command can be used to load a different page (a URL) into another window, providing the program knows the window name, or to load a different page into the current window, which will also destroy the running plug-in instance.

Alternately the EMBED parameter AutoCloseWindow can be used to instruct the plug-in to close the browser window, load a different URL, or display a text message in the window when the Rexx program is terminates. If AutoCloseWindow is set to YES the current window is closed when the Rexx program terminates. If set to a URL the page in the current window is replaced with the URL when the program terminates. If set to any other value, the value is considered a text string and the page in the current window is replaced with the text string. The text string can include an argument to specify a number of seconds to to leave the window open before automatically closing the window. Some examples are shown below.

autoCloseWindow="YES"
autoCloseWindow="http://www.warpdoctor.org/newPage.html"
autoCloseWindow="<p><p><p><center><h1>Done with Install"
autoCloseWindow="#10#<p><p><p><center><h1>Done with Install"

The second to the last example above replaces the current page with the text Done with Install when the program terminates. The last example replaces the current page with the same text but after displaying the text for 10 seconds the browser window is closed.

Downloading Files

There are two protocols that can be used for transferring files from a sever to the client: HTTP and FTP. Of the two, FTP is the most reliable for binary files. Our experience has been that browsers mangle binary files when transferring with HTTP unless the browser is aware that the file is a binary file. (This may not be true on UNIX but it is true on OS/2 and Windows.)

The Rexx Plug-in provides two commands for transferring files from a server to the client. GetURL can transfer using either HTTP or FTP. GetFile transfers only using HTTP. However GetFile is capable of telling the browser that the file being transferred is binary; with GetURL there is no reliable way of insuring that binary files transferred with HTTP are not mangled.

GetURL

The GetURL command can be used to download a file using either FTP or HTTP. The syntax of the command is

getUrl    url [target] [NOWAIT | fileName] 

If an HTTP type URL is specified as the url argument the file is transferred using HTTP. If a FTP URL is specified as the url argument the file is transferred using FTP.

When downloading a file the target argument must be _file. This tells the command to route the data stream to a disk file rather than to a window. If the fileName argument is not specified the plug-in will create a random file name automatically; if a file name is specified that name will be used for the disk file that is created. In either case if the command is successful the name of the disk file will be the return value.

When using HTTP do download binary files the transfer is reliable with zipped data. For non-zipped binary data we have observed mangled data using Opera, Netscape and Mozilla. For complete reliability with non-zipped binary data we advise using the FTP protocol, even though that involves setting up an FTP server to handle the requests. Alternately for non-zipped binary data you can use the GetFile command for reliable HTTP transfers.

GetFile

The GetFile command downloads files using the HTTP protocol. The syntax is

getfile  url  target 
where url is an HTTP URL only, target is the name the file will have on disk at the client.

GetFile requires the CGI program wdPluginCgi.exe on the web server. (The CGIURL variable/parameter must be set correctly for this command to work. If the default value set by the plug-in is not correct the Rexx program must specify the correct value in the EMBED parameter.) The CGI program compresses the file using gzip and sends the file with a Content-Encoding: gzip header. This notifies the browser that the file contains binary data. With Opera and Mozilla based browsers the contents of the data stream (the file) are decompressed automatically by the browser; for Netscape browsers the plug-in decompresses the file before returning from the command.

Uploading Files

The only reliable protocol for uploading binary files to a server is FTP. The HTTP protocol cannot be reliably used with Netscape browsers on the OS/2 or Windows platform. The Rexx Plug-in provides two commands for uploading a file to a FTP server: CopyFileToServer and MoveFileToServer. Both use the FTP protocol and require an FTP server at the server end. The different between the two is that the CopyFileToServer leaves the original file on the client, where the MoveFileToServer command removes the file from the client.

Unfortunately both CopyFileToServer and MoveFileToServer only work on Netscape browsers. Mozilla based browsers, including IBM Web Browser, and Opera browsers do not handle the upload correctly. The commands appear to work but the file never makes it to the server. Therefor if your program is running in one of those browsers you need to use FTP directly to upload files to a server. Luckily the Rexx/FTP utility package is complete and easy to use. You can also be fairly certain that the package on in the client machine since the client is using TCP/IP to connect to the web server. The example below shows a small program that uploads a file using the Rexx/FTP package.

/*  rexx ftp upload */
call wdParseArgs
rc = rxFuncAdd('FTPLoadFuncs','rxFtp','FtpLoadFuncs')
rc = FtpLoadFuncs()
rc = ftpsetuser('www.hometown.org','uploadUser','uploadPassword');
rc = ftpput("f:\temp\a.cmd",a.cmd,"BINARY");
exit

CopyFileToServer

The syntax is.
CopyFileToServer  url  filename 

The CopyFileToServer command copies the source file to a temporary file name, and uploads the temporary file to the FTP server. The temporary file name is made up of a randomly generated name plus the user's IP address as it appears to the web server. This helps to insure that the file name will be unique when it gets to the FTP server. The command returns when the file transfer is complete. The return value is the file name used for the transfer, i.e. the name of the file on the FTP server.

If you want to specify what the name of the file will be on the FTP server use the MoveFileToServer command. If needed you can use the CopyFile command to create a copy of the file on the client before it is "moved", so that the original will not be destroyed.

MoveFileToServer

The syntax of the command is
MoveFileToServer  url  filename 

The MoveFileToServer command moves the file from the client to the FTP server. When the command returns the file is no longer on the client. The name of the file on the FTP server is the same as the name of the file on the client.

Local File Operations

The Rexx Plug-in provides a number of commands for working with or querying local files and directories. Some of these actions could also be accomplished in a Rexx program by the program passing a command to the OS/2 Command Processor, which is the default "environment" for unrecognized Rexx commands. The advantage to using the plug-in command is that error messages are returned in the return value rather than displayed using STDOUT, as they are when using commands passed to the OS/2 Command Processor.

The commands AppendFile, CopyFile, DeleteFile, and MoveFile are all interfaces to operating system functions. If the command is successful the command returns a zero as the return value. If the command is not successful the command returns a string starting with # Error - rc message where rc is the operating system return code and message is that return code translated into text. The OS return code is always the fourth word in the return string; you can use the Rexx word() function to retrieve that return value, if needed. Please note that while the return code will have a different numeric value on different operating systems for the same type of error, a value of zero will always be returned for success regardless of the operating system.

Installing WarpIN Archives

The Rexx Plug-in can install WarpIN type install packages with a single click by the user of a link on an HTML page. This capability, coupled with the Rexx Plug-in's interface to FTP for downloading, enables the Rexx Plug-in to reliably and successfully download and install WarpIN install packages. To use this feature of the plug-in the web page designer must take certain design steps to enable the plug-in operation.

The Rexx Plug-in treats *.WPI type WarpIN install packages just the same as it does Rexx programs, except that instead of executing the Rexx program the plug-in executes WarpIN on the client machine, passing the name of the downloaded install package. To use the WarpIN install feature:

  1. The HTML page must have an EMBED tag for the WarpIN install file.
  2. The EMBED tag must specify a Type=x-warpdoctor/warpin or Type=x-warpdoctor/generic parameter. The x-warpdoctor/warpin MIME-Type is used for *.WPI type WarpIN packages; the x-warpdoctor/generic MIME-Type is used for *.EXE type "self-contained" WarpIN install packages, i.e. where WarpIN executable code is include in the install file so that it can be installed on machines that do not already have WarpIN.
  3. The EMBED tag SRC parameter must be a URL that contains the *.WPI or *.EXE install file. It is strongly advised to use a FTP URL for *.WPI files to insure that the file is downloaded without being mangled. FTP also works well for *.EXE type files, although those are downloaded reliably by browsers using a HTTP URL.
  4. Set the parameters Height=10 and Width=10 to minimize the size of the plug-in area on the page.

Six additional EMBED parameters are recommended for WarpIN installations, but not required:

The example below shows how to run the WarpIN plug-in instance in a separate window. The first figure is the HTML page that runs the WarpIN install - plugin_warpin1.html

<html>
<head>
<BODY bgcolor="white">
<br>
<h3>WarpIN Install Demo</h3>
<p><b>Do not close this window until the install is complete</b>
<br>
<embed
 type='x-warpdoctor/warpin'
 height=10
 width=10
 src='ftp://www.warpdoctor.org/wdRexxIn.wpi'
 title='WarpIN Demo Install - Installs the Rexx Plug-in"
 bgcolor='white'
 eraseOnExit=YES
 saveprompt=yes
 autoCloseWindow=yes
 runExclusive='ftp://www.warpdoctor.org/wdRexxIn.exe ftp://www.warpdoctor.org/wdRexxIn.wpi' >
</embed>
</body>
<html>

The next figure is the HTML that provides the link the user clicks on to start the install. When the link is clicked a second browser window is opened with plugin_warpin1.html loaded in the window.

<html>
<script>
function openWin()
{
    window.open('plugin_warpin1.html','instWin','outerheight=300,outerwidt h=500')
}
</script>
<body>
Click <a href="javascript:openWin()">here</a>
to install the Rexx Plug-in
</body>
</html>

The figure below shows the window with the link.


When you click on the link, this is the window that is opened - the window with page plugin_warpin1.html.

The default setting of MakeNameSame=YES for x-warpdoctor/rexx programs allows you to write self-referencing WarpIN install scripts, which would not be possible if the name of the install file on the client was not known to the script. The code snippet below is from the WarpIN install script for the Rexx Plug-in. The install script checks if the IBM Web Browser is installed on the client machine. If it is, a "package" is displayed on the WarpIN screen for installing the plug-in for that browser. If the browser is not installed, the "package" is not shown on the WarpIn screen. The install script relies on the name of the install file being wdRexxin.wpi in order to work.

<REXX name="checkForIBMWEB"> call RxFuncAdd 'SysIni','RexxUtil','SysIni' netPath = sysini("USER","Netscape","6.0") if (netpath = 'ERROR:') then return 'NoInstal.wpi' else return 'wdRexxin.wpi' </REXX> <PCK INDEX=3 PACKAGEID="WarpDoctor\Rexx Plug-in\IBM Web Browser Plug-in DLL\0\99" EXTERNAL="=("checkForIBMWEB")" TARGET="=("IbmWebPath")" SELECT FIXED TITLE="Plug-in DLL for the IBM Web Browser" >Plug-in DLL for the IBM Web Browser</PCK>

The EXTERNAL keyword of the package 3 (PCK INDEX=3) checks if the file name on the right side of the equal sign exists. It if exists the package is shown on the screen. If the file doesn't exist the package is not shown. The EXTERNAL keyword is using a facility of WarpIN where the return value from a Rexx script can be used in place of a value. The Rexx script checks if the IBM Web Browser has an entry in the OS2USER.INI file. If it does the Rexx script returns the value wdRexxIn.wpi, which is the name of the currently running install program. If there is no entry in OS2USER.INI for the browser the Rexx script returns a name that is known to not exist - NoInstall.wpi.

Self-contained WarpIN install files, i.e. executable files with WarpIN bundled in the install file, must be specified as type=x-warpdoctor/generic, and the SRC parameter changed to the executable install file. All the other parameters should stay the same. The x-warpdoctor/generic MIME-Type will run any executable file, including self-contained executable WarpIN install files. The example below shows the EMBED tag for the self-contained version of the Rexx Plug-in install file.

<embed type='x-warpdoctor/generic' height=10 width=10 src='ftp://www.warpdoctor.org/wdRexxIn.exe' title='WarpIN Demo Install - Installs the Rexx Plug-in" bgcolor='white' eraseOnExit=YES saveprompt=yes autoCloseWindow=yes runExclusive='ftp://www.warpdoctor.org/wdRexxIn.exe ftp://www.warpdoctor.org/wdRexxIn.wpi' > </embed>

Detecting the Plug-in

Using the plug-in makes installing packages easier for the user, but makes life more difficult for the web administrator. The web administrator cannot simply write an EMBED tag for the install package, because then users without the plug-in would not be able to download the install file. If the web administrator does not write the EMBED tag the plug-in will never get called. The answer for is to include a little JavaScript routine that detects the presence of the plug-in: if the plug-in is installed the page with the EMBED tag is called, if the plug-in does not exist the install file is simply downloaded. The example modifies our previous example to include detection of the plug-in. If the plug-in is detected (foundFlag=1) another window is opened that runs the plug-in instance, If foundFlag=0 the file is simply downloaded using FTP.

<html>
<script>
function openWin()
{
    var numPlugins = navigator.plugins.length;
    var foundFlag = 0
    for (var i = 0; i < numPlugins; i++)
    {
        aa = navigator.plugins[i].filename.toUpperCase().split('\\');
        if (aa[aa.length-1]  == 'NPWRPDOC.DLL')  foundFlag = 1
    }
    if (foundFlag==1)  window.open('plugin_warpin1.html','instWin','outerheight=300,outerwidth=500')
    else           window.location.href='ftp://www.warpdoctor.org/wdRexxIn.wpi' 
}
</script>
<body>
Click <a href="javascript:openWin()">here</a>
to install the Rexx Plug-in
</body>
</html>

Running Generic Executables

The Rexx Plug-in includes the MIME-Type x-warpdoctor/generic which is designed for running three types of executables

  1. Executables (programs) that are unconnected and unrelated to the plug-in. These types of programs run in their own window and do not use any of the Rexx Plug-in facilities. These can be any type of program that is small enough to be downloaded before it is run.
  2. Rexx programs that are packaged as executables. These Rexx programs run just like the Rexx MIME-Types (drrexx, vxrexx, cmdrexx, etc.) except they are packaged as an executable file. They may be packaged as executables because that is the only way the application builder makes the program, or because the author is concerned about security and copyright issues, or to simplify distribution by eliminating runs-times.
  3. Executable programs that use the Rexx Plug-in "API". These programs are written in a language other than Rexx but want to issue plug-in commands and use the other features of the Rexx Plug-in.

All three of these types of programs use the type=x-warpdoctor/generic parameter in the EMBED tag. All three are executed by the plug-in in a separate session. The difference between the three types of programs are the arguments passed to the program when it is started by the plug-in, and actions taken by the program to communicate with the plug-in.

What arguments are passed to the executable program and how the arguments are passed are determined by the GenericArgsFlag parameter of the EMBED tag.

Applications not written in Rexx can still use the full facilities of the Rexx Plug-in because all communication between the plug-in and Rexx programs running in a separate session is handled through named pipes. (Communication between the plug-in and a Rexx program running as a macro of the plug-in is handled differently and does not use named pipes.) The plug-in was designed this way to allow non-Rexx programs to communication with the plug-in in hopes that some vendors (say for example Sundial Systems) would convert their applications (say for example Mesa/2) to run as applets in the plug-in.

Each Rexx Plug-in instance creates a unique named pipe with a name of \PIPE\WDPLUGIN\instanceHandle. The pipe is a message based pipe with a buffer size of 64K. When the Rexx program calls the function wdParseArgs() the client end of the pipe is opened with a DosOpen() command. Each time wdCommand() is called the arguments are concatenated together (separated by a space) and written to to the pipe with a DosWrite(). The pipe is then read with with a DosRead() and the result string from the pipe is the return value for the function. Every command (DosWrite() ) has a return value (DosRead() ). Everything that passes through the pipe is a string value, just as all values stored in Rexx variables are string values.

This means any program that can work with character strings (with or without a terminating NULL) and can call DosRead() and DosWrite() can sends commands to the Rexx Plug-in. Strings sent to the plug-in do not need a terminating null character; result strings sent by the plug-in always have a terminating null character.

Any program that can send commands to the plug-in can also run as an applet of the plug-in, provided the program meets the same requirements for running as an applet that Rexx programs do, namely: all controls must be removed from the main window of the program that allow the user to size, move, close, minimize or maximize the main window. The program must initially size and position its main window to fit the plug-in from arguments passed to the program when it is started. And the program must use one of two Link commands to establish a parent-child relationship between the program and the plug-in window. The Link findHandle command causes the plug-in search for a window appearing on the desktop with a PID that matches the PID of the session started to run the program. This is the same method used to link DrRexx applications to the plug-in. With Link Handle handle command the program supplies the window handle of the main window to the plug-in as an argument of the command. The handle value must be a in base 10 ASCII format.

Executing CGI Programs on the Server

A Common Gateway Interface (CGI) program is a program on the web server that is called by the web server to perform processing beyond what the web server can do. Rexx programs can use the PostURL command to execute CGI programs on the web server and pass parameters to those programs.

Background

A CGI program is called when the user

The web server passes parameters to the CGI program when it calls the program. The parameters passed in the first example are everything past the question mark, which separates the program name from the parameters. The parameter passed in the second example is the name and value for the input field input1; forms pass a parameter for each input field on the form.

The parameters are passed by the web server to the CGI program using three different methods:

  1. For ISINDEX the parameters are passed as command line arguments to the CGI program.
  2. For HTML forms with a parameter of METHOD=GET, the parameters are put into an environment variable named QUERY_STRING by the web server before it calls the CGI program. The CGI program retrieves the parameters from QUERY_STRING.
  3. For HTML forms with a parameter of METHOD=POST, the parameters are passed to the CGI program by the webs server using STAIN. The CGI program reads STAIN to get the parameters.

The environmental variable REQUEST_METHOD is set by the web server before it calls the CGI program to a value of POST or GET to indicate to the program which method it is using to pass parameters to the program.

The CGI program communicates with the browser by sending output to STDOUT. The web server picks up the CGI program's output and routes it to the browser that caused the program to be executed, when the CGI program finishes executing. Before routing the output to the browser, the web server first examines the output and applies HTTP headers to the output, unless instructed not to.

The Rexx Plug-in provides a way of calling CGI programs and passing parameters with the PostURL command. This command executes a CGI program on the web server using the POST method of passing parameters.

PostURL

The PostURL command is the only plug-in command that is broken into "subcommands", the subcommand being the first argument to PostURL. The four subcommands:

The TARGET and VAR subcommands can be issued in any order, and other plug-in commands can be issued between the URL and POST subcommands.

The PostURL command enables cooperative processing between the Rexx program running in the plug-in and CGI programs on the web server. The most common way for this to take place is for the Rexx program to direct the output of the CGI program to a file and read the file to process the data returned by the program. Alternately, for smaller results (64K or less) the Rexx program can direct the output from the CGI program to the return value of the POST subcommand. This is the method used by the plug-in to ascertain the user's IP address on the web server. The example below emulates in Rexx how the plug-in gets the remote IP address for the Query IPAddress command.

/* rexx test */ call wdParseArgs wdplugin.errorswitch = 1 signal on syntax name catchError call wdcommand 'posturl url http://www.warpdoctor.org/cgi-bin/wdpluginCgi.exe' call wdcommand 'posturl var action=69' call wdcommand 'posturl target _result' rc = wdcommand('posturl post') say 'rc: ' rc exit catchError: say wdplugin.errorMessage exit

The above Rexx program produces the output below.

rc: REMOTE_ADDR:192.168.32.102

The CGI program wdPluginCgi looks for an variable called action and performs some action based on the value of that variable. The C++ code snippet below show the section that handles the IP Address request. REMOTE_ADDR is an environment variable set by the web browser to the IP address of the requester before executing a CGI program.

main(int argc, char *argv[]) { HtmlOutput htmlOutput; int rn=0; try { // get html or command line paremeters and process them // This class calls parseFunc (i.e. setInputValue() ) for each variable it finds CgiInput cgiObject(&htmlOutput, argc, argv, parseFunc); switch (action) { ... ... case 69: // Remote IP Address htmlOutput.setHtmlEndFlag(); // suppress the automatic output of html ending tags cout << "Content-type: plain/text" << endl; cout << endl; cout << "REMOTE_ADDR:" << getenv("REMOTE_ADDR"); break; ... ... } } }

Rexx and JavaScript

The Rexx Plug-in provides a limited interface between JavaScript and Rexx. The interface allows a Rexx program to execute JavaScript commands and functions, a JavaScript routine to start a Rexx program, a Rexx program to set JavaScript variables (in Netscape and Mozilla based browsers), and a JavaScript routine to set plug-in variables that a Rexx program can access.

This chapter is divided into two sections: JavaScript to Rexx features, and Rexx to JavaScript features

JavaScript to Rexx

JavaScript to Rexx interface breaks down into two basic scenarios:

  1. Starting a new Rexx program and passing values/parameters to the Rexx program.
  2. Passing values/parameters to an already running Rexx program.

Each scenario is covered is its own section below.

When we say passing values/parameters from JavaScript to Rexx we are refering to both JavaScript variables and HTML "fields" defined in an HTML FORM tag. JavaScript variables are those that are defined within <SCRIPT> </SCRIPT> tags, as shown below

<html>
<script>
var rundate
var tempStr = ''
</script>

runDate and tempStr are JavaScript variables. HTML "fields" are defined between the <FORM> </FORM> tags, and would be called window "controls" in OS/2 and Windows programming, or widgets in the Unix world. The example below shows two HTML "fields": birthdate and lastname. The field/input control birthdate is visible on the screen, the field lastname is invisible to the user.

<html>
<body>
<form>
Enter your birth date: <input type='text' name='birthdate'>
<input type='hidden' name='lastname' value='smith'>
</form>
</body>
</html>

Starting a New Rexx Program

A JavaScript routine can start a new Rexx program by writing out a EMBED tag and its parameters to an HTML page. (New program here means a Rexx program that is not already running the plug-in.) Parameters or values are passed to the Rexx program as user defined parameters of the EMBED. When the page is finished being created (written to) by JavaScript it is read by the browser and the Rexx program specified in the Type and Src parameters is started.

The Rexx program sees the parameters two ways:

  1. All parameters can be queried by name or number with the Query ParmValue command. Parameters are passed to the Rexx program in the same order they appear - left to right, top to bottom - in the EMBED tag. say 'parm 1 name is' wdCommand('query parmName 1') say 'parm 1 value is' wdCommand('query parmValue 1') say 'birthdate parameter is ' wdCommand('query parmValue birthdate')
  2. User defined parameters are placed into the Rexx stem variable wdEmbed. stem variable when the Rexx plug-in environment is initialized by the Rexx program. The user defined parameters can be found by number or name in the wdEmbed. variable, as shown below. say 'parm 1 name is' wdEmbed.name.1 say 'parm 1 value is' wdEmbed.value.1 say 'birthdate parameter is ' wdEmbed.birthdate

Parameters are not case sensitive when queried with the Query ParmValue command or when set into the wdEmbed. stem variable.

The JavaScript commands to create an EMBED tag on a new page can be somewhat complex, depending on where the values are coming from for the parameters of the EMBED tag. The example below shows a JavaScript function that creates an HTML page containing an EMBED tag. The page is created in a work window so it is essentially invisible. The EMBED tag parameters come from HTML fields, JavaScript variables and literal text.

function passValues()
{
    parent.workWin.document.write("<html><body>")
    parent.workWin.document.write("<embed")
    parent.workWin.document.write(" type='x-warpdoctor/rexx'")
    parent.workWin.document.write(" src='http://192.168.32.100/doThis.rex'")
    parent.workWin.document.write("  libpath='",document.sform.libpathList[document.sform.libpathList.selectedIndex].text,"'")
    parent.workWin.document.write("  path='",document.sform.pathList[document.sform.pathList.selectedIndex].text,"'")
    parent.workWin.document.write("  width=",xwidth);
    parent.workWin.document.write("  height=",xheight);
    parent.workWin.document.write("  rexxOutputWindow=NO");
    parent.workWin.document.write("  >")
    parent.workWin.document.write("</embed></body></html>")
}

An alternative to hand-coding the JavaScript needed to start a Rexx program and pass values to the program, is to use the plugin_form2embed.html file or the form2embed() JavaScript function provided in the WarpDoctor web site. Using either the HTML file or the JavaScript function requires a small amount of JavaScript in your HTML page, but the JavaScript is very simple compared with writing your own routine to create the EMBED tag. The example below shows a very simple, one field, HTML form and the JavaScript needed to use the plugin_form2embed.html file, which appears in red.

<html>
<head>
</head>
<body>
<form name='form1'>
Mother's name: <input type='text' name='mom'>
<br>
<input type='button' value='Run Rexx' onClick='makeEmbed()'>
</form>
</body>
<script>
var type = 'x-warpdoctor/rexx'
var src = 'http://www.warpdoctor.org/plugin_form2rexx.rex'
var width = 400
var height = 600
var title='Test Form 2 Rexx'
function makeEmbed()
{   
    win = window.open("plugin_form2embed.html","win1")
}
</script>
</html>

The way the plugin_form2embed.html file works is that it looks for JavaScript variables that match any HTML Standard and Plug-in Standard parameters and output those in the EMBED. It then looks for HTML "fields" in the form