Currently procedure requires Aacini's cursorpos.exe.
Code: Select all
@echo off
REM -------------------------------------MENU SYSTEM----------------------------------------------
REM (C) 2000 Saso Tomat - First developed in DCL on OpenVMS
REM (C) 2014 Saso Tomat - Port to Windows Batch
REM Procedure uses Aacini's cursorpos.exe
REM
REM This is a menu system with menu options in a fixed length format within this procedure.
REM
REM This procedure should be called with parameters:
REM parameter1: username
REM parameter2: privilege user has
REM parameter3: user's job description or depertment description or something similar
REM parameter4: currently not in use. Could be used for defining a current folder
REM parameter5: first name/last name
REM
REM parameter3 and parameter5 are displayed in the top of the screen
REM parameter2 is used to check access privileges
REM ----------------------------------------------------------------------------------------------
set filnam=%0
REM Below REM should be removed in production
REM call :INIT %1 %2 %3 %4 %5
REM Below two lines should be removed in production. These are here only for testing purposes
call :INIT "SASO" "9" "SYSTEM MANAGER HAS FULL ACCESS" "X" "SASO TOMAT"
REM call :INIT "JOHN" "3" "HUMAN RESOURCES" "X" "JOHN DOE"
set hd=&rem
:00
set key1=%levelk%
set old_level=%levelk%
call :frame
if "%level%"=="0" echo 0 Exit
if not "%level%"=="0" echo 0 Previous menu
set strng=00/
findstr /B /C:"MMMMM%key1%" %filnam%>find.temp
for /f "tokens=1,2,3,4,5 delims=#" %%f in (find.temp) do call :0 "%%f" "%%g" "%%h" "%%i" "%%j"
if exist find.temp del find.temp
goto :1
:0
set selections=%~1
set selections=%selections:~5%
REM variable rp contains list of required privileges to access the selection. Priv 9 (full access) is
REM added automatically so the person who manages (or system manager) this menus has full access.
REM if required privilege is 'A' then this selection is skipped (not in use anymore - archived)
set rp=%~2
if not "%rp%"=="A" set rp=%rp%9
REM apl$priv:user's privilege
set au=0
>rp.temp (echo %rp%)
findstr /C:"%apl$priv%" rp.temp>nul&&set au=1
findstr /C:"0" rp.temp>nul&&set au=1
if exist rp.temp del rp.temp
REM au=1=user has access to the current selection
REM au=0=user does not have access to the current selection
set ti=%~3
set op=%~4
set rf=%~5
set /a selec_tmp=2+2*level
call set selec=%%selections:~%selec_tmp%,2%%
set /a nselec_tmp=4+2*level
call set nselec=%%selections:~%nselec_tmp%,2%%
call :strlen %old_level% old_level_len
call set old_level_tmp=%%selections:~0,%old_level_len%%%
if not "%old_level%"=="%old_level_tmp%" goto :1
set dod= &rem
if "%au%"=="1" if "%ti%"=="M" set dod=menu &rem
if "%au%"=="1" if "%ti%"=="M" if "%selec%"=="00" set hd=%hd%/%op%
if "%au%"=="1" if "%nselec%"=="00" if not "%selec%"=="00" call :DISPLAY_SELECTION
goto :EOF
:DISPLAY_SELECTION
set /a selecnum=100%selec% %% 100
set selec_tmp= %selecnum%
set selec_tmp=%selec_tmp:~-2%
echo %dod%%selec_tmp% %op%
set strng=%strng%%selec%/
set type_%level%_%selec%=%ti%
set rf_%level%_%selec%=%rf%
goto :EOF
:1
cursorpos=2,5
echo %hd:~1%
set uchoice=0
cursorpos=0,23
set /p "uchoice=[0] "
:02
if "%uchoice%"=="0" goto :9
set uchoice=00%uchoice%
set uchoice=%uchoice:~-2%
>rp.temp (echo %strng%)
findstr /C:"%uchoice%/" rp.temp>nul||goto :991
call set ttt=%%type_%level%_%uchoice%%%
if "%nselec%"=="00" if "%ttt%"=="C" goto :EXECUTE
set levelk=%levelk%%uchoice:~-2%
set /a level+=1
goto :00
:9
if "%level%"=="0" goto :fin
set /a level-=1
call :strlen %levelk% levelk_tmp
set /a levelk_tmp-=2
call set levelk=%%levelk:~0,%levelk_tmp%%%
:991
set /a cnt=0
set hdc=/&rem
:99
set /a cnttmp=cnt+1
for /F "tokens=%cnttmp% delims=/" %%t in ("/_%hd%") do set hdc=%hdc%%%t/
set /a cnt+=1
if %cnt% LEQ %level% goto :99
set hd=%hdc:~2,-1%
goto :00
:EXECUTE
REM Lines below should be corrected in production
REM maybe checking for file existence should be added
REM (what about labels?)
call set rf=%%rf_%level%_%uchoice%%%
echo EXECUTING %rf%
%rf%
goto :991
REM ---------------INIT--------------------
:INIT
if not exist cursorpos.exe call :createcursorposexe
set levelk=00
set /a level=0
if "%~1"=="" set apl$user=&rem
if not "%~1"=="" set apl$user=%~1
if "%~2"=="" set apl$priv=0
if not "%~2"=="" set apl$priv=%~2
if "%~3"=="" set apl$menu=&rem
if not "%~3"=="" set apl$menu=%~3
if "%~4"=="" set apl$lib=&rem
if not "%~4"=="" set apl$lib=%~4
if "%~5"=="" set apl$owner=&rem
if not "%~5"=="" set apl$owner=%~5
call :strlen "%apl$menu%" mx
set /a mx=39-(mx/2)
call :makebinvalue 218
call :makebinvalue 196
call :makebinvalue 191
call :makebinvalue 179
call :makebinvalue 192
call :makebinvalue 217
call :makebinvalue 219
set lines=%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%
set line0=%znak218%%lines%%lines%%lines%%lines%%lines%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak191%
set line1=%znak179% %apl$owner% &rem
call set line1=%%line1:~0,%mx%%%
set line1=%line1%%apl$menu% &rem
set line1=%line1:~0,78%%znak179%
set line2=%znak192%%lines%%lines%%lines%%lines%%lines%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak196%%znak217%
goto :EOF
:strlen
set par1=%~1
>temporary_file.tmp (echo %par1%)
for %%Z in (temporary_file.tmp) do set %~2=%%~zZ&&set /a %~2-=2
if exist temporary_file.tmp del temporary_file.tmp
goto :EOF
:fin
if exist rp.temp del rp.temp
goto :EOF
:frame
cls
set message= No messages.&rem
if exist message.txt set message=Message exists.
set line3= %message%
echo %line0%
echo %line1%
echo %line2%
echo %line3%
echo.
echo.
echo.
echo.
goto :EOF
:makebinvalue
set par1=%1
type nul > t.tmp
makecab /d compress=off /d reserveperdatablocksize=26 /d reserveperfoldersize=%par1% t.tmp %par1%.chr > nul
type %par1%.chr | ( (for /l %%N in (1,1,38) do pause)>nul & findstr "^" > temp.tmp )
>nul copy /y temp.tmp /a %par1%.chr /b
del t.tmp temp.tmp
for /F "delims=" %%a in (%par1%.chr) do set "znak%par1%=%%a"
del %par1%.chr
goto :EOF
:createcursorposexe
for %%b in (
"4D53434600000000DB020000000000002C000000000000000301010001000000000000004A0000000100010000060000"
"000000000000C944C5392000637572736F72706F732E65786500681767E789020006434BD5534D485451143EEFCD288E"
"BF5346B810BA4642510D836E0A6A187F9E56F83338B989825E33F7354F67DE933BF791CB07B9D14968D3AAA0555B6991"
"21D2C21A0BC2DC4448E04654E43533418B341465BAEF67666C530A2DEAC039E7DE73BEF31DCEFDE9BDF1105C00E0669A"
"CF03CC802D41F8B33C675A7B62B6165E78169B66B89EC5A6EB31398946887A97880914111545A5E80E46445390ACA0CE"
"FE304AA851ECABA9A93CE5700C4ECFEC1DF9B43455D0A70B6FA71A98FFFA7D7EAA9EF901391233E3859E2101A087E321"
"3BB6DA5F88AD401D57C5955503CF36BC13F43A8A9C69BC76CEEDA40B1EFCA51A57A1D0BBDF179D258D8CEFF401CEE6D0"
"C2781B7F93F6513C4A996FE7A0384B71D612C56D1F898A5404D8720216C6FD2B2EB8EF7A8D72F3508D7A463B98CADD9F"
"5F19DA348EB2CDB8B03B296C84F2DAAEB1C710524AC849E3C2BAF1CAAC5966460F8056961232D99B7AE0B256DE65BCB3"
"60BD19E31A98E51963DA46D1063D70CE043CB301EBC61973312EE452B73261B38179B966B3F0103729AC593D1FB150DD"
"4B61ED7DBA75AE65B9F5E3C4F12E7DE72CADD077CE6B1E7D81D717382BE42775FACEC57B957AC63F3C57E97A93FDB295"
"E668D5569AA72EE9C767C9F5BA2FFD61BF18DD8C39F56DA2BCEBD249CD63BBED6CB5B940D43D36A76DF6A5EDCD36ABCC"
"371F4341C8378365DD96ADB06CB565BDE820FFE45F1685BD91074C9F309D65BA643E2264E73A510967A0C25F3A1CC763"
"1046651A226A042793B009DD9876A84A528DE3708460ACB46B9284C9554552018638960DD3E8155189C631C0057E008B"
"5107DEAFD1118D76C444224628266D90E0C345AE0E8D24551252933295550560C3EE934830A61E59C16D308C8982E3AD"
"2DBE683CFE9F5FD95F959F") Do >>cursorpos.exe (Echo.For b=1 To len^(%%b^) Step 2
Echo WScript.StdOut.Write Chr^(CByte^("&H"^&Mid^(%%b,b,2^)^)^) : Next)
Cscript /b /e:vbs cursorpos.exe > cursorpos.ex_
Expand -r cursorpos.ex_ cursorpos.exe>nul 2>&1
if exist cursorpos.ex_ del cursorpos.ex_
Goto :Eof
MMMMM.-----selections----->#required privs#M=MENU, C=CMD#description#what to do (call a .cmd or call a label)
MMMMM0000000000000000000000#0#M#MAIN MENU#
MMMMM0001000000000000000000#0#C#Read message#goto :READ_MESSAGE
MMMMM0002000000000000000000#A#C#Option 2#call FILE_02.cmd
MMMMM0004000000000000000000#1#C#Option 4-priv 1#call FILE_04.cmd
MMMMM0005000000000000000000#12#C#Option 5-privs 1,2#call FILE_05.cmd
MMMMM0007000000000000000000#34#M#REPORTS HR and FINANCE#
MMMMM0007010000000000000000#3#M#Reports HR#
MMMMM0007010100000000000000#3#C#Report 1#call FILE_07_01_01.cmd
MMMMM0007010200000000000000#3#C#Report 2#call FILE_07_01_02.cmd
MMMMM0007010300000000000000#3#C#Report 3#call FILE_07_01_03.cmd
MMMMM0007010400000000000000#3#C#Report 4#call FILE_07_01_04.cmd
MMMMM0007010500000000000000#3#C#Report 5#call FILE_07_01_05.cmd
MMMMM0007010600000000000000#3#C#Report 6#call FILE_07_01_06.cmd
MMMMM0007010700000000000000#3#C#Report 7#call FILE_07_01_07.cmd
MMMMM0007010800000000000000#3#C#Report 8#call FILE_07_01_08.cmd
MMMMM0007010900000000000000#3#C#Report 9#call FILE_07_01_09.cmd
MMMMM0007020000000000000000#4#M#Reports FINANCE#
MMMMM0007020100000000000000#4#C#Report 1-Finance#call FILE_07_02_01.cmd
MMMMM0007020200000000000000#4#C#Report 2-Finance#call FILE_07_02_02.cmd
MMMMM0007020300000000000000#4#C#Report 3-Finance#call FILE_07_02_03.cmd
MMMMM0007020400000000000000#4#C#Report 4-Finance#call FILE_07_02_04.cmd
MMMMM0007020500000000000000#4#C#Report 5-Finance#call FILE_07_02_05.cmd
MMMMM0007020600000000000000#4#C#Report 6-Finance#call FILE_07_02_06.cmd
MMMMM0007020700000000000000#4#C#Report 7-Finance#call FILE_07_02_07.cmd
MMMMM0010000000000000000000#5#M#OPERATIONS#
MMMMM0010020000000000000000#5#C#File transfer 1#call FILE_10_02.cmd
MMMMM0010030000000000000000#5#C#File transfer 2#call FILE_10_03.cmd
MMMMM0010040000000000000000#5#C#File transfer 3#call FILE_10_04.cmd
MMMMM0010050000000000000000#5#C#File transfer 4#call FILE_10_05.cmd
MMMMM0010070000000000000000#5#C#File transfer 5#call FILE_10_07.cmd
MMMMM0010080000000000000000#5#M#PRINTING#
MMMMM0010080100000000000000#5#C#Job 1#goto :CONTINUE1
MMMMM0010080200000000000000#5#C#Job 2#call FILE_10_08_02.cmd
MMMMM0010080300000000000000#5#C#Job 3#call FILE_10_08_03.cmd
MMMMM0010080400000000000000#5#C#Job 4#call FILE_10_08_04.cmd
MMMMM0010080500000000000000#5#C#Job 5#call FILE_10_08_05.cmd
MMMMM0010080600000000000000#5#C#Job 6#call FILE_10_08_06.cmd
MMMMM0010081000000000000000#5#C#Job 7#call FILE_10_08_10.cmd
MMMMM0010081100000000000000#5#C#Job 8#call FILE_10_08_11.cmd
MMMMM0010081200000000000000#5#C#Job 9#call FILE_10_08_12.cmd
MMMMM0010081300000000000000#5#C#Job 10#call FILE_10_08_13.cmd
MMMMM0010090000000000000000#5#M#QUEUE MANAGEMENT#
MMMMM0010090100000000000000#5#C#Stop que $LPA#call FILE_10_09_01.cmd
MMMMM0010090200000000000000#5#C#Stop que $LPB#call FILE_10_09_02.cmd
MMMMM0010090300000000000000#5#C#Stop que $LPC#call FILE_10_09_03.cmd
MMMMM0010090400000000000000#5#C#Stop que $LPD#call FILE_10_09_04.cmd
MMMMM0016000000000000000000#6#M#WEB SUPPORT#
MMMMM0016010000000000000000#6#C#Task 1#call FILE_16_01.cmd
MMMMM0016020000000000000000#6#C#Task 2#call FILE_16_02.cmd
MMMMM0016040000000000000000#6#C#Task 3#call FILE_16_04.cmd
MMMMM0016050000000000000000#6#C#Task 4#call FILE_16_05.cmd
MMMMM0016060000000000000000#6#C#Task 5#call FILE_16_06.cmd
MMMMM0016070000000000000000#6#C#Task 6#call FILE_16_07.cmd
MMMMM0016080000000000000000#6#C#Task 7#call FILE_16_08.cmd
MMMMM0016090000000000000000#6#C#Task 8#call FILE_16_09.cmd
MMMMM0016100000000000000000#6#C#Task 9#call FILE_16_10.cmd
MMMMM0016110000000000000000#6#C#Task 10#call FILE_16_11.cmd
MMMMM0016120000000000000000#6#C#Task 11#call FILE_16_12.cmd
MMMMM0017000000000000000000#7#M#ANOTHER DEPARTMENT#
MMMMM0017050000000000000000#7#C#Report 1#call FILE_17_05.cmd
MMMMM0017060000000000000000#7#C#Job 1#call FILE_17_06.cmd
MMMMM0030000000000000000000#9#M#UTILITIES#
MMMMM0030010000000000000000#9#C#Write message#goto :WRITE_MESSAGE
MMMMM0030020000000000000000#9#C#Delete message#goto :DELETE_MESSAGE
MMMMM0030030000000000000000#9#C#Show active transfer#call FILE_30_03.cmd
MMMMM0030040000000000000000#9#C#Show errors#call FILE_30_04.cmd
MMMMM0030050000000000000000#9#C#Check passive line#call FILE_30_05.cmd
MMMMM0030060000000000000000#9#C#Check active line#call FILE_30_06.cmd
MMMMM0030070000000000000000#9#C#Delete log files#call FILE_30_07.cmd
MMMMM0030080000000000000000#9#C#Get file 1#call FILE_30_08.cmd
MMMMM0030090000000000000000#9#C#Get file 2#call FILE_30_09.cmd
MMMMM0030100000000000000000#9#C#Check scheduler#call FILE_30_10.cmd
MMMMM0099000000000000000000#9#C#Go to CMD prompt#call FILE_99.cmd
:READ_MESSAGE
call :frame
if not exist message.txt echo No messages.&&Pause&&goto :991
type message.txt
echo.
echo.
echo.
pause
goto :991
:WRITE_MESSAGE
call :frame
set /p "msg=Enter message: "
echo %msg% >message.txt
echo.
echo.
echo Message written to file.
pause
goto :991
:DELETE_MESSAGE
call :frame
if not exist message.txt echo No messages.&&Pause&&goto :991
set /p "dlt=Delete message file? "
if "%dlt%"=="Y" del message.txt>nul 2>nul
echo Message delete.
echo.
echo.
pause
goto :991
:CONTINUE1
echo CMD continues here...
pause
goto :991
Menu options are embeded in the .cmd file itself (though this could be easily moved to external file). File has a structure like this:
Code: Select all
MMMMM.-----selections----->#required privs#M=MENU, C=CMD#description#what to do (call a .cmd or call a label)
MMMMM0000000000000000000000#0#M#MAIN MENU#
MMMMM0001000000000000000000#0#C#Read message#goto :READ_MESSAGE
MMMMM0002000000000000000000#A#C#Option 2#call FILE_02.cmd
MMMMM0004000000000000000000#1#C#Option 4-priv 1#call FILE_04.cmd
MMMMM0005000000000000000000#12#C#Option 5-privs 1,2#call FILE_05.cmd
MMMMM0007000000000000000000#34#M#REPORTS HR and FINANCE#
MMMMM0007010100000000000000#3#C#Report 1#call FILE_07_01_01.cmd
MMMMM just makes sure to find correct records when searching .cmd itself.
Field 2 determines the privilege (or we can call this a group of users) required to access the selection:
0 is accessable to everyone, A is archived selection (and is not displayed), 9 should be reserved for system managers or for the person who is maintaing these menus.
Example above (in the .cmd) has privilege 3 for HR department, 4 is for FINANCE Dept. They have s common menu selection but later in submenus they get only the correct menu selections displayed.
Menu selections can have multiple privileges while users accessing the menu system must have only one privilege set (though this can be corrected).
Every selection has a privilege 9 added so the system manager has access to all selections. Selections with privilege 9 are displayed only to system managers of course.
Also it has a built-in messaging system - a message system admin can leave for users (something like: we have technical difficulties. Problem will be resolved soon or something like that).
First image shows a main menu for group 3 (HR) (both HR and FINANCE are displayed). Also you can see that option 2 is not displayed (privilege level A):

The second image show next level of choices (for HR only):

And final level:

Procedure can call a label within current .cmd or another .cmd if required.
As mentioned it is ported from DCL so some functions (lexical functions) which are not available here in .cmd were replaced by some other methods of course.
The information 'M' or 'C' in the menu list can probably be left out. On OpenVMS I had to use the information if the resulting file is a DCL command procedure (.com) or an .exe file because they are run in different ways (@proc.com or run file.exe).
Saso