!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! J. Pety (2003)
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
if exist(window_init) then
   ! If only help, display and return
   if (pro%narg.ge.1) then
      if (pro%arg[1].eq."help") then
         @ window_tools_help
         return
      endif
   endif
   @ window_init ! Reset reasonnable default, each time the procedure is loaded
   return ! Was missing - everything executed twice...
endif
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
begin procedure window_tools_help
  say ""
  say "The procedure provides useful procedures and parameters for defining"
  say "plots in Greg. Once window_tools has been executed, access to the tools"
  say "is available. Usage:"
  say "  @ window_tools: load the procedures and define the parameters"
  say "  @ window_tools help: show this help."
  say ""
  say "@ full_position: define the 'position' parameter for best use of the"
  say "     plot page (see description of this tuning parameter below). This"
  say "     is default at startup."
  say "@ plot_position: define the 'position' parameter for best use of the"
  say "     plot page in the context of a plot+header (plot part)."
  say "@ header_position: define the 'position' parameter for best use of the"
  say "     plot page in the context of a plot+header (header part)."
  say "The above procedures should be (re)executed if the plot page has"
  say "changed."
  say ""
  say "@ window_xy: is a flexible overlay to the command G\SET BOX_LOCATION,"
  say "     suited for many uses like several boxes in the plot, tuning"
  say "     aspect ratios, margins, and box separation. This command does not"
  say "     draw anything, it just sets the box location. Usage:"
  say "     @ window_xy Nx Ny I: set the location of the I-th box (flat"
  say "                          numbering) in a grid of Nx*Ny boxes,"
  say "     @ window_xy Nx Ny Ix Iy: set the location of the box number"
  say "                          [Ix,Iy] in a grid of Nx*Ny boxes,"
  say "For example, @ window_xy 1 1 1 prepare the location for a single box in"
  say "the drawing area (see parameter 'position' below)."
  say ""
  say "Tuning parameters:"
  say "  aspect_ratio [yes/no]: should the aspect ratio of the box be forced?"
  say "     Default is yes."
  say "  aspect [value]: the desired aspect ratio (aspect>1 means X range"
  say "     larger than Y range). Default is 1."
  say "  position [Xmin Xmax Ymin Ymax]: the area of the plot page to be used"
  say "     by the box(es). Unit is in fraction of the smallest side for both"
  say "     directions, e.g. 0.1 0.9 0.1 1.4. Using the same unit in both"
  say "     direction ensure that the same value correspond to the same length"
  say "     on the plot."
  say "  inter [X Y]: the interspace between the boxes in the grid, in user"
  say "     units (as defined by a previous call to G\LIMITS). Default is 0."
  say "  fixed_trc [yes/no]: ? Default is no."
  say ""
  say "Example:"
  say "    clear"
  say "    @ window_tools"
  say "    let inter 0.1 0.0"
  say "    let aspect_ratio no"
  say "    @ window_xy 2 1 1 1"
  say "    box n n"
  say "    @ window_xy 2 3 2 1"
  say "    box n n"
  say "    @ window_xy 2 3 2 2"
  say "    box n n"
  say "    @ window_xy 2 3 2 3"
  say "    box n n"
  say ""
end procedure window_tools_help
!
begin procedure xy_limits
  !
  define real xmin xmax ymin ymax xrange yrange
  define char xlog*32 ylog*32
  !
  sic\compute xmin min &1
  sic\compute xmax max &1
  sic\compute ymin min &2
  sic\compute ymax max &2
  !
  if (("&3a".eq."/xloga").or.("&4a".eq."/xloga")) then
     !
     let xrange log(xmax)-log(xmin)
     let xmin exp(log(xmin)-0.1*xrange)
     let xmax exp(log(xmax)+0.1*xrange)
     !
     let xlog "log"
     !
  else
     !
     let xrange xmax-xmin
     let xmin xmin-0.1*xrange
     let xmax xmax+0.1*xrange
     !
     let xlog " "
     !
  endif
  !
  if (("&3a".eq."/yloga").or.("&4a".eq."/yloga")) then
     !
     let yrange log(ymax)-log(ymin)
     let ymin exp(log(ymin)-0.1*yrange)
     let ymax exp(log(ymax)+0.1*yrange)
     !
     let ylog "log"
  else
     !
     let yrange ymax-ymin
     let ymin ymin-0.1*yrange
     let ymax ymax+0.1*yrange
     !
     let ylog " "
     !
  endif
  !
  if ((xmin.ne.xmax).and.(ymin.ne.ymax)) then
     if ((xlog.eq."log").and.(ylog.eq."log")) then
        greg1\limits xmin xmax ymin ymax /xlog /ylog
     else if (xlog.eq."log") then
        greg1\limits xmin xmax ymin ymax /xlog
     else if (ylog.eq."log") then
        greg1\limits xmin xmax ymin ymax /ylog
     else
        greg1\limits xmin xmax ymin ymax
     endif
  else if (xmin.ne.xmax) then
     if (xlog.eq."log") then
        greg1\limits xmin xmax = = /xlog
     else
        greg1\limits xmin xmax = =
     endif
  else if (ymin.ne.ymax) then
     greg1\limits = = ymin ymax
     if (ylog.eq."log") then
        limits = = ymin ymax /ylog
     else
        limits = = ymin ymax
     endif
  else
     greg1\limits = = = =
  endif
  !
end procedure xy_limits
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
begin procedure find_nx_ny
  !
  ! Find horizontal (nx_box) and vertical (ny_box) number of box to fill
  ! as best as possible a square area with nbox boxes.
  !
  if ((nxy_box[1].ne.0).and.(nxy_box[2].ne.0)) then
     ! User defined number of box.
     let nx_box nxy_box[1]
     let ny_box nxy_box[2]
  else
     ! Automatic definition: box nx_box and ny_box must be non-zero.
     if (nxy_box[1].ne.0) then
        message w find_nx_ny "ny_box can not be zero, when nx_box is zero"
     endif
     if (nxy_box[2].ne.0) then
        message w find_nx_ny "nx_box can not be zero, when ny_box is zero"
     endif
     !
     define integer nbox
     !
     if ("&1none".ne."none") then
        let nbox &1
     else
        message e find_nx_ny "should give the number of box as first argument"
        pause
     endif
     !
     if (aspect.gt.1.d0) then ! ny_box > nx_box
        let ny_box int(sqrt(nbox*aspect+1))
        let nx_box nint(ny_box/aspect)
        if (ny_box*nx_box.lt.nbox) then
           let ny_box ny_box+1
           if (ny_box*nx_box.lt.nbox) then
              let nx_box nx_box+1
           endif
        else if ((ny_box-1)*nx_box.eq.nbox) then
           let ny_box ny_box-1
        endif
     else
        let nx_box int(sqrt(nbox/aspect+1))
        let ny_box nint(nx_box*aspect)
        if (ny_box*nx_box.lt.nbox) then
           let nx_box nx_box+1
           if (ny_box*nx_box.lt.nbox) then
              let ny_box ny_box+1
           endif
        else if ((nx_box-1)*ny_box.eq.nbox) then
           let nx_box nx_box-1
        endif
     endif
  endif
  !
end procedure find_nx_ny
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
begin procedure find_size_margin
  !
  define real xplo yplo x_sym_marg y_sym_marg R R0 R1
  !
  ! Input parameters are interpretated as:
  !     * `nwindowx_int' (&1) is the number of windows on the x axis.
  !     * `nwindowy_int' (&2) is the number of windows on the y axis.
  !
  let nwindowx_int &1
  let nwindowy_int &2
  !
  ! Define size of total plotting area
  let xplo position[2,1]-position[1,1]
  let yplo position[2,2]-position[1,2]
  !
  ! If white interspaces are asked, just need to redefine the number
  ! of windows.
  if ((inter[1].ne.0.0).or.(inter[2].ne.0.0)) then
     let nwindowx nwindowx_int*(1.0+inter[1])-inter[1]
     let nwindowy nwindowy_int*(1.0+inter[2])-inter[2]
  else
     let nwindowx nwindowx_int
     let nwindowy nwindowy_int
  endif
  !
  ! The margin defining the plotting region are defined through the
  ! global variable "position". But when we want to respect the image
  ! aspect ratio, we have to enlarge either the x or y one depending on
  ! the ratio.
  let x_sym_marg 0.0
  let y_sym_marg 0.0
  if (aspect_ratio) then
     !
     ! Verify aspect ratio value.
     if (aspect.le.0.0) then
        say "Negative or zero aspect ratio!"
        exa aspect
        return base
     endif
     !
     ! Computes the image size when using all the available plotting area.
     let wxsize xplo/nwindowx
     let wysize yplo/nwindowy
     !
     ! Computes the corresponding aspect ratio (`R'), the image aspect
     ! ratio in normal coordinates (`R0') and another needed parameter
     ! (`R1').
     let R  wxsize/wysize
     let R0 aspect
     let R1 R0*nwindowx/nwindowy
     !
     ! From the comparison between `R' and `R0', increase either the x
     ! or the y margin size.
     if (R.gt.R0) then
        let x_sym_marg 0.5*(xplo-yplo*R1)
        let y_sym_marg 0.0
     else if (R.lt.R0) then
        let x_sym_marg 0.0
        let y_sym_marg 0.5*(yplo-xplo/R1)
     endif
     !
  endif
  !
  ! Computes the image size in normal coordinates.
  let wxsize ((xplo-2.0*x_sym_marg)/nwindowx)
  let wysize ((yplo-2.0*y_sym_marg)/nwindowy)
  !
  ! Fix the top, right corner when asked.
  if (fixed_trc) then
     let x_sym_marg 2.0*x_sym_marg
     let y_sym_marg 2.0*y_sym_marg
  endif
  !
  ! Define bottom, left corner
  let wxoff position[1,1]+x_sym_marg
  let wyoff position[1,2]+y_sym_marg
  !
  ! Translate to normal (ie between 0 and 1) coordinates
  let plot_page_aspect page_x/page_y
  if (plot_page_aspect.gt.1.0) then
     let  wxoff  wxoff/plot_page_aspect
     let wxsize wxsize/plot_page_aspect
  else
     let  wyoff  wyoff*plot_page_aspect
     let wysize wysize*plot_page_aspect
  endif
  !
end procedure find_size_margin
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
begin procedure find_window_position
  !
  define real inumberx inumbery x1 x2 y1 y2
  !
  ! Input parameters are interpretated either as:
  !     * &1 is the linear window number.
  !     * In this case, origin is on the top, left corner.
  ! or as:
  !     * `inumberx' (&1) as the window number on the x axis.
  !     * `inumbery' (&2) as the window number on the y axis.
  !     * In this case, axis origin is on the bottom, left corner.
  !
  if ("&2a".eq."a") then
     let inumbery int((&1-1)/nwindowx_int)+1
     let inumberx &1-(inumbery-1)*nwindowx_int
     let inumbery (nwindowy_int+1)-inumbery
  else
     let inumberx &1
     let inumbery &2
  endif
  !
  ! If white interspaces are asked, just need to redefine the current
  ! window position.
  if ((inter[1].ne.0.0).or.(inter[2].ne.0.0)) then
     let inumberx (inumberx*(1.0+inter[1])-inter[1])
     let inumbery (inumbery*(1.0+inter[2])-inter[2])
  endif
  !
  ! Computes the image position in normal coordinates.
  let x1 (wxoff+(inumberx-1)*wxsize)
  let y1 (wyoff+(inumbery-1)*wysize)
  let x2 (wxoff+inumberx*wxsize)
  let y2 (wyoff+inumbery*wysize)
  !
  ! Verification
  if ((x1.lt.0.0).or.(x2.gt.1.0)) then
     say "E-WINDOW_XY problem in x direction"
     exa x1
     exa x2
     return base
  endif
  !
  if ((y1.lt.0.0).or.(y2.gt.1.0)) then
     say "E-WINDOW_XY problem in y direction"
     exa y1
     exa y2
     return base
  endif
  !
  greg1\set viewport x1 x2 y1 y2
  !say "Aspect ratio: "'(box_xmax-box_xmin)/(box_ymax-box_ymin)'
  !
end procedure find_window_position
!
begin procedure find_window_number
  ! S.Guilloteau 2017 (see p_popup.greg)
  !
  sic precis auto
  define integer inumberx inumbery inumber
  define real x1 y1 rnumberx rnumbery
  !
  @ plot_position
  define real boxp[4]
  let boxp position*page_y
  greg1\set box 'boxp[1]' 'boxp[2]' 'boxp[3]' 'boxp[4]'
  !
  ! Input parameters are X Y in Absolute coordinates
  !
  ! WXOFF and WXSIZE, as well as WYOFF and WYSIZE are in ViewPort units
  !   (fraction of PAGE_X of PAGE_Y depending on orientation)
  !
  let x1 &1
  let y1 &2
  if (x1.le.box_xmin.or.x1.ge.box_xmax) return
  if (y1.le.box_ymin.or.y1.ge.box_ymax) return
  !
  let x1 (x1/page_x-wxoff)/wxsize
  let y1 (y1/page_y-wyoff)/wysize
  ! At this stage the INTER spaces are not considered...
  !
  ! Computes the image number
  let inumberx int(x1)+1
  let inumbery nwindowy_int-int(y1)
  !
  ! Convert to total number
  let inumber (inumbery-1)*nwindowx_int+inumberx
  say "Box Number "'inumber'" ["'inumberx'","'inumbery'"] "
  if pro%narg.eq.3 then
    let &3 'inumber'
  endif
  !
end procedure find_window_number
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
begin procedure window_xy
  !
  ! Input parameters are interpretated either as:
  !     * `nwindowx' (&1) is the number of windows on the x axis.
  !     * `nwindowy' (&2) is the number of windows on the y axis.
  !     * &3 is the linear window number.
  !     * In this case, origin is on the top, left corner.
  ! or as:
  !     * `nwindowx' (&1) is the number of windows on the x axis.
  !     * `nwindowy' (&2) is the number of windows on the y axis.
  !     * `inumberx' (&3) as the window number on the x axis.
  !     * `inumbery' (&4) as the window number on the y axis.
  !     * In this case, axis origin is on the bottom, left corner.
  !
  @ find_size_margin &1 &2
  @ find_window_position &3 &4
  !
end procedure window_xy
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
begin procedure plot_position
  !---------------------------------------------------------------------
  ! Define 'position' suited for plot+header (plot part)
  !---------------------------------------------------------------------
  !
  if (plot_position[1].eq.0.0) then
     let plot_page_aspect page_x/page_y
     if (plot_page_aspect.ge.1.0) then
        let position 0.171 1.081 0.085 0.995
     else
        let position 0.085 0.995 0.171 1.081
     endif
  else
     let position plot_position
  endif
  !
end procedure plot_position
!
begin procedure header_position
  !---------------------------------------------------------------------
  ! Define 'position' suited for plot+header (header part)
  !---------------------------------------------------------------------
  !
  let plot_page_aspect page_x/page_y
  if (plot_page_aspect.ge.1.0) then
     let position 1.081 1.428 0.085 0.995
  else
     let position 0.085 0.995 1.081 1.428
  endif
  !
end procedure header_position
!
begin procedure full_position
  !---------------------------------------------------------------------
  ! Define 'position' suited for full page plot
  !---------------------------------------------------------------------
  !
  if (page_x.eq.30.and.page_y.eq.21) then
     ! Standard LANDSCAPE
     let position 0.214 1.322 0.125 0.925
  else if (page_x.eq.21.and.page_y.eq.30) then
     ! Standard PORTRAIT
     let position 0.125 0.875 0.1 1.25
  else if (page_x.gt.page_y) then
     ! Non standard landscape, try something not too stupid
     ! Not that much room on right (no label there by default)
     let position 0.125 page_x/page_y-0.1  0.125 0.925
  else
     ! Square or non standard portrait, try something not too stupid
     ! Leave room on top for a title
     let position 0.125 0.875 0.125 page_y/page_x-0.125
  endif
  !
end procedure full_position
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
begin procedure window_init
  !
  let fixed_trc no
  let aspect_ratio yes
  let aspect 1.0
  let inter 0.0
  @ full_position
  !
end procedure window_init
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
if (.not.exist(window_init)) then
   !
   ! Outer parameters
   define logical aspect_ratio fixed_trc /global
   if (.not.exist(aspect)) then
      define real aspect /global
   endif
   define real plot_page_aspect /global
   define real inter[2] position[2,2] /global
   !
   ! Inner parameters
   define logical window_init /global
   define integer nwindowx_int nwindowy_int /global
   define real nwindowx nwindowy wxsize wysize wxoff wyoff /global
   !
endif
!
@ window_init
!
if (pro%narg.ge.1) then
  if (pro%arg[1].eq."help") then
    @ window_tools_help
  endif
endif
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! The end !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
