/* BEGINNING OF CmdLine CODE BY ALBERT CROSBY */ /* */ /* */ /* CmdLine.CMD Version 1.0 */ /* (c) 1994 by Albert Crosby <acrosby@comp.uark.edu> */ /* */ /* This code may be distributed freely and used in other programs.*/ /* Please give credit where credit is due. */ /* */ /* CmdLine.CMD is REXX code that creates a full featured version */ /* of the OS/2 command line parser that may be called from your */ /* programs. */ /* */ /* see also the Documentation */ /* */ /* bug corrections by Bernd Schemmer */ /* */ /* 03.10.1994 /bs */ /* - changed variable "key" to "key1" */ /* - added variable "userDefinedKey" */ /* 24.06.1995 /bs */ /* - added code to save the and load the history list */ /* - added code to show an online help */ /* 08.01.1996 /bs */ /* - added code to handle dropping of REXXUTIL functions */ /* */ /* */ /* This is a CmdLine function for REXX. It supports */ /* * OS/2 style command history. (1) */ /* * Keeps insert state. (1) */ /* * Command line _can_ include control chars. */ /* * Allows for "hidden" input, for passwords. */ /* * A call can be restricted from accessing the history. */ /* * A call can be restricted from updating the history. */ /* * A predefined value can be given to extended keys. (1) (2) */ /* */ /* NOTE */ /* (1) These functions work ONLY if CmdLine is included in the source */ /* file for your program. */ /* (2) Format: !history.nn="string" where nn is the DECIMAL */ /* value for the second character returned when the extended */ /* key is pressed. */ /* */ /* The following two lines are used in case CmdLine is called as an */ /* external function */ parse source . . name if translate(filespec("name",name))="CMDLINE.CMD" then signal extproc CmdLine: procedure expose !history. !rexxUtilLoaded (exposeList) extproc: /* CmdLine called as an external proc or command line */ /* Parameters can be any combination of */ /* Hidden Characters are displayed as "*", no history, */ /* not kept. */ /* Forget Do not add the result of this call to the */ /* history list. */ /* No History Do not allow access to the history list. */ /* Clear Clear the history list with this call (no input */ /* action made.) */ /* Also clears any predefined keys! */ /* Insert Set insert mode ON. */ /* Overwrite Set overwrite mode OFF. */ /* SameLine Keep cursor on sameline after input. */ /* (Default off) */ /* Required null values are not accepted. (Default off) */ /* Valid Next parameter specifies the valid charachters */ /* (no translation) unless specified elsewhere. (1)*/ /* Upper Translate input to upper case. (1) */ /* Lower Translate input to lower case. (1) */ /* Width Next parameter specifies the maximum width. (1) */ /* Autoskip Do not wait for enter after last char on a */ /* field with a width. */ /* X Next parameter specifies the initial X (column) */ /* position. */ /* Y Next parameter specifies the initial Y (row) */ /* position. */ /* Prompt Displays the next parameter as a prompt in front*/ /* of the entry field. */ /* */ /* Only the first letter matters. Enter each desired parameter */ /* seperated by commas. */ /* */ /* NOTES */ /* (1) Upper, Lower, Width, and VALID preclude access to the */ /* history list. */ /* */ /* */ hidden=0 history=1 keep=1 sameline=0 required=0 reset=0 valid=xrange() upper=0 lower=0 width=0 autoskip=0 /* ------------------------ RXT&T v2.00 start ----------------------- */ /* install a local error handler */ signal on syntax Name cmdLineError /* ------------------------ RXT&T v2.00 end ------------------------- */ /* ------------------------ RXT&T v1.70 start ----------------------- */ if symbol( "!history.file" ) <> "VAR" | , value( "!history.file" ) = "" then !history.file = "EREXXTRY.HST" /* ------------------------ RXT&T v1.70 end ------------------------- */ parse value SysCurPos() with x y do i=1 to arg() cmd=translate(left(arg(i),1)) parm="" if pos("=",arg(i))\=0 then parse value arg(i) with ."="parm select when cmd="X" then do parse value SysCurPos() with x y if parm="" then do;i=i+1;parm=arg(i);end if datatype(parm,"W") then Call SysCurPos parm,y end when cmd="Y" then do parse value SysCurPos() with x y if parm="" then do;i=i+1;parm=arg(i);end if datatype(parm,"W") then Call SysCurPos x,parm end when cmd="T" then do if parm="" then do;i=i+1;parm=arg(i);end call charout, parm end when cmd="H" then do hidden=1 keep=0 history=0 end when cmd="C" then reset=1 when cmd="O" then !history.insert=0 when cmd="I" then !history.insert=1 when cmd="F" then keep=0 when cmd="S" then sameline=1 when cmd="R" then required=1 when cmd="V" then do if parm="" then do;i=i+1;parm=arg(i);end valid=parm history=0 keep=0 end when cmd="U" then do; upper=1; lower=0; history=0; keep=0; end when cmd="L" then do; upper=0; lower=1; history=0; keep=0; end when cmd="A" then autoskip=1 when cmd="W" then do if parm="" then do;i=i+1;parm=arg(i);end width=parm if \datatype(width,"Whole") then width=0 if width<0 then width=0 history=0 keep=0 end otherwise nop end end if width=0 then autoskip=0 if reset then do drop !history. return "" end if symbol("!history.0")="LIT" then !history.0=0 if symbol("!history.insert")="LIT" then !history.insert=1 historical=-1 key1=SysGetKey("NoEcho") word="" pos=0 do forever /* while key1\=d2c(13)*/ userDefinedkey=0 if key1=d2c(13) then /* Enter key */ if required & word="" then nop; else leave else if (key1=d2c(8)) then /* Backspace */ do if length(word)>0 then do word=delstr(word,pos,1) call rubout 1 pos=pos-1 if pos<length(word) then do if \hidden then call charout, substr(word,pos+1)||" " else call charout, copies("*",length(substr(word,pos+1)))||" " call charout, copies(d2c(8),length(word)-pos+1) end end end else if key1=d2c(27) then /* Escape */ do if pos<length(word) then if \hidden then call charout, substr(word,pos+1) else call charout, copies("*",length(substr(word,pos+1))) call rubout length(word) word="" pos=0 end else if key1=d2c(10) | key1=d2c(9) then /* Ctrl-Enter and TAB */ nop; /* Ignored */ else if key1=d2c(224) | key1=d2c(0) then /* Extended key handler */ do key2=SysGetKey("NoEcho") select /* ----------------------- RXT&T v1.70 start ------------------------ */ when key2=d2c( 94 ) then /* CTRL-F1 */ do call ShowKeys word = '' pos = 0 userDefinedKey = 1 end /* when */ when key2=d2c( 60 ) then /* F2 */ do /* save the history list */ call SLHist 'SAVE' word = '' pos = 0 userDefinedKey = 1 end /* when */ when key2=d2c( 85) then /* SHIFT-F2 */ do /* load the history list */ call SLHist 'LOAD' word = '' pos = 0 userDefinedKey = 1 end /* when */ when key2=d2c( 105 ) then /* ALT-F2 */ do /* append the history list */ call SLHist 'APPEND' word = '' pos = 0 userDefinedKey = 1 end /* when */ when key2=d2c( 95 ) then /* CTRL-F2 */ do /* change the current history file */ call SLHist 'FILE' word = '' pos = 0 userDefinedKey = 1 end /* when */ when key2=d2c( 107 ) then /* ALT-F4 */ do /* save the history list and exit */ /* (without a warning if the list is empty */ call SLHist 'SAVE', 'QUIET' word = 'EXIT' userdefinedkey = 1 end /* when */ /* ------------------------ RXT&T v1.70 end ------------------------- */ when key2=d2c(59) then /* F1 */ if (history) & (!history.0<>0) then do if symbol("search")="LIT" then search=word if symbol("LastFind")="LIT" then search=word else if LastFind\=word then search=word if historical=-1 then start=!history.0 else start=historical-1 if start=0 then start=!history.0 found=0 do i=start to 1 by -1 if abbrev(!history.i,search) then do found=1 historical=i LastFind=!history.i leave end end if found then do if pos<length(word) then if \hidden then call charout, substr(word,pos+1) else call charout, copies("*",length(substr(word,pos+1))) call rubout length(word) word=!history.historical pos=length(word) if \hidden then call charout, word else call charout, copies("*",length(word)) end end when key2=d2c(72) then /* Up arrow */ if (history) & (!history.0<>0) then do if historical=-1 then historical=!history.0 else historical=historical-1 if historical=0 then historical=!history.0 if pos<length(word) then if \hidden then call charout, substr(word,pos+1) else call charout, copies("*",length(substr(word,pos+1))) call rubout length(word) word=!history.historical pos=length(word) if \hidden then call charout, word else call charout, copies("*",length(word)) end when key2=d2c(80) then /* Down arrow */ if (history) & (!history.0<>0) then do if historical=-1 then historical=1 else historical=historical+1 if historical>!history.0 then historical=1 if pos<length(word) then if \hidden then call charout, substr(word,pos+1) else call charout, copies("*",length(substr(word,pos+1))) call rubout length(word) word=!history.historical pos=length(word) if \hidden then call charout, word else call charout, copies("*",length(word)) end when key2=d2c(75) then /* Left arrow */ if pos>0 then do call Charout, d2c(8) pos=pos-1 end when key2=d2c(77) then /* Right arrow */ if pos<length(word) then do if \hidden then call Charout, substr(word,pos+1,1) else call charout, "*" pos=pos+1 end when key2=d2c(115) then /* Ctrl-Left arrow */ if pos>0 then do call charout, d2c(8) pos=pos-1 do forever if pos=0 then leave if substr(word,pos+1,1)\==" " & substr(word,pos,1)==" " then leave else do call charout, d2c(8) pos=pos-1 end end end when key2=d2c(116) then /* Ctrl-Right arrow */ if pos<length(word) then do if \hidden then call Charout, substr(word,pos+1,1) else call charout, "*" pos=pos+1 do forever if pos=length(word) then leave if substr(word,pos,1)==" " & substr(word,pos+1,1)\==" " then leave else do if \hidden then call Charout, substr(word,pos+1,1) else call charout, "*" pos=pos+1 end end end when key2=d2c(83) then /* Delete key */ if pos<length(word) then do word=delstr(word,pos+1,1) if \hidden then call Charout, substr(word,pos+1)||" " else call Charout, copies("*",length(substr(word,pos+1)))||" " call charout, copies(d2c(8),length(word)-pos+1) end when key2=d2c(82) then /* Insert key */ !history.insert=\!history.insert when key2=d2c(79) then /* End key */ if pos<length(word) then do if \hidden then call Charout, substr(word,pos+1) else call Charout, copies("*",length(substr(word,pos+1))) pos=length(word) end when key2=d2c(71) then /* Home key */ if pos\=0 then do call Charout, copies(d2c(8),pos) pos=0 end when key2=d2c(117) then /* Control-End key */ if pos<length(word) then do call Charout, copies(" ",length(word)-pos) call Charout, copies(d2c(8),length(word)-pos) word=left(word,pos) end when key2=d2c(119) then /* Control-Home key */ if pos>0 then do if pos<length(word) then if \hidden then call charout, substr(word,pos+1) else call charout, copies("*",length(substr(word,pos+1))) call rubout length(word) word=substr(word,pos+1) if \hidden then call Charout, word else call Charout, copies("*",length(word)) call Charout, copies(d2c(8),length(word)) pos=0 end otherwise if history & symbol("!history.key."||c2d(key2))\="LIT" then /* Is there a defined string? */ do if pos<length(word) then if \hidden then call charout, substr(word,pos+1) else call charout, copies("*",length(substr(word,pos+1))) call rubout length(word) i=c2d(key2) word=!history.key.i pos=length(word) if \hidden then call charout, word else call charout, copies("*",length(word)) userDefinedkey=1 end end end else if width=0 | length(word)<width then /* The key is a normal key & within width */ do if upper then key1=translate(key1); if lower then key1=translate(key1,"abcdefghijklmnopqrstuvwxyz","ABCDEFGHIJKLMNOPQRSTUVWXYZ") if pos(key1,valid)\=0 then do; if \hidden then call Charout, key1; else call charout, "*" if !history.insert then word=insert(key1,word,pos); else word=overlay(key1,word,pos+1) pos=pos+1; if pos<length(word) then do if \hidden then call Charout, substr(word,pos+1) else call Charout, copies("*", length(substr(word,pos+1))) call Charout, copies(d2c(8),length(word)-pos) end end else beep(400,4) end if (autoskip & length(word)=width) | userDefinedKey then leave key1=SysGetKey("NoEcho") end if \sameline then say if (keep) & (word\=="") then do historical=!history.0 if word\=!history.historical then do !history.0=!history.0+1 historical=!history.0 !history.historical=word end end return word rubout: procedure arg n do i=1 to n call Charout, d2c(8)||" "||d2c(8) end return /* END OF CmdLine CODE BY ALBERT CROSBY */ /* ----------------------- RXT&T v1.70 start ------------------------ */ /* ------------------------------------------------------------------ */ /* Function: Save or Load the history list or change the name of the */ /* history file */ /* */ /* Usage: SLHist [SAVE|APPEND|LOAD|FILE], {QUIET} */ /* */ /* */ /* where: SAVE - save the history list to the history file */ /* (overwrite an existing file) */ /* APPEND - append the history list to the history file */ /* LOAD - load the histry list from the history file */ /* FILE - change the current history file */ /* */ /* QUIET - suppress all mesages */ /* This parameter is ignored, if the first */ /* parameter is FILE */ /* */ SLHist: PROCEDURE expose !history. parse upper arg action, quietMode SIGNAL OFF NOTREADY crLF = "0D0A"x select when action = "FILE" then do call lineOut, crLF || "The current history file is " || !history.file || "." , crLF || "Enter the new name for the history file ("""" to abort):" userInput = strip( lineIN() ) if userInput <> "" then do !History.file = userInput call lineOut , "The history file is now " || !history.file || "." end /* if userInput = "" then */ else call lineOut, "History file not changed." end /* when */ when !History.file = "" then do if quietMode <> "QUIET" then call lineOut ,crLF || "No history file defined!" end when action = "SAVE" | action = "APPEND" then do if !history.0 = 0 then do if quietMode <> "QUIET" then call LineOut , crLF || "Historylist is empty. No data saved." end /* if !history.0 = 0 then */ else do if action = "SAVE" then do /* delete an existing history file */ if stream( !history.file, "c", "QUERY EXISTS" ) <> "" then "@del " !history.file "2>NUL 1>NUL" actionMsg = "Saving" end /* if action = "SAVE" then */ else actionmsg = "Appending" if quietMode <> "QUIET" then call CharOut , crLF || actionmsg || " the history list to the file" , crLF !history.file || " ..." do i = 1 to !history.0 if quietMode <> "QUIET" then call CharOut , "." call lineOut !history.file, !history.i end /* do i = 1 to history.0 */ /* close the file */ call stream !history.file, "c", "CLOSE" if quietMode <> "QUIET" then call lineOut, " done (" || i-1 || " commands written)." end /* else */ end /* when */ when action = "LOAD" then do if stream( !history.file, "c", "QUERY EXISTS" ) = "" then do if quietMode <> "QUIET" then call LineOut , crLF || "Historyfile " || , !history.file || " not found!" end /* if stream( ... */ else do if quietMode <> "QUIET" then call CharOut , crLF || "Loading the history list from the file" , crLF !history.file || " ..." !history.0 = 0 do i=1 while lines( !history.file ) <> 0 if quietMode <> "QUIET" then call CharOut , "." !history.i = lineIn( !history.file ) end /* do i=1 while lines( !history.file ) <> 0 */ !history.0 = i-1 /* close the file */ call stream !history.file, "c", "CLOSE" if quietMode <> "QUIET" then call lineOut, "done (" || i-1 || " commands read)." end /* else */ end /* when */ otherwise do if quietMode <> "QUIET" then call lineOut,crLF || "Invalid call to SLHist!" end /* otherwise */ end /* select */ RETURN 0 /* ------------------------------------------------------------------ */ /* Function: Show a usage help for the new keys */ /* */ /* Usage: ShowKeys */ /* */ /* where: - */ /* */ /* returns: - */ /* */ ShowKeys: crLF = "0D0A"x call LineOut ,, crLF || , "Keys for editing the command line: " || crLF || , " [Up] Cycle to the previous entry in the history list" || crLF || , " [Down] Cycle to the next entry in the history list" || crLF || , " [Left] Move the cursor to the left" || crLF || , " [Right] Move the cursor to the right" || crLF || , " [ESC] Clear the input line" || crLF || , " [Home] Moves the cursor to the beginning of the input line" || crLF || , " [End] Moves the cursor to the end of the input line" || crLF || , " [^Home] Erases from the cursor to the beginning of the input line" || crLF || , " [^End] Erases from the cursor to the end of the input line" || crLF || , " [Ins] Toggles Insert/Typeover mode" || crLF || , " [Del] Deletes character under the cursor" || crLF || , " [Bkspc] Deletes the charcter in front of the cursor" || crLF || , " [^Left] Moves to the beginning of the previous word" || crLF || , " [^Right] Moves to the beginning of the next word" || crLF || , " " || crLF || , " [F2] Save the history list (overwrite an existing file)" || crLF || , " [ALT-F2] Save the history list (append to an existing file)" || crLF || , " [SHIFT-F2] Load the history list" || crLF || , " [CTRL-F2] Change the history list file" || crLF || , " [ALT-F4] Save history list and exit program" RETURN /* ------------------------ RXT&T v1.70 end ------------------------- */ /* ------------------------ RXT&T v2.00 start ----------------------- */ cmdLineError: /* error handler for syntax error */ /* some program dropped the REXXUTIL function --- */ /* use old input routine again */ call LineOut , "" call LineOut , "07"x || "Warning: Some program dropped the REXXUTIL functions!" call LineOut , "07"x || " Now using the old input routine again." call LineOut , "" call LineOut , "Execute 'SIGNAL Restart' to load the functions again." call LineOut , "" !rexxUtilLoaded = 0 RETURN "" /* ------------------------ RXT&T v2.00 end ------------------------- */