C*****************************************************************************
C	Subroutines for establishing & using the DCL subprocess.
C*****************************************************************************
C
C  Revisions (Version 6.x)            August, 1986
C	Dale E. Coy
C	Los Alamos National Laboratory
C	(505) 667-7159
C
C*****************************************************************************
C--------------------------------------------------------------------
C	Create Mailbox and Open unit for MailBox Output
C--------------------------------------------------------------------
	Subroutine Setup_For_DCL
	Integer Stat
	Integer*4 MaxMsg
	Integer*2 Dst_Len
	Character*20 TTname

	Include 'Common.Dat'
	Data MaxMsg /256/
C-------------------------------------------------------------------

	STAT = Sys$Crembx(,%Ref(Channel),,,,,%Descr(Mbx_Name))

 	Call Lib$Sys_Trnlog('TT',%Ref(Dst_Len),%Descr(TTname))
	Call Lib$Set_Logical('SYS$COMMAND',%Descr(TTname(:Dst_Len)))


	Stat = Lib$Get_Lun (Mbx_Lun)
	Open(Unit=Mbx_Lun,File=Mbx_Name,CarriageControl = 'List',
  	1	Recl = MaxMsg, Status = 'New', Shared)

	If (.NOT.Have_SubProcess) Call Create_SubProcess

	Have_DCL_Setup = .TRUE.

	Return
	End

C--------------------------------------------------------------------
C	Handle Unexpected Exit from SubProcess
C--------------------------------------------------------------------
	Subroutine Subprocess_Quit_AST
	Integer*4 Stat
	Integer*4 New_Mbx_Lun
	Character*255 Dummy
	Include 'Common.Dat'

C--------------------------------------------------------------------

	If (Have_SubProcess) then   ! Necessary to handle forced exit.
	  Have_SubProcess = .FALSE.
          If (Doing_Command) then
	      Stat = Lib$Get_Lun (New_Mbx_Lun)
	      Open(Unit=New_Mbx_Lun,File=Mbx_Name,
	1	 CarriageControl = 'List',Status = 'New',Shared)
	      Read(New_Mbx_Lun,1000) Dummy
	  Else
	      Call Sys$Cancel (%Val(Channel))
	  End If

1000	Format (A)

	End If

	Return
	End


C--------------------------------------------------------------------
C	Create DCL SubProcess
C--------------------------------------------------------------------
	Subroutine Create_SubProcess
	Integer*4 Stat
	Include 'Common.Dat'

	EXTERNAL SUBPROCESS_QUIT_AST
C--------------------------------------------------------------------

	Call SMG$Paste_Virtual_Display (Working_Display,
	1		Pasteboard_ID,1,1)
	Call SMG$Flush_Buffer (Pasteboard_ID)

	Doing_Command = .FALSE.

	Stat = LIB$SPAWN(,%Descr(Mbx_Name),
	1      %Descr('TT:'),%Ref(1),,%Ref(Process_ID),,,
	2	SUBPROCESS_QUIT_AST)


	Have_SubProcess = .TRUE.
	Call SMG$UnPaste_Virtual_Display (Working_Display,
	1		Pasteboard_ID)

	Return
	End

C--------------------------------------------------------------------
C	Do one DCL command, when we want to open a "window" for
C	output to the screen.  Used for /LOG internal DM
C	functions (copy, purge, etc....)
C--------------------------------------------------------------------
	Subroutine Do_Controlled_DCL
	Integer*4 Saved_Display_ID

	Include 'Common.Dat'

C-------------------------------------------------------------------

1000	Format (A)
  
	If (.NOT.Have_DCL_Setup)  Call Setup_For_DCL
	If (.NOT.Have_SubProcess) then
		Call Create_SubProcess
	End If
                 
C		Can't Use SMG$ -- DCL Insists it has the whole thing.
C		But ... we're going to "fake" it
C		We use a window, and then a "save" inside the window.
C		Window1 is 8x80 and bordered.
	Call SMG$Erase_Display (Window1_Display)
	Call SMG$Paste_Virtual_Display (Window1_Display,Pasteboard_ID,
	1	3,1)

	Call SMG$Save_Physical_Screen (Pasteboard_ID,
	1	 Saved_Display_ID,3,10)

 	Write (Mbx_Lun,1000) CmdLine1
	Write (Mbx_Lun,1000) CmdLine2

	Doing_Command = .TRUE.
	Write (Mbx_Lun,1000) Exit_Com

	Write (Mbx_Lun,1000) '$'

C	Call Lib$Wait (Wait_Time)

        Call Mess_Wait (' DM Operation Complete')	

	Call SMG$Begin_Pasteboard_Update (Pasteboard_ID)

	Call SMG$Restore_Physical_Screen (Pasteboard_ID,
	1	 Saved_Display_ID)

	Call SMG$Unpaste_Virtual_Display (Window1_Display,Pasteboard_ID)

	If (.NOT.ReLoad) 
	1	Call SMG$End_Pasteboard_Update (Pasteboard_ID)

	Doing_Command = .FALSE.

	Return
	End

C--------------------------------------------------------------------
C  DO_NoShow_DCL
C     	Do one DCL command, when we know the result WILL not do
C	something funny to the screen.  Used for internal DM
C	functions ( purge, etc....) where /LOG is not used.
C	NOTE: Any error can really garbage up the screen here.
C--------------------------------------------------------------------
	Subroutine Do_NoShow_DCL
	Integer*4 Saved_Display,Screen_Line
                             
	Include 'Common.Dat'

C-------------------------------------------------------------------

1000	Format (A)
  
	If (.NOT.Have_DCL_Setup)  Call Setup_For_DCL
	If (.NOT.Have_SubProcess) then
		Call Create_SubProcess
	End If

	Write (Mbx_Lun,1000) CmdLine1
  	Write (Mbx_Lun,1000) CmdLine2

	Doing_Command = .TRUE.
	Write (Mbx_Lun,1000) Exit_Com

	Write (Mbx_Lun,1000) '$'

C	Call Lib$Wait (Wait_Time)

	Doing_Command = .FALSE.

	Return
	End

C--------------------------------------------------------------------
C  DO_Immediate_DCL
C     	Do one DCL command, when we know the result WILL not do
C	something funny to the screen, and where we won't wait for
C	the results.  Used for things like setting the default directory
C	for the subprocess.
C	NOTE: Any error can really garbage up the screen here.
C--------------------------------------------------------------------
	Subroutine Do_Immediate_DCL
	Integer*4 Saved_Display,Screen_Line
                             
	Include 'Common.Dat'

C-------------------------------------------------------------------

1000	Format (A)
  
	If (.NOT.Have_DCL_Setup)  Call Setup_For_DCL
	If (.NOT.Have_SubProcess) then
		Call Create_SubProcess
	End If

	Write (Mbx_Lun,1000) CmdLine1
  	Write (Mbx_Lun,1000) CmdLine2

	Doing_Command = .TRUE.
	Write (Mbx_Lun,1000) Exit_Com

C	Write (Mbx_Lun,1000) '$'
C	Call Lib$Wait (Wait_Time)

	Doing_Command = .FALSE.

	Return
	End

C--------------------------------------------------------------------
C  DO_Hidden_DCL
C     	Do one DCL command, when we know the result should not do
C	something funny to the screen.  Used for internal DM
C	functions (copy,  etc....) where /LOG is not used.
C	NOTE: We DO provide a 2-line scrolling region, in case of errors.
C--------------------------------------------------------------------
	Subroutine Do_Hidden_DCL
	Integer*4 Saved_Display,Screen_Line

	Include 'Common.Dat'

C-------------------------------------------------------------------

1000	Format (A)
  
	If (.NOT.Have_DCL_Setup)  Call Setup_For_DCL
	If (.NOT.Have_SubProcess) then
		Call Create_SubProcess
	End If

C		Create somewhere to put a short message or (horrors)
C		the process-exit message from the subprocess.
	Screen_Line = Current_Line - TopLine + 1
	If (Screen_Line .EQ. 22) Screen_Line = 21

	Call SMG$Save_Physical_Screen (Pasteboard_ID,Saved_Display,
	1	Screen_Line, Screen_Line + 1 )


	Write (Mbx_Lun,1000) CmdLine1
  	Write (Mbx_Lun,1000) CmdLine2

	Doing_Command = .TRUE.
	Write (Mbx_Lun,1000) Exit_Com

	Write (Mbx_Lun,1000) '$'

C	Call Lib$Wait (Wait_Time)              

	If (ReLoad) Call SMG$Begin_Pasteboard_Update (Pasteboard_ID)
	Call SMG$Restore_Physical_Screen (Pasteboard_ID,Saved_Display)

	Doing_Command = .FALSE.

	Return
	End

C--------------------------------------------------------------------
C--------------------------------------------------------------------
C	Do one DCL command, when we must have the entire screen.
C	Used for "one-line" DCL commands ($ Command).
C	Holds screen upon return.
C	Assumes that we won't know the state of file upon return,
C		so ReLoad is set automatically
C--------------------------------------------------------------------
	Subroutine Do_One_DCL
	Integer*4 Saved_Display_ID

	Include 'Common.Dat'

C-------------------------------------------------------------------

1000	Format (A)                        
  
	If (.NOT.Have_DCL_Setup)  Call Setup_For_DCL
	If (.NOT.Have_SubProcess) then
		Call Create_SubProcess
	End If
                 

	Call SMG$Save_Physical_Screen (Pasteboard_ID,
	1	 Saved_Display_ID)
	Call SMG$Erase_Pasteboard (Pasteboard_ID)

 	Write (Mbx_Lun,1000) CmdLine1
	Write (Mbx_Lun,1000) CmdLine2

	Doing_Command = .TRUE.
	Write (Mbx_Lun,1000) Exit_Com

  	Write (Mbx_Lun,1000) '$'

C	Call Lib$Wait (Wait_Time)

50	If (.NOT.Have_SubProcess) then
		Call Create_SubProcess
	End If
	Write (Mbx_Lun,1000) 'Write SYS$OUTPUT " "'
	Write (Mbx_Lun,1000) 'Write SYS$OUTPUT " "'
	Write (Mbx_Lun,1000) 'Write SYS$OUTPUT " "'

	Call Lib$Wait (Wait_Time)
	Doing_Command = .FALSE.

        Call Mess_Wait (' DM Operation Complete')	

	Call SMG$Begin_Pasteboard_Update (Pasteboard_ID)

	Call SMG$Restore_Physical_Screen (Pasteboard_ID,
	1	 Saved_Display_ID)



	ReLoad = .TRUE.

	Return
	End

C--------------------------------------------------------------------
C	Do Single DCL command, when we must have the entire screen.
C	Used for "single" DCL commands Edit, More, etc.
C	Does NOT hold screen upon return.
C	Assumes that we won't know the state of file upon return,
C		so ReLoad is set automatically
C--------------------------------------------------------------------
	Subroutine Do_Single_DCL
	Integer*4 Saved_Display_ID

	Include 'Common.Dat'

C-------------------------------------------------------------------

1000	Format (A)                        
  
	If (.NOT.Have_DCL_Setup)  Call Setup_For_DCL
	If (.NOT.Have_SubProcess) then
		Call Create_SubProcess
	End If
                 

	Call SMG$Save_Physical_Screen (Pasteboard_ID,
	1	 Saved_Display_ID)
	Call SMG$Erase_Pasteboard (Pasteboard_ID)

 	Write (Mbx_Lun,1000) CmdLine1
	Write (Mbx_Lun,1000) CmdLine2

	Doing_Command = .TRUE.
	Write (Mbx_Lun,1000) Exit_Com

	Write (Mbx_Lun,1000) '$'

C	Call Lib$Wait (Wait_Time)


	Call SMG$Begin_Pasteboard_Update (Pasteboard_ID)

	Call SMG$Restore_Physical_Screen (Pasteboard_ID,
	1	 Saved_Display_ID)



	ReLoad = .TRUE.

	Doing_Command = .FALSE.

	Return
	End

C--------------------------------------------------------------------
C	Go out to DCL.  Come back when an "empty" CR is entered.
C--------------------------------------------------------------------
	Subroutine GoTo_DCL
	Implicit Integer*4 (A-Z)
	Integer*4 Max_Length
	Integer*2 Input_Length, K
	Character*255 Input

	Include 'Common.Dat'
	Data Max_Length /255/                   
C-------------------------------------------------------------------


	If (.NOT.Have_DCL_Setup)  Call Setup_For_DCL
	If (.NOT.Have_SubProcess) then
		Call Create_SubProcess
	End If


	Call SMG$Save_Physical_Screen (Pasteboard_ID,
	1	 Saved_Display_ID)

	Doing_Command = .TRUE.


10	Call Lib$Get_Command (Input,%Descr('$ '),%Ref(Input_Length))

	If ((Input .NE. ' ').AND.(Input_Length.GT.0)) then

		If (.NOT.Have_SubProcess) Call Create_SubProcess

1000	Format (A)
 		Write (Mbx_Lun,1000) CmdLine1
		Write (Mbx_Lun,1000) CmdLine2

		Write (Mbx_Lun,1000) '$ '//Input(:Input_Length)


		If (.NOT.Have_SubProcess) Call Create_SubProcess

		Write (Mbx_Lun,1000) '$'

		Call Lib$Wait (Wait_Time)
		GoTo 10
	End If

C		In case the subprocess directory was changed..

	Call Str$Trim (%Descr(Current_Device)
	1		,%Descr(Current_Device),%Ref(K))
	Exit_Com = 'SET DEFAULT '//Current_Device(:K)//Current_Dir
	Call Do_Immediate_DCL

	Call SMG$Begin_Pasteboard_Update (Pasteboard_ID)

	Call SMG$Restore_Physical_Screen (Pasteboard_ID,
	1	 Saved_Display_ID)

	Doing_Command = .FALSE.


	ReLoad = .TRUE.

	Return
	End

C--------------------------------------------------------------------
C--------------------------------------------------------------------
	Subroutine Cancel_DCL

	Include 'Common.Dat'

C-------------------------------------------------------------------

	Doing_Command = .FALSE.

	If (Have_SubProcess) then
		Have_SubProcess = .FALSE.
		Call Sys$Delprc (%Ref(Process_ID))
	End If

	If (Have_DCL_Setup) then
		Close (Mbx_Lun)
		Have_DCL_Setup  = .FALSE.
	End If

	Return
	End

