REXX Tips & Tricks:Sample source code
Appearance
This section contains some sample source code. (see also Using the samples)
Using ANSI sequences
This section contains some routines for the display and for redefining of keys using ANSI sequences. (see also ANSI ESC Sequences)
Check if ANSI is active - 1 -
/* sample routine to check if ANSI is activated */ /* */ /* see also Check if ANSI is active - 2 - */ /* */ i = CheckAnsi() if i = 1 then say "ANSI is activated" else if i = 0 then say "ANSI is not activated." else say "Error detecting ANSI." exit 0 /* ------------------------------------------------------------------ */ /* function: Check if ANSI is activated */ /* */ /* call: CheckAnsi */ /* */ /* where: - */ /* */ /* returns: 1 - ANSI support detected */ /* 0 - no ANSI support available */ /* -1 - error detecting ansi */ /* */ /* note: Tested with the German and the US version of OS/2 3.0 */ /* */ /* */ CheckAnsi: PROCEDURE thisRC = -1 trace off /* install a local error handler */ SIGNAL ON ERROR Name InitAnsiEnd "@ANSI 2>NUL | rxqueue 2>NUL" thisRC = 0 do while queued() <> 0 queueLine = lineIN( "QUEUE:" ) if pos( " on.", queueLine ) <> 0 | , /* USA */ pos( " (ON).", queueLine ) <> 0 then /* GER */ thisRC = 1 end /* do while queued() <> 0 */ InitAnsiEnd: RETURN thisRC
Check if ANSI is active - 2 -
/* sample routine to check if ANSI is activated (using REXXUTIL) */ /* based on a idea and code of Erik Schneller */ /* (see EMail Addresses) */ /* */ /* see also Check if ANSI is active - 1 - */ /* */ i = CheckAnsi() if i = 1 then say "ANSI is activated" else if i = 0 then say "ANSI is not activated." else say "Error detecting ANSI." exit 0 /* ------------------------------------------------------------------ */ /* function: Check if ANSI is activated */ /* */ /* call: CheckAnsi */ /* */ /* where: - */ /* */ /* returns: 1 - ANSI support detected */ /* 0 - no ANSI support available */ /* -1 - error detecting ansi */ /* */ /* note: Tested with the German and the US version of OS/2 3.0 */ /* based on a idea and code of Erik Schneller */ /* (see EMail Addresses) */ /* */ /* */ CheckAnsi: PROCEDURE thisRC = -1 /* install a local error handler */ SIGNAL ON ERROR Name InitAnsiEnd /* register the function SysCurPos from REXXUTIL */ call rxFuncAdd "SysCurPos", "REXXUTIL", "SysCurPos" /* get and save the current cursor position */ curPos = SysCurPos() /* write a CR/LF and the ANSI code for CursorUp */ call charOut , D2C(13) || "1B"x || "[1A" /* now get the current cursor position */ NewPos=SysCurPos() /* compare the new position to the old position */ if LEFT( NewPos,2 ) == LEFT( curPos,2 ) THEN do /* ANSI support is OFF */ thisRC = 0 /* goto the begin of the line and delete the garbage */ call CharOut, D2C(13) || copies( " ",4 ) || D2C(13) end /* if left( ... */ else do /* ANSI support is ON */ /* restore the old cursor position */ call CharOut , "1B"x || "[B" thisRC = 1 end /* else */ InitAnsiEnd: RETURN thisRC
Get the current cursor position
/* sample routine to get the current cursor position with plain REXX */ /* and ANSI commands */ /* Original code is from the ANSICD package from Jamie Hoglund */ parse value GetCursorPos() with col row say "At program start the cursor was at " || , "Column " || col || ", Row " || row || "." exit 0 /* ------------------------------------------------------------------ */ /* function: Get the current cursor position */ /* */ /* call: GetCursorPos */ /* */ /* returns: col row */ /* */ /* note: This function works only for display sizes up to 200 for */ /* columns or rows. The upper left corner is 1,1. */ /* The REXXUTIL function SysCurPos uses zero based values */ /* (the upper left corner is 0,0). */ /* Caution: v2.90*/ /* The REXX Queue must be empty for this code to work! */ /* If the REXX Queue is not empty, you can use code */ /* like */ /* - create a new */ /* - make the new queue the default queue */ /* - call GetCursorPos */ /* - make the old queue the default queue again */ /* - delete the new queue */ /* */ GetCursorPos: PROCEDURE usedChars = ":;<=>?@ABCD" Rc = Charout(,D2C(27) || "[6n") Pull Q /* v2.30 */ parse var q 3 y1 +1 y2 +1 3 row +2 6 x1 +1 x2 +1 6 col +2 . if pos( y1, usedChars ) <> 0 then row = 10 || y2 if pos( x1, usedChars ) <> 0 then col = 10 || x2 return col row
Get the current screen size
/* sample routine to get the current screensize for textmode windows */ /* without using REXXUTIL functions. */ parse value GetDisplaySize() with columns rows say "The current OS/2 window size is " || , rows || " rows and " || columns || " columns." exit 0 /* ------------------------------------------------------------------ */ /* function: Get the current display size */ /* */ /* call: GetDisplaySize */ /* */ /* returns: columns rows */ /* */ /* note: This function works only for display sizes up to 200 for */ /* columns or rows. The upper left corner is 1,1. */ /* The REXXUTIL function SysCurPos uses zero based values */ /* (the upper left corner is 0,0). */ /* */ GetDisplaySize: PROCEDURE expose thisPos usedChars = ":;<=>?@ABCD" /* save current cursor position */ rc = CharOut(, D2C(27) || '[' || "6n") pull curPos /* try to set the cursor to the position 200,200 */ rc = CharOut(, D2C(27) || '[' || "200;200H" ) /* get cursor position */ rc = CharOut(, D2C(27) || '[' || "6n") pull tPos /* restore current cursor position */ rc = CharOut(, substr( curPos,1, length( curPos)-1) || "H" ) /* v2.30 */ parse var tPos 3 y1 +1 y2 +1 3 rows +2 6 x1 +1 x2 +1 6 cols +2 . if pos( y1, usedChars ) <> 0 then rows = 10 || y2 if pos( x1, usedChars ) <> 0 then cols = 10 || x2 RETURN cols rows
Redefine some keys
/* sample code to do some key remapping with ANSI sequences */ /* see also ANSI ESC Sequences , */ /* Key codes for key redefinitions and */ /* Using function keys */ /* */ /* Note: Turning extended keys off is NOT necessary for key v1.60 */ /* remapping. This information in RXT&T v1.50 was wrong. v1.60 */ /* set F1 key to HELP<RETURN> */ call CharOut , '1B'x || '[0;59;"HELP";13p' /* set ALT-F10 to EXIT (without RETURN) */ call CharOut , '1B'x || '[0;113;"EXIT";p' /* set "A" to ABER (without RETURN) */ /* corrected in RXT&T v1.60 */ call CharOut , '1B'x || '[65;"ABER";p' /* reset F1 key to F1 */ call CharOut , '1B'x || '[0;59;0;59;p'
Using function keys
To use function keys without the REXXUTIL functions, redefine them with a trailing CR (see also ANSI ESC Sequences, Key codes for key redefinitions, and download RxLBox for a working example):
/* sample key redefinitons */ /* new definitons for the function keys */ keys.0 = 0 i = keys.0 i=i+1; keys.i.__org = '59'; keys.i.__new = 'F1' i=i+1; keys.i.__org = '60'; keys.i.__new = 'F2' i=i+1; keys.i.__org = '61'; keys.i.__new = 'F3' i=i+1; keys.i.__org = '62'; keys.i.__new = 'F4' i=i+1; keys.i.__org = '63'; keys.i.__new = 'F5' i=i+1; keys.i.__org = '64'; keys.i.__new = 'F6' i=i+1; keys.i.__org = '65'; keys.i.__new = 'F7' i=i+1; keys.i.__org = '66'; keys.i.__new = 'F8' i=i+1; keys.i.__org = '67'; keys.i.__new = 'F9' i=i+1; keys.i.__org = '68'; keys.i.__new = 'F10' keys.0 = i /* ANSI esc sequence */ ansi.__ESC = '1B'x /* special character to detect function keys */ specialChar = 'FE'x /* install error handler for CTRL-BREAK */ signal on halt /* redefine the function keys */ do i = 1 to keys.0 call CharOut , ansi.__ESC || '[0;' || keys.i.__org || ';' || , '"' || specialChar || keys.i.__New || specialChar || '"' || , ';13p' end /* do i = 1 to keys.0 */ /* test the new key definitons */ do forever call LineOut, 'Test the function key redefinitions' call CharOut, 'Enter a string (F10 to end): ' userInput = lineIn() /* test for function keys */ parse var UserInput part1 (specialChar) fKey (specialChar) part2 UserInput = part1 || part2 say 'Userinput was: "' || UserInput || '"' if fkey = '' then say 'No function key pressed.' else say 'Function key "' || fkey || '" pressed.' if fkey = 'F10' then leave end /* do forever */ ProgramEnd: /* undo the key redefinitons */ do i = 1 to keys.0 call CharOut , ansi.__ESC || '[0;' || keys.i.__org || ';' || , '0;' || keys.i.__org || ';p' end /* do i = 1 to keys.0 */ exit /* error handler for CTRL-BREAK */ Halt: say say 'Program aborted by the user!' signal ProgramEnd
Use ANSI for a password input routine
/* sample input routine for passwords using ANSI sequences to hide */ /* the input (stolen from a message on a public CompuServe forum) */ /* */ myPassWord = GetPassword( "Please enter the password: " ) say "You entered the password: " || myPassword exit /* ------------------------------------------------------------------ */ /* function: get a password from the user (without showing it on the */ /* screen) */ /* */ /* call: GetPassword( {prompt} ) */ /* */ /* where: prompt - prompt string */ /* def.: none */ /* */ /* returns: the entered password */ /* */ /* note: This code only works with ANSI enabled */ /* */ /* */ GetPassword: PROCEDURE parse arg prompt /* show the prompt (if any) and set the screen */ /* attributes to notvisible */ call CharOut , prompt || "1B"x || "[8m" /* get the user input */ parse pull password /* reset the screen attributes */ call CharOut , "1B"x || "[0m" RETURN password
Using the lower right corner of the display
To print a character to the lower right corner of the screen without scrolling you must turn off the word wrap function of the ANSI driver (see also ANSI ESC Sequences):
/* code to show how to use the lower right corner of the display */ /* ESC code for ANSI sequences */ ansi.__ESC = "1B"x /* ANSI sequences to position the cursor in the */ /* upper right corner */ ansi.__Pos0 = ansi.__ESC || "[1;1H" /* ANSI code to turn word wrap off */ ansi.__WordWrapOff = ansi.__ESC || "[7l" /* ANSI code to turn word wrap on */ ansi.__WordWrapOn = ansi.__ESC || "[7h" /* empty line for the menu frame */ Menu.__emptyLine = "º" || copies( " ", 78 ) || "º" /* separator lines for the menu frame */ Menu.__FrameLine1 = copies( "Í", 78 ) Menu.__FrameLine2 = copies( "Ä", 76 ) /* menu frame */ Menu.__MenuMask = , ansi.__Pos0 || , /* position cursor */ ansi.__WordWrapOn || , /* turn word wrap on! */ "É" || Menu.__FrameLine1 || "»" || , /* menu frame */ Menu.__emptyLine || , Menu.__emptyLine || , "º " || Menu.__FrameLine2 || " º" || , Menu.__emptyLine || , "Ì" || Menu.__FrameLine1 || "¹" || , copies( Menu.__emptyLine, 14 ) || , "Ì" || Menu.__FrameLine1 || "¹" || , Menu.__emptyLine || , "º " || Menu.__FrameLine2 || " º" || , Menu.__emptyLine || , ansi.__WordWrapOff || , /* turn word wrap off */ "È" || Menu.__FrameLine1 || "¼" || , /* last menu line */ ansi.__Pos0 || , /* position cursor */ ansi.__WordWrapOn /* turn word wrap on */ /* clear the screen */ 'cls' /* show the menu frame */ call CharOut , Menu.__MenuMask /* position the cursor in the middle of the */ /* screen */ call CharOut , ansi.__ESC || "[12;30H" /* wait for a key from the user */ "@pause"