c*****************************************************************************
c  Description: Static multiple file plotter for X-terminal graphics
c
c  Author:      JGS   7/1/91  (Pilfered mostly from XRTPLOT)
c
c  $Revision: 1.1 $
c  $Modtime:   29 Oct 1997 17:48:26  $
c
c   The following line directs xpc to turn the Sun FORTRAN compiler
c   optimization down to level 1 due to its inability to correctly optimize
c   the code referencing pointers
c   #_SUN OPTIMIZATION -O1
c
c  Modifications:  18-Jun-2004 - C Bland - DR #503517 - xplot index mode fix
c		   Modified XPLOT_PREP to check for index mode, if so then
c		   xpoint[] is numbered from 1:npts for indecies.  Also
c		   modified n1/n2 statements in check (xdelta .ge. 0d0)
c		   Change takes into account negative x-vals so the real #
c		   of points is returned instead of less.
c  
c*********************************************
c
c Basic algorithm for plotting data:
c
c 1. Call LOAD_FILES with file input string; puts HCB(s) into HCB arrays,
c    opens file(s) and inits associated lyr struct(s).
c       A. If an overlay, loads in data and plots it to the screen
c	B. If a base file, loads in data and scales the plotting range
c	C. If a modify file, opens for R/W, loads in data and plots it
c 2. Call DRAW_LAYER to load and draw the data to the screen
c   A. Call GET_DATA to load the raw data into the data lyr structure(s)
c   B. Call XPLOT_PREP to convert raw data to proper mode in the Gx.xptr 
c       and Gx.yptr arrays (and updates the pan limits in the process)
c   C. Call MX$TRACE to draw it to the screen
c
c XPLOT_INIT 
c Called only once, it picks the arguments off of the command line, converts
c the xmin,xmax ymin,ymax to properly scaled values if not present on the 
c command line and picks up any special command line switches. 
c
c XPLOT_REFRESH 
c Redraws the plotting screen with all current parameters.
c
c XPLOT_EVENTLOOP 
c Processes one event and performs all necessary functions so that the 
c display reflects that actions consequences (I.E. redraws if necessary). It 
c returns a status of -1 if an event indicated that the primitive should be 
c exited. Because so many events necessitate redrawing the screen by calling 
c XPLOT_REFRESH, it is indicated throughout by setting the Mx.resize field 
c to .true. and then checking this field before leaving.  This avoids 
c refreshing the screen more than needed. 
c
c XPLOT_MSG 
c Processes one message from the message queue and performs all necessary
c functions so that the display reflects any consequences of that message.  
c If no message is available, or the message received is not recognized, 
c XPLOT returns a value of .false. 
c
c XPLOT_PAN 
c Handles all panning functions including centering.  If a pan operation
c necessitates loading in new data, this is also done. 
c
c XPLOT_CHANGEMODE 
c Changes the current plotting mode of the data and loads in all new data 
c that change might require.  The plotting field is rescaled to the data in 
c the base layers (those layers established through files given on the command
c line) and the data field is redrawn. 
c
c SCALE_BASE 
c Refigures the stk(1) by looking at the data and updating the panxmin,
c panxmax, panymin, panymax variables.  Depending on the mode, this routine 
c is also used to load data into the data layers by calling (GET_DATA). This 
c routine is called when XPLOT is first brought up to determine the base 
c plotting field. It is also called when the mode is changed (e.g. from Real 
c to Log) or when deoverlaying a file requires new base layers be established. 
c
c*****************************************************************************

	program xplot

	include 'xplot.inc'
	logical*4 pause
	integer*4 n
	character*(L_max_ascii) psfile
	integer*4		lpsfile

	call M$CHECKIN

c perform preamble calculations
	call XPLOT_INIT
	lpsfile = M$GET_USWITCH('PSFILE',psfile)

	call M$SYNC	! Done with global memory

	if (lpsfile.gt.0) then
	  if (.not. MX$HARDCOPY_OPEN(psfile,1)) lpsfile = 0
	endif
	call XPLOT_REFRESH(2)
	if (Gx.modified) call MODIFY_OPEN(1)
	if (lpsfile .gt. 0) call MX$HARDCOPY_CLOSE()

	if (Gx.cross) call TOGGLE_CROSS ()
	do while (.not.(Mc.break .or. Mx.breakflag))
	  pause = .not. XPLOT_MSG()
	  if (Gx.hold.lt.2 .and. .not. Mx.breakflag) then
	    if ( MX$QUEUED() .gt. 0 ) then
	      call XPLOT_EVENTLOOP ()
	      pause = .false.
	    endif
	    if (pause) call M$PAUSE (Mc.pause)
	  endif
	enddo

c close associated files, check for modifications still open, free buffers
	call XPLOT_CLEANUP
	call MX$FACILITIES (Gx.xf, 'ABP', L_CleanExit)
	call MX$MAP (Gx.lmap,0,0,0,0,L_FreeMap)
	do n = 1, min(Gx.bs,L_zoommax)
	  call MX$MAP (Mx.zoom(n),0,0,0,0,L_FreeMap)
	enddo
	call MX$CLOSE		! close display

	call MSGDO(MSK_EXIT, 0)
	call M$RETURN		! restart shell

	end

	subroutine TOGGLE_CROSS ()

	include 'xplot.inc'
	integer*4 i, j

	if (Mx.xpos .ge. Gx.l .and. Mx.xpos .le. Gx.r)
     &		call MX$RUBBERLINE (Mx.xpos, Gx.t, Mx.xpos, Gx.b)
	if (Mx.ypos .ge. Gx.t .and. Mx.ypos .le. Gx.b)
     &		call MX$RUBBERLINE (Gx.l, Mx.ypos, Gx.r, Mx.ypos)
	return
	end

c*****************************************************************************
c This routine is called once and only once when the X-Plot primitive is
c first called.  It reads all of the information from global memory present
c on the command line, opens necessary files, scales the plotting field
c opens the graphics window and plots the data the first time.
c*****************************************************************************

	subroutine XPLOT_INIT ()

	include 'xplot.inc'
	include 'qmessdef.inc'

	character address*4, cmode*2, c*10
	character inputstring*(L_cmd_chars)
	integer*4 linput
	integer*4 mixc(L_XPlotLayers)
     &			/0,53,27,80,13,40,67,93, 7,60,33,87,20,47,73,100/
	integer*4 mixl(L_XPlotLayers)
     &			/3, 0, 3, 0, 3, 0, 3, 3, 0, 0, 3, 3, 0, 3, 3,  0/
	integer*4 mixs(L_XPlotLayers)
     &			/0, 2, 0, 3, 0, 4, 0, 0, 5, 6, 0, 0, 7, 0, 0,  3/
	integer*4 mixt(L_XPlotLayers)
     &			/1, 3,-1, 3,-1, 3,-1, 1, 3, 3, 1,-1, 3, 1,-1,  3/
	integer*4 line, thick, sym, rad, n, ncolors, mask
	logical*4 imode, havexmin, havexmax, haveymin, haveymax
	external DISPLAY_SPECS
	real*8 dbscale
	record /MQD_COLOR/ color(L_XPlotLayers)
	record /MQD_TRACE/ MQD

c read shared memory
	linput = M$UAPICK(1, inputstring, 0)
	Gx.xmin  = M$DPICK(2)
	Gx.xmax  = M$DPICK(3)
	havexmin = M$PPICK(2)
	havexmax = M$PPICK(3)
	address  = M$APICK(4)
	line	 = M$LPICK(5)
	Gx.ylab	 = M$BPICK(6)
	Gx.ymin = M$DPICK(7)
	Gx.ymax = M$DPICK(8)
	haveymin = M$PPICK(7)
	haveymax = M$PPICK(8)

c DR 5566 SAR 10/1/02
c       See if the /forcelab switch has been specified
        Gx.forcelab     = M$GET_PSWITCH ('FORCELAB')

	Gx.all 		= M$GET_PSWITCH ('ALL') 
	Gx.mimic	= M$GET_SWITCH ('MIMIC')
	Gx.xlab		= M$GET_SWITCH ('XLAB')
        Gx.segment	= M$GET_PSWITCH ('SEGMENT')
	Gx.ylab		= M$GET_SWITCH_DEF('YLAB', Gx.ylab)
	Gx.plab		= 24
	if (M$GET_USWITCH('PHUNITS', c).gt.0) then
	  if (c(1:1).eq.'R') Gx.plab = 23
	  if (c(1:1).eq.'C') Gx.plab = 25
	endif
	Gx.xdiv		= 5
	Gx.ydiv		= 5
	if (M$GET_PSWITCH('XDIV')) Gx.xdiv = M$GET_SWITCH ('XDIV')
	if (M$GET_PSWITCH('YDIV')) Gx.ydiv = M$GET_SWITCH ('YDIV')
	Mx.origin = 1
	if (M$GET_PSWITCH('YINV')) Mx.origin = 4
	if (M$GET_USWITCH('XMN', Gx.mouse) .le. 0)  Gx.mouse = 'MOUSE'
	Gx.pmt = 1.d0
	if (M$GET_PSWITCH('PMT')) Gx.pmt = max(0, M$GET_SWITCH('PMT'))
	if (M$GET_PSWITCH('XDIV')) Gx.xdiv = M$GET_SWITCH ('XDIV')
	Gx.bufmax = M$GET_SWITCH('BUF')
	if (Gx.bufmax .le. 0) Gx.bufmax = 32768
	Gx.sections = M$GET_SWITCH_DEF('NSEC',0)
c
c get user specs formatting
	if (M$GET_USWITCH('XFMT',Gx.xfmt) .le. 0)  Gx.xfmt = ' '
	if (M$GET_USWITCH('YFMT',Gx.yfmt) .le. 0)  Gx.yfmt = ' '

c if MSGID switch is indicated, this plot will send & respond to
c status change messages

	Gx.xf.msgid	= M$GET_SWITCH ('MSGID')
	Gx.xf.msgmask	= max (0, M$GET_SWITCH ('MASK'))

c Get switch for DATALIST mode, also if 'IN' prefix is found in address
c assume command line parameters are specified in terms of indices
	Gx.index 	= M$GET_PSWITCH ('INDEX')
	imode = (Gx.index .or. address(1:2) .eq. 'IN')
	if (imode) then
	  if (havexmin .and. Gx.xmin.eq. 1.d0) havexmin = .false.
	  if (havexmax .and. Gx.xmax.eq.-1.d0) havexmax = .false.
	endif

	Gx.layers = 0
	Gx.nfiles = 0
	Gx.xptr.p = 0
	Gx.yptr.p = 0
	Gx.pointbufsize = 0
	Gx.xdata = .false.
	Gx.note = ' '
	Gx.hold = 0

	call M$VSTYPE ('D')

c
c parse out filestring
	if (linput.eq.0) then
	  call BASEFILE (.false.)
	else
	  call LOAD_FILES (inputstring, 0, M$GET_PSWITCH('STAY'))
	endif
c
c get complex mode from address parameter
	cmode = address(1:2)
	if (cmode.eq.'IN' .or. cmode.eq.'AB' .or. cmode.eq.'__') then
	  cmode = address(3:4)
	endif
	if (Gx.lyr(1).cx) Gx.cmode = 1
	if (.not. Gx.lyr(1).cx) Gx.cmode = 3

	if (cmode.eq.'MA') Gx.cmode = 1
	if (cmode.eq.'PH') Gx.cmode = 2
	if (cmode.eq.'RE') Gx.cmode = 3
	if (cmode.eq.'IM') Gx.cmode = 4
	if (cmode.eq.'LO' .or. cmode.eq.'D1') Gx.cmode = 6
	if (cmode.eq.'L2' .or. cmode.eq.'D2') Gx.cmode = 7
	if (cmode.eq.'RI' .or. cmode.eq.'IR') then
	  if (Gx.index) then
	    call M$WARNING ('Imag/Real mode not permitted in /INDEX mode')
	  else
	    Gx.cmode = 5
	  endif
	endif
	Gx.basemode = Gx.cmode
	call XPLOT_CHANGEMODE(Gx.cmode)

c DR 5566 SAR 10/1/02
c Make sure that either the /xlab or /ylab has been specified in conjunction
c with using the /forcelab switch.
        if ( (Gx.forcelab) .and. (Gx.xlab .le. 0) .and. 
     &       (Gx.ylab .le. 0) ) then
          call M$WARNING
     &      ('/xlab or /ylab is missing with /forcelab usage')
          Gx.forcelab = .false.
        endif
c end DR 5566 SAR

c
c convert 'LO' and 'L2' parameters to dB and set lower limit on DB values
	Gx.dbmin = 1d-20
	if (Gx.cmode .ge. 6) then
	  dbscale = 10.d0
	  if (Gx.cmode.eq.7) dbscale = 20.d0
	  if (cmode(1:1).eq.'L') then   ! keep backwords compatible behavior
	    if (Gx.lyr(1).cx) then
	      Gx.ymin = max(Gx.ymin, 1d-10)
	      Gx.ymax = max(Gx.ymax, 1d-10)
	    else
	      Gx.ymin = max(Gx.ymin, 1d-20)
	      Gx.ymax = max(Gx.ymax, 1d-20)
	    endif
	    Gx.ymin = dlog10(Gx.ymin) * dbscale
	    Gx.ymax = dlog10(Gx.ymax) * dbscale
	  elseif (Gx.lyr(1).cx) then   ! these values must be squared
	    Gx.ymin = max(-18.d0 * dbscale, Gx.ymin)
	    Gx.ymax = max(-18.d0 * dbscale, Gx.ymax)
	    Gx.dbmin = 1d-37    ! smallest possible float/double
	  elseif (min(Gx.ymin,Gx.ymax) .lt. -20.0*dbscale) then
	    Gx.ymin = max(-37.d0 * dbscale, Gx.ymin)
	    Gx.ymax = max(-37.d0 * dbscale, Gx.ymax)
	    Gx.dbmin = 10**(min(Gx.ymin,Gx.ymax)/dbscale)
	  endif
	endif

c
c initialize base plot request range checking for DATALIST type parameters
c also check to see if inverted Y range was specified on the command line
	Mx.level = 1
	if (imode .and. .not.Gx.index) then	!INdex base addressing mode
	  if (havexmin) Gx.xmin = Gx.xstart + Gx.xdelta*(Gx.xmin-1.d0)
	  if (havexmax) Gx.xmax = Gx.xstart + Gx.xdelta*(Gx.xmax-1.d0)
	endif
	Gx.autox = M$GET_SWITCH('AUTOX')
	if (Gx.autox.lt.0) then
	  Gx.autox = 0
	  if (.not. havexmin) Gx.autox = Gx.autox + 1
	  if (.not. havexmax) Gx.autox = Gx.autox + 2
	endif
	Gx.autoy = M$GET_SWITCH('AUTO')
	if (Gx.autoy.lt.0) then
	  Gx.autoy = 0
	  if (.not. haveymin) Gx.autoy = Gx.autoy + 1
	  if (.not. haveymax) Gx.autoy = Gx.autoy + 2
	endif

	mask = s_get_data
	if (havexmin) mask = mask + s_xmin
	if (havexmax) mask = mask + s_xmax
	call SCALE_BASE(mask, Gx.xmin, Gx.xmax)

c if no values indicated on the command line, set base values from data
	if (.not. havexmin) Gx.xmin = Mx.stk(1).xmin
	if (.not. havexmax) Gx.xmax = Mx.stk(1).xmax
	if (.not. haveymin) Gx.ymin = Mx.stk(1).ymin
	if (.not. haveymax) Gx.ymax = Mx.stk(1).ymax

c base values reset to those specified on the command line / or from data
	if (Gx.xmin .gt. Gx.xmax) then	! command line caused base X
	  Mx.stk(1).xmin = Gx.xmax	! bounds to flip, flip em back
	  Gx.xmax = Gx.xmin
	  Gx.xmin = Mx.stk(1).xmin
	endif
	if (Gx.ymin .gt. Gx.ymax) then	! command line cause base Y
	  Mx.stk(1).ymin = Gx.ymax	! bounds to flip, flip em back
	  Gx.ymax = Gx.ymin
	  Gx.ymin = Mx.stk(1).ymin
	endif
	Mx.stk(1).xmin = Gx.xmin
	Mx.stk(1).xmax = Gx.xmax
	Mx.stk(1).ymin = Gx.ymin
	Mx.stk(1).ymax = Gx.ymax
	Gx.panxmin = min (Gx.panxmin, Gx.xmin)
	Gx.panxmax = max (Gx.panxmax, Gx.xmax)
	Gx.panymin = min (Gx.panymin, Gx.ymin)
	Gx.panymax = max (Gx.panymax, Gx.ymax)

c open X-window display and root window
	call MX$SETUP (Mc.width, Mc.height)
	call MX$OPEN ('X-Plot')
	call MX$SETFONT (min(7, Mx.width/64))

c setup colormap from "Spectrum" table #4, get specific color in colormap 
c for 1st layer if specified on command line
	ncolors = L_XPlotLayers
	do n = 1, ncolors
	  color(n).position = mixc(n)
	enddo
	call MX$XC(Mc.colormap(4), color, ncolors)
	call MX$COLORMAP (Mc.colormap(4), ncolors)
	do n = 1, ncolors
	  if (color(n).position .lt. 0) then
	    call MX$COLORTAB (n, color(n), -2)
	  else
	    mixc(n) = color(n).position
	    call MX$COLORTAB (n, Mc.colormap(4), mixc(n))
	  endif
	enddo

c setup annotate, boxes and points facilities
#if _PGF77|_HPUX
	Gx.xf.ROUTINE.p = get_address(DISPLAY_SPECS)
#else
	Gx.xf.ROUTINE.p = %loc(DISPLAY_SPECS)
#endif
	Gx.xf.xy = .true.
	Gx.xf.mannt = 20
	Gx.xf.mbox = 100
	Gx.xf.mpoint = 1024
	call MX$FACILITIES (Gx.xf, 'ABP', L_InitFacilities)

c initialize layer structure line types
	if (line.ne.999) then
	  if (line.eq.0) then
	    line = 0
	    thick = 1
	    sym = L_PixelSymbol
	    rad = 0
	  else
	    thick = line
	    line = 3
	    sym = 0
	    rad = 3
	  endif

	  call MX$TRACE_MSG(MQD, line, thick, sym, rad, 999)
	endif

	do n = 1, L_XPlotLayers
	  Gx.lyr(n).display = .TRUE.
	  Gx.lyr(n).color = mod(n-1,ncolors) + 1
	  if (line.eq.999) then
	    Gx.lyr(n).line  = mixl(n)
	    Gx.lyr(n).symbol = mixs(n)
	    if (mixl(n).eq.0) then
	      Gx.lyr(n).radius = mixt(n)
	      Gx.lyr(n).thick = 0
	    else
	      Gx.lyr(n).radius = 0
	      Gx.lyr(n).thick = mixt(n)
	    endif
	  else
	    Gx.lyr(n).line  = line
	    Gx.lyr(n).thick = thick
	    Gx.lyr(n).symbol = sym
	    Gx.lyr(n).radius = rad
	  endif
	enddo

c get control mode
	Gx.cntrls = M$GET_SWITCH ('XCNT')
	if (Gx.cntrls.gt.2 .or. Gx.cntrls.lt.0) Gx.cntrls = 1

c initialize grid, legend, modify and absc modes
	Gx.bs        = min(L_zoommax, min(L_stack, M$GET_SWITCH('BS')))
	do n = 1, L_zoommax
	  Gx.bslyr(n)  = 0
	  Mx.zoom(n).ip = 0
	enddo
	Gx.cross     = M$GET_PSWITCH('CROSS')
	Gx.grid      = .not. M$GET_PSWITCH('NOGRID')
	Gx.legend    = M$GET_PSWITCH('LEGEND')
	Gx.pan       = .not. M$GET_PSWITCH('NOPAN')
	Gx.lmap.ip   = 0
	Gx.modmode   = 0
	Gx.modlayer  = 0
	Gx.modsource = 0
	Gx.modified  = (M$GET_PSWITCH('MOD') .and. Gx.layers.gt.0)
	Gx.marks(5)  = 5
	Gx.nmark     = 0
	Gx.iabsc     = 0
	if (Gx.index) Gx.iabsc = 1
	if (M$GET_USWITCH('SPECS',c).gt.0) Gx.iabsc = M$SEARCH('IRS',c(1:1))
	Gx.specs     = .not. M$GET_PSWITCH('NOSPECS')
	Gx.xmrk      = 0.d0
	Gx.ymrk      = 0.d0

	return
	end



c*****************************************************************************
c This routine redraws the plotting field and data the stk.yscl and stk.xscl
c fields are reset each time this routine is called.  If flag is 0 then a
c conditional redraw of the plotting field is done in case backing store has
c been turned on, we're in level one, and the Mx.resize field is not set.  If 
c flag is 1, then the redraw is forced.
c*****************************************************************************

	subroutine XPLOT_REFRESH (flag)

	include 'xplot.inc'
	external DISPLAY_SPECS

	real*4 timer
	integer*4 i, k, n, m, tw, th, flag, grid
	logical*4 bs, putbs

	if (Gx.hold.ne.0) return
	timer = SECNDS(0.0)

c set font width and plotting window dimensions
	call MX$SETFONT (min(7, Mx.width/64))
	tw = Mx.text_w
	th = Mx.text_h
	Gx.pthk = tw * 1.5
	if (Gx.specs) then
	  Gx.t = th*2
	  Gx.b = Mx.height - th*4
	  Gx.l = tw*6
	  Gx.r = Mx.width - (Gx.pthk + 2*tw)
	  Gx.pl = tw*50
	  Gx.pr = max (Gx.pl + tw*9, Gx.r)
	  Gx.pt = Gx.b + th + (Mx.height - Gx.b - th - Gx.pthk) / 2
	  Gx.lbtn = Mx.text_h + Mx.text_w + 2
	else
	  if (Gx.pan) then
	    Gx.t = Gx.pthk + 2*tw
	    Gx.r = Mx.width - (Gx.pthk + tw)
	  else
	    Gx.t = 1
	    Gx.r = Mx.width - 2
	  endif
	  Gx.b = Mx.height - 2
	  Gx.l = 1
	  Gx.pl = Gx.l
	  Gx.pr = Gx.r
	  Gx.pt = (Gx.t - Gx.pthk) / 2
	  Gx.lbtn = 0
	endif

c pan select ranges
	Gx.pyl = Gx.r + (Mx.width - Gx.r - Gx.pthk) / 2 + 1

c set virtual window size/pos/scaling for current level
	k = Mx.level
	Mx.stk(k).x1 = Gx.l
	Mx.stk(k).y1 = Gx.t
	Mx.stk(k).x2 = Gx.r
	Mx.stk(k).y2 = Gx.b
	Mx.stk(k).xscl = (Mx.stk(k).xmax - Mx.stk(k).xmin) / DBLE(Gx.r-Gx.l)
	Mx.stk(k).yscl = (Mx.stk(k).ymax - Mx.stk(k).ymin) / DBLE(Gx.b-Gx.t)

c modify stack for section plotting
	if (Gx.sections.ne.0) then
	  Gx.nsec = Gx.sections
	  if (Gx.sections .eq. -1) Gx.nsec = Gx.layers
	  Gx.nsec = max(1,Gx.nsec)
	  Gx.iysec = (Gx.b - Gx.t)/Gx.nsec
	  Mx.stk(k).yscl = (Mx.stk(k).ymax - Mx.stk(k).ymin) / 
     &			DBLE(Gx.iysec)
	endif

c clear window and draw axes
	if (Gx.panning.eq.0) then
	  call MX$CLEAR_WINDOW()
	elseif (.not. Gx.specs) then
	  call MX$CLEAR_AREA(Gx.l-1, Gx.t-1, Gx.r-Gx.l+4, Gx.b-Gx.t+4)
	elseif (Gx.panning.eq.1) then
	  call MX$CLEAR_AREA(0, 0, Gx.r+2, Gx.b + 3*Mx.text_h/2)
	  call MX$CLEAR_AREA(Gx.r, Gx.b, Mx.width-Gx.r, 3*Mx.text_h/2)
	else
	  call MX$CLEAR_AREA(0, 0, Gx.r+3, Gx.b+3)
	  call MX$CLEAR_AREA(0, Gx.b, Gx.l, Mx.text_w)
	endif

c set labels
	Gx.ixlab = 30
	Gx.iylab = 30
	if (Gx.nfiles.gt.0) then
	  hcb_ptr = Gx.HCB(1).p
	  Gx.ixlab = HCB.xunits
	endif
	if (Gx.xlab .ge. 0) Gx.ixlab = Gx.xlab
	if (Gx.ylab .ge. 0) Gx.iylab = Gx.ylab
c DR 5566 SAR 10/1/02
c If the /forcelab switch is present, regardless of the mode, use the
c /xlab and/or /ylab values.  If it is not present, then use these labels
c depending on the mode.
        if ( .not. Gx.forcelab ) then
	  if (Gx.cmode.eq.1 .and. .not. Gx.lyr(1).cx) Gx.iylab = 28
	  if (Gx.cmode.eq.2) Gx.iylab = Gx.plab
	  if (Gx.cmode.eq.3 .and. Gx.lyr(1).cx) Gx.iylab = 21
	  if (Gx.cmode.eq.4) Gx.iylab = 22
	  if (Gx.cmode.eq.5) Gx.iylab = 22
	  if (Gx.cmode.eq.5) Gx.ixlab = 21
	  if (Gx.cmode.eq.6) Gx.iylab = 26
	  if (Gx.cmode.eq.7) Gx.iylab = 27
        endif
c end DR 5566 SAR

	if (Gx.specs) then
	  if (Gx.sections.eq.0) then
	    grid = 0
	    if (Gx.grid) grid = L_gridlines
	    if (Gx.panning.eq.2) grid = grid + L_noxtlab
	    call MX$DRAWAXIS (Gx.xdiv,Gx.ydiv,Gx.ixlab,Gx.iylab,grid)
	  else
	    do m = 1, Gx.nsec
	      Mx.stk(k).y1 = Gx.t + (m-1) * Gx.iysec 
	      Mx.stk(k).y2 = Mx.stk(k).y1 + Gx.iysec
	      grid = L_exactbox
	      if (Gx.grid) grid = grid + L_gridlines
	      if (m.ne.1) grid = grid + L_noxplab + L_noyplab
	      if (m.ne.Gx.nsec) grid = grid + L_noxtlab
	      call MX$DRAWAXIS (Gx.xdiv,Gx.ydiv,Gx.ixlab,Gx.iylab,grid)
	    enddo
	  endif
c Legend symbol
	  i = Gx.lbtn-2
	  if (Gx.legend) then
	    call MX$SHADOWBOX(Mx.width-Gx.lbtn, 2, i, i, 1, -2, 'L')
	  else
	    call MX$SHADOWBOX(Mx.width-Gx.lbtn, 2, i, i, 1, 2, 'L')
	  endif
c display cursor location
	  call DISPLAY_SPECS
	elseif (Gx.grid .and. Gx.sections.ge.0) then
	  grid = L_gridlines + L_noaxisbox + L_noxspecs + L_noyspecs
	  call MX$DRAWAXIS (Gx.xdiv, Gx.ydiv, Gx.ixlab, Gx.iylab, grid)
	endif

c plot layers to screen or backing store zoom level if present

	bs = Gx.bs .ge. Mx.level	! Do we need to worry about BkngStore?
	if (bs .or. flag.eq.2) then
	  i = k+1
	  if (flag.eq.2) i = 1
	  do n = i, L_zoommax
	    Gx.bslyr(n) = 0
	  enddo
	  if (flag.eq.1) Gx.bslyr(k) = 0 ! Force new BS
	  putbs = flag.eq.0 .and. Gx.bslyr(k).gt.0 .and. Mx.zoom(k).ip.ne.0
	  if (putbs) call MX$MAP (Mx.zoom(k), 0, 0, 0, 0, L_PutMap)
	else
	  putbs = .false.
	endif

	i = 1
	if (putbs) i = Gx.bslyr(k) + 1

	do n = i, Gx.layers
	  if (Gx.sections.ne.0) then
	    m = mod(n-1,Gx.nsec)+1
	    Mx.stk(k).y1 = Gx.t + (m-1) * Gx.iysec 
	    Mx.stk(k).y2 = Mx.stk(k).y1 + Gx.iysec
	  endif
	  call DRAW_LAYER(n)
	enddo

	if (Gx.sections.ne.0) then
	  Mx.stk(k).y1 = Gx.t 
	  Mx.stk(k).y2 = Mx.stk(k).y1 + Gx.iysec 
	endif

	if (bs .and. Gx.layers.gt.0) then	! Get new backing store area
	  call MX$MAP (Mx.zoom(k),Gx.l,Gx.t,Gx.r-Gx.l+1,Gx.b-Gx.t+1,L_NewMap)
	  do n = 1, Gx.layers
	    if (Gx.lyr(n).display) Gx.bslyr(k) = n
	  enddo
	endif

	Mx.resize = .false.
	Mx.exposure = .false.

c draw PAN selectors and controls indicator
	if (Gx.nmark.ge.1) call MX$RUBBERDOT (Gx.marks(1), Gx.marks(2), -2)
	if (Gx.nmark.ge.2) call MX$RUBBERDOT (Gx.marks(3), Gx.marks(4), -2)

c draw all other accessories
	call DRAW_ACCESSORIES (4) ! draw panbars, points, boxes, annt, legend

	call MX$XFLUSH()
	timer = SECNDS(timer)
	if (timer .ge. Gx.pmt) then
	  Gx.panmode = 1
	  Gx.panning = 0
	else
	  Gx.panmode = -2
	endif
	return
	end

	subroutine DRAW_ACCESSORIES (mode)

	include 'xplot.inc'
	integer*4 mode, ln

	if (mode.gt.0) then
	  if (mode.ge.4 .and. Gx.specs) then
	    ln = M$LENGTH(Gx.note)
	    call MX$TEXT(Mx.width-Gx.lbtn-(ln+1)*Mx.text_w, Mx.text_h,
     &			Gx.note(1:ln))
	  endif
	  if (mode.ge.4) call DRAW_PANBARS ()
	  if (mode.ge.3) call MX$FACILITIES (Gx.xf, 'BP', L_Draw)
	  if (mode.ge.2) call MX$FACILITIES (Gx.xf, 'A', L_Draw)
	  if (mode.ge.1 .and. Gx.legend) call DRAW_LEGEND()
	else
	  if (mode.le.-1.and.Gx.legend) call MX$MAP(Gx.lmap,0,0,0,0,L_PutMap)
	  if (mode.le.-2) call MX$FACILITIES (Gx.xf, 'A', -2)
	  if (mode.le.-3) call MX$FACILITIES (Gx.xf, 'BP', L_Draw)
	endif

	return
	end

c*****************************************************************************
c This routine redraws the X and Y scrollbars, or erases them, depending on
c the mode.  The scrollbars need only be erased during an OVERLAY since the
c entire plotting field is normally cleared each time and the scrollbars
c are redrawn from scratch.
c
c	Gx.pthk - specifies the thickness of the scrollbars.
c	Gx.pl, Gx.pr, Gx.pt, Gx.pthk - designate the bounds for the X scrollbox
c		panning region (left,right,top,bottom) including the <<X>>
c	Gx.px1, Gx.px2 - specifies the left and right edges of the actual
c		scrollbar within the scrollbox. The scrollbars coordinates are
c		Gx.px1, Gx.pt, Gx.px2, Gx.pt+Gx.pthk
c
c	Gx.pyl - is the left edge of the Y scrollbox.  The top is at Gx.t and
c		the bottom at Gx.b - Mx.text_h
c	Gx.py1, Gx.py2 - specifies the top and bottom edges of the actual
c		scrollbar within the Y scrollbox. The scrollbars coordinates
c		are Gx.pyl, Gx.py1, Gx.pyl+Gx.pthk, Gx.py2
c
c*****************************************************************************

	subroutine DRAW_PANBARS ()

	include 'xplot.inc'
	integer*4 k, i1, itext

	if (.not. Gx.pan .or. Gx.panning.ne.0) return

	k = Mx.level						! Y scrollbar

	i1 = MX$SCROLLBAR(0, Gx.pyl, Gx.pyl+Gx.pthk, Gx.t, Gx.b,
     &			  Mx.stk(k).ymin, Mx.stk(k).ymax,
     &			  Gx.panymin, Gx.panymax)

	if (Gx.pl .lt. Mx.width) then				! X scrollbar

	  i1 = MX$SCROLLBAR(0, Gx.pl, Gx.pr, Gx.pt, Gx.pt+Gx.pthk,
     &			    Mx.stk(k).xmin, Mx.stk(k).xmax,
     &			    Gx.panxmin, Gx.panxmax)
	endif

	return
	end


	subroutine DISPLAY_SPECS

	include 'xplot.inc'
	character chara*47, charb*47
	character*2 cxm(7) /'Ma', 'Ph', 'Re', 'Im', 'IR', 'Lo', 'L2'/
	character*6 cam(0:3) /'(absc)', '(indx)', '(1/ab)', '(dydx)'/
	integer*4 iretx, irety, k, ls, xt

c valid range check
	iretx = min (Gx.r, max0 (Gx.l, Mx.xpos))
	irety = min (Gx.b, max0 (Gx.t, Mx.ypos))

c section logic
	if (Gx.sections.ne.0) then
	  Gx.isec = max(1,min(Gx.nsec, ((irety-Gx.t)/Gx.iysec)+1 ))
	  irety = mod(irety-Gx.t,Gx.iysec) + Gx.t	! section #1
	else
	  Gx.isec = 0
	endif

c transform into realworld coordinates
	k = Mx.level
	if (IAND(Mx.origin,2) .eq. 0)  then
	  Gx.retx = Mx.stk(k).xmin + (iretx - Mx.stk(k).x1) * Mx.stk(k).xscl
	else
	  Gx.retx = Mx.stk(k).xmin + (Mx.stk(k).x2 - iretx) * Mx.stk(k).xscl
	endif
	if (Mx.origin .gt. 2) then
	  Gx.rety = Mx.stk(k).ymin + (irety - Mx.stk(k).y1) * Mx.stk(k).yscl
	else
	  Gx.rety = Mx.stk(k).ymin + (Mx.stk(k).y2 - irety) * Mx.stk(k).yscl
	endif

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.cmode.eq.5 .and. Gx.iabsc.eq.1) Gx.iabsc = 2	! R/I mode
	if (Gx.iabsc.eq.1) then			! index
	  Gx.aretx = DNINT((Gx.aretx-Gx.xstart)/Gx.xdelta) + 1.d0
	  Gx.dretx = DNINT(Gx.dretx/Gx.xdelta)
	elseif (Gx.iabsc.eq.2) then		! 1/absc
	  if (Gx.aretx.ne.0.d0) Gx.aretx = 1.d0/Gx.aretx
	  if (Gx.arety.ne.0.d0) Gx.arety = 1.d0/Gx.arety
	  if (Gx.dretx.ne.0.d0) Gx.dretx = 1.d0/Gx.dretx
	  if (Gx.drety.ne.0.d0) Gx.drety = 1.d0/Gx.drety
	endif

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.eq.0.d0) then
	    chara(21:40) = 'sl: Inf'
	  else
	    write(chara(21:40), '(3hsl:, g16.9)') Gx.drety/Gx.dretx
	  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

	xt = Mx.height - 1.5*Mx.text_h
	call MX$TEXT (Mx.text_w, xt, chara)
	xt = xt + Mx.text_h
	call MX$TEXT (Mx.text_w, xt, charb)

c  display controls indicator
	k = max (Gx.pr+Mx.text_w, Mx.width-Mx.text_w*2)
	if (k.lt.Mx.width) then
	  if (Gx.cntrls.gt.0) call MX$TEXT (k, xt, 'C')
	  if (Gx.cntrls.le.0) call MX$TEXT (k, xt, ' ')
	endif

	return
	end




	subroutine DRAW_LEGEND ()

	include 'xplot.inc'
	integer*4 n, ix, iy, ln, tw, xc, yc, xs, ys, thk, ic

	tw = Mx.text_w
	xs = tw*23
	ys = (Gx.layers + 1) * Mx.text_h
	xc = Gx.r - xs
	yc = Gx.t
	call MX$MAP (Gx.lmap, xc, yc, xs, ys, L_NewMap)
	call MX$CLEAR_AREA (xc, yc, xs, ys)
	call MX$DRAW_MODE (2)
	call MX$DRAW_BOX(L_FGColor, xc+2, yc+2, xs-5, ys-5)
	do n = 1, Gx.layers
	  ix = xc + 4*tw
	  iy = yc + n*Mx.text_h
	  if (n .eq. Gx.modlayer) call MX$TEXT (xc+tw, iy, '**')
	  if (Gx.lyr(n).display) then
	    ic = Gx.lyr(n).color
	    if (Gx.lyr(n).line.gt.0) then
	      thk = isign(min(tw,iabs(Gx.lyr(n).thick)), Gx.lyr(n).thick)
	      call MX$DRAW_MODE(thk)
	      call MX$DRAW_LINE(ic, ix, iy, ix+tw*2, iy)
	    endif
	    if (Gx.lyr(n).symbol .gt. 0) then
	      call MX$DRAW_MODE(0)
	      thk = min(Gx.lyr(n).radius, tw)
	      call MX$DRAW_SYMBOL(ic, ix+tw, iy, Gx.lyr(n).symbol, thk)
	    endif
	  endif
	  ix = ix + tw*3
	  iy = iy + Mx.text_h*.3
	  ln = M$LENGTH (Gx.lyr(n).name)
	  call MX$TEXT (ix, iy, Gx.lyr(n).name(1:ln))
	enddo

	return
	end


c**************************************************************
c
c  XPLOT_PREP -  uses xmin and xmax to translate and transfer the correct
c	portion of the layer's raw data buffer to the two x and y point
c	arrays with the correct CX MODE transformations.  If in I/R mode,
c	xmin and xmax no longer reflect abscissa coordinates and are ignored,
c	the entire buffer dbuf is moved and translated into the point array
c
c**************************************************************

	function XPLOT_PREP (n, xmin, xmax, xptr, yptr)
	include 'xplot.inc'
c Arguments
	integer*4 n		! layer number to prepare
	real*8 xmin, xmax	! X bounds within which data is to be viewed
	record /M_PTR/ xptr, yptr
c Locals
	real*8 drad2cyc
	parameter (drad2cyc = 1.d0/dtwopi)
	character*2  form
	integer*4  i, j, n1, n2, skip, npts
	logical*4  cx
	real*8 xstart, xdelta, d, dbscale, qmin, qmax
	complex*16 cdbuf(1)
	real*8 dbuf(*), xpoint(*), ypoint(*)
	pointer (dbuf_ptr,   dbuf)
	pointer (xpoint_ptr, xpoint)
	pointer (ypoint_ptr, ypoint)
c Code
	npts = Gx.lyr(n).size
	skip = Gx.lyr(n).skip

c
c calculate abscissa values
	if (npts * 8 .gt. Gx.pointbufsize) then
	  Gx.pointbufsize = npts * 8
	  call M$REMALLOC (Gx.pointbufsize, Gx.xptr)
	  call M$REMALLOC (Gx.pointbufsize, Gx.yptr)
	endif
	dbuf_ptr = Gx.lyr(n).ybuf.p

	xpoint_ptr = Gx.xptr.p
	qmin = Gx.lyr(n).xmin
	qmax = Gx.lyr(n).xmax
	if (Gx.cmode.eq.5 .or. Gx.lyr(n).xsub.gt.0) then
	  if (npts .le. 0) then
	    qmin = Gx.panxmin
	    qmax = Gx.panxmax
	  elseif (Gx.cmode.ne.5) then
	    xpoint_ptr = Gx.lyr(n).xbuf.p
	  elseif (Gx.lyr(n).cx) then
	    call M$VMOV(dbuf, 2, xpoint, 1, npts)
	  elseif (Gx.lyr(n).line .ne. 0) then
	    call M$VMXMN(dbuf, xpoint(1), xpoint(2), n1, n2, npts)
	    npts = 2
	  else
	    xpoint_ptr = dbuf_ptr
	  endif
	  if (npts.gt.0) call M$VMXMN(xpoint, qmax, qmin, n1, n2, npts)

	elseif (npts.gt.0) then
	  xstart = Gx.lyr(n).xstart
	  xdelta = Gx.lyr(n).xdelta
	  d = npts
	  if (xdelta .ge. 0.d0) then
c********MODIFICATION DR #503517************************************************
	    if (Gx.index) then
	      n1 = 1
	    else
	      n1 = max(1.d0, min(d, DNINT((xmin-xstart)/xdelta)) )
	    endif
c********END MODIFICATIONS******************************************************
	    n2 = max(1.d0, min(d, DNINT((xmax-xstart)/xdelta)+2.d0) )
	  else
	    n1 = max(1.d0, min(d, DNINT((xmax-xstart)/xdelta)) )
	    n2 = max(1.d0, min(d, DNINT((xmin-xstart)/xdelta)+2.d0) )
	  endif
	  npts = n2-n1+1
	  if (npts .lt. 0) npts = 0
	  dbuf_ptr = Gx.lyr(n).ybuf.p + ((n1-1) * skip * 8)
	  xstart = xstart + xdelta*(n1-2)
	  do i = 1, npts
c********MODIFICATION DR #503517************************************************
	    if (Gx.index) then
	      xpoint(i) = i
	    else
	      xpoint(i) = xstart + i*xdelta
	    endif
c********END MODIFICATIONS******************************************************
	  enddo
	endif

	xptr.p = xpoint_ptr
	yptr.p = dbuf_ptr

	XPLOT_PREP = npts

	if (Gx.panxmin.gt.Gx.panxmax) then
	  Gx.panxmin = qmin
	  Gx.panxmax = qmax
	else
	  Gx.panxmin = min(Gx.panxmin, qmin)
	  Gx.panxmax = max(Gx.panxmax, qmax)
	endif

c
c calculate ordinate values (if any)
	if (npts.le.0) return

	ypoint_ptr = Gx.yptr.p
	if (Gx.lyr(n).cx) then
	  if (Gx.cmode.eq.1) then			! CX MAGNITUDE
	    call M$CVMAG(dbuf, ypoint, npts)
	  elseif (Gx.cmode.eq.2) then			! CX PHASE
	    if (Gx.plab.eq.25) then
	      call M$CVPHA(dbuf, ypoint, npts)
	      call M$VSMUL(ypoint, drad2cyc, ypoint, npts)
	    elseif (Gx.plab.ne.24) then
	      call M$CVPHA(dbuf, ypoint, npts)
	    else
	      call M$CVPHAD(dbuf, ypoint, npts)
	    endif
	  elseif (Gx.cmode.eq.3) then			! CX REAL
	    call M$VMOV(dbuf, skip, ypoint, 1, npts)
	  elseif (Gx.cmode.ge.6) then			! CX LOG
	    call M$CVMAG2(dbuf, ypoint, npts)
	  elseif (Gx.cmode.ge.4) then			! CX IMAG, I vs R
	    call M$VMOV(dbuf(2), skip, ypoint, 1, npts)
	  endif
	else
	  if (Gx.cmode.eq.5) then			! SCALAR I vs R
	    call M$VFILL(ypoint, 0.d0, npts)
	  elseif (Gx.cmode.eq.1 .or. Gx.cmode.ge.6) then! SCALAR MAG,LOGS
	    do i = 1, npts
	      ypoint(i) = abs(dbuf(i))
	    enddo
	  else						! SCALAR RE,IM,PH
	    ypoint_ptr = dbuf_ptr
	  endif
	endif
	
	if (Gx.cmode.ge.6) then
	  call M$VLOG10(ypoint, Gx.dbmin, ypoint, npts)
	  dbscale = 10.d0		! log multipliers for log mode
	  if (Gx.cmode.eq.7) dbscale = 20.d0
	  if (Gx.lyr(n).cx) dbscale = dbscale / 2.d0
	  call M$VSMUL(ypoint, dbscale, ypoint, npts)
	endif

	call M$VMXMN(ypoint, qmax, qmin, n1, n2, npts)
	if (Gx.panymin.gt.Gx.panymax) then
	  Gx.panymin = qmin
	  Gx.panymax = qmax
	else
	  Gx.panymin = min(Gx.panymin, qmin)
	  Gx.panymax = max(Gx.panymax, qmax)
	endif

	yptr.p = ypoint_ptr

	return
	end

c***********************************************************************
c
c  SCALE_BASE - this routine loads in 32K elements from the beginning
c  of all base files and scales the stack elements accordingly.  If
c  mode is 0 only the Y stk elements are set.  This is normally called
c  when plotting for the first time, or when changing to IR mode since
c  you are unable to specify the abscissa range over which to sample
c
c  Things done in this routine:
c    -1,0	32K elements loaded from the beginning of all base files
c      		elements loaded in from basexmin to basexmax
c    -1,0,1	panxmin and panxmax reset
c    -1,0,1,2	panxmin and panxmax updated
c    -1,0,1	Mx.stk(1).xmin and Mx.stk(1).xmax set from panxmin, panxmax
c    -1,0,1,2	panymin and panymax reset
c    0,1	panymin and panymax updated from lyr.xmin to lyr.xmax
c    2		panymin and panymax updated from basexmin to basexmax
c    -1,0,1,2	Mx.stk(1).ymin and Mx.stk(1).ymax set from panymin, panymax
c
c    -2	n elements loaded from basexmin to basexmax 
c    -2	panxmin and panxmax reset & updated, panymin and panymax reset
c    -2	panymin and panymax updated from lyr.xmin to lyr.xmax (slow)
c    -2	Mx.stk(1).ymin and Mx.stk(1).ymax set from panymin, panymax
c
c    -1	32K elements loaded from the beginning of all base files
c    -1	panxmin and panxmax reset & updated, panymin and panymax reset
c    -1	Mx.stk(1).xmin and Mx.stk(1).xmax set from panxmin, panxmax
c
c    0	32K elements loaded from the beginning of all base files
c    0	panxmin and panxmax reset & updated, panymin and panymax reset
c    0	Mx.stk(1).xmin and Mx.stk(1).xmax set from panxmin, panxmax
c    0	panymin and panymax updated from lyr.xmin to lyr.xmax (slow)
c    0	Mx.stk(1).ymin and Mx.stk(1).ymax set from panymin, panymax
c
c    1	panxmin and panxmax reset & updated, panymin and panymax reset
c    1	Mx.stk(1).xmin and Mx.stk(1).xmax set from panxmin, panxmax
c    1	panymin and panymax updated from lyr.xmin to lyr.xmax (slow)
c    1	Mx.stk(1).ymin and Mx.stk(1).ymax set from panymin, panymax
c
c    2  panxmin and panxmax reset & updated, panymin and panymax reset
c    2	panymin and panymax updated from basexmin to basexmax (slow)
c    2	Mx.stk(1).ymin and Mx.stk(1).ymax set from panymin, panymax
c    
c
c  mode 0: scale X and Y stk fetching first 32K from files regardless
c       1: scale X and Y but with data currently in buffers
c       2: scale only Y with data in buffers between basexmin and basexmax
c      -1: scale X and Y stk fetching first 32K from files but not forming
c	   any elements, this will still scale X but will not convert any
c	   y elements.  This is done when Y is specified on the command line.
c	   there is no need for that initial Y forming to occur.
c***********************************************************************

	subroutine SCALE_BASE (mode, xxmin, xxmax)

	include 'xplot.inc'
	integer*4 n, mode, x, y, npts
	logical*4 load, noxmin, noxmax
	real*8 xxmin, xxmax
	real*8 xran, yran, xmin, xmax, dpts
	record /M_PTR/ xptr, yptr

	load = IAND(mode,s_get_data) .ne. 0
	noxmin = IAND(mode,s_xmin) .eq. 0
	noxmax = IAND(mode,s_xmax) .eq. 0


	Gx.panxmin = 1.d0	! Flags to rescale pan bounds
	Gx.panxmax = -1.d0
	Gx.panymin = 1.d0
	Gx.panymax = -1.d0
	xmin = xxmin
	xmax = xxmax

	do n = 1, Gx.layers
	  if (noxmin) xmin = Gx.lyr(n).xmin
	  if (noxmax) xmax = Gx.lyr(n).xmax
	  if (load) call GET_DATA (n, xmin, xmax)
	  if (Gx.autox.gt.0 .or. Gx.autoy.gt.0) then
	    npts = XPLOT_PREP(n, xmin, xmax, xptr, yptr)
	  else 
	    npts = XPLOT_PREP(n, 1.d0, -1.d0, xptr, yptr)
	  endif
	enddo

	xran = Gx.panxmax - Gx.panxmin
	if (xran .lt. 0.d0) then
	  Gx.panxmax = Gx.panxmin
	  Gx.panxmin = Gx.panxmax + xran
	  xran = -xran
	endif
	if (xran .le. 1d-20) then
	  Gx.panxmin = Gx.panxmin - 1.d0	! X range too small
	  Gx.panxmax = Gx.panxmax + 1.d0
	endif
	if (IAND(Gx.autox,1).ne.0 .and. noxmin) Mx.stk(1).xmin = Gx.panxmin
	if (IAND(Gx.autox,2).ne.0 .and. noxmax) then
	  Mx.stk(1).xmax = Gx.panxmax
	  ! Trim range to Gx.bufmax points
	  if (.not. (Gx.all .or. Gx.xdata)) then 
	    do n = 1,Gx.layers
	      xmax = min (Gx.lyr(n).xmax , Mx.stk(1).xmax)
	      dpts = dabs((xmax-Gx.lyr(n).xmin)/Gx.lyr(n).xdelta) -
     &		Gx.bufmax + 1.d0
	      if (dpts.gt.0.d0)
     &		Mx.stk(1).xmax = xmax - dpts*dabs(Gx.lyr(n).xdelta)
	    enddo
	  endif
	endif

	yran = Gx.panymax - Gx.panymin
	if (yran .lt. 0.d0) then
	  Gx.panymax = Gx.panymin
	  Gx.panymin = Gx.panymax + yran
	  yran = -yran
	endif
	if (yran .le. 1d-20) then
	  Gx.panymin = Gx.panymin - 1.d0	! Y range too small
	  Gx.panymax = Gx.panymax + 1.d0
	else
	  Gx.panymin = Gx.panymin - .02*yran	! create a small margin
	  Gx.panymax = Gx.panymax + .02*yran
	endif
	if (IAND(Gx.autoy,1).ne.0) Mx.stk(1).ymin = Gx.panymin
	if (IAND(Gx.autoy,2).ne.0) Mx.stk(1).ymax = Gx.panymax

	return
	end



c**************************************************************
c
c  DRAW_LAYER - takes the layer specified by n, formats its data to the
c		proper mode by calling XPLOT_PREP and using the returned
c		pointers to X and Y double arrays, plots it to the 
c		screen by calling MX$TRACE
c
c  n		layer number to draw, the layer contains information
c		about line thickness, color, dot radius, etc.
c
c**************************************************************

	subroutine DRAW_LAYER (n)

	include 'xplot.inc'
	integer*4 n, ic, line, rad, symbol, npts, mask
	logical*4 segment
	real*8 xmin, xmax, xdelta, xran, x
	record /M_PTR/ xptr, yptr
	record /PIXSTRUCT/ pix(*)
	pointer (pix_ptr, pix)

	if (.not. Gx.lyr(n).display .or. Gx.hold.ne.0) return
	ic = Gx.lyr(n).color

	symbol = Gx.lyr(n).symbol
	rad = Gx.lyr(n).radius
	mask = 0
	if (Gx.lyr(n).line.eq.0) then
	  if (symbol.eq.0) return
	  line = 0
	  call MX$DRAW_MODE(0)
	else
	  line = 1
	  if (Gx.lyr(n).thick.ne.0) line = Gx.lyr(n).thick
	  if (Gx.lyr(n).line .eq. 1) mask = 2
	  if (Gx.lyr(n).line .eq. 2) mask = 4
	endif

	! Call TRACE_SEGMENT plotting routine if all of the following are true:
	!   1) The SEGMENT setting is set to TRUE
	!   2) We're not in R vs I mode
	!   3) The X data value is not the HEADER abscissa delta
	!   4) We are plotting connecting lines
	segment = (Gx.segment .and. Gx.cmode.ne.5 .and.
     &				Gx.lyr(n).xsub.gt.0 .and. mask.eq.0)

	xdelta = Gx.lyr(n).xdelta

	if (Gx.lyr(n).xdata) then		! X is in file data, could
	  xmin = Gx.lyr(n).xmin			! be anything!!!
	  xmax = Gx.lyr(n).xmax
	else					! X is from file header
	  xmin = max(Gx.lyr(n).xmin, Mx.stk(Mx.level).xmin)
	  xmax = min(Gx.lyr(n).xmax, Mx.stk(Mx.level).xmax)
	  if (xmin.ge.xmax) then		! No data, but do scaling
	    Gx.panxmin = min(Gx.panxmin, Gx.lyr(n).xmin)
	    Gx.panxmax = max(Gx.panxmax, Gx.lyr(n).xmax)
	  endif
	endif

	if (.not. Gx.all) then
	  xran = (Gx.bufmax - 1.d0) * xdelta
	  if (xran .ge. 0.d0) xmax = min(xmax, xmin + xran)
	  if (xran .lt. 0.d0) xmin = max(xmin, xmax + xran)
	endif

	do while (xmin .lt. xmax)
	  if (Gx.all) then
	    do while ( MX$IFEVENT() )
	      if (Gx.panning.ne.0 .and. Mx.button_release.ne.0) then
		Gx.panning = 0
	      elseif (Mx.resize) then
		call MX$PUTBACKEVENT()
		Gx.panning = 0
		return
	      elseif (Mx.button_press.eq.2 .or. Mx.key_upchar.eq.'M') then
		if (MX$MENU(1,'FILE READ;Continue,Stop').eq.2) xmax = xmin
	      endif
	    enddo
	  endif

	  call GET_DATA(n, xmin, xmax)
	  
	  npts = XPLOT_PREP(n, xmin, xmax, xptr, yptr)
	  if (npts.gt.0) then
	    call M$MALLOC(L_Pixstruct * npts, pix_ptr)
	    if (segment) then
	      ! NOTE: TRACE_SEGMENT relies on skip being 1, if this changes
	      ! it needs to be updated to handle it
	      call TRACE_SEGMENT(ic, %val(xptr.p), %val(yptr.p),
     &		npts, line, symbol, rad, pix, mask)
	    else
	      call MX$TRACE(ic, %val(xptr.p), %val(yptr.p),
     &		npts, 1, line, symbol, rad, pix, mask)
	    endif
	    call M$FREE(pix_ptr)
	  endif

	  if (Gx.all) then
	   if (Gx.lyr(n).size .eq. 0) then
	    xmin = xmax
	   else
	    if (xdelta .ge. 0.d0) then
	      xmin = xmin + (Gx.lyr(n).size * xdelta)
	    else
	      xmax = xmax + (Gx.lyr(n).size * xdelta)
	    endif
	   endif
	  else
	    xmin = xmax
	  endif
	enddo

	return
	end


c
c  This routine prevents lines being drawn between points in type 3000
c  files if the point has an X value less than the X of the preceding point
c  Handy for time oriented burst data where the bursts are not necessarily
c  placed in the file in time order.  Relies on skip being one.
c
	subroutine TRACE_SEGMENT (ic, x, y, npts, lin, sym, rad, pix, mask)
	include 'xplot.inc'
c Arguments
	integer*4 ic, npts, skip, lin, sym, rad, mask
	real*8 x(*), y(*)
	record /PIXSTRUCT/ pix(*)
c Locals
	integer*4 i	! index of current point
	integer*4 nplot	! number of points we haven't plotted yet

	nplot = 0
	do i = 1, npts-1
	  nplot = nplot + 1
	  if (x(i) .gt. x(i+1)) then
	    call MX$TRACE(ic, x(i-nplot+1), y(i-nplot+1),
     &		nplot, 1, lin, sym, rad, pix, mask)
	    nplot = 0
	  endif
	enddo
	nplot = nplot + 1	! add the last point, we only looped to npts-1
	call MX$TRACE(ic, x(npts-nplot+1), y(npts-nplot+1),
     &		nplot, 1, lin, sym, rad, pix, mask)

	return
	end


	subroutine TRIM_NAME (filename, target)

	implicit none
	include 'types.inc'
	character*(*) 	filename, target
	integer*4 	i, j

c trim name of path and extensions
	i = M$SEARCHB(filename, ']')
	if (i.eq.0) i = M$SEARCHB(filename, '/')
	if (i.eq.0) i = M$SEARCHB(filename, ':')
	j = M$SEARCH(filename(i+1:), '.') - 1
	if (j.lt.0) j = M$LENGTH(filename) - i
	target = filename(i+1:i+j)

	return
	end


c**************************************************************
c
c  GET_DATA - takes the HIN and the specified X bounds and creates
c		a buffer containing the requested data in its raw mode
c		straight from the file (XPLOT_PREP converts it to the
c		correct mode).  The buffer location, size offsets etc.
c		are set into a new Gx.lyr structure and the number of
c		layers is increased by one.  If the file is a type 2000
c		file then more than one layer may be added.
c
c**************************************************************

	subroutine GET_DATA (n, xmin, xmax)

	include 'xplot.inc'
	character*2 form
	integer*4 bufsize
	integer*4 npts, n, nframe, skip, h, i, xsub, ysub
	real*8 start, xmin, xmax, size, xstart, xdelta, imin, imax
	byte buf(*)
	real*8 xbuf(*), ybuf(*)
	pointer (buf_ptr, buf)
	pointer (xbuf_ptr, xbuf)
	pointer (ybuf_ptr, ybuf)

c get class and force reformat
	hcb_ptr = Gx.HCB(Gx.lyr(n).hcb).p
	skip = Gx.lyr(n).skip

	if (HCB.class .eq. 2) then
	  size = HCB.subsize
	else
	  size = HCB.size
	endif

	if (Gx.index) then
	  imin = DINT(xmin)
	  imax = DINT(xmax + 0.5d0)
	elseif (HCB.xdelta .ge. 0.d0) then
	  imin = 1.d0 + DINT((xmin-HCB.xstart)/HCB.xdelta)
	  imax = 1.d0 + DINT((xmax-HCB.xstart)/HCB.xdelta + 0.5d0)
	else
	  imin = 1.d0 + DINT((xmax-HCB.xstart)/HCB.xdelta)
	  imax = 1.d0 + DINT((xmin-HCB.xstart)/HCB.xdelta + 0.5d0)
	endif
	imin = max(1.d0, imin)
	imax = min(size, imax)
	npts = max(0.d0, min (imax-imin+1.d0, DBLE(Gx.bufmax)))
	if (HCB.xdelta.lt.0) imin = imax - npts + 1

	if (imin.ge.Gx.lyr(n).imin .and.
     &	    imin+npts .le. Gx.lyr(n).imin+Gx.lyr(n).size) then
	  ! data already in buffers
	elseif (n.eq.Gx.modlayer .and. Gx.modified) then
	  ! modified data not yet saved off
	  call MX$MESSAGE('Cannot read new buffer until current'//
     &		'file modifications are saved or undone', -1.0)
	elseif (HCB.class.le.2) then
	  ! load new data in for type 1000, 2000 files
	  start = Gx.lyr(n).offset + imin
	  Gx.lyr(n).ybufn = npts * max ( skip * 8, HCB.bpa )
	  call M$REMALLOC(Gx.lyr(n).ybufn, Gx.lyr(n).ybuf)
	  call M$GRAB(HCB, %val(Gx.lyr(n).ybuf.p), start, npts, -1)
	  Gx.lyr(n).imin = imin
	  Gx.lyr(n).xstart = HCB.xstart + (imin-1.d0) * Gx.lyr(n).xdelta
	  Gx.lyr(n).size = npts
	else
	  ! load new data in for type 3000, 5000, 6000 files
	  start = Gx.lyr(n).offset + imin
	  bufsize = npts * HCB.bpe
	  call M$MALLOC(bufsize, buf_ptr)
	  call M$GRAB(HCB, buf, start, npts, -1)
c TODO: If in Gx.all mode there could be some repeated transfers for the
c other layers from this file.
	  i = n
	  do while (i.le.Gx.layers .and. Gx.lyr(i).hcb.eq.Gx.lyr(n).hcb)
	    xsub = Gx.lyr(i).xsub
	    ysub = Gx.lyr(i).ysub
	    if (xsub.gt.0) then
	      Gx.lyr(i).xbufn = npts * 8
	      call M$REMALLOC(Gx.lyr(i).xbufn, Gx.lyr(i).xbuf)
	      xbuf_ptr = Gx.lyr(i).xbuf.p
	      call M$TRANSFER(HCB, buf, xsub, xbuf, npts, -1)
	      call M$REFORMAT(xbuf, M$SUB_FORMAT(HCB, xsub), xbuf, 'D', npts)
	    endif
	    if (ysub.gt.0) then
	      Gx.lyr(i).ybufn = npts * 8 * skip
	      call M$REMALLOC(Gx.lyr(i).ybufn, Gx.lyr(i).ybuf)
	      ybuf_ptr = Gx.lyr(i).ybuf.p
	      call M$TRANSFER(HCB, buf, ysub, ybuf, npts, -1)
	      call M$REFORMAT(ybuf, M$SUB_FORMAT(HCB, ysub), ybuf, 'D', npts)
	    endif
	    Gx.lyr(i).imin = imin
	    Gx.lyr(i).xstart = HCB.xstart + (imin-1.d0) * Gx.lyr(i).xdelta
	    Gx.lyr(i).size = npts
	    i = i + 1
	  enddo
	  call M$MFREE(bufsize, buf_ptr)
	endif

	return
	end	  



	subroutine MODIFY_OPEN (layer)

	include 'xplot.inc'
	character*80 filename
	character*512 menu
	integer*4 layer, n, i, lmenu

	if (Gx.all) then
	  call MX$MESSAGE ('Modify does not work with /ALL option', -1.0)
	elseif (Gx.modlayer .ne. 0) then
	  call MX$MESSAGE ('File already open for modification', 1.0)
	elseif (Gx.layers .eq. L_XPlotLayers) then
	  call MX$MESSAGE ('No layers available for modify', -1.0)
	elseif (Gx.nfiles.eq.0) then
	  call MX$MESSAGE ('File must be loaded using Overlay '//
     &			'before it can be opened for modifications', -1.0)
	else
	  if (layer.eq.-999) then
	    menu = 'MODIFY LAYER;'
	    lmenu = M$LENGTH(menu)
	    do n = 1, Gx.layers
	      i = M$LENGTH(Gx.lyr(n).name) + 1
	      menu(lmenu+1:lmenu+i) = Gx.lyr(n).name(1:i-1)//','
	      lmenu = lmenu + i
	    enddo
	    n = MX$MENU (0, menu(1:lmenu))
	  else
	    n = layer
	  endif
	  if (n.eq.0) return
	  hcb_ptr = Gx.HCB(Gx.lyr(n).hcb).p
	  if (HCB.class.le.2) then
	    filename = HCB.file_name(1:M$LENGTH(HCB.file_name))//
     &		HCB.qualifier(1:M$LENGTH(HCB.qualifier))
	    call LOAD_FILES (filename, -n, .true.)
	  else
	    call MX$MESSAGE('Modify mode available only for type '//
     &				'1000/2000 files.', -1.0)
	  endif
	endif

	return
	end


	subroutine MODIFY_DATA (mode)

	include 'xplot.inc'
	integer*4 L_bbuf
	parameter (L_bbuf=32)
	include 'buffers.inc'
	record /M_PTR/ bp, op, tp
	record /BUFFER/ out
	integer*4 mode, wid, widmed, npts, nbpa
	integer*4 i, ii, k, kk, i1, i2, nbytes, nput, ml, h
	logical*4 change
	real*8 d, d1, d2, zstart, zdelta, doff, a, b, x, f, f1, f2, VMEDIAN
	complex*16 CVMEDIAN

	if (Gx.modlayer.eq.0) then
	  call MX$MESSAGE ('Modify layer must be open for operation', 
     &                      -1.0)
	  return
	endif

c get some specs
 	ml     = Gx.modlayer
	hcb_ptr = Gx.HCB(Gx.lyr(ml).hcb).p
	zstart = Gx.lyr(ml).xstart 
	zdelta = Gx.lyr(ml).xdelta
	npts   = Gx.lyr(ml).size
	wid    = Gx.marks(5)
	nbpa   = Gx.lyr(ml).skip * 8
	bp.p   = Gx.lyr(ml).ybuf.p
	doff   = nbpa * (zstart - Gx.lyr(Gx.modsource).xstart) / zdelta
	op.p   = Gx.lyr(Gx.modsource).ybuf.p + DNINT(doff)


c write buffer to file
	change = .true.
	if (mode.lt.0) then
	  if (Gx.modified) then
	    npts = Gx.lyr(ml).size
	    nbytes = npts * HCB.dbpe
	    doff = DNINT((zstart-HCB.xstart)/HCB.xdelta)
	    doff = Gx.lyr(ml).offset + doff
	    if (Gx.index) doff = Gx.lyr(ml).offset + zstart - 1.d0
	    doff = HCB.first_byte + doff*HCB.dbpe
	    call M$REFORMAT (%val(bp.p), HCB.format(1:1)//'D', 
     &		%val(bp.p), HCB.format(2:2), npts)
	    call M$FWRITE (HCB, %val(bp.p), doff, nbytes, nput)
	    if (nput.ne.nbytes)
     &		call MX$MESSAGE ('Error writing buffer to file', -1.0)
	    call M$REFORMAT (%val(bp.p),HCB.format,%val(bp.p),'D',npts)
	    call M$MOVE (%val(bp.p), %val(op.p), Gx.lyr(ml).ybufn)
	  endif

c undo buffer
	elseif (mode.eq.0) then
	  if (Gx.modified) 
     &		call M$MOVE (%val(op.p), %val(bp.p), Gx.lyr(ml).ybufn)

	elseif (Gx.cmode.eq.5) then
	  call MX$MESSAGE ('Modify not supported in Real/Imag mode',
     &                      -1.0)
	  change = .false.

c
c single point modify
	else
	  k = Mx.level
	  if (Gx.nmark.eq.2) then
	    if (Gx.marks(1).gt.Gx.marks(3)) then
	      i = Gx.marks(1)
	      Gx.marks(1) = Gx.marks(3)
	      Gx.marks(3) = i
	      i = Gx.marks(2)
	      Gx.marks(2) = Gx.marks(4)
	      Gx.marks(4) = i
	    endif

	    d1 = Mx.stk(k).xmin + (Gx.marks(1)-Mx.stk(k).x1)*Mx.stk(k).xscl
	    d2 = Mx.stk(k).xmin + (Gx.marks(3)-Mx.stk(k).x1)*Mx.stk(k).xscl
	    i1 = max(0.d0, DNINT((d1-zstart)/zdelta))
	    i2 = min(npts-1.d0, DNINT((d2-zstart)/zdelta))
	  else
	    if (Gx.nmark.eq.1) then 
	      d1 = Mx.stk(k).xmin + (Gx.marks(1)-Mx.stk(k).x1)*Mx.stk(k).xscl
	    else
	      d1 = Gx.retx
	    endif
	    i1 = NINT((d1-zstart)/zdelta)
	    i2 = i1
	  endif

	  if (i1.ge.npts .or. i2.lt.0) then
	    call MX$MESSAGE('Point(s) out of range', -1.0)
	    change = .false.

	  elseif (mode.eq.1) then
	    if (Gx.nmark.le.0) then
	      f = Gx.marks(2)
	      if (Gx.nmark.eq.0) f = Mx.ypos
	      call MODVAL (Gx.cmode, f, %val(bp.p+i1*nbpa), 
     &			%val(bp.p+i1*nbpa), Gx.lyr(ml).skip)
	    elseif (d1 .eq. d2) then
	      call MX$MESSAGE('Region given infinite slope',-1.0)
	      change = .false.
	    else
	      f1 = Gx.marks(2)
	      f2 = Gx.marks(4)
	      a = (f2-f1)/(d2-d1)
	      b = f1 - a*(d1-zstart)
	      do i = i1, i2
		x = i*zdelta
		f = a*x + b
		call MODVAL (Gx.cmode, f, %val(bp.p+i*nbpa), 
     &			%val(bp.p+i*nbpa), Gx.lyr(ml).skip)
	      enddo
	    endif
	  elseif (mode.eq.2) then
	    widmed = wid/2
	    do i = i1, i2
	      ii = max(0, i-widmed)
	      kk = min(npts-ii, wid)
	      if (Gx.lyr(ml).cx) then
		call M$CVBLK (%val(op.p+ii*nbpa), out, kk, kk)
		out.cdbuf(1) = out.cdbuf(1)/kk
	      else
		call M$VBLK(%val(op.p+ii*nbpa), out, kk, kk)
		out.dbuf(1) = out.dbuf(1)/kk
	      endif
	      call M$MOVE(out, %val(bp.p+i*nbpa), nbpa)
	    enddo
	  elseif (mode.eq.3) then
	    call M$MALLOC(nbpa*wid, tp)
	    widmed = wid/2
	    do i = i1, i2
	      ii = max(0, i-widmed)
	      kk = min(npts-ii, wid)
	      if (Gx.lyr(ml).cx) then
		out.cdbuf(1) = CVMEDIAN(%val(op.p+ii*nbpa), %val(tp.p), kk)
	      else
		out.dbuf(1) = VMEDIAN(%val(op.p+ii*nbpa), %val(tp.p), kk)
	      endif
	      call M$MOVE(out, %val(bp.p+i*nbpa), nbpa)
	    enddo
	    call M$FREE(tp)
	  endif
	endif

	if (change) then
	  Gx.modified = (mode.gt.0)
	  call XPLOT_REFRESH (2)
	endif

	return
	end


	real*8 function VMEDIAN (dbuf, tbuf, npts)
	implicit none
	real*8 dbuf(*), tbuf(*), dval
	integer*4 npts, i, j
	tbuf(1) = dbuf(1)
	do i = 2, npts
	  tbuf(i) = dbuf(i)
	  do j = i-1, 1, -1
	    if (tbuf(j).gt.tbuf(j+1)) then
	      dval = tbuf(j)
	      tbuf(j) = tbuf(j+1)
	      tbuf(j+1) = dval
	    endif
	  enddo
	enddo
	VMEDIAN = tbuf(max(1,npts/2))
	return
	end

	complex*16 function CVMEDIAN (cdbuf, tbuf, npts)
	implicit none
	complex*16 cdbuf(*), tbuf(*), cdval
	integer*4 npts, i, j
	tbuf(1) = cdbuf(1)
	do i = 2, npts
	  tbuf(i) = cdbuf(i)
	  j = i - 1
	  do while (j.gt.0)
	    if (abs(tbuf(j)).gt.abs(tbuf(j+1))) then
	      cdval = tbuf(j)
	      tbuf(j) = tbuf(j+1)
	      tbuf(j+1) = cdval
	      j = j - 1
	    else
	      j = 0
	    endif
	  enddo
	enddo
	CVMEDIAN = tbuf(max(1,npts/2))
	return
	end

	subroutine MODVAL (cmode, y, f, g, spa)

	implicit none
	include 'xprimitive.inc'
	include 'constants.inc'
	real*8 f(*), g(*), a, y, b, p
	integer*4 k, spa, cmode

	k = Mx.level
	if (Mx.origin .gt. 2) then
	  a = Mx.stk(k).ymin + (y - Mx.stk(k).y1) * Mx.stk(k).yscl
	else
	  a = Mx.stk(k).ymin + (Mx.stk(k).y2 - y) * Mx.stk(k).yscl
	endif

	if (spa.eq.1) then
	  if (cmode .lt. 5) then
	    f(1) = a
	  else
	    if (cmode.eq.7) a = 0.5d0*a
	    f(1) = 10.d0**(0.1d0*a)
	  endif

	else
	  if (cmode .eq. 2) then		! phase
	    b = sqrt( g(1)*g(1) + g(2)*g(2) )
	    p = a * deg2rad
	    f(1) = b * cos(p)
	    f(2) = b * sin(p)
	  elseif (cmode .eq. 3) then		! real
	    f(1) = a
	  elseif (cmode .eq. 4) then		! imag
	    f(2) = a
	  else					! mag, logs
	    p = 0.
	    if (g(1).ne.0.0 .or. g(2).ne.0.0) p = atan2(g(2), g(1))
	    b = a
	    if (cmode.eq.7) b = 0.5d0*b
	    if (cmode.ge.6) b = 10.d0**(0.1d0*b)
	    f(1) = b * cos(p)
	    f(2) = b * sin(p)
	  endif
	endif

	return
	end

c**************************************************************************
c
c  LOAD_FILES - this routine takes a file name (which may include a list 
c  of files) opens the file, and initializes the necessary data layer
c  structures. If this is the first set of files to be plotted the special
c  BASEFILE routine is called to set some of the plotting display parameters
c  such as the xlabel, ylabel, plotnote, xstart, xdelta (used to determine 
c  the index coordinates in DISPLAY_SPECS). If type is negative, it indicates 
c  a ModifyFile and the abs(type) is the source layer which will be modified.
c
c  type	0: CommandLineFiles; load in main file header(s) from command line
c	1: OverlayFiles; load in overlay file header(s)
c     < 0: ModifyFile; load in file header for read/write data modifications
c
c**************************************************************************

	subroutine LOAD_FILES (name, type, noabort)

	include 'xplot.inc'

	record /T6SUBR_STRUCT/     t6subr
	character*(*) name
	character trimname*12, csub*4, qual*40, fc, xformat*2, yformat*2
	integer*4 i, lq, j, type, ibar, ipar
	integer*4 n, nf, k, n1, n2, nfiles, newlayer, h
	integer*4 xsub, ysub
	integer*4 istart, CmdLineFile, OverlayFile, RereadFile
	parameter (CmdLineFile=0, OverlayFile=1, RereadFile=2)
	logical*4 basefiles, dum, noabort
	real*8 d, size
	integer*4 mask

	ibar = 1
	istart = 1

	basefiles = (Gx.nfiles .eq. 0) .or. (type.eq.RereadFile)
	do while (ibar.ne.0 .and. Gx.layers.lt.L_XPlotLayers)
	  h = Gx.nfiles + 1
	  call M$MALLOC(L_header_size, Gx.HCB(h).p)
	  hcb_ptr = Gx.HCB(h).p
	  call M$INITIALIZE(HCB)
	  if (type.eq.RereadFile) then
	    if (h.lt.L_XPlotLayers) then
	      if (Gx.filestring(h+1).eq.' ') ibar = 0
	    endif
	  else
	    Gx.filestring(h) = name(istart:)
	    ibar = M$SEARCH(name(istart:), '|')		! prune off |'d files
	    if (ibar.gt.0) Gx.filestring(h)(ibar:) = ' '
	    istart = istart + ibar
	  endif
	  HCB.file_name = Gx.filestring(h)
	  ipar = M$SEARCH(HCB.file_name, '(')
	  if (ipar.eq.0) then
	    HCB.qualifier = ' '
	    csub = M$RFIND (HCB.file_name, HCB.file_name, d)
	  else					! process qualifiers
	    HCB.qualifier = HCB.file_name(ipar:)
	    HCB.file_name(ipar:) = ' '
	    csub = M$RFIND (HCB.file_name, HCB.file_name, d)
	    ipar = M$LENGTHQ(HCB.file_name)
	    HCB.file_name = HCB.file_name(1:ipar)//
     &		HCB.qualifier
	  endif
	  HCB.format_allow = 'S#, C#, NH'
	  HCB.switch = ' '
	  if (noabort) HCB.switch = 'NOABORT'
	  HCB.type_allow = '1000, 2000, 3000, 5000, 6000'
	  if (type.ge.0) call M$INOK (HCB)
	  if (type.lt.0) call M$INOKW (HCB)
	  if (HCB.open) then
	    size = HCB.size
	    if (HCB.pipe.ne.0) call M$WARNING
     &		('XPLOT not coded for piped data - use XRTPLOT')
	    if (HCB.class.le.2) then
	      call M$FORCE1000 (HCB)
	      HCB.buf_type = 'D'
	    endif
	    if (HCB.xdelta .eq. 0.d0) then
	      call M$WARNING ('File has 0.0 X abscissa delta, using 1.d0')
	      HCB.xdelta = 1.d0
	    endif
	    Gx.nfiles = h
	    if (Gx.nfiles.eq.1) call BASEFILE (.true.)

c initialize data layer structures
	    call TRIM_NAME (HCB.file_name, trimname)
	    newlayer = Gx.layers + 1
	    n1 = 1
	    n2 = 1
	    if (HCB.class .eq. 2) then
	      if (type.lt.0) then	! Find the correct 2000 modify layer 
		do i = 2, -type
		  if (Gx.lyr(i).hcb .eq. Gx.lyr(i-1).hcb) n1 = n1 + 1
		  if (Gx.lyr(i).hcb .ne. Gx.lyr(i-1).hcb) n1 = 1
		enddo
		n2 = n1
	      else
		i = INT(HCB.size) / HCB.subsize
		n2 = min(i, L_XPlotLayers-Gx.layers)
	      endif
	    elseif (HCB.class.ge.3) then
	      lq = M$GET_UQUALIFIER(HCB, 'X', qual)
	      if (lq.le.0) then
		xsub = M$SUB_FIND(HCB, 'ABSC')
		if (xsub.eq.0) xsub = M$SUB_FIND(HCB, 'TIME')
	      elseif (qual(1:1).eq.'~') then
		xsub = M$SUB_FIND(HCB, qual(2:lq))
		if (xsub.eq.0)
     &		  call M$WARNING('Could not find subrecord '//qual(2:lq))
	      elseif (M$A2D(qual(1:lq),d).gt.0) then
		xsub = d
	      else
		xsub = 0
		call M$WARNING('Could not translate (X='//qual(1:lq)//')')
	      endif
	      if (xsub.le.0 .or. xsub.gt.HCB.subrecords) xsub = -1
	      if (xsub.gt.0) then
		if (HCB.class .eq.6) then
		  call M$GET_T6SUBRECORD(HCB, xsub, t6subr)
		  t6subr.format(1:1) = 'S'
		  call M$PUT_T6SUBRECORD(HCB, xsub, t6subr)
		else
		  HCB.subr(xsub).format(1:1) = 'S'
		endif
		xformat = M$SUB_FORMAT(HCB, xsub)
		if (M$SEARCH('DFLIB',xformat(2:2)).eq.0) then
		  call M$WARNING('Non-supported data type for X subrecord')
		  xsub = -1
		endif
	      endif
		  
c TODO: Allow multiple layers from the same 3000 file with a comma separated
c list of Y qualifiers (Y=~POS,~ORD,~RF) etc.
	      lq = M$GET_UQUALIFIER(HCB, 'Y', qual)
	      if (lq.le.0) then
		ysub = M$SUB_FIND(HCB, 'ORD')
	      elseif (qual(1:1).eq.'~') then
		ysub = M$SUB_FIND(HCB, qual(2:lq))
		if (ysub.eq.0)
     &		  call M$WARNING('Could not find subrecord '//qual(2:lq))
	      elseif (M$A2D(qual(1:lq),d).gt.0) then
		ysub = d
	      else
		ysub = -1
		call M$WARNING('Could not translate (Y='//qual(1:lq)//')')
	      endif
	      if (ysub.le.0 .or. ysub.gt.HCB.subrecords) ysub = 1
	      yformat = M$SUB_FORMAT(HCB, ysub)
	      if (M$SEARCH('DFLIB',yformat(2:2)).eq.0) then
		call M$ERROR('Non-supported data type for Y subrecord')
	      elseif (yformat(1:1).ne.'C') then
		if (HCB.class .eq.6) then
		  call M$GET_T6SUBRECORD(HCB, ysub, t6subr)
		  t6subr.format(1:1) = 'S'
		  call M$PUT_T6SUBRECORD(HCB, ysub, t6subr)
		else
		  HCB.subr(ysub).format(1:1) = 'S'
		endif
	      endif
	      ! Note; the 'yformat' variable may not match the subrecord
	      ! format at this point

#ifdef MAYBELATERTOSPEEDTHINGSUP
	      ! Note; this '#ifdef' section of code has not been updated
	      ! to support Type 6000 files since I did not want to test
	      ! code that dosen't exist!! - cew
	      call M$INITIALIZE(HCBT)
	      i = 0
	      do i = 1, HCB.records
	      if (xsub.gt.0) then
		i = i + 1
		HCBT.subr(i) = HCB.subr(xsub)
		HCBT.subr(i).form = 'S'//HCB.subr(xsub).format(2:2)
		HCBT.subrecords = i
	      endif
	      if (ysub.gt.0) then
		i = i + 1
		HCBT.subr(i) = HCB.subr(ysub)
		if (HCBT.subr(i).format(1:1).ne.'C')
     &		  HCBT.subr(i).form = 'S'//HCB.subr(ysub).format(2:2)
		HCBT.subrecords = i
	      endif
#endif
	    endif

	    do i = n1, n2
	      n = Gx.layers + 1
	      if (HCB.class .eq. 2) then
		write(csub, '(1h., i3.3)') i
		Gx.lyr(n).name    = trimname(1:M$LENGTH(trimname))//csub
		Gx.lyr(n).offset  = (i-1)*HCB.subsize
		size = HCB.subsize
	      else
		Gx.lyr(n).name    = trimname
		Gx.lyr(n).offset  = 0.d0
		if (HCB.class.eq.1) size = HCB.size
	      endif
	      Gx.lyr(n).hcb     = h
	      Gx.lyr(n).size    = 0
	      Gx.lyr(n).xbuf.p  = 0
	      Gx.lyr(n).xbufn   = 0
	      Gx.lyr(n).ybuf.p  = 0
	      Gx.lyr(n).ybufn   = 0
	      if (HCB.class.le.2) then
		Gx.lyr(n).xsub = -1
		Gx.lyr(n).ysub = 1
		Gx.lyr(n).cx = (HCB.format(1:1) .eq. 'C')
	      else
		Gx.lyr(n).xsub = xsub
		Gx.lyr(n).ysub = ysub
		yformat = M$SUB_FORMAT(HCB, ysub)
		Gx.lyr(n).cx = (yformat(1:1) .eq. 'C')
	      endif
	      Gx.lyr(n).skip = 1
	      if (Gx.lyr(n).cx) Gx.lyr(n).skip = 2
	      if (Gx.index) then
		Gx.lyr(n).xstart  = 1.d0
		Gx.lyr(n).xdelta  = 1.d0
		Gx.lyr(n).xmin    = 1.d0
		Gx.lyr(n).xmax    = size
	      else
		Gx.lyr(n).xstart  = HCB.xstart
		Gx.lyr(n).xdelta  = HCB.xdelta
		d = HCB.xstart + HCB.xdelta*(size - 1.d0)
		Gx.lyr(n).xmin    = min (HCB.xstart, d)
		Gx.lyr(n).xmax    = max (HCB.xstart, d)
	      endif
	      Gx.layers = n
	    enddo

	    if (type.lt.0) then
	      if (Gx.modmode .eq. 0) Gx.modmode = 1
	      Gx.modlayer = Gx.layers
	      Gx.modsource = -type
	      Gx.modified = .false.
	    endif
	    if (.not.Gx.all .and. size.gt.Gx.bufmax) call M$WARNING 
     &	('Plot truncated to buffer size. Use panning or /ALL switch')
	    if (.not.basefiles) then
	      ! The next call updates the .xdata fields then returns without
	      ! doing anything else because Gx.cmode is not being changed. The
	      ! xdata fields (of which there is one in each layer and a global
	      ! one set to true if any of the layers are true) signify if the
	      ! X axis data is data from disk (TRUE), or derived from the
	      ! abscissa information in the header (FALSE).  This depends on
	      ! the current data transformation mode. and then returns because
	      ! Gx.cmode is not being changed.
	      call XPLOT_CHANGEMODE(Gx.cmode)

	      call DRAW_ACCESSORIES (-5)
	      do n = newlayer, Gx.layers
		call DRAW_LAYER (n)
	      enddo
	      call FORM_PLOTNOTE
	      call DRAW_ACCESSORIES (5)
	    endif
	  else
	    if (Gx.nfiles.eq.0) call BASEFILE (.false.)
	    do n = Gx.nfiles+1, L_XPlotLayers-1
	      Gx.filestring(n) = Gx.filestring(n+1)
	    enddo
	    Gx.filestring(L_XPlotLayers) = ' '
	    n = M$LENGTHQ(HCB.file_name)
	    if (type.eq.CmdLineFile) then
	      call M$WARNING ('Could not open file '//
     &			HCB.file_name(1:n))
	    elseif (HCB.file_name .ne. ' ') then
	      call MX$MESSAGE ('Could not open file '//
     &			HCB.file_name(1:n),-1.0)
	    endif
	    call M$MFREE(L_header_size, hcb_ptr)
	  endif
	enddo

	if (ibar.ne.0 .and. Gx.layers.eq.L_XPlotLayers) then
	  if (type.eq.CmdLineFile) then
	    call M$WARNING  ('Not enough layers to open file '//name)
	  else
	    call MX$MESSAGE ('Not enough layers to open file '//name,
     &                        -1.0)
	  endif
	endif
	if (Gx.nfiles.lt.L_XPlotLayers) Gx.filestring(Gx.nfiles+1) = ' '

	if (basefiles) then
	  Gx.basemode = Gx.cmode
	  if (type.ne.CmdLineFile) then
	    mask = s_get_data
	    if (IAND(Gx.autox,1).eq.0) mask = mask + s_xmin
	    if (IAND(Gx.autox,2).eq.0) mask = mask + s_xmax
	    call SCALE_BASE(mask, Gx.xmin, Gx.xmax)
	    Mx.level = 1
	    if (IAND(Gx.autox,1).ne.0) Gx.xmin = Mx.stk(1).xmin
	    if (IAND(Gx.autox,2).ne.0) Gx.xmax = Mx.stk(1).xmax
	    if (IAND(Gx.autoy,1).ne.0) Gx.ymin = Mx.stk(1).ymin
	    if (IAND(Gx.autoy,2).ne.0) Gx.ymax = Mx.stk(1).ymax
	    Mx.resize = .true.
	  endif
	endif
	call FORM_PLOTNOTE

	return
	end

	subroutine FORM_PLOTNOTE ()

	include 'xplot.inc'
	character*(L_XPlotNote) note
	integer*4 i, j, n, nn, ib

	if (Gx.nfiles .eq. 0) then
	  Gx.note = ' '
	elseif (M$GET_KEYWORD(%val(Gx.HCB(1).p),
     &		'PLOTNOTE',Gx.note) .le. 0) then
	  ib = 0
	  j = 0
	  note = ' '
	  do n = 1, Gx.nfiles
	    i = min (M$LENGTHQ(Gx.filestring(n)), L_XPlotNote-ib)
	    if (i.gt.0) then
	      if (n.gt.1) note(ib+1:ib+1) = '|'
	      if (n.gt.1) ib = ib + 1
	      note(ib+1:) = Gx.filestring(n)(1:i)
	      ib = ib + i
	    endif
	  enddo

          !  Check to see if the '(' and ')' are unbalanced 
          !  This can cause a problem with the PS processing
          !  This can occur if the note was truncated and it
          !  contained an opening '(' but the closing one was
          !  part of the truncated text.
          if (M$SEARCHB(note, '(') .gt. M$SEARCHB(note, ')')) then 
             note(M$LENGTH(note):M$LENGTH(note)) = ')' 
          endif

	  Gx.note = note
	  if (j.ne.0) call M$LOWERCASE (note)
	  if (j.ne.0) Gx.note(j:L_XPlotNote) = note(j:L_XPlotNote)
	endif
	return
	end


	function XPLOT_MSG ()

	include 'xplot.inc'
	include 'qmessdef.inc'
	include 'qmessdecl.inc'
	character*2 cxm(7) /'MA', 'PH', 'RE', 'IM', 'IR', 'LO', 'L2'/
	character*3 fac /'BPA'/
	logical*4 xpan, ypan, echo
	integer*4 i, info, sid, mimic, msgid
	integer*4 lin, thk, sym, rad, color

	XPLOT_MSG = .false.

	do while (.not. Mx.breakflag)

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

	  XPLOT_MSG = .true.
	  info = MQH.info
	  sid = MQH.sender
	  msgid = Gx.xf.msgid
	  mimic = Gx.mimic

	  Gx.xf.iarg = MQH.info
	  Gx.xf.mqdloc.p = %loc(MQD)
	
	  if (Gx.cross .and. MQH.name.ne.MQH_QUERY.name) call TOGGLE_CROSS()
	  ! Do not echo actions caused by an id to that id, unless MSK_ECHO 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

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

	  elseif (MQH.name(1:3).eq.'BOX' .or.
     &		  MQH.name(1:5).eq.'POINT' .or.
     &		  MQH.name.eq.MQH_ANNOTATE.name) then
	    if (MQH.name .eq. MQH_ANNOTATE.name) then
	      call FACILITIES('A', 3)
	    elseif (MQH.name .eq. MQH_BOXDELETE.name .or.
     &		MQH.name .eq. MQH_POINTDELETE.name) then
	      call FACILITIES (MQH.name(1:1), 4)
	    else
	      i = 2
	      if (info .le. -1) i = L_OneShot
	      if (MQH.name .eq. MQH_BOXADD.name) Gx.xf.iarg = Gx.xf.nbox+1
	      if (MQH.name .eq. MQH_POINTADD.name) Gx.xf.iarg = Gx.xf.npoint+1
	      if (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) 
     &		call FACILITIES (MQH.name(1:1), i)
	    endif

	  elseif (MQH.name .eq. MQH_COLOR.name) then
	    if (info.lt.0) info = max (0, Gx.layers+info+1)
	    if (info .ge. 1 .and. info .le. L_XPlotLayers) then
	      i = MQD.COLOR.position
	      if (Gx.lyr(info).display) then
		if (i .ge. 0) then
		  call MX$COLORTAB (Gx.lyr(info).color, Mc.colormap(4), i)
		else
		  call MX$COLORTAB (Gx.lyr(info).color, MQD.COLOR, -2)
                endif
                if (Mx.exposure) call XPLOT_REFRESH( 2 )  ! RDA: static color change
	      endif
	      call MSGDO (MSK_COLOR, info)
	    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 DISPLAY_SPECS
	    call MSGDO (MSK_MARK, Mx.level)

	  elseif (MQH.name .eq. MQH_CXMODE.name) then
	    do i = 1,7
	      if (MQD.CXMODE.mode .eq. cxm(i) .and. i.ne.Gx.cmode) then
		if (i.ne.5 .or. .not.Gx.index) call XPLOT_CHANGEMODE (i)
	      endif
	    enddo

	  elseif (MQH.name .eq. MQH_DEOVERLAY.name) then
	    call DEOVERLAY (info)

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

	    if (MX$HARDCOPY_OPEN(MQD.HARDCOPY.file, MQH.info)) then
	      call XPLOT_REFRESH (1)
	      call MX$HARDCOPY_CLOSE ()
	    endif

	  elseif (MQH.name .eq. MQH_NEWFILE.name) then
	    i = MQD.NEWFILE.arg1
	    if (i .eq. 0) then
	      call DEOVERLAY(0)
	      call LOAD_FILES(MQD.NEWFILE.filename, 1, .true.)
	      if (Mx.resize) call XPLOT_REFRESH(2)
	      if (info.gt.0) call MODIFY_OPEN(info)
	    elseif (i.ge.1 .and. i.le.3) then
	      call FACILITIES(fac(i:i), 6)
	    endif

	  elseif (MQH.name .eq. MQH_OVERLAY.name) then
	    call LOAD_FILES (MQD.OVERLAY.text, 1, .true.)
	    if (Mx.resize) call XPLOT_REFRESH (2)

	  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
	      Mx.stk(Mx.level).ymin = MQD.PAN.ymin
	      Mx.stk(Mx.level).ymax = MQD.PAN.ymax
	    endif
	    if (xpan .or. ypan) then
	      if (xpan) then
		call MSGDO (MSK_PANX, Mx.level)
	      else
		call MSGDO (MSK_PANY, Mx.level)
	      endif
	      call XPLOT_REFRESH (1)
	    endif

	  elseif (MQH.name .eq. MQH_PANRANGE.name) then
	    if (MQD.PANRANGE.xmin .lt. MQD.PANRANGE.xmax) then
	      Gx.panxmin = MQD.PANRANGE.xmin
	      Gx.panxmax = MQD.PANRANGE.xmax
	    endif
	    if (MQD.PANRANGE.ymin .lt. MQD.PANRANGE.ymax) then
	      Gx.panymin = MQD.PANRANGE.ymin
	      Gx.panymax = MQD.PANRANGE.ymax
	    endif
	    call DRAW_PANBARS ()

	  elseif (MQH.name .eq. MQH_REFRESH.name) then
	    Gx.hold = 0
	    call XPLOT_REFRESH (1)

	  elseif (MQH.name .eq. MQH_REREAD.name) then
	    call XPLOT_CLEANUP
	    call LOAD_FILES (' ', 2, .true.)
	    call XPLOT_REFRESH (2)

	  elseif (MQH.name .eq. MQH_SET.name .or. 
     +		  MQH.name .eq. MQH_SETD.name) then
	    if (MQH.name .eq. MQH_SETD.name) info = MQD.SETD.value
	    i = (M$SEARCH('ALL     ,BS      ,BUF     ,CONTROLS,CROSS   ,'//
     +			  'GRID    ,HOLD    ,INDEX   ,LEGEND  ,MIMIC   ,'//
     +			  'MSGID   ,PAN     ,PLABEL  ,SECTIONS,SEGMENT ,'//
     +			  'SPECS   ,XDIV    ,XLABEL  ,YDIV    ,YINV    ,'//
     +			  'YLABEL  ,',
     +				MQD.SET.object(1:8)//',') + 8) / 9

	    if (i.eq.t_mimic) then
	      mimic = info
	    elseif (i.ne.0) then
	      call SETTINGS(i, info)
	    elseif (MQD.SET.object(1:4) .eq. 'ANNT' .or.
     +	    	    MQD.SET.object(1:3) .eq. 'BOX' .or.
     +	    	    MQD.SET.object(1:5) .eq. 'POINT') then
	      call FACILITIES(MQD.SET.object(1:1), 5)
	    elseif (MQD.SET.object .eq. 'AUTO') then
	      if (info.ge.0 .and. info.le.3) then
		Gx.autoy = info
		if (Gx.autoy.eq.0) then
		  Gx.ymin = Mx.stk(1).ymin
		  Gx.ymax = Mx.stk(1).ymax
		endif
	      endif
	    elseif (MQD.SET.object .eq. 'AUTOX') then
	      if (info.ge.0 .and. info.le.3) then
		Gx.autox = info
		if (Gx.autox.eq.0) then
		  Gx.xmin = Mx.stk(1).xmin
		  Gx.xmax = Mx.stk(1).xmax
		endif
	      endif
	    elseif (MQD.SET.object .eq. 'HOLD') then
	      Gx.hold = info
	      Mx.exposure = .true.
	    endif
	    if (Mx.resize)   call XPLOT_REFRESH (2)
	    if (Mx.exposure) call XPLOT_REFRESH (0)

	  elseif (MQH.name .eq. MQH_TRACE.name) then
	    if (info.lt.0) info = max(1, info+Gx.layers+1)
	    info = min(info, L_XPlotLayers)
	    lin = Gx.lyr(max(1,info)).line
	    thk = Gx.lyr(max(1,info)).thick
	    sym = Gx.lyr(max(1,info)).symbol
	    rad = Gx.lyr(max(1,info)).radius
	    color = Gx.lyr(max(1,info)).color
	    call MX$TRACE_MSG(MQD, lin, thk, sym, rad, color)
	    call XPLOT_TRACE(info, lin, thk, sym, rad, color)

	  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 MSGDO (MSK_UNZOOM, Mx.level)
	      call XPLOT_REFRESH (0)
	    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
		Mx.stk(i).ymin = MQD.ZOOM.ymin
		Mx.stk(i).ymax = MQD.ZOOM.ymax
	      else
		Mx.stk(i).ymin = Mx.stk(Mx.level).ymin
		Mx.stk(i).ymax = Mx.stk(Mx.level).ymax
	      endif
	      Mx.level = i
	      call MSGDO (MSK_ZOOM, Mx.level)
	      call XPLOT_REFRESH (1)
	    endif
	  endif

	  Gx.xf.msgid = msgid
	  Gx.mimic = mimic
	  if (Gx.cross .and. MQH.name.ne.MQH_QUERY.name) call TOGGLE_CROSS()

	enddo

	return
	end


	function XPLOT_PAN (action,flag)

	include 'xplot.inc'
	include 'xwidgets.inc'
	character*(*) action
	integer*4 i, k, ih, iw, imin, imax, flag, j
	real*8 xmin, xmax, xran, xtemp, ymin, ymax, yran, ytemp
	logical*4 warn
	record /SCROLLBAR/ sbx,sby

	XPLOT_PAN = .false.
	k = Mx.level
	if (Gx.panmode.gt.0) then
	  sbx.flag = 11
	  sby.flag = 11
	else
	  sbx.flag = -12
	  sby.flag = -12
	endif
	if (flag.eq.0) then
	  sbx.action = 0
	  sby.action = 0
	endif
							 
	warn = .true.
	if (action(1:1) .eq. 'Y') then
	  ymin = Mx.stk(k).ymin
	  ymax = Mx.stk(k).ymax
	  yran = ymax - ymin
	  if (action.eq.'YPAN') then
	    i = MX$SCROLLBAR(sby, Gx.pyl, Gx.pyl+Gx.pthk, Gx.t, Gx.b,
     &			      ymin, ymax, Gx.panymin, Gx.panymax)
C TODO: Warn only if Scrollbar arrow is pressed and no movement.
	    if (sby.action.ne.0) then
	      Gx.panning = 2
	      j = MX$SCROLL(sby, XW_UPDATE)
	    else
	      Gx.panning = 0
	    endif
	    warn = .false.
	  elseif (action.eq.'YCENTER') then
	    ymin = ymin - yran * (Mx.ypos - (Gx.t+Gx.b)/2) / (Gx.b-Gx.t)
	    ymax = ymin + yran
	    warn = .false.
	  endif

	  if (ymin.ne.Mx.stk(k).ymin .or. ymax.ne.Mx.stk(k).ymax) then
	    Mx.stk(k).ymin = ymin
	    Mx.stk(k).ymax = ymax
	    if (Gx.cmode.eq.Gx.basemode .and. Mx.level.eq.1) then
	      Gx.ymin = min (Gx.ymin, ymin)
	      Gx.ymax = max (Gx.ymax, ymax)
	    endif
	    call XPLOT_REFRESH (1)
	    call MSGDO (MSK_PANY, Mx.level)
	    XPLOT_PAN = .true.
	  elseif (warn) then
	    call MX$MESSAGE('All panned out', -1.0)
	  endif

	else
	  xmin = Mx.stk(k).xmin
	  xmax = Mx.stk(k).xmax
	  xran = xmax - xmin
	  if (action.eq.'XPAN') then
	    i = MX$SCROLLBAR(sbx, Gx.pl, Gx.pr, Gx.pt, Gx.pt+Gx.pthk,
     &			      xmin, xmax, Gx.panxmin, Gx.panxmax)
C TODO: Warn only if Scrollbox arrow is pressed and no movement.
	    if (sbx.action.ne.0) then
	      Gx.panning = 1
	      j = MX$SCROLL(sbx, XW_UPDATE)
	    else
	      Gx.panning = 0
	    endif
	    warn = .false.
	  elseif (action.eq.'XCENTER') then
	    xmin = xmin + xran*(Mx.xpos - (Gx.l+Gx.r)/2)/(Gx.r-Gx.l)
	    if (xmin .ne. Mx.stk(k).xmin) xmax = xmin + xran
	    warn = .false.
	  endif

	  if (Mx.stk(k).xmin.ne.xmin .or. Mx.stk(k).xmax.ne.xmax) then
	    Mx.stk(k).xmin = xmin
	    Mx.stk(k).xmax = xmax
	    if (.not. Gx.xdata .and. Mx.level.eq.1) then
	      Gx.xmin = Mx.stk(1).xmin
	      Gx.xmax = Mx.stk(1).xmax
	    endif
	    call XPLOT_REFRESH (1)
	    call MSGDO (MSK_PANX, Mx.level)
	    XPLOT_PAN = .true.
	  elseif (warn) then
	    call MX$MESSAGE('All panned out', -1.0)
	  endif
	endif

	return
	end

	subroutine BASEFILE (open)

	include 'xplot.inc'
	logical*4 open
	real*8 size

	if (Gx.index) then
	  Gx.xstart = 1.d0
	  Gx.xdelta = 1.d0
	elseif (open) then
	  hcb_ptr = Gx.HCB(1).p
	  Gx.xstart = HCB.xstart
	  Gx.xdelta = HCB.xdelta
	else
	  Gx.xstart = 0.d0
	  Gx.xdelta = 1.d0
	endif

	if (.not. open) Gx.lyr(1).cx = .false.

	return
	end

c*******************************************************************
c
c 1. Get needed data
c 2. Reset pan variables
c 3. Reset stack variables
c  
c    NON-IR -> IR or (BASEMODE.EQ.5 and IR -> NON-IR)
c	1. GRAB first 32K from each file
c	if (newmode.eq.basemode)
c	  3. stk <- base
c	else
c	  2. Form for pan
c	  3. stk <- pan
c	endif
c
c    IR -> NON-IR
c	1. GRAB data from basexmin to basexmax
c	if (mode.eq.BASEMODE) then
c	  3. stk <- base
c	else
c	  2. Form for pan.y
c	  3a. stk.x <- base.x
c	  3b. stk.y <- pan.y
c	endif
c
c    NON-IR -> NON-IR
c	if (log to log) then
c	  3b. stk.y <- stk.y * fact
c	elseif (mode.eq.BASEMODE) then
c	  3b. stk.y <- base.y
c	else
c	  2. Form for pan.y
c	  3b. stk.y <- pan.y
c	endif
c
c
c*******************************************************************

	subroutine XPLOT_CHANGEMODE (newmode)

	include 'xplot.inc'
	integer*4 n, newmode, oldmode, autox, autoy
	real*8 fact 

	Gx.xdata = .false.
	do n = 1, Gx.layers
	  if (newmode.eq.5) then
	    Gx.lyr(n).xdata = .true.
	  else
	    Gx.lyr(n).xdata = (Gx.lyr(n).xsub .gt. 0)
	  endif
	  if (Gx.lyr(n).xdata) Gx.xdata = .true.
	enddo

	if (newmode.eq.Gx.cmode) then
	  return

	elseif (newmode.eq.5 .and. Gx.index) then
	  call MX$MESSAGE ('Imag/Real mode not permitted in /INDEX mode',
     &                      -1.0)

	elseif (Gx.layers.le.0) then
	  Gx.cmode = newmode

	elseif (newmode.gt.0) then
	  oldmode = Gx.cmode
	  Gx.cmode = newmode

	  autox = Gx.autox		! Temporarily turn on auto scaling
	  autoy = Gx.autoy		! for non-basemode cx mode scaling
	  Gx.autox = 3
	  Gx.autoy = 3

					! IR to NON-IR or NON-IR to IR
	  if (newmode.eq.5 .or. oldmode.eq.5) then
	    Gx.panxmin = 1.d0		! Flags to rescale X and Y pan bounds
	    Gx.panxmax = -1.d0
	    Gx.panymin = 1.d0
	    Gx.panymax = -1.d0
	    Mx.level = 1

	    if (newmode.eq.Gx.basemode) then
	      Mx.stk(1).xmin = Gx.xmin
	      Mx.stk(1).xmax = Gx.xmax
	      Mx.stk(1).ymin = Gx.ymin
	      Mx.stk(1).ymax = Gx.ymax
	    elseif (newmode.eq.5 .or. Gx.basemode.eq.5) then
	      call SCALE_BASE(s_get_data, 0.d0, 0.d0)
	    else			! basemode NON-IR
	      Mx.stk(1).xmin = Gx.xmin
	      Mx.stk(1).xmax = Gx.xmax
	      call SCALE_BASE(s_get_data+s_xmin+s_xmax, Gx.xmin, Gx.xmax)
	    endif
							  ! LOG to LOG
	  elseif (newmode.ge.6 .and. oldmode.ge.6) then
	    if (oldmode.eq.6) fact = 2.d0	! Get Y from existing stacks by
	    if (oldmode.eq.7) fact = 0.5d0	! multiplying or dividing by 2
	    Gx.panymin = Gx.panymin * fact
	    Gx.panymax = Gx.panymax * fact
	    do n = 1, Mx.level
	      Mx.stk(n).ymin = Mx.stk(n).ymin * fact
	      Mx.stk(n).ymax = Mx.stk(n).ymax * fact
	    enddo

	  else						! NON-IR to NON-IR
	    if (newmode.eq.Gx.basemode) then	! Get y from base
	      Gx.panymin = 1.d0		! Flag to rescale pan y bounds
	      Gx.panymax = -1.d0
	      Mx.stk(1).ymin = Gx.ymin
	      Mx.stk(1).ymax = Gx.ymax
	    else
	      call SCALE_BASE(s_xmin+s_xmax,
     &		Mx.stk(Mx.level).xmin, Mx.stk(Mx.level).xmax)
	    endif
	    do n = 2, Mx.level			! Set new Y's into all levels
	      Mx.stk(n).ymin = Mx.stk(1).ymin
	      Mx.stk(n).ymax = Mx.stk(1).ymax
	    enddo
	  endif
	  Gx.autox = autox
	  Gx.autoy = autoy
	  call MSGDO(MSK_CXMODE, Mx.level)
	  call XPLOT_REFRESH(2)

	endif

	return
	end

c******************************************************************
c
c  XPLOT_CLEANUP - called upon exiting X-Plot, this routine checks 
c  for unresolved file modifications, frees up allocated memory, 
c  closes all open files and closes the window and its connection 
c  to the server.
c
c******************************************************************

	subroutine XPLOT_CLEANUP 

	include 'xplot.inc'
	integer*4 n
	logical*4 breakflag

	if (Gx.modified) then			! save modifications
	  if (.not. Mc.break) then
	    breakflag = Mx.breakflag
	    Mx.breakflag = .false.
	    if (MX$MENU(2,'SAVE MODIFICATIONS?;Yes,No').eq.1) then
	      call MODIFY_DATA (-1)
	    endif
	    Mx.breakflag = breakflag
	  endif
	  Gx.modified = .false.
	  Gx.modsource = 0
	  Gx.modlayer = 0
	endif

	do n = 1, Gx.layers				! free up raw buffers
	  call M$MFREE(Gx.lyr(n).ybufn, Gx.lyr(n).ybuf)
	  call M$MFREE(Gx.lyr(n).xbufn, Gx.lyr(n).xbuf)
	enddo
	Gx.layers = 0
	Gx.xdata = .false.

	call M$MFREE(Gx.pointbufsize, Gx.xptr)	! free up point buffers
	call M$MFREE(Gx.pointbufsize, Gx.yptr)
	Gx.xptr.p = 0
	Gx.yptr.p = 0
	Gx.pointbufsize = 0


	do n = 1, Gx.nfiles				! close files
	  call M$CLOSE(%val(Gx.HCB(n).p))
	  call M$MFREE(L_header_size, Gx.HCB(n).p)
	enddo
	Gx.nfiles = 0
	Mx.level = 1

	return
	end


	subroutine DEOVERLAY (index)

	include 'xplot.inc'
	integer*4	index, n

	if (Gx.nfiles .gt. 0) then	! index < 0, remove top overlay
	  if (index .lt. 0) then
	    n = Gx.nfiles + index + 1
	    if (n.le.0) return
	    call DEOVERLAY_FILE (n)
	  elseif (index.gt.0) then	! index > 0, remove overlay # index
	    if (index.gt.Gx.nfiles) return
	    call DEOVERLAY_FILE (index)
	  else				! index = 0, remove all overlays
	    if (Gx.nfiles.eq.0) return
	    do n = Gx.nfiles, 1, -1
	      call DEOVERLAY_FILE (n)
	    enddo
	  endif
	  call XPLOT_REFRESH (1)
	endif
	return
	end



	subroutine DEOVERLAY_FILE (index)

	include 'xplot.inc'
	include 'qmessdef.inc'
	integer*4	index
	character*80	answer
	integer*4	n,i,ic,topbs,ms,red,green,blue
	record /XPLOTLAYER/ lyr
	record /MQD_COLORINFO/ color(L_XPlotLayers)

	if ((index .gt. 0) .and. (index .le. Gx.nfiles)) then
	  if (Gx.modsource .gt. 0) then
	    ms = Gx.lyr(Gx.modsource).hcb
	    if (index.eq.ms .or. index.eq.Gx.lyr(Gx.modlayer).hcb) then
	      if (Gx.modified) then
		n = MX$MENU (2, 'FILE MODIFICATIONS;Save,Undo') - 2
		if (n.eq.-1 .or. index.eq.ms) call MODIFY_DATA (n)
	      endif
	      Gx.modlayer = 0
	      Gx.modsource = 0
	      Gx.modified = .false.
	    endif
	  endif
	  call M$CLOSE(%val(Gx.HCB(index).p))
	  call M$MFREE(L_header_size, Gx.HCB(index).p)
	  do n = index, Gx.nfiles - 1
	    Gx.HCB(n) = Gx.HCB(n+1)
	    Gx.filestring(n) = Gx.filestring(n+1)
	  enddo
	  Gx.filestring(Gx.nfiles) = ' '
	  Gx.nfiles = Gx.nfiles - 1

c cleanup

	  topbs = L_XPlotLayers + 1
	  do n = Gx.layers, 1, -1
	    if (Gx.lyr(n).hcb .gt. index) then
	      Gx.lyr(n).hcb = Gx.lyr(n).hcb - 1
	    elseif (Gx.lyr(n).hcb .eq. index) then
	      if (n.lt.Gx.modlayer) Gx.modlayer = Gx.modlayer - 1
	      if (n.lt.Gx.modsource) Gx.modsource = Gx.modsource - 1
	      if (Gx.lyr(n).display) topbs = n
	      call M$MFREE(Gx.lyr(n).ybufn, Gx.lyr(n).ybuf)
	      Gx.lyr(n).ybufn = 0
	      Gx.lyr(n).ybuf.p = 0
	      if (n .lt. Gx.layers) then
		lyr = Gx.lyr(n)
		do i = n, Gx.layers-1
		  Gx.lyr(i) = Gx.lyr(i+1)
		enddo
		Gx.lyr(Gx.layers) = lyr
	      endif
	      Gx.layers = Gx.layers - 1
	    endif
	  enddo
	  do n = 1, L_zoommax
	    if (topbs.le.Gx.bslyr(n)) Gx.bslyr(n) = 0
	  enddo
	  call FORM_PLOTNOTE()
	  if (Gx.nfiles.gt.0) then
	    Gx.panxmin = 1.d0
	    Gx.panxmax = -1.d0
	    Gx.panymin = 1.d0
	    Gx.panymax = -1.d0
	  endif

	endif
	return
	end

	subroutine XPLOT_MAINMENU ()

	include 'xplot.inc'
	include 'qmessdef.inc'
	character answer*80, menu*512
	integer*4 i, n, lmenu, mode, item, mitem, iauto, xpos, ypos
	integer*4 optmask
	logical*4 redraw
	record /MQD_COLORINFO/ color(L_XPlotLayers), tc
	real*8 dtemp
	external XPLOT_SETTINGS

	item = MX$MENU (0,'X-PLOT;Refresh,Cntrls...,CX Mode...,'//
     &		'Scaling...,Grid,Settings...,Color...,Traces...,'//
     &		'Files...,Modify...,Boxes,Points,Annotate,Spawn...,'//
     &		'Keypress Info,Exit')

	if (item.eq.1) then				! refresh
	  call XPLOT_REFRESH (1)

	elseif (item.eq.2) then       		! controls option
	  call SETTINGS (t_cntrls, -999)

	elseif (item.eq.3) then			! change complex mode
	  mode = MX$MENU (Gx.cmode,'COMPLEX MODE;Magnitude,'//
     &		'Phase,Real,Imaginary,IR:Imag/Real,10*Log10,20*Log10')
	  if (mode.ne.Gx.cmode) call XPLOT_CHANGEMODE (mode)

	elseif (item.eq.4) then			! auto scaling
	  mitem = 1
	  xpos = Mx.xpos
	  ypos = Mx.ypos

	  do while (mitem.ne.0 .and. .not.Mc.break .and. .not.Mx.breakflag)
	    menu = 'SCALING;Y Axis ,'//
     &		   '  Parameters...,  Min Auto     ,'//
     &		   '  Max Auto     ,  Full Auto    ,'//
     &		   'X Axis         ,'//
     &		   '  Parameters...,  Min Auto     ,'//
     &		   '  Max Auto     ,  Full Auto,'

	    n = M$SEARCH(menu,',')
	    i = (1 + Gx.autoy)*n + 1
	    menu(i:i) = '+'
	    i = (6 + Gx.autox)*n + 1
	    menu(i:i) = '+'

	    Mx.xpos = xpos
	    Mx.ypos = ypos
	    mitem = MX$MENU(0, menu)

	    if (mitem.ge.2 .and. mitem.le.5) then
	      iauto = mitem - 2
	      if (iauto.eq.0) then
		Gx.ymin = Mx.stk(1).ymin
		Gx.ymax = Mx.stk(1).ymax
		call MX$DPROMPT('Y Axis Min: ', Gx.ymin)
		call MX$DPROMPT('Y Axis Max: ', Gx.ymax)
		if (Mx.stk(1).ymin .ne. Gx.ymin .or.
     &		    Mx.stk(1).ymax .ne. Gx.ymax) then
		  Mx.stk(1).ymin = Gx.ymin
		  Mx.stk(1).ymax = Gx.ymax
		  if (Mx.level.eq.1) Mx.resize = .true.
		  Gx.bslyr(1) = 0
		endif
	      endif
	      Gx.autoy = iauto
	    
	    elseif (mitem.ge.7 .and. mitem.le.10) then
	      iauto = mitem - 7
	      if (iauto.eq.0) then
		Gx.xmin = Mx.stk(1).xmin
		Gx.xmax = Mx.stk(1).xmax
		call MX$DPROMPT('X Axis Min: ', Gx.xmin)
		call MX$DPROMPT('X Axis Max: ', Gx.xmax)
		if (Mx.stk(1).xmin .ne. Gx.xmin .or.
     &		    Mx.stk(1).xmax .ne. Gx.xmax) then
		  Mx.stk(1).xmin = Gx.xmin
		  Mx.stk(1).xmax = Gx.xmax
		  if (Mx.level.eq.1) Mx.resize = .true.
		  Gx.bslyr(1) = 0
		endif
	      endif
	      Gx.autox = iauto
	    endif
	  enddo

	elseif (item.eq.5) then			! toggle grid
	  call SETTINGS (t_grid, -1)

	elseif (item.eq.6) then			! settings

	  optmask = 0
	  if (Gx.all) optmask = IBSET (optmask,t_all)
	  if (Gx.cross) optmask = IBSET (optmask,t_cross)
	  if (Gx.grid) optmask = IBSET (optmask,t_grid)
	  if (Gx.index) optmask = IBSET (optmask,t_index)
	  if (Gx.legend) optmask = IBSET (optmask,t_legend)
	  if (Gx.pan) optmask = IBSET (optmask,t_pan)
	  if (Gx.segment) optmask = IBSET (optmask,t_segment)
	  if (Gx.specs) optmask = IBSET (optmask,t_specs)
	  if (Mx.origin.gt.2) optmask = IBSET (optmask,t_yinv)
	  if (Gx.hold.ne.0) optmask = IBSET (optmask,t_hold)

	  optmask = MX$MENUPLUS(optmask, 'SETTINGS;#ALL Mode,Backing '//
     +	   'Store...,BUF Max Size...,Controls...,#CROSShairs,#GRID,'//
     +	   '#Hold,#INDEX Mode,#LEGEND,MIMIC...,MSGID...,#PAN Scroll'//
     +	   'bars,PHase UNITS...,Sections...,#SEGMENT Lines,#SPECS,'//
     +	   'XDIVisions...,XLABel...,YDIVisions...,#YINVersion,YLABel...', 
     +		L_CBautomask, L_CBenable, XPLOT_SETTINGS)

	elseif (item.eq.7) then			! change colormap
	  call MX$COLORTAB (0, color, -3)
	  call MX$COLORTAB (Gx.lyr(1).color, Mc.colormap(4), -1)
	  do n = 1, L_XPlotLayers
	    if (n .eq. Gx.lyr(n).color) then
	      call MX$COLORTAB (n, tc, -3)
	      if (tc.red.ne.color(n).red .or. tc.green.ne.color(n).green
     &		  .or. tc.blue.ne.color(n).blue) call MSGDO (MSK_COLOR, n)
	    endif
	  enddo

	elseif (item.eq.8) then			! change linetype
	  menu = 'TRACE;All,'
	  lmenu = M$LENGTH(menu)
	  do n = 1, L_XPlotLayers
	    if (n.le.Gx.layers) then
	      i = M$LENGTH(Gx.lyr(n).name) + 1
	    else
	      i = M$L2A(n, Gx.lyr(n).name) + 1
	    endif
	    menu(lmenu+1:lmenu+i) = Gx.lyr(n).name(1:i-1)//','
	    lmenu = lmenu + i
	  enddo
	  n = MX$MENU (0, menu(1:lmenu)) - 1
	  if (n.ge.0) call XPLOT_TRACE(n, -999, 0, 0, 0, 0)

	elseif (item.eq.9) then			! overlay
	  mitem = MX$MENU (0, 'FILES OPTIONS;'//
     &		'Overlay File...,Deoverlay File...,Reread All')
	  if (mitem.eq.1) then
	    answer = ' '
	    if (MX$FILES(answer) .gt. 0) then
	      i = M$CLEAN (answer, answer)
	      call LOAD_FILES (answer(1:i-1), 1, .true.)
	    endif
	  elseif (mitem.eq.2 .and. Gx.nfiles.gt.0) then	! deoverlay
	    menu = 'DEOVERLAY;All Files,'
	    lmenu = M$LENGTH(menu)
	    do n = 1, Gx.nfiles
	      i = M$LENGTHQ(Gx.filestring(n))
	      if (i.gt.29) then
		menu(lmenu+1:lmenu+30) = Gx.filestring(n)(1:26)//'..., '
		lmenu = lmenu + 30
	      else
		menu(lmenu+1:lmenu+i+1) = Gx.filestring(n)(1:i)//', '
		lmenu = lmenu + i + 1
	      endif
	    enddo
	    n = MX$MENU (0, menu(1:lmenu)) - 1
	    if (n.ge.0) call DEOVERLAY (n)

	  elseif (mitem.eq.3 .and. Gx.nfiles.gt.0) then
	    call XPLOT_CLEANUP
	    call LOAD_FILES (' ', 2, .true.)
	    call XPLOT_REFRESH (2)
	  endif

	elseif (item.eq.10) then
	  mitem = MX$MENU(Gx.modmode, 'MODIFY;'//
     &		'ASSIGN,AVERAGE,MEDIAN,Open...,Undo,Save,Width...')
	  if (Gx.all) then
	    call MX$MESSAGE('Modify does not work with /ALL option', 
     &                       -1.0)

	  elseif (mitem.le.3) then		! change modify mode
	    Gx.modmode = mitem

	  elseif (mitem.eq.4) then		! open file for modify
	    call MODIFY_OPEN(-999)

	  elseif (mitem.eq.5) then	! undo
	    call MODIFY_DATA (0)

	  elseif (mitem.eq.6) then	! save to file
	    call MODIFY_DATA (-1)

	  elseif (mitem.eq.7) then	! change window width
	    call MX$LVAL ('Scope Width: ', Gx.marks(5), 1, 100, 2, 0)
	  endif


	elseif (item.ge.11 .and. item.le.13) then	! boxes,pts,annt modes
	  answer = 'BPA'
	  call FACILITIES (answer(item-10:item-10), L_Interactive) 

	elseif (item.eq.14) then			! spawn
	  answer = ' '
	  call MX$PROMPT('Spawn Command: ', answer)
	  i = M$LENGTH(answer)
	  if (i.gt.0) call M$DISPATCH(answer(1:i), LD_smart, -1)

	elseif (item.eq.15) then			! keypress info
	  call MX$MHELP ('X-PLOT', 'Keypress Info')

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

	return
	end


c*****************************************************************************
c This routine processes one event and returns.  It is located in the main
c program and is called only when MX$QUEUED > 0.  Certain events may cause
c a refresh to be necessary.  Throughout this is indicated by setting
c Mx.resize to true.  At the end of the routine, this flag, and the Mx.resize
c flag are checked (since a resize would cause the screen to blank out) and
c if either is set XPLOT_REFRESH is called.  This also enables us to catch any
c exposes or resizes that might have occurred while X-Widgets were up since
c they will set the Mx.exposure and Mx.resize fields when they detect
c such events.  These fields do not get cleared until we call MX$EVENT again.
c***************************************************************************** 

	subroutine XPLOT_EVENTLOOP ()

	include 'xplot.inc'
	integer*4 i, ixo, iyo, ixl, iyl, tw, th, x, y, ls, isec
	logical*4 junk
	character*40 cspec
	character*12 command
	character*(L_max_ascii) psfile
	integer*4		lpsfile
	external DISPLAY_SPECS

	tw = Mx.text_w
	th = Mx.text_h
	Gx.panning = 0

	if (Gx.cross) call TOGGLE_CROSS ()

	call MX$EVENT ()

  10	if (Mx.motion_notify) then			! mouse moved
	  call DISPLAY_SPECS
	  if (Gx.cntrls.eq.2) then
	    call M$DRSLT (Mx.xtag, Gx.retx)
	    call M$DRSLT (Mx.ytag, Gx.rety)
	    call M$LRSLT (Mx.ztag, Gx.isec)
	  endif
							! pan/zoom/menu
	elseif (Mx.button_press .ne. 0) then
	  ! this is the panning box section
	  x = Mx.xpos
	  y = Mx.ypos
	  command = ' '

	  if (Gx.pan) then
	    if (x.gt.Gx.r .and. y.ge.Gx.t .and. y.le.Gx.b) then
	      command = 'YPAN'				! Y scrollbar
	      Mx.xpos = Gx.pyl + Gx.pthk/2
	      Gx.panning = 2

	    elseif (x.ge.Gx.pl .and. x.le.Gx.pr) then
	      if ((Gx.specs .and. y.gt.Gx.pt-2) .or. 
     &		 (.not. Gx.specs .and. y.le.Gx.pt+Gx.pthk+2)) then
		command = 'XPAN'				! X scrollbar
		Mx.ypos = Gx.pt + Gx.pthk/2
		Gx.panning = 1
	      endif
	    endif
	  endif

	  if (command .ne. ' ') then			! pan
	    junk = XPLOT_PAN (command,0)

	  elseif (Mx.button_press .eq. 2) then		! main menu
	    call XPLOT_MAINMENU

	  elseif (Mx.button_press.eq.3) then 		! unzoom/expand
	    if (Mx.level.gt.1) then
	      Mx.level = Mx.level-1
	      Mx.exposure = .true.
	      call MSGDO (MSK_UNZOOM, Mx.level)
	    endif

	  elseif (Gx.legend .and. x.ge.Gx.lmap.x .and.  y.ge.Gx.lmap.y .and.
     &	    x.le.Gx.lmap.x+Gx.lmap.w .and. y.le.Gx.lmap.y+Gx.lmap.h) then

	    if (Gx.layers.gt.0) then
	      i = 1 + (y - Gx.lmap.y - Mx.text_h*.3) / Mx.text_h
	      i = max(1, min(i, Gx.layers))
	      call XPLOT_TRACE(i, -999, 0, 0, 0, 0)
	    endif

	  elseif (x.ge.Mx.width-Gx.lbtn .and. y.le.Gx.lbtn) then
	    call SETTINGS (t_legend, -1)

	  else			  ! this is the click/mark/zoom section
	    call MX$RUBBERBOX (ixo, iyo, ixl, iyl, DISPLAY_SPECS)
	    if (Mx.button_release.ne.1) then
	    elseif ((ixl-ixo).lt.5 .or. (iyl-iyo).lt.5) then
	      if (x .lt. Gx.l-2*tw .and. y .le. Gx.b .and. y .ge. Gx.t) then
		junk = XPLOT_PAN ('YCENTER',0)		! Y centering
	      elseif ( y .gt. Gx.b+tw .and. y .le. Gx.b+3*th/2 .and.
     &		       x .ge. Gx.l .and. x .le. Gx.r ) then
		junk = XPLOT_PAN ('XCENTER',0)		! X centering
	      else
		call DISPLAY_SPECS		! set origin
		Gx.xmrk = Gx.retx
		Gx.ymrk = Gx.rety
		if (Gx.cntrls.eq.1) then
		  call M$DRSLT (Mx.xtag, Gx.xmrk)
		  call M$DRSLT (Mx.ytag, Gx.ymrk)
		  call M$LRSLT (Mx.ztag, Gx.isec)
		endif
		call MSGDO (MSK_MARK, Mx.level)
		call DISPLAY_SPECS
		if (Gx.modlayer.ne.0) then	! set mark
		  if (Gx.nmark.eq.2) then
		    call MX$RUBBERDOT (Gx.marks(1), Gx.marks(2), -2)
		    call MX$RUBBERDOT (Gx.marks(3), Gx.marks(4), -2)
		    Gx.nmark = 0
		  else
		    Gx.marks(Gx.nmark*2+1) = Mx.xpos
		    Gx.marks(Gx.nmark*2+2) = Mx.ypos
		    call MX$RUBBERDOT (Mx.xpos, Mx.ypos, -2)
		    Gx.nmark = Gx.nmark+1
		  endif
		endif
	      endif
	    elseif (Mx.level.eq.L_stack) then
	      call MX$MESSAGE ('No more stack levels for zooming', 1.0)
	    else
	      i = Mx.level			! perform zoom
	      Mx.stk(i+1).xmin = Mx.stk(i).xmin + 
     &		(ixo - Mx.stk(i).x1) * Mx.stk(i).xscl
	      Mx.stk(i+1).xmax = Mx.stk(i).xmin + 
     &		(ixl - Mx.stk(i).x1) * Mx.stk(i).xscl
	      if (Gx.sections.ne.0) then
		isec = max(0,min(Gx.nsec-1,((iyl+iyo)/2-Gx.t)/Gx.iysec))		
		iyl =  max(iyl,Gx.t+isec*Gx.iysec) - isec*Gx.iysec
		iyo =  min(iyo,Gx.t+(isec+1)*Gx.iysec) - isec*Gx.iysec
	      endif
	      if (Mx.origin .gt. 2) then
		Mx.stk(i+1).ymin = Mx.stk(i).ymin + 
     &			(iyo - Mx.stk(i).y1) * Mx.stk(i).yscl
		Mx.stk(i+1).ymax = Mx.stk(i).ymin + 
     &			(iyl - Mx.stk(i).y1) * Mx.stk(i).yscl
	      else
		Mx.stk(i+1).ymin = Mx.stk(i).ymin + 
     &			(Mx.stk(i).y2 - iyl) * Mx.stk(i).yscl
		Mx.stk(i+1).ymax = Mx.stk(i).ymin + 
     &			(Mx.stk(i).y2 - iyo) * Mx.stk(i).yscl
	      endif
	      Mx.level = i+1
	      call MSGDO (MSK_ZOOM, Mx.level)

	      Mx.exposure = .true.
	    endif
	  endif

							! oneshot boxes/points

	elseif (Mx.key_upchar.eq.'B' .or. Mx.key_upchar.eq.'P') then
	  call FACILITIES (Mx.key_upchar, L_OneShot)

	elseif (Mx.key_upchar.eq.'H') then 		! hardcopy
	  psfile = 'xplot'
	  if (MX$HARDCOPY_OPEN(psfile,-1)) then
	    call XPLOT_REFRESH (1)
	    call MX$HARDCOPY_CLOSE ()
	  endif

	elseif (Mx.key_upchar.eq.'L') then 		! toggle legend
	  call SETTINGS (t_legend, -1)

	elseif (Mx.key_upchar.eq.'M') then		! menu
	  call XPLOT_MAINMENU ()

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

	elseif (Mx.key_upchar.eq.'S') then 		! toggle specs
	  call SETTINGS (t_specs, -1)

	elseif (Mx.key_upchar.eq.'T') then		! timecode
	  call DISPLAY_SPECS
	  hcb_ptr = Gx.HCB(1).p
	  i = M$SEC2TOD(HCB.timecode+Gx.retx, cspec)
	  call MX$MESSAGE('Time = '//cspec(1:i), -1.0)

	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
	  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. 'A') then	! abscissa mode
	  Gx.iabsc = mod(Gx.iabsc+1, 4)
	  call DISPLAY_SPECS

	elseif (Mx.key_upchar.eq.'C') then      ! toggle Gx.cntrls
	  call SETTINGS (t_cntrls, -Gx.cntrls)

	elseif (Mx.key_upchar .eq. '?') then	! main help
	  call MX$MHELP('X-PLOT', 'Primitive')
 
	elseif (Mx.key_upchar.eq.'J') then	! modify option (do) 
	  call MODIFY_DATA (Gx.modmode)

	elseif (Mx.key_upchar.eq.'U') then	! modify option (undo) 
	  call MODIFY_DATA (0)

	elseif (Mx.key_press .eq. 13 .and. Mx.noexit.le.0) then ! the END
	  Mx.breakflag = .true.
	endif

	if (Mx.resize) call XPLOT_REFRESH (2)
	if (Mx.exposure) call XPLOT_REFRESH (0)
	if (Gx.cross) call TOGGLE_CROSS ()

	if ( Gx.panning .ne. 0 ) then
	  i = Mx.button_press
	  x = 1
	  do while (x.le.6 .and. Mx.button_release.eq.0)
	    call M$PAUSE(0.05)
	    junk = MX$IFEVENT()
	    x = x + 1
	  enddo
	  do while ( Gx.panning.ne.0 .AND. Mx.button_release.eq.0 )
	    Mx.button_press = i
	    junk = XPLOT_PAN (command,1)
	    junk = MX$IFEVENT()
	  enddo
	endif

	return
	end


	subroutine MSGDO (bit, iarg)
	include 'xplot.inc'
	integer*4 bit, iarg

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

	subroutine INFOMSG (bit, iarg, rid)

	include 'xplot.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 = Gx.isec
	  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 = 0
	      if (Gx.nfiles.gt.0) then
		hcb_ptr = Gx.HCB(1).p
		MQD.PLOTINFO.xunits = HCB.xunits
	      endif
	      if (Gx.xlab.ge.0) 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 = 0
		if (Gx.layers.gt.0) then
		  d = min (Gx.lyr(1).xmax, Mx.stk(i).xmax)
		  d = (d-max(Gx.lyr(1).xmin,Mx.stk(i).xmin))/Gx.lyr(1).xdelta
		  MQD.PLOTINFO.xframe = max (0, NINT(d))
		endif
		MQD.PLOTINFO.yframe = Gx.layers
		MQD.PLOTINFO.primname = 'XPLOT'
		call M$SEND_MSG (MQH_PLOTINFO, MQD.PLOTINFO, rid, 0)
	      endif
	    endif
	  endif
	endif

	return
	end

	subroutine SETTINGS (flag, v)
	include 'xplot.inc'
	record /CBSTRUCT/ cb
	integer*4 flag, v, status
	cb.item = flag
	cb.value = v
	cb.mode = 0
	if (v.eq.-999) cb.mode = L_CBenable
	call XPLOT_SETTINGS (cb)
	return
	end

	subroutine XPLOT_SETTINGS (cb)
	include 'xplot.inc'
	record /CBSTRUCT/ cb
	integer*4 v, i, k, item
	logical*4 t, interactive
	real*8 dtemp
	real*8 phscale(3) / dpi, 180.d0, 0.5d0 /

	cb.status = 1	! OK status

	v = cb.value
	item = cb.item
	interactive = cb.mode .eq. L_CBenable
	if (interactive) v = -1
	t = v .lt. 0

	if (item.eq.t_all) then
	  if (t .or. (v.eq.0 .eqv. Gx.all)) then
	    Gx.all = .not. Gx.all
	    Mx.resize = .true.
	  endif
	elseif (item.eq.t_bs) then
	  if (interactive) then
	    v = Gx.bs
	    call MX$LPROMPT ('Backing Store Levels: ', v)
	  endif
	  if (v.ne.Gx.bs) then
	    i = min(min(v,L_stack),L_zoommax)
	    if (i.eq.Gx.bs .or. (i.le.0 .and. Gx.bs.le.0)) then
	    elseif (i .gt. Gx.bs) then
	      do k = max(1,Gx.bs+1), i
		if (k.eq.Mx.level) then
		  call DRAW_ACCESSORIES (-3)
		  call MX$MAP (Mx.zoom(i),Gx.l,Gx.t,Gx.r-Gx.l+1,Gx.b-Gx.t+1,
     &			L_NewMap)
		  Gx.bslyr(k) = Gx.layers
		  call DRAW_ACCESSORIES (3)
		else
		  Gx.bslyr(k) = 0
		endif
	      enddo
	    else
	      do k = max(1,i+1), Gx.bs
		call MX$MAP (Mx.zoom(k),0,0,0,0,L_FreeMap)
		Gx.bslyr(k) = 0
	      enddo
	    endif
	    Gx.bs = i
	  endif
	elseif (item.eq.t_bufsize) then
	  if (interactive) then
	    v = Gx.bufmax
	    call MX$LPROMPT ('Max buffer (elements): ', v)
	  endif
	  if (v.gt.0) Gx.bufmax = v
	elseif (item.eq.t_cntrls) then
	  if (interactive) then
	    v = MX$MENU (Gx.cntrls+3, 'CONTROLS OPTIONS;'//
     &	      'Continuous (Disabled),LM Click (Disabled),Off,'//
     &	      'LM Click,Continuous,Assign...') - 3
	    if (v.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)
	      v = Gx.cntrls
	    endif
	  endif
	  if (v .ne. Gx.cntrls) then
	    Gx.cntrls = v
	    call DISPLAY_SPECS
	  endif
	elseif (item.eq.t_cross) then
	  if (t .or. (v.eq.0 .eqv. Gx.cross)) Gx.cross = .not. Gx.cross
	elseif (item.eq.t_grid) then
	  if (t .or. (v.eq.0 .eqv. Gx.grid)) then
	    Gx.grid = .not. Gx.grid
	    Mx.resize = .true.
	  endif
	elseif (item.eq.t_index) then
	  if (t .or. (v.eq.0 .eqv. Gx.index)) then
	    Gx.index = .not.Gx.index
	    call XPLOT_CLEANUP
	    call LOAD_FILES (' ', 2, .true.)
	    Mx.resize = .true.
	  endif
	elseif (item.eq.t_legend) then
	  if (t .or. (v.eq.0 .eqv. Gx.legend)) then
	    call DRAW_ACCESSORIES (-1)
	    Gx.legend = .not. Gx.legend
	    if (Gx.specs) then
	      i = Gx.lbtn - 2
	      if (Gx.legend) then
		call MX$SHADOWBOX(Mx.width-Gx.lbtn, 2, i, i, 1, -1, 'L')
	      else
		call MX$SHADOWBOX(Mx.width-Gx.lbtn, 2, i, i, 1, 1, 'L')
	      endif
	    endif
	    call DRAW_ACCESSORIES (1)
	  endif
	elseif (item.eq.t_mimic) then
	  if (interactive) then
	    call MX$LPROMPT ('Mimic ID: ', Gx.mimic)
	  else
	    Gx.mimic = v
	  endif
	elseif (item.eq.t_msgid) then
	  if (interactive) then
	    call MX$LPROMPT ('Msg ID: ', Gx.xf.msgid)
	  else
	    Gx.xf.msgid = v
	  endif
	elseif (item.eq.t_pan) then
	  if (t .or. (v.eq.0 .eqv. Gx.pan)) then
	    Gx.pan = .not. Gx.pan
	    call XPLOT_REFRESH(2)
	  endif
	elseif (item.eq.t_plabel) then
	  if (interactive) v = 22 +
     &		MX$MENU(Gx.plab-22,'PHASE UNITS;Radians,Degrees,Cycles')
	  if (v.ne.Gx.plab .and. v.ge.23 .and. v.le.25) then
	    if (Gx.cmode.eq.2) then
	      dtemp = phscale(v-22) / phscale(Gx.plab-22)
	      do i = 1, Mx.level
		Mx.stk(i).ymin = Mx.stk(i).ymin * dtemp
		Mx.stk(i).ymax = Mx.stk(i).ymax * dtemp
		Mx.stk(i).yscl = Mx.stk(i).yscl * dtemp
	      enddo
	      Gx.panymin = Gx.panymin * dtemp
	      Gx.panymax = Gx.panymax * dtemp
	      Mx.exposure = .true.
	    endif
	    Gx.plab = v
	  endif
	elseif (item.eq.t_segment) then
	  if (t .or. (v.eq.0 .eqv. Gx.segment)) then
	    Gx.segment = .not. Gx.segment
	    if (Gx.cmode.ne.5) then
	      do k = 1, Gx.layers
		! only affects 3000 files with absc data from the file
		! and connecting lines between the points
		if (Gx.lyr(k).xsub.gt.0 .and. Gx.lyr(k).line.eq.3)
     &			Mx.resize = .true.
	      enddo
	    endif
	  endif
	elseif (item.eq.t_specs) then
	  if (t .or. (v.eq.0 .eqv. Gx.specs)) then
	    Gx.specs = .not. Gx.specs
	    call XPLOT_REFRESH(2)
	  endif
	elseif (item.eq.t_xdivisions) then
	  if (interactive) then
	    v = Gx.xdiv
	    call MX$LPROMPT ('X Divisions: ', v)
	  endif
	  if (v .eq. 0) v = 1
	  if (Gx.xdiv .ne. v) then
	    Gx.xdiv = v
	    Mx.exposure = .true.
	  endif
	elseif (item.eq.t_xlabel) then
	  if (interactive) then
	    v = Gx.xlab
	    call MX$LPROMPT ('X Units: ', v)
	  endif
	  if (Gx.xlab .ne. v) then
	    Gx.xlab = v
	    Mx.exposure = .true.
	  endif
	elseif (item.eq.t_ydivisions) then
	  if (interactive) then
	    v = Gx.ydiv
	    call MX$LPROMPT ('Y Divisions: ', v)
	  endif
	  if (v.eq.0) v = 1
	  if (Gx.ydiv .ne. v) then
	    Gx.ydiv = v
	    Mx.exposure = .true.
	  endif
	elseif (item.eq.t_yinv) then
	  if (t .or. (v.eq.0 .eqv. Mx.origin.gt.2)) then
	    Mx.origin = 5 - Mx.origin
	    Mx.resize = .true.
	  endif
	elseif (item.eq.t_ylabel) then
	  if (interactive) then
	    v = Gx.ylab
	    call MX$LPROMPT ('Y Units: ', v)
	  endif
	  if (Gx.ylab .ne. v) then
	    Gx.ylab = v
	    Mx.exposure = .true.
	  endif
	elseif (item.eq.t_sections) then
	  if (interactive) then
	    v = Gx.sections
	    call MX$LVAL ('Sections: ', v,-1,16,1,0)
	  endif
	  if (Gx.sections .ne. v) then
	    Gx.sections = v
	    Mx.resize = .true.
	  endif
	elseif (item.eq.t_hold) then
	  if (t .or. (v.eq.0 .eqv. Gx.hold.ne.0)) then
	    if (Gx.hold.eq.0) then
	      Gx.hold = 1
	    else
	      Gx.hold = 0
	    endif
	  endif
	else
	  call M$WARNING('Unknown flag item in SETTINGS')
	endif

	if (interactive) then
	  if (Mx.resize)   call XPLOT_REFRESH (2)
	  if (Mx.exposure) call XPLOT_REFRESH (0)
	  Mx.resize = .false.
	  Mx.exposure = .false.
	endif

	return
	end

	subroutine FACILITIES (type, mode)

	include 'xplot.inc'
	character*(*) type
	integer*4 mode, flag

	flag = 1
	if (type.eq.'B' .or. type.eq.'P') flag = 2
	call DRAW_ACCESSORIES (-flag)
	call MX$FACILITIES (Gx.xf, type, mode)
	call DRAW_ACCESSORIES (flag)

	return
	end


	subroutine XPLOT_TRACE (n, slin, sthk, ssym, srad, scol)
	include 'xplot.inc'
	integer*4 n, slin, sthk, ssym, srad, scol
	integer*4 i, lin, thk, sym, rad, col
	character c, menu*128
	integer*4 redraw	! need to redraw all layers >= this value
	logical*4 toggle

	redraw = Gx.layers + 1

	if (slin .ne. -999) then
	  lin = slin
	  sym = ssym
	  thk = sthk
	  rad = srad
	  col = scol
	  toggle = .false.
	else
	  lin = Gx.lyr(max(1,n)).line
	  thk = Gx.lyr(max(1,n)).thick
	  sym = Gx.lyr(max(1,n)).symbol
	  if (sym.ge.8) Gx.lyr(max(1,n)).radius = -(Mx.text_w/2)
	  rad = Gx.lyr(max(1,n)).radius
	  col = Gx.lyr(max(1,n)).color
	  toggle = .false.
	  if (n.le.0) then
	    do i = 2, L_XPlotLayers
	      if (lin.ne.Gx.lyr(i).line) lin = -1
	      if (thk.ne.Gx.lyr(i).thick) thk = 0
	      if (sym.ne.Gx.lyr(i).symbol) sym = -1
	      if (Gx.lyr(i).symbol .ge. 8) Gx.lyr(i).radius = -(Mx.text_w/2)
	      if (rad.ne.Gx.lyr(i).radius) rad = 0
	      if (col.ne.Gx.lyr(i).color) col = 0
	    enddo
	  endif

	  i = -1
	  do while (i.ne.0)
	    if (i.lt.0) then
	      menu = 'TRACE OPTIONS;Dashed...,Dots...,Solid...,'//
     &		'Toggle,More Options...'
	      i = MX$MENU(0, menu)
	      if (i.le.4) i = -i
	    endif

	    if (i.gt.0) then
	      menu = 'TRACE OPTIONS;- Enable,Line Type...,Thickness...,'//
     &	 	 'Symbols...,Radius...,Color...,Cancel'
	      if (n.eq.0) then
	        menu(17:20) = 'Togg'
	        if (toggle) menu(15:15) = '+'
	      elseif (Gx.lyr(n).display .neqv. toggle) then
	        menu(15:15) = '+'
	      endif
	      i = MX$MENU(0, menu) 
	    endif


	    if (i.eq.-1) then
	      sym = 0
	      lin = 3
	      thk = iabs(thk)
	      call MX$LVAL ('Line Thickness: ', thk, 1, 16, 1, 0)
	      thk = -thk
	    elseif (i.eq.-2) then
	      lin = 0
	      if (sym .eq. L_SquareSymbol) rad = -rad
	      call MX$LVAL ('Radius/Shape: ', rad, -16, 16, 1, 0)
	      if (rad.lt.0) then
		sym = L_SquareSymbol
		rad = -rad
	      elseif (rad.eq.0) then
		sym = L_PixelSymbol
	      else
		sym = L_CircleSymbol
	      endif
	    elseif (i.eq.-3) then
	      sym = 0
	      lin = 3
	      thk = iabs(thk)
	      call MX$LVAL ('Line Thickness: ', thk, 1, 16, 1, 0)
	    elseif (i.eq.1 .or. i.eq.-4) then
	      toggle = .not. toggle
	    elseif (i.eq.2) then
	      lin = MX$MENU(lin+2, 'LINE TYPE;Retain Current,'//
     &		  'None,Verticals,Horizontals,Connecting') - 2
	    elseif (i.eq.3) then
	      call MX$LVAL ('Thickness: ', thk, -16, 16, 1, 0)
	    elseif (i.eq.4) then
	      i = MX$MENU(min(8,sym)+2, '~SYMBOLS;Retain Current,'//
     &	      		'None,Pixels,Circles,Squares,Plusses,X''s,'//
     &			'Triangles,Downward Triangles,ASCII...') - 2
	      if (i.eq.8) then
		c = ' '
		if (sym.gt.ICHAR(' ')) c = CHAR(sym)
		call MX$PROMPT('ASCII Character: ', c)
		if (c .ne. ' ') then
		  sym = ICHAR(c)
		else
		  return
		endif
	      else
		sym = i
	      endif
	      i = 1
	    elseif (i.eq.5) then
	      if (sym.eq.L_PixelSymbol .or. sym.gt.8) then
		call MX$MESSAGE('Radius cannot be set for the current '//
     &				'symbol type.', -1.0)
	      else
		call MX$LVAL ('~Symbol Radius:', rad, -16, 16, 1, 0)
	      endif
	    elseif (i.eq.6) then
	      col = MX$MENU(col+8, 'TRACE COLOR;X-Widget Low,X-Widget '//
     &	      	 'Bottom Shadow,X-Widget Top Shadow,X-Widget BG,X-Widg'//
     &	      	 'et FG,XOR,Foreground,Retain Current,1,2,3,4,5,6,7,8,'//
     &	      	 '9,10,11,12,13,14,15,16') - 8
	    elseif (i.eq.7) then
	      return
	    endif
	    if (i.lt.0) i = 0
	  enddo
	endif

	do i = L_XPlotLayers, 1, -1
	  if (n.le.0 .or. i.eq.n) then
	    if (toggle) then
	      Gx.lyr(i).display = .not. Gx.lyr(i).display
	      redraw = i
	    endif
	    if (lin.ge.0 .and. Gx.lyr(i).line.ne.lin) then
	      Gx.lyr(i).line = lin
	      if (Gx.lyr(i).display) redraw = i
	    endif
	    if (thk.ne.0 .and. Gx.lyr(i).thick.ne.thk) then
	      Gx.lyr(i).thick = thk
	      if (Gx.lyr(i).display .and. Gx.lyr(i).line.ne.0) redraw = i
	    endif
	    if (sym.ge.0 .and. Gx.lyr(i).symbol.ne.sym) then
	      Gx.lyr(i).symbol = sym
	      if (sym.ge.8) Gx.lyr(i).radius = - (Mx.text_w / 2)
	      if (Gx.lyr(i).display) redraw = i
	    endif
	    if (rad.ne.0 .and. Gx.lyr(i).radius.ne.rad .and.
     &	    					Gx.lyr(i).symbol.lt.8) then
	      Gx.lyr(i).radius = rad
	      if (Gx.lyr(i).display .and. Gx.lyr(i).symbol.ne.0) redraw = i
	    endif
	    if (col.ne.0 .and. col.ne.Gx.lyr(i).color) then
	      Gx.lyr(i).color = col
	      if (Gx.lyr(i).display) redraw = i
	    endif
	  endif
	enddo

	if (redraw .le. Gx.layers) then
	  do i = 1, L_zoommax
	    if (Gx.bslyr(i) .ge. redraw) Gx.bslyr(i) = 0
	  enddo
	  call XPLOT_REFRESH (1)
	endif

	return
	end
