From:	SMTP%"RELAY-INFO-VAX@CRVAX.SRI.COM" 10-JUN-1994 10:19:17.57
To:	EVERHART
CC:	
Subj:	SUMMARY: "Hex editor for VMS?"

Date: Thu, 9 Jun 1994 16:43:19 -0500 (CDT)
From: William John Pisciella <pisciell@tenet.edu>
Subject: SUMMARY: "Hex editor for VMS?"
To: INFO-VAX@SRI.COM
In-Reply-To: <Pine.3.89.9405081039.D13905-0100000@Kay-Abernathy.tenet.edu>
Message-ID: <Pine.3.89.9406091648.D29715-0100000@Kay-Abernathy.tenet.edu>
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII


About two weeks ago I posted a question about file editors that can
manipulate data in hexadecimal format (i.e. as chunks of binary data).
I received several replies and would like to thank everyone who responded
to my question.

The majority of the replies I received suggested using VFE. It does everything
I asked for and more. Here is  a message sent to me by Rod Eldridge
<GVROD@ISUVAX.IASTATE.EDU> describing VFE:

From: Rod Eldridge <GVROD@ISUVAX.IASTATE.EDU>
---------------------------------------------
"The VFE utility by Ward Condit, Maricopa Community Colleges, can do what
you ask for above. I have used this utility to edit chunks of data in
files, without having to write a specialized program.

>From "The OpenVMS Software List II" posted monthly to comp.os.vms/INFO-VAX
by J.C. Higgins, VFE is available from the following:

VFE
Description:     Virtual File Editor
Availability:    vesta.sunquest.com (149.138.1.42)
Filename:        [.vaxvms.vfe]
Date:            4-Dec-1992

About VFE:

     VFE is a block-oriented, type insensitive VMS file editor.  It
can edit user files, FOREIGN-mounted tapes, and disk devices.  Data
can be displayed in ASCII, EBCDIC, hex, binary, and integer format.
User-defined sections of single or multiple contiguous blocks can be
changed, compared, and transferred within a file or between files.
VFE also has a very fast search which can target a string, hex or
integer constant.  All or part of a terminal session can be logged
to a sequential file for later lineprinter output."

H.A. Kippenhan Jr. <KIPPENHAN@fndcd.fnal.gov> also suggested using VFE. He
mentioned some additional anonymous ftp sites were VFE can be found:
ftp.spc.edu and black.cerritos.edu. Eberhard Heuser-Hofmann
(vaxinf@chclu.chemie.uni-konstanz.de) from Univ.Konstav, Germany was another
person who pointed me to the VFE editor.

If you just want to swap a couple of bytes in a file without appending or
inserting data, the VMS PATCH utility invoked with the /ABSOLUTE qualifier
can do the job as was suggested by Steve Lionel <lionel@quark.enet.dec.com> 
from Digital. The editing can be done using normal PATCH commands with some 
restrictions. However the file size of the target file can not be changed, so
no new data can be inserted.

And if none of the above fits your needs, here is the Fortran source code 
sent to me by Lee K. Gleason <gleason@MWK.COM> of another hex editor. 

*********************************************************

  This is short enough to just send to you...good luck...

ZAP V2.0
Lee K. Gleason N5ZMR (the fragmentation guy)
Control-G Consultants
1734 Wakefield
Houston TX 77018

Phone 713/681-3985
gleason@mwk.com

*****************************************************************


		ZAP Command Summary

	ZAP, while useful, is as yet unfinished. This accounts for
	the many deficiencies you will notice while using it.

	ZAP was written in a hurry. The code is not a pretty sight.



$ ZAP:==$somedisk:[somedir]zap.exe

$ ZAP filename


	Keypad Commands

	Select		enter block to edit
	Next Screen	edit next block
	Prev Screen	edit previous block
	DO		write current block to file
			press this key in any block
			that you have made permanent changes in	

	GOLD Commands	(PF1, then indicated key)

	A		Display current block in ASCII

	H		Display current block in hex

	B		Block copy (Enter FROM block, then TO Block)

	C		Cut block (save in temp file for paste)

	P		Paste block (restore from previous Cut command)

			Cut and paste will work between ZAP sessions...
			you can cut from one file, exit, then paste
			into another.


	CTRL Commands	(control keys)
	^Z		exit

	^W		repaint part of the screen

	In any block, use the cursor keys to move around.
	When you reach the bottom or top of the screen, the block will
	scroll up or down as needed. It will not scroll into next block.
	To change a value, position on it, then enter the new value.
	If you are in HEX mode, and want to enter a new value,
	entry must be two digits (leading zeros are required.
	To write any changes you make to the file, press the DO
	key before leaving the block.


$ FOR/EXTEND ZAP.FOR
$ FOR/EXTEND FORMAT_LINE.FOR
$ FOR/EXTEND FRESH.FOR
$ FOR/EXTEND READ.FOR
$ FOR/EXTEND SCREEN_INIT.FOR
$ FOR/EXTEND UFO.FOR
$ FOR/EXTEND WRITE.FOR
$ LINK ZAP,FORMAT_LINE,FRESH,READ,SCREEN_INIT,UFO,WRITE



***************************************************************************
File ZAP.FOR
***************************************************************************

! ZAP version 2.00
! Lee K. Gleason N5ZMR
! Control-G Consultants
! 1734 Wakefield
! Houston TX 77018
!
! Phone 713/681-3985
! gleason@mwk.uucp
!
! ZAP mostly works. It was done in a hurry and Fortran's not my native
! language. We've all written things we're not proud of...
!
! If you find bugs, let me know...
!

	implicit integer*4 (a-z)
	include '($smgdef)'
	include '($trmdef)'
	include '($rmsdef)'
	external ufo
	external write
	external read
	character*512 tempblock
	character*80 inchars
	character*6 idstr

	character*10 bcountstr
	character*10 fblockstr
	character*10 tblockstr
	character*14 cvalstr

	character*4	term_set
	byte term_setb(4)	/-1,-1,-1,-1/
	equivalence (term_set,term_setb)

	character*512 a
	integer*2 b(0:255)
	integer*4 c(0:127)
	logical*1 d(16,32)
	equivalence (a,b,c,d)

	integer*4 maxlen /132/,id
	character*132 infile,fid
	integer*4 bufsiz /2/
	integer*4 inlen
	integer*4 term
	integer*4 format /0/
	integer*4 vpsize /20/
	integer*4 dsize /32/

	common /screen/ paste_id,keyboard_id,disp_id1,disp_id2,disp_id3
	common /data/ a
	common /pos/ currow,curcol

	call screen_init

	call smg$set_cursor_abs(disp_id1,1,1)
	call lib$get_foreign(infile,,inlen)
	if (inlen .eq. 0) then
	    call smg$read_string(keyboard_id,infile,'file to mangle? ',
	1	132,,,,inlen,term,disp_id1)
	call smg$erase_display(disp_id1)
	endif

	open (name=infile,err=666,unit=7,status='old',useropen=ufo)
	rabadr=for$rab(7)

1000	id = 1
1001	stat = read (%val(rabadr),id,%ref(a))
	if (.not. stat) then
	    if (stat .eq. rms$_eof) then
	        call smg$ring_bell(disp_id1)
		goto 777		!skip new block stuff if at end
	    else
		goto 666		!die if some other read error
	    endif
	endif

	call smg$begin_display_update(disp_id2)
	do i = 1,scrow
	    call smg$scroll_viewport(disp_id2,smg$m_down)
	end do

	call fresh(format)
	call smg$end_display_update(disp_id2)

	call ots$cvt_l_tu(id,idstr,%val(1),%val(4))
	call smg$set_cursor_abs(disp_id3,2,2)
	call smg$put_line(disp_id3,'Current block='//idstr)

	if (format .eq. 0) then
	    call smg$set_cursor_abs(disp_id2,1,3*16-1)
	else
	    call smg$set_cursor_abs(disp_id2,1,2)
	endif
	
	scrow = 0
	col = 1
	row = 1


777	call smg$return_cursor_pos(disp_id2,currow,curcol)
	stat = smg$read_string(keyboard_id,inchars,,bufsiz,
	1   trm$m_tm_noedit+trm$m_tm_noecho,,term_set,inlen,intermcode,disp_id2,)
	call smg$set_cursor_abs(disp_id2,currow,curcol)

	if (intermcode .eq. smg$k_trm_pf1) then
	    call smg$return_cursor_pos(disp_id2,currow,curcol)
	    call smg$read_string(keyboard_id,inchars,,1,
	1	trm$m_tm_cvtlow+trm$m_tm_noecho+trm$m_tm_noedit,
	1   	,,inlen,intermcode,disp_id2,)
	    call smg$set_cursor_abs(disp_id2,currow,curcol)


	    if (inchars .eq. 'B' ) then
		call smg$read_string(keyboard_id,fblockstr,'From block? ',
	1	    maxlen,,,,inlen,term,disp_id1)
		call lib$cvt_dtb(%val(inlen),%ref(fblockstr),fblock)
		call smg$read_string(keyboard_id,tblockstr,'To block? ',
	1	    maxlen,,,,inlen,term,disp_id1)
		call lib$cvt_dtb(%val(inlen),%ref(tblockstr),tblock)
		call smg$read_string(keyboard_id,bcountstr,'Count? ',
	1	    maxlen,,,,inlen,term,disp_id1)
		call lib$cvt_dtb(%val(inlen),%ref(bcountstr),bcount)
		if (bcount .eq. 0) bcount = 1
		call read (%val(rabadr),fblock,%ref(tempblock))
		do bmove = 0,bcount-1
		    call write (%val(rabadr),tblock+bmove,%ref(tempblock))
		end do

		if (id .ge. fblock .and. id .le. tblock+bcount) then	
		    call read (%val(rabadr),id,%ref(a))
		    call fresh(format)
		endif
	    else if (inchars .eq. 'C' ) then
		open (name='sys$scratch:kut.tmp',type='UNKNOWN',recordsize=512,
	1	    carriagecontrol='none',form='formatted',unit=74,
	1	    recordtype='fixed')
		write (74,100) a(1:512)
		close (74)
	    else if (inchars .eq. 'P') then
		open (name='sys$scratch:kut.tmp',type='old',
	1	    form='formatted',unit=74,recordsize=512,recordtype='fixed')
		read (74,100) a
		stat = write (%val(rabadr),id,%ref(a))
		call fresh(format)
		close (74)

	else if (inchars .eq. 'A') then
	    if (format .eq. 0) then
		call smg$return_cursor_pos(disp_id2,currow,curcol)
		curcol = 3*16 + 1 - curcol
		call smg$set_cursor_abs(disp_id2,currow,curcol)
	    endif	
	    format = 1
	    bufsiz = 1
	    call fresh(format)
	    call smg$set_cursor_abs(disp_id2,currow,curcol)
	    goto 777

	else if (inchars .eq. 'H') then
	    if (format .eq. 1) then
		call smg$return_cursor_pos(disp_id2,currow,curcol)
		curcol = 3*16 + 1 - curcol
		call smg$set_cursor_abs(disp_id2,currow,curcol)
	    endif	
	    format = 0
	    bufsiz = 2
	    call fresh(format)
	    call smg$set_cursor_abs(disp_id2,currow,curcol)
	    goto 777

	    else
		 goto 777
	    endif


	else if (intermcode .eq. smg$k_trm_ctrlz) then
	    stat = 1	
	    goto 666

	else if (intermcode .eq. smg$k_trm_ctrlw) then
	    call smg$erase_display(disp_id2)
	    call fresh(format)
	    call smg$set_cursor_abs(disp_id2,currow,curcol)
	    goto 777

	else if (intermcode .eq. smg$k_trm_select) then
	    call smg$set_cursor_abs(disp_id1,1,30)
	    call smg$read_string(keyboard_id,fid,'block number? ',maxlen,,,,
	1	inlen,term,disp_id1)
	    call lib$cvt_dtb(%val(inlen),%ref(fid),id)
	    call smg$erase_display(disp_id1)
	    goto 1001

	else if (intermcode .eq. smg$k_trm_do) then
	    stat = write (%val(rabadr),id,%ref(a))
	    goto 777

	else if (intermcode .eq. smg$k_trm_next_screen) then
	    id = id+1
	    goto 1001

	else if (intermcode .eq. smg$k_trm_prev_screen .and. (id .gt. 1)) then
	    id = id-1
	    goto 1001

	else if (intermcode .eq. smg$k_trm_buffer_full) then
	    call smg$put_chars(disp_id2,inchars(:bufsiz))
	    call smg$set_cursor_rel(disp_id2,,-bufsiz)
	    if (format .eq. 0) then
		call lib$cvt_htb(%val(inlen),%ref(inchars),newval)
		if (newval .gt. 127) newval = newval-256
		d(col,row) = newval
	        if (smg$cursor_column(disp_id2) .gt. 3) then
		    col = col+1
		    call smg$set_cursor_rel(disp_id2,,-3)
	        else
		    if (row .lt. dsize) then
		        row = row+1
		        col = 1
		        if (row .gt. dsize+scrow) then
			    call format_line(smg$m_up,row,0,format)
			    scrow = scrow+1
			    call smg$set_cursor_rel(disp_id2,0,3*(16-1))
		        else
			    call smg$set_cursor_rel(disp_id2,1,3*(16-1))
		        endif
		    endif
	        endif
	    else
		d(col,row) = ichar(inchars(1:1))
	        if (smg$cursor_column(disp_id2) .le. 3*(16-1)) then
		    col = col+1
		    call smg$set_cursor_rel(disp_id2,,3)
		else
	            if (row .lt. dsize) then
		        row = row + 1
		        col = 1
		        if (row .gt. vpsize+scrow) then
		            call smg$scroll_viewport(disp_id2,smg$m_up)
		            scrow = scrow+1
		        endif
	            endif
		call smg$set_cursor_rel(disp_id2,1,-3*(16-1))
		endif
	    endif
	
	else if (intermcode .eq. smg$k_trm_up) then
	    if (row .gt.1) then
		row = row-1
	        if (row  .le. scrow) then
		    call smg$scroll_viewport(disp_id2,smg$m_down)
		    scrow = scrow-1
	        endif
		call smg$set_cursor_rel(disp_id2,-1)
	    endif

	else if (intermcode .eq. smg$k_trm_down) then
	    if (row .lt. dsize) then
		row = row+1
		if (row .gt. vpsize+scrow) then
		    call smg$scroll_viewport(disp_id2,smg$m_up)
		    scrow = scrow+1
		endif
		call smg$set_cursor_rel(disp_id2,1,0)
	    endif

	else if (intermcode .eq. smg$k_trm_right) then
	    if (smg$cursor_column(disp_id2) .le. 3*(16-1)) then
		if (format .eq. 0) then
		    col = col - 1
		else
		    col = col + 1
		endif
		call smg$set_cursor_rel(disp_id2,0,3)
	    else
		if (format .eq. 0) then
		    if (row .gt. 1) then
		        row = row-1
		        col = 16
		        if (row .le. scrow) then
			    call smg$scroll_viewport(disp_id2,smg$m_down)
			    scrow = scrow-1
		        endif
		    endif
		    call smg$set_cursor_rel(disp_id2,-1,(-3*(16-1)))
		else
	            if (row .lt. dsize) then
		        row = row + 1
		        col = 1
		        if (row .gt. vpsize+scrow) then
		            call smg$scroll_viewport(disp_id2,smg$m_up)
		            scrow = scrow+1
		        endif
		    endif
		    call smg$set_cursor_rel(disp_id2,1,-3*(16-1))
		endif
	    endif


 	else if (intermcode .eq. smg$k_trm_left) then
	    if (smg$cursor_column(disp_id2) .gt. 3) then
		if (format .eq. 0) then
		    col = col + 1
		else
		    col = col - 1
		endif
		call smg$set_cursor_rel(disp_id2,,-3)
	    else
		if (format .eq. 0) then
	            if (row .lt. dsize) then
		        row = row + 1
		        col = 1
		        if (row .gt. vpsize+scrow) then
		            call smg$scroll_viewport(disp_id2,smg$m_up)
		            scrow = scrow+1
		        endif
		    endif
		    call smg$set_cursor_rel(disp_id2,1,3*(16-1))
		else
		    if (row .gt. 1) then
		        row = row-1
		        col = 16
		        if (row .le. scrow) then
			    call smg$scroll_viewport(disp_id2,smg$m_down)
			    scrow = scrow-1
		        endif
		    endif
		    call smg$set_cursor_rel(disp_id2,-1,(3*(16-1)))
		endif
	    endif

	endif


	goto 777

666	close (7)
	call exit(stat)
100	format (a)
	end

********************************************************************
File FORMAT_LINE.FOR
********************************************************************
	integer function format_line(row,format)
	implicit integer*4 (a-z)
	character*512 a
	character*80 outlin

	byte b(16,32)
	equivalence (a,b)
	common /screen/ paste_id,keyboard_id,disp_id1,disp_id2,disp_id3
	common /data/ a

	outlin = ' '
	k = 16
	    do i = 1,16
		if (format .eq. 0 ) then
		    call ots$cvt_l_tz(b(i,row),outlin(:k*3),%val(2),%val(1))
		else
		    call sys$fao('!AF',,outlin(i*3-1:i*3-1),1,b(i,row))
		endif
		k = k-1
		end do

	call smg$put_line(disp_id2,outlin)
	return
	end
********************************************************************
File FRESH.FOR
********************************************************************
	integer function fresh(format)
	implicit integer*4 (a-z)
	include '($smgdef)/nolist'

	common /screen/ paste_id,keyboard_id,disp_id1,disp_id2,disp_id3

	call smg$begin_display_update(disp_id2)
	call smg$return_cursor_pos(disp_id2,currow,curcol)
	call smg$set_cursor_abs(disp_id2,1,1)
	do x = 1,32
	    call format_line(x,format)
	enddo
	call smg$set_cursor_abs(disp_id2,currow,curcol)
	call smg$end_display_update(disp_id2)

	return
	end

********************************************************************
File READ.FOR
********************************************************************
	integer function read(rab,block,buffer)
	implicit integer*4 (a-z)

	include '($rabdef)/nolist'

	record	/rabdef/	rab


	rab.rab$l_bkt = block
	rab.rab$w_usz = 512
	rab.rab$l_ubf = %loc(buffer)

	read = sys$read(rab)

	return	

	end

********************************************************************
File SCREEN_INIT.FOR
********************************************************************
	subroutine screen_init
	implicit integer*4 (a-z)
	include '($smgdef)/nolist'

	common /screen/ paste_id,keyboard_id,disp_id1,disp_id2,disp_id3

	call smg$create_pasteboard(paste_id)
	call smg$control_mode(paste_id,,oldmode)
	call smg$control_mode(paste_id,oldmode+smg$m_notabs+smg$m_clear_screen,)
	
	call smg$create_virtual_keyboard(keyboard_id,'sys$input')
	call smg$create_virtual_display(1,78,disp_id1,smg$m_noborder)
	call smg$create_virtual_display(32,50,disp_id2,smg$m_border)
	call smg$create_viewport(disp_id2,1,1,20,50)
	call smg$create_virtual_display(20,27,disp_id3,smg$m_border)

	call smg$paste_virtual_display(disp_id2,paste_id,2,30)
	call smg$paste_virtual_display(disp_id1,paste_id,23,2)
	call smg$paste_virtual_display(disp_id3,paste_id,2,2)

	return
	end
********************************************************************
File UFO.FOR
********************************************************************
	integer function ufo(fab,rab,lun)

	implicit integer*4 (a-z)
	include '($fabdef)/nolist'
	include '($rabdef)/nolist'

	record	/fabdef/	fab
	record	/rabdef/	rab

	fab.fab$b_fac = fab.fab$b_fac .or. fab$m_bio
	fab.fab$b_shr = 64+8+4+2+1
	rab.rab$l_rop = rab.rab$l_rop .and. (.not. rab$m_tpt)

	stat = sys$open(fab)
	if (stat) stat = sys$connect(rab)
	ufo = stat
	return	

	end

********************************************************************
File WRITE.FOR
********************************************************************
	integer function write(rab,block,buffer)
	implicit integer*4 (a-z)

	include '($rabdef)/nolist'

	record	/rabdef/	rab

	rab.rab$l_bkt = block
	rab.rab$w_rsz = 512
	rab.rab$l_rbf = %loc(buffer)

	write = sys$write(rab)

	return	

	end

********************************************************************
********************************************************


And this is it. I would like to thank everybody again who helped me with my 
search and I hope that this information will be usefull to someone at some
point in time.

