[comp.sources.misc] SWING 08/10

u3369429@murdu.OZ (Michael 'I love VMS' Bednarek) (05/07/87)

$ Name=File'nF
$ Write SYS$Output "creating ",Name
$ Open/Write Out 'Name
$ Open/Read In VMS_SHAR_DUMMY.DUMMY
$Next_Record49: Read/End_Of_File=EOF49 In Record
$ Write Out F$Extract(1,255,Record)
$ Goto Next_Record49
$EOF49: Close Out
$ Close In
$ Delete VMS_SHAR_DUMMY.DUMMY;*
$ Checksum 'Name
$ Success=F$Element(Check_Sum'nF.eq.CHECKSUM$CHECKSUM,",",Pass_or_Failed)
$ Write SYS$ERROR "Checking CHECKSUM. ''Success'"
$ nF=nF+1
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X	Options	/Extend_Source
X
X	Program   SWING
X	Implicit  NONE
X	Character Program_Name*5/'SWING'/
X
X! Nomenclature:	ea Eric Andresen
X!		mb Michael Bednarek (u3369429@murdu.oz.au)
X!		ms Mike Strasser (STRASSER@RSBS0.ANU.au)
X* Version:	1-001 ea
X!		1-002 mb Heavy de-bugging and "Implicit NONE" everywhere
X!		27-Apr-87 mb implemented "Next/Previous Screen"
X!			     removed calls to set_notab & reset_terminal
X!		01-May-87 mb Fixed bug re: multiple width changes
X	Character Version*9
X	1     /'04-May-87'/ ! mb added M.Strasser's ISADIR
X
X* Abstract:	SWING is a VMS utility for displaying and manipulating
X*		VMS directory trees.
X*
X* Environment:	VMS
X*
X* Author:	Eric Andresen of General Research Corporation
X*
X* Date:		24-SEP-1986
X
X! Bugs: Major	For reasons unknown, one cannot change more than once the
X!		width of the screen. If one creates a directory so that the
X!		width is set to 132 and then deletes it again, SWING crashes.
X!		Or, if one has already a structure which requires a width of
X!		132 and then deletes directories so that the display changes to
X!		80, and then creates again a directory so that the display
X!		has to change to 132 again, SWING will crash, too.
X!	01-May-87 This behaviour disappeared when 6 calls to SMG$Erase_Display
X!		  in Load_Display were removed.
X
X!	Minor	When SWING has to alter the width of the screen as compared
X!		to what it was when the program started, the SMG-routines will
X!		restore the original screen width and the cursor is left at the
X!		top of the screen.
X
X!		When a structure is deleted which is larger than the current
X!		display, the window is not scrolled to show the progress
X!		of deleting the structure.
X
X*-----------------------------------------------------------------------
X	include   '($smgdef)/List'
X	include   'swing.cmn/List'
X
X	Integer*4 ikey,old_level,old_line,isave,code,code_type,ii,jj,
X	1	  Swing_Err_Hdl,Old_Handler,LIB$Establish
X	logical   crt,finished
X	character key,choice*(PD_MAX_CHOICE_LEN)
X	External  Swing_Err_Hdl
X
X	Write	(*,*) Program_Name,' ',Version
X
X	if (.not.crt()) call print_message('You must use a DEC CRT terminal',1)
X
X! Establish a Condition Handler
X	Old_Handler=LIB$Establish(Swing_Err_Hdl)
X
X	call load_nodes
X	call define_smg_layout
X	call load_display
X	call draw_screen
X
X	do while (.not.finished)
X
X	 call smg$read_keystroke(keyboard,ikey)
X
X	 call print_message(' ',0)
X
X	 old_line=cur_line
X	 old_level=cur_level
X	 old_rend=node(node_num).rend
X
X! Pulldown Menu
X	 if (ikey.eq.smg$k_trm_do .or. ikey.eq.smg$k_trm_ctrlp) then
X	  call pd_get_choice(board_id,keyboard,width,pull_choices,choice,code)
X	  code_type=code/10
X	 else
X	  code_type=0
X	  code=0
X	 end if
X
X	 if    (ikey.eq.smg$k_trm_ctrlz.or.
X	1	ikey.eq.smg$k_trm_lowercase_x.or.
X	1	ikey.eq.smg$k_trm_uppercase_x.or.
X	1	ikey.eq.smg$k_trm_lowercase_e.or.
X	1	ikey.eq.smg$k_trm_uppercase_e.or.
X	1	ikey.eq.SMG$K_TRM_LowerCase_q.or.
X	1	ikey.eq.SMG$K_TRM_UpperCase_Q.or.
X	1	ikey.eq.SMG$K_TRM_F10.or.
X	1	ikey.eq.smg$k_trm_enter.or.
X	1	code.eq.91) then
X	  finished=.true.
X
X	 else if (ikey.eq.smg$k_trm_up) then
X	  ii=cur_level
X	  jj=cur_line-1
X! find the next line upwards with a node_pointer
X	  do while (jj.ge.1 .and. node_pointer(ii,jj).eq.0)
X	   jj=jj-1
X	  end do
X	  if (jj.ge.1) cur_line=jj
X	  call update_screen(old_line,old_level)
X
X	 else if (ikey.eq.smg$k_trm_down) then
X	  ii=cur_level
X	  jj=cur_line+1
X	  do while (jj.le.num_lines .and. node_pointer(ii,jj).eq.0)
X	   jj=jj+1
X	  end do
X	  if (jj.le.num_lines) cur_line=jj
X	  call update_screen(old_line,old_level)
X
X	 else If (ikey.eq.SMG$K_TRM_Prev_Screen) then
X	  jj=MAX(top_line-20,1)
X	  ii=0
X! find the first level with a pointer
X	  Do while (ii.le.MAX_LEVELS .and. node_pointer(ii,jj).eq.0)
X	   ii=ii+1
X	  End Do
X	  cur_line=jj
X	  cur_level=ii
X	  Call Update_Screen(old_line,old_level)
X
X	 else If (ikey.eq.SMG$K_TRM_Next_Screen) then
X	  jj=MIN(bottom_line+20,num_lines)
X	  ii=0
X! find the first level with a pointer
X	  Do while (ii.le.MAX_LEVELS .and. node_pointer(ii,jj).eq.0)
X	   ii=ii+1
X	  End Do
X	  cur_line=jj
X	  cur_level=ii
X	  Call Update_Screen(old_line,old_level)
X
X	 else if (cur_level.lt.MAX_LEVELS .and. ikey.eq.smg$k_trm_right) then
X	  ii=cur_level+1
X	  jj=cur_line
X	  do while(ii.le.MAX_LEVELS .and. node_pointer(ii,jj).eq.0)
X	   ii=ii+1
X	  end do
X	  if (ii.le.MAX_LEVELS) cur_level=ii
X	  call update_screen(old_line,old_level)
X
X	 else if (cur_level.gt.0 .and. ikey.eq.smg$k_trm_left) then
X	  ii=cur_level-1
X	  jj=cur_line
X	  do while(jj.ge.1 .and. node_pointer(ii,jj).eq.0)
X	   jj=jj-1
X	  end do
X	  if (jj.ge.1) then
X	   cur_level=ii
X	   cur_line=jj
X	  end if
X	  call update_screen(old_line,old_level)
X
X	 else if (code_type.eq.1 .or.
X	1		ikey.eq.smg$k_trm_lowercase_c .or.
X	1		ikey.eq.smg$k_trm_uppercase_c) then
X	  call create_directory(code)
X
X	 else if (code_type.eq.2 .or.
X	1		ikey.eq.smg$k_trm_lowercase_r .or.
X	1		ikey.eq.smg$k_trm_uppercase_r) then
X	  call rename_directory(20)
X
X	 else if (code_type.eq.3 .or.
X	1		ikey.eq.smg$k_trm_lowercase_m .or.
X	1		ikey.eq.smg$k_trm_uppercase_m) then
X	  call rename_directory(30)
X
X	 else if (code_type.eq.4 .or.
X	1		ikey.eq.smg$k_trm_lowercase_d .or.
X	1		ikey.eq.smg$k_trm_uppercase_d) then
X	  call delete_directory(code)
X
X	 else if (code_type.eq.5 .or.
X	1		ikey.eq.smg$k_trm_lowercase_p .or.
X	1		ikey.eq.smg$k_trm_uppercase_p) then
X	  call hardcopy(code)
X
X	 else if (code_type.eq.6 .or.
X	1		ikey.eq.smg$k_trm_lowercase_s .or.
X	1		ikey.eq.smg$k_trm_uppercase_s) then
X	  call record_structure(.true.)
X
X	 else if (code_type.eq.7 .or.
X	1		ikey.eq.smg$k_trm_lowercase_o .or.
X	1		ikey.eq.smg$k_trm_uppercase_o) then
X	  call change_options(71)
X
X	 else if (code_type.eq.8 .or.
X	1		ikey.eq.smg$k_trm_pf2 .or.
X	1		ikey.eq.smg$k_trm_help .or.
X	1		ikey.eq.smg$k_trm_lowercase_h .or.
X	1		ikey.eq.smg$k_trm_uppercase_h) then
X	  call help(code)
X	 end if
X
X	 call smg$set_cursor_abs(window2,cur_line,cur_level*17+1)
X
X	end do
X
X	Call Lib$Establish(%VAL(Old_Handler))	! Establish previous Handler
X	call exit_swing
X
X	end
$ Name=File'nF
$ Write SYS$Output "creating ",Name
$ Open/Write Out 'Name
$ Open/Read In VMS_SHAR_DUMMY.DUMMY
$Next_Record50: Read/End_Of_File=EOF50 In Record
$ Write Out F$Extract(1,255,Record)
$ Goto Next_Record50
$EOF50: Close Out
$ Close In
$ Delete VMS_SHAR_DUMMY.DUMMY;*
$ Checksum 'Name
$ Success=F$Element(Check_Sum'nF.eq.CHECKSUM$CHECKSUM,",",Pass_or_Failed)
$ Write SYS$ERROR "Checking CHECKSUM. ''Success'"
$ nF=nF+1
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X	Options	/Extend_Source
X	Integer*4 Function Swing_Err_HDL (SigArgs,MechArgs)
X	Implicit NONE
X
X	Include    'swing.cmn/List'
X
X	Integer*4 SigArgs(*),MechArgs(*)
X	External  SS$_Resignal
X
X	Call SMG$Set_Cursor_Abs(window3,1,1)
X	Call SMG$Delete_Pasteboard(board_id,0)
X
X! Now re-signal the error
X	Swing_Err_Hdl=%LOC(SS$_Resignal)
X
X	End
$ Name=File'nF
$ Write SYS$Output "creating ",Name
$ Open/Write Out 'Name
$ Open/Read In VMS_SHAR_DUMMY.DUMMY
$Next_Record51: Read/End_Of_File=EOF51 In Record
$ Write Out F$Extract(1,255,Record)
$ Goto Next_Record51
$EOF51: Close Out
$ Close In
$ Delete VMS_SHAR_DUMMY.DUMMY;*
$ Checksum 'Name
$ Success=F$Element(Check_Sum'nF.eq.CHECKSUM$CHECKSUM,",",Pass_or_Failed)
$ Write SYS$ERROR "Checking CHECKSUM. ''Success'"
$ nF=nF+1
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X	Options	/Extend_Source
X	subroutine update_screen(old_line,old_level)
X	Implicit NONE
X
X	include '($smgdef)/List'
X	include 'swing.cmn/List'
X
X	integer old_line,old_level,sys$setddir,ii,istat
X
X	node_num=node_pointer(cur_level,cur_line)
X
X	call smg$begin_pasteboard_update(board_id)
X
X	call smg$change_rendition(window2,old_line,old_level*17+1,1,12,
X	1	old_rend)
X	call smg$change_rendition(window2,cur_line,cur_level*17+1,1,12,
X	1	smg$m_bold+node(node_num).rend)
X
X	call update_window1
X	call smg$end_pasteboard_update(board_id)
X
X	if (cur_line.gt.bottom_line) then
X	 do ii=bottom_line+1,cur_line
X	  call smg$move_virtual_display(window2,board_id,23-ii,1)
X	 end do
X	 top_line=cur_line-19
X	 bottom_line=cur_line
X
X	else if (cur_line.lt.top_line) then
X	 do ii=top_line-1,cur_line,-1
X	  call smg$move_virtual_display(window2,board_id,4-ii,1)
X	 end do
X	 top_line=cur_line
X	 bottom_line=cur_line+19
X	end if
X
X	istat=sys$setddir(node(node_num).spec,%val(0),%val(0))
X
X	return
X	end
$ Name=File'nF
$ Write SYS$Output "creating ",Name
$ Open/Write Out 'Name
$ Open/Read In VMS_SHAR_DUMMY.DUMMY
$Next_Record52: Read/End_Of_File=EOF52 In Record
$ Write Out F$Extract(1,255,Record)
$ Goto Next_Record52
$EOF52: Close Out
$ Close In
$ Delete VMS_SHAR_DUMMY.DUMMY;*
$ Checksum 'Name
$ Success=F$Element(Check_Sum'nF.eq.CHECKSUM$CHECKSUM,",",Pass_or_Failed)
$ Write SYS$ERROR "Checking CHECKSUM. ''Success'"
$ nF=nF+1
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X	Options	/Extend_Source
X	subroutine update_window1
X	Implicit NONE
X
X	include '($smgdef)/List'
X	include 'swing.cmn/List'
X
X	integer start
X
X	if (use_window1) then
X	 start=(width-(len_disk+node(node_num).length))/2
X	 if (start.le.0) start=1
X
X	 call smg$erase_line(window1,1,1)
X	 call smg$put_chars(window1,
X	1	disk(1:len_disk)//node(node_num).spec(1:node(node_num).length),
X	1	1,start,,smg$m_underline)
X	end if
X
X	return
X	end
$ Name=File'nF
$ Write SYS$Output "creating ",Name
$ Open/Write Out 'Name
$ Open/Read In VMS_SHAR_DUMMY.DUMMY
$Next_Record53: Read/End_Of_File=EOF53 In Record
$ Write Out F$Extract(1,255,Record)
$ Goto Next_Record53
$EOF53: Close Out
$ Close In
$ Delete VMS_SHAR_DUMMY.DUMMY;*
$ Checksum 'Name
$ Success=F$Element(Check_Sum'nF.eq.CHECKSUM$CHECKSUM,",",Pass_or_Failed)
$ Write SYS$ERROR "Checking CHECKSUM. ''Success'"
$ nF=nF+1
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X;  ISADIR routine by Mike Strasser 1987.  It is to be called from FORTRAN as
X;
X;                  STATUS = ISADIR( FILE )
X;
X;  Where FILE is a character string containing a file name.
X;
X;  The return value is 1 (SS$_NORMAL) if FILE is a directory, and 0 if
X;  it isn't, but otherwise OK.  If an error is encountered along the way,
X;  processing stops and its status value is returned
X;
X;  The $OPEN macro uses the option user file open.  This is a "Clayton's"
X;  open, and no further RMS processing is allowed on the file.  It does 
X;  count against the process' open file quota, however, and while it cannot
X;  be $CLOSED, the channel assigned in the $OPEN must be $DEASSGNed.
X;
X;  References:
X;
X;    $FAB, $NAM and $OPEN macros	RMS Ref. Man.
X;    $DASSGN macro			System Services Man.
X;    FIBs and Attribute Control Block	I/O User's Ref. Man.:  ACP-QIO I'face
X 
X 
X	.Title ISADIR  Is this a directory file?
X	.Ident  /1.02/
X 
X	.Library "SYS$LIBRARY:LIB.MLB"	;Get $FCHDEF from here
X 
X	.NoCross
X 
X	$ATRDEF				;File attributes def'ns
X	$FCHDEF				;File characteristic bits def'ns
X	$FIBDEF				;File Info Block offsets
X	$IODEF				;I/O function codes def'ns
X	$RMSDEF				;RMS status codes def'ns
X	$SSDEF				;System service codes def'ns
X 
X	.Cross
X 
X	.Psect	DATA	NOEXE, RD, WRT, PIC, NOSHR, PAGE
X 
X; Call the $FAB macro to set up a FAB here.  File name to be included later
X 
XFAB:	$FAB	FOP=<UFO>, -		;User file open option
X		NAM=NAM			;Address of NAM block
XNAM:	$NAM				;Set up NAM block here
X 
X; FIB descriptor and FIB
X 
XFIB_DESC:	.Long	FIB_END - FIB	;Length of the FIB
X		.Address FIB		;Address of the FIB
X 
XFIB:		.Long	0		;FIB$L_ACCTL and FIB$B_WSIZE
XFID:		.Blkw	3		;FIB$W_FID:  file ID, 3 words
XDID:		.Blkw	3		;FIB$W_DID:  directory ID, 3 words
X		.Blkl			;FIB$L_WCC:  wildcard context
X		.Word	FIB$M_FINDFID	;FIB$W_NMCTL:  file name control bits
XFIB_END:				;Mark end of the FIB
X 
X; Attribute control block (zero-terminated)
X 
XATTR_LIST:	.Word	ATR$S_UCHAR, ATR$C_UCHAR ;4 byte file characteristics
X		.Address UCHAR		;To go here
X		.Long	0		;This marks the end of the list
X 
XUCHAR:		.Blkl			;File attributes to go here
XIOSB:		.Blkq			;IO status block for IO$_ACCESS
X 
X	.Psect	CODE	EXE, RD, NOWRT, PIC, SHR, PAGE
X 
X	.Entry	ISADIR, 0
X 
X; Get the file name from the agument list (passed by descriptor)
X 
X	MOVL	4(AP), R0		;Address of descriptor -> R0
X	MOVL	4(R0), FAB+FAB$L_FNA	;Address of string -> FAB block
X	MOVB	(R0), FAB+FAB$B_FNS	;Length of string -> FAB block
X 
X	$OPEN	FAB=FAB			;Call to open file
X	BLBS	R0, 10$			;Bomb out if error
X	RET
X 
X; Copy file and directory info from NAM block into the FIB block
X 
X10$:	MOVL	NAM+NAM$W_FID, FID	;Copy the FID (file)
X	MOVW	NAM+NAM$W_FID+4, FID+4
X	MOVL	NAM+NAM$W_DID, DID	;Copy the DID (directory)
X	MOVW	NAM+NAM$W_DID+4, DID+4
X 
X	MOVAL	ATTR_LIST, R1		;Address of Attr. list to R1
X 
X	$QIOW_S	CHAN=FAB+FAB$L_STV, -	;I/O on this channel
X		FUNC=#IO$_ACCESS, -	;Access the file
X		IOSB=IOSB, -		;I/O status here
X		P1=FIB_DESC, -		;Address of FIB descriptor
X		P5=R1			;Address of return attributes
X	BLBC	R0, 30$			;Bomb out via deassign if error
X	MOVZWL	IOSB, R0		;Get status in more detail
X	BLBC	R0, 30$			;Bomb out via deassign if error
X 
X	$DASSGN_S -
X		CHAN=FAB+FAB$L_STV	;Deassign the channel
X	BLBC	R0, 20$			;Bomb out if error
X 
X; Directory check:  if the FCH$V_DIRECTORY bit is set, it's a dir
X 
X	MOVL	#SS$_NORMAL, R0
X	BBS	#FCH$V_DIRECTORY, UCHAR, 20$
X	MOVL	#0, R0
X 
X20$:	RET
X 
X30$:	PUSHL	R0			;Push error status code
X	$DASSGN_S -
X		CHAN=FAB+FAB$L_STV	;Deassign the channel
X	POPL	R0			;This is the code we want to return
X	RET
X 
X	.End