═══ 1. Introduction ═══ About... Installation REXX Registration REXX Deregistration REXX Registration Tips ═══ 1.1. About... ═══ This is version 1.3 of RxExtras, released in September, 1993. RxExtras is a set of functions to enhance OS/2's REXX programming language, and is accompanied by additional functions to be used by other PM Rexx-based software (VisPro/Rexx and VX-Rexx, among others). Some of the functions provided by RxExtras can be accomplished by various other means using "pure" OS/2 REXX code, but RxExtras provides an easier interface and more efficient processing. Take the RxSort() function as an example. You can certainly write REXX code to write a stem to a file, run the external SORT program, and read the sorted data back into a stem. The RxSort() function of RxExtras saves a lot of disk I/O; 1. writing the stem to disk. 2. the SORT program reading the file from disk. 3. the SORT program writing the file back to disk. 4. reading the sorted file back into a stem. Plus, with RxSort(), you only need 1 line of code to accomplish the entire task! Once RxExtras is registered to your REXX interpreter, you can take advantage of any RxExtras functions in your existing and future REXX-based programs. ═══ 1.2. Installation ═══ To install RxExtras, place the RxExtras.DLL file in any subdirectory which is part of your LIBPATH statement (LIBPATH is found in your CONFIG.SYS file). For example, you could place RxExtras.DLL in your x:\OS2\DLL subdirectory (by default, x:\OS2\DLL is part of your LIBPATH when you install OS/2). However, it is recommended that you place RxExtras.DLL in some other subdirectory. The reason for this is that should you have to reinstall OS/2, RxExtras.DLL will not automatically be reinstalled with OS/2. All REXX-based programs that require RxExtras.DLL will fail until such time as you manually copy RxExtras.DLL to your x:\OS2\DLL subdirectory. A better, more flexible approach is to make a subdirectory (preferably on a drive other than where OS/2 is installed) for all your add-on *.DLL files, which includes RxExtras.DLL. For example, make a subdirectory called y:\USER\DLL and place RxExtras.DLL in there. Then, edit your CONFIG.SYS file, and add ";y:\USER\DLL" to the end of your LIBPATH. Save CONFIG.SYS and reboot (you must reboot in order for this last change to take effect). Once you've done this, you will never have to modify CONFIG.SYS again, no matter what *.DLL file you add to your system. Just place your new *.DLL file in y:\USER\DLL, and the system will automatically find it when needed. After installing RxExtras, you must register the APIs in order to use them. ═══ 1.3. Registering RxExtras ═══ In order to use any REXX features of OS/2, you must have installed the REXX Interpreter. When you installed OS/2, you may have chosen to not install REXX. If this is the case, open your Selective Install icon and install REXX before continuing. In order to take advantage of RxExtras' REXX APIs found in RxExtras.DLL, you must first "register" the APIs with OS/2's REXX Interpreter. This is true of any and all REXX-based *.DLL files. The process is rather simple. In your *.CMD file (or within your PM REXX-Based program), simply code these 2 lines: Call RxFuncAdd 'RxExtra', 'RxExtras', 'RxExtra' Call RxExtra 'Load' Note: You must code these 2 lines so that they execute before any RxExtras APIs are referenced elsewhere in your program. Once you have done this, your REXX program can take full advantage of RxExtras' APIs (functions). Additionally, all future sessions of REXX-based programs will likewise have access to the RxExtras APIs. In other words, once these APIs are registered, they have a global effect across your entire system; all OS/2 REXX sessions will be able to use them. They stay registered until you reboot or intentionally deregister them. Double-click here for some tips and advice on REXX API registration techniques. ═══ 1.4. Deregistering RxExtras ═══ When you are through with the RxExtras APIs, it is possible to deregister them from your system. The advantage to doing this is that the shared memory they occupied will be released for other programs to use. The disadvantage is that if you wish to use the APIs once more, they must be registered once more. This requires some disk I/O activity to locate the RxExtras.DLL file and load its contents into memory. Warning: If you chose to deregister the RxExtras APIs the affect is global across your entire system. No other REXX-based programs will have access to the APIs and they will in all likelihood fail miserably! To deregister the RxExtras APIs, simply code this line anywhere in any *.CMD file or any other REXX-based program: Call RxExtra 'Drop' Upon execution of the above line, the APIs will be flushed from memory when the system finds it convenient so to do. Double-click here for some tips and advice on REXX API registration techniques. ═══ 1.5. Registration Tips ═══ A good technique for registering any and all REXX API packages (including RxExtras) is as follows: o Define a STARTUP.CMD file in the root directory of your OS/2 boot drive. o Register, within STARTUP.CMD, any and all REXX API packages that you frequently use. o In each *.CMD file or REXX-based program that requires the API: 1. Test for the pre-registration of the API package and save the results in a REXX variable. 2. If the test indicates that the API is not yet registered with REXX, then register it according to the API package's instructions. 3. Just before exiting your program, if the status variable shows that the API was not pre-registered, then deregister it. This method ensures that: 1. Your *.CMD or REXX-based program has access to the APIs it requires. 2. Your REXX environment, in terms of the pre-registered APIs, is restored to its native state before your program exits. This makes for a very well behaved, tolerant program. Specifically, for RxExtras: In your x:\STARTUP.CMD file, place: Call RxFuncAdd 'RxExtra', 'RxExtras', 'RxExtra' Call RxExtra 'Load' In all of your *.CMD and other REXX-based programs that require the RxExtras APIs, place: RxExtraAPI = RxFuncQuery('RxExtra') If RxExtraAPI \= 0 Then Do Call RxFuncAdd 'RxExtra', 'RxExtras', 'RxExtra' Call RxExtra 'Load' End before any other references to RxExtras APIs, and then just before your program exits, use: If RxExtraAPI \= 0 Then Call RxExtra 'Drop' Notice that registering your RxExtras APIs in the STARTUP.CMD file makes the need for the per-program test of pre-registration superfluous. However, it is a good programming practice to code these lines anyway. One reason is that if you give a copy of your program to someone else to use, they might not have registered the APIs in their STARTUP.CMD file. Another reason is that since registration in STARTUP.CMD puts these APIs in memory and leaves them there, you may decide (in the interest of saving memory) to remove the pre-registration from STARTUP.CMD. If you do, and you did not code the above tests (or you got a program from someone else and they did not code the above tests), your programs will no longer execute. CAUTION: Never blindly assume you can deregister any API functions when your program exits. A program that always deregisters the APIs when it quits only causes problems for everyone that uses it. If you are going to include code that deregisters an API (RxExtras or otherwise), you should do so only if you're certain it was not pre-registered when the program started! ═══ 2. RxExtras Release Information ═══ About... Release 1.4 Release 1.3 Release 1.2 Previous Releases ═══ 2.1. About... ═══ This section has details on what is, or was, in each release of RxExtras. You can determine the current release level of RxExtras by running the RxExtra function when you are first registering RxExtras to REXX. Double click on any of the releases on the left hand side to see information pertaining to a particular release. The sort of information that is displayed will be a list of functions added, and any other miscellaneous work, such as parameter checking, or multiple threaded-ness. ═══ 2.2. Release 1.4 ═══ The following functions were added in Release 1.4 of RxExtras:- o RxSetIcon o RxDrawBitmap o RxSetClipboardText o RxQueryClipboardText o RxAppendClipboardText o RxScrollListBox o RxGetEXEName The RxSetGlobal function was enhanced to accept valid REXX variable names and support one call setting of global stems. The RxGetGlobal function was enhanced to accept valid REXX variable names. Note: You can not get global stems in one call using RxGetGlobal. Also, the complete User's Guide you are now reading was included in the package to replace the RxExtras.DOC, and RxExtras.VPR files. Many thanks to Ric Naff for doing a lot of the work. ═══ 2.3. Release 1.3 ═══ The following functions were added in release 1.3 of RxExtras:- o RxThread o RxKillThread o RxSuspendThread o RxResumeThread o RxChangeThreadPriority o RxSetThreadClass ═══ 2.4. Release 1.2 ═══ The following function was added in Release 1.2 of RxExtras:- o RxQueryClassName Also the following miscellaneous work was completed:- o A First cut INF file was included in the ZIP file. o Parameter checking for all functions was enhanced. o RxListBoxFromFile was made multithreaded. o RxVarDump now dumps to a stem, rather than to STDOUT. o RxExtra now returns the version number of RxExtras you have loaded or dropped. o RxVolumeLabel returns an error message if the drive tried is not valid. o RxSwitchTo will match on any part of the string, not just a prefix. o RxQueryDriveType will return "NOTREADY" for CDAUDIO or empty floppy drives. ═══ 2.5. Previously available (No release numbers) ═══ The following functions were available in previous releases of RxExtras that had no release number :- o RxMaximize o RxMinimize o RxRestore o RxBootDrive o RxRead o RxWrite o RxVolumeLabel o RxVarDump o RxStemCopy o RxExtra o RxSort o RxSwitchTo o RxQuerySwitchList o RxQueryDriveType o RxSearchPath o RxSetGlobal o RxGetGlobal o RxLineCount o RxListBoxFromFile o RxListBoxToFile o RxListBoxFromStem o RxListBoxToStem o RxGetListBoxCount o RxGetItemFromListBox o RxGetItemFromListBoxAtIndex o RxAddItemAtIndex o RxSetSpinButtonCharRange o RxSetSpinButtonRangeFromStem o RxSetSpinButtonRangeWithIncrement o RxMorphButtonToIcon o RxSearchItem o RxQueryWindow ═══ 3. RxExtras APIs ═══ The listings for RxExtras APIs (functions) will designate which types of REXX programs can take advantage of them. Each API will have a box at the top of its description detailing in which environments it may be used: ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ If you see "OS/2 REXX" in the above box for a function, you may use that RxExtras function in any *.CMD and/or other REXX-based program. If you do not see "OS/2 REXX", then you cannot use the API in a *.CMD file. If you see "VisPro/REXX" in the above box for a function, you may use that RxExtras function in any VisPro/REXX program. If you see "VX-REXX" in the above box for a function, you may use that RxExtras function in any VX-REXX program. APIs for VisPro/REXX and/or VX-REXX could possibly be used in other PM Rexx-based programs. Some experimentation may be necessary. ═══ 3.1. Disc/File ═══ These APIs deal with accessing information to, from, or about discs and files. Some of them are unique in that there are no standard REXX commands that will retrieve the information for you; RxExtras must be used in these instances. ═══ 3.1.1. RxBootDrive ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXBOOTDRIVE()─── Returns the drive from which OS2 was booted in the format 'X'. If you want a trailing ':' you must append one to the returned drive letter. Example: SAY 'My Boot Drive is' RxBootDrive() || ':' Output: My Boot Drive is C: /* perhaps */ ═══ 3.1.2. RxLineCount ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXLINECOUNT(─┬────────┬─┬────────────┬──filename─)─── └─drive:─┘ └─\─┬───────┬┘ └─path\─┘ Returns the number of lines in filename. The lines in filename are assumed to be delimited by CR/LF characters. If filename does not exist, RXLINECOUNT raises an 'Incorrect call to routine' condition. Example: SAY 'There are' RxLineCount('C:\CONFIG.SYS') 'lines in Config.Sys.' Output: There are 117 lines in Config.Sys. /* perhaps */ ═══ 3.1.3. RxListBoxFromFile ═══ ═══ 3.1.4. RxListBoxToFile ═══ ═══ 3.1.5. RxQueryDriveType ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXQUERYDRIVETYPE(drive:)─── Returns 'HPFS', 'FAT' or 'CDFS' for their respective drive types. Returns 'NOTREADY' for the following conditions: o A CD-ROM drive with an Audio CD loaded. o An empty floppy drive. o An invalid drive letter. Example: SAY 'Drive C: is a' RxQueryDriveType('C:') 'drive.' Output: Drive C: is a HPFS drive. /* perhaps */ ═══ 3.1.6. RxRead ═══ ═══ 3.1.7. RxSearchPath ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXSEARCHPATH(─┬─''─────────┬─,─┬─────────┬──filename─)─── └─searchpath─┘ └─subdir\─┘ Searches for [ subdir\ ]filename in the path(s) defined by searchpath. If the first arument is NULL (i.e., ''), the current default path is searched. Otherwise the path(s) defined for searchpath will be used for the search. searchpath may be composed of several pathnames, each separated by a semicolon. Each pathname is allowed to have either a drive designator, a directory designator, or both. Currently, filename must specify a complete filename; no wildcard characters are accepted. If you supply the optional subdir\ qualifier, the effect is as if you had modified all the values of searchparh to include the addtional subdir\ value. For example, if searchpath contains 'F:\OS2;G:\USER', and you specify 'DLL\' for subdir,, the effect is the same as having specified 'F:\OS2\DLL;G:\USER\DLL' for searchpath and no value for subdir\. RXSEARCHPATH returns a fully qualified filename if it finds one, otherwise it returns NULL. Example: /* Find COUNTRY.SYS */ SchPath = 'C:\OS2\SYSTEM;D:\OS2\SYSTEM;E:\OS2\SYSTEM' SAY RxSearchPath(SchPath,'COUNTRY.SYS') /* Test for presence of a temporary file in current directory */ Status = RxSearchPath('',MYFILE.TMP') If Status \= '' SAY 'MYFILE.TMP exists in current directory!' Else SAY 'MYFILE.TMP does not exist.' Output: D:\OS2\SYSTEM\COUNTRY.SYS /* if found in D:\OS2\SYSTEM */ MYFILE.TMP does not exist. /* perhaps */ ═══ 3.1.8. RxVolumeLabel ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXVOLUMELABEL(drive)─── Returns the volume label for disc drive drive. If no label exists, it returns 'NO LABEL'. Returns 'Error Querying drive label' for an invalid drive letter. You may append an optional colon to the letter, but only the drive letter itself is required. Example: SAY 'Volume Label of drive C is' RxVolumeLabel('C') Output: Volume Label of drive C is MY DRIVE C /* perhaps */ ═══ 3.1.9. RxWrite ═══ ═══ 3.2. REXX Environment ═══ These APIs deal with accessing information to, from, or about 1 or more REXX Sessions. All of these functions are available only with RxExtras; there are no REXX commands which will achieve the same results. ═══ 3.2.1. RxExtra ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXEXTRA(─┬─'LOAD'─┬─)─── └─'DROP'─┘ Loads or Drops all functions in this package. Returns the version number of RxExtras after loading or dropping. Example: rcy = RxFuncAdd('RxExtra', 'RxExtras', 'RxExtra') Say 'Using version 'RxExtra("Load")' of RxExtras' Output: Using version 1.3 of RxExtras /* perhaps */ ═══ 3.2.2. RxGetGlobal ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXGETGLOBAL(──varname──)─── Returns the value for varname, where varname was previously defined via RXSETGLOBAL. If varname was not defined via RXSETGLOBAL, RXGETGLOBAL returns NULL. Example: Call RxSetGlobal('MyVar','Hello World!') Say RxGetGlobal('MyVar') Output: Hello World! ═══ 3.2.3. RxSetGlobal ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXSETGLOBAL(──varname─,─varvalue──)─── Sets a global variable value for use across all REXX sessions. A variable thus set can be retrieved by any other REXX session via RXGETGLOBAL. You can set a global stem from a local stem by passing the global stem name (which must have a trailing period) for varname and passing the local stem name (which also must have a trailing period) for varvalue. Returns varvalue if successful. Example: SomeVar = 'MyVar' Call RxSetGlobal(SomeVar,'Hello World!') Say RxGetGlobal('MyVar') Output: Hello World! ═══ 3.2.4. RxVarDump ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXVARDUMP(──'stemname.'──)─── Copies all local variables to stemname for debugging. The trailing period is required; results are unpredictable without it. RXVARDUMP always returns NULL. The count of variables retrieved is placed in stemname.0. Each unique variable is placed in a pair of variables, stemname.n.name and stemname.n.value and may be displayed in a loop or by other means. Example: XYZ = '123' MyVar = 'Quick Brown Fox' Call RxVarDump('varlist.') Do Count = 1 to varlist.0 Say varlist.Count.name 'has the value "'varlist.Count.value'"' End Output: XYZ has the value "123" MYVAR has the value "Quick Brown Fox" ═══ 3.3. REXX Stems ═══ These APIs deal with accessing information to, from, or about REXX Stem variables. Some of them require PM REXX-based programs in order to function. ═══ 3.3.1. RxListBoxFromStem ═══ ═══ 3.3.2. RxListBoxToStem ═══ ═══ 3.3.3. RxQuerySwitchList ═══ ═══ 3.3.4. RxRead ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXREAD(──'stemname.'─,─┬────────┬─┬────────────┬──filename──)─── └─drive:─┘ └─\─┬───────┬┘ └─path\─┘ Reads filename into the stem variable stemname.. The trailing period to stemname. is required; results are unpredictable if it is not supplied. RXREAD assumes that the contents of filename are ASCII text, with each line terminated by a CR/LF. RXREAD always returns NULL if successful, and the count of lines retrieved is placed in stemname.0. Each unique line of text is place in stemname.n and may be displayed in a loop or by other means. If filename cannot be read, RXREAD raises an 'Incorrect call to routine' condition. Example: Call RxRead('textlines.','C:\Config.Sys') Do Count = 1 to textlines.0 Say textlines.Count End Output: PROTSHELL=C:\OS2\PMSHELL.EXE /* perhaps */ SET USER_INI=C:\OS2\OS2.INI /* perhaps */ . . . ═══ 3.3.5. RxSetSpinButtonRangeFromStem ═══ ═══ 3.3.6. RxSort ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXSORT(──'stemname.'──,─┬─'Ascending'──┬─)─── └─'Descending'─┘ Sorts a stemmed variable stemname. in either Ascending or Descending ASCII sequence. Only the A or D of the sort order is required. The number of items to sort must be placed in stemname.0. All values to sort must be in stemname.1 through stemname.n, where n is the number placed in stemname.0. RXSORT always returns NULL if invoked properly. Example: Stem.0 = 3 Stem.1 = 'Now is the time...' Stem.2 = 'A stitch in time...' Stem.3 = 'Somewhere in time...' Call RxSort('Stem.','A') Do Count = 1 to Stem.0 Say Stem.Count End Say '-----------------' Call RxSort('Stem.','D') Do Count = 1 to Stem.0 Say Stem.Count End Output: A stitch in time... Now is the time... Somewhere in time... ----------------- Somewhere in time... Now is the time... A stitch in time... ═══ 3.3.7. RxStemCopy ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXSTEMCOPY(──'sourcestem.'──,──'targetstem.'──)─── Copies the entire contents of sourcestem. to targetstem.. The trailing period to sourcestem. and targetstem. are required; results are unpredictable if they are not supplied. RXSTEMCOPY always returns NULL. Example: Source.ABC = 'ABCDEFG' Source.123 = '123456789' Call RxStemCopy('Source.','Target.') Say Target.ABC Say Target.123 Output: ABCDEFG 123456789 ═══ 3.3.8. RxVarDump ═══ ═══ 3.3.9. RxWrite ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXWRITE(──'stemname.'─,─┬────────┬─┬────────────┬──filename──)─── └─drive:─┘ └─\─┬───────┬┘ └─path\─┘ Writes filename from the stem variable stemname.. The trailing period to stemname. is required; results are unpredictable if it is not supplied. RXWRITE requires that the number of lines to write are designated in stemname.0. It also requires that the lines of text are placed in stemname. such that entries are numeric in nature, starting at 1 and continuing up to the number defined in stemname..0. stemname. variables that are not numeric or are not within the range 1 to stemname.0 will not be written to filename. RXWRITE writes the text lines in ascending numerical order. RXWRITE always overlays the contents of a previously-existing file, otherwise it creates the file as required. RXWRITE always returns NULL if successful. If filename cannot be written, it raises an 'Incorrect call to routine' condition. Example: MyStem.0 = 4 MyStem.4 = 'We''re as happy as can be.' MyStem.2 = 'Hi There!' MyStem.3 = 'Ho There!' MyStem.1 = 'Hey There!' Call RxWrite('MyStem.','C:\Temp.Out') Contents of C:\Temp.Out: Hey There! Hi There! Ho There! We're as happy as can be. ═══ 3.4. OS/2 Environment ═══ These APIs deal with accessing information about or changing characterstics of your OS/2 machine. ═══ 3.4.1. RxChangeThreadPriority ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXCHANGETHREADPRIORITY(──threadid───┬──────────────┬─)─── ├─,delta───────┤ ├─,'MINIMUM'───┤ ├─,'MAXIMUM'───┤ ├─,''──────────┤ ├─,────────────┤ Changes the priority of threadid by the delta value specified. If the value is left out, NULL or invalid, it is assumed to be the maximum. RXCHANGETHREADPRIORITY returns :- ┌─────────────────────────┬────────────────────────────────────────┐ │Return value │Reason │ ├─────────────────────────┼────────────────────────────────────────┤ │"Priority changed" │Priority was successfully changed │ ├─────────────────────────┼────────────────────────────────────────┤ │"Invalid delta" │The second parameter was not in the │ │ │range -31 to +31, blank, "maximum" or │ │ │"minimum" │ ├─────────────────────────┼────────────────────────────────────────┤ │"Invalid Thread id" │The first parameter did not specify a │ │ │valid thread id. │ ├─────────────────────────┼────────────────────────────────────────┤ │"Unknown return code n" │DosSetPriority returned an undocumented │ │ │return code of n │ └─────────────────────────┴────────────────────────────────────────┘ Example: rc = RxChangeThreadPriority(threadId, 5) Results: rc should contain the value "Priority changed" ═══ 3.4.2. RxGetEXEName ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXGETEXENAME(──)─── Returns the name of the executable currently running your REXX Code. Example: Say "The current running program is "RxGetEXEName() Results: The currnet running program is CMD.EXE /* possibly */ ═══ 3.4.3. RxKillThread ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXKILLTHREAD(──threadid──)─── Kills thread threadid. RXKILLTHREAD returns :- ┌─────────────────────────┬────────────────────────────────────────┐ │Return value │Reason │ ├─────────────────────────┼────────────────────────────────────────┤ │"Killed" │Thread was successfully killed │ ├─────────────────────────┼────────────────────────────────────────┤ │"Thread busy" │The thread to be killed was executing 16│ │ │bit code, or was created by 16 bit code.│ ├─────────────────────────┼────────────────────────────────────────┤ │"Invalid Thread id" │The first parameter did not specify a │ │ │valid thread id. │ ├─────────────────────────┼────────────────────────────────────────┤ │"Unknown return code n" │DosKillThread returned an undocumented │ │ │return code of n │ └─────────────────────────┴────────────────────────────────────────┘ Example: If RxKillThread(5) = "Killed" Then Say "Printing ceased" Results: Thread number 5 is stopped permanently and rc should have the value "Killed" Note: RxKillThread returns to the caller without waiting for the ending thread to complete its termination processing. Note: You cannot use this function to end the current thread. If you use RxKillThread to end thread 1, the entire process ends. ═══ 3.4.4. RxQuerySwitchList ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXQUERYSWITCHLIST(──'stemname.'──)─── Retrieves a list of executing sessions into the stemmed variable stemname.. The count of executing sessions, plus 1, is placed in stemname.0, and the title of each session is placed in stemname.2 through stemname.n, where n is the value found in stemname.0. stemname.1 will contain 'Switch to'. Note that RXQUERYSWITCHLIST will list "hidden" sessions. RXQUERYSWITCHLIST always returns NULL. Example: Call RxQuerySwitchList 'temp.' Do Count = 2 to temp.0 Say temp.Count End Output: 4OS2 Window /* perhaps */ Tritus SPF /* perhaps */ System Clock /* perhaps */ Pulse /* perhaps */ Desktop /* perhaps */ ═══ 3.4.5. RxResumeThread ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXRESUMETHREAD(──threadid──)─── Allows thread threadid to resume execution after being suspended with RXSUSPENDTHREAD. RXRESUMETHREAD returns :- ┌─────────────────────────┬────────────────────────────────────────┐ │Return value │Reason │ ├─────────────────────────┼────────────────────────────────────────┤ │"Resumed" │Thread was successfully resumed │ ├─────────────────────────┼────────────────────────────────────────┤ │"Thread not previously │The thread to be resumed had not been │ │suspended" │previously suspended │ ├─────────────────────────┼────────────────────────────────────────┤ │"Invalid Thread id" │The first parameter did not specify a │ │ │valid thread id. │ ├─────────────────────────┼────────────────────────────────────────┤ │"Unknown return code n" │DosResumeThread returned an undocumented│ │ │return code of n │ └─────────────────────────┴────────────────────────────────────────┘ Example: If RxResumeThread(5) = 'Resumed' Then Say 'Suspended Printing Continues...' Results: Thread number 6 continues processing /* hopefully */ ═══ 3.4.6. RxSetThreadClass ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXSETTHREADCLASS(──threadid ──,─┬─'REGULAR'──────────┬──)─── ├─'IDLE'─────────────┤ ├─'TIMECRITICAL'─────┤ └─'FOREGROUNDSERVER'─┘ Sets the class type of thread threadid to one of REGULAR, IDLE, TIMECRITICAL, or FOREGROUNDSERVER. Only the R, I, T or F of the class type is required. RXSETTHREADCLASS returns :- ┌─────────────────────────┬────────────────────────────────────────┐ │Return value │Reason │ ├─────────────────────────┼────────────────────────────────────────┤ │"Class set" │The class of the thread was successfully│ │ │set │ ├─────────────────────────┼────────────────────────────────────────┤ │"Invalid class" │The class pthread to be killed was │ │ │executing 16 bit code, or was created by│ │ │16 bit code. │ ├─────────────────────────┼────────────────────────────────────────┤ │"Invalid Thread id" │The first parameter did not specify a │ │ │valid thread id. │ ├─────────────────────────┼────────────────────────────────────────┤ │"Unknown return code n" │DosKillThread returned an undocumented │ │ │return code of n │ └─────────────────────────┴────────────────────────────────────────┘ Example: If RxSetThreadClass(id, 'F') = 'Class set' Then Say 'Printing sped up to foreground priority' Results: The thread should perform better than previously ═══ 3.4.7. RxSuspendThread ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXSUSPENDTHREAD(──threadid──)─── Causes thread threadid to halt execution until it is killed with RXKILLTHREAD, restarted with RXRESUMETHREAD, or the parent session is closed. RXSUSPENDTHREAD returns :- ┌─────────────────────────┬────────────────────────────────────────┐ │Return value │Reason │ ├─────────────────────────┼────────────────────────────────────────┤ │"Suspended" │The class of the thread was successfully│ │ │set │ ├─────────────────────────┼────────────────────────────────────────┤ │"Invalid Thread id" │The first parameter did not specify a │ │ │valid thread id. │ ├─────────────────────────┼────────────────────────────────────────┤ │"Unknown return code n" │DosSuspendThread returned an │ │ │undocumented return code of n │ └─────────────────────────┴────────────────────────────────────────┘ Example: Call RxSuspendThread(id) If (result = 'Suspended') Then Say 'Thread 'id' is temporarily suspended' Results: The thread number contained in the variable id is suspended. ═══ 3.4.8. RxSwitchTo ═══ ┌─────────┬───────────┬───────┐ │OS/2 REXX│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXSWITCHTO(──'session'──)─── Switches the forground session to the the session named by session. RXSWITCHTO will attempt to locate a session, by name, that matches in any part of its name to the contiguous characters defined by session For example, if session contains 'stem C', RXSWITCHTO will switch to the System Clock session, if it is active. If you desire to specifiy a complete name, use RXQUERYSWITCHLIST to obtain the full names of all executing sessions. RXSWITCHTO returns 'Switch Entry not found' if it cannot find a session name to match session. Example: Call RxSwitchTo '2.0' /* try "OS/2 2.0 Desktop" */ If Result \= '' Then /* probably 2.1 */ Call RxSwitchTo 'Desktop' Results: The system switches to your OS/2 desktop, making it the active forground session. Your REXX program continues to execute in the background. ═══ 3.4.9. RxThread ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│.......│ └─────────┴───────────┴───────┘ ───RXTHREAD(──'ProcName'───┬───────────┬──)─── │┌─────────┐│ │ ││ └┴, arg────┴┘ Causes the SubProc called ProcName to start execution in its own separate thread. As many arguments as REXX allows (up to 16 currently) can be passed to the SubProc by specifying them after the SubProc name. The new thread runs asynchronously until it is suspended (RXSUSPENDTHREAD), is killed (RXKILLTHREAD), terminates of its own accord, or the parent session is closed. RXTHREAD returns the thread id if successful, otherwise it returns :- ┌─────────────────────────┬────────────────────────────────────────┐ │Return value │Reason │ ├─────────────────────────┼────────────────────────────────────────┤ │"Out of memory" │There was not enough memory to start the│ │ │thread │ ├─────────────────────────┼────────────────────────────────────────┤ │"Interrupt" │The system was interrupted during thread│ │ │creation and the thread was aborted │ ├─────────────────────────┼────────────────────────────────────────┤ │"Protection violation" │The system encountered a protection │ │ │violation (accessing inaccesible memory │ │ │usually) while starting the thread. The │ │ │thread is aborted │ ├─────────────────────────┼────────────────────────────────────────┤ │"Too many threads" │The system could not create any more │ │ │threads. Check your THREADS= line in the│ │ │CONFIG.SYS. It may be too low. │ ├─────────────────────────┼────────────────────────────────────────┤ │"Unknown return code n" │DosCreateThread returned an undocumented│ │ │return code n │ └─────────────────────────┴────────────────────────────────────────┘ Note: The value returned is the threadid required for use with other RxExtras thread functions. Note: SubProcs started using RxThread CANNOT call other SubProcs or use global variables defined in VisPro/REXX. Note: Global Variables such as those created by RxSetGlobal can be used. Note: The author is working on removing these restrictions. Example: tid = RxThread('SEARCH', window, listboxid, text) Results: tid will hold the thread id that was returned when the SubProc SEARCH was executed in parallel. ═══ RxChangeThreadPriority (threadID, delta) ═══ Changes the priority of the thread id specified by the delta amount specified. The delta value must be in the range -31 to +31. ═══ RxChangeThreadPriority (threadID, 'Minimum') ═══ Lowers the priority of the thread id specified by the most possible (-31). Only the first two characters of the second parameter are significant. ═══ RxChangeThreadPriority (threadID, 'Maximum') ═══ Raises the priority of the thread id specified by the most possible (+31). Only the first two characters of the second parameter are significant. ═══ RxChangeThreadPriority (threadID, '') ═══ Raises the priority of the thread id specified by the most possible (+31). ═══ RxSetThreadClass (threadID, 'REGULAR') ═══ Sets the class of the specified thread id to REGULAR. This is the class of applications running in the background. The application with focus runs at FOREGROUNDSERVER ═══ RxSetThreadClass (threadID, 'IDLE') ═══ Sets the class of the specified thread id to IDLE. This is one step less important than a normal application. ═══ RxSetThreadClass (threadID, 'FOREGROUNDSERVER') ═══ Sets the class of the specified thread id to FOREGROUNDSERVER. This is the class of the applications that currently has focus, or a server thread needing higher than normal CPU. ═══ RxSetThreadClass (threadID, 'TIMECRITICAL') ═══ Sets the class of the specified thread id to TIMECRITICAL. This should be used very sparingly as it can make the foreground applcation unresponsive, since a TIMECRITICAL thread gets more of the CPU than any FOREGROUNDSERVER thread. ═══ 3.5. ListBox Objects ═══ These APIs deal with PM ListBox Objects. They require a PM REXX-based program in order to function. ═══ 3.5.1. RxAddItemAtIndex ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXADDITEMATINDEX(──winid──,──lbid──,──row──,──value──)─── Inserts the entry value at line row into ListBox lbid of Window winid. If either winid or lbid are invalid, the rexx error condition INCORRECT CALL TO ROUTINE is raised. RXADDITEMATINDEX returns the index that the item was inserted at if successful, otherwise it returns :- ┌──────────┬────────────────────────────────────────┐ │Return │Reason │ │value │ │ ├──────────┼────────────────────────────────────────┤ │-1 │There was not enough memory to insert │ │ │the item into the list box │ ├──────────┼────────────────────────────────────────┤ │-2 │An error occurred inserting the item │ │ │into the listbox │ └──────────┴────────────────────────────────────────┘ Example: Call RxAddtItemAtIndex window, 1000, 4, 'This is the fourth line' Results: The ListBox with ID=1000 in window window receives a new row 4, the contents of which are 'This is the fourth line'. Rows 5 and higher are shifted down 1 row. The REXX special variable result contains 4. ═══ 3.5.2. RxGetItemFromListBox ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXGETITEMFROMLISTBOX(──winid──,──lbid──)─── Retrieves the first selected item from ListBox lbid of Window winid. If either winid or lbid are invalid, the REXX error condition INCORRECT CALL TO ROUTINE is raised. If no items are selected, RXGETITEMFROMLISTBOX returns an empty string (""). If winid and/or lbid are invalid, RXGETITEMFROMLISTBOX raises an INCORRECT CALL TO ROUTINE error from within REXX. Otherwise, RXGETITEMFROMLISTBOX returns the selected item. Note: The VisPro/Rexx API VpGetItemValue will only return up to 256 characters for the retrieved item. RxGetItemFromListBox will exactly what is in the listbox. Example: row = RxGetItemFromListBox(window, 1000) Results: The first selected item in ListBox 1000 of window window is retrieved and placed in the variable row. ═══ 3.5.3. RxGetItemFromListBoxAtIndex ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXGETITEMFROMLISTBOXATINDEX(──winid──,──lbid──,──row──)─── Retrieves the line row from ListBox lbid of Window winid. If no item exists at line row, or winid or lbid are invalid, RXGETITEMFROMLISTBOXATINDEX returns an empty string (""). If winid and/or lbid are invalid, RXGETITEMFROMLISTBOXATINDEX raises an INCORRECT CALL TO ROUTINE error from within REXX. Otherwise, RXGETITEMFROMLISTBOXATINDEX returns the item of choice. Note: The VisPro/Rexx API VpGetItemValueAtIndex will only return up to 256 characters for the retrieved item. RxGetItemFromListBoxAtIndex will return whatever is in the listbox, with no limitations. Example: row = RxGetItemFromListBoxAtIndex(window, 1000, 4) Results: If it exists, the item at line 4 in ListBox 1000 of window window is retrieved and placed in the variable row. ═══ 3.5.4. RxGetListBoxCount ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXGETLISTBOXCOUNT(──winid──,──lbid──)─── Retrieves the number of rows available in ListBox lbid of Window winid. If winid and/or lbid are invalid, RXGETLISTBOXCOUNT raises the INCORRECT CALL TO ROUTINE error condition from within REXX. Otherwise, RXGETLISTBOXCOUNT returns the number of available rows. Example: items = RxListBoxCount(window, 1000) Results: The number of rows in ListBox 1000 of window window are placed in the variable items. ═══ 3.5.5. RxListBoxFromFile ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXLISTBOXFROMFILE(──winid──,──lbid──,──filename──)─── Places the contents of file filename into ListBox lbid of Window winid. If winid and/or lbid and/or filename are invalid/inaccessible, RXLISTBOXFROMFILE raises an INCORRECT CALL TO ROUTINE condition from within REXX. Otherwise, RXLISTBOXFROMFILE returns a null string. Note: This API is mutlithreaded. The ListBox continues to have items added to it after control is returned to your program. This makes this API faster than those suplied with VisPro/REXX or VX-REXX. Note: For VisPro/Rexx, winid is passed to all events. Note: This API appends to the end of any existing contents already in ListBox lbid. Example: Call RxListBoxFromFile window, 1000, 'C:\Config.Sys' Results: The contents of C:\Config.Sys are placed into ListBox 1000 of window window. The ListBox is populated while your program continues with other chores. ═══ 3.5.6. RxListBoxFromStem ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXLISTBOXFROMSTEM(──winid──,──lbid──,──stemname.──)─── Places the contents of stem stemname into ListBox lbid of Window winid. The trailing period to stemname. is required; results are unpredictable if not supplied. stemname.0 must contain the count of items to be placed into ListBox lbid. All other occurrences for stemname must be numeric, from 1 to n, where n is the number contained in stemname.0. If winid and/or lbid are invalid, RXLISTBOXFROMSTEM raises an INCORRECT CALL TO ROUTINE from within REXX. Otherwise, RXLISTBOXFROMSTEM returns an empty string (""). Note: This API appends to the end of any existing contents already in ListBox lbid. Example: MyStem.0 = 2 MyStem.1 = 'This will be the 1st line added' MyStem.2 = 'This will be the 2nd line added' Call RxListBoxFromStem window, 1000, 'MyStem.' Results: The contents of ListBox 1000 of window window will have 2 new rows. The rows will be: This will be the 1st line added This will be the 2nd line added ═══ 3.5.7. RxListBoxToFile ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXLISTBOXTOFILE(──winid──,──lbid──,──filename──)─── Places the contents ListBox lbid of Window winid into file filename. If winid and/or lbid and/or filename are invalid/inaccessible, RXLISTBOXTOFILE raises the REXX INCORRECT CALL TO ROUTINE error condition. Otherwise, RXLISTBOXTOFILE returns an empty string (""). Note: This API erases all contents of file filename before writing to it. Example: Call RxListBoxToFile window, 1000, 'C:\MyData.Dat' Results: The contents of ListBox 1000 of window window are written to file C:\MyData.Dat. ═══ 3.5.8. RxListBoxToStem ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXLISTBOXTOSTEM(──winid──,──lbid──,──stemname.──)─── Places the contents of ListBox lbid of Window winid into stem stemname. The trailing period to stemname. is required; results are unpredictable if not supplied. stemname.0 will contain the count of items to placed into it from ListBox lbid. All other occurrences for stemname will be numeric, from 1 to n, where n is the number contained in stemname.0. If winid and/or lbid are invalid, RXLISTBOXTOSTEM raises the REXX error condition INCORRECT CALL TO ROUTINE. Otherwise, RXLISTBOXTOSTEM returns an empty string (""). Note: This API destroyes any existing contents already in stem stemname. Example: Call RxListBoxToStem window, 1000, 'MyStem.' Results: The contents of ListBox 1000 of window window will be copied to stem MyStem. Assuming there are 2 rows in ListBox 1000, MyStem.0 will contain 2, and occurrences will exist for MyStem.1 and MyStem.2. ═══ 3.5.9. RxScrollListBox ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXSCROLLISTBOX(──winid──,──lbid──,──numLinesToScroll.──)─── Scrolls the ListBox lbid of Window winid by numLinesToScroll lines. A negative value should be used to scroll up, a positive value to scroll the listbox down. If winid and/or lbid are invalid, RXSCROLLLISTBOX raises the REXX error condition INCORRECT CALL TO ROUTINE. if numLinesToScroll is not numeric, the listbox is simply not scrolled. Otherwise, RXSCROLLLISTBOX returns an empty string (""). Example: Call RxScrollListBox window, 1000, -3 Results: The contents of ListBox 1000 of window window will be scrolled up 3 lines ═══ 3.5.10. RxSearchItem ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ Searches a listbox for text. Doesn't have to be an entire line, it can be text contained within one line of a listbox. RxSearchItem returns the line in the listbox that holds the text. ───RXSEARCHITEM(──winid──,──lbid──,─┬─''───┬─,──row──,─┬─'F'─┬──)─── └─mask─┘ └─'B'─┘ Searches ListBox lbid of Window winid, starting at line row, for a line containing the characters mask. The search will procede forward or backward, depending on the use of 'F' or 'B', respectively. If winid and/or lbid are invalid, RXSEARCHITEM raises the REXX error condition INCORRECT CALL TO ROUTINE. Otherwise, RXSEARCHITEM returns the index number of the first matching line, or 0 if no lines were found to match mask. 0 is used to indicate no match. Note: If NULL (i.e., '') is used for mask, the first item tested will match. RXSEARCHITEM can therefore be used to retrieve the index of the last item in ListBox lbid. Example: JohnIsAt = RxSearchItem window, 1000, 'John Smith', 1, 'F' Results: The contents of ListBox 1000 of window window will be searched, starting at row 1 and proceding in a forward direction, looking for any row that contains the characters 'John Smith'. If found, variable JohnIsAt will contain the index (row number) of the matching entry. Otherwise, JohnIsAt will contain 0. ═══ 3.6. PushButton Objects ═══ These APIs deal with PM PushButton Objects. They require a PM REXX-based program in order to function. ═══ 3.6.1. RxMorphButtonToIcon ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXMORPHBUTTONTOICON(──winid──,──pbid──,──┬─VpLoadPictureHandle──┬──)─── └─DLLname──,──resource─┘ Converts a standard PushButton object pbid of window winid into a "Toolbox" button. If any arguments are invalid or inaccessible, RXMORPHBUTTONTOICON raises the REXX error condition INCORRECT CALL TO ROUTINE. Otherwise, RXMORPHBUTTONTOICON returns an empty string (""). Note: The use of VpLoadPictureHandle requires VisPro/Rexx. You must call VpLoadPicture and obtain the handle. Note: The use of DLLName, resource can be used by any PM REXX-based program, and retrieves the requested icon. If DLLname is in your LIBPATH, do not specify an extension of '.DLL'. Note: In order to make the window appear to start-up with your required icons, you should call RXMORPHBUTTONTOICON immediately at entry to your program, when the window is being opened. Otherwise, the user will see the buttons change appearance. Example: value = VpLoadPicture('FILE','C:\TEMP\OS2CMD.ICO') Call RxMorphButtonToIcon Hwindow, 2000, value Results: The PushButton with ID=2000 in window Hwindow is changed to an OS/2 Command-Prompt icon (stored previously in C:\TEMP\OS2CMD.ICO). ═══ 3.7. SpinButton Objects ═══ These APIs deal with PM SpinButton Objects. They require a PM REXX-based program in order to function. ═══ 3.7.1. RxSetSpinButtonCharRange ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│.......│ └─────────┴───────────┴───────┘ ───RXSETSPINBUTTONCHARRANGE(──winid──,──sbid──,──low──,──high──)─── Sets the SpinButton sbid of Window winid to include the ASCII character range low through high. Only the first character of low and high are used. If winid and/or sbid are invalid, RXSETSPINBUTTONCHARRANGE raises the REXX error condition INCORRECT CALL TO ROUTINE. Otherwise, RXSETSPINBUTTONCHARRANGE returns an empty string (""). Example: Call RxSetSpinButtonCharRange Hwindow, 4000, 'a', 'z' Results: The SpinButton with ID=4000 in window Hwindow now contains the selection character set 'a' through 'z', inclusive. ═══ 3.7.2. RxSetSpinButtonRangeFromStem ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│.......│ └─────────┴───────────┴───────┘ ───RXSETSPINBUTTONRANGEFROMSTEM(──winid──,──sbid──,──stemname.──)─── Sets the SpinButton sbid of Window winid to include the values found in stem stemname. The trailing period to stemname. is required; results are unpredictable if not supplied. stemname.0 must contain the number of values to assign to SpinButton sbid. All other occurences of stemname should contain the values desired for sbid, and be in the range 1 to n, where n is the value contained in stemname.0. If winid and/or sbid are invalid, RXSETSPINBUTTONRANGEFROMSTEM raises the REXX error condition INCORRECT CALL TO ROUTINE. Otherwise, RXSETSPINBUTTONRANGEFROMSTEM returns an empty string (""). Example: days.0 = 7; days.1 = 'Sun'; days.2 = 'Mon'; days.3 = 'Tue'; days.4 = 'Wed'; days.5 = 'Thu'; days.6 = 'Fri'; days.7 = 'Sat'; Call RxSetSpinButtonRangeFromStem Hwindow, 4000, 'days.' Results: The SpinButton with ID=4000 in window Hwindow now contains the selection character set 'Sun', 'Mon', 'Tue', ... ═══ 3.7.3. RxSetSpinButtonRangeWithIncrement ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│.......│ └─────────┴───────────┴───────┘ ───RXSETSPINBUTTONRANGEWITHINCREMENT(──winid──,──sbid──,──low──,──high──,───── ───────────────────────────────────────increment───────────────────────────)── Sets the SpinButton sbid of Window winid to the numeric range of low to high, in incriments of incriment. If winid and/or sbid are invalid, RXSETSPINBUTTONRANGEWITHINCRIMENT raises the REXX error condition INCORRECT CALL TO ROUTINE. Otherwise, RXSETSPINBUTTONRANGEWITHINCRIMENT returns an empty string (""). Example: Call RxSetSpinButtonRangeWithIncrment Hwindow, 4000, 0, 10000, 2000 Results: The SpinButton with ID=4000 in window Hwindow now contains the selection numeric set 0, 2000, 4000, 6000, 8000, and 10000. Note: The maximum number of discrete values that this function can store in a spin button is 4096. ═══ 3.8. Window Objects ═══ These APIs deal with OS/2 Windows and PM window types & hierarchies. They require a window handle, therefore, a PM REXX-based program in order to function. ═══ 3.8.1. RxMaximize ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXMAXIMIZE(──winid──)─── Causes window winid to become maximized. If winid is invalid, RXMAXIMIZE raises the REXX error condition INCORRECT CALL TO ROUTINE. If an error occurs, RXMAXIMIZE returns "Error occured trying to maximize", otherwise, RXMAXIMIZE returns an empty string (""). Example: Call RxMaximize Hwindow Results: The window Hwindow is maximized. ═══ 3.8.2. RxMinimize ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXMINIMIZE(──winid──)─── Causes window winid to become minimized. If winid is invalid, RXMINIMIZE raises the REXX error condition INCORRECT CALL TO ROUTINE. If RXMINIMIZE encounters an error, it returns "Error trying to minimize", otherwise, RXMINIMIZE returns an empty string (""). Example: Call RxMinimize Hwindow Results: The window Hwindow is minimized. ═══ 3.8.3. RxQueryClassName ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXQUERYCLASSNAME(──winid──)─── Returns the Class Name for window winid. If winid is invalid, RXQUERYCLASSNAME raises the REXX error condition INCORRECT CALL TO ROUTINE. If an error occurs, RXQUERYCLASSNAME returns "Error trying to query classs name", otherwise, RXQUERYCLASSNAME returns the PM Class Name for the window. Example: WinClass = RxQueryClassName(Hwindow) Results: The Class Name of window Hwindow is placed in the variable WinClass. ═══ 3.8.4. RxQueryWindow ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXQUERYWINDOW(──winid──,─┬─'Owner'──────┬─)─── ├─'Parent'─────┤ ├─'Next'───────┤ ├─'Prev'───────┤ ├─'Top'────────┤ ├─'Bottom'─────┤ ├─'NextTop'────┤ ├─'PrevTop'────┤ └─'FrameOwner'─┘ Returns the window handle for the requested related window to winid. Double-click on each window relation above for further information. If winid is invalid, RXQUERYWINDOW raises the REXX error condition INCORRECT CALL TO ROUTINE. Otherwise, RXQUERYWINDOW returns the requested PM window handle, in decimal. Example: WinParent = RxQueryWindow(Hwindow, 'Parent') Results: The parent window handle, in decimal, for window Hwindow is placed in the variable WinParent. ═══ 3.8.5. RxRestore ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXRESTORE(──winid──)─── Restores window winid to its normal state after being maximized or minimized. If winid is invalid, RXRESTORE raises the REXX error condition INCORRECT CALL TO ROUTINE. If an error occurs, RXRESTORE returns "Error trying to restore", otherwise, RXRESTORE restores the requested PM window, and returns an empty string (""). Example: Call RxRestore(Hwindow) Results: Restores the window Hwindow. ═══ 3.8.6. RxSetIcon ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXSETICON(──winid──,──┬─VpLoadPictureHandle──┬──)─── └─DLLname──,──resource─┘ Sets the icon for a window. This icon is the one used when a window is minimized. If winid is invalid, RXSETICON raises the REXX error condition INCORRECT CALL TO ROUTINE. If an error occurs loading the icon from a DLL, RXSETICON returns "Error loading icon from DLL". If an error occurs setting the icon, RXSETICON returns "Error setting icon". Otherwise RXSETICON returns an empty string (""). Example: value = VpLoadPicture('FILE', 'C:\TEMP.ICO'); FrameWindow = RxQueryWindow(RxQueryWindow(window, 'parent'), 'parent') Call RxSetIcon(FrameWindow, value) Results: Loads an icon from C:\TEMP.ICO Calculates the Frame Window (the one that the user interacts with) from the window passed to a VisPro/REXX event Sets the minimized icon for the window passed. ═══ RxQueryWindow (winid,'Owner') ═══ Requests the Owner window handle of winid. The Owner window is the one which window winid is dependent upon. Quite frequently, this is the same as 'Parent'. ═══ RxQueryWindow (winid,'Parent') ═══ Requests the Parent window handle of winid. The Parent window is the one that causes window winid to be initialized. ═══ RxQueryWindow (winid,'Next') ═══ Requests the Next window handle, in z-order, of winid. This is the next window at the same "level" as window winid. ═══ RxQueryWindow (winid,'Prev') ═══ Requests the Previous window handle, in z-order, of winid. This is the previous window at the same "level" as window winid. ═══ RxQueryWindow (winid,'Top') ═══ Requests the Topmost (first) "child" window handle of winid. This is the first window that window winid caused to be initialized. ═══ RxQueryWindow (winid,'Bottom') ═══ Requests the Bottommost (last) "child" window handle of winid. This is the last window that window winid caused to be initialized. ═══ RxQueryWindow (winid,'NextTop') ═══ Requests the next window, in z-order, of the owner window hierarchy for winid. See 'Owner'. ═══ RxQueryWindow (winid,'PrevTop') ═══ Requests the previous window, in enumeration order defined by NextTop, of the owner window hierarchy for winid. See 'Owner'. ═══ RxQueryWindow (winid,'FrameOwner') ═══ Requests the owner of winid, normalized so that it shares the same window as its Parent. ═══ 3.9. Free Form window Objects ═══ These APIs deal with VisPro/REXX Free Form Window Objects. They require a PM REXX-based program in order to function. ═══ 3.9.1. RxDrawBitmap ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXDRAWBITMAP(──winid──,──ffid──,──┬─VpLoadPictureHandle──┬──)─── └─DLLname──,──resource─┘ Draws a bitmap in a free form window of id ffid in window winid. RXDRAWBITMAP will stretch the bitmap to take up the entire size of the free form window. If any arguments are invalid or inaccessible, RXDRAWBITMAP raises the REXX error condition INCORRECT CALL TO ROUTINE. If there is an error loading the bitmap from a DLL, RXDRAWBITMAP will return "Error loading bitmap from DLL". Otherwise, RXDRAWBITAMP returns an empty string (""). Note: The use of VpLoadPictureHandle requires VisPro/Rexx. You must call VpLoadPicture and obtain the handle. Note: The use of DLLName, resource can be used by any PM REXX-based program, and retrieves the requested bitmap. If DLLname is in your LIBPATH, do not specify an extension of '.DLL'. Example: value = VpLoadPicture('FILE','C:\OS2\BITMAP\OS2LOGO.BMP') Call RxDrawBitmap window, 2000, value Results: The Free From window with ID=2000 in window window has the OS2LOGO bitmap drawn inside it. Note: This API may work with other window types, it just has not been tested with them. ═══ 3.10. Clipboard Objects ═══ These APIs deal with the OS/2 Presentation Manager clipboard. They require a PM REXX-based program in order to function. ═══ 3.10.1. RxAppendClipboardText ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXAPPENDCLIPBOARDTEXT(──Text──)─── This function appends the text passed to the current contents of the clipboard. RXAPPENDCLIPBOARDTEXT returns the text previously in the clipboard if successful. If there is an error opening the clipboard, RXAPPENDCLIPBOARDTEXT returns "Error opening the clipboard". If there is no textual data in the clipboard, RXAPPENDCLIPBOARDTEXT sets the clipboard to contain the text passed. If there is an error setting the clipboard data, RXAPPENDCLIPBOARDTEXT returns "Error setting clipboard data". If there is not one valid string as the argument to RXAPPENDCLIPBOARDTEXT, the REXX error condition INCORRECT CALL TO ROUTINE is raised. Example: PrevText = RxAppendClipboardText("Stuff to add") Say 'The contents of the clipboard were "'PrevText'", and are now "'RxQueryClipboardText()'".' Results: The contents of the clipboard were "ABCD", and are now "ABCDStuff to add". Note: To get multiple lines into the clipboard, you should use a carriage return and linefeed combination at the end of the string. This can be achieved by the following code sample :- CrLfString = OldString || d2c(13) || d2c(10) ═══ 3.10.2. RxQueryClipboardText ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXQUERYCLIPBOARDTEXT()─── This function queries the current content of the clipboard. RXQUERYCLIPBOARDTEXT returns the text currently in the clipboard if successful. If there is an error opening the clipboard, RXQUERYCLIPBOARDTEXT returns "Error opening the clipboard". If there is no textual data in the clipboard, RXQUERYCLIPBOARD returns an empty string (""). Example: Text = RxQueryClipboardText() Say 'The contents of the clipboard are "'Text'".' Results: The contents of the clipboard are "This is in the clipboard". ═══ 3.10.3. RxSetClipboardText ═══ ┌─────────┬───────────┬───────┐ │.........│VisPro/REXX│VX-REXX│ └─────────┴───────────┴───────┘ ───RXSETCLIPBOARDTEXT(──Text──)─── This function sets the current content of the clipboard. RXSETCLIPBOARDTEXT returns "Clipboard set" if successful. If there is an error opening the clipboard, RXSETCLIPBOARDTEXT returns "Error opening the clipboard". If there is an error putting the data into the clipboard, RXSETCLIPBOARDTEXT returns "Error setting clipboard data". If there is not one valid string as the argument to RXSETCLIPBOARDTEXT, the REXX error condition INCORRECT CALL TO ROUTINE is raised. Example: Say RxSetClipboardText("New text for the clipboard") Say 'The contents of the clipboard are now "'RxQueryClipboardText()'".' Results: Clipboard Set The contents of the clipboard are now "New text for the clipboard". ═══ 4. RxExtras.LIB ═══ RxExtras.LIB is a library file for use in C programming. If you want to use some of the functions in RxExtras in your own C code, you need to link with RxExtras.LIB when you are building your application. All functions exported from RxExtras.LIB are callable from REXX and therefore have the following function prototype :- ULONG Name(PSZ pszFnName, ULONG ulArgc, RXSTRING rxArgv[], PSZ pszQName, PRXSTRING prxReturn) The following is a list of all functions exported in RxExtras.LIB o RxRead o RxWrite o RxBootDrive o RxVolumeLabel o RxVarDump o RxStemCopy o RxExtra o RxSort o RxSwitchTo o RxQuerySwitchlist o RxListBoxFromFile o RxListBoxFromStem o RxQueryDriveType o RxSearchPath o RxGetItemFromListBox o RxSetSpinButtonRangeWithIncrement o RxSetSpinButtonCharRange o RxSetSpinButtonRangeFromStem o RxGetItemFromListBoxAtIndex o RxSetGlobal o RxGetGlobal o RxGetListBoxCount o RxListBoxToFile o RxListBoxToStem o RxAddItemAtIndex o RxMorphButtonToIcon o RxSearchItem o RxSetAccelTable o RxQueryAccelTable o RxQueryWindow o RxQueryClassName o RxQueryFonts o RxLineCount o RxMaximize o RxMinimize o RxRestore o RxThread o RxKillThread o RxSuspendThread o RxResumeThread o RxSetThreadClass o RxChangeThreadPriority o RxSetIcon o RxDrawBitmap ═══ 5. RxExtras.CMD ═══ RxExtras.CMD is a command file that will test all parts of RxExtras that can be run from the command line. A copy of this file is included here in case you delete it. You can easily copy the file from the Services->Copy menu item on the action bar and then paste it back into your favourite editor. ═══ 5.1. RxExtras.CMD - Source ═══ /* RxExtras - test for all functions in RxExtras.DLL */ Address CMD /* rcy = RxFuncDrop('RxExtra') */ If RxFuncQuery('RxExtra') <> 0 Then rcy = RxFuncAdd('RxExtra', 'RxExtras', 'RxExtra') Call RxExtra "Drop" /* Drop everything */ rcy = RxFuncAdd('RxExtra', 'RxExtras', 'RxExtra') Say 'Using version 'RxExtra("Load")' of RxExtras' Say Say "Testing RxBootDrive and RxRead..." Call RxRead 'stem.', RxBootDrive()":"'\CONFIG.SYS' Say "Your Config.Sys file should now appear" "@PAUSE" Do i = 1 to stem.0 Say stem.i end /* do */ "@PAUSE" Say Say "Testing RxBootDrive by itself" Say 'Your bootdrive is 'RxBootDrive()":" "@PAUSE" temp.0 = 5 temp.1 = "This is a test file" temp.2 = "With this ring, I thee bed" temp.3 = "The worlds smallest handcuff" temp.4 = "How to win fiends and affluent people" temp.5 = "### The last line ###" Say Say "Testing RxWrite by writing 5 lines to \TEMP.DAT" Call RxWrite "temp.", "\temp.dat" Say "Here is \TEMP.DAT" "@type \temp.dat | more" "@PAUSE" "@DEL \temp.dat" Say Say "Testing RxVolumeLabel" Say "Label of C is "RxVolumeLabel("C") "@PAUSE" Say Drop stem. Drop temp. temp.1 = 1 temp.testing = "Testing is on" temp.2 = 3 temp.testing.1 = "Life be in it" Say "Testing RxVarDump - dumping all 'local' variables" Call RxVarDump 'vars.' Do i = 1 to vars.0 Say 'Variable Name:"'vars.i.name'" has the value: "'vars.i.value'"' End Drop vars. "@PAUSE" Say Say "Testing RxStemCopy" Say "Copy all variables from temp. to temp2." Say "See RxVarDump above for temp. variables" Call RxStemCopy "temp.", "temp2." Say "Now we have..." Call RxVarDump 'vars.' Do i = 1 to vars.0 Say 'Variable Name:"'vars.i.name'" has the value: "'vars.i.value'"' End Drop vars. "@PAUSE" Say Say "Testing RxSort" temp.0 = 16 temp.1 = "This is a list" temp.2 = "a List should be sorted" temp.3 = "upper and Lowercase" temp.4 = "$trange" temp.5 = "#unny" temp.6 = "@nd unusual" temp.7 = "12345" temp.8 = "123456" temp.9 = "One isthe 9" temp.10 = "Ten green bottles 10" temp.11 = "Legs 11" temp.12 = "And then some 12" temp.13 = "Hollow weeing 13" temp.14 = "Only 14" temp.15 = "15" temp.16 = "The last line!" Say Say "The unsorted list is..." Say Copies('-', 50) Do i = 1 to temp.0 Say temp.i end /* do */ Say Copies('-', 50) "@PAUSE" Say Say "Sorting in descending order gives..." Call RxSort 'temp.', 'Descending' Say Copies('-', 50) Do i = 1 to temp.0 Say temp.i end /* do */ Say Copies('-', 50) "@PAUSE" Say Say "Sorting in ascending order gives..." Call RxSort 'temp.', 'Asc' Say Copies('-', 50) Do i = 1 to temp.0 Say temp.i end /* do */ Say Copies('-', 50) "@PAUSE" Say Say "Testing RxSwitchTo" Say "Switching to the desktop, hit Ctrl-Alt-Shift-O to see developers" /* RxSwitchTo works by matching as much of the string as you give it * to the first session. * i.e. Call RxSwitchTo "System C" * Will switch to the system clock. */ Call RxSwitchTo "OS" If POS("Switch", result) <> 0 Then Do /* probably 2.1 */ Call RxSwitchTo "Desktop" End "@PAUSE" Say Say "Testing RxQuerySwitchListo" Say "The programs running should now appear." Call RxQuerySwitchList "temp." Do i = 1 to temp.0 Say temp.i End /* do */ "@PAUSE" Say Say "Testing RxQueryDriveType for Drive C:" Say RxQueryDriveType("C:") BD = RxBootDrive() PathToSearch = BD":\OS2;"BD":\OS2\INSTALL" Say Say "Testing RxSearchPath looking for DATABASE.TXT in \OS2 and \OS2\INSTALL" Say RxSearchPath(PathToSearch, 'DATABASE.TXT') "@PAUSE" Say Say "Testing Global variables" Call RxSetGlobal "TX1", "This is shared memory!" Say "The text 'This is shared memory' should now appear..." Say RxGetGlobal('tx1') /* Limitations - variable names must adhere to the 8.3 file naming standard and are 4096 chars max */ "@PAUSE" Say Say "Testing RxLineCount" LC = RxLineCount(RxBootDrive()':\config.sys') Say 'There are 'LC' lines in the your CONFIG.SYS file' "@PAUSE" Say "All testing is now over..." "@PAUSE" Call RxExtra "Drop" ═══ 6. Registration/Support ═══ Registration Support Future Enhancements Trademarks ═══ 6.1. Registration ═══ This software package is distributed as Shareware. Non-corporate users are granted the right to use and evaluate the usefulness of RxExtras, and to distribute the package, intact, by any medium. Continued use of RxExtras requires formal registration of the software. Distribution of any software which requires RxExtras APIs by persons who have not paid their registration fee is illegal. Users acquiring a software package which requires RxExtras may freely use RxExtras with that package without being required to submit payment for RxExtras. However, such Users are required to pay for RxExtras if the User creates his/her own programs which utilize the RxExtras APIs. If you find this package useful and use it, register for $25 Australian ($18 US) at the address below. Use of this package in any commercial product is illegal without registration and licensing. License arrangements can be made via: o Compuserve (100026,470) o Internet (10026.470@compuserve.com) o Voice Telephone (61-2-413-2281) o FAX Telephone (61-2-415-2754) o Mail: Dion Gillard 5 Lobelia St, Chatswood, NSW, 2067 Australia ═══ 6.2. Support ═══ If you have any questions or would like some other functions added, please contact me on Compu$erve (100026,470) or via Internet at 100026.470@compuserve.com ═══ 6.3. Future Enhancements ═══ If you have any ideas for future improvement of RxExtras, please contact me with your suggestions. Some of the ideas I am considering in future releases are: Function Description RxReplace Replace a given string of text with another in a file. RxFind Find file(s) which have a given string of text within them. RxRun Start a thread of execution within the current session. RxKillDir Delete a subdirectory, all of its files, and all of its subdirectories. RxClipCut Cut a string of text from a file and place it in the OS/2 clipboard. RxClipCopy Copy a string of text from a file and place it in the OS/2 clipboard. RxClipPaste Paste a string of text from the OS/2 clipboard into a file. RxClipAppend Paste a string of text from the OS/2 clipboard at the end of a file. ═══ 6.4. Trademarks ═══ VisPro/Rexx is a registered trademark of HockWare, Inc. VX-Rexx is a registered trademark of Watcom, Inc. RxExtras is copyrighted Dion Gillard, 1992 1993.