c************
c  Description: HOST code for XRTPLOT primitive
c
c  Author:      SES   1/11/94
c
c  $Revision: 1.1 $
c  $Modtime:   01/16/96 20:46:16  $
c
c************
#define _HOSTVERSION
	program XRTPLOT
c
	include 'xrtplot.inc'
	include 'midas.inc'
	include 'headers.inc'
	integer*4 status

	record /HEADER/ HCB
	record /M_PTR/ lPCB,lbuf
	common /xrtplot/ HCB,Mx,Gx,lPCB,lbuf
c
	call M$CHECKIN ()	! map to shared memory
c old	call MDF$XRTPLOT ()	! get command line parameters/switches
	call MDFH$XRTPLOT ()	! get command line parameters/switches
	call XRTPLOT_INIT(Mx, Gx)
	call M$SYNC ()		! end of preamble
c
	call XRTPLOT_REFRESH(Mx, Gx)	! draw window
c
	do while (.not. Mc.break .and. .not. Mx.breakflag)
	  ! get msg/event/data
	  if (XRTPLOT_RUN(Mx,Gx).eq.0) call M$PAUSE(Mc.pause)
	enddo
c
	if (HCB.open) call M$CLOSE (HCB)
	call XRTPLOT_END(Mx,Gx)
	call M$RETURN ()
c
	end

	subroutine XRTPLOT_SPECS_ ()
	include 'xrtplot.inc'
	include 'headers.inc'
	record /HEADER/ HCB
	record /M_PTR/ lPCB,lbuf
	common /xrtplot/ HCB,Mx,Gx,lPCB,lbuf
	call XRTPLOT_SPECS (Mx,Gx)
	return
	end

	function MD$BUFRES (bufid, nelem, itype)
	include 'xrtplot.inc'
	include 'dsestypes.inc'
	include 'headers.inc'
c Arguments
	integer*4 bufid, nelem, itype
c Locals
	integer*4 ibpa, gbpa
	record /M_PTR/ tbuf
c Common block
	record /HEADER/ HCB
	record /M_PTR/ lPCB,lbuf
	common /xrtplot/ HCB,Mx,Gx,lPCB,lbuf

	if (nelem .eq. 0) then
	  if (bufid.eq.1) then
	    call M$FREE (Gx.lpix)
	  elseif (bufid.eq.2) then
	    ! free both the raw data buffer and the associated GRABX buffer
	    if (lbuf.p .ne. Gx.rbuf.p) call M$FREE (lbuf)
	    call M$FREE (Gx.rbuf)
	  elseif (bufid.eq.3) then
	    call M$FREE (Gx.fbuf)
	  endif
	  MD$BUFRES = 0
	else
	  ! bufid 2, is the buffer for the raw data.  On the host side we
	  ! also need a buffer for GRABX to put data and do the reformatting
	  ! if necessary.  This buffer is lbuf, it can be the same buffer we
	  ! keep the raw data in Gx.rbuf as long as our file data size
	  ! is not larger than float or we have only one frame of data to
	  ! get at a time.
	  ibpa = M$NPT(CHAR(itype))
	  if (bufid.eq.2) then
	    gbpa = M$NPT(CHAR(Gx.type))
	    call M$MALLOC(max(ibpa,gbpa)*nelem, lbuf)
	    if (gbpa.gt.ibpa .and. Gx.lps.gt.1) then
	      call M$MALLOC(ibpa*nelem, tbuf)
	    else
	      tbuf.p = lbuf.p
	    endif
	  else
	    call M$MALLOC(ibpa*nelem, tbuf)
	  endif
	  MD$BUFRES = tbuf.p
	endif

	return
	end

	subroutine MD$SETBUFXFER (bufid, xfer_len)
	include 'xrtplot.inc'
	include 'headers.inc'
	integer*4 bufid, xfer_len
	record /HEADER/ HCB
	record /M_PTR/ lPCB,lbuf
	common /xrtplot/ HCB,Mx,Gx,lPCB,lbuf
	HCB.xfer_len = xfer_len
	return
	end

	subroutine MD$SETBUFCONS (bufid, cons_len)
	include 'xrtplot.inc'
	include 'headers.inc'
	integer*4 bufid, cons_len
	record /HEADER/ HCB
	record /M_PTR/ lPCB,lbuf
	common /xrtplot/ HCB,Mx,Gx,lPCB,lbuf
	HCB.cons_len = cons_len
	return
	end

	function MD$BUFCONS (bufid)
	include 'xrtplot.inc'
	include 'headers.inc'
	include 'dsestypes.inc'
	integer*4 bufid, cons_len
	record /HEADER/ HCB
	record /M_PTR/ lPCB,lbuf
	common /xrtplot/ HCB,Mx,Gx,lPCB,lbuf
	MD$BUFCONS = HCB.cons_len 
	return
	end

c TODO: Find out why XRTPLOT refuses to die when the pipe closes

	function MD$BUFOPEN (bufid)
	include 'xrtplot.inc'
	include 'headers.inc'
	include 'dsestypes.inc'
	integer*4 bufid
	record /HEADER/ PCB
	pointer (pcb_addr, PCB)
	record /HEADER/ HCB
	record /M_PTR/ lPCB,lbuf
	common /xrtplot/ HCB,Mx,Gx,lPCB,lbuf
#if JEFF
	MD$BUFOPEN = 0
	if (HCB.pipe.eq.0) then
	  if (HCB.size - HCB.offset.gt.HCB.xfer_len) MD$BUFOPEN = 1
	elseif (lPCB.p .ne. 0) then
	  pcb_addr = lPCB.p
	  if (PCB.inlet.ge.0) MD$BUFOPEN = 1
	endif
#else
	MD$BUFOPEN = 1
#endif
	return
	end

	function MD$BUFIN (bufid, nelem, type)
	include 'xrtplot.inc'
	include 'headers.inc'
	include 'dsestypes.inc'
	integer*4 bufid, nelem, type, i
	record /HEADER/ HCB
	record /M_PTR/ lPCB,lbuf
	common /xrtplot/ HCB,Mx,Gx,lPCB,lbuf
	if (Gx.loff .eq. 0) then
	  i = 0
	elseif (Gx.cx) then
	  i = 8 * Gx.loff
	else
	  i = 4 * Gx.loff
	endif
	call M$GRABX (HCB, %val(lbuf.p+i), nelem)
	MD$BUFIN = lbuf.p + i
	return
	end

	function MD$BUFAVAILNEXT (bufid, nelem)
	include 'xrtplot.inc'
	include 'headers.inc'
	include 'dsestypes.inc'
c Arguments
	integer*4 bufid, nelem
c Locals
	real*8 out_bytes, dbpe
	record /HEADER/ PCB
	pointer (pcb_addr, PCB)
c Common block
	record /HEADER/ HCB
	record /M_PTR/ lPCB,lbuf
	common /xrtplot/ HCB,Mx,Gx,lPCB,lbuf

c	print *,'BUFAVAILNEXT'
#if JEFF
	if (HCB.pipe.eq.0) then
	  MD$BUFAVAILNEXT = HCB.size - HCB.offset
	elseif (lPCB.p.ne.0) then
	  pcb_addr = lPCB.p
	  if (HCB.open) then
	    MD$BUFAVAILNEXT = (PCB.in_byte -
     +	      PCB.out_bytes(HCB.outlet)) / HCB.dbpe
	  else		! asynchronous read from pipe
c TODO: we need to keep our own local HCB.offset when /SETD/ FRAME message
c is received.
	    out_bytes = max (0.d0, PCB.in_byte - PCB.pipesize)
	    out_bytes = max (out_bytes, PCB.out_bytes(HCB.outlet))
	    if (nelem.gt.1) then
	      dbpe = nelem * HCB.dbpe
	      out_bytes = out_bytes + dbpe - mod(out_bytes-1.d0, dbpe) + 1.d0
	    endif
	    MD$BUFAVAILNEXT = (PCB.in_byte - out_bytes)/HCB.dbpe
	  endif
	else
	  MD$BUFAVAILNEXT = 0
	endif
#else
	call M$HCBFUNC(HCB,HCBF_AVAIL,MD$BUFAVAILNEXT)
#endif
	return
	end

#if _DEBUG
c These routines are here when I need debugging turned on

	subroutine DSMCLIENT ()
	return
	end

	subroutine M$MAP_DS_STRUCTS ()
	return
	end
#endif

c*************
c  Description: DSEF for XRTPLOT 
c
c  Author:	JGS   4/1/91
c
c  $Revision: 1.1 $
c  $Modtime:   17 Oct 1996 08:30:54  $
c
c************
#if _HOSTVERSION
	subroutine MDFH$XRTPLOT ()
#else
	subroutine MDF$XRTPLOT ()
#endif
c
	include 'xrtplot.inc'
	include 'midas.inc'
	include 'dseftypes.inc'
	include 'headers.inc'
	include 'qmessdef.inc'
c
	record /HEADER/ HIN
	character cmode*2, c*10, ch
	real*8 dval
	real*4 dbscale
	integer*4 ic
	record /MQD_TRACE/ MQD
#if _HOSTVERSION
	record /M_PTR/ lPCB,lbuf
	common /xrtplot/ HIN,Mx,Gx,lPCB,lbuf
#endif
c
c open input file
	HIN.file_name =	M$APICK(1)
	HIN.type_allow = '1000,2000,3000,5000,6000'
	HIN.format_allow = 'S*,C*'
	call M$INOK (HIN)
	Gx.class = HIN.class
	Gx.xstart = HIN.xstart
	if (HIN.xdelta .eq. 0.d0) then
	  call M$WARNING ('File has 0.0 X abscissa delta, using 1.0')
	  Gx.xdelta = 1.d0
	else
	  Gx.xdelta = HIN.xdelta
	endif
c
c get other specs
	Gx.ymin   = M$FPICK(2)
	Gx.ymax	  = M$FPICK(3)
	cmode     = M$APICK(4)
	Gx.mframe = M$LPICK(5)	
	Gx.trace  = M$BPICK(6)
c
c get autoscaling and exponential length and init real time range
	Gx.iautom = M$GET_SWITCH('AUTO')
	if (Gx.iautom.lt.0) then
	  Gx.iautom = 0
	  if (.not.M$PPICK(2)) Gx.iautom = 1
	  if (.not.M$PPICK(3)) Gx.iautom = Gx.iautom+2
	  if (Gx.iautom.gt.1) Gx.ymax = 1.0
	endif
	Gx.iautom = max(0,min(3,Gx.iautom))
	Gx.iautol = M$GET_SWITCH_DEF ('AUTOL',1)
c
c figure out X and Y labels
	Gx.ylab	= M$GET_SWITCH_DEF ('YLAB',-1)
	Gx.xlab = M$GET_SWITCH_DEF ('XLAB',HIN.xunits)
	Gx.xdiv = M$GET_SWITCH_DEF ('XDIV',5)
	Gx.ydiv = M$GET_SWITCH_DEF ('YDIV',5)
	if (M$GET_USWITCH('XFMT',Gx.xfmt) .le. 0)  Gx.xfmt = ' '
	if (M$GET_USWITCH('YFMT',Gx.yfmt) .le. 0)  Gx.yfmt = ' '
c
c figure out X and Y mouse results parameter labels
	Gx.imouse = M$GET_USWITCH('XMN',Gx.mouse)
	if (Gx.imouse.le.0)  then
	  Gx.mouse = 'MOUSE'
	  Gx.imouse = 5
	endif
c
c get complex mode from command line parameter
        Gx.cx = HIN.format(1:1) .eq. 'C'
	if (Gx.cx) then
	  Gx.cmode = 1		! Default to magnitude mode for COMPLEX data
	  if (cmode.eq.'PH') Gx.cmode = 2
	  if (cmode.eq.'IM') Gx.cmode = 4
	  if (cmode.eq.'RE') Gx.cmode = 3
	  if (cmode.eq.'RI' .or. cmode.eq.'IR') Gx.cmode = 5
	else
	  Gx.cmode = 3		! Default to real mode for SCALAR data
	  if (cmode.eq.'MA') Gx.cmode = 1
	endif
	if (cmode.eq.'LO' .or. cmode.eq.'D1') Gx.cmode = 6
	if (cmode.eq.'L2' .or. cmode.eq.'D2') Gx.cmode = 7

c
c convert 'LO' and 'L2' parameters to DB and set lower limit on DB values
        Gx.dbmin = 1e-20
	Gx.dbrange = M$GET_SWITCH('DBRANGE')
	if (Gx.dbrange.lt.0.0 .and. cmode(1:1).ne.'L') then
          Gx.dbrange = 50.0
        endif
        if (Gx.cmode .ge. 6) then
          dbscale = 10.0
          if (Gx.cmode.eq.7) dbscale = 20.0
          if (cmode(1:1).eq.'L') then   ! keep backwords compatible behavior
            if (Gx.cx) then
              Gx.ymin = max(Gx.ymin, 1e-10)
              Gx.ymax = max(Gx.ymax, 1e-10)
            else
              Gx.ymin = max(Gx.ymin, 1e-20)
              Gx.ymax = max(Gx.ymax, 1e-20)
          endif
            Gx.ymin = log10(Gx.ymin) * dbscale
            Gx.ymax = log10(Gx.ymax) * dbscale
          elseif (Gx.cx) then   ! these values must be squared
            Gx.ymin = max(-18.0 * dbscale, Gx.ymin)
            Gx.ymax = max(-18.0 * dbscale, Gx.ymax)
            Gx.dbmin = 1e-37            ! smallest possible float/double
          elseif (min(Gx.ymin,Gx.ymax) .lt. -20.0*dbscale) then
            Gx.ymin = max(-37.0 * dbscale, Gx.ymin)
            Gx.ymax = max(-37.0 * dbscale, Gx.ymax)
            Gx.dbmin = 10**(min(Gx.ymin,Gx.ymax)/dbscale)
         endif
        endif
c
c get the frame rate
	if (Gx.mframe.lt.0) then
	  Gx.mframe = -Gx.mframe
	  Gx.class = 1
	elseif (Gx.class .eq. 2) then
	  Gx.mframe = HIN.subsize
	  if (Gx.mframe .eq. 0) then
	    call M$WARNING('File has frame size 0, using 1')
	    Gx.mframe = 1
	  endif
	elseif (Gx.mframe.eq.0) then
	  call M$WARNING('Illegal frame size 0 requested, using 1')
	  Gx.mframe = 1
	endif
c
c get xbounds if indicated
	Gx.xmin = Gx.xstart - Gx.xdelta*(Gx.mframe-1)*.01d0
	Gx.xmax = Gx.xstart + Gx.xdelta*(Gx.mframe-1)*1.02d0
	if (M$PPICK(7)) Gx.xmin = M$DPICK(7)
	if (M$PPICK(8)) Gx.xmax = M$DPICK(8)
	if (Gx.xmin .eq. Gx.xmax) then
	  Gx.xmin = Gx.xmin - 1.d0
	  Gx.xmax = Gx.xmax + 1.d0
	  call M$WARNING ('Illegal X range specified, expanding X axis range')
	endif
c
c get lines per screen switch
	Gx.lps = M$GET_SWITCH('LPS')
	if (Gx.class.gt.2) Gx.lps = SIGN(HIN.subrecords,Gx.lps)
	Gx.clear = (Gx.lps .ge. 0) .and. .not. M$GET_SSWITCH('NOCLEAR')
	Gx.lps = max (1, abs(Gx.lps))
	call M$FORCE1000 (HIN)
	HIN.xfer_len = Gx.mframe * Gx.lps
c
c get widget control ids
        Gx.cntrls = M$GET_SWITCH_DEF ('XCNT',1)
c
c get other switches
	Gx.autoexit = .not. M$GET_SSWITCH('STAY')
	Gx.edge = .not. M$GET_SSWITCH ('NOEDGE')
	Gx.events = M$GET_SWITCH_DEF ('EVENTS',2)
        Gx.grid  = M$GET_SSWITCH('GRID')
	Gx.fast = M$GET_SSWITCH('FAST')
	Gx.mimic = M$GET_SWITCH ('MIMIC')
	Gx.xf.msgid = M$GET_SWITCH ('MSGID')
	Gx.xf.msgmask = M$GET_SWITCH_DEF ('MASK',0)
	Gx.specs = .not. M$GET_SSWITCH('NOSPECS')
	Gx.nowrap = M$GET_SSWITCH ('NOWRAP')
	Gx.yinv = M$GET_SSWITCH ('YINV')

	! pass the color info of the 6th arg to the DSES through Gx.ncolors
	Gx.ncolors = min(100, abs(Gx.trace))

	! interpret old command line syntax
	Gx.symbol = 0
	Gx.thick = 0
	Gx.radius = 3
	if (Gx.trace.gt.0) then		! lines
	  Gx.trace = 3
	elseif (Gx.trace.lt.0) then	! bars
	  Gx.trace = 4
	endif
	if (M$GET_USWITCH('TYPE',c).gt.0) then
	  ic = M$SEARCH('D  LVS',c(1:1)) - 1
	  if (ic.ge.0) Gx.trace = ic
	endif
	if (Gx.trace.eq.0) Gx.symbol = L_PixelSymbol 	! pixels only
	if (M$GET_PSWITCH('THK')) then
	  Gx.thick = M$GET_SWITCH('THK')
	  if (Gx.symbol.ne.0) then
	    if (Gx.thick.gt.0) Gx.symbol = L_CircleSymbol
	    if (Gx.thick.lt.0) Gx.symbol = L_SquareSymbol
	    Gx.radius = iabs(Gx.thick)
	    Gx.thick = 0
	  endif
	endif

	call MX$TRACE_MSG(MQD, Gx.trace, Gx.thick, Gx.symbol, Gx.radius, 999)

#if _CNVX
c
c this is to handle a Convex compiler bug, remove when fixed
	ch = HIN.format(2:2)
	Gx.type = ICHAR (ch)
#else
        Gx.type = ICHAR(HIN.format(2:2))
#endif
        Gx.nelem = Gx.mframe*Gx.lps
        Gx.rmin  = Gx.ymin
        Gx.rmin0 = Gx.ymin
        Gx.rmax  = Gx.ymax
        Gx.rmax0 = Gx.ymax
	if (M$GET_USWITCH('SPECS',ch).lt.0) ch = ' '
	Gx.iabsc = M$SEARCH('IRS',ch)
        Gx.loff = 0
	Gx.pan = 0
	Gx.panbutton = 0
	Gx.markm = 0
	if (M$GET_PSWITCH('MARK')) Gx.markm = -1
	Gx.marks = M$GET_SWITCH('MARK')
	Gx.hold = 0
	Gx.pass = 0
	Gx.j1 = 1
	Gx.j2 = Gx.mframe
	Gx.status = 0

#if _HOSTVERSION

c
c init the graphics setup
	call MX$GRAPHICSINIT ()
	call MXF$SETUP (Mx, Mc.width, Mc.height)
c
c the host version requires some tweeking of the input file header
c and if piped, a mapping to the pipe's header control block
c only go to asynchronous mode if default consume length case
	if (HIN.cons_len.eq.-1) HIN.cons_len = -2
	lPCB.p = 0
	if (HIN.pipe.ne.0) lPCB.p = M$PHEADLOC(HIN.file_lu)
	lbuf.p = 0

#else

c
c init the graphics setup
	call MDX$SETUP (Mx, Mc.width, Mc.height)
c
c initialize dataflow structure counters
	call MD$INIT ()
c
c build data structure
	call MD$DATA (HIN)
c
c build block data structures
	call MD$BBLOCK(Mx, L_Mx)
	call MD$BBLOCK(Gx, L_Gx)
	! pass the cmd line so the DSES gets the color and facilities switches
	call MD$ABLOCK(Mc.command_string(1:Mc.command_length))
c
c submit the structure
	call MD$SUBMIT (MD_NODATA+MD_GRAPHIC)
#endif
c
c get autosync mode
	if (HIN.pipe.ne.0 .and. M$GET_SWITCH('ASYNC').gt.0) 
     &		call M$CLOSE(HIN)
c
	return
	end

c*************
c  Description: Host DSES for XRTPLOT routine
c
c  Author:	JGS   4/1/91
c
c  $Revision: 1.1 $
c  $Modtime:   17 Oct 1996 08:33:16  $
c              21 Jun 2000 MIB DR RRCcl00886 per JCW from Gigi D. observation.
c                 When user zooms in to create a "zoom-box" then iconifies
c              the XRTPLOT window and then de-iconifies it display is not
c              correct; fix is to move the line 
c              "if(X.icon or. Gx.hold.ne.0) return" down abive 25 lines so
c              all required parameters are "saved" before icon to they can
c              be used to restore the window after de-iconify. 
c
c************

#if !_HOSTVERSION
	subroutine MDS$XRTPLOT
c
	include 'xrtplot.inc'
	include 'midas.inc'
	include 'dsestypes.inc'
c
	record /M_PTR/ lMx,lGx,lcmd
	integer*4 invoke,lc
	common/md$context/ BOC,lMx,lGx,EOC
c
	invoke = MD$CHECKIN(BOC,EOC)
c
	if (invoke.eq.0) then

	  call MD$VSTYPE (MP_FLOAT)
	  lMx.p = MD$BLOCKDATA(1, lc)
	  lGx.p = MD$BLOCKDATA(2, lc)
	  lcmd.p = MD$BLOCKDATA(3, lc)
	  call M$MOVE(%val(lcmd.p), %val(%loc(Mc.command_string)), lc)
	  Mc.command_length = lc
	  Mc.switch_length = M$LENGTHD(Mc.command_string(1:lc)) + 1
	  call MX$SETCONTEXT(%val(lMx.p))
	  call XRTPLOT_INIT(%val(lMx.p), %val(lGx.p))
	  call XRTPLOT_REFRESH(%val(lMx.p), %val(lGx.p))

	elseif (invoke.gt.0) then

	  call MX$SETCONTEXT(%val(lMx.p))
	  if (XRTPLOT_RUN(%val(lMx.p),%val(lGx.p)).eq.0) call MD$PEBMODE(-2)

	elseif (invoke.eq.-1) then

	  call MX$SETCONTEXT(%val(lMx.p))
	  call XRTPLOT_END(%val(lMx.p), %val(lGx.p))

	endif
c
	return
	end


	subroutine XRTPLOT_SPECS_()
	implicit none
	include 'dses.inc'
	record /M_PTR/ lMx,lGx
	common/md$context/ BOC,lMx,lGx,EOC
	call XRTPLOT_SPECS (%val(lMx.p),%val(lGx.p))
	return
	end

#endif

	subroutine XRTPLOT_END (Mx,Gx)
	include 'xrtplot.inc'
	if (Gx.status.ge.0) then
	  call MX$FACILITIES(Gx.xf, 'ABP', L_CleanExit)
	  call MX$CLOSE()
#if !_HOSTVERSION
	  call MD$PEBMODE(0)
#endif
	  call XRTPLOT_MSGDO (Mx, Gx, MSK_EXIT, 0)
	  Gx.status = -1
	endif
	return
	end

	function XRTPLOT_RUN (Mx, Gx)
	include 'xrtplot.inc'
	include 'midas.inc'
	include 'dsestypes.inc'
	integer*4 nelem
	record /M_PTR/ lin
c
c handle events and messages
	Gx.status = 0
	if (Gx.hold.lt.2) call XRTPLOT_EVENT (Mx,Gx)
	if (Mu.todo.le.0) call XRTPLOT_MSG (Mx,Gx)
c
c handle next data block
	if (Mx.breakflag .or. Gx.hold .ge. 2 .or. Mu.todo.eq.0) then
	  ! abort from event or message, or skip due to hold flag, queued
	elseif (Gx.class .eq. 2) then
	  nelem = MD$BUFAVAILNEXT(1,1) / Gx.mframe
	  if (nelem.ge.Gx.lps .or. 		! full buffer
     +	      (Mu.todo.gt.0 .and. nelem.ge.NINT(Mu.todo))) then
	    nelem = min(nelem,Gx.lps)
	    if (Mu.todo.gt.0) nelem = min(nelem,NINT(Mu.todo))
	    call MD$SETBUFXFER (1,nelem*Gx.mframe)
	  elseif (MD$BUFOPEN(1).ne.0) then	! pipe open; wait 4 full buffer
	    nelem = 0
	  elseif (nelem.gt.0) then	! pipe closed; plot frames left
	    call MD$SETBUFXFER (1,nelem*Gx.mframe)
	  elseif (Gx.autoexit) then		! no full frames left; exit(?)
	    Mx.breakflag = .true.
	  endif
	  if (nelem.gt.0) then
	    lin.p = MD$BUFIN (1,Gx.nelem,Gx.type)
	    if (Mu.todo.gt.0) Mu.todo = INT(Mu.todo - Gx.nelem/Gx.mframe)
	    call XRTPLOT_PREP(Mx, Gx, %val(lin.p), 0)
	    call XRTPLOT_PLOT(Mx, Gx, Gx.nelem)
	    Gx.status = 1
	  endif
	else
	  nelem = MD$BUFAVAILNEXT(1,1)
	  if (nelem .gt. 0) then
	    nelem = min( nelem, Gx.mframe * Gx.lps - Gx.loff )
	    if (Mu.todo.gt.0) nelem = min(nelem,NINT(Mu.todo))
	    call MD$SETBUFXFER (1,nelem)
	    lin.p = MD$BUFIN (1,nelem,Gx.type)
	    if (Mu.todo.gt.0) Mu.todo = Mu.todo - nelem
	    Gx.nelem = Gx.loff + nelem
	    call XRTPLOT_PREP(Mx, Gx, %val(lin.p), 0)
	    call XRTPLOT_PLOT(Mx, Gx, nelem)
	    Gx.loff = Gx.nelem
	    if (Gx.loff .ge. Gx.mframe * Gx.lps) Gx.loff = 0
	    Gx.status = 1
	  elseif (MD$BUFOPEN(1).eq.0) then
	    if (Gx.autoexit) Mx.breakflag = .true.
	  endif
	endif

	if (Mx.breakflag) call XRTPLOT_END(Mx,Gx)
	XRTPLOT_RUN = Gx.status
	return
	end


	subroutine XRTPLOT_INIT (Mx,Gx)
	include 'xrtplot.inc'
	include 'midas.inc'
	include 'qmessdef.inc'
	integer*4 nelem, n, pos
	logical*4 sqwave
	record /MQD_COLOR/ color(L_color)
	external XRTPLOT_SPECS_
c
c open window
	Mx.origin = 1
	Mx.level = 1
#if _HOSTVERSION
	call MX$OPEN ('X-RTPlot')
#else
	call MX$DOPEN (Mx,'X-RTPlot') 
#endif
c
c setup colormap and initial text size
	color(1).position = Gx.ncolors
	do n = 2, L_color
	  color(n).position = -2
	enddo
        Gx.ncolors = Gx.lps
	call MX$XC(Mc.colormap(4), color, Gx.ncolors)
	call MX$COLORMAP(Mc.colormap(4), Gx.ncolors)
	do n = 1, Gx.ncolors
	  pos = color(n).position
	  if (pos .eq. -1) then
	    call MX$COLORTAB(n, color(n), -2)
	  elseif (pos .ge. 0) then
	    call MX$COLORTAB(n, Mc.colormap(4), pos)
	  endif
	enddo

	call MX$DRAW_MODE(Gx.thick)
c
c allocate the PIX buf, raw data buf and temp float buf
	call XRTPLOT_ALLOCATE (Gx, 0)
c
c set up the facilities (points/boxes/annotations)
	Gx.xf.mpoint = 512
	Gx.xf.mbox = 50
	Gx.xf.mannt = 20
	Gx.xf.xy = .true.
#if _PGF77|_HPUX
	Gx.xf.ROUTINE.p = get_address(XRTPLOT_SPECS_)
#else
	Gx.xf.ROUTINE.p = %loc(XRTPLOT_SPECS_)
#endif
	call MX$FACILITIES(Gx.xf, 'ABP', L_InitFacilities)
	Gx.nxf = max(0,Gx.xf.nannt) + Gx.xf.nbox + Gx.xf.npoint
c
c init stuff
	call XRTPLOT_RESET (Mx,Gx)
	Gx.melem = 0
	Gx.nelem = 0	! no data yet
c
	return
	end



	subroutine XRTPLOT_ALLOCATE (Gx, flag)
	include 'xrtplot.inc'
	include 'dsestypes.inc'
	integer*4 nelem, flag

	nelem = Gx.nelem
	if (Gx.cx) nelem = nelem + nelem
	if (flag.eq.1) then ! realloc / no copy on ds / m$free on host
	  Gx.lpix.p = MD$BUFRES (1, 0, MP_LONG)		! pix buf
	  Gx.rbuf.p = MD$BUFRES (2, 0, MP_FLOAT)	! raw data buf
	  Gx.fbuf.p = MD$BUFRES (3, 0, MP_FLOAT)	! float buf
	endif
	Gx.lpix.p = MD$BUFRES (1, Gx.mframe, MP_LONG)	! pix buf
	Gx.rbuf.p = MD$BUFRES (2, nelem, MP_FLOAT)	! raw data buf
	Gx.fbuf.p = MD$BUFRES (3, Gx.nelem, MP_FLOAT)	! float buf

	return
	end



	subroutine XRTPLOT_RESET (Mx,Gx)
	include 'xrtplot.inc'
	real*8 ymin, ymax
	integer*4 k, level
c
c initialize the plot ranges
	level = Mx.level
	k = 1
	Mx.level = k
	if (Gx.rmin0.eq.Gx.rmax0) then	! if no plot range, create one
	  Gx.rmin0 = Gx.rmin0 - 1.0
	  Gx.rmax0 = Gx.rmax0 + 1.0
	endif
	if (Gx.cmode.eq.2) then
	  ymin = -180.
	  ymax = 180.
	else
	  ymin = Gx.rmin0
	  ymax = Gx.rmax0
	endif
	if (Gx.yinv) then
	  Mx.stk(k).ymin = ymax
	  Mx.stk(k).ymax = ymin
	else
	  Mx.stk(k).ymin = ymin
	  Mx.stk(k).ymax = ymax
	endif
	if (Gx.cmode.eq.5) then
	  Mx.stk(k).xmin = Mx.stk(k).ymin 
	  Mx.stk(k).xmax = Mx.stk(k).ymax 
	else
	  Mx.stk(k).xmin = Gx.xmin
	  Mx.stk(k).xmax = Gx.xmax
	endif
	if (level.gt.1) call XRTPLOT_MSGDO (Mx, Gx, MSK_UNZOOM, Mx.level)
c
	return
	end



	subroutine XRTPLOT_REFRESH (Mx, Gx)
	include 'xrtplot.inc'
	integer*4 iscl,isct,iscw,isch,mtext,k,i,ii
	record /PIXSTRUCT/ pix(1)
	pointer (pix_addr, pix)

c
c set text size
	mtext = min(8,Mx.width/48)
	call MX$SETFONT (mtext)
	if (Gx.symbol .gt. ICHAR(' ')) Gx.radius = Mx.text_w / 2
c
c set window borders
	k = Mx.level
	if (Gx.specs) then
	  Mx.stk(k).x1 = Mx.text_w*6
	  Mx.stk(k).x2 = Mx.width - Mx.text_w*2
	  Mx.stk(k).y1 = Mx.text_h*2
	  Mx.stk(k).y2 = Mx.height - Mx.text_h*4
	else
	  Mx.stk(k).x1 = 1
	  Mx.stk(k).x2 = Mx.width - 2
	  Mx.stk(k).y1 = 1
	  Mx.stk(k).y2 = Mx.height - 2
	endif
	if (k.eq.1) then
	  ! no pan bars
	elseif (Gx.specs) then
	  Mx.stk(k).x2 = Mx.stk(k).x2 - 2
	else
	  Mx.stk(k).y1 = Mx.stk(k).y1 + Mx.text_w*2
	  Mx.stk(k).x2 = Mx.stk(k).x2 - Mx.text_w*2
	endif
	Mx.stk(k).xscl = (Mx.stk(k).xmax-Mx.stk(k).xmin)/
     &		(Mx.stk(k).x2-Mx.stk(k).x1)
	Mx.stk(k).yscl = (Mx.stk(k).ymax-Mx.stk(k).ymin)/
     &		(Mx.stk(k).y2-Mx.stk(k).y1)
c
c mib 21-June-2000 MIB start fix for DR RRCcl00886
c now that we have valid info, bail out if iconified &c
	if (Mx.icon .or. Gx.hold.ne.0) return
c mib 21-June-2000 MIB end fix for DR RRCcl00886

c set graphics clip window
	call MX$CLIP (Mx.stk(k).x1, Mx.stk(k).y1,
     &    Mx.stk(k).x2-Mx.stk(k).x1+1, Mx.stk(k).y2-Mx.stk(k).y1)
c
c clear the window
	call MX$CLEAR_WINDOW ()
	Gx.e1 = Mx.stk(k).x1
	Gx.markp.x = -1
c
c set labels, display axis and current specs
	Gx.ixlab = Gx.xlab
	if (Gx.cmode.eq.5) Gx.ixlab = 21
	Gx.iylab = Gx.ylab
	if (Gx.cmode.eq.1 .and. .not. Gx.cx) Gx.iylab = 28
	if (Gx.cmode.eq.2) Gx.iylab = 24
	if (Gx.cmode.eq.3 .and. Gx.cx) Gx.iylab = 21
	if (Gx.cmode.eq.4) Gx.iylab = 22
	if (Gx.cmode.eq.5) Gx.iylab = 22
	if (Gx.cmode.eq.6) Gx.iylab = 26
	if (Gx.cmode.eq.7) Gx.iylab = 27
	if (Gx.specs) then
	  call MX$DRAWAXIS(Gx.xdiv, Gx.ydiv, Gx.ixlab, Gx.iylab, Gx.grid)
	  call XRTPLOT_SPECS (Mx,Gx)
	elseif (Gx.grid) then
	  if (Gx.ixlab.eq.4) then
	    call MX$DRAWAXIS(Gx.xdiv, Gx.ydiv, -4, -3, .true.)
	  else
	    call MX$DRAWAXIS(Gx.xdiv, Gx.ydiv, -2, -3, .true.)
	  endif
	endif
	
c
c draw the pan bars
	if (k.gt.1) i = XRTPLOT_PAN_HANDLE (Mx,Gx,0,i)
c
c form the X-pix values
	if (Gx.cmode.ne.5) then
	  pix_addr = Gx.lpix.p
	  Gx.j1 = max(1,INT((Mx.stk(k).xmin-Gx.xstart)/Gx.xdelta)+1)
	  Gx.j2 = min(Gx.mframe, INT((Mx.stk(k).xmax-Gx.xstart)/Gx.xdelta)+2)
	  do i = Gx.j1, Gx.j2
	    ii = Mx.stk(k).x1 + 
     +	    ( Gx.xstart+(i-1)*Gx.xdelta - Mx.stk(k).xmin )/Mx.stk(k).xscl
	    pix(i).x = ii
	    pix(i).y = 0
	  enddo
	endif
c
c replot the data/facilities
	call XRTPLOT_PLOT(Mx, Gx, 0)

	return
	end



	function XRTPLOT_PAN_HANDLE (Mx,Gx,m,i) 
	include 'xrtplot.inc'
	include 'xwidgets.inc'
	integer*4 i,m,k,ix,iy,ix1,ix2,iy1,iy2
	logical*4 act
	record /SCROLLBAR/ sbx, sby
c  m = 0:draw  1:check 
	i = 0
	k = Mx.level 
	act = .false.
	sbx.flag = -12
	sby.flag = -12
	if (k.eq.1 .or. (m.gt.0 .and. Mx.button_press.eq.0)) goto 9
	if (Gx.pan.eq.0) then
	  Gx.click.x = Mx.xpos
	  Gx.click.y = Mx.ypos
	  sbx.action = 0
	  sby.action = 0
	else
	  if (Gx.pan.ne.5) Mx.xpos = Gx.click.x
	  if (Gx.pan.ne.6) Mx.ypos = Gx.click.y
	endif
	ix = Mx.xpos
	iy = Mx.ypos
c vertical
	ix1 = min(Mx.width-Mx.text_w-1, Mx.stk(k).x2+4+(Mx.text_w-3)/2)
	ix2 = ix1 + Mx.text_w
	iy1 = Mx.stk(k).y1
	iy2 = Mx.stk(k).y2
	if (Gx.pan.eq.6) then
	  Mx.ypos = max (iy1+Mx.text_w-2, min (iy2-Mx.text_w+1, Mx.ypos)) 
	  iy = Mx.ypos
	endif
	if (m.eq.0) then
	  i = MX$SCROLLBAR (0,ix1,ix2,iy1,iy2,
     +	    Mx.stk(k).ymin,Mx.stk(k).ymax,Mx.stk(1).ymin,Mx.stk(1).ymax)
	elseif (ix.gt.ix1-25*(m-1) .and. iy.gt.iy1 .and. iy.lt.iy2) then
	  if (Gx.pan.eq.0) then
	    Gx.pan = 6
	    if (iy.lt.iy1+Mx.text_w-1) Gx.pan = 2
	    if (iy.gt.iy2-Mx.text_w) Gx.pan = 4
	  endif
	  i = i + MX$SCROLLBAR(sby,ix1,ix2,iy1,iy2,
     +	    Mx.stk(k).ymin,Mx.stk(k).ymax,Mx.stk(1).ymin,Mx.stk(1).ymax) 
	  if (i.gt.0)  call XRTPLOT_MSGDO (Mx, Gx, MSK_PANY, Mx.level)
	  act = .true.
	endif
c horizontal
	ix1 = Mx.stk(k).x1
	ix2 = Mx.stk(k).x2 
	if (Gx.specs) ix1 = min(ix2-40,ix1 + Mx.text_w*30)
	iy2 = Mx.stk(k).y1 - Mx.text_w
	iy1 = iy2 - Mx.text_w
	if (Gx.pan.eq.5) then
	  Mx.xpos = max (ix1+Mx.text_w-2, min (ix2-Mx.text_w+1, Mx.xpos)) 
	  ix = Mx.xpos
	endif
	if (m.eq.0) then
	  i = MX$SCROLLBAR (0,ix1,ix2,iy1,iy2,
     +	    Mx.stk(k).xmin,Mx.stk(k).xmax,Mx.stk(1).xmin,Mx.stk(1).xmax)
	elseif (ix.gt.ix1.and.ix.lt.ix2.and.iy.lt.iy2+25*(m-1)) then
	  if (Gx.pan.eq.0) then
	    Gx.pan = 5
	    if (Mx.xpos.gt.ix2-Mx.text_w) Gx.pan = 1
	    if (Mx.xpos.lt.ix1+Mx.text_w-1) Gx.pan = 3
	  endif
	  i = i + MX$SCROLLBAR(sbx,ix1,ix2,iy1,iy2,
     +	    Mx.stk(k).xmin,Mx.stk(k).xmax,Mx.stk(1).xmin,Mx.stk(1).xmax) 
	  if (i.gt.0) call XRTPLOT_MSGDO (Mx, Gx, MSK_PANX, Mx.level)
	  act = .true.
	endif
	Gx.panbutton = Mx.button_press
 9	XRTPLOT_PAN_HANDLE = act
	return
	end


	subroutine XRTPLOT_EVENT (Mx,Gx)
	include 'xrtplot.inc'
	include 'dsestypes.inc'
	include 'midas.inc'
	integer*4 ix1,iy1,ix2,iy2,item,imode,idef,lcolor,ls,i,j,k,evs
	integer*4 lin,thk,sym,rad
	character cspec*30, c
	character*(L_max_ascii) filename
	character*300 menu
	external XRTPLOT_SPECS_

	evs = 0
	do while (.not. Mx.breakflag .and. evs.lt.Gx.events)

	  if (MX$IFEVENT()) then
	    Gx.status = Gx.status + 1
	  elseif (Gx.pan.le.0) then
	    return
	  endif
	  evs = evs + 1

	  if (Gx.pan.gt.0) then				! held pan
	    Mx.button_press = Gx.panbutton
	    if (Mx.button_release.ne.0) then
	      Gx.pan = 0
	    elseif (Gx.tclick.ge.0.0 .and. 
     +              SECNDS(Gx.tclick).lt.0.3) then
	      ! Wait for initial time to pass
	    elseif (XRTPLOT_PAN_HANDLE(Mx,Gx,1,i)) then
	      Gx.tclick = -1.0
	      if (i.gt.0) then
#if !_HOSTVERSION
		if (evs.ge.Gx.events .and. Gx.class.eq.2) then
		  if (MD$BUFAVAILNEXT(1,Gx.mframe).ge.Gx.mframe*Gx.lps) then
		    Gx.nelem = 0
		    Gx.melem = 0
		  endif
		endif
#endif
		call XRTPLOT_REFRESH (Mx,Gx)
		if (Gx.status.eq.0) Gx.status = Gx.status + 1
	      endif
	    endif
	    return

	  elseif (Mx.motion_notify) then
	    ! display specs at bottom

	  elseif (XRTPLOT_PAN_HANDLE(Mx,Gx,1,i)) then	! pan
	    Gx.tclick = -1.0
	    if (Gx.pan.le.4) Gx.tclick = SECNDS(0.0)
	    Gx.click.x = Mx.xpos
	    Gx.click.y = Mx.ypos
	    Mx.exposure = (i.gt.0)

	  elseif (Mx.button_press.eq.1) then
	    call MX$RUBBERBOX (ix1,iy1,ix2,iy2,XRTPLOT_SPECS_)
	    if (Mx.button_release.ne.1) then
	    elseif (ix2-ix1.lt.5 .and. iy2-iy1.lt.5) then	! set origin
              call XRTPLOT_SPECS (Mx,Gx)
	      Gx.xmrk = Gx.retx 
	      Gx.ymrk = Gx.rety
	      if (Gx.cntrls.eq.1) then
		call M$DRSLT (Mx.xtag,Gx.retx)
		call M$DRSLT (Mx.ytag,Gx.rety)
	      endif
	      call XRTPLOT_MSGDO (Mx, Gx, MSK_MARK, Mx.level)
	    elseif (ix2-ix1.gt.5 .and. iy2-iy1.gt.5) then	! zoom
              call XRTPLOT_ZOOM (Mx,Gx,ix1,iy1,ix2,iy2)
	    endif 

	  elseif (Mx.button_press.eq.3) then		! unzoom
	    if (Mx.level.gt.1) then
	      Mx.level = Mx.level-1
	      call XRTPLOT_REFRESH (Mx,Gx)
	      call XRTPLOT_MSGDO (Mx, Gx, MSK_UNZOOM, Mx.level)
	    endif	    

	  elseif (Mx.button_press.eq.2 .or. Mx.key_upchar.eq.'M') then	! menu

	    item = MX$MENU (0,'X-RTPLOT;Refresh,Cntrls...,CX Mode...,'//
     &		'Frame...,Scale...,Color...,Lines...,Settings...,'//
     &		'Annotate,Boxes,Points,Exit')

	    if (item.eq.1) then				! refresh
	      Mx.exposure = .true.

	    elseif (item.eq.2) then			! controls option

	      item = 3 - MX$MENU (3-Gx.cntrls,'CONTROLS OPTIONS;'//
     &		'Continuous,LM Click,Off,LM Click (Disabled),'//
     &		'Continuous (Disabled),Assign...')
              if (item.eq.-3) then
		call MX$PROMPT ('Mouse X location -> ',Mx.xtag)
		call M$UPPERCASE (Mx.xtag)
		call MX$PROMPT ('Mouse Y location -> ',Mx.ytag)
		call M$UPPERCASE (Mx.ytag)
              else
                Gx.cntrls = item
	      endif

	    elseif (item.eq.3) then			! change complex mode
	      i = MX$MENU(Gx.cmode, 'DATA TRANSFORMATION;Magnitude,'//
     &		  'Phase,Real,Imaginary,IR:Imag/Real,10*Log10,20*Log10')

	      if (i.ne.0 .and. i.ne.Gx.cmode) then
		call XRTPLOT_CMODE(Mx, Gx, i)
		if (.not.Gx.cx .and. Gx.cmode.ne.i)
     &		  call MX$MESSAGE('The data transformation selected is '//
     &		'not valid for SCALAR data.  Selection aborted.', -1.0)
	      endif

	    elseif (item.eq.4) then			! change frame
	      i = Gx.mframe
	      call MX$LPROMPT('Frame: ',i)
	      if (i.ne.Gx.mframe) then
		j = MX$MENUPLUS (6,'Options;Warp Range,Retain Data',
     &			-1, 0, 0) / 2	! right shift one bit
		call XRTPLOT_REFRAME (Mx,Gx,i,j)	      
	      endif

	    elseif (item.eq.5) then			! scale
	      cspec = ': '
	      if (Gx.cmode.ge.6) cspec = '(dB)'//cspec
	      i = M$LENGTH(cspec) + 1
	      call XRTPLOT_SETTINGS(Mx, Gx, t_auto, -999)
	      if (Gx.iautom.eq.0) then		! Parameters
	        call MX$FPROMPT('Minimum'//cspec(1:i), Gx.ymin)
	        call MX$FPROMPT('Maximum'//cspec(1:i), Gx.ymax)
		Gx.rmin0 = Gx.ymin
		Gx.rmax0 = Gx.ymax
	      elseif (Gx.iautom.eq.4) then	! Auto Fix
	        call MX$FPROMPT('FixAuto Min'//cspec(1:i), Gx.rmin0)
	        call MX$FPROMPT('FixAuto Max'//cspec(1:i), Gx.rmax0)
	      else
		if (Gx.cmode.ge.6 .and.
     &		  (Gx.iautom.eq.1 .or. Gx.iautom.eq.3)) 
     &		  call MX$FVAL('dB Range: ',Gx.dbrange,0.0,
     &                          300.0,5.0,0)
	        call XRTPLOT_SETTINGS(Mx, Gx, t_autol, -999)
	      endif
	      call XRTPLOT_RESET (Mx,Gx)
	      Mx.exposure = .true.

	    elseif (item.eq.6) then			! color
	      call MX$COLORTAB (1, Mc.colormap(4), -1)

	    elseif (item.eq.7) then			! LineType
	      lin = Gx.trace
	      thk = Gx.thick
	      rad = Gx.radius
	      sym = Gx.symbol

	      i = 1
	      do while (i.ne.0)
		i = MX$MENU(0,'TRACE ATTRIBUTES;Line Type...,'//
     &				'Thickness...,Symbols...,Radius...')

		if (i.eq.1) then
		  lin = MX$MENU(Gx.trace+1, 'LINE TYPE;None,Verticals,'//
     &		    'Horizontals,Connecting,Bars,Square Wave')-1

		elseif (i.eq.2) then
		  call MX$LVAL('Line Thickness: ', thk, -16, 16, 1, 0)

		elseif (i.eq.3) then
		  sym = MX$MENU(max(0,min(8,Gx.symbol))+1, 'SYMBOLS;None,'//
     &		    'Pixels,Circles,Squares,Plusses,X''s,Triangles,'//
     &		    'Downward Triangles,ASCII...')-1
		  if (sym.eq.8) then
		    c = ' '
		    if (Gx.trace .gt. ICHAR(' ')) c = CHAR(Gx.trace)
		    call MX$PROMPT('ASCII Character: ', c(1:1))
		    if (c .ne. ' ') then
		      rad = Mx.text_w / 2
		      sym = ICHAR(c)
		    else
		      sym = Gx.symbol
		    endif
		  elseif (sym.eq.L_PixelSymbol) then
		    rad = 0
		  endif

		elseif (i.eq.4) then
		  if (sym.ne.0 .and. sym.lt.8) then
		    call MX$LVAL('Radius: ', rad, -16, 16, 1, 0)
		  else
		    call MX$MESSAGE(
     &		'Radius cannot be set with this type of symbol.',-1.d0)
		  endif
		endif
	      enddo

	      if (lin.ne.Gx.trace .or. thk.ne.Gx.thick .or.
     &		  sym.ne.Gx.symbol .or. rad.ne.Gx.radius) then
		Gx.trace = lin
		Gx.thick = thk
		Gx.symbol = sym
		Gx.radius = rad
		call MX$DRAW_MODE(Gx.thick)
		Mx.exposure = .true.
	      endif

	    elseif (item.eq.8) then
	      menu = 'SETTINGS;  AUTO Scale Mode...,  AUTOLines...,- CLE'//
     &		     'AR Old Data,  CONTROLS...,- EDGE,  EVENTS/Pass...,'//
     &		     '- FAST,- GRID,  MARKer Mode...,  MARKer Size...,  '//
     &		     'MIMIC id...,  MSGID...,- SPECS,- WRAP Specs,  XDIV'//
     &		     'isions...,  XLABEL...,  YDIVisions...,- YINVersion'//
     &		     ',  YLABEL...,'

	      i = M$SEARCH(menu, 'CLEAR') - 2
	      if (Gx.clear) menu(i:i) = '+'
	      i = M$SEARCH(menu, 'EDGE') - 2
	      if (Gx.edge) menu(i:i) = '+'
	      i = M$SEARCH(menu, 'FAST') - 2
	      if (Gx.fast) menu(i:i) = '+'
	      i = M$SEARCH(menu, 'GRID') - 2
	      if (Gx.grid) menu(i:i) = '+'
	      i = M$SEARCH(menu, 'SPECS') - 2
	      if (Gx.specs) menu(i:i) = '+'
	      i = M$SEARCH(menu, 'WRAP') - 2
	      if (.not. Gx.nowrap) menu(i:i) = '+'
	      i = M$SEARCH(menu, 'YINV') - 2
	      if (Gx.yinv) menu(i:i) = '+'

	      i = MX$MENU(0,menu)

	      call XRTPLOT_SETTINGS(Mx, Gx, i, -999)

	    elseif (item.ge.9 .and. item.le.11) then
	      cspec = 'ABP'
	      call XRTPLOT_XF(Mx, Gx, cspec(item-8:item-8), L_Interactive)

	    elseif (item.eq.12) then			! exit
	      if (Mx.noexit.gt.1) call MX$MESSAGE ('Exit disabled', 1.0)
	      if (Mx.noexit.le.1) Mx.breakflag = .true.
	    endif

	  elseif (Mx.key_char.ge.'0'.and.Mx.key_char.le.'9') then ! markers
	    call XRTPLOT_SPECS (Mx,Gx)
	    call M$DRSLT(Gx.mouse(1:Gx.imouse)//'_X'//Mx.key_char,Gx.retx)
	    call M$DRSLT(Gx.mouse(1:Gx.imouse)//'_Y'//Mx.key_char,Gx.rety)
	    call M$BEEP (1,0.0)

	  elseif (Mx.key_upchar.eq.'B') then      ! Boxes Oneshot
	    call XRTPLOT_XF(Mx, Gx, 'B', L_OneShot)

	  elseif (Mx.key_upchar.eq.'P') then      ! Points Oneshot
	    call XRTPLOT_XF(Mx, Gx, 'P', L_OneShot)

	  elseif (Mx.key_upchar.eq.'?') then      ! help
	    call MX$MHELP('X-RTPLOT','Primitive')

	  elseif (Mx.key_upchar.eq.'H') then      ! help
	    filename = 'xrtplot'
	    if (MX$HARDCOPY_OPEN(filename, -1)) then
	      call XRTPLOT_REFRESH(Mx,Gx)
	      call MX$HARDCOPY_CLOSE()
	      Mx.exposure = .false.
	      Mx.resize = .false.
	    endif

	  elseif (Mx.key_upchar.eq.'A') then 	! toggle abscissa
	    Gx.iabsc = mod(Gx.iabsc+1,4)

	  elseif (Mx.key_upchar.eq.'S') then 	! toggle specs
	    Gx.specs = .not. Gx.specs
	    Mx.exposure = .true.

	  elseif (Mx.key_upchar.eq.'X') then 	! show X
	    ls = M$D2A (Gx.aretx,cspec)
	    if (Gx.iabsc.eq.1) then
	      call MX$MESSAGE('INDEX = '//cspec(1:ls), -1.0)
	    elseif (Gx.iabsc.eq.2) then
	      call MX$MESSAGE('1/X = '//cspec(1:ls), -1.0)
	    else
	      if (Gx.ixlab.eq.4) ls = M$SEC2TSPEC (Gx.aretx,cspec,0)
	      call MX$MESSAGE('X = '//cspec(1:ls), -1.0)
	    endif

	  elseif (Mx.key_upchar.eq.'Y') then 	! show Y
	    ls = M$D2A (Gx.arety,cspec)
	    if (Gx.iabsc.eq.2) then
	      call MX$MESSAGE('1/Y = '//cspec(1:ls), -1.0)
	    else
	      if (Gx.iylab.eq.4) ls = M$SEC2TSPEC (Gx.arety,cspec,0)
	      call MX$MESSAGE('Y = '//cspec(1:ls), -1.0)
	    endif

	  elseif (Mx.key_upchar.eq.'C') then 	! toggle cntrls
	    Gx.cntrls = -Gx.cntrls

	  elseif (Mx.key_press.eq.13) then	! the END (except in pipe)
	    if (Mx.noexit.le.0) Mx.breakflag = .true.

	  endif

	  call XRTPLOT_SPECS (Mx,Gx)
	  if (Gx.pan.eq.0 .and. Mx.motion_notify .and. Gx.cntrls.eq.2) then
	    k = Mx.level
	    if (Mx.xpos.ge.Mx.stk(k).x1 .and. Mx.xpos.le.Mx.stk(k).x2 .and.
     &		Mx.ypos.ge.Mx.stk(k).y1 .and. Mx.ypos.le.Mx.stk(k).y2) then
	      call M$DRSLT (Mx.xtag,Gx.retx)
	      call M$DRSLT (Mx.ytag,Gx.rety)
	    endif
	  endif

	  if (Mx.exposure .or. Mx.resize) call XRTPLOT_REFRESH(Mx,Gx)

	enddo

	return
	end


	subroutine XRTPLOT_MSG (Mx,Gx)

	include 'xrtplot.inc'
	include 'midas.inc'
	include 'qmessdef.inc'
	include 'qmessdecl.inc'
	logical*4 xpan, ypan, echo, cons
	integer*4 i, info, sid, mimic, msgid
	integer*4 thk, lin, rad, colr, sym
	real*8 dval, d
	character*3 fac /'BPA'/

	do while (.not. Mx.breakflag)

	  if (M$GET_MSG(MQH,MQD,L_mqd,0.0,0).le.0) return

	  Gx.status = Gx.status + 1
	  info = MQH.info
	  sid = MQH.sender
	  msgid = Gx.xf.msgid
	  mimic = Gx.mimic

	  Gx.xf.iarg = MQH.info
	  Gx.xf.mqdloc.p = %loc(MQD)

	  ! Do not echo actions to an id who CAUSED it unless MSK_ECHO is set
	  if (.not. BTEST(Gx.xf.msgmask,MSK_ECHO)) then
	    if (msgid.gt.0 .and. msgid.eq.sid) Gx.xf.msgid = -1
	    if (mimic.gt.0 .and. mimic.eq.sid) Gx.mimic = -1
	  endif

	  if (MX$MIMIC_MSG(MQH,MQD,mimic).lt.0) then
	    ! info message but not from who we're mimicing

	  elseif (MX$GRAPHICS_MSG(Mx,MQH,MQD,msgid,Gx.xf.msgmask).ne.0) then
	    if (Mx.breakflag) return ! so echo works, do not reset msgid

	  elseif (MQH.name .eq. MQH_QUERY.name) then
	    Gx.xf.msgid = msgid
            if (MQD.QUERY.object .eq. MQH_BOXINFO.name) then
              call XRTPLOT_INFOMSG (Mx, Gx, MSK_BOXES, info, sid)
	    elseif (MQD.QUERY.object .eq. MQH_COLORINFO.name) then
	      call XRTPLOT_INFOMSG (Mx, Gx, MSK_COLOR, info, sid)
	    elseif (MQD.QUERY.object .eq. MQH_CXMODEINFO.name) then
	      call XRTPLOT_INFOMSG (Mx, Gx, MSK_CXMODE, info+1, sid)
	    elseif (MQD.QUERY.object .eq. MQH_MARKINFO.name) then
	      call XRTPLOT_INFOMSG (Mx, Gx, MSK_MARK, info, sid)
	    elseif (MQD.QUERY.object .eq. MQH_PANINFO.name) then
	      call XRTPLOT_INFOMSG (Mx, Gx, MSK_PANX, info+1, sid)
	    elseif (MQD.QUERY.object .eq. MQH_PLOTINFO.name) then
	      call XRTPLOT_INFOMSG (Mx, Gx, -1, info+1, sid) 
            elseif (MQD.QUERY.object .eq. MQH_POINTINFO.name) then
              call XRTPLOT_INFOMSG (MSK_POINTS, info, sid)
	    elseif (MQD.QUERY.object .eq. MQH_ZOOMINFO.name) then 
	      call XRTPLOT_INFOMSG (Mx, Gx, MSK_ZOOM, info+1, sid)
	    endif

	  elseif (MQH.name .eq. MQH_ANNOTATE.name) then
	    call XRTPLOT_XF(Mx, Gx, 'A', 3)

	  elseif (MQH.name(1:3).eq.'BOX' .or. MQH.name(1:5).eq.'POINT') then
	    if (MQH.name .eq. MQH_BOXDELETE.name .or.
     &		MQH.name .eq. MQH_POINTDELETE.name) then
	      call XRTPLOT_XF(Mx, Gx, MQH.name(1:1), 4)
	    elseif (MQH.name .eq. MQH_BOXADD.name .or.
     &		    MQH.name .eq. MQH_POINTADD.name .or.
     &		    MQH.name .eq. MQH_BOXALTER.name .or.
     &		    MQH.name .eq. MQH_POINTALTER.name) then
	      if (MQH.info .le. -1) then
		call XRTPLOT_XF(Mx, Gx, MQH.name(1:1), L_OneShot)
	      elseif (MQH.name .eq. MQH_BOXADD.name) then
		Gx.xf.iarg = Gx.xf.nbox+1
		call XRTPLOT_XF(Mx, Gx, MQH.name(1:1), 2)
	      elseif (MQH.name .eq. MQH_POINTADD.name) then
		Gx.xf.iarg = Gx.xf.npoint+1
		call XRTPLOT_XF(Mx, Gx, MQH.name(1:1), 2)
	      else
		call XRTPLOT_XF(Mx, Gx, MQH.name(1:1), 2)
	      endif
	    endif

	  elseif (MQH.name .eq. MQH_COLOR.name) then
	    if (info.lt.0) info = max (0, Gx.lps+info+1)
	    if (info .ge. 1 .and. info .le. Gx.lps) then
	      i = MQD.COLOR.position
	      if (i .ge. 0) then
		call MX$COLORTAB (info, Mc.colormap(4), i)
	      else
		call MX$COLORTAB (info, MQD.COLOR, -2)
	      endif
	      call XRTPLOT_MSGDO (Mx, Gx, MSK_COLOR, info)
	    endif

	  elseif (MQH.name .eq. MQH_CXMODE.name) then
	    i = (M$SEARCH('MA;PH;RE;IM;IR;LO;L2;D1;D2',
     +		MQD.CXMODE.mode(1:2))+2)/3
	    if (i.ne.0 .and. i.ne.Gx.cmode) call XRTPLOT_CMODE(Mx, Gx, i)

	  elseif (MQH.name .eq. MQH_HARDCOPY.name) then

	    if (MX$HARDCOPY_OPEN(MQD.HARDCOPY.file, info)) then
	      call XRTPLOT_REFRESH (Mx,Gx)
	      call MX$HARDCOPY_CLOSE ()
	    endif

	  elseif (MQH.name .eq. MQH_MARK.name) then
	    Gx.xmrk = MQD.MARK.x
	    Gx.ymrk = MQD.MARK.y
	    if (Gx.cntrls.gt.0) then
	      call M$DRSLT (Mx.xtag, Gx.xmrk)
	      call M$DRSLT (Mx.ytag, Gx.ymrk)
	    endif
	    call XRTPLOT_SPECS (Mx,Gx)
	    call XRTPLOT_MSGDO (Mx, Gx, MSK_MARK, Mx.level)

	  elseif (MQH.name .eq. MQH_NEWFILE.name) then
	    i = MQD.NEWFILE.arg1
	    if (i.ge.1 .and. i.le.3) call XRTPLOT_XF(Mx, Gx, fac(i:i), 6)

	  elseif (MQH.name .eq. MQH_OVERLAY.name) then

	    if (Mx.resize) call XRTPLOT_REFRESH (Mx,Gx)

	  elseif (MQH.name .eq. MQH_PAN.name) then
	    xpan = MQD.PAN.xmin .lt. MQD.PAN.xmax
	    if (xpan) then
	      Mx.stk(Mx.level).xmin = MQD.PAN.xmin
	      Mx.stk(Mx.level).xmax = MQD.PAN.xmax
	    endif
	    ypan = MQD.PAN.ymin .lt. MQD.PAN.ymax
	    if (ypan) then
	      if (Gx.yinv) then
		Mx.stk(Mx.level).ymin = MQD.PAN.ymax
		Mx.stk(Mx.level).ymax = MQD.PAN.ymin
	      else
		Mx.stk(Mx.level).ymin = MQD.PAN.ymin
		Mx.stk(Mx.level).ymax = MQD.PAN.ymax
	      endif
	    endif
	    if (xpan .or. ypan) then
	      if (xpan) call XRTPLOT_MSGDO (Mx, Gx, MSK_PANX, Mx.level)
	      if (.not. xpan) call XRTPLOT_MSGDO (Mx, Gx, MSK_PANY, Mx.level)
	      call XRTPLOT_REFRESH (Mx,Gx)
	    endif

	  elseif (MQH.name .eq. MQH_PANRANGE.name) then
	    if (MQD.PANRANGE.xmin .lt. MQD.PANRANGE.xmax) then 
	      Gx.xmin = MQD.PANRANGE.xmin
	      Gx.xmax = MQD.PANRANGE.xmax
	      Mx.stk(1).xmin = Gx.xmin
	      Mx.stk(1).xmax = Gx.xmax
	    endif
	    if (MQD.PANRANGE.ymin .lt. MQD.PANRANGE.ymax) then
	      Gx.ymin = MQD.PANRANGE.ymin
	      Gx.ymax = MQD.PANRANGE.ymax
	      Gx.rmin0 = Gx.ymin
	      Gx.rmax0 = Gx.ymax
	      if (Gx.yinv) then
		Mx.stk(1).ymin = Gx.ymin
		Mx.stk(1).ymax = Gx.ymax
	      else
		Mx.stk(1).ymin = Gx.ymax
		Mx.stk(1).ymax = Gx.ymin
	      endif
	      Gx.iautom = 0
	    endif
	    if (Mx.level.eq.1) call XRTPLOT_REFRESH (Mx,Gx)
	    if (Mx.level.gt.1) i = XRTPLOT_PAN_HANDLE (Mx,Gx,0,i)

	  elseif (MQH.name .eq. MQH_REFRESH.name) then
	    Gx.hold = 0
	    call XRTPLOT_REFRESH (Mx,Gx)

	  elseif (MQH.name .eq. MQH_REREAD.name) then
	    call XRTPLOT_RESET (Mx,Gx)
	    call XRTPLOT_REFRESH (Mx,Gx)

	  elseif (MQH.name .eq. MQH_SET.name .or.
     +		  MQH.name .eq. MQH_SETD.name) then
	    dval = info
	    if (MQH.name .eq. MQH_SETD.name) dval = MQD.SETD.value
	    info = dval
	    i = (M$SEARCH('AUTO    ,AUTOL   ,CLEAR   ,CONTROLS,EDGE    ,'//
     +			  'EVENTS  ,FAST    ,GRID    ,MARKMODE,MARKSIZE,'//
     +			  'MIMIC   ,MSGID   ,SPECS   ,WRAP    ,XDIV    ,'//
     +			  'XLABEL  ,YDIV    ,YINV    ,YLABEL  ,',
     +				MQD.SET.object(1:8)//',') + 8) / 9

	    if (i.ne.0) then
	      if (i.eq.t_mimic) then
		mimic = info
	      elseif (i.eq.t_msgid) then
		msgid = info
	      else
		call XRTPLOT_SETTINGS (Mx, Gx, i, info)
	      endif
	    ! for backwards compatibility, the case below was advertised
	    ! for 3.30 release; it does not match the switch name or
	    ! other plotters' name for this setting.
	    elseif (MQD.SET.object .eq. 'AUTOM') then
	      call XRTPLOT_SETTINGS (Mx, Gx, t_auto, info)
	    elseif (MQD.SET.object .eq. 'HOLD') then
	      Gx.hold = info
	      Mx.exposure = .true.
	    elseif (MQD.SET.object(1:3) .eq. 'BOX' .or.
     +		    MQD.SET.object(1:5) .eq. 'POINT' .or.
     +		    MQD.SET.object(1:4) .eq. 'ANNT') then
	      call XRTPLOT_XF(Mx, Gx, MQD.SET.object(1:1), 5)
	    else
	      Mx.exposure = .true.
	      if (MQD.SETD.object .eq. 'FRAME') then
		d = Gx.mframe
		call XRTPLOT_REFRAME (Mx,Gx,NINT(dval),MQH.info)
	      elseif (MQD.SETD.object .eq. 'SCALEMIN') then
		Gx.ymin = dval
		Gx.rmin0 = Gx.ymin
		Mx.resize = .true.
	      elseif (MQD.SETD.object .eq. 'SCALEMAX') then
		Gx.ymax = dval
		Gx.rmax0 = Gx.ymax
		Mx.resize = .true.
	      elseif (MQD.SETD.object .eq. 'XSTART') then
		if (MQH.info.eq.1)
     +			call XRTPLOT_WARPRANGE(Mx, Gx, 1.d0, dval-Gx.xstart)
		Gx.xstart = dval
		Gx.pass = 0
	      elseif (MQD.SETD.object .eq. 'XDELTA') then
		if (Gx.xdelta.ne.dval .and. dval.ne.0.d0) then
		  if (MQH.info.eq.1) 
     +			call XRTPLOT_WARPRANGE(Mx, Gx, dval/Gx.xdelta, 0.d0)
		  Gx.xdelta = dval
	        endif
	      elseif (MQD.SETD.object .eq. 'XMIN') then
		Gx.xmin = dval
		Mx.stk(1).xmin = Gx.xmin
	      elseif (MQD.SETD.object .eq. 'XMAX') then
		Gx.xmax = dval
		Mx.stk(1).xmax = Gx.xmax
	      elseif (MQD.SETD.object .eq. 'YMIN') then
		Mx.stk(1).ymin = dval
	      elseif (MQD.SETD.object .eq. 'YMAX') then
		Mx.stk(1).ymax = dval
	      else
		Mx.exposure = .false.
	      endif
	    endif

	    if (Mx.resize)   call XRTPLOT_RESET (Mx,Gx)
	    if (Mx.exposure) call XRTPLOT_REFRESH (Mx,Gx)

	  elseif (MQH.name .eq. MQH_TRACE.name) then
	    lin = Gx.trace
	    thk = Gx.thick
	    sym = Gx.symbol
	    rad = Gx.radius
	    colr = 0
	    call MX$TRACE_MSG(MQD.TRACE, lin, thk, sym, rad, colr)

            if (lin.ne.Gx.trace .or. thk.ne.Gx.thick .or.
     &		sym.ne.Gx.symbol .or. rad.ne.Gx.radius) then
	      Gx.trace = lin
	      Gx.thick = thk
	      Gx.symbol = sym
	      Gx.radius = rad
	      call MX$DRAW_MODE(Gx.thick)
	      call XRTPLOT_REFRESH(Mx,Gx)
	    endif

	  elseif (MQH.name .eq. MQH_UNZOOM.name) then
	    if (Mx.level.gt.1 .and. info.lt.Mx.level-1) then
	      if (info .ge. 0) Mx.level = info + 1
	      if (info .lt. 0) Mx.level = max (1, Mx.level+info)
	      call XRTPLOT_MSGDO (Mx, Gx, MSK_UNZOOM, Mx.level)
	      call XRTPLOT_REFRESH (Mx, Gx)
	    endif

	  elseif (MQH.name .eq. MQH_ZOOM.name) then
	    if (Mx.level.lt.L_stack) then
	      i = Mx.level + 1
	      if (MQD.ZOOM.xmin .lt. MQD.ZOOM.xmax) then
		Mx.stk(i).xmin = MQD.ZOOM.xmin
		Mx.stk(i).xmax = MQD.ZOOM.xmax
	      else
		Mx.stk(i).xmin = Mx.stk(Mx.level).xmin
		Mx.stk(i).xmax = Mx.stk(Mx.level).xmax
	      endif
	      if (MQD.ZOOM.ymin .lt. MQD.ZOOM.ymax) then
		if (Gx.yinv) then
		  Mx.stk(i).ymin = MQD.ZOOM.ymax
		  Mx.stk(i).ymax = MQD.ZOOM.ymin
		else
		  Mx.stk(i).ymin = MQD.ZOOM.ymin
		  Mx.stk(i).ymax = MQD.ZOOM.ymax
		endif
	      else
		Mx.stk(i).ymin = Mx.stk(Mx.level).ymin
		Mx.stk(i).ymax = Mx.stk(Mx.level).ymax
	      endif
	      Mx.level = i
	      call XRTPLOT_MSGDO (Mx, Gx, MSK_ZOOM, Mx.level)
	      call XRTPLOT_REFRESH (Mx,Gx)
	    endif

	  elseif (MQH.name .eq. MQH_XTODO.name) then
	    Mu.todo = NINT(MQD.XTODO.amount)

	  endif

	  Gx.xf.msgid = msgid
	  Gx.mimic = mimic

	  if (Mu.todo .gt. 0) then
	    Gx.hold = min(Gx.hold,1)		!<<< we're in queued mode and
	    return				!<<< just got an XTODO
	  endif

	enddo

	return
	end

	subroutine XRTPLOT_PLOT (Mx, Gx, new_data)
	include 'xrtplot.inc'
	real*4	ftop,fyscale,fleft,fxscale,qmin,qmax,fac,rtol,fmax,dbscale
	integer*4 n,n1,n2,nvis,k,i,ii,jj,lc,ic,ix,iy,i1,i2,if1,ib,ixx,iyy
	integer*4 lines, x1, x2, y1, y2, rad, imax, xlab, ylab, c1, c2
	integer*4 new_data, dpass, thk, isk
	logical*4 clear, clear_partial, new_tics, bp_drawn, erase_bp, draw_bp
	integer*4 idbmagindex
#if _EEEI
	parameter (idbmagindex=2)	! exponent in last 2 bytes
#else
	parameter (idbmagindex=1)	! exponent in first 2 bytes
#endif
	record /PIXSTRUCT/ pix(1)
	real*4 fbuf(1)
	integer*2 ibuf(1)
	pointer (ibuf_addr, ibuf)
	pointer (fbuf_addr, fbuf)
	pointer (pix_addr, pix)
c
	bp_drawn = .false.
	if (Mx.icon) return
	if (Gx.nelem .le. 0) goto 99

	fbuf_addr = Gx.lbuf.p
	pix_addr = Gx.lpix.p
c
c remove mark
	if (Gx.markp.x .ne. -1) then
	  call MX$DRAW_DOTS(L_XORColor, Gx.markp, 1, Gx.marks)
	  Gx.markp.x = -1
	endif
c
c Update Gx.pass if we're plotting new data into new frame(s)
c If specs are not wrapping, decide if we need to update the X axis tic marks.
	if (Gx.lps.eq.1 .or. Gx.class.gt.2) then
	  lc = Gx.lps
	else
	  lc = INT((Gx.nelem-1)/Gx.mframe) + 1 ! current line in lps
	endif

	xlab = -2		! flag to MX$DRAWAXIS: draw tics only
	ylab = -3
	new_tics = .false.
	clear = (new_data.eq.0)	! flag indicating the plotting field is clear
	if (new_data.gt.0) then
	  dpass = 0
	  if (.not.Gx.clear .and. Gx.lps.gt.1 .and. Gx.class.eq.1) then
	    if (Gx.loff.eq.0) then
	      dpass = lc
	      if (Gx.pass.eq.0) then
		Gx.pass = 1
		dpass = dpass - 1
	      endif
	    elseif (Gx.class.gt.2) then
	      dpass = lc
	    elseif (lc.gt.1) then
	      dpass = lc - (INT((Gx.loff-1)/Gx.mframe) + 1)
	    endif
	  elseif (Gx.pass.eq.0) then
	    Gx.pass = 1
	  elseif (Gx.loff.eq.0) then
	    dpass = 1
	  endif

	  if (dpass.ne.0) then
	    call XRTPLOT_PASS(Mx, Gx, Gx.pass+dpass, dpass, 1)
	    if (Gx.nowrap .and. Gx.cmode.ne.5) then
	      if (Gx.specs) then
		xlab = -1	! redraw x tic labels
		ylab = -1	! redraw y tic labels (we might clear them)
		new_tics = .true.
	      elseif (Gx.grid) then
		new_tics = .true.	! in case the grid lines move
	      endif
	    endif
	  endif
        endif

c
c autoscale ?
	if (Gx.cmode.ge.6) then
	  dbscale = 10.
	  if (Gx.cmode.eq.7) dbscale = 20.
	  if (Gx.cx) dbscale = dbscale / 2.0
	endif

	if (Gx.iautom.ge.1 .and. Gx.iautom.le.3 .and. Gx.cmode.ne.2) then
	  if (Gx.loff.eq.0) then
	    fac = 1./float(max(Gx.iautol,1))
	    call M$VMXMN(fbuf, qmax, qmin, i1, i2, Gx.nelem)
	    if (Gx.iautom.ge.2) then			! Auto Max, Auto Full
	      if (Gx.cmode.ge.6) then
		if (Gx.fast) qmax = log10(qmax)
		qmax = qmax * dbscale
	      endif
	      Gx.rmax = qmax*fac + Gx.rmax*(1.-fac)
	    endif
	    if (Gx.iautom.ne.2) then			! Auto Min, Auto Full
	      if (Gx.cmode.ge.6) then
		if (Gx.dbrange.gt.0) then
		  qmin = Gx.rmax - Gx.dbrange
		  Gx.rmin = qmin
		else
		  if (Gx.fast) qmin = log10(qmin)
		  qmin = qmin * dbscale
		endif
	      endif
	      Gx.rmin = qmin*fac + Gx.rmin*(1.-fac)
	    endif
	    if (Gx.rmin .ge. Gx.rmax) then
	      if (Gx.iautom.eq.1) Gx.rmin = Gx.rmax - 1.0
	      if (Gx.iautom.eq.2) Gx.rmax = Gx.rmin + 1.0
	    endif
	  endif
c
c apply autoscaling
	  rtol = (Gx.rmax-Gx.rmin)*.1
	  if (Gx.cmode.eq.2) then
	  elseif (Gx.iautol.eq.0 .or. 
     +	      Gx.rmax.gt.Gx.rmax0 .or. Gx.rmax.lt.Gx.rmax0-rtol .or.
     +	      Gx.rmin.lt.Gx.rmin0 .or. Gx.rmin.gt.Gx.rmin0+rtol ) then
	    Gx.rmin0 = Gx.rmin - rtol/2
	    Gx.rmax0 = Gx.rmax + rtol/2
	    if (Mx.level.eq.1) then
	      ii = Gx.nelem
	      jj = Gx.nxf
	      Gx.nelem = 0  ! no data yet
	      Gx.nxf = 0    ! don't draw facilities yet
	      call XRTPLOT_RESET (Mx,Gx)
	      call XRTPLOT_REFRESH (Mx,Gx)
	      Gx.nelem = ii
	      Gx.nxf = jj
	      clear = .true.
	      new_tics = .false.
	    endif
	  endif
	endif
c
c get scaling constants
	k = Mx.level
	x1 = Mx.stk(k).x1
	x2 = Mx.stk(k).x2
	y1 = Mx.stk(k).y1
	y2 = Mx.stk(k).y2

	ftop = Mx.stk(k).ymax + y1*Mx.stk(k).yscl
	fleft = Mx.stk(k).xmin - x1*Mx.stk(k).xscl
	fyscale = 1.
	if (Mx.stk(k).yscl.ne.0.) fyscale = 1./Mx.stk(k).yscl
	fxscale = 1.
	if (Mx.stk(k).xscl.ne.0.) fxscale = 1./Mx.stk(k).xscl
	if (Gx.cmode.ge.6) then
	  ftop = ftop / dbscale
	  fyscale = fyscale * dbscale
	  ! Exponent bits being read from first 16 bytes of non-logged
	  ! floats.  These 2 byte integer values are on a different scale
	  ! and must be converted back, hence the funky calculations below.
	  if (Gx.fast) then
	    ftop = (ftop*425.0) + 16248.0
	    fyscale = fyscale / 425.0
	  endif
	endif

c
c clear data display area ?
	! If not previously cleared, do we need to clear it ?
	if (.not. clear) then
	  if (Gx.nowrap) then
	    if (new_tics) then ! clear top and bottom tic marks and X tic labels
	      clear = Gx.grid  ! if the grid is on, we need to clear the field
	      if (Gx.specs) then
		if (Gx.grid) then
		  ! clear the X tic labels only
		  call MX$CLEAR_AREA(0, y2+3, Mx.width, Mx.height-y2-3)
		else 
		  ! clear the X tic labels and the X tic marks
		  call MX$CLEAR_AREA(x1, y1-4, x2-x1, 4)
		  call MX$CLEAR_AREA(0, y2, Mx.width, Mx.height-y2)
		endif
	        call XRTPLOT_SPECS(Mx, Gx)
	      endif
	    endif
	  endif
	  ! adjust xlab flag for timecode tic separation
	  if (Gx.xlab.eq.4 .and. Gx.cmode.ne.5) xlab = xlab - 2

c
c If we're not displaying the first pass of data, decide if we need to clear
c the plotting field
	  if (Gx.nelem.le.Gx.melem) then
	    ! in clear mode, clear window at start of new buffer
	    if (Gx.clear) then
	      if (Gx.loff.eq.0) then
		clear = .true.
		Gx.melem = 0
	      endif
	    elseif (clear .or. Gx.class.gt.2) then
	    ! in non-clear mode, only if > 1 lps and drawing a different frame
	    elseif (Gx.lps.gt.1) then
	      clear = (dpass.gt.0)
	    ! in IR mode with Gx.lps=1 we cannot do partial clears
	    elseif (Gx.loff.eq.0) then
	      clear = (Gx.nelem.ge.Gx.j2 .or. Gx.cmode.eq.5)
	      if (Gx.cmode.eq.5) Gx.melem = 0
	    endif
	  endif

c	  if (Gx.nxf .gt. 0) call MX$FACILITIES(Gx.xf, 'A', -2)
	  if (clear) then
	    call MX$CLEAR_AREA (x1, y1, x2-x1+1, y2-y1+1)
	    if (Gx.grid) then
	      call MX$DRAWAXIS(Gx.xdiv,Gx.ydiv,xlab,ylab,.true.)
	      new_tics = .false.
	    endif
	    Gx.e1 = x1
	  elseif (Gx.nxf .gt. 0) then
	    bp_drawn = .true.
	  endif

	endif

c
c compute range of points to plot
	if (Gx.cmode.ne.5) then		! plot between visible endpoints
	  n1 = Gx.j1
	  n2 = Gx.j2
	else				! RI mode exception, plot all points
	  n1 = 1
	  n2 = Gx.mframe
	endif
c
c draw the data
	rad = Gx.radius
	thk = Gx.thick
	if (Gx.thick.eq.1) thk = 0
	lines = 0
	lc = lc + 1  ! offset loop so current line will be drawn last
	do while (lines.lt.Gx.lps)

	  lines = lines + 1
	  if (lc.gt.Gx.lps) lc = 1
	  if (Gx.class.le.2) then
	    ib = (lc-1)*Gx.mframe
	    i1 = ib + n1
	    i2 = ib + n2
	    isk = 1
	    nvis = Gx.nelem
	  else
	    i1 = (n1-1)*Gx.lps + lc
	    i2 = (n2-1)*Gx.lps + lc
	    isk = Gx.lps
	    nvis = Gx.nelem / isk
	  endif
	  ic = mod(lc-1, max(1,Gx.ncolors)) + 1

	  if (clear) then 	! plot entire frame
	    if ((Gx.cmode.ne.5 .and. Gx.lps.le.1) 
     &		.or. lines.ne.Gx.lps .or. Gx.class.gt.2)
     &	      nvis = max(Gx.melem,Gx.nelem)/isk
	    clear_partial = .false.
	  elseif (i2.lt.Gx.loff) then		! data already drawn - no draw
	    nvis = 0
	  elseif (Gx.class.gt.2) then		! plot only new data
	    n = max(n1,Gx.loff/Gx.lps)
	    i1 = (n-1)*Gx.lps + lc
	    ! clear partial field only if 1st pass
	    clear_partial = (lc.eq.1 .and. Gx.nelem.le.Gx.melem)
	  else					! plot only new data
	    i1 = max (Gx.loff, i1)
	    ! clear partial field if only 1 line and > 1st pass
	    clear_partial = (Gx.lps.le.1 .and. Gx.nelem.le.Gx.melem)
	  endif
	  if (Gx.class.le.2) then
	    nvis = min(i2,nvis) - i1 + 1
	  else
	    nvis = (min(i2,nvis*Gx.lps) - i1)/Gx.lps + 1
	  endif
	  if (nvis.gt.0) then
	    erase_bp = bp_drawn		! init flags indicating whether we
	    draw_bp = bp_drawn		! need to erase & redraw points/boxes
	    if (Gx.class.le.2) then
	      n = i1 - ib
	      i2 = i1 + nvis - 1	! save starting ending index for later
	    else
	      n = (i1-lc)/Gx.lps + 1
	      i2 = i1 + (nvis-1)*Gx.lps	! save starting ending index for later
	    endif
	    if (Gx.cmode .eq. 5) then
	      if1 = i1+i1-1
	      do i = n,n+nvis-1
		ii = (fbuf(if1)-fleft)*fxscale
		pix(i).x = max(-32768,min(32767,ii))
		ii = (ftop-fbuf(if1+1))*fyscale
		pix(i).y = max(-32768,min(32767,ii))
		if1 = if1+isk+isk
	      enddo
	    else
	      if (Gx.cmode.gt.5 .and. Gx.fast) then
		if1 = 2*(i1-1) + idbmagindex
		ibuf_addr = %loc(fbuf)
		do i = n,n+nvis-1
		  ii = (ftop-ibuf(if1))*fyscale
		  pix(i).y = max(-32768,min(32767,ii))
		  if1 = if1+isk+isk
		enddo
	      else
		if1 = i1
		do i = n,n+nvis-1
		  ii = (ftop-fbuf(if1))*fyscale
		  pix(i).y = max(-32768,min(32767,ii))
		  if1 = if1+isk
		enddo
	      endif
c
c	Erase edge line and clear area just ahead of the edge line for the next 
c	draw if necessary.  If the grid is toggled on then it's necessary to 
c	redraw the portion of the grid that is located within that area.
c
	      if (Gx.edge .and. Gx.e1.gt.x1 .and. Gx.e1.lt.x2) 
     &		call MX$DRAW_LINE (-2, Gx.e1, y1, Gx.e1, y2)

	      if (clear_partial .or. bp_drawn) then
		c1 = pix(n).x		! c1 = where to start clearing
		c1 = max(c1,Gx.e1)
		c2 = pix(n+nvis-1).x	! c2 = where to stop clearing
		if (Gx.symbol.gt.0) then
		  c1 = c1 + rad
		  c2 = c2 + rad
		  if (Gx.loff.le.ib+n1) c1 = x1	! 1st pt, clear from far left
		endif
		c1 = max(x1,c1)
		c2 = min(x2,c2)
		if (c2.lt.c1) then
		  erase_bp = .false.
		  draw_bp = .false.
		else
		  if (clear_partial) then
		    call MX$CLEAR_AREA (c1, y1, c2-c1+1, y2-y1+1)
		    if (Gx.grid) then
		      call MX$DRAWAXIS(Gx.xdiv,Gx.ydiv,xlab,ylab,.true.)
		      new_tics = .false.
		    endif
		    erase_bp = .false.
		  endif
		  if (bp_drawn) then
		    Gx.xf.clip = .true.
		    Gx.xf.x1 = c1
		    Gx.xf.x2 = c2
		    Gx.xf.y1 = y1
		    Gx.xf.y2 = y2
		  endif
		endif
	      endif
	    endif

	    if (erase_bp) call MX$FACILITIES(Gx.xf, 'PB', L_Draw)

	    if (Gx.trace.eq.3) then		! draw connecting lines
	      if (i1.le.Gx.nelem .and. i2.gt.Gx.nelem) then
		i = (Gx.nelem-i1)/isk + 1
		call MX$DRAW_LINES (ic, pix(n), i)
		call MX$DRAW_LINES (ic, pix(n+i), nvis-i)
		if (Gx.symbol.le.0) nvis = i
	      else
	        call MX$DRAW_LINES (ic, pix(n), nvis)
	      endif
	    elseif (Gx.trace.eq.1) then	! draw verticals
	      do i = n,n+nvis-1
		ix = pix(i).x
		call MX$DRAW_LINE (ic,ix,y1,ix,y2)
	      enddo
	    elseif (Gx.trace.eq.2) then	! draw horizontals
	      do i = n,n+nvis-1
		iy = pix(i).y
		call MX$DRAW_LINE (ic,x1,iy,x2,iy)
	      enddo
	    elseif (Gx.trace.eq.4) then	! draw vertical bars
	      do i = n,n+nvis-1
		ix = pix(i).x
		iy = pix(i).y
		call MX$DRAW_LINE (ic,ix,iy,ix,y2)
	      enddo
	    elseif (Gx.trace.eq.5) then	! square wave
	      ix  = pix(n).x
	      iy  = pix(n).y
	      do i = n+1,n+nvis-1
		ixx = pix(i).x
		iyy = pix(i).y
		call MX$DRAW_LINE (ic,ix,iy,ixx,iy)
		call MX$DRAW_LINE (ic,ixx,iy,ixx,iyy)
		ix = ixx
		iy = iyy
	      enddo
	    endif
	    if (Gx.symbol.gt.0) then		! draw dots
	      if (rad.ne.0 .and. i1.le.Gx.nelem .and. i2.gt.Gx.nelem) then
		i = (Gx.nelem-i1)/isk + 1
		call MX$DRAW_SYMBOLS(ic, pix(n), i, Gx.symbol, Gx.radius)
		ix = pix(n+i-1).x + rad + 1
		call MX$CLIP (ix, y1, x2-ix+1, y2-y1+1)
		call MX$DRAW_SYMBOLS(ic,pix(n+i),nvis-i,Gx.symbol,Gx.radius)
		call MX$CLIP (x1, y1, x2-x1+1, y2-y1+1)
		nvis = i
	      else
		call MX$DRAW_SYMBOLS(ic, pix(n), nvis, Gx.symbol, Gx.radius)
	      endif
	    endif

	    if (draw_bp) then
	      call MX$FACILITIES(Gx.xf, 'PB', L_Draw)
	      Gx.xf.clip = .false.
	    endif

	    if (Gx.cmode.ne.5) then
	      Gx.e1 = x1
	      i = n + nvis - 1
	      if (i.lt.Gx.mframe .and. pix(i).x.lt.x2-1) then
		Gx.e1 = pix(i).x + 1
		if (Gx.edge .and. Gx.e1.gt.x1)
     &			call MX$DRAW_LINE (-2, Gx.e1, y1, Gx.e1, y2)
	      endif
	      if (Gx.nowrap .and. .not. (Gx.clear .or. clear) .and. Gx.specs
     +		  .and. Mx.xpos.gt.pix(n).x .and. Mx.xpos.le.pix(i).x)
     +		  call XRTPLOT_SPECS(Mx,Gx)
	    endif
	  endif

	  if (Gx.markm.ne.0 .and. lines.eq.1) then
	   if (Gx.markm .gt. 0) then
	    imax = Gx.markm
	   elseif (Gx.markm .eq. -2) then
	    imax = NINT((Gx.xmrk-Gx.xstart)/Gx.xdelta) + 1
	    imax = max(1,min(Gx.mframe,imax))
	   else
	    ii=0
	    if (pix(n).x .lt. x1) ii=1
	    jj=0
	    if (pix(n+nvis-1).x .gt. x2) jj=1
	    if1 = i1+ii
	    imax = n+ii
	    fmax = fbuf(if1)
	    do i = n+ii,n+nvis-jj-1
	      if (fbuf(if1).gt.fmax) then
		fmax = fbuf(if1)
		imax = i
	      endif
	      if1 = if1+1
	    enddo
	   endif
	   Gx.markp = pix(imax)
c+++
c DR 5446
c Old
c	   call MX$DRAW_DOTS(L_XORColor, Gx.markp, 1, Gx.marks)
c New
c          Check if Mark is in view before plotting erf
	   if (Gx.markm .lt. 0 .or.
     &         (Gx.markm .ge. i1 .and. Gx.markm .le. i2)) then
	     call MX$DRAW_DOTS(L_XORColor, Gx.markp, 1, Gx.marks)
	   endif
c---
	  endif

	  lc = lc + 1

	enddo

	! if in the course of drawing new data MX$DRAWAXIS was never called
	! and we need to update the X axis tic labels, do it now.
	if (new_tics) call MX$DRAWAXIS(Gx.xdiv,Gx.ydiv,xlab,ylab,.false.)
	Gx.melem = max (Gx.nelem, Gx.melem)
c
c draw facilities
  99	if (Gx.nxf .gt. 0) then
	  if (.not. bp_drawn) call MX$FACILITIES(Gx.xf, 'PB', L_Draw)
	  call MX$FACILITIES(Gx.xf, 'A', L_Draw)
	endif

	return
	end

	subroutine XRTPLOT_SPECS (Mx,Gx)
	include 'xrtplot.inc'
	character chara*47, charb*47
	character*2 cxm(7) /'Ma','Ph','Re','Im','RI','Lo','L2'/
	character*6 cam(0:3) /'(absc)', '(indx)', '(1/ab)', '(dydx)'/
	integer*4 ix,iy,k,ls
c
c valid range check (none)
	ix = Mx.xpos
	iy = Mx.ypos
c
c adjust/scale for segments and Y inversion
	k = Mx.level
	Gx.retx = Mx.stk(k).xmin + (ix-Mx.stk(k).x1)*Mx.stk(k).xscl
	Gx.rety = Mx.stk(k).ymin + (Mx.stk(k).y2-iy)*Mx.stk(k).yscl
c
c adjust for wrap mode
	if (Gx.nowrap .and. Gx.pass.gt.1 .and. .not.Gx.clear) then
	  if (Gx.nelem.gt.0) then
	    ix = NINT((Gx.retx-Gx.xstart)/Gx.xdelta)
	    if (ix .gt. mod(Gx.nelem-1,Gx.mframe)) 
     +	      Gx.retx = Gx.retx - Gx.mframe*Gx.xdelta
	  endif
	endif
c
c adjust for abscissa mode
	Gx.aretx = Gx.retx
	Gx.arety = Gx.rety
	Gx.dretx = Gx.retx-Gx.xmrk
	Gx.drety = Gx.rety-Gx.ymrk

	if (Gx.iabsc.eq.1 .and. Gx.cmode.eq.5) Gx.iabsc = 2
	if (Gx.iabsc.eq.1) then					! index
	  Gx.aretx = NINT((Gx.aretx-Gx.xstart)/Gx.xdelta) + 1
	  if (Gx.nowrap .and. Gx.pass.gt.1) then
	    Gx.aretx = Gx.aretx + (Gx.pass-1) * Gx.mframe
	  endif
	  Gx.dretx = NINT(Gx.dretx/Gx.xdelta)
	elseif (Gx.iabsc.eq.2) then				! 1/absc
	  if (Gx.aretx.ne.0.d0) Gx.aretx = 1/Gx.aretx
	  if (Gx.arety.ne.0.d0) Gx.arety = 1/Gx.arety
	  if (Gx.dretx.ne.0.d0) Gx.dretx = 1/Gx.dretx
	  if (Gx.drety.ne.0.d0) Gx.drety = 1/Gx.drety
	endif
c
c  display updated specs
	if ( .not. Gx.specs) return
	write(chara, 1001) Gx.arety, Gx.drety, Mx.level-1, cxm(Gx.cmode)
 1001	format('y: ', 1p1g16.9, ' dy: ', g16.9, ' L=', i1, a3)
	write(charb, 1002) Gx.aretx, Gx.dretx, cam(Gx.iabsc)
 1002	format('x: ', 1p1g16.9, ' dx: ', g16.9, ' ', a6)
	if (Gx.iabsc.eq.3) then
	  if (Gx.dretx.ne.0.d0) then
	    write(chara(21:40), '(4hsl: , g16.9)') Gx.drety/Gx.dretx
	  else
	    chara(21:40) = 'sl: Inf'
	  endif
	endif
	if (Gx.iabsc.eq.0 .and. Gx.yfmt.ne.' ') then
	  ls = M$D2A_FORM (Gx.arety, chara( 4:19), Gx.yfmt)
	  ls = M$D2A_FORM (Gx.drety, chara(25:40), Gx.yfmt)
	elseif (Gx.iabsc.eq.0 .and. Gx.iylab.eq.4) then
          ls = M$SEC2TSPEC(Gx.arety, chara( 4:19), 0)
          ls = M$SEC2TSPEC(Gx.drety, chara(25:40), 1)
	endif
	if (Gx.iabsc.eq.0 .and. Gx.xfmt.ne.' ') then
	  ls = M$D2A_FORM (Gx.aretx, charb( 4:19), Gx.xfmt)
	  ls = M$D2A_FORM (Gx.dretx, charb(25:40), Gx.xfmt)
	elseif (Gx.iabsc.eq.0 .and. Gx.ixlab.eq.4) then
          ls = M$SEC2TSPEC(Gx.aretx, charb( 4:19), 0)
          ls = M$SEC2TSPEC(Gx.dretx, charb(25:40), 1)
	endif

	call MX$TEXT (Mx.text_w, NINT(Mx.height-Mx.text_h*1.5),chara)
	call MX$TEXT (Mx.text_w, NINT(Mx.height-Mx.text_h*.5),charb)

	ix = max (Mx.text_w*48, Mx.width-Mx.text_w*2)
	iy = NINT(Mx.height-Mx.text_h*.5)
	if (Gx.cntrls.gt.0) call MX$TEXT (ix,iy,'C')
	if (Gx.cntrls.le.0) call MX$TEXT (ix,iy,' ')
c
	return
	end

	subroutine XRTPLOT_ZOOM (Mx,Gx,ix1,iy1,ix2,iy2)
	include 'xrtplot.inc'
	integer*4 ix1,iy1,ix2,iy2,k
	k = Mx.level
	if (k.eq.L_stack) then
	  call MX$MESSAGE ('No more stack levels',1.0)
	else
	  Mx.stk(k+1).xmin = Mx.stk(k).xmin + 
     &		(ix1-Mx.stk(k).x1)*Mx.stk(k).xscl
	  Mx.stk(k+1).xmax = Mx.stk(k).xmin + 
     &		(ix2-Mx.stk(k).x1)*Mx.stk(k).xscl
	  Mx.stk(k+1).ymin = Mx.stk(k).ymin + 
     &		(Mx.stk(k).y2-iy2)*Mx.stk(k).yscl
	  Mx.stk(k+1).ymax = Mx.stk(k).ymin + 
     &		(Mx.stk(k).y2-iy1)*Mx.stk(k).yscl
	  Mx.level = k+1
	  call XRTPLOT_MSGDO (Mx, Gx, MSK_ZOOM, Mx.level)
	  call XRTPLOT_REFRESH (Mx,Gx)
	endif
	return
	end



	subroutine XRTPLOT_PREP (Mx, Gx, bufin, mode)
	include 'xrtplot.inc'
	real*4 bufin(*), fac, dbmin
	integer*4 ndo, i, iy, mode, loff, nelem
	real*4 rbuf(1), fbuf(1)
	pointer (rbuf_addr, rbuf)
	pointer (fbuf_addr, fbuf)
c
	if (mode.eq.0) then
	  loff = Gx.loff+1
	  nelem = Gx.nelem
	else
	  loff = 1
	  nelem = Gx.melem
	endif

	i = loff - 1
	ndo = nelem - i
	if (ndo .le. 0) return

	rbuf_addr = Gx.rbuf.p
	fbuf_addr = Gx.fbuf.p
c
c reformat to float if read in for the first time
	if (Gx.cx) then
	  ndo = ndo+ndo
	  i = i+i
	endif
	if (mode.ne.0) then
	elseif (Gx.type .ne. MP_FLOAT) then
	  call M$RETYPE (bufin,Gx.type,rbuf(i+1),MP_FLOAT,ndo)
	else
	  call M$MOVE (bufin,rbuf(i+1),ndo*4)
	endif
c
c init constants
	fac = 10.
	if (Gx.cmode.eq.7) fac = 20.
	Gx.lbuf.p = Gx.fbuf.p ! point usable buffer to fbuf
c
c get complex/log modes into scalar array of values
	ndo = nelem-loff+1
	if (Gx.cx) then
	  iy = i+1
	  if (Gx.cmode.eq.1) then
	    call M$CVMAG(rbuf(iy), fbuf(loff), ndo)
	  else if (Gx.cmode.eq.2) then
	    if (Gx.fast) then
	      call M$CVRPHAD(rbuf(iy), fbuf(loff), ndo, 90)
	    else
	      call M$CVPHAD(rbuf(iy), fbuf(loff), ndo)
	    endif
	  else if (Gx.cmode.eq.3) then
	    call M$VMOV(rbuf(iy), 2, fbuf(loff), 1, ndo)
	  else if (Gx.cmode.eq.4) then
	    call M$VMOV(rbuf(iy+1), 2, fbuf(loff), 1, ndo)
	  elseif (Gx.cmode.ge.6) then
	    call M$CVMAG2(rbuf(iy), fbuf(loff), ndo)
	    dbmin = Gx.dbmin
	    ! Fast Algorithm uses exponent bytes directly, no log needed
	    if (Gx.fast) then
	      do i = loff,nelem
		fbuf(i) = max(abs(fbuf(i)), dbmin)
	      enddo
	    else
	      call M$VLOG10(fbuf(loff), dbmin, fbuf(loff), ndo)
	    endif
	  else 
	    Gx.lbuf.p = Gx.rbuf.p	! use raw buffer
	  endif
	else
	  if (Gx.cmode.eq.1 .or. Gx.cmode.ge.6) then
	    do i = loff,nelem
	      fbuf(i) = abs(rbuf(i))
	    enddo
	  endif
	  if (Gx.cmode.ge.6) then
	    ! Fast Algorithm uses exponent bytes directly, no log needed
	    if (Gx.fast) then
	      dbmin = Gx.dbmin
	      do i = loff,nelem
		fbuf(i) = max(fbuf(i), dbmin)
	      enddo
	    else
	      call M$VLOG10(fbuf(loff), Gx.dbmin, fbuf(loff), ndo)
	    endif
	  elseif (Gx.cmode.ne.1) then
	    Gx.lbuf.p = Gx.rbuf.p	! use raw buffer
	  endif
	endif


	return
	end

	subroutine XRTPLOT_MSGDO (Mx, Gx, bit, iarg)
	include 'xrtplot.inc'
	integer*4 bit, iarg

	if (Gx.xf.msgid.ge.0 .and. BTEST(Gx.xf.msgmask,bit)) 
     &		call XRTPLOT_INFOMSG (Mx, Gx, bit, iarg, Gx.xf.msgid)
	return
	end

	subroutine XRTPLOT_INFOMSG (Mx, Gx, bit, iarg, rid)
	include 'xrtplot.inc'
	include 'qmessdef.inc'
	include 'qmessdecl.inc'
	character*2 cxm(7) /'MA', 'PH', 'RE', 'IM', 'IR', 'LO', 'L2'/
	integer*4 iarg, rid, i, bit
	real*8 d

	if (bit .eq. MSK_BOXES) then
	  Gx.xf.iarg = iarg
	  Gx.xf.mqdloc.p = %loc(MQD.BOXINFO)
	  call MX$FACILITIES (Gx.xf, 'B', 3)
	  MQH_BOXINFO.boxid = Gx.xf.iarg
	  call M$SEND_MSG (MQH_BOXINFO, MQD.BOXINFO, rid, 0)
	elseif (bit .eq. MSK_COLOR) then
	  call MX$COLORTAB (iarg, MQD.COLORINFO, -3)
	  MQH_COLORINFO.colorid = iarg
	  call M$SEND_MSG (MQH_COLORINFO, MQD.COLORINFO, rid, 0)
	elseif (bit .eq. MSK_EXIT) then
	  call M$SEND_MSG (MQH_EXITINFO, MQD, rid, 0)
	elseif (bit .eq. MSK_MARK) then
	  MQD.MARKINFO.x = Gx.xmrk
	  MQD.MARKINFO.y = Gx.ymrk
	  MQD.MARKINFO.z = 0.d0
	  MQH_MARKINFO.info = Mx.state_mask
	  call M$SEND_MSG (MQH_MARKINFO, MQD.MARKINFO, rid, 0)
        elseif (bit .eq. MSK_POINTS) then
          Gx.xf.iarg = iarg
          Gx.xf.mqdloc.p = %loc(MQD.POINTINFO)
          call MX$FACILITIES (Gx.xf, 'P', 3)
          MQH_POINTINFO.pointid = Gx.xf.iarg
          call M$SEND_MSG (MQH_POINTINFO, MQD.POINTINFO, rid, 0)
	else
	  if (iarg.lt.1) i = max(1,Mx.level+iarg)
	  if (iarg.ge.1) i = min(iarg,Mx.level)
	  if (bit .eq. MSK_CXMODE) then
	    MQD.CXMODE.mode = cxm(Gx.cmode)
	    MQH_CXMODEINFO.level = i - 1
	    call M$SEND_MSG (MQH_CXMODEINFO, MQD.CXMODEINFO, rid, 0)
	  else
	    MQD.PLOTINFO.xmin = min (Mx.stk(i).xmin, Mx.stk(i).xmax)
	    MQD.PLOTINFO.xmax = max (Mx.stk(i).xmin, Mx.stk(i).xmax)
	    MQD.PLOTINFO.ymin = min (Mx.stk(i).ymin, Mx.stk(i).ymax)
	    MQD.PLOTINFO.ymax = max (Mx.stk(i).ymin, Mx.stk(i).ymax)
	    if (bit .eq. MSK_ZOOM) then
	      MQH_ZOOMINFO.level = i - 1
	      call M$SEND_MSG (MQH_ZOOMINFO, MQD.PLOTINFO, rid, 0)
	    elseif (bit .eq. MSK_UNZOOM) then
	      MQH_UNZOOMINFO.level = i - 1
	      call M$SEND_MSG (MQH_UNZOOMINFO, MQD.PLOTINFO, rid, 0)
	    else
	      MQD.PLOTINFO.xunits = Gx.xlab
	      MQD.PLOTINFO.yunits = Gx.ylab
	      MQD.PLOTINFO.cxmode = cxm(Gx.cmode)
	      if (bit .eq. MSK_PANX .or. bit .eq. MSK_PANY) then
		if (bit .ne. MSK_PANX) then
		  MQD.PLOTINFO.xmin =  1.0d0
		  MQD.PLOTINFO.xmax = -1.0d0
		endif
		if (bit .ne. MSK_PANY) then
		  MQD.PLOTINFO.ymin =  1.0d0
		  MQD.PLOTINFO.ymax = -1.0d0
		endif
		MQH_PANINFO.level = i - 1
		call M$SEND_MSG (MQH_PANINFO, MQD.PLOTINFO, rid, 0)
	      elseif (bit .eq. -1) then
		MQH_PLOTINFO.level = i - 1
		MQD.PLOTINFO.xframe = Gx.mframe
		MQD.PLOTINFO.yframe = Gx.lps
		MQD.PLOTINFO.primname = 'XRTPLOT'
		call M$SEND_MSG (MQH_PLOTINFO, MQD.PLOTINFO, rid, 0)
	      endif
	    endif
	  endif
	endif

	return
	end

	subroutine XRTPLOT_SETTINGS (Mx, Gx, item, v)
	include 'xrtplot.inc'
	integer*4 item, v, i, k, pass, oldval
	logical*4 t, interactive
	real*8 dtemp

	t = v .lt. 0
	interactive = v .eq. -999

	if (item.eq.t_auto) then
	  if (interactive) then
	    Gx.iautom = MX$MENU(Gx.iautom+1,'SCALING;Parameters...,'//
     +		  'Min Auto...,Max Auto...,Full Auto...,Fix Auto...') - 1
	  else
	    Gx.iautom = max(0, min(v, 4))
	  endif
	elseif (item.eq.t_autol) then
	  if (interactive) then
	    call MX$LPROMPT('Number lines in average: ', Gx.iautol)
	  else
	    Gx.iautol = v
	  endif
	elseif (item.eq.t_clear) then
	  if (t .or. (v.eq.0 .eqv. Gx.clear)) then
	    Gx.clear = .not. Gx.clear
	    if (Gx.lps.gt.1 .and. Gx.class.eq.1 .and. Gx.pass.ne.0) then
	      if (Gx.clear) then
		pass = (Gx.pass + Gx.lps - 1) / Gx.lps
	      else
		pass = (Gx.pass-1)*Gx.lps + INT((Gx.nelem-1)/Gx.mframe) + 1
	      endif
	      call XRTPLOT_PASS(Mx, Gx, pass, pass-Gx.pass, 1)
	      if ((Gx.specs .or. Gx.grid)
     +		.and. Gx.nowrap .and. Gx.cmode.ne.5) Mx.exposure = .true.
	    endif
	    if (Gx.clear .and. Gx.melem.gt.Gx.nelem) then
	      Gx.melem = Gx.nelem
	      Mx.exposure = .true.
	    endif
	  endif
	elseif (item.eq.t_cntrls) then
	  oldval = Gx.cntrls
	  if (interactive) then
	    Gx.cntrls = 3 - MX$MENU(3-Gx.cntrls,'CONTROLS OPTIONS;'//
     +		  'Continuous,LM Click,Off,LM Click (Disabled),'//
     +		  'Continuous (Disabled)')
	  else
	    Gx.cntrls = max(-2, min(2, v))
	  endif
	  if (oldval .ne. Gx.cntrls) call XRTPLOT_SPECS (Mx,Gx)
	elseif (item.eq.t_edge) then
	  if (t .or. (v.eq.0 .eqv. Gx.edge)) then
	    Gx.edge = .not. Gx.edge
	    k = Mx.level
	    if (Gx.e1.gt.Mx.stk(k).x1 .and. Gx.e1.lt.Mx.stk(k).x2) 
     +		call MX$DRAW_LINE (-2,Gx.e1,Mx.stk(k).y1,Gx.e1,Mx.stk(k).y2)
	  endif
	elseif (item.eq.t_events) then
	  if (interactive) then
	    call MX$LPROMPT ('Events Processed Per Pass: ', Gx.events)
	  else
	    Gx.events = v
	  endif
	  if (Gx.events.le.0) Gx.events = 2
	elseif (item.eq.t_fast) then
	  if (t .or. (v.eq.0 .eqv. Gx.grid)) Gx.fast = .not. Gx.fast
	elseif (item.eq.t_grid) then
	  if (t .or. (v.eq.0 .eqv. Gx.grid)) then
	    Gx.grid = .not. Gx.grid
	    Mx.exposure = .true.
	  endif
	elseif (item.eq.t_markm) then
	  oldval = Gx.markm
	  if (interactive) then
	    Gx.markm = MX$MENU(min(4,Gx.markm+3),
     +			'MARKER MODE;Origin,Peak,Off,Index...')-3
	    if (Gx.markm.eq.1) call MX$LPROMPT('Marker Index: ', Gx.markm)
	  else
	    Gx.markm = v
	  endif
	  if (oldval.ne.Gx.markm) Mx.exposure = .true.
	elseif (item.eq.t_marks) then
	  oldval = Gx.marks
	  if (interactive) then
	    call MX$LPROMPT('Marker Size: ', Gx.marks)
	  else
	    Gx.marks = v
	  endif
	  if (oldval.ne.Gx.marks) Mx.exposure = .true.
	elseif (item.eq.t_mimic) then
	  if (interactive) then
	    call MX$LPROMPT('Primitive to MIMIC: ', Gx.mimic)
	  else
	    Gx.mimic = v
	  endif
	elseif (item.eq.t_msgid) then
	  if (interactive) then
	    call MX$LPROMPT('MSGID to report to: ', Gx.xf.msgid)
	  else
	    Gx.xf.msgid = v
	  endif
	elseif (item.eq.t_specs) then
	  if (t .or. (v.eq.0 .eqv. Gx.specs)) then
	    Gx.specs = .not. Gx.specs
	    Mx.exposure = .true.
	  endif
	elseif (item.eq.t_wrap) then
	  if (t .or. (v.ne.0 .eqv. Gx.nowrap)) then
	    Gx.nowrap = .not. Gx.nowrap
	    if (Gx.pass.gt.1 .and. Gx.cmode.ne.5) then
	      if (Gx.nowrap) then
		call XRTPLOT_PASS(Mx, Gx, Gx.pass, Gx.pass-1, 0)
	      else
		call XRTPLOT_PASS(Mx, Gx, Gx.pass, 1-Gx.pass, 0)
	      endif
	      if (Gx.specs .or. Gx.grid) Mx.exposure = .true.
	    endif
	  endif
	elseif (item.eq.t_xdivisions) then
	  oldval = Gx.xdiv
	  if (interactive) then
	    call MX$LPROMPT('X Divisions: ', Gx.xdiv)
	  else
	    Gx.xdiv = v
	  endif
	  if (Gx.xdiv .eq. 0) Gx.xdiv = 1
	  if (oldval.ne.Gx.xdiv) Mx.exposure = .true.
	elseif (item.eq.t_xlabel) then
	  oldval = Gx.xlab
	  if (interactive) then
	    call MX$LPROMPT('X Units: ', Gx.xlab)
	  else
	    Gx.xlab = v
	  endif
	  if (oldval.ne.Gx.xlab) Mx.exposure = .true.
	elseif (item.eq.t_ydivisions) then
	  oldval = Gx.ydiv
	  if (interactive) then
	    call MX$LPROMPT('Y Divisions: ', Gx.ydiv)
	  else
	    Gx.ydiv = v
	  endif
	  if (Gx.ydiv .eq. 0) Gx.ydiv = 1
	  if (oldval.ne.Gx.ydiv) Mx.exposure = .true.
	elseif (item.eq.t_yinv) then
	  if (t .or. (v.eq.0 .eqv. Gx.yinv)) then
	    Gx.yinv = .not. Gx.yinv
	    do i = 1, Mx.level
	      dtemp = Mx.stk(i).ymax
	      Mx.stk(i).ymax = Mx.stk(i).ymin
	      Mx.stk(i).ymin = dtemp
	      Mx.stk(i).yscl = - Mx.stk(i).yscl
	    enddo
	    Mx.exposure = .true.
	  endif
	elseif (item.eq.t_ylabel) then
	  oldval = Gx.ylab
	  if (interactive) then
	    call MX$LPROMPT('Y Units: ', Gx.ylab)
	  else
	    Gx.ylab = v
	  endif
	  if (oldval.ne.Gx.ylab) Mx.exposure = .true.
	endif

	return
	end


	subroutine XRTPLOT_REFRAME (Mx, Gx, fframe, flags)
	include 'xrtplot.inc'
	include 'dsestypes.inc'
	integer*4 fframe,frame,cons,flags,oldframe,oldnelem,nbytes
	record /M_PTR/ tbuf
	cons = MD$BUFCONS (1)
	if (fframe.le.0) then
	  call M$WARNING('Illegal frame size <= 0 requested, using 1')
	  frame = 1
	else
	  frame = fframe
	endif
	if (cons.gt.0) then
	  cons = cons*frame/Gx.mframe
	  call MD$SETBUFCONS (1,cons)
	endif
	oldframe = Gx.mframe 
	if (BTEST(flags,1)) then	! retain data
	  oldnelem = min(Gx.nelem,frame)
	  nbytes = oldnelem*4
	  if (Gx.cx) nbytes=nbytes*2
	  call M$MALLOC (nbytes,tbuf.p)
	  call M$MOVE (%val(Gx.rbuf.p),%val(tbuf.p),nbytes)
	endif
	Gx.mframe = max (1, frame)
	Gx.nelem = Gx.mframe * Gx.lps
	call XRTPLOT_ALLOCATE (Gx, 1)
	Gx.loff = 0
	Gx.nelem = 0
	Gx.melem = 0
	Gx.pass = 0
	if (BTEST(flags,1)) then	! retain data
	  Gx.nelem = oldnelem
	  Gx.melem = oldnelem
	  call M$MOVE (%val(tbuf.p),%val(Gx.rbuf.p),nbytes)
	  call M$FREE (tbuf.p)
	  call XRTPLOT_PREP (Mx,Gx,0,1)
	endif
	if (BTEST(flags,0)) call XRTPLOT_WARPRANGE
     &	  (Mx, Gx, DBLE(Gx.mframe)/oldframe, 0.d0)
	call XRTPLOT_REFRESH (Mx,Gx)

	return
	end

	subroutine XRTPLOT_CMODE (Mx, Gx, newmode)
	include 'xrtplot.inc'
	integer*4 newmode, tmode
	real*4 dbscale

	! PHASE, IMAGINARY, and IR:Imag/Real are illegal for scalar data
	if (.not. Gx.cx) then
	  if (newmode.eq.2 .or. newmode.eq.4 .or. newmode.eq.5) return
	endif

	if (Gx.nowrap .and. Gx.pass.gt.1) then
	  if (Gx.cmode.eq.5) then
	    Gx.xstart = Gx.xstart + (Gx.pass-1)*Gx.mframe*Gx.xdelta
	  elseif (newmode.eq.5) then
	    Gx.xstart = Gx.xstart - (Gx.pass-1)*Gx.mframe*Gx.xdelta
	  endif
	endif

	tmode = newmode
	if (newmode .gt. 7) tmode = tmode - 2	! D1 and D2 = LO and L2

	if (Gx.cmode .ne. tmode) then
	  ! Both modes non-log, no changes needed
	  if (Gx.cmode.lt.6 .and. tmode.lt.6) then
	  ! Changing from log to log mode
	  elseif (Gx.cmode.ge.6 .and. tmode.ge.6) then
	    dbscale = 2.0
	    if (Gx.cmode .eq. 7) dbscale = 0.5
	    Gx.ymin  = Gx.ymin * dbscale
	    Gx.ymax  = Gx.ymax * dbscale
	    Gx.rmin  = Gx.rmin * dbscale
	    Gx.rmax  = Gx.rmax * dbscale
	    Gx.rmin0 = Gx.rmin0 * dbscale
	    Gx.rmax0 = Gx.rmax0 * dbscale
	  ! Changing from log to non-log mode
	  elseif (Gx.cmode.ge.6) then
	    dbscale = 10.0
	    if (Gx.cmode.eq.7) dbscale = 20.0
	    Gx.ymin  = 10**(Gx.ymin/dbscale)
	    Gx.ymax  = 10**(Gx.ymax/dbscale)
	    Gx.rmin  = 10**(Gx.rmin/dbscale)
	    Gx.rmax  = 10**(Gx.rmax/dbscale)
	    Gx.rmin0 = 10**(Gx.rmin0/dbscale)
	    Gx.rmax0 = 10**(Gx.rmax0/dbscale)
	  ! Changing from non-log to log mode
	  else
	    dbscale = 10.0
	    if (tmode.eq.7) dbscale = 20.0
	    Gx.ymin = log10(max(abs(Gx.ymin),Gx.dbmin)) * dbscale
	    Gx.ymax = log10(max(abs(Gx.ymax),Gx.dbmin)) * dbscale
	    Gx.rmin = log10(max(abs(Gx.rmin),Gx.dbmin)) * dbscale
	    Gx.rmax = log10(max(abs(Gx.rmax),Gx.dbmin)) * dbscale
	    Gx.rmin0 = log10(max(abs(Gx.rmin0),Gx.dbmin)) * dbscale
	    Gx.rmax0 = log10(max(abs(Gx.rmax0),Gx.dbmin)) * dbscale
	  endif

	  Gx.cmode = tmode
	  call XRTPLOT_PREP(Mx, Gx, 0, 1)
	  call XRTPLOT_RESET (Mx,Gx)
	  call XRTPLOT_MSGDO (Mx, Gx, MSK_CXMODE, newmode)
	  call XRTPLOT_REFRESH (Mx,Gx)
	endif

	return
	end

	subroutine XRTPLOT_PASS (Mx, Gx, pass, dpass, check_nowrap)
	include 'xrtplot.inc'
	integer*4 pass, dpass, k, check_nowrap
	real*8 xoff

	if (check_nowrap.eq.0 .or. Gx.nowrap) then
	  if (Gx.cmode.ne.5 .and. dpass.ne.0) then
	    xoff = dpass * Gx.mframe * Gx.xdelta
	    Gx.xstart = Gx.xstart + xoff
	    Gx.xmin   = Gx.xmin + xoff
	    Gx.xmax   = Gx.xmax + xoff
	    do k = 1, Mx.level
	      Mx.stk(k).xmin = Mx.stk(k).xmin + xoff
	      Mx.stk(k).xmax = Mx.stk(k).xmax + xoff
	    enddo
	  endif
	endif
	Gx.pass = pass

	return
	end


	subroutine XRTPLOT_WARPRANGE (Mx, Gx, scale, shift)
	include 'xrtplot.inc'
	real*8 scale, shift, doff
	integer*4 ii
	if (scale.ne.1.d0 .or. shift.ne.0.d0) then
	  doff = Gx.xstart + shift
	  do ii = 1, Mx.level
	    Mx.stk(ii).xmin = (Mx.stk(ii).xmin-Gx.xstart) * scale + doff
	    Mx.stk(ii).xmax = (Mx.stk(ii).xmax-Gx.xstart) * scale + doff
	  enddo
	  Gx.xmin = Mx.stk(1).xmin
	  Gx.xmax = Mx.stk(1).xmax
	endif
	return
	end

	subroutine XRTPLOT_XF (Mx, Gx, type, mode)
	include 'xrtplot.inc'
	character type
	integer*4 mode

	if (type.eq.'A') call XRTPLOT_REFRESH(Mx,Gx)

	call MX$FACILITIES(Gx.xf, type, mode)

	Gx.nxf = 0
	if (Gx.xf.aview) Gx.nxf = max(Gx.nxf, Gx.xf.nannt)
	if (Gx.xf.bview) Gx.nxf = Gx.nxf + Gx.xf.nbox
	if (Gx.xf.pdot.ne.0 .or.
     &		Gx.xf.pline.gt.0) Gx.nxf = Gx.nxf + Gx.xf.npoint
	return
	end
