C*****************************************************************************
C	Keystroke handling routines for DM
C  Version 6.x				            August, 1986
C	Dale E. Coy
C	Los Alamos National Laboratory
C	(505) 667-3270
C
C*****************************************************************************
	Subroutine Normal_Keys 

	Implicit Integer*4 (A - Z)
	Character*1 UCMD
	Logical*1 SavFor
	Integer*2 Nbytes
	
	Include 'Common.Dat'

C-------------------------------------------------------------------C
C	PROCESS NORMAL CHARACTER COMMANDS
C-------------------------------------------------------------------C
C		The normal character commands are processed in order
C	of estimated usage frequency, to speed up operation as much
C	as possible.
C
C	The "possible" and currently "used" normal characters are-
C                                
C	Possible: [ Key used with <CTL>:  <CTL>@ = CHAR(0) ]
C		: @ABCDEF HIJKLMNOP R TUVWXYZ \]^_
C	    Used:  AB          M         W  Z
C
C	Possible: [ Regular Keys ]
C		: @ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*\/?|Space
C	    Used: @ABCDE G I  LM  PQRSTUVWX Z             $%  *    Space
C	
C	NOTE: The numbers are there to support non-application-keypad
C-------------------------------------------------------------------C
C	First, the movement keys usually used:
C-------------------------------------------------------------------C

	Call Str$UpCase (%Descr(UCMD),%Descr(CMD))

C}{}{}{}      {A} = Top of Screen   
        If ( UCMD .EQ. 'A' ) then     
		call top_of_screen
       	

C}{}{}{}      {Z} = Bottom of Screen
        Else If ( UCMD .EQ. 'Z' ) then
		call bottom_of_screen
       	

C}{}{}{}      {Space} = Move One Line (Up or Down)
C}{}{}{}      {CR} = Move One Line (Up or Down)
       Else If ((CMD .EQ. ' ') .OR. (CMD .EQ. char(13))) then 
         If (Forward) then 
           Call DnArrow    ! blank, and <cr> are like the down arrow char
         Else
           Call UpArrow    ! blank, and <cr> are like the up arrow char
         End If


C-----------------------------------------------------------------------
C	Keys to Edit, View, Show (Also includes Execute Com File)
C		For efficiency, all DCL interfaces go here.
C-----------------------------------------------------------------------
C Interface to any DCL program  Letters left = hjknoy!^&()<>
C	Current Support is:
C	    a. EDT (e)
C	    b. FMS (f)
C	    e. @ <com file> (@)
C-----------------------------------------------------------------------

C}{}{}{}      {} All of these are external interfaces: 
C}{}{}{}      {@} = Execute selected .COM file
C}{}{}{}      {E} = Edit selected file (WPE)
C}{}{}{}      {F} = Edit selected FMS file
C}{}{}{}      {V} = View selected file (MORE)
C}{}{}{}      {S} = Same as V
C			NOTE: E,F,V, and S, if the selected file is a
C			.DIR, do a "PUSH" (Go To selected directory).

       Else If (lib$matchc(CMD, '@EeFfVvSs').GT. 0 ) then
         Call GetName(Current_Line, TempName, Itsa_Dir)
	       If (Itsa_Dir) then  ! 'DIR' type
		  Call PUSHSTACK
	       else	
         	  Call Envoke_DCL_Command( CMD )
 	       end if
       


C-----------------------------------------------------------------------
C	And now, the rest of the normal key commands
C-----------------------------------------------------------------------

C}{}{}{}      {$} = Go to DCL
        Else If (CMD .EQ. '$') then 
	 Call DCL ! Do DCL Command
       

C}{}{}{}      {%} =  Do a DCL command by exiting (context of .COM file)
        Else If (CMD .EQ. '%') then 
	 DM_Exit = .TRUE.     	! Tell DCL to NOT execute.
	 Call DCL 		! Prepare DCL Command in Exit_Com
	 If (.NOT.Do_DCL) DM_Exit = .FALSE.   ! DCL Wasn't Happy!



C}{}{}{}      {!} =  Do a DCL comment to exit, read broadcast messages,
C 				and come back.
        Else If (CMD .EQ. '!') then 
	  If (Num_Message .GT. 0) then
	    NBytes = 1
	    Call Make_DCL_Line ('!', NBytes )
	    DM_Exit = .TRUE.
	  End If



C}{}{}{}      {CTL-W} = Refresh Screen
C		GET1CHAR.FOR TAKES CARE OF THIS
C       Else If (CMD .Eq. Char(23)) then !Control W - refresh
C	Call SMG$Repaint_Screen(Pasteboard_ID)       
                     
C}{}{}{}      {Q} =     Exit DM, returning to directory at time of entry.
C}{}{}{}      {CTL-Z} = Exit DM, returning to directory at time of entry.
        Else If (( UCMD .EQ. 'Q' ) .or.
	1	 (CMD .EQ. Char(26)) )		then
         Exit_Com = 'zzzz'!
	 DM_Exit = .TRUE.
       
                     
C}{}{}{}      {X} =     Exit DM, remaining in currently-visible directory. 
        Else If ( UCMD .EQ. 'X' ) then
C		Fake out DM_Exit_Handler by the following:
	   Original_Dir = Current_Dir
	   Original_Device = Current_Device
	   Call Fix_SD_Stack (Current_Device, Current_Dir)
           Exit_Com = 'zzzz'!
	   DM_Exit = .TRUE.
       

C}{}{}{}      {P} =  Print Tagged Files
        Else If ( UCMD .EQ. 'P' ) then
		Call DM_Print
       

C}{}{}{}      {M} =  Change to "more information" (file size & prot.)
        Else If ( UCMD .EQ. 'M' ) then
	       Call SetChoices (More_Mode)
       


C}{}{}{}      {L} =  Change to "less information" (file names only)
        Else If ( UCMD .EQ. 'L' ) then
	       Call SetChoices (Normal_Mode)
       


C}{}{}{}      {D} =  Delete Tagged Files
        Else If ( UCMD .EQ. 'D' ) then
		Call DM_Delete
       
                                                            

C}{}{}{}      {U} =  Un-tag all files
         Else If ( UCMD .EQ. 'U' ) then
		Call Exclude
	        If (Forward) then
        		Call Dnarrow
	        Else
               		 Call UpArrow
	        End If
	


C}{}{}{}      {T} =  Tag this file
        Else If (( UCMD .EQ. 'T' ) .OR. ( CMD .EQ. '.' )) then
        	Call Include
		If (Forward) then
			Call Dnarrow
		Else
			Call UpArrow
		End If


C}{}{}{}      {G} =  Purge (entire directory?)
        Else If ( UCMD .EQ. 'G' ) then
         Call DM_Purge
       

C}{}{}{}      {C} =  Copy file
        Else If ( UCMD .EQ. 'C' ) then
         Call DM_Copy
       

C}{}{}{}      {R} =  Rename file
        Else If ( UCMD .EQ. 'R' ) then
         Call DM_Rename
       

C}{}{}{}      {I} =  Give INFO on this file (Like M, but for one file)
        Else If ( UCMD .EQ. 'I' ) then
	       Call SetChoices (Info_Mode)
       

C}{}{}{}      {W} =  Change Wildcard
        Else If ( UCMD .EQ. 'W' ) then
	 Call Wild


C}{}{}{}      {?} =  Help
        Else If ( UCMD .EQ. '?' ) then
	 Call DM_Help (3) ! Normal function help is first.


C}{}{}{}      {*} =  Link to SD *    -- A real kludge, to get SD code
C					to work with DM.
        Else If ( UCMD .EQ. '*' ) then
	 Call DM_Tree ( Current_Dir, Current_Device,
	1	Current_Dir_FileName, TLen, 
	2	Pasteboard_ID, Keyboard_ID, Highlight, VT300)

		If (TLen .LT. 0) then
			Call Mess_Wait (' DM * .... '//
	1			' There are No SubDirectories '//
	2			'in this Directory')
		Else If (TLen .GT. 0) then
			StkIndex = 0
			Call PopStack
			Call SMG$End_Pasteboard_Update (Pasteboard_ID)
			Call SMG$End_Pasteboard_Update (Pasteboard_ID)
		End If	! If it's =0, we don't have to do anything.


C}{}{}{}      { <X| } =  (Delete Key) = Go Up One Line
C		THIS DOESN'T WORK - DELETE KEY NOT PASSED TO PROGRAM.
        Else If ((CMD .EQ. CHAR(255)) .or. 
	1    (CMD .EQ. CHAR(127)) )	then
 		Call UpArrow ! 


C}{}{}{}      {CTL-A} = Page Forward
        Else If (CMD .Eq. Char(1)) then !Control A - page forward
         SavFor = Forward
         Forward = .TRUE.
         Call Page             
C		If it's not the "end" screen..
         If (Current_Line .NE. LastLine) Forward = SavFor


C}{}{}{}      {CTL-B} = Page Back
        Else If (CMD .Eq. Char(2)) then !Control B - page back
         SavFor = Forward
         Forward = .FALSE.
         Call Page
C		If it's not the "end" screen..
         If (Current_Line .NE. FirstUsed) Forward = SavFor
                                                     


	END IF

	Return
	End


C-----------------------------------------------------------------------
C	Fix the SD Stack, if it exists
C-----------------------------------------------------------------------

	SUBROUTINE Fix_SD_Stack (This_Device, This_Directory)

	Implicit Integer*4 (A-Z)
                  
	Character*(*) This_Device, This_Directory

	Include 'SD_Common.Dat'
                  
	Include '($LIBCLIDEF)'  
	Include '($LIBDEF)'
	Include '($SSDEF)'


C-----------------------------------------------------------------------
         
	Status = Lib$Get_Symbol (%Descr('SD_Stack_Pointer'),
	1		%Descr(SD_Stack_Pointer),
	2		,%Ref(Table))
                  

	If (Status .NE. LIB$_NOSUCHSYM) then


C			Get Stack Entry and Compare with Environment.
C			We do this because this process may have
C			changed our directory.

	CDevLen = Lib$MatchC (':',This_Device)
	Current_Device = This_Device(:CDevLen)
	CDirLen = Lib$MatchC (']',This_Directory)
	Current_Directory = This_Directory(:CDirLen)

  
	Environment = Current_Device(:CDevLen)
	Environment(CDevLen+1:) = Current_Directory
	EnvLen = CDevLen + CDirLen
  

  		Read (SD_Stack_Pointer,102, Err=9999) SD_SP_Number
102			Format(I2)

40		Write (SD_Slotn(8:9),108) SD_SP_Number
108				Format (I2.2)
	
		Status = Lib$Get_Symbol (%Descr(SD_Slotn),
	1		%Descr(String),%Ref(SLen))

		If (Status .EQ. LIB$_NOSUCHSYM) GoTo 9999
  
		If (String(:Slen) .NE. Environment(:EnvLen)) then

			SD_SP_Number = MOD(SD_SP_Number+1, Stack_Depth)
			Write (SD_Stack_Pointer,108) SD_SP_Number 

			Call Lib$Set_Symbol (%Descr('SD_Stack_Pointer'),
	1      			%Descr(SD_Stack_Pointer),
	2			LIB$K_CLI_GLOBAL_SYM)       

			Write (SD_Slotn(8:9),108) SD_SP_Number

			Call Lib$Set_Symbol (%Descr(SD_Slotn),
	1			%Descr(Environment(:EnvLen)),
	2			LIB$K_CLI_GLOBAL_SYM)
		End If

	END IF                 

9999	Continue
	Return
	End

