Introduction to object manipulation in REXX
This month's column is my initial contribution to OS/2 Magazine and I hope you will find it both informative and interesting. As the author and publisher of REXX Reference Summary Handbook, I have the privilege of being able to include segments of that book where it is appropriate.
An entire book could be written about the OS/2 Workplace Shell and managing its objects. However, I will try to capsulize both the creation and the manipulation of primarily two classes of Workplace Shell objects with OS/2 REXX - WPFolder and WPProgram objects.
If you have installed any applications on OS/2 2.x, there is a good chance that you have run a .CMD file that created a new folder, either on your Desktop or somewhere else in your system. The installation program then included various objects into the newly created folder. This was accomplished with the REXX functions described below.
Three WPS-related functions exist in the REXXUTIL API (an application program interface), which is installed on OS/2 when you select REXX from the Setup and Installation screen. When you install REXX, be sure to select REXX Information from the More box on the Documentation selection screen. In the event that the REXX documentation is not available on your system, you can use Selective Install to add rexx.inf to your Information folder.
I will show you how to use three functions: SysCreateObject(), SysSetObjectData() and SysDestroyObject(). As the name of each of these functions implies, they are used to create a new WPS object, modify an existing object, or to remove an existing object from your system, respectively.
Workplace Shell objects generally are either real objects (a file or a directory) or abstract objects (desktop objects). These objects may be referenced with the three REXXUTIL functions with either their full file-system name (a fancy term that simply means the drive letter, path name and file and extension of the real object) or an object ID.
An object ID is any unique string that is preceded by a less than character (<) and followed by a greater than character (>). Object IDs are case sensitive (<Test> is not the same as <TEST>). Object IDs are assigned to objects when they are created and remain with that object until it is removed. An object ID may be used as the location value when an object is created. For example, if you create a folder with an object ID of <MYFOLDER>, then that folder may be used as the location for program objects by specifying its object ID.
Generally, it is a good idea to construct an object ID from characters that occur on your keyboard (within the range of 032 to 126 - '20'x to '7E'x). Object IDs can be assigned to real objects as well, and it is a good idea to assign an object ID to all WPS objects you create, unless the object is a template. Assigning an object ID to a template would create a conflict in the system as more than one object with the same object ID would then exist.
Each object belongs to a class. The majority of classes that users will concern themselves with are those classes defined by OS/2 as standard classes. These classes can be listed using the SysQueryClassList() function in REXXUTIL. This function returns a compound, or stem, variable of all of the classes that have been registered in your system. In addition, the name of the DLL (dynamic link library) module that processes objects of each respective class is shown.
New classes can be registered (identified to the system) with the SysRegisterObjectClass() function.
For your convenience, I have included the definition of the SysCreateObject(), SysSetObjectData() and SysDestroyObject() functions from the REXX Reference Summary Handbook:
- SysCreateObject( class_name, title, location[, setup_string][, option] )
- Returns 1 if a new object class was created; otherwise, returns 0.
Class_name is the name of the WPS class of which the object is a member and title is the new object's title. A new line character, '0A'x, may be included in title. The occurrence of the escape character ^ ('5E'x) also causes a new line to be created; however, 2nd and subsequent escape characters used for this purpose appear to be ignored. Location can be either an object ID (any unique string preceded with a '<' and terminated with a '>') or a full file system path. Setup_string optionally must contain a WinCreateObject string which is comprised of a series of "key name=value" pairs that change the behavior of the object. "Key names" are separated by semicolons and "values" are separated by commas. Note: If a value includes a semicolon (; - '3B'x) or a comma (, - '2C'x), it must be "escaped" by preceding it with a caret (^ - '5E'x). Option is a string which indicates the action to be taken if the object class already exists and may be: FAIL, REPLACE or UPDATE.
- SysDestroyObject( object_name )
- Returns the resultant code from WinDestroyData: 1 if object_name is destroyed; otherwise, returns 0. Object_name is either the object's ID (the unique string preceded with a '<' and terminated with a '>') assigned to the object when it was created or the full file system name of the object to be destroyed. Some of the predefined object IDs are shown in Table 1.
- SysSetObjectData( object_name, setup_string )
- Returns the resultant code from WinSetObjectData: 1 if object_name is successfully updated; otherwise, returns 0.
Object_name can be a WPS object ID (the unique string preceded with a '<' and terminated with a '>') assigned to the object when it was created (e.g. <WP_DESKTOP>) or a fully qualified file name. Setup_string must contain a WinCreateObject string which is comprised of a series of "key name=value" pairs that change the behavior of the object. "Key names" are separated by semicolons and "values" are separated by commas.
The biggest mystery to creating WPS objects with the SysCreateObject() function lies in the "key name=value" pairs used in the setup string parameter.
Much of that mystery was eliminated by an excellent article along with working examples published by Mike Lamb of IBM's ISSC-MHV Solution Center. This information can be found on CompuServe in CIS:OS2USER, Library 5 as crtobj.txt and on most OS/2 BBS systems under either the same file name or as crtobj.zip. (Information on how to create WPS objects using REXX)
Though Lamb's information has not been updated since July 1993, it can serve as a starting point and is the best free source for the parameters used in creating WPS objects with SysCreateObject(). The most complete and accurate information for the setup string "key name=value" pairs available is contained in the REXX Reference Summary Handbook.
Another excellent source of information about objects that already exist on your system will be found in the *.rc files in the \os2 subdirectory on your OS/2 boot drive. Do a dir ?:\os2\*.rc (where ? represents your OS/2 drive) to see a list of the .rc files. Specifically, if you look at the ?:\os2\ini.rc file you will see the following (lines have been split for publication):
STRINGTABLE REPLACEMODE BEGIN "PM_InstallObject" "Nowhere;WPFolder;?:\" "OBJECTID=<WP_NOWHERE>" "PM_InstallObject" "View;WPProgram;<WP_NOWHERE>;UPDATE" "EXENAME=?:\OS2\VIEW.EXE;ASSOCFILTER=*.INF; NOTVISIBLE=YES;OBJECTID=<WP_VIEWINF>" "PM_InstallObject" "Templates;WPTemplates;<WP_DESKTOP>" "HELPPANEL=15680;NODELETE=YES;ICONPOS=8 8; OBJECTID=<WP_TEMPS>" . . . END
These "PM_InstallObject" lines are used by the system to create the standard system objects.
WPS objects fall into a hierarchy structure that results in objects subordinate to a class inheriting the appropriate characteristics of the classes higher up in its structure. Therefore, some of the parameters used with these functions are appropriate for all of the kinds of objects I refer to in this article (WPFolder and WPProgram). Others apply to either but not both.
I have included some working examples here that demonstrate some of the different uses of these functions. [#Listing 1 Listing 1] contains a REXX program that will create a new folder on your desktop. Before I explain the use of the SysCreateObject() function, I would like to make a couple of comments about the style of the code used in my examples because it may be a little different from what you are accustomed to seeing.
During my 33 years in the computer industry, I have developed a style for each language that I write code for. My style is predicated on 2 things: neatness makes for readability, and I am lazy when it comes to changing code. You will notice that, for the most part, I split parameters to a separate line and isolate them so that lines can be moved without affecting the line above or below the moved line.
Also, with REXX source statements, I generally use explicit concatenation (two vertical bars) instead of abuttal concatenation (placing eligible strings together without an intervening space), unless the latter is actually more clear and meaningful in intent.
The folder created in Listing 1 will appear on your desktop. Its icon will be positioned in the horizontal center of the desktop and up 90 percent of the height of the desktop from the bottom. That position was set by the ICONPOS=50,90; parameter.
The folder's object ID is the same as its title, only the "<" and ">" characters surround it. Although the background has been set to the blocks.bmp image, because of a bug in OS/2, the background will not actually appear in the new folder unless its notebook is opened and the background tab is selected. This will cause the correct background image to be shown.
A couple of the most frequently asked questions by REXX programmers after they find the BACKGROUND= setting are: "Can the scaled and tiled options be set with these functions?" and "How can I set Always maintain sort order for a folder?". Unfortunately, the answer to the first question is no. The Always maintain... option can only be set using SOM methods and, to set this option with a REXX program you need the assistance of a commercial program called Deskman/2 from Development Technologies.
Finally, the folder has been opened on the desktop to its ICON view by using the call to the SysSetObjectData() function at the end of the program. The OPEN=ICON; parameter could have been included in the SysCreateObject() setup string just as well; however, its separate use shows how any object can be opened. Generally you specify OPEN=DEFAULT; unless you want to open a specific view. The options for the views are DEFAULT, SETTINGS, ICON, TREE, and DETAILS when any of these options are valid for the referenced object.
I included the NOMOVE=YES; value to show one of the various style settings. The style settings include: NOCOPY, NODELETE, NODRAG, NODROP, NOLINK, NOMOVE, NOPRINT, NORENAME, NOSHADOW, and NOTVISIBLE. By the way, NOMOVE doesn't mean that you can not move the object. It means that if you try to move the object from its present container - in this case, the desktop - to another container (some other folder), it will result in the equivalent of a copy. The original will remain on the desktop but a copy will be placed in the container where it is dropped.
/* 9409-001.CMD - Create WPS WPFolder Object */ call RxFuncAdd 'SysLoadFuncs', 'REXXUTIL', 'SysLoadFuncs' call SysLoadFuncs wpf_title = 'OS/2 Magazine^Test Folder' wpf_class = 'WPFolder' wpf_location = '<WP_DESKTOP>' wpf_setup =, 'OBJECTID=<' || wpf_title || '>;' ||, 'ICONPOS=50,90;' ||, 'NOMOVE=YES;' ||, 'BACKGROUND=BLOCKS.BMP;' ||, call SysCreateObject wpf_class,, wpf_title,, wpf_location,, wpf_setup,, 'R' if RESULT <> 1 then do say 'Unable to create ' ||, wpf_title exit 255 end call SysSetObjectData '<'wpf_title'>',, 'OPEN=ICON;' exit 0
Most of the parameters that can be specified in the setup string used in SysCreateObject() can also be used in the setup string specified for SysSetObjectData(). One known exception is the ICONPOS=x,y setting which is functional only when an object is created.
The OPEN=DEFAULT setting can be used to "open" any kind of object to its default setting (that is the setting with the check mark beside it when you select Open on an object's menu). You can even launch an OS/2 program.
[#Listing 2 Listing 2] shows the program SYSLEVEL, that merely displays the level of the OS/2 components being started. After running the program in Listing 2, switch to your desktop and you will see an OS/2 session running SYSLEVEL.
/* 9409-002.CMD - Launch SYSLEVEL in an OS/2 window */ call RxFuncAdd 'SysLoadFuncs', 'REXXUTIL', 'SysLoadFuncs' call SysLoadFuncs boot_drive = LEFT( VALUE( 'COMSPEC',, 'OS2ENVIRONMENT' ), 2 ) object = boot_drive ||, '\OS2\SYSLEVEL.EXE' setup = 'OPEN=DEFAULT;' call SysSetObjectData object, setup exit
Now, duplicate the line with the call to SysSetObjectData() and rerun this program with the two calls. I won't spoil the surprise that is in store for you.
An object's settings notebook will be opened by specifying OPEN=SETTINGS.
In some cases, the changes that you make to an object's settings with SysSetObjectData() do not take effect until the object's notebook settings are opened and closed (as in the background image example shown in Listing 1). This problem has been reported to IBM, but no solution has been offered by IBM as of this writing.
The SysDestroyFunction() is used to delete an object. SysDestroyObject() will destroy objects that have NODELETE=YES in their style so caution is advised when using this function.
In conclusion, the REXX WPS alliance will provide you with the tools to manage most of your needs for creating and maintaining WPFolder and WPProgram objects. Admittedly, some object settings can not be handled in REXX. I am sure that IBM will address these
in a future release. The WPS class that is most sorely lacking in parameters for both creating and changing its objects is the WPPrinter objects.
Though a WPPrinter object can be created using SysCreateObject(), there is no way to alter the object's settings - a problem that needs to be addressed.
New information regarding WPS objects makes its way across the information super highway very quickly. New information is always being disseminated via the commercial forums (CompuServe, AOL, and so on), the Internet and your local OS/2 oriented BBS's.