! command line processor, encapsulated, self-contained,
       !  designed to look like 1-2-3 - Jim DuLaney, 20th Century Armadilllo
       !   this source listing is available in the application area
       !   of the user's society computer under the name of SELECT.2CA

       ! ******************************************************************
       ! ******* USE RESTRICTION to simplify code, all command strings must
       !                         be terminated with a blank at the end of
       !                         the line.
       ! ******************************************************************

       map1 primary'commands,S,80,&
"Calculator   Database.manager Spreadsheet  Report:processor Word'proc "
       map1 other'commands,S,80,&
" Mycommand    Yourcommand        Theircommand Amos's'command "
       map1 current'commands,S,80
       map1 command'register(30,3),F
       map1 return'code,F
       map1 register'max,F
       map1 tmp'X,F
       map1 tmp'Y,F
       map1 cur'c,F
       map1 l'c'd,F
       map1 T,F

       xcall noecho : !necessary to get control characters from Xcall Accept

! test program to display characteristics of process'command'line routine
       ?tab(-1,0);
doit'toit:
       current'commands=primary'commands
       call process'command'line
       current'commands=other'commands
       call process'command'line
       goto doit'toit
       ?tab(20,1);"returned code";return'code
       end

 process'command'line:

       ?tab(1,1);tab(-1,11);current'commands;
       cur'c = 0

       ! STEP 1
       ! initialize the register for this command line.
       !   command'register(30,3)
       !     where x indicates element number of array
       !     and   y=1 is the character,
       !           y=2 is the beginning position,
       !           y=3 is the ending position.

       ! STEP TWO
       ! next initialize the command register to all zeroes
       for tmp'X = 1 to 30
               for tmp'Y = 1 to 3
                       command'register(tmp'X,tmp'Y)=0
               next tmp'Y
       next tmp'X

       ! STEP THREE
       ! next, load the command register with the characteristics of the
       !     current'command string.
       tmp'X = 0 ! this will be used for the index to the command register
       tmp'Y = 0 ! this will be used for the pointer into the string

       command'register'initialization'loop:

               tmp'Y = tmp'Y + 1

               if tmp'Y > len(current'commands) then &
                       go to end'command'register'initialization'loop

               if current'commands[tmp'Y;1] = space$(1) then &
                       go to command'register'initialization'loop

               ! found a non blank character at current'commands[tmp'Y;1]

               tmp'X = tmp'X + 1

               ! load element one with the character id of the command
               command'register(tmp'X,1)=asc(current'commands[tmp'Y;1])
               ! load element two with the location of character in line
               command'register(tmp'X,2)=tmp'Y
               ! load element three with length of the command in the line
               command'register(tmp'X,3)=&
                       instr(tmp'Y,current'commands,space$(1))-tmp'Y
               ! push the pointer up to the next space to save scanning time
               tmp'Y = tmp'Y + command'register(tmp'X,3)
                       register'max = tmp'X
                       goto command'register'initialization'loop

   end'command'register'initialization'loop:

       ! STEP FOUR
               ! set up at the right margin and wait for the first input.

               cur'c = 0
               ?tab(-1,78);

   command'register'accept'character:

       ! STEP FIVE
               xcall ACCEPT,T
               ?tab(-1,11);chr$(8);space$(1);
               l'c'd = cur'c   ! flag which command was selected from before
                               !    used to dim old/brighten new.
               if T = asc("/") then goto command'line'abort
                               ! this is the default way to get out of the
                               !    routine
               if T = 8 then cur'c = cur'c-1:goto update'command'line
                               ! control-H is used to "step" left
               if T =12 then cur'c = cur'c+1:goto update'command'line
                               ! control-L is used to "step" right
               if cur'c = 0 then if T = 13 then goto command'line'abort
                               ! on receipt of return
                               !      with no command selected, abort
               if T = 13 then goto command'line'abort
                               ! on receipt of return
                               !      with a command selected, return

       ! STEP SIX
               ! ok, so we got a character.
               ! need to check character input against command register

               tmp'X = 0
       command'register'entry'check'loop:
                       tmp'X = tmp'X + 1
                       if command'register(tmp'X,1)=0 then go to &
                                       command'register'accept'character
                       if T      = command'register(tmp'X,1) then &
                                       goto command'register'entry'check'ok
                       if (T-32) = command'register(tmp'X,1) then &
                                       goto command'register'entry'check'ok

                                       goto command'register'entry'check'loop

       ! STEP SEVEN
       ! if it proves to be a valid command selection,
       command'register'entry'check'ok:
               cur'c = tmp'X
               if T =13 then ?tab(1,1);tab(-1,9);

               ! at this point, operator successfully selected a valid option

       ! STEP EIGHT
         update'command'line:
               if cur'c<1 then cur'c=register'max
               if cur'c>register'max then cur'c=1
               if l'c'd=0 then goto don't'darken'old

               ?tab(1,(command'register(l'c'd,2)));
               ?tab(-1,11);
?current'commands[(command'register(l'c'd,2));(command'register(l'c'd,3))];

    don't'darken'old:
               ?tab(1,(command'register(cur'c,2)));
               ?tab(-1,12);
?current'commands[(command'register(cur'c,2));(command'register(cur'c,3))];

       goto command'register'accept'character

       ! STEP NINE
 command'line'abort:
               return'code = cur'c
               ?tab(-1,12);
               return