c
c     Copyright (c) 1999,2000, Compaq Computer Corporation
c
c     See the file "license.terms" for information on usage and redistribution
c     of this file, and for a DISCLAIMER OF ALL WARRANTIES.
c
c   1d comparison plot routines
c
      subroutine compare
      implicit none
c
      include 'sysdep.cmn'
      include 'io.cmn'
c
c     local variables
c
      logical invalid
      integer string_len, mode
      character*10 answer
c
c     Reset color names back to x-y plot values
      call pm_set_xy_colornames
c
400   call clear_screen
      write(luttyo,300)
300   format(' ','X-Y comparison plot:'//
     1    ' ','Add       - Add data to plot'/
     1    ' ','Barchart  - Plot data as a bar chart'/
     1    ' ','Clear     - Delete all data entries'/
     1    ' ','Delete    - Delete a data entry'/
     1    ' ','Exit      - Return to main menu'/
     1    ' ','Integrate - Integrate quantity in x or y'/
     1    ' ','List      - List all current data entries'/
     1    ' ','Plot      - Plot all current data entries'/
     1    ' ','Oxide     - Select a cut along an oxide interface'/
     1    ' ','Modify    - Change the plot attributes for an entry'/
     1    ' ','            or apply offsets and scale factors to data'/
     1    ' ','Quit      - Return to main menu (same as exit)'/
     1    ' ','Read      - Read new data file'/
     1    ' ','Show      - Print information about entry')
410   write(luttyo,305)
305   format(/' ','Request? ',$)
      read(luttyi,310) answer
310   format(a)
      call upcase(answer)
c
c     switch on answer
c
      invalid = .FALSE.
      if( answer(1:1) .eq. 'A' ) then
          call compare_add
      else if( answer(1:1) .eq. 'B' ) then
          mode = 2
          call compare_plot(.FALSE.,.FALSE.,mode)
      else if( answer(1:1) .eq. 'C' ) then
          call compare_clear
      else if( answer(1:1) .eq. 'D' ) then
          call compare_delete
      else if( answer(1:1) .eq. 'E' ) then
          goto 10100
      else if( answer(1:1) .eq. 'I' ) then
          call compare_integrate
      else if( answer(1:1) .eq. 'L' ) then
          call compare_list
      else if( answer(1:1) .eq. 'M' ) then
          call compare_modify
      else if( answer(1:1) .eq. 'O' ) then
          call compare_interface
      else if( answer(1:1) .eq. 'P' ) then
          mode = 1
          call compare_plot(.FALSE.,.FALSE.,mode)
      else if( answer(1:1) .eq. 'Q' ) then
         goto 10100
      else if( answer(1:1) .eq. 'R' ) then
         call readbinfile
      else if( answer(1:1) .eq. 'S' ) then
          call compare_show
      else if( string_len(answer) .eq. 0 ) then
          goto 10100
      else
         invalid = .TRUE.
      endif
c
      if( invalid ) then
         write(luttyo,390) answer
390      format(' ','Invaid request: ''',a,'''')
         goto 410
      else
         goto 400
      endif
c
c
c     the end of the road...
c
10100 continue
      return
      end
c*******************************************************************
c
      subroutine compare_clear
      implicit none
c
      include 'const.h'
      include 'sysdep.cmn'
      include 'compare.cmn'
      include 'io.cmn'
c
c     locals
c
      character*1 answer
      integer i
c
      write(luttyo,100)
100   format(//' ','Warning: all data will be deleted.')
      call get_char(answer,'Type y to confirm: ',0)
      call upcase(answer)
      if( answer .ne. 'Y' ) return
c
c     Mark all data as erased
      do 10 i=1,MULTI_SIZE
         in_use(i) = .FALSE.
         slot_index(i) = -1
10       continue
      n_cuts = 0
c
c     Tell compare menu routines that things have been reset
      comp_lfirst = .TRUE.
c
      return
      end
c
c*******************************************************************
c
      subroutine compare_delete
      implicit none
c
      include 'const.h'
      include 'sysdep.cmn'
      include 'compare.cmn'
      include 'io.cmn'
c
c     locals
c
      character*1 answer
      integer i, len, string_len, slot, entry, int_vec(2)
      integer delete_entry, rcode
c
1000  call clear_screen
      write(luttyo,100)
100   format(' ','Data entries:'/
     1       ' ','Entry          Label'/)
      do 10 i=1,n_cuts
         slot = slot_index(i)
         len = string_len(multi_1d(slot)%label)
         write(luttyo,200) i, multi_1d(slot)%label(1:len)
200      format(' ',2x,i2,': ',a)
10       continue
      write(luttyo,201)
201   format(/)
c
      call get_ints(int_vec,1,'Which entry number to delete? ',0)
      entry = int_vec(1)
      call get_char(answer,'Type y to confirm: ',0)
      call upcase(answer)
      if( answer .eq. 'Y' ) then
         rcode = delete_entry(entry)
         if( rcode .lt. 0 ) then
            write(luttyo,300) entry
300         format(' ','Error: ',i2,' is an illegal entry'/)
         endif
      endif
      call get_char(answer,'More entries to delete? (Y/N) ',0)
      call upcase(answer)
      if( answer .eq. 'Y' ) goto 1000
c
c     Reset menu/axis items if we've deleted all data
      if( n_cuts .eq. 0 ) comp_lfirst = .TRUE.
c
      return
      end
c
c*******************************************************************
c
      subroutine compare_modify
      implicit none
c
      include 'const.h'
      include 'sysdep.cmn'
      include 'compare.cmn'
c
c     locals
c
      integer i, len, string_len, slot
c
c     Menu code items
      character*80 string
      character*3  yn
      integer      item_number
      logical      eof
c
100   call clear_screen
      call display_string(2 ,1 ,'Data entries:',13,0)
      call display_string(3, 1 ,'Entry   Selected  Label',23,0)
c
      do 10 i=1,n_cuts
         slot = slot_index(i)
         len = string_len(multi_1d(slot)%label)
         if( multi_1d(slot)%selected .eq. 1 ) then
c           Show as selected to plot
            yn = 'yes'
         else
            yn = 'no '
         endif
c        Avoid over-running 'string' (magic number depends on contents
c        of format statement 2000)
         len = MIN(62,len)
         write(string,2000) i, yn, multi_1d(slot)%label(1:len)
2000     format(1x,i2,7x,a3,5x,a)
         call display_string(i+3, 1 ,string,79,1)
10    continue
c
200   call display_prompt(
     1 'Enter number of entry to modify, or Repaint, Accept/Exit/Quit:')
      call read_from_input_area(string, eof)
      if( eof ) goto 200
      call upcase(string)
      if( string(1:1) .eq. 'A' .or. string(1:1) .eq. 'E' .or.
     1    string(1:1) .eq. 'Q' ) then
         goto 300
      elseif (string(1:1) .eq. 'R' ) then
         goto 100
      else
         read(string,*,err=1000) item_number
         if( item_number .lt. 1 .or. item_number .gt. n_cuts ) then
            call display_message('Item number out of range')
            goto 200
         else
c           Bring up menu for that data slice
            call compare_modify_menu(item_number)
            goto 100
         endif
      endif
      goto 200
c
1000  call display_message('Illegal input')
      goto 200
c
300   continue
c
      return
      end
c
      subroutine compare_modify_menu(entry_id)
      implicit none
c
      include 'const.h'
      include 'sysdep.cmn'
      include 'units.cmn'
      include 'compare.cmn'
      include 'defaults.cmn'
      include 'evaluate.cmn'
c
      integer entry_id
c
c     locals
      real ax, ay, mx, my
      integer i, j, ierr, ind, pm_color_to_index, pm_symbol_to_index,
     1        pm_linetype_to_index, ilen, string_len, nvar
      real dummy_in(1,MAXCOLS), dummy_out
      real, allocatable :: tmp(:,:)
      logical have_x_expr, have_y_expr
      character*8  var_names(MAXCOLS)
c
c     Menu code items
      character*22 line_colors(0:MAX_RGB_VALUES)
      character*6 xtag_name(2), ytag_name(2)
      data xtag_name/'bottom','top   '/
      data ytag_name/'left  ','right '/
      character*80 string, buf, msg
      character*32 temp_str
      character*3  str
      integer      item_number, int_vec(2), slot, istat, nvars
      real         real_vec(2)
      logical      eof, reuse_last_input, color0_invisible
c
c     Initialize
      do i=1,MAX_RGB_VALUES
         line_colors(i) = color_names(i)
      end do
      line_colors(0) = 'invisible'
c
      slot = slot_index(entry_id)
c
      if( string_len(multi_1d(slot)%x_expression) .ne. 0 ) then
         have_x_expr = .TRUE.
      else
         have_x_expr = .FALSE.
      endif
      if( string_len(multi_1d(slot)%y_expression) .ne. 0 ) then
         have_y_expr = .TRUE.
      else
         have_y_expr = .FALSE.
      endif
c
100   call clear_screen
      call display_string(1, 1,'   Plot attributes for entry ',29,0)
      call display_int   (1,30,entry_id,3)
      call display_string(3 ,1 ,' 1) Plot label    :',19,0)
      call display_string(4 ,1 ,' 2) Color         :',19,0)
      call display_string(5 ,1 ,' 3) Linetype      :',19,0)
      call display_string(6 ,1 ,' 4) Linewidth     :',19,0)
      call display_string(7 ,1 ,' 5) Symbol color  :',19,0)
      call display_string(8 ,1 ,' 6) Symbol type   :',19,0)
      call display_string(9 ,1 ,' 7) Symbol size   :',19,0)
      call display_string(11,1 ,' 8) X coord offset (AX) :',25,0)
      call display_string(12,1 ,' 9) X coord scale  (MX) :',25,0)
      call display_string(13,1 ,'10) Y coord offset (AY) :',25,0)
      call display_string(14,1 ,'11) Y coord scale  (MY) :',25,0)
      call display_string(15,1 ,'12) X coord expression  :',25,0)
      call display_string(16,1 ,'13) Y coord expression  :',25,0)
      call display_string(17,1 ,'14) X axis tag    :',19,0)
      call display_string(18,1 ,'15) Y axis tag    :',19,0)
      call display_string(20,1 ,'16) Selected      :',19,0)
c
      call display_string(3,21,multi_1d(slot)%label(1:ilen),50,1)
c
      i = multi_1d(slot)%color
      if( i .lt. 0 .or. i .gt. MAX_RGB_VALUES ) i = MAX_RGB_VALUES
      call display_string(4,21,line_colors(i),15,1)
      call display_intp  (4,37,i,3)
c
      i = multi_1d(slot)%linestyle
      if( i .lt. 0 .or. i .gt. MAX_LINETYPE_VALUES )
     1    i = MAX_LINETYPE_VALUES
      call display_string(5,21,line_names(i),15,1)
      call display_intp  (5,37,i,3)
c
      call display_real  (6,21,multi_1d(slot)%linewidth,1)
c
      i = multi_1d(slot)%marker_color
      if( i .lt. 0 .or. i .gt. MAX_RGB_VALUES ) i = MAX_RGB_VALUES
      call display_string(7,21,line_colors(i),15,1)
      call display_intp  (7,37,i,3)
c
      i = multi_1d(slot)%marker_type
      if( i .lt. 0 .or. i .gt. MAX_SYMBOL_VALUES ) i = MAX_SYMBOL_VALUES
      call display_string(8,21,symbol_names(i),15,1)
      call display_intp  (8,37,i,3)
c
      call display_real  (9,21,multi_1d(slot)%marker_scale,1)
c
      if( have_x_expr ) then
         call display_string(11,26,'       NA',9,1)
         call display_string(12,26,'       NA',9,1)
      else
         call display_real(11,26,multi_1d(slot)%ax,1)
         call display_real(12,26,multi_1d(slot)%mx,1)
      endif
      if( have_y_expr ) then
         call display_string(13,26,'       NA',9,1)
         call display_string(14,26,'       NA',9,1)
      else
         call display_real(13,26,multi_1d(slot)%ay,1)
         call display_real(14,26,multi_1d(slot)%my,1)
      endif
      if( have_x_expr ) then
         call display_string(15,27,multi_1d(slot)%x_expression,52,1)
      else
         call display_string(15,27,'(none)',6,1)
      endif
      if( have_y_expr ) then
         call display_string(16,27,multi_1d(slot)%y_expression,52,1)
      else
         call display_string(16,27,'(none)',6,1)
      endif
c
      call display_string(17,21,xtag_name(multi_1d(slot)%xaxis_tag),6,1)
      call display_string(18,21,ytag_name(multi_1d(slot)%yaxis_tag),6,1)
c
      if( multi_1d(slot)%selected .eq. 1 ) then
         str = 'yes'
      else
         str = 'no'
      endif
      call display_string(20,21,str,3,1)
c
200   call display_prompt(
     1 'Enter number of item to modify, or Repaint, Accept/Exit/Quit:')
      if( reuse_last_input ) then
         reuse_last_input = .FALSE.
      else
         call read_from_input_area(string, eof)
      endif
      if( eof ) goto 200
      call upcase(string)
      if( string(1:1) .eq. 'A' .or. string(1:1) .eq. 'E' .or.
     1    string(1:1) .eq. 'Q' ) then
         goto 300
      elseif (string(1:1) .eq. 'R' ) then
         goto 100
      else
         read(string,*,err=1000) item_number
         if ( item_number .eq. 1 ) then
c           Label
            call get_string_with_prompt(multi_1d(slot)%label,
     1           'Enter label for curve')
            call display_string(3,21,multi_1d(slot)%label,50,1)
         else if ( item_number .eq. 2 ) then
c           Curve color
            call get_string_with_prompt(temp_str,
     1      'Enter color name (enter ? for list of colors)')
            if( temp_str .eq. '?' ) then
c              Display color names and then repaint screen
               color0_invisible = .TRUE.
               call pm_display_color_list(color0_invisible)
               reuse_last_input = .TRUE.
               goto 100
            endif
            int_vec(1) = pm_color_to_index(temp_str)
            if( int_vec(1) .lt. 0 ) then
               call display_message('Illegal value')
            else
               multi_1d(slot)%color = int_vec(1)
               i = multi_1d(slot)%color
               if( i .lt. 0 .or. i .gt. 15 ) i = 15
               call display_string(4,21,line_colors(i),15,1)
               call display_intp  (4,37,i, 3)
            endif
         else if ( item_number .eq. 3 ) then
c           Curve linestyle
            call get_string_with_prompt(temp_str,
     1      'Enter line type (enter ? for list of types)')
            if( temp_str .eq. '?' ) then
c              Display linetypes and then repaint screen
               call pm_display_linetype_list
               reuse_last_input = .TRUE.
               goto 100
            endif
            int_vec(1) = pm_linetype_to_index(temp_str)
            if( int_vec(1) .lt. 0 ) then
               call display_message('Illegal value')
            else
               multi_1d(slot)%linestyle = int_vec(1)
               call display_string(5,21,line_names(int_vec(1)),15,1)
               call display_intp  (5,37,int_vec(1), 3)
            endif
         else if ( item_number .eq. 4 ) then
c           Line width
            real_vec(1) = multi_1d(slot)%linewidth
            call get_reals_with_prompt(real_vec,1,
     1        'Enter line width scale (> 0.0)')
            multi_1d(slot)%linewidth = MIN(MAX(0.01,real_vec(1)),10.0)
            call display_real(6,21,multi_1d(slot)%linewidth,1)
         else if ( item_number .eq. 5 ) then
c           Symbol color
            call get_string_with_prompt(temp_str,
     1      'Enter color name (enter ? for list of colors)')
            if( temp_str .eq. '?' ) then
c              Display color names and then repaint screen
               color0_invisible = .TRUE.
               call pm_display_color_list(color0_invisible)
               reuse_last_input = .TRUE.
               goto 100
            endif
            int_vec(1) = pm_color_to_index(temp_str)
            if( int_vec(1) .lt. 0 ) then
               call display_message('Illegal value')
            else
               multi_1d(slot)%marker_color = int_vec(1)
               call display_string(7,21,line_colors(int_vec(1)),15,1)
               call display_intp  (7,37,int_vec(1), 3)
            endif
         else if ( item_number .eq. 6 ) then
c           Symbol type
            call get_string_with_prompt(temp_str,
     1      'Enter symbol type (enter ? for list of types)')
            if( temp_str .eq. '?' ) then
c              Display symbol names and then repaint screen
               call pm_display_symbol_list
               reuse_last_input = .TRUE.
               goto 100
            endif
            int_vec(1) = pm_symbol_to_index(temp_str)
            if( int_vec(1) .lt. 0 ) then
               call display_message('Illegal value')
            else
               multi_1d(slot)%marker_type = int_vec(1)
               call display_string(8,21,symbol_names(int_vec(1)),15,1)
               call display_intp  (8,37,int_vec(1), 3)
            endif
         else if ( item_number .eq. 7 ) then
c           Symbol size
            real_vec(1) = multi_1d(slot)%marker_scale
            call get_reals_with_prompt(real_vec,1,
     1        'Enter symbol size')
            multi_1d(slot)%marker_scale = MAX(0.01,real_vec(1))
            call display_real(9,21,multi_1d(slot)%marker_scale,1)
         else if ( item_number .eq. 8 ) then
            if( have_x_expr) then
               call display_message(
     1         'Both AX and X expression cannot be specified')
            else
               real_vec(1) = multi_1d(slot)%ax
               call get_reals_with_prompt(real_vec,1,
     1           'Enter X coordinate offset (AX in formula: MX*x + AX)')
               multi_1d(slot)%ax = real_vec(1)
               call display_real(11,26,multi_1d(slot)%ax,1)
            endif
         else if ( item_number .eq. 9 ) then
            if( have_x_expr) then
               call display_message(
     1         'Both AX and X expression cannot be specified')
            else
               real_vec(1) = multi_1d(slot)%mx
               call get_reals_with_prompt(real_vec,1,
     1           'Enter X coordinate scale (MX in formula: MX*x + AX)')
               if( real_vec(1) .eq. 0.0 ) then
                  call display_message('MX must not be set to zero')
               else
                  multi_1d(slot)%mx = real_vec(1)
                  call display_real(12,26,multi_1d(slot)%mx,1)
               endif
            endif
         else if ( item_number .eq. 10 ) then
            if( have_y_expr ) then
               call display_message(
     1         'Both AY and Y expression cannot be specified')
            else
               real_vec(1) = multi_1d(slot)%ay
               call get_reals_with_prompt(real_vec,1,
     1           'Enter Y coordinate offset (AY in formula: MY*y + AY)')
               multi_1d(slot)%ay = real_vec(1)
               call display_real(13,26,multi_1d(slot)%ay,1)
            endif
         else if ( item_number .eq. 11 ) then
            if( have_y_expr ) then
               call display_message(
     1         'Both AY and Y expression cannot be specified')
            else
               real_vec(1) = multi_1d(slot)%my
               call get_reals_with_prompt(real_vec,1,
     1           'Enter Y coordinate scale (MY in formula: MY*y + AY)')
               if( real_vec(1) .eq. 0.0 ) then
                  call display_message('MY must not be set to zero')
               else
                  multi_1d(slot)%my = real_vec(1)
                  call display_real(14,26,multi_1d(slot)%my,1)
               endif
            endif
         else if ( item_number .eq. 12 ) then
c           X axis expression
            call get_string_with_prompt(multi_1d(slot)%x_expression,
     1           'Enter expression to apply to x axis data '//
     2           '(e.g. 3.0*x**2 + sqrt(sin(x)) )')
            ilen = string_len(multi_1d(slot)%x_expression)
            if( ilen .eq. 0 ) then
               call display_string(15,27,'(none)',52,1)
               have_x_expr = .FALSE.
               call display_real(11,26,multi_1d(slot)%ax,1)
               call display_real(12,26,multi_1d(slot)%mx,1)
            else
c              Make a dummy evaluation to see if function is suitable
               dummy_in(1,1) = 1.0
               var_names(1) = 'x'
               call ev_expression_f(multi_1d(slot)%x_expression,
     1                        var_names,1,1,
     1                        dummy_in,1,
     1                        dummy_out,ierr,ind)
               if( ierr .ne. EVAL_SUCCESS ) then
                  call ev_lookup_error_message(ierr,buf)
                  msg = 'Error evaluating x axis expression: ' // buf
                  call display_message(msg)
               else
                  call display_string(15,27,
     1                                multi_1d(slot)%x_expression,52,1)
                  call display_string(11,26,'       NA',9,1)
                  call display_string(12,26,'       NA',9,1)
                  have_x_expr = .TRUE.
               endif
            endif
         else if ( item_number .eq. 13 ) then
c           Y axis expression
            call get_string_with_prompt(multi_1d(slot)%y_expression,
     1           'Enter expression to apply to y axis data '//
     2           '(e.g. 3.0*y**2 + sqrt(sin(y)) )')
            ilen = string_len(multi_1d(slot)%y_expression)
            if( ilen .eq. 0 ) then
               call display_string(16,27,'(none)',52,1)
               have_y_expr = .FALSE.
               call display_real(13,26,multi_1d(slot)%ay,1)
               call display_real(14,26,multi_1d(slot)%my,1)
            else
c              Make a dummy evaluation to see if function is suitable
               call pm_set_expression_var_names(multi_1d(slot)%type,
     1            multi_1d(slot)%n_ycols, multi_1d(slot)%col_y,
     2            multi_1d(slot)%merge_ycols, var_names, nvars, MAXCOLS)
               do i=1,nvars
                  dummy_in(1,i) = 1.0
               end do
               call ev_expression_f(multi_1d(slot)%y_expression,
     1                        var_names,nvars,1,
     1                        dummy_in,1,
     1                        dummy_out,ierr,ind)
               if( ierr .ne. EVAL_SUCCESS ) then
                  call ev_lookup_error_message(ierr,buf)
                  msg = 'Error evaluating y axis expression: ' // buf
                  call display_message(msg)
               else
                  call display_string(16,27,
     1                                multi_1d(slot)%y_expression,52,1)
                  call display_string(13,26,'       NA',9,1)
                  call display_string(14,26,'       NA',9,1)
                  have_y_expr = .TRUE.
               endif
            endif
         else if ( item_number .eq. 14 ) then
            if( multi_1d(slot)%xaxis_tag .eq. 1 ) then
               multi_1d(slot)%xaxis_tag = 2
            else
               multi_1d(slot)%xaxis_tag = 1
            endif
            call display_string(17,21,
     1                          xtag_name(multi_1d(slot)%xaxis_tag),6,1)
         else if ( item_number .eq. 15 ) then
            if( multi_1d(slot)%yaxis_tag .eq. 1 ) then
               multi_1d(slot)%yaxis_tag = 2
            else
               multi_1d(slot)%yaxis_tag = 1
            endif
            call display_string(18,21,
     1                          ytag_name(multi_1d(slot)%yaxis_tag),6,1)
         else if ( item_number .eq. 16 ) then
            if( multi_1d(slot)%selected .eq. 1 ) then
               multi_1d(slot)%selected = 0
               str = 'no '
            else
               multi_1d(slot)%selected = 1
               str = 'yes'
            endif
            call display_string(20,21,str,3,1)
         else
            call display_message('Item number out of range')
         endif
      endif
      goto 200
c
1000  call display_message('Illegal input')
      goto 200
c
300   continue
c
c     Re-scale data from raw information
CC      if( multi_1d(slot)%datatype .eq. DT_ASCII ) then
c        Coords have to be converted to appropriate internal units.
c        In the case of external files, the absissa data has to
c        to be scaled 'as if' it were being converted from microns
c        to cm, as the other plot routines consider all coordinates
c        to be in units of cm.
CC         ax = MU2CM*multi_1d(slot)%ax
CC         mx = MU2CM*multi_1d(slot)%mx
CC      else
c        Scale factors have to be converted to appropriate internal
c        units. mx is not converted, as it is unitless.
         ax = pm_scale_plot2cm*multi_1d(slot)%ax
         mx = multi_1d(slot)%mx
CC      endif
c
      if( string_len(multi_1d(slot)%x_expression) .ne. 0 .or.
     1    string_len(multi_1d(slot)%y_expression) .ne. 0) then
c        Dynamically allocate temporary storage
c        Could we use work_vec() and avoid creating tmp? 12-21-98 jvf
         if( allocated(tmp) ) then
            deallocate(tmp)
         endif
         if( multi_1d(slot)%datatype .eq. DT_ASCII .and.
     1       multi_1d(slot)%n_ycols .gt. 1 .and. .not.
     1       multi_1d(slot)%merge_ycols) then
          allocate(tmp(1:multi_1d(slot)%np,1:multi_1d(slot)%n_ycols+1),
     1             stat=istat)
         else
            allocate(tmp(1:multi_1d(slot)%np,1:2),stat=istat)
         endif
      endif
c
      ay = multi_1d(slot)%ay
      my = multi_1d(slot)%my
      if( string_len(multi_1d(slot)%x_expression) .ne. 0 ) then
         do i=1,multi_1d(slot)%np
            tmp(i,1) = multi_1d(slot)%raw_coord(i)*pm_scale_cm2plot
         end do
         var_names(1) = 'x'
         call ev_expression_f(multi_1d(slot)%x_expression,var_names,
     1                        1,multi_1d(slot)%np,
     2                        tmp,multi_1d(slot)%np,
     3                        multi_1d(slot)%coord,ierr,ind)
         if( ierr .ne. EVAL_SUCCESS ) then
            call ev_lookup_error_message(ierr,buf)
            msg = 'Error evaluating x axis expression: ' // buf
            call display_message(msg)
            goto 200
         endif
         do i=1,multi_1d(slot)%np
            multi_1d(slot)%coord(i) = multi_1d(slot)%coord(i)*
     1                                pm_scale_plot2cm
         end do
      else
         do i=1,multi_1d(slot)%np
            multi_1d(slot)%coord(i)=mx*multi_1d(slot)%raw_coord(i) + ax
         end do
      endif
      if( string_len(multi_1d(slot)%y_expression) .ne. 0 ) then
         do i=1,multi_1d(slot)%np
            tmp(i,1) = multi_1d(slot)%raw_coord(i)*pm_scale_cm2plot
            tmp(i,2) = multi_1d(slot)%raw_data(i)
         end do
         if( multi_1d(slot)%datatype .eq. DT_ASCII .and.
     1       multi_1d(slot)%n_ycols .gt. 1 .and.
     2       .not. multi_1d(slot)%merge_ycols ) then
c           Copy the rest of the y columns into tmp
            do j=2,multi_1d(slot)%n_ycols
               do i=1,multi_1d(slot)%np
                  tmp(i,j+1) =
     1               multi_1d(slot)%raw_data((j-1)*multi_1d(slot)%np+i)
               end do
            end do
         endif
         call pm_set_expression_var_names(multi_1d(slot)%type,
     1      multi_1d(slot)%n_ycols, multi_1d(slot)%col_y,
     2      multi_1d(slot)%merge_ycols, var_names, nvars, MAXCOLS)
         call ev_expression_f(multi_1d(slot)%y_expression,var_names,
     1                        nvars,multi_1d(slot)%np,
     2                        tmp,multi_1d(slot)%np,
     3                        multi_1d(slot)%data,ierr,ind)
         if( ierr .ne. EVAL_SUCCESS ) then
            call ev_lookup_error_message(ierr,buf)
            msg = 'Error evaluating y axis expression: ' // buf
            call display_message(msg)
            goto 200
         endif
         deallocate(tmp)
      else
         do i=1,multi_1d(slot)%np
            multi_1d(slot)%data(i) = my*multi_1d(slot)%raw_data(i) + ay
         end do
      endif
c
      return
      end
c
c*******************************************************************
c
      subroutine compare_list
      implicit none
c
      include 'const.h'
      include 'sysdep.cmn'
      include 'compare.cmn'
      include 'io.cmn'
c
c     locals
c
      character*1 answer, mark
      integer i, len, string_len, slot
c
      call clear_screen
      write(luttyo,100)
100   format(' ','Data entries:'/
     1       ' ','Selected  Entry          Label'/)
c
      if( n_cuts .eq. 0 ) then
         write(luttyo,150)
150      format(' ','No data has been selected')
      endif
c
      do 10 i=1,n_cuts
         slot = slot_index(i)
         len = string_len(multi_1d(slot)%label)
         if( multi_1d(slot)%selected .eq. 1 ) then
c           Show as selected to plot
            mark = '*'
         else
            mark = ' '
         endif
         write(luttyo,200) mark, i, multi_1d(slot)%label(1:len)
200      format(' ',3x,a1,8x,i2,':  ',a)
10       continue
c
      write(luttyo,201)
201   format(/)
c
      call get_char(answer,'Hit return to continue...',0)
      return
      end
c
c*******************************************************************
c
      subroutine compare_show
      implicit none
c
      include 'const.h'
      include 'sysdep.cmn'
      include 'compare.cmn'
      include 'data.cmn'
      include 'units.cmn'
      include 'defaults.cmn'
      include 'io.cmn'
c
c     locals
c
      character*1 answer, mark
      character*22 line_colors(0:MAX_RGB_VALUES)
      integer i, len, ulen, string_len, slot, entry, int_vec(2)
c
c     Initialize
      do i=1,MAX_RGB_VALUES
         line_colors(i) = color_names(i)
      end do
      line_colors(0) = 'invisible'
c
      ulen = string_len(pm_length_unit)
c
1000  call clear_screen
      write(luttyo,100)
100   format(' ','Data entries:'/
     1       ' ','Selected  Entry          Label'/)
      do 10 i=1,n_cuts
         slot = slot_index(i)
         len = string_len(multi_1d(slot)%label)
         if( multi_1d(slot)%selected .eq. 1 ) then
c           Show as selected to plot
            mark = '*'
         else
            mark = ' '
         endif
         write(luttyo,200) mark,i, multi_1d(slot)%label(1:len)
200      format(' ',3x,a1,8x,i2,':  ',a)
10       continue
      write(luttyo,101)
101   format(/)
c
      call get_ints(int_vec,1,'Which entry number to display? ',0)
      entry = int_vec(1)
      if( entry .lt. 1 .or. entry .gt. n_cuts ) then
         write(luttyo,300) entry
300      format(' ','Error: ',i2,' is an illegal entry'/)
      else
         slot = slot_index(entry)
         len = string_len(multi_1d(slot)%label)
         write(luttyo,400) multi_1d(slot)%label(1:len),
     1                multi_1d(slot)%quantity
         if( multi_1d(slot)%type .eq. COMP_CUT_TYPE ) then
            write(luttyo,410) multi_1d(slot)%units,
     1                multi_1d(slot)%cut_line_axis,
     1                multi_1d(slot)%cut_line_coord*pm_scale_cm2plot,
     1                pm_length_unit(1:ulen),
     1                multi_1d(slot)%cut_plane_axis,
     1                multi_1d(slot)%cut_plane_coord*pm_scale_cm2plot,
     1                pm_length_unit(1:ulen)
         else if( multi_1d(slot)%type .eq. COMP_INT_TYPE ) then
            write(luttyo,415) multi_1d(slot)%int_units,
     1                multi_1d(slot)%cut_line_axis,
     1                multi_1d(slot)%cut_plane_axis,
     1                multi_1d(slot)%cut_plane_coord*pm_scale_cm2plot,
     1                pm_length_unit(1:ulen)
         else if( multi_1d(slot)%type .eq. COMP_INTERFACE_TYPE ) then
            write(luttyo,416) multi_1d(slot)%units,
     1                multi_1d(slot)%cut_line_coord*pm_scale_cm2plot,
     1                pm_length_unit(1:ulen),
     1                multi_1d(slot)%cut_plane_axis,
     1                multi_1d(slot)%cut_plane_coord*pm_scale_cm2plot,
     1                pm_length_unit(1:ulen)
         endif
         if( multi_1d(slot)%datatype .eq. DT_MINIMOS ) then
            write(luttyo,420) multi_1d(slot)%binfilename,
     1                   multi_1d(slot)%vs, multi_1d(slot)%vg,
     1                   multi_1d(slot)%vd, multi_1d(slot)%vb,
     1                   multi_1d(slot)%id, multi_1d(slot)%is,
     1                   multi_1d(slot)%ib
         else
            write(luttyo,425) multi_1d(slot)%binfilename
         endif
         i = multi_1d(slot)%color
         if( i .lt. 0 .or. i .gt. MAX_RGB_VALUES ) i = MAX_RGB_VALUES
         write(luttyo,430) line_colors(i), multi_1d(slot)%color
         i = multi_1d(slot)%linestyle
         if( i .lt. 1 .or. i .gt. MAX_LINETYPE_VALUES )
     1       i = MAX_LINETYPE_VALUES
         write(luttyo,431) line_names(i), multi_1d(slot)%linestyle
         write(luttyo,432) multi_1d(slot)%linewidth
         i = multi_1d(slot)%marker_color
         if( i .lt. 0 .or. i .gt. MAX_RGB_VALUES ) i = MAX_RGB_VALUES
         write(luttyo,433) line_colors(i), multi_1d(slot)%marker_color
         i = multi_1d(slot)%marker_type
         if( i .lt. 1 .or. i .gt. MAX_SYMBOL_VALUES )
     1       i = MAX_SYMBOL_VALUES
         write(luttyo,434) symbol_names(i), multi_1d(slot)%marker_type
         write(luttyo,435) multi_1d(slot)%marker_scale
400      format(/' ','----------'/
     1           ' ','Label:'/
     1           ' ',a//
     1           ' ','Quantity: ',a)
410      format( ' ','Units: ',a/
     1           ' ','Cut line taken at ',a1,' = ',1pg12.5,' ',a/
     1           ' ','Cut plane at ',a1,' = ',1pg12.5,' ',a//)
415      format( ' ','Units: ',a/
     1           ' ','Integration done in ',a1,' direction'/
     1           ' ','Cut plane at ',a1,' = ',1pg12.5,' ',a//)
416      format( ' ','Units: ',a/
     1           ' ','Cut line taken at ',1pg12.5,' from interface'/
     1           ' ','Cut plane at ',a1,' = ',1pg12.5,' ',a//)
420      format( ' ','Taken from binary file:'/
     1           ' ',a//
     1           ' ','Source voltage = ',f8.3/
     1           ' ','Gate   voltage = ',f8.3/
     1           ' ','Drain  voltage = ',f8.3/
     1           ' ','Bulk   voltage = ',f8.3//
     1           ' ','Drain  current  = ',1pe12.3/
     1           ' ','Source current  = ',1pe12.3/
     1           ' ','Bulk   current  = ',1pe12.3/
     1           ' ','----------')
425      format( ' ','Taken from data file:'/
     1           ' ',a//
     1           ' ','----------')
430      format( ' ','Line color:   ',a15,'  (',i3,')')
431      format( ' ','Line type:    ',a15,'  (',i3,')')
432      format( ' ','Line width:   ',f5.3)
433      format( ' ','Symbol color: ',a15,'  (',i3,')')
434      format( ' ','Symbol type:  ',a15,'  (',i3,')')
435      format( ' ','Symbol size:  ',f5.3/
     1           ' ','----------'//)
c
      endif
      call get_char(answer,'More entries to display? (Y/N) ',0)
      call upcase(answer)
      if( answer .eq. 'Y' ) goto 1000
c
      return
      end
c
c*******************************************************************
c
      integer function find_new_entry()
      implicit none
c
c     Find empty slot in multi_1d to store data.c
c     Returns next entry number if there is room.
c     Returns -1 if no room.
c
      include 'const.h'
      include 'sysdep.cmn'
      include 'compare.cmn'
c
c     locals
c
      integer i, slot, ierr
c
      slot = -1
      do 10 i=1, MULTI_SIZE
         if( .not. in_use(i) ) then
            slot = i
            goto 20
         endif
10       continue
20    continue
      if( slot .ne. -1 ) then
c        clear out record entries
c        Arrays are dynamically allocated, so they are not cleared here
         multi_1d(slot)%vd = 0.0
         multi_1d(slot)%vs = 0.0
         multi_1d(slot)%vg = 0.0
         multi_1d(slot)%vb = 0.0
         multi_1d(slot)%id = 0.0
         multi_1d(slot)%is = 0.0
         multi_1d(slot)%ib = 0.0
         multi_1d(slot)%cut_line_coord = 0.0
         multi_1d(slot)%np = 0
         multi_1d(slot)%type = 0
         multi_1d(slot)%binfilename = ' '
         multi_1d(slot)%label = ' '
         multi_1d(slot)%quantity = ' '
         multi_1d(slot)%nickname = ' '
         multi_1d(slot)%units = ' '
         multi_1d(slot)%int_units = ' '
         multi_1d(slot)%cut_line_axis = ' '
         multi_1d(slot)%linewidth    = 1.0
         multi_1d(slot)%marker_scale = 1.0
         multi_1d(slot)%col_x = 0
         multi_1d(slot)%col_y(1) = 0
         multi_1d(slot)%n_ycols = 1
         multi_1d(slot)%col_z = 0
         multi_1d(slot)%ax    = 0.0
         multi_1d(slot)%ay    = 0.0
         multi_1d(slot)%az    = 0.0
         multi_1d(slot)%mx    = 1.0
         multi_1d(slot)%my    = 1.0
         multi_1d(slot)%mz    = 1.0
         multi_1d(slot)%int_limits(1) = 0.0
         multi_1d(slot)%int_limits(2) = 0.0
         multi_1d(slot)%skip  = 0
         multi_1d(slot)%lines_to_read  = 0
         multi_1d(slot)%sample_freq  = 1
         multi_1d(slot)%sweep = .FALSE.
         multi_1d(slot)%log   = .FALSE.
         multi_1d(slot)%xabs = .FALSE.
         multi_1d(slot)%yabs = .FALSE.
         multi_1d(slot)%zabs = .FALSE.
         multi_1d(slot)%sort = .FALSE.
         multi_1d(slot)%suppress = .FALSE.
         multi_1d(slot)%contour  = .FALSE.
         multi_1d(slot)%errorbars = .FALSE.
         multi_1d(slot)%x_char_data = .FALSE.
c        mark new entry
         in_use(slot) = .TRUE.
         n_cuts = n_cuts + 1
         multi_1d(slot)%color = n_cuts
         multi_1d(slot)%linestyle = 1
         multi_1d(slot)%marker_color = n_cuts
         multi_1d(slot)%marker_type  = 0
         multi_1d(slot)%selected = 1
         slot_index(n_cuts) = slot
         find_new_entry = n_cuts
      else
         find_new_entry = -1
      endif
c
      return
      end
c
c*******************************************************************
c
      integer function delete_entry(index)
      implicit none
c
c     Deletes slot in multi_1d array
c
      include 'const.h'
      include 'sysdep.cmn'
      include 'compare.cmn'
      integer index
c
c     locals
c
      integer i, slot
c
      if( index .lt. 1 .or. index .gt. n_cuts ) then
c        Illegal index number...
         delete_entry = -1
         return
      endif
c
c     Find slot number given plot index number
      slot = slot_index(index)
      if ( .not. in_use(slot) ) then
c        Already free
         delete_entry = -2
         return
      else
c        Deallocate dynamic arrays
c        Note: during plot restore, we can allocate an entry and then
c        delete it without ever allocating the dynamic arrays
         if( associated(multi_1d(slot)%data) ) then
            deallocate(multi_1d(slot)%data)
            deallocate(multi_1d(slot)%coord)
            deallocate(multi_1d(slot)%raw_data)
            deallocate(multi_1d(slot)%raw_coord)
         endif
         if( associated(multi_1d(slot)%raw_zval) ) then
            deallocate(multi_1d(slot)%zval)
            deallocate(multi_1d(slot)%raw_zval)
         endif
c        Move everyone up a notch.
         do 10 i=index, n_cuts-1
            slot_index(i) = slot_index(i+1)
10       continue
         in_use(slot) = .FALSE.  ! mark as empty
         slot_index(n_cuts) = -1
         n_cuts = n_cuts - 1
      endif
      delete_entry = 0
      return
      end
c
c*******************************************************************
c
      subroutine pm_init_comp_sticky
      implicit none
c
c     Initialize "sticky" information for comparison plots
c
      include 'const.h'
      include 'sysdep.cmn'
      include 'gksdefs.cmn'
      include 'defaults.cmn'
      include 'compare.cmn'
c
      comp_horiz_label(1) = ' '
      comp_vert_label(1)  = ' '
      comp_hunits(1) = ' '
      comp_vunits(1) = ' '
      comp_h_used(1)  = .TRUE.
      comp_h_used(2)  = .FALSE.
      comp_horiz_label(2) = ' '
      comp_vert_label(2)  = ' '
      comp_hunits(2) = ' '
      comp_vunits(2) = ' '
      comp_v_used(1)  = .TRUE.
      comp_v_used(2)  = .FALSE.
      comp_nolabels   = .FALSE.
c
c     New stuff for Curv compatibility
c
c     Make sure we're in standard Postmini plot mode
      l_curv = .FALSE.
      comp_h_minortic_size(1) = 0.025
      comp_h_minortic_size(2) = 0.025
      comp_v_minortic_size(1) = 0.025
      comp_v_minortic_size(2) = 0.025
      comp_h_lminortic_size(1) = 0.0125
      comp_h_lminortic_size(2) = 0.0125
      comp_v_lminortic_size(1) = 0.0125
      comp_v_lminortic_size(2) = 0.0125
      comp_h_majortic_factor(1) = 2.0
      comp_h_majortic_factor(2) = 2.0
      comp_v_majortic_factor(1) = 2.0
      comp_v_majortic_factor(2) = 2.0
      comp_h_thickness(1) = 1.0
      comp_h_thickness(2) = 1.0
      comp_v_thickness(1) = 1.0
      comp_v_thickness(2) = 1.0
      comp_h_format(1) = ' '
      comp_h_format(2) = ' '
      comp_v_format(1) = ' '
      comp_v_format(2) = ' '
      comp_h_nonumbering(1) = .FALSE.
      comp_h_nonumbering(2) = .FALSE.
      comp_v_nonumbering(1) = .FALSE.
      comp_v_nonumbering(2) = .FALSE.
      comp_h_omit(1) = .FALSE.
      comp_h_omit(2) = .FALSE.
      comp_v_omit(1) = .FALSE.
      comp_v_omit(2) = .FALSE.
      comp_h_color(1) = 1
      comp_h_color(2) = 1
      comp_v_color(1) = 1
      comp_v_color(2) = 1
c
      comp_h_major_grid(1) = .FALSE.
      comp_h_major_grid(2) = .FALSE.
      comp_h_minor_grid(1) = .FALSE.
      comp_h_minor_grid(2) = .FALSE.
      comp_h_major_grid_linetype(1) = GKS$K_LINETYPE_SOLID
      comp_h_major_grid_linetype(2) = GKS$K_LINETYPE_SOLID
      comp_h_minor_grid_linetype(1) = GKS$K_LINETYPE_DOTTED
      comp_h_minor_grid_linetype(2) = GKS$K_LINETYPE_DOTTED
c
      comp_v_major_grid(1) = .FALSE.
      comp_v_major_grid(2) = .FALSE.
      comp_v_minor_grid(1) = .FALSE.
      comp_v_minor_grid(2) = .FALSE.
      comp_v_major_grid_linetype(1) = GKS$K_LINETYPE_SOLID
      comp_v_major_grid_linetype(2) = GKS$K_LINETYPE_SOLID
      comp_v_minor_grid_linetype(1) = GKS$K_LINETYPE_DOTTED
      comp_v_minor_grid_linetype(2) = GKS$K_LINETYPE_DOTTED
c
      return
      end
