head	8.7;
access;
symbols;
locks; strict;
comment	@c @;


8.7
date	2026.05.11.12.01.11;	author mcalabre;	state Exp;
branches;
next	8.6;

8.6
date	2026.03.29.13.53.57;	author mcalabre;	state Exp;
branches
	8.6.1.1;
next	8.5;

8.5
date	2025.12.06.13.47.42;	author mcalabre;	state Exp;
branches
	8.5.1.1;
next	8.4;

8.4
date	2024.10.28.13.56.18;	author mcalabre;	state Exp;
branches
	8.4.1.1;
next	8.3;

8.3
date	2024.05.13.16.33.01;	author mcalabre;	state Exp;
branches
	8.3.1.1;
next	8.2;

8.2
date	2023.11.16.10.00.31;	author mcalabre;	state Exp;
branches
	8.2.1.1;
next	8.1;

8.1
date	2023.07.05.17.12.07;	author mcalabre;	state Exp;
branches
	8.1.1.1;
next	8.0;

8.0
date	2023.07.01.06.15.05;	author mcalabre;	state Exp;
branches
	8.0.1.1;
next	7.13;

7.13
date	2022.10.07.03.43.35;	author mcalabre;	state Exp;
branches
	7.13.1.1;
next	7.12;

7.12
date	2022.09.09.04.57.58;	author mcalabre;	state Exp;
branches
	7.12.1.1;
next	7.11;

7.11
date	2022.04.26.06.13.52;	author mcalabre;	state Exp;
branches
	7.11.1.1;
next	7.10;

7.10
date	2022.04.23.14.25.15;	author mcalabre;	state Exp;
branches
	7.10.1.1;
next	7.9;

7.9
date	2022.03.25.15.14.49;	author mcalabre;	state Exp;
branches
	7.9.1.1;
next	7.8;

7.8
date	2022.03.25.06.11.50;	author mcalabre;	state Exp;
branches
	7.8.1.1;
next	7.7;

7.7
date	2021.07.12.06.36.49;	author mcalabre;	state Exp;
branches
	7.7.1.1;
next	7.6;

7.6
date	2021.04.13.12.57.02;	author mcalabre;	state Exp;
branches
	7.6.1.1;
next	7.5;

7.5
date	2021.03.20.05.54.59;	author mcalabre;	state Exp;
branches
	7.5.1.1;
next	7.4;

7.4
date	2021.01.31.02.24.52;	author mcalabre;	state Exp;
branches
	7.4.1.1;
next	7.3;

7.3
date	2020.06.03.03.37.03;	author mcalabre;	state Exp;
branches
	7.3.1.1;
next	7.2;

7.2
date	2020.03.09.07.31.24;	author mcalabre;	state Exp;
branches
	7.2.1.1;
next	7.1;

7.1
date	2019.12.31.13.25.20;	author mcalabre;	state Exp;
branches
	7.1.1.1;
next	6.4;

6.4
date	2019.08.15.09.30.18;	author mcalabre;	state Exp;
branches
	6.4.1.1;
next	6.3;

6.3
date	2019.07.12.07.33.40;	author mcalabre;	state Exp;
branches
	6.3.1.1;
next	6.2;

6.2
date	2018.10.20.10.03.14;	author mcalabre;	state Exp;
branches
	6.2.1.1;
next	6.1;

6.1
date	2018.10.19.08.35.17;	author mcalabre;	state Exp;
branches
	6.1.1.1;
next	5.20;

5.20
date	2018.10.05.05.32.42;	author mcalabre;	state Exp;
branches
	5.20.1.1;
next	5.19;

5.19
date	2018.07.26.15.37.05;	author mcalabre;	state Exp;
branches
	5.19.1.1;
next	5.18;

5.18
date	2018.01.10.08.32.14;	author mcalabre;	state Exp;
branches
	5.18.1.1;
next	5.17;

5.17
date	2017.09.18.08.44.25;	author mcalabre;	state Exp;
branches
	5.17.1.1;
next	5.16;

5.16
date	2017.01.15.04.25.03;	author mcalabre;	state Exp;
branches
	5.16.1.1;
next	5.15;

5.15
date	2016.04.05.12.55.13;	author mcalabre;	state Exp;
branches
	5.15.1.1;
next	5.14;

5.14
date	2016.02.07.10.49.33;	author mcalabre;	state Exp;
branches
	5.14.1.1;
next	5.13;

5.13
date	2016.01.26.08.51.16;	author mcalabre;	state Exp;
branches
	5.13.1.1;
next	5.12;

5.12
date	2015.11.15.02.13.03;	author mcalabre;	state Exp;
branches
	5.12.1.1;
next	5.11;

5.11
date	2015.10.18.09.13.08;	author mcalabre;	state Exp;
branches
	5.11.1.1;
next	5.10;

5.10
date	2015.10.09.08.19.18;	author mcalabre;	state Exp;
branches
	5.10.1.1;
next	5.9;

5.9
date	2015.07.21.09.20.04;	author mcalabre;	state Exp;
branches
	5.9.1.1;
next	5.8;

5.8
date	2015.07.08.11.04.03;	author mcalabre;	state Exp;
branches
	5.8.1.1;
next	5.7;

5.7
date	2015.06.29.02.44.19;	author mcalabre;	state Exp;
branches
	5.7.1.1;
next	5.6;

5.6
date	2015.06.14.07.11.26;	author mcalabre;	state Exp;
branches
	5.6.1.1;
next	5.5;

5.5
date	2015.05.05.13.16.34;	author mcalabre;	state Exp;
branches
	5.5.1.1;
next	5.4;

5.4
date	2015.04.21.14.41.08;	author mcalabre;	state Exp;
branches
	5.4.1.1;
next	5.3;

5.3
date	2015.04.21.02.50.54;	author mcalabre;	state Exp;
branches
	5.3.1.1;
next	5.2;

5.2
date	2015.04.15.12.35.10;	author mcalabre;	state Exp;
branches
	5.2.1.1;
next	5.1;

5.1
date	2015.04.07.10.56.39;	author mcalabre;	state Exp;
branches
	5.1.1.1;
next	5.0;

5.0
date	2015.04.05.12.25.03;	author mcalabre;	state Exp;
branches
	5.0.1.1;
next	4.25;

4.25
date	2014.12.14.14.29.38;	author mcalabre;	state Exp;
branches
	4.25.1.1;
next	4.24;

4.24
date	2014.09.18.15.25.02;	author mcalabre;	state Exp;
branches
	4.24.1.1;
next	4.23;

4.23
date	2014.05.13.05.50.53;	author mcalabre;	state Exp;
branches
	4.23.1.1;
next	4.22;

4.22
date	2014.04.12.15.03.54;	author mcalabre;	state Exp;
branches
	4.22.1.1;
next	4.21;

4.21
date	2014.03.24.05.12.29;	author mcalabre;	state Exp;
branches
	4.21.1.1;
next	4.20;

4.20
date	2013.12.18.05.42.51;	author mcalabre;	state Exp;
branches
	4.20.1.1;
next	4.19;

4.19
date	2013.09.29.14.17.53;	author mcalabre;	state Exp;
branches
	4.19.1.1;
next	4.18;

4.18
date	2013.07.13.10.00.06;	author mcalabre;	state Exp;
branches
	4.18.1.1;
next	4.17;

4.17
date	2013.01.29.05.29.22;	author cal103;	state Exp;
branches
	4.17.1.1;
next	4.16;

4.16
date	2012.11.07.04.42.45;	author cal103;	state Exp;
branches
	4.16.1.1;
next	4.15;

4.15
date	2012.09.26.14.26.06;	author cal103;	state Exp;
branches
	4.15.1.1;
next	4.14;

4.14
date	2012.07.13.10.02.47;	author cal103;	state Exp;
branches
	4.14.1.1;
next	4.13;

4.13
date	2012.03.14.07.39.31;	author cal103;	state Exp;
branches
	4.13.1.1;
next	4.12;

4.12
date	2012.02.29.07.57.57;	author cal103;	state Exp;
branches
	4.12.1.1;
next	4.11;

4.11
date	2012.02.20.23.30.03;	author cal103;	state Exp;
branches
	4.11.1.1;
next	4.10;

4.10
date	2012.02.05.23.41.45;	author cal103;	state Exp;
branches
	4.10.1.1;
next	4.9;

4.9
date	2012.01.24.05.40.30;	author cal103;	state Exp;
branches
	4.9.1.1;
next	4.8;

4.8
date	2011.08.15.08.05.55;	author cal103;	state Exp;
branches
	4.8.1.1;
next	4.7;

4.7
date	2011.02.07.07.03.43;	author cal103;	state Exp;
branches
	4.7.1.1;
next	4.6;

4.6
date	2010.11.16.06.15.32;	author cal103;	state Exp;
branches
	4.6.1.1;
next	4.5;

4.5
date	2010.07.16.07.01.27;	author cal103;	state Exp;
branches
	4.5.1.1;
next	4.4;

4.4
date	2009.08.06.07.54.40;	author cal103;	state Exp;
branches
	4.4.1.1;
next	4.3;

4.3
date	2007.12.27.05.49.14;	author cal103;	state Exp;
branches
	4.3.1.1;
next	4.2;

4.2
date	2005.09.21.13.27.15;	author cal103;	state Exp;
branches
	4.2.1.1;
next	4.1;

4.1
date	2005.08.26.13.03.06;	author cal103;	state Exp;
branches;
next	4.0;

4.0
date	2005.02.04.12.21.32;	author cal103;	state Exp;
branches;
next	3.6;

3.6
date	2004.08.24.08.36.29;	author cal103;	state Exp;
branches;
next	3.5;

3.5
date	2004.06.28.05.31.36;	author mcalabre;	state Exp;
branches;
next	3.4;

3.4
date	2004.02.10.23.56.37;	author mcalabre;	state Exp;
branches;
next	3.3;

3.3
date	2003.10.22.08.30.06;	author mcalabre;	state Exp;
branches;
next	3.2;

3.2
date	2003.09.09.08.00.24;	author mcalabre;	state Exp;
branches;
next	3.1;

3.1
date	2003.04.28.08.54.22;	author mcalabre;	state Exp;
branches;
next	1.9;

1.9
date	2002.11.06.06.45.34;	author mcalabre;	state Exp;
branches;
next	1.8;

1.8
date	2001.12.07.06.08.27;	author mcalabre;	state Exp;
branches;
next	1.7;

1.7
date	2001.11.21.00.28.20;	author mcalabre;	state Exp;
branches;
next	1.6;

1.6
date	2001.02.23.00.36.34;	author mcalabre;	state Exp;
branches;
next	1.5;

1.5
date	2001.02.19.02.18.18;	author mcalabre;	state Exp;
branches;
next	1.4;

1.4
date	2000.11.28.02.19.51;	author mcalabre;	state Exp;
branches;
next	1.3;

1.3
date	2000.11.16.01.07.29;	author mcalabre;	state Exp;
branches;
next	1.2;

1.2
date	2000.11.15.06.44.37;	author mcalabre;	state Exp;
branches;
next	1.1;

1.1
date	2000.11.13.07.17.22;	author mcalabre;	state Exp;
branches;
next	;

4.2.1.1
date	2005.12.05.03.23.34;	author cal103;	state Exp;
branches;
next	4.2.1.2;

4.2.1.2
date	2005.12.05.03.26.34;	author cal103;	state Exp;
branches;
next	4.2.1.3;

4.2.1.3
date	2005.12.06.06.46.09;	author cal103;	state Exp;
branches;
next	4.2.1.4;

4.2.1.4
date	2007.12.03.05.41.29;	author cal103;	state Exp;
branches;
next	;

4.3.1.1
date	2007.12.27.13.26.31;	author cal103;	state Exp;
branches;
next	4.3.1.2;

4.3.1.2
date	2009.07.23.04.17.17;	author cal103;	state Exp;
branches;
next	4.3.1.3;

4.3.1.3
date	2009.08.04.04.51.22;	author cal103;	state Exp;
branches;
next	4.3.1.4;

4.3.1.4
date	2009.08.04.06.48.38;	author cal103;	state Exp;
branches;
next	4.3.1.5;

4.3.1.5
date	2009.08.04.08.12.29;	author cal103;	state Exp;
branches;
next	;

4.4.1.1
date	2009.08.10.08.55.45;	author cal103;	state Exp;
branches;
next	4.4.1.2;

4.4.1.2
date	2010.01.19.03.45.24;	author cal103;	state Exp;
branches;
next	;

4.5.1.1
date	2010.07.16.07.05.33;	author cal103;	state Exp;
branches;
next	;

4.6.1.1
date	2010.11.16.06.16.20;	author cal103;	state Exp;
branches;
next	4.6.1.2;

4.6.1.2
date	2011.01.14.06.35.20;	author cal103;	state Exp;
branches;
next	4.6.1.3;

4.6.1.3
date	2011.01.25.00.50.51;	author cal103;	state Exp;
branches;
next	;

4.7.1.1
date	2011.02.07.07.04.23;	author cal103;	state Exp;
branches;
next	;

4.8.1.1
date	2011.08.15.08.07.07;	author cal103;	state Exp;
branches;
next	4.8.1.2;

4.8.1.2
date	2012.01.24.05.24.50;	author cal103;	state Exp;
branches;
next	;

4.9.1.1
date	2012.01.24.05.41.46;	author cal103;	state Exp;
branches;
next	;

4.10.1.1
date	2012.02.05.23.42.47;	author cal103;	state Exp;
branches;
next	;

4.11.1.1
date	2012.02.20.23.31.14;	author cal103;	state Exp;
branches;
next	;

4.12.1.1
date	2012.02.29.07.59.11;	author cal103;	state Exp;
branches;
next	;

4.13.1.1
date	2012.03.14.07.40.39;	author cal103;	state Exp;
branches;
next	4.13.1.2;

4.13.1.2
date	2012.07.13.03.43.52;	author cal103;	state Exp;
branches;
next	;

4.14.1.1
date	2012.07.13.10.05.05;	author cal103;	state Exp;
branches;
next	4.14.1.2;

4.14.1.2
date	2012.07.31.10.48.02;	author cal103;	state Exp;
branches;
next	;

4.15.1.1
date	2012.09.26.14.27.53;	author cal103;	state Exp;
branches;
next	;

4.16.1.1
date	2012.11.07.04.45.58;	author cal103;	state Exp;
branches;
next	4.16.1.2;

4.16.1.2
date	2013.01.29.05.11.32;	author cal103;	state Exp;
branches;
next	;

4.17.1.1
date	2013.01.29.05.32.33;	author cal103;	state Exp;
branches;
next	;

4.18.1.1
date	2013.07.13.10.02.40;	author mcalabre;	state Exp;
branches;
next	;

4.19.1.1
date	2013.09.29.14.20.41;	author mcalabre;	state Exp;
branches;
next	4.19.1.2;

4.19.1.2
date	2013.12.10.23.13.17;	author mcalabre;	state Exp;
branches;
next	;

4.20.1.1
date	2013.12.18.05.46.57;	author mcalabre;	state Exp;
branches;
next	4.20.1.2;

4.20.1.2
date	2014.03.21.06.45.26;	author mcalabre;	state Exp;
branches;
next	;

4.21.1.1
date	2014.03.24.05.15.31;	author mcalabre;	state Exp;
branches;
next	;

4.22.1.1
date	2014.04.12.15.06.34;	author mcalabre;	state Exp;
branches;
next	;

4.23.1.1
date	2014.05.13.05.53.52;	author mcalabre;	state Exp;
branches;
next	;

4.24.1.1
date	2014.09.18.15.28.12;	author mcalabre;	state Exp;
branches;
next	;

4.25.1.1
date	2014.12.14.14.32.48;	author mcalabre;	state Exp;
branches;
next	4.25.1.2;

4.25.1.2
date	2015.01.06.01.03.14;	author mcalabre;	state Exp;
branches;
next	4.25.1.3;

4.25.1.3
date	2015.03.06.11.56.51;	author mcalabre;	state Exp;
branches;
next	;

5.0.1.1
date	2015.04.05.12.28.04;	author mcalabre;	state Exp;
branches;
next	;

5.1.1.1
date	2015.04.07.11.01.13;	author mcalabre;	state Exp;
branches;
next	;

5.2.1.1
date	2015.04.15.12.39.18;	author mcalabre;	state Exp;
branches;
next	;

5.3.1.1
date	2015.04.21.02.54.06;	author mcalabre;	state Exp;
branches;
next	;

5.4.1.1
date	2015.04.21.14.44.32;	author mcalabre;	state Exp;
branches;
next	;

5.5.1.1
date	2015.05.05.13.21.04;	author mcalabre;	state Exp;
branches;
next	;

5.6.1.1
date	2015.06.14.07.14.48;	author mcalabre;	state Exp;
branches;
next	;

5.7.1.1
date	2015.06.29.02.47.27;	author mcalabre;	state Exp;
branches;
next	;

5.8.1.1
date	2015.07.08.11.07.22;	author mcalabre;	state Exp;
branches;
next	;

5.9.1.1
date	2015.07.21.09.28.12;	author mcalabre;	state Exp;
branches;
next	;

5.10.1.1
date	2015.10.09.08.22.40;	author mcalabre;	state Exp;
branches;
next	;

5.11.1.1
date	2015.10.18.09.16.31;	author mcalabre;	state Exp;
branches;
next	;

5.12.1.1
date	2015.11.15.02.16.18;	author mcalabre;	state Exp;
branches;
next	5.12.1.2;

5.12.1.2
date	2016.01.25.05.22.41;	author mcalabre;	state Exp;
branches;
next	;

5.13.1.1
date	2016.01.26.08.54.36;	author mcalabre;	state Exp;
branches;
next	;

5.14.1.1
date	2016.02.07.10.52.48;	author mcalabre;	state Exp;
branches;
next	;

5.15.1.1
date	2016.04.05.12.58.39;	author mcalabre;	state Exp;
branches;
next	5.15.1.2;

5.15.1.2
date	2017.01.15.04.08.24;	author mcalabre;	state Exp;
branches;
next	;

5.16.1.1
date	2017.01.15.04.29.04;	author mcalabre;	state Exp;
branches;
next	;

5.17.1.1
date	2017.09.18.08.46.01;	author mcalabre;	state Exp;
branches;
next	5.17.1.2;

5.17.1.2
date	2018.01.10.08.27.33;	author mcalabre;	state Exp;
branches;
next	;

5.18.1.1
date	2018.01.10.08.33.04;	author mcalabre;	state Exp;
branches;
next	;

5.19.1.1
date	2018.07.26.15.41.42;	author mcalabre;	state Exp;
branches;
next	;

5.20.1.1
date	2018.10.05.05.33.33;	author mcalabre;	state Exp;
branches;
next	;

6.1.1.1
date	2018.10.19.08.36.15;	author mcalabre;	state Exp;
branches;
next	;

6.2.1.1
date	2018.10.20.10.04.15;	author mcalabre;	state Exp;
branches;
next	6.2.1.2;

6.2.1.2
date	2019.05.10.02.13.12;	author mcalabre;	state Exp;
branches;
next	6.2.1.3;

6.2.1.3
date	2019.07.09.13.47.10;	author mcalabre;	state Exp;
branches;
next	;

6.3.1.1
date	2019.07.12.07.34.37;	author mcalabre;	state Exp;
branches;
next	;

6.4.1.1
date	2019.08.15.09.31.29;	author mcalabre;	state Exp;
branches;
next	6.4.1.2;

6.4.1.2
date	2019.12.31.03.29.47;	author mcalabre;	state Exp;
branches;
next	;

7.1.1.1
date	2019.12.31.13.28.19;	author mcalabre;	state Exp;
branches;
next	;

7.2.1.1
date	2020.03.09.07.34.50;	author mcalabre;	state Exp;
branches;
next	;

7.3.1.1
date	2020.06.03.03.38.11;	author mcalabre;	state Exp;
branches;
next	7.3.1.2;

7.3.1.2
date	2021.01.19.14.12.19;	author mcalabre;	state Exp;
branches;
next	7.3.1.3;

7.3.1.3
date	2021.01.28.12.32.51;	author mcalabre;	state Exp;
branches;
next	;

7.4.1.1
date	2021.01.31.02.26.24;	author mcalabre;	state Exp;
branches;
next	;

7.5.1.1
date	2021.03.20.05.56.42;	author mcalabre;	state Exp;
branches;
next	;

7.6.1.1
date	2021.04.13.13.00.37;	author mcalabre;	state Exp;
branches;
next	7.6.1.2;

7.6.1.2
date	2021.07.01.14.45.37;	author mcalabre;	state Exp;
branches;
next	;

7.7.1.1
date	2021.07.12.06.38.28;	author mcalabre;	state Exp;
branches;
next	7.7.1.2;

7.7.1.2
date	2022.03.25.06.06.01;	author mcalabre;	state Exp;
branches;
next	;

7.8.1.1
date	2022.03.25.06.14.15;	author mcalabre;	state Exp;
branches;
next	;

7.9.1.1
date	2022.03.25.15.16.40;	author mcalabre;	state Exp;
branches;
next	;

7.10.1.1
date	2022.04.23.14.26.55;	author mcalabre;	state Exp;
branches;
next	;

7.11.1.1
date	2022.04.26.06.15.33;	author mcalabre;	state Exp;
branches;
next	;

7.12.1.1
date	2022.09.09.05.00.36;	author mcalabre;	state Exp;
branches;
next	;

7.13.1.1
date	2022.10.07.03.45.47;	author mcalabre;	state Exp;
branches;
next	7.13.1.2;

7.13.1.2
date	2023.06.15.04.17.22;	author mcalabre;	state Exp;
branches;
next	;

8.0.1.1
date	2023.07.01.06.22.45;	author mcalabre;	state Exp;
branches;
next	;

8.1.1.1
date	2023.07.05.17.15.01;	author mcalabre;	state Exp;
branches;
next	;

8.2.1.1
date	2023.11.16.10.05.59;	author mcalabre;	state Exp;
branches;
next	8.2.1.2;

8.2.1.2
date	2024.04.02.13.43.15;	author mcalabre;	state Exp;
branches;
next	8.2.1.3;

8.2.1.3
date	2024.05.06.09.26.06;	author mcalabre;	state Exp;
branches;
next	;

8.3.1.1
date	2024.05.13.16.35.40;	author mcalabre;	state Exp;
branches;
next	;

8.4.1.1
date	2024.10.28.13.58.42;	author mcalabre;	state Exp;
branches;
next	8.4.1.2;

8.4.1.2
date	2025.12.06.13.37.20;	author mcalabre;	state Exp;
branches;
next	;

8.5.1.1
date	2025.12.06.14.05.17;	author mcalabre;	state Exp;
branches;
next	8.5.1.2;

8.5.1.2
date	2026.03.29.13.21.35;	author mcalabre;	state Exp;
branches;
next	8.5.1.3;

8.5.1.3
date	2026.03.29.13.36.20;	author mcalabre;	state Exp;
branches;
next	;

8.6.1.1
date	2026.03.29.14.19.28;	author mcalabre;	state Exp;
branches;
next	;


desc
@PGPLOT routine to draw and label a non-linear coordinate grid.
@


8.7
log
@WCSLIB 8.7
@
text
@*=======================================================================
*
* PGSBOX 8.7 - draw curvilinear coordinate axes for PGPLOT.
* Copyright (C) 1997-2026, Mark Calabretta
*
* This file is part of PGSBOX.
*
* PGSBOX is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PGSBOX is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with PGSBOX.  If not, see http://www.gnu.org/licenses.
*
* Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
* http://www.atnf.csiro.au/computing/software/wcs
* $Id: pgsbox.f,v 8.6.1.1 2026/03/29 14:19:28 mcalabre Exp mcalabre $
*=======================================================================
*
* PGSBOX draws and labels a curvilinear coordinate grid.  The caller
* must provide a separate external function, NLFUNC, to define the
* non-linear coordinate transformation.
*
* PGLBOX, a simplified ENTRY point to PGSBOX, has been provided for
* drawing simple linear axes without the need to specify NLFUNC.
* PGLBOX allows simplified access to formatting control for labelling
* world coordinate axes that is not provided by the standard PGPLOT
* routines, PGBOX or PGTBOX.  PGLBOX uses the world coordinate range
* set by a prior call to PGSWIN and omits the following arguments:
*
*   BLC, TRC, NLFUNC, NLC, NLI, NLD, NLCPRM, NLIPRM, NLDPRM
*
* The remaining arguments are specified in the same order as PGSBOX.
*
* Given:
*   BLC       R(2)      Cartesian coordinates of the bottom left-hand
*   TRC       R(2)      corner and top right-hand corner of the frame.
*                       Any convenient Cartesian system may be used in
*                       conjunction with the non-linear transformation
*                       function, NLFUNC, described below.
*
*                       For example, FITS images have pixel coordinate
*                       (1,1) at the centre of the pixel in the bottom
*                       left-hand corner.  Thus it would be
*                       appropriate to set BLC to (0.5,0.5) and TRC to
*                       (NAXIS1+0.5, NAXIS2+0.5).
*
*   IDENTS    C(3)*(*)  Identification strings:
*                         1: Name of the first world coordinate
*                            element used for axis labelling.
*                         2: Name of the second world coordinate.
*                         3: Title, written at top.
*
*   OPT       C(2)*(*)  Formatting control for the world coordinates,
*                       used for axis labelling (see notes 1 and 2):
*                         ' ': plain numeric
*                         'A': angle in degrees expressed in decimal
*                              notation normalized in the range [0,360).
*                         'B': as 'A' but normalized in the range
*                              (-180,180].
*                         'C': as 'A' but unnormalized.
*                         'D': angle in degrees expressed in sexagesimal
*                              notation, DD^MM'SS".S, normalized in the
*                              range [0,360).
*                         'E': as 'D' but normalized in the range
*                              (-180,180].
*                         'F': as 'D' but unnormalized.
*                         'G': angle in degrees expressed in hms
*                              notation, HHhMMmSSs.S, normalized in the
*                              range [0,24) hours.
*                         'H': as 'G' but normalized in the range
*                              (-12,12] hours.
*                         'I': as 'G' but unnormalized.
*                         'L': logarithmic (see note 2)
*                         'T': time in hours expressed as HH:MM:SS.S
*                         'Y': Modified Julian Date to be expressed as
*                              a Gregorian calendar date, YYYY/MM/DD.
*                              (MJD = JD - 2400000.5.)
*
*                       For the angular types, NLFUNC is assumed to
*                       return the angle in degrees whereupon it will
*                       be formatted for display in the specified way.
*                       For example, an angle of -417.2958 degrees
*                       (returned by NLFUNC):
*
*                         'A':  302^.7042
*                         'B':  -57^.2958
*                         'C': -417^.2958
*                         'D':  302^42'15"
*                         'E':  -57^17'45"
*                         'F': -417^17'45"
*                         'H':   20h10m49s
*                         'I':   -3h49m11s
*                         'J':  -27h49m11s
*
*                       These are properly superscripted.
*
*   LABCTL    I         Decimal encoded grid labelling control:
*                            -1: Accumulate information on grid labels
*                                (see note 3) but do not write them.
*                             0: Let PGSBOX decide what edges to label.
*                             1: Label bottom of frame with the first
*                                world coordinate.
*                             2: Label bottom of frame with the second
*                                world coordinate.
*                            10: ... left side of frame.
*                            20: ... left side of frame.
*                           100: ... top of frame.
*                           200: ... top of frame.
*                          1000: ... right side of frame.
*                          2000: ... right side of frame.
*                         10000: Write labels from information
*                                accumulated in previous calls without
*                                drawing grid lines or tick marks.
*
*                       LABCTL = 0 usually gets what you want.
*                       LABCTL = 3333 labels all sides with both world
*                       coordinates.
*
*   LABDEN    I         Decimal encoded labelling density control for
*                       use where PGSBOX is called upon to determine a
*                       suitable grid spacing (e.g. via NG1 = 0,
*                       GRID1(0) = 0).  LABDEN = 100*D2 + D1 where
*                       D1, and D2 are the approximate number of grid
*                       lines for the first and second world
*                       coordinate.  LABDEN = 0 is effectively the same
*                       as LABDEN = 808.
*
*   CI        I(7)      Table of predefined colours established by
*                       calls to PGSCR.  This is used to control the
*                       colour used for different parts of the plot.
*                       CI table entries are used as follows:
*
*                                                world
*                                              coordinate
*                       Index      usage        element
*                       -----  --------------  ----------
*                         1      grid lines        1
*                         2      grid lines        2
*                         3    numeric labels      1
*                         4    numeric labels      2
*                         5    axis annotation     1
*                         6    axis annotation     2
*                         7        title           -
*
*                       For example, CI(3) is used for numeric labels
*                       for the first world coordinate.
*
*                       Colour selection is disabled for component J
*                       if CI(J) < 0.
*
*   GCODE(2)  I         Code for the type of grid to draw for each
*                       world coordinate:
*                         0: No grid or tick marks.
*                         1: Tick marks (on all edges).
*                         2: Full coordinate grid.
*
*                       Tick marks can be restricted to particular
*                       edges of the frame; a negative GCODE is
*                       interpreted as a decimal encoded control
*                       variable:
*                            -1: bottom
*                           -10: left
*                          -100: top
*                         -1000: right
*
*                       The digit scales the basic tick length.  For
*                       example, GCODE(1) = -102 restricts tick marks
*                       for the first world coordinate to the bottom
*                       and top edges of the frame.  Those on the
*                       bottom will be twice the length specified by
*                       TIKLEN.
*
*   TIKLEN    D         Tick length, in mm.  Negative values produce
*                       outside tick marks.
*
*   NG1       I         Upper array index for GRID1.
*
*   GRID1     D(0:NG1)  Grid values in WORLD(1) in the same units as
*                       returned by NLFUNC.
*
*                       If NG1 is zero, then
*                         a: if GRID1(0) is greater than zero it
*                            defines a uniform grid spacing.
*                         b: if GRID1(0) is zero a suitable spacing
*                            will be determined (see LABDEN).
*                         c: if GRID1(0) is less than zero then no
*                            grid lines will be drawn.
*
*                       If NG1 is greater than zero, then GRID1(0) is
*                       ignored.
*
*   NG2       I         Upper array index for GRID2.
*
*   GRID2     D(0:NG2)  Grid values in WORLD(2) in the same units as
*                       returned by NLFUNC, interpreted the same way
*                       as GRID1.
*
*   DOEQ      L         If NG1 = NG2 = 0, and GRID1(0) = 0D0 and/or
*                       GRID2(0) = 0D0, then choose the same grid
*                       spacing for each world coordinate.
*
*   NLFUNC    Ext       Non-linear coordinate function, see below.
*
*   NLC       I         Number of elements in NLCPRM (must be >0).
*
*   NLI       I         Number of elements in NLIPRM (must be >0).
*
*   NLD       I         Number of elements in NLDPRM (must be >0).
*
* Given and/or returned:
*   NLCPRM    C(NLC)*1  Character coefficients for NLFUNC.
*
*   NLIPRM    I(NLI)    Integer coefficients for NLFUNC.
*
*   NLDPRM    D(NLD)    Double precision coefficients for NLFUNC.
*
*   NC        I         Upper array index for CACHE (see note 3).
*
*   IC        I         Current number of entries in the CACHE table.
*                       Should be set to -1 on the first call to
*                       PGSBOX (see note 3).
*
*   CACHE     D(4,0:NC) Table of points where the tick marks or grid
*                       lines cross the frame (see note 3).
*                         1: Frame segment
*                            1: bottom
*                            2: left
*                            3: top
*                            4: right
*                         2: X or Y-Cartesian coordinate.
*                         3: World coordinate element (1 or 2).
*                         4: Value.
*
*                       CACHE(,0) is used to cache the extrema of the
*                       coordinate values between calls.  CACHE(1,NC-1)
*                       is also used to store related information.
*
*                       CACHE(,NC) will contain the margin widths in
*                       Cartesian coordinates when the labels are
*                       produced (i.e. the same Cartesian system used
*                       for BLC and TRC).
*
* Returned:
*   IERR      I         Status return value:
*                         0: Success
*                         1: Initialization error
*                         2: Invalid coordinate system
*                         3: Cache overflow (see note 3).
*
* Notes:
*   1: Where a logarithmic world coordinate type is indicated PGSBOX
*      chooses grid lines and labels on the basis that the value
*      returned by NLFUNC is a base 10 logarithm.  PGSBOX does not
*      itself take logarithms or antilogarithms.  For example, if the
*      range of values returned by NLFUNC were 0.9 - 2.5, then PGSBOX
*      would draw a subset of the following set of grid lines and
*      labels:
*
*                 value          label
*          ------------------    -----
*          0.9031 = log10(8)      8
*          0.9542 = log10(9)      9
*          1.0000 = log10(10)    10**1
*          1.3010 = log10(20)     2
*          1.4771 = log10(30)     3
*          1.6021 = log10(40)     4
*          1.6990 = log10(50)     5
*          1.7782 = log10(60)     6
*          1.8451 = log10(70)     7
*          1.9031 = log10(80)     8
*          1.9542 = log10(90)     9
*          2.0000 = log10(100)   10**2
*          2.3010 = log10(200)    2
*          2.4771 = log10(300)    3
*
*      The subset chosen depends on the coordinate increment as
*      specified by the caller (e.g. via NG1 = 0, GRID1(0) > 0) or as
*      deduced by PGSBOX from the required density of grid lines
*      specified in the LABDEN argument.  The selection is made
*      according to the following table:
*
*          increment          grid lines
*         (0.00,0.12]   1, 2, 3, 4, 5, 6, 7, 8, 9
*         (0.12,0.18]   1, 2, 3, 4, 5,    7
*         (0.18,0.23]   1, 2, 3,    5,    7
*         (0.23,0.28]   1, 2, 3,    5
*         (0.28,0.40]   1, 2,       5
*         (0.40,0.70]   1, 3
*         (0.70,1.00]   1
*
*      For increments greater than 1 the nearest integer is used.
*
*   2: PGSBOX will attempt to handle discontinuities in angle, such as
*      may occur when cycling through 360 degrees, wherever the
*      discontinuity may occur, for example
*
*        359 -> 0 -> 1
*
*      or
*
*        179 -> 180 -> -179
*
*      Only single cycles are detected, so the sequence
*
*        -360 -> 0 -> ... -> 359 -> 0 -> ... -> 359
*
*      would not be handled properly.  In such cases NLFUNC should be
*      changed to return a normalized angle, or else a continuous
*      sequence.
*
*   3: PGSBOX maintains a table of axis crossings, CACHE, in which it
*      stores information used for axis labelling.  The caller need not
*      normally be concerned about the use of this table other than to
*      provide sufficient space.  Typically, NC = 256 should be enough;
*      if not, IERR = 3 will be returned.
*
*      However, a coordinate grid may be produced via multiple calls to
*      PGSBOX with deferment of axis labelling.  This might be done to
*      change the pen colour and/or thickness for different sets of
*      grid lines.  The table accumulates information from each
*      successive call until the labels are produced.  The table index,
*      IC, may be reset to zero by the caller to discard the
*      information collected.
*
*      The extrema of the world coordinate elements are stored in
*      CACHE(,0).  When a coordinate grid is plotted with multiple
*      calls to PGSBOX the initial call should always have IC set to -1
*      to signal that PGSBOX needs to determine the extrema.  On
*      subsequent calls with IC non-negative PGSBOX uses the extrema
*      cached from the first call.  This can speed up execution
*      considerably.
*
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* The curvilinear coordinate grid is defined by external function
* NLFUNC whose interface is defined as follows:
*
* Given:
*   OPCODE    I         Transformation code:
*                         +2: Compute a set of Cartesian coordinates
*                             that describe a path between this and
*                             the previous pair of world coordinates
*                             remembered from the last call with
*                             OPCODE = +1 or +2.  Usually only takes
*                             a single step unless traversing a
*                             discontinuity or some other
*                             irregularity (see explanation below).
*                         +1: Compute Cartesian coordinates from world
*                             coordinates.
*                          0: Initialize.
*                         -1: Compute world coordinates from Cartesian
*                             coordinates.
*
*                       N.B. NLFUNC must not change the input
*                       coordinates; that is the world coordinates for
*                       OPCODEs = +2 and +1, or the Cartesian
*                       coordinates for OPCODE = -1.
*
*   NLC       I         Number of elements in NLCPRM (must be >0).
*
*   NLI       I         Number of elements in NLIPRM (must be >0).
*
*   NLD       I         Number of elements in NLDPRM (must be >0).
*
* Given and/or returned:
*   NLCPRM    C(NLC)*1  Character array.
*
*   NLIPRM    I(NLI)    Integer coefficients.
*
*   NLDPRM    D(NLD)    Double precision coefficients.
*
*   WORLD     D(2)      World coordinates.  Given if OPCODE > 0,
*                       returned if OPCODE < 0.
*
*   XY        D(2)      Cartesian coordinates.  Given if OPCODE < 0,
*                       returned if OPCODE > 0.
*
*   CONTRL    I         Control flag for OPCODE = +2:
*                         0: Normal state.
*                         1: Force PGSBOX to flush its plotting buffer
*                            and call NLFUNC again with the same world
*                            coordinates.
*                         2: Force PGSBOX to call NLFUNC again with
*                            the same world coordinates (without
*                            flushing its plotting buffer).
*
*   CONTXT    D(20)     Context elements for OPCODE = +2.
*
* Returned:
*   IERR      I         Status return value:
*                         0: Success.
*                         1: Invalid parameters.
*                         2: Invalid world coordinate.
*                         3: Invalid Cartesian coordinate.
*
*                       The following status returns are recognized for
*                       opcodes +2 and +1
*                         -1: Accept the returned (x,y) coordinates but
*                             do not consider this as one end of a
*                             crossing segment for labelling world
*                             coordinate 1.
*                         -2: Ditto for world coordinate 2.
*                         -3: Ditto for world coordinates 1 and 2.
*
* PGSBOX passes its NLCPRM, NLIPRM, and NLDPRM adjustable size array
* arguments of length NLC, NLI, and NLD to NLFUNC without
* modification.  Comments within NLFUNC should specify the parameters
* it wants passed to it via these arrays.
*
* PGSBOX first calls NLFUNC with OPCODE = 0 to cause it to initialize
* its work arrays (if necessary).  It then uses OPCODE = -1 to
* determine the range of world coordinate values.  It anchors the
* start of each coordinate grid line with a call with OPCODE = +1, and
* then tracks it with OPCODE = +2.
*
* The CONTXT array is also passed to NLFUNC without modification to
* allow it to preserve state information between calls for OPCODE = 2.
* In particular, NLFUNC can use this to detect discontinuities in the
* grid lines.
*
* The CONTRL argument is provided so that NLFUNC can force PGSBOX to
* call it again with or without flushing its plotting buffer.  This
* may be needed when plotting a grid line through a discontinuity.
* PGSBOX does not modify CONTRL.
*
* Notes:
*   1: NLFUNC must not change the input coordinates; that is the world
*      coordinates for OPCODEs = +1 and +2, or the Cartesian coordinates
*      for OPCODE = -1.
*
*   2: NLFUNC must define a single-valued function, that is, each
*      Cartesian coordinate (x,y) must map to a unique world coordinate
*      pair (xi,eta).
*
*   3: Notwithstanding the fact that PGSBOX declares NLCPRM, NLIPRM,
*      and NLDPRM as single dimension arrays of length NLC, NLI, and
*      NLD, NLFUNC may treat these as higher-dimensional arrays, for
*      example, NLDPRM(2,NLD).  (The Fortran standard requires that
*      only the last dimension is adjustable.)
*
*=======================================================================
      SUBROUTINE PGSBOX (BLC_, TRC_, IDENTS, OPT, LABCTL, LABDEN, CI,
     :  GCODE, TIKLEN, NG1, GRID1, NG2, GRID2, DOEQ, NLFUNC, NLC, NLI,
     :  NLD, NLCPRM, NLIPRM, NLDPRM, NC, IC, CACHE, IERR)
*-----------------------------------------------------------------------
      INTEGER   BUFSIZ
      PARAMETER (BUFSIZ = 2048)

      LOGICAL   DOEDGE, DOEQ, DOLBOX, FULLSM, GETEND, INSIDE, ISANGL(2),
     :          LABLOK, MAJOR, OVERFL, PREVIN
      INTEGER   CI(7), CI0, CJ(7), CONTRL, DENS(2), FSEG, GCODE(2), IC,
     :          ID, IERR, IM, ISTEP, IW0, IWJ, IWK, IX, IY, IYPREV, J,
     :          K, KX, L, LABCTL, LABDEN, LDIV(2), LTABL(6,2:6), NC,
     :          NG(2), NG1, NG2, NLC, NLD, NLI, NLIPRM(NLI), NP,
     :          NSTEP(2), NWJ, NX, NY, TCODE(2,4)
      REAL      BLC(2), BLC_(2), RHO, RTIKLN, S, TAU, TRC(2), TRC_(2),
     :          WXY(4), X1, X2, XPOINT, XR(BUFSIZ), XSCL, XSPAN, xSTEP,
     :          XTOL, XVP1, XVP2, Y1, Y2, YR(BUFSIZ), YSCL, YSPAN,
     :          YSTEP, YTOL, YVP1, YVP2
      DOUBLE PRECISION CONTXT(20), CACHE(4,0:NC), DW(2), DX, DY, FACT,
     :          G0(2), GSTEP(2), GRID1(0:NG1), GRID2(0:NG2),
     :          NLDPRM(NLD), STEP, SW(2), TIKLEN, TMP, VMAX(2,2),
     :          VMIN(2,2), W1PREV, W1X0, W2PREV, W2X0, WJUMP, WMAX(2),
     :          WMIN(2), WORLD(9), WRLD(9), XY(9)
      CHARACTER FTYPE(2), IDENTS(3)*(*), NLCPRM(NLC)*1, OPT(2)*(*)

      EXTERNAL NLFUNC

*     Approximate number of grid lines for each coordinate.
      INTEGER DENS0
      PARAMETER (DENS0 = 8)

*     Double precision round-off tolerance.
      REAL    TOL
      PARAMETER (TOL = 1E-8)

*     Number of steps per grid line.
      DATA NSTEP /80, 80/

*     Table of logarithmic grid values.
      DATA LTABL /3, 10,  0,  0,  0,  0,
     :            2,  5, 10,  0,  0,  0,
     :            2,  3,  5, 10,  0,  0,
     :            2,  3,  5,  7, 10,  0,
     :            2,  3,  4,  5,  7, 10/

*     These are to stop compiler messages about uninitialized variables.
      DATA IW0 /0/
      DATA LABLOK, PREVIN /2 * .FALSE./
      DATA G0 /2 * 0D0/
      DATA W1X0, W1PREV, W2X0, W2PREV /4 * 0D0/
      DATA WORLD, XY /9 * 0D0, 9 * 0D0/
*-----------------------------------------------------------------------
*  Initialize.
      DOLBOX = .FALSE.

      CALL NLFUNC (0, NLC, NLI, NLD, NLCPRM, NLIPRM, NLDPRM, WORLD,
     :  XY, CONTRL, CONTXT, IERR)
*     Quick return for now.
      IF (IERR.NE.0) THEN
        IERR = 1
        RETURN
      END IF

      BLC(1) = BLC_(1)
      BLC(2) = BLC_(2)
      TRC(1) = TRC_(1)
      TRC(2) = TRC_(2)

      DOEDGE = GCODE(1).NE.2 .AND. GCODE(2).NE.2

*-----------------------------------------------------------------------
      GO TO 10

      ENTRY PGLBOX (IDENTS, OPT, LABCTL, LABDEN, CI, GCODE, TIKLEN, NG1,
     :  GRID1, NG2, GRID2, DOEQ, NC, IC, CACHE, IERR)

      DOLBOX = .TRUE.

      BLC(1) = 0.0
      BLC(2) = 0.0
      TRC(1) = 1.0
      TRC(2) = 1.0

      DOEDGE = .TRUE.

      CONTRL = 0
      IERR = 0

 10   CONTINUE

*-----------------------------------------------------------------------
      IF (NC.LT.1) THEN
        IERR = 3
        RETURN
      END IF

      NG(1) = NG1
      NG(2) = NG2

      FTYPE(1) = OPT(1)(1:1)
      FTYPE(2) = OPT(2)(1:1)

*     Extend the PGPLOT window and rescale it.
      CALL PGQVP (0, XVP1, XVP2, YVP1, YVP2)
      CALL PGQWIN (WXY(1), WXY(2), WXY(3), WXY(4))
      CALL PGSVP (0.0, 1.0, 0.0, 1.0)
      XSCL = (TRC(1)-BLC(1))/(XVP2-XVP1)
      YSCL = (TRC(2)-BLC(2))/(YVP2-YVP1)
      CALL PGSWIN (BLC(1)-XSCL*XVP1, TRC(1)+XSCL*(1.0-XVP2),
     :             BLC(2)-YSCL*YVP1, TRC(2)+YSCL*(1.0-YVP2))

*     Determine initial colour and set colour indices.
      CALL PGQCI (CI0)
      DO 20 J = 1, 7
        IF (CI(J).GE.0) THEN
          CJ(J) = CI(J)
        ELSE
          CJ(J) = CI0
        END IF
 20   CONTINUE

*     Labels only?
      IF (LABCTL.GE.10000) GO TO 130


      XSPAN = WXY(2) - WXY(1)
      YSPAN = WXY(4) - WXY(3)
      XTOL  = XSPAN*TOL
      YTOL  = YSPAN*TOL

*  Find world coordinate ranges:
*  WMIN(1:2)  ...lower limit of each world coordinate element.
*  WMAX(1:2)  ...upper limit of each world coordinate element.
*  GSTEP(1:2) ...spacing between grid lines for each element.
*  DW(1:2)    ...span from WMIN to WMAX.
*  SW(1:2)    ...increment in world coordinate between plotting steps.
*  NSTEP(1:2) ...number of plotting steps between WMIN and WMAX.
      FULLSM = .FALSE.
      IF (IC.GE.0 .AND. IC.LT.NC-1) FULLSM = CACHE(1,NC-1).EQ.1D0

      IF (IC.GE.0 .AND. (FULLSM .OR. DOEDGE)) THEN
*       Use extrema cached from a previous call.
        WMIN(1) = CACHE(1,0)
        WMAX(1) = CACHE(2,0)
        WMIN(2) = CACHE(3,0)
        WMAX(2) = CACHE(4,0)

      ELSE
*       Do a coarse search to find approximate ranges.
        WMIN(1) =  1D99
        WMAX(1) = -1D99
        WMIN(2) =  1D99
        WMAX(2) = -1D99

*       Need to consider cycles in angle through 360 degrees.
        ISANGL(1) = INDEX('ABCDEFGHI',FTYPE(1)).NE.0
        ISANGL(2) = INDEX('ABCDEFGHI',FTYPE(2)).NE.0
        VMIN(1,1) =  1D99
        VMIN(1,2) =  1D99
        VMAX(1,1) = -1D99
        VMAX(1,2) = -1D99
        VMIN(2,1) =  1D99
        VMIN(2,2) =  1D99
        VMAX(2,1) = -1D99
        VMAX(2,2) = -1D99

*       Sample coordinates on a 50 x 50 grid.
        NX = 50
        NY = 50
        DX = DBLE(TRC(1)-BLC(1))/NX
        DY = DBLE(TRC(2)-BLC(2))/NY

        K = 0
        IYPREV = -1
        DO 40 IY = 0, NY
          XY(2) = BLC(2) + IY*DY

*         Sample the edges only?
          KX = 1
          IF (DOEDGE) THEN
            IF (IY.NE.0 .AND. IY.NE.NY) KX = NX
          END IF

          DO 30 IX = 0, NX, KX
            XY(1) = BLC(1) + IX*DX

            IF (DOLBOX) THEN
              WORLD(1) = WXY(1) + XY(1)*XSPAN
              WORLD(2) = WXY(3) + XY(2)*YSPAN
            ELSE
              CALL NLFUNC (-1, NLC, NLI, NLD, NLCPRM, NLIPRM,
     :          NLDPRM, WORLD, XY, CONTRL, CONTXT, IERR)
            END IF

            IF (IERR.EQ.0) THEN
              K = K + 1

              IF (ISANGL(1)) THEN
                IF (K.EQ.1) W1X0 = WORLD(1)

                IF (IY.NE.IYPREV) THEN
                  W1PREV = W1X0
                  W1X0 = WORLD(1)
                END IF

*               Iron out jumps.
                WJUMP = WORLD(1) - W1PREV
                IF (ABS(WJUMP).GT.180D0) THEN
                  WJUMP = WJUMP + SIGN(180D0,WJUMP)
                  WJUMP = 360D0*INT(WJUMP/360D0)
                  WORLD(1) = WORLD(1) - WJUMP
                END IF

                W1PREV = WORLD(1)
              END IF

              IF (ISANGL(2)) THEN
                IF (K.EQ.1) W2X0 = WORLD(2)

                IF (IY.NE.IYPREV) THEN
                  W2PREV = W2X0
                  W2X0 = WORLD(2)
                END IF

*               Iron out jumps.
                WJUMP = WORLD(2) - W2PREV
                IF (ABS(WJUMP).GT.180D0) THEN
                  WJUMP = WJUMP + SIGN(180D0,WJUMP)
                  WJUMP = 360D0*INT(WJUMP/360D0)
                  WORLD(2) = WORLD(2) - WJUMP
                END IF

                W2PREV = WORLD(2)
              END IF

              IYPREV = IY

              IF (WORLD(1).LT.WMIN(1)) WMIN(1) = WORLD(1)
              IF (WORLD(1).GT.WMAX(1)) WMAX(1) = WORLD(1)
              IF (WORLD(2).LT.WMIN(2)) WMIN(2) = WORLD(2)
              IF (WORLD(2).GT.WMAX(2)) WMAX(2) = WORLD(2)

              IF (ISANGL(1)) THEN
*               Normalize to the range [0,360).
                WORLD(1) = MOD(WORLD(1), 360D0)
                IF (WORLD(1).LT.0D0) WORLD(1) = WORLD(1) + 360D0
                IF (WORLD(1).LT.VMIN(1,1)) VMIN(1,1) = WORLD(1)
                IF (WORLD(1).GT.VMAX(1,1)) VMAX(1,1) = WORLD(1)

*               Normalize to the range (-180,180].
                IF (WORLD(1).GT.180D0) WORLD(1) = WORLD(1) - 360D0
                IF (WORLD(1).LT.VMIN(1,2)) VMIN(1,2) = WORLD(1)
                IF (WORLD(1).GT.VMAX(1,2)) VMAX(1,2) = WORLD(1)
              END IF

              IF (ISANGL(2)) THEN
*               Normalize to the range [0,360).
                WORLD(2) = MOD(WORLD(2), 360D0)
                IF (WORLD(2).LT.0D0) WORLD(2) = WORLD(2) + 360D0
                IF (WORLD(2).LT.VMIN(2,1)) VMIN(2,1) = WORLD(2)
                IF (WORLD(2).GT.VMAX(2,1)) VMAX(2,1) = WORLD(2)

*               Normalize to the range (-180,180].
                IF (WORLD(2).GT.180D0) WORLD(2) = WORLD(2) - 360D0
                IF (WORLD(2).LT.VMIN(2,2)) VMIN(2,2) = WORLD(2)
                IF (WORLD(2).GT.VMAX(2,2)) VMAX(2,2) = WORLD(2)
              END IF
            END IF
 30       CONTINUE
 40     CONTINUE

        IF (K.EQ.0) THEN
*         No valid coordinates found within the frame.
          IERR = 2
          GO TO 999
        END IF

*       Check for cycles in angle.
        DO 50 J = 1, 2
          IF (ISANGL(J)) THEN
            IF (WMAX(J)-WMIN(J).LT.360D0 .AND.
     :          WMAX(J)-WMIN(J).GT.VMAX(J,1)-VMIN(J,1)+TOL) THEN
*             Must have a cycle, preserve the sign.
              IF (WMAX(J).GE.0D0) THEN
                WMIN(J) = VMIN(J,1)
                WMAX(J) = VMAX(J,1)
              ELSE
                WMIN(J) = VMIN(J,1) - 360D0
                WMAX(J) = VMAX(J,1) - 360D0
              END IF
            END IF

            IF (WMAX(J)-WMIN(J).LT.360D0 .AND.
     :          WMAX(J)-WMIN(J).GT.VMAX(J,2)-VMIN(J,2)+TOL) THEN
*             Must have a cycle, preserve the sign.
              IF (WMAX(J).GE.0D0) THEN
                IF (VMAX(J,2).GE.0D0) THEN
                  WMIN(J) = VMIN(J,2)
                  WMAX(J) = VMAX(J,2)
                ELSE
                  WMIN(J) = VMIN(J,2) + 360D0
                  WMAX(J) = VMAX(J,2) + 360D0
                END IF
              ELSE
                IF (VMAX(J,2).LT.0D0) THEN
                  WMIN(J) = VMIN(J,2)
                  WMAX(J) = VMAX(J,2)
                ELSE
                  WMIN(J) = VMIN(J,2) - 360D0
                  WMAX(J) = VMAX(J,2) - 360D0
                END IF
              END IF
            END IF
          END IF
 50     CONTINUE

*       Cache extrema for subsequent calls.
        CACHE(1,0) = WMIN(1)
        CACHE(2,0) = WMAX(1)
        CACHE(3,0) = WMIN(2)
        CACHE(4,0) = WMAX(2)

*       Was full sampling done?
        IF (DOEDGE) THEN
          CACHE(1,NC-1) = 0D0
        ELSE
          CACHE(1,NC-1) = 1D0
        END IF

        IC = 0
      END IF

*     Choose an appropriate grid spacing.
      IF (LABDEN.GT.0) THEN
*       User specified grid density.
        DENS(1) = MOD(LABDEN,100)
        DENS(2) = LABDEN/100
        IF (DENS(1).EQ.0) DENS(1) = DENS0
        IF (DENS(2).EQ.0) DENS(2) = DENS0
      ELSE
*       Default grid density.
        DENS(1) = DENS0
        DENS(2) = DENS0
      END IF

      IF (NG(1).EQ.0) G0(1) = GRID1(0)
      IF (NG(2).EQ.0) G0(2) = GRID2(0)

      DO 60 J = 1, 2
        IF (J.EQ.1) THEN
          K = 2
        ELSE
          K = 1
        END IF

        IF (NG(J).EQ.0 .AND. G0(J).LT.0D0) THEN
*         Defeat grid lines and tick marks.
          GCODE(J) = 0
        END IF

        IF (NG(J).EQ.0 .AND. G0(J).GT.0D0) THEN
*         User-specified, directly.
          GSTEP(J) = G0(J)
        ELSE IF (DOEQ .AND. NG(K).EQ.0 .AND. G0(K).GT.0D0) THEN
*         User-specified, indirectly.
          GSTEP(J) = G0(K)
        ELSE
*         Left to us to choose.  Even if grid lines are not drawn for
*         coordinate J, i.e. NG(J) = 0 and G0(J) < 0, GSTEP(J) is still
*         needed because it is used to deduce SW(J) which is used for
*         drawing grid lines for the other coordinate.
          DW(J) = WMAX(J) - WMIN(J)
          STEP = DW(J)/DENS(J)

          FACT = 1D0
          IF (INDEX('GHI',FTYPE(J)).NE.0) THEN
*           Rescale degrees to hours.
            FACT = 1D0/15D0
            STEP = STEP*FACT
          ELSE IF (FTYPE(J).EQ.'Y' .AND. STEP.LT.0.5D0) THEN
*           Calendar increment of less than 12h; use time format.
            FTYPE(J) = 'y'

*           Rescale days to hours.
            FACT = 24D0
            STEP = STEP*FACT
          END IF

          IF (INDEX('ABCDEF',FTYPE(J)).NE.0 .AND. STEP.GE.1D0) THEN
*           Angle with multi-degree increment.
            IF (STEP.LT.1.5D0) THEN
              STEP = 1D0
            ELSE IF (STEP.LT.3D0) THEN
              STEP = 2D0
            ELSE IF (STEP.LT.7D0) THEN
              STEP = 5D0
            ELSE IF (STEP.LT.12D0) THEN
              STEP = 10D0
            ELSE IF (STEP.LT.20D0) THEN
              STEP = 15D0
            ELSE IF (STEP.LT.40D0) THEN
              STEP = 30D0
            ELSE IF (STEP.LT.70D0) THEN
              STEP = 45D0
            ELSE IF (STEP.LT.120D0) THEN
              STEP = 90D0
            ELSE IF (STEP.LT.270D0) THEN
              STEP = 180D0
            ELSE IF (STEP.LT.520D0) THEN
              STEP = 360D0
            ELSE
              STEP = 360D0*INT(STEP/360D0 + 0.5)
            END IF

          ELSE IF (INDEX('GHITy',FTYPE(J)).NE.0 .AND.
     :      STEP.GE.1D0) THEN
*           Angle or time in hms format with multi-hour increment.
            IF (STEP.LT.1.5D0) THEN
              STEP = 1D0
            ELSE IF (STEP.LT.2.5D0) THEN
              STEP = 2D0
            ELSE IF (STEP.LT.3.5D0) THEN
              STEP = 3D0
            ELSE IF (STEP.LT.5D0) THEN
              STEP = 4D0
            ELSE IF (STEP.LT.7D0) THEN
              STEP = 6D0
            ELSE IF (STEP.LT.10D0) THEN
              STEP = 8D0
            ELSE IF (STEP.LT.15D0) THEN
              STEP = 12D0
            ELSE IF (STEP.LT.21D0) THEN
              STEP = 18D0
            ELSE IF (STEP.LT.36D0) THEN
              STEP = 24D0
            ELSE
              STEP = 24D0*INT(STEP/24D0 + 0.5)
            END IF

            STEP = STEP/FACT

          ELSE IF (INDEX('DEFGHITy',FTYPE(J)).NE.0 .AND.
     :      STEP.LT.1D0) THEN
*           Angle or time in sexagesimal format with sub-degree/hour
*           increment.
            FACT = FACT*60D0
            STEP = STEP*60D0
            IF (STEP.LT.1D0) THEN
*             Sub-minute increment.
              FACT = FACT*60D0
              STEP = STEP*60D0
            END IF

            IF (STEP.LT.1D0) THEN
*             Sub-second increment.
              TMP = 10D0**(INT(LOG10(STEP))-1)
              IF (1.5*TMP.GE.STEP) THEN
                STEP = TMP
              ELSE
                IF (3D0*TMP.GE.STEP) THEN
                  STEP = 2D0*TMP
                ELSE
                  IF (7D0*TMP.GE.STEP) THEN
                    STEP = 5D0*TMP
                  ELSE
                    STEP = 10D0*TMP
                  END IF
                END IF
              END IF

            ELSE
              IF (STEP.LT.1.5D0) THEN
                STEP = 1D0
              ELSE IF (STEP.LT.2.5D0) THEN
                STEP = 2D0
              ELSE IF (STEP.LT.3.5D0) THEN
                STEP = 3D0
              ELSE IF (STEP.LT.4.5D0) THEN
                STEP = 4D0
              ELSE IF (STEP.LT.5.5D0) THEN
                STEP = 5D0
              ELSE IF (STEP.LT.8D0) THEN
                STEP = 6D0
              ELSE IF (STEP.LT.11D0) THEN
                STEP = 10D0
              ELSE IF (STEP.LT.14D0) THEN
                STEP = 12D0
              ELSE IF (STEP.LT.18D0) THEN
                STEP = 15D0
              ELSE IF (STEP.LT.25D0) THEN
                STEP = 20D0
              ELSE IF (STEP.LT.45D0) THEN
                STEP = 30D0
              ELSE
                STEP = 60D0
              END IF
            END IF

            STEP = STEP/FACT

          ELSE IF (FTYPE(J).EQ.'Y') THEN
*           Calendar axis: use coded steps.
            IF (STEP.LT.15D0) THEN
*             Timespan of a few months; use multi-day increments.
              STEP = ANINT(STEP)
              IF (STEP.LT.1D0) THEN
                STEP = 1D0
              ELSE IF (STEP.GT.9D0) THEN
*               Fortnightly.
                STEP = 14D0
              ELSE IF (STEP.GT.4D0) THEN
*               Weekly.
                STEP = 7D0
              END IF

            ELSE IF (STEP.LT.270D0) THEN
*             Timespan of a few years; use multi-month increments.
              STEP = ANINT(STEP/30.44D0)
              IF (STEP.LT.1.5D0) THEN
                STEP = 1D0
              ELSE IF (STEP.LT.2.5D0) THEN
                STEP = 2D0
              ELSE IF (STEP.LT.3.5D0) THEN
                STEP = 3D0
              ELSE IF (STEP.LT.4.5D0) THEN
                STEP = 4D0
              ELSE
                STEP = 6D0
              END IF

*             Coding for multi-month increments.
              STEP = 100D0*STEP

            ELSE
*             Multi-year increments.
              STEP = ANINT(DW(J)/DENS(J)/365.25D0)
              IF (STEP.LT.1D0) THEN
                STEP = 1D0
              ELSE
                TMP = 10D0**INT(LOG10(STEP))

                IF (1.5D0*TMP.GE.STEP) THEN
                  STEP = TMP
                ELSE
                  IF (3D0*TMP.GE.STEP) THEN
                    STEP = 2D0*TMP
                  ELSE
                    IF (7D0*TMP.GE.STEP) THEN
                      STEP = 5D0*TMP
                    ELSE
                      STEP = 10D0*TMP
                    END IF
                  END IF
                END IF
              END IF

*             Coding for multi-year increments.
              STEP = 10000D0*STEP
            END IF

          ELSE
*           Just numbers.
            TMP = 10D0**INT(LOG10(STEP))
            IF (STEP.LT.1D0) TMP = TMP/10D0

            IF (1.5D0*TMP.GE.STEP) THEN
              STEP = TMP
            ELSE
              IF (3D0*TMP.GE.STEP) THEN
                STEP = 2D0*TMP
              ELSE
                IF (7D0*TMP.GE.STEP) THEN
                  STEP = 5D0*TMP
                ELSE
                  STEP = 10D0*TMP
                END IF
              END IF
            END IF

*           Adjust the step size for logarithmic values.
            IF (FTYPE(J).EQ.'L') THEN
              IF (STEP.GT.0.7D0) THEN
                LDIV(J) = 1
                STEP = NINT(STEP)
              ELSE
                IF (STEP.GT.0.4D0) THEN
                  LDIV(J) = 2
                ELSE IF (STEP.GT.0.28D0) THEN
                  LDIV(J) = 3
                ELSE IF (STEP.GT.0.23D0) THEN
                  LDIV(J) = 4
                ELSE IF (STEP.GT.0.18D0) THEN
                  LDIV(J) = 5
                ELSE IF (STEP.GT.0.12D0) THEN
                  LDIV(J) = 6
                ELSE
                  LDIV(J) = 9
                END IF

                STEP = 1D0/LDIV(J)
              END IF
            END IF
          END IF

          GSTEP(J) = STEP
        END IF
 60   CONTINUE

*     Equal grid spacing?
      IF (DOEQ .AND. NG(1).EQ.0 .AND. NG(2).EQ.0) THEN
        IF (GRID1(0).EQ.0D0 .AND. GRID2(0).EQ.0D0) THEN
          GSTEP(1) = MIN(GSTEP(1), GSTEP(2))
          GSTEP(2) = GSTEP(1)
        ELSE IF (GRID1(0).EQ.0D0) THEN
          GSTEP(1) = GSTEP(2)
        ELSE IF (GRID2(0).EQ.0D0) THEN
          GSTEP(2) = GSTEP(1)
        END IF
      END IF

*     Fine tune the end points.
      DO 70 J = 1, 2
        IF (FTYPE(J).EQ.'L') THEN
          WMIN(J) = AINT(WMIN(J)-1D0)
          WMAX(J) = AINT(WMAX(J)+1D0)
        ELSE IF (FTYPE(J).EQ.'Y') THEN
*         Calendar axis.
          IF (GSTEP(J).LT.100D0) THEN
*           Daily increments.
            WMIN(J) = AINT(WMIN(J))
            WMAX(J) = AINT(WMAX(J)+1D0)
          ELSE
*           Start on Jan/01.
            CALL PGMJD (0, WMIN(J), IY, IM, ID)
            CALL PGMJD (1, WMIN(J), IY, 1, 1)

            CALL PGMJD (0, WMAX(J), IY, IM, ID)
            IF (GSTEP(J).LT.10000D0) THEN
*             Monthly increments.
              CALL PGMJD (1, WMAX(J), IY, 12, 1)
            ELSE
*             Yearly increments.
              CALL PGMJD (1, WMAX(J), IY+1, 1, 1)
            END IF
          END IF

        ELSE
          TMP = AINT(WMIN(J)/GSTEP(J))*GSTEP(J)
          IF (TMP.GE.WMIN(J)) TMP = TMP - GSTEP(J)
          WMIN(J) = TMP
          TMP = AINT(WMAX(J)/GSTEP(J))*GSTEP(J)
          IF (TMP.LE.WMAX(J)) TMP = TMP + GSTEP(J)
          WMAX(J) = TMP
        END IF

        DW(J) = WMAX(J) - WMIN(J)
        SW(J) = DW(J)/NSTEP(J)

*       Adjust NSTEP so that SW divides GSTEP.
        IF (SW(J).LT.GSTEP(J)) THEN
          SW(J) = GSTEP(J)/ANINT(GSTEP(J)/SW(J))
        ELSE
          SW(J) = GSTEP(J)
        END IF
        NSTEP(J) = NINT(DW(J)/SW(J))
 70   CONTINUE


*  Draw the grid.
*     Get absolute scale for tick marks.
      CALL PGQVP (2, X1, X2, Y1, Y2)
      XSCL = (X2-X1)/(TRC(1)-BLC(1))
      YSCL = (Y2-Y1)/(TRC(2)-BLC(2))

*     Decode tick mark control.
      DO 80 J = 1, 2
        IF (GCODE(J).EQ.2) THEN
          TCODE(J,1) = -1
          TCODE(J,2) = -1
          TCODE(J,3) = -1
          TCODE(J,4) = -1
        ELSE IF (GCODE(J).EQ.1) THEN
          TCODE(J,1) = 1
          TCODE(J,2) = 1
          TCODE(J,3) = 1
          TCODE(J,4) = 1
        ELSE IF (GCODE(J).LT.0) THEN
          K = ABS(GCODE(J))
          TCODE(J,1) = MOD(K,10)
          TCODE(J,2) = MOD(K/10,10)
          TCODE(J,3) = MOD(K/100,10)
          TCODE(J,4) = MOD(K/1000,10)
        ELSE
          TCODE(J,1) = 0
          TCODE(J,2) = 0
          TCODE(J,3) = 0
          TCODE(J,4) = 0
        END IF
 80   CONTINUE

*     Draw each set of grid lines.
      RTIKLN = REAL(TIKLEN)
      OVERFL = .FALSE.
      DO 120 J = 1, 2
        IF (GCODE(J).EQ.0) GO TO 120

        IF (J.EQ.1) THEN
          CALL PGSCI (CJ(1))
          K = 2
        ELSE
          CALL PGSCI (CJ(2))
          K = 1
        END IF

        IF (NG(J).GT.0) THEN
          NWJ = NG(J)

        ELSE IF (FTYPE(J).EQ.'Y' .AND. GSTEP(J).GE.100D0) THEN
*         Calendar axis.
          CALL PGMJD (0, WMAX(J), IY, IM, ID)
          IF (GSTEP(J).LT.10000D0) THEN
            NWJ = 12*IY + IM
            CALL PGMJD (0, WMIN(J), IY, IM, ID)
            NWJ = (NWJ - (12*IY + IM))/INT(GSTEP(J)/100D0)
          ELSE
            NWJ = IY
            CALL PGMJD (0, WMIN(J), IY, IM, ID)
            NWJ = (NWJ - IY)/INT(GSTEP(J)/10000D0)
          END IF

        ELSE
          NWJ = NINT(DW(J)/GSTEP(J))
          IW0 = NINT(WMIN(J)/GSTEP(J))
        END IF

        DO 110 IWJ = 0, NWJ
          MAJOR = .FALSE.

*         Determine the world coordinate of the grid line.
          IF (NG(J).GT.0) THEN
*           User-specified.
            IF (IWJ.EQ.0) GO TO 110
            IF (J.EQ.1) THEN
              WORLD(1) = GRID1(IWJ)
            ELSE
              WORLD(2) = GRID2(IWJ)
            END IF

          ELSE
*           Internally computed.
            IF (FTYPE(J).EQ.'Y' .AND. GSTEP(J).GE.100D0) THEN
*             Calendar axis.
              CALL PGMJD (0, WMIN(J), IY, IM, ID)
              IF (GSTEP(J).LT.10000D0) THEN
                IM = IM + IWJ*INT(GSTEP(J)/100D0)
                CALL PGMJD (1, WORLD(J), IY, IM, ID)
              ELSE
                IY = IY + IWJ*INT(GSTEP(J)/10000D0)
                CALL PGMJD (1, WORLD(J), IY, IM, ID)
              END IF

            ELSE
              WORLD(J) = (IW0 + IWJ)*GSTEP(J)

*             Logarithmic?
              IF (FTYPE(J).EQ.'L') THEN
                TMP = MOD(WORLD(J),1D0)
                IF (TMP.LT.0D0) TMP = TMP + 1D0
                L = NINT(TMP*LDIV(J))

                IF (L.EQ.0) THEN
*                 Major tick mark.
                  MAJOR = .TRUE.
                ELSE
*                 Adjust logarithmic scales.
                  IF (LDIV(J).LE.6) THEN
                    L = LTABL(L,LDIV(J))
                  ELSE
                    L = L + 1
                  END IF

                  WORLD(J) = WORLD(J) - TMP + LOG10(DBLE(L))
                END IF
              END IF
            END IF
          END IF

          NP = 0
          GETEND = .TRUE.
          DO 100 IWK = 0, NSTEP(K)
            WORLD(K) = WMIN(K) + IWK*SW(K)

            IF (GETEND) THEN
*             Get end-point context.
              IF (DOLBOX) THEN
                XY(1) = (WORLD(1) - WXY(1))/XSPAN
                XY(2) = (WORLD(2) - WXY(3))/YSPAN
              ELSE
                CALL NLFUNC (1, NLC, NLI, NLD, NLCPRM, NLIPRM,
     :            NLDPRM, WORLD, XY, CONTRL, CONTXT, IERR)
              END IF

              IF (IERR.LE.0) THEN
                X1 = REAL(XY(1))
                Y1 = REAL(XY(2))

*               On the frame is outside; gives a crossing-point.
                INSIDE = X1.GT.BLC(1) .AND. X1.LT.TRC(1) .AND.
     :                   Y1.GT.BLC(2) .AND. Y1.LT.TRC(2)

*               Account for coordinate systems that are not defined
*               outside the frame.
                IF (INSIDE .AND. IWK.GT.0) THEN
*                 If the first point (IWK.EQ.0) is valid and already
*                 inside the frame, then the grid line begins inside
*                 the frame.  However, if there were invalid points
*                 before it (IWK.GT.0) and the first valid point is
*                 already inside the frame then look for a crossing
*                 point.
                  WRLD(J) = WORLD(J)
                  WRLD(K) = WORLD(K) + SW(K)

                  IF (DOLBOX) THEN
                    XY(1) = (WRLD(1) - WXY(1))/XSPAN
                    XY(2) = (WRLD(2) - WXY(3))/YSPAN
                  ELSE
                    CALL NLFUNC (1, NLC, NLI, NLD, NLCPRM, NLIPRM,
     :                NLDPRM, WRLD, XY, CONTRL, CONTXT, IERR)
                  END IF

                  IF (IERR.LE.0) THEN
                    X2 = REAL(XY(1))
                    Y2 = REAL(XY(2))

                    RHO = 999.0
                    XSTEP = X2 - X1
                    YSTEP = Y2 - Y1

                    IF (XSTEP.NE.0.0) THEN
*                     Proximity to left edge of frame.
                      TAU = (X1 - BLC(1)) / XSTEP
                      IF (ABS(TAU).LT.RHO) THEN
                        XY(1) = BLC(1)
                        XY(2) = Y1 - TAU*YSTEP
                        RHO = ABS(TAU)
                      END IF

*                     Proximity to right edge of frame.
                      TAU = (X1 - TRC(1)) / XSTEP
                      IF (ABS(TAU).LT.RHO) THEN
                        XY(1) = TRC(1)
                        XY(2) = Y1 - TAU*YSTEP
                        RHO = ABS(TAU)
                      END IF
                    END IF

                    IF (YSTEP.NE.0.0) THEN
*                     Proximity to bottom edge of frame.
                      TAU = (Y1 - BLC(2)) / YSTEP
                      IF (ABS(TAU).LT.RHO) THEN
                        XY(1) = X1 - TAU*XSTEP
                        XY(2) = BLC(2)
                        RHO = ABS(TAU)
                      END IF

*                     Proximity to top edge of frame.
                      TAU = (Y1 - TRC(2)) / YSTEP
                      IF (ABS(TAU).LT.RHO) THEN
                        XY(1) = X1 - TAU*XSTEP
                        XY(2) = TRC(2)
                        RHO = ABS(TAU)
                      END IF
                    END IF

*                   Check that it really is a crossing point.
                    IF (RHO.LT.3.0) THEN
                      CALL NLFUNC (-1, NLC, NLI, NLD, NLCPRM, NLIPRM,
     :                  NLDPRM, WRLD, XY, CONTRL, CONTXT, IERR)
                      IF (IERR.LE.0) THEN
                        X1 = REAL(XY(1))
                        Y1 = REAL(XY(2))
                        INSIDE = .FALSE.
                      END IF
                    END IF
                  END IF
                END IF

                NP = 1
                XR(1) = X1
                YR(1) = Y1

                PREVIN = INSIDE
                GETEND = .FALSE.

                LABLOK = IERR.NE.-J .AND. IERR.NE.-3
              END IF
              GO TO 100
            END IF

            DO 90 ISTEP = 1, 1000
              IF (DOLBOX) THEN
                XY(1) = (WORLD(1) - WXY(1))/XSPAN
                XY(2) = (WORLD(2) - WXY(3))/YSPAN
              ELSE
                CALL NLFUNC (2, NLC, NLI, NLD, NLCPRM, NLIPRM,
     :            NLDPRM, WORLD, XY, CONTRL, CONTXT, IERR)
              END IF

              IF (IERR.GT.0) THEN
*               Account for coordinate systems that are not defined
*               outside the frame.
                IF (NP.GT.1 .AND. .NOT.GETEND) THEN
*                 Look for a crossing point.
                  RHO = 999.0
                  XSTEP = XR(NP) - XR(NP-1)
                  YSTEP = YR(NP) - YR(NP-1)

                  IF (XSTEP.NE.0.0) THEN
*                   Proximity to left edge of frame.
                    TAU = (BLC(1) - XR(NP)) / XSTEP
                    IF (ABS(TAU).LT.RHO) THEN
                      XY(1) = BLC(1)
                      XY(2) = YR(NP) + TAU*YSTEP
                      RHO = ABS(TAU)
                    END IF

*                   Proximity to right edge of frame.
                    TAU = (TRC(1) - XR(NP)) / XSTEP
                    IF (ABS(TAU).LT.RHO) THEN
                      XY(1) = TRC(1)
                      XY(2) = YR(NP) + TAU*YSTEP
                      RHO = ABS(TAU)
                    END IF
                  END IF

                  IF (YSTEP.NE.0.0) THEN
*                   Proximity to bottom edge of frame.
                    TAU = (BLC(2) - YR(NP)) / YSTEP
                    IF (ABS(TAU).LT.RHO) THEN
                      XY(1) = XR(NP) + TAU*XSTEP
                      XY(2) = BLC(2)
                      RHO = ABS(TAU)
                    END IF

*                   Proximity to top edge of frame.
                    TAU = (TRC(2) - YR(NP)) / YSTEP
                    IF (ABS(TAU).LT.RHO) THEN
                      XY(1) = XR(NP) + TAU*XSTEP
                      XY(2) = TRC(2)
                      RHO = ABS(TAU)
                    END IF
                  END IF

*                 Check that it really is a crossing point.
                  IF (RHO.LT.3.0) THEN
                    CALL NLFUNC (-1, NLC, NLI, NLD, NLCPRM, NLIPRM,
     :                NLDPRM, WRLD, XY, CONTRL, CONTXT, IERR)
                    IF (IERR.LE.0) THEN
                      NP = NP + 1
                      XR(NP) = REAL(XY(1))
                      YR(NP) = REAL(XY(2))
                    END IF
                  END IF
                END IF

*               Flush buffer.
                IF (NP.GT.1) CALL PGLINE(NP, XR, YR)
                NP = 0
                GETEND = .TRUE.
                GO TO 100
              END IF

              IF (NP.EQ.BUFSIZ) THEN
*               Recycle buffer.
                CALL PGLINE(NP, XR, YR)
                XR(1) = XR(NP)
                YR(1) = YR(NP)
                NP = 1
              END IF

              X2 = REAL(XY(1))
              Y2 = REAL(XY(2))
              INSIDE = X2.GT.BLC(1) .AND. X2.LT.TRC(1) .AND.
     :                 Y2.GT.BLC(2) .AND. Y2.LT.TRC(2)

              IF (NP.EQ.0) THEN
                NP = 1
                XR(1) = X2
                YR(1) = Y2
              ELSE
                IF (.NOT.INSIDE) THEN
*                 For tick marks at the left or right edge.
                  IF ((X2.EQ.BLC(1) .OR.  X2.EQ.TRC(1)) .AND.
     :                 Y2.GT.BLC(2) .AND. Y2.LT.TRC(2)) THEN
                    INSIDE = X2.EQ.XR(NP)
                  END IF
                END IF

                IF (.NOT.INSIDE) THEN
*                 For tick marks at the bottom or top edge.
                  IF ((Y2.EQ.BLC(2) .OR.  Y2.EQ.TRC(2)) .AND.
     :                 X2.GT.BLC(1) .AND. X2.LT.TRC(1)) THEN
                    INSIDE = Y2.EQ.YR(NP)
                  END IF
                END IF

                IF (INSIDE) THEN
*                 This point is inside the frame...
                  IF (.NOT.PREVIN) THEN
*                   ...but the previous one was outside.
                    X1 = XR(NP)
                    Y1 = YR(NP)

                    FSEG = 0
                    XPOINT = 0.0
                    IF (ABS(X2-X1).GT.XTOL) THEN
                      S = (Y2-Y1)/(X2-X1)
                      IF (XR(NP).LE.BLC(1)) THEN
                        FSEG = 2
                        XR(NP) = BLC(1)
                        XPOINT = Y1 + (XR(NP) - X1)*S
                        YR(NP) = XPOINT
                      ELSE IF (XR(NP).GE.TRC(1)) THEN
                        FSEG = 4
                        XR(NP) = TRC(1)
                        XPOINT = Y1 + (XR(NP) - X1)*S
                        YR(NP) = XPOINT
                      END IF
                    END IF

                    IF (ABS(Y2-Y1).GT.YTOL) THEN
                      S = (X2-X1)/(Y2-Y1)
                      IF (YR(NP).LE.BLC(2)) THEN
                        FSEG = 1
                        YR(NP) = BLC(2)
                        XPOINT = X1 + (YR(NP) - Y1)*S
                        XR(NP) = XPOINT
                      ELSE IF (YR(NP).GE.TRC(2)) THEN
                        FSEG = 3
                        YR(NP) = TRC(2)
                        XPOINT = X1 + (YR(NP) - Y1)*S
                        XR(NP) = XPOINT
                      END IF
                    END IF


                    IF (FSEG.EQ.0) THEN
*                     The crossing is too oblique.
                      INSIDE = .FALSE.

                    ELSE
*                     Record this crossing point.
                      IF (TCODE(J,FSEG).NE.0 .AND. LABLOK) THEN
                        IF (IC.LT.NC-1) THEN
                          IC = IC + 1
                          CACHE(1,IC) = FSEG
                          CACHE(2,IC) = XPOINT
                          CACHE(3,IC) = J
                          CACHE(4,IC) = WORLD(J)
                        ELSE
*                         Cache overflow.
                          OVERFL = .TRUE.
                        END IF
                      END IF

                      IF (TCODE(J,FSEG).GT.0) THEN
*                       Just want tick marks.
                        S = (XSCL*(X2-X1))**2 + (YSCL*(Y2-Y1))**2
                        S = SQRT(S)/TCODE(J,FSEG)
                        IF (MAJOR) S = S/1.5
                        NP = NP + 1
                        XR(NP) = XR(NP-1) + (X2-X1)*RTIKLN/S
                        YR(NP) = YR(NP-1) + (Y2-Y1)*RTIKLN/S

                        CALL PGLINE(NP, XR, YR)
                        NP = 1
                      END IF
                    END IF
                  END IF

                  IF (INSIDE .AND. GCODE(J).EQ.2) THEN
*                   Full grid.
                    NP = NP + 1
                  END IF
                  XR(NP) = X2
                  YR(NP) = Y2
                ELSE
*                 This point is outside the frame...
                  IF (PREVIN) THEN
*                   ...but the previous one was inside.
                    X1 = XR(NP)
                    Y1 = YR(NP)

                    NP = NP + 1
                    XR(NP) = X2
                    YR(NP) = Y2

                    FSEG = 0
                    XPOINT = 0.0
                    IF (ABS(X2-X1).GT.XTOL) THEN
                      S = (Y2-Y1)/(X2-X1)
                      IF (XR(NP).LE.BLC(1)) THEN
                        FSEG = 2
                        XR(NP) = BLC(1)
                        XPOINT = Y1 + (XR(NP) - X1)*S
                        YR(NP) = XPOINT
                      ELSE IF (XR(NP).GE.TRC(1)) THEN
                        FSEG = 4
                        XR(NP) = TRC(1)
                        XPOINT = Y1 + (XR(NP) - X1)*S
                        YR(NP) = XPOINT
                      END IF
                    END IF

                    IF (ABS(Y2-Y1).GT.YTOL) THEN
                      S = (X2-X1)/(Y2-Y1)
                      IF (YR(NP).LE.BLC(2)) THEN
                        FSEG = 1
                        YR(NP) = BLC(2)
                        XPOINT = X1 + (YR(NP) - Y1)*S
                        XR(NP) = XPOINT
                      ELSE IF (YR(NP).GE.TRC(2)) THEN
                        FSEG = 3
                        YR(NP) = TRC(2)
                        XPOINT = X1 + (YR(NP) - Y1)*S
                        XR(NP) = XPOINT
                      END IF
                    END IF


                    IF (FSEG.EQ.0) THEN
*                     The crossing is too oblique.
                      INSIDE = .TRUE.

                      IF (GCODE(J).EQ.2) THEN
*                       Full grid.
                        NP = NP + 1
                      END IF
                      XR(NP) = X2
                      YR(NP) = Y2

                    ELSE
*                     Record this crossing point.
                      IF (TCODE(J,FSEG).NE.0 .AND. LABLOK) THEN
                        IF (IC.LT.NC-1) THEN
                          IC = IC + 1
                          CACHE(1,IC) = FSEG
                          CACHE(2,IC) = XPOINT
                          CACHE(3,IC) = J
                          CACHE(4,IC) = WORLD(J)
                        ELSE
*                         Cache overflow.
                          OVERFL = .TRUE.
                        END IF
                      END IF

                      IF (TCODE(J,FSEG).GT.0) THEN
*                       Just want tick marks.
                        X1 = XR(NP)
                        Y1 = YR(NP)
                        X2 = XR(NP-1)
                        Y2 = YR(NP-1)
                        S = (XSCL*(X2-X1))**2 + (YSCL*(Y2-Y1))**2
                        S = SQRT(S)/TCODE(J,FSEG)
                        IF (MAJOR) S = S/1.5
                        XR(NP-1) = X1 + (X2-X1)*RTIKLN/S
                        YR(NP-1) = Y1 + (Y2-Y1)*RTIKLN/S
                      END IF

*                     Flush buffer.
                      IF (TCODE(J,FSEG).NE.0) THEN
                        CALL PGLINE(NP, XR, YR)
                      END IF
                      NP = 0
                    END IF
                  ELSE
*                   The previous point was also outside.
                    XR(NP) = X2
                    YR(NP) = Y2
                  END IF
                END IF
              END IF

              PREVIN = INSIDE
              LABLOK = IERR.NE.-J .AND. IERR.NE.-3

              IF (CONTRL.EQ.0) THEN
                GO TO 100
              ELSE IF (CONTRL.EQ.1) THEN
*               Flush buffer.
                IF (NP.GT.1) CALL PGLINE(NP, XR, YR)
                NP = 0
              END IF
 90         CONTINUE
 100      CONTINUE

          IF (NP.GT.1) CALL PGLINE(NP, XR, YR)
 110    CONTINUE
 120  CONTINUE

      IERR = 0
      IF (OVERFL) IERR = 3


*  Produce axis labels.
 130  IF (LABCTL.NE.-1) CALL PGCRLB (BLC, TRC, IDENTS, FTYPE, LABCTL,
     :  CJ, NC, IC, CACHE)

*     Restore the original viewport, window and pen colour.
 999  CALL PGSVP (XVP1, XVP2, YVP1, YVP2)
      CALL PGSWIN (WXY(1), WXY(2), WXY(3), WXY(4))
      CALL PGSCI (CI0)

      RETURN
      END



*=======================================================================
*
* PGCRLB is a helper routine for PGSBOX, not meant to be called directly
* since it expects the viewport and window to be scaled to the full
* extent; it labels a curvilinear coordinate grid.
*
* Given:
*   BLC       R(2)      Cartesian coordinates of the bottom left-hand
*                       corner.
*   TRC       R(2)      Cartesian coordinates of the top right-hand
*                       corner.
*
*   IDENTS    C(3)*(*)  Identification strings (see PGSBOX).
*
*   FTYPE     C(2)*1    Axis types, used for axis labelling (see
*                       PGSBOX).
*
*   LABCTL    I         Decimal encoded grid labelling control (see
*                       PGSBOX).
*
*   CI        I(7)      Colour table (see PGSBOX).
*
* Given and/or returned:
*   NC        I         Upper array index for CACHE.
*
*   IC        I         Current number of entries in the CACHE table.
*
*   CACHE     D(4,0:NC) Table of points where the tick marks or grid
*                       lines cross the frame (see PGSBOX).
*
* Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
*=======================================================================
      SUBROUTINE PGCRLB (BLC, TRC, IDENTS, FTYPE, LABCTL, CI, NC, IC,
     :                   CACHE)
*-----------------------------------------------------------------------
      LOGICAL   ANGLE, DODEG, DOMIN, DOYEAR, LFORCE, SEXA(2), TICKIT
      INTEGER   CI(7), DOLAB(4), EDGE, EDJE, IC, ID, ID2, IM, IM2,
     :          IMAG(2), ITER, IWRLD, IY, IY2, J, JC, K, K1, K2, KWRLD,
     :          L, LABCTL, LD, LM, LMAG(2), LS, LV, M, M1, M2, MM, NC,
     :          NCH, NI(2,0:4), NLAB, NLABS(2,-2:6), NSWAP, PP,
     :          PRVDEG(2), PRVMIN(2), PRVEDG, PRVYR(2), SEXSUP(2),
     :          SKOP(4)
      REAL      ANGL, BLC(2), FJUST, BNDRY(4), OMAG(2), SI(2), TRC(2),
     :          X, XBOX(4), XCH, XL, XW1, XW2, Y, YCH, YBOX(4), YL, YW1,
     :          YW2, Z
      DOUBLE PRECISION CACHE(4,0:NC), MJD1(2), MJD2(2), TMP, VS
      CHARACTER ESCAPE*1, EXPONT*20, FMT*8, IDENTS(3)*(*), TEXT*80,
     :          FTYPE(2)*1, TXT(2)*80

*     These are to stop compiler messages about uninitialized variables.
      DATA DODEG, DOMIN, DOYEAR /3 * .FALSE./
      DATA XL, YL /2 * -999.0/
*-----------------------------------------------------------------------
*  Normalize angular table entries.
      IF (INDEX('ABDEGH',FTYPE(1)).NE.0 .OR.
     :    INDEX('ABDEGH',FTYPE(2)).NE.0) THEN
        DO 10 J = 1, IC
          IWRLD = NINT(CACHE(3,J))

          IF (INDEX('ADG', FTYPE(IWRLD)).NE.0) THEN
            CACHE(4,J) = MOD(CACHE(4,J), 360D0)
            IF (CACHE(4,J).LT.0D0) CACHE(4,J) = CACHE(4,J) + 360D0
          ELSE IF (INDEX('BEH', FTYPE(IWRLD)).NE.0) THEN
            CACHE(4,J) = MOD(CACHE(4,J), 360D0)
            IF (CACHE(4,J).LE.-180D0) THEN
              CACHE(4,J) = CACHE(4,J) + 360D0
            ELSE IF (CACHE(4,J).GT.180D0) THEN
              CACHE(4,J) = CACHE(4,J) - 360D0
            END IF
          END IF

          IF (INDEX('GHI', FTYPE(IWRLD)).NE.0) THEN
*           Angle expressed as time.
            CACHE(4,J) = CACHE(4,J)/15D0
          END IF
 10     CONTINUE
      END IF


*  Reorganize the table entries.
*     Sort crossings for each of the four frame segments.
      DO 40 ITER = 1, IC
        NSWAP = 0
        DO 30 J = 1, IC-1
          IF (CACHE(1,J).LT.CACHE(1,J+1)) GO TO 30
          IF (CACHE(1,J).EQ.CACHE(1,J+1) .AND.
     :        CACHE(2,J).LE.CACHE(2,J+1)) GO TO 30

          NSWAP = NSWAP + 1
          DO 20 M = 1, 4
            TMP = CACHE(M,J)
            CACHE(M,J) = CACHE(M,J+1)
            CACHE(M,J+1) = TMP
 20       CONTINUE
 30     CONTINUE
        IF (NSWAP.EQ.0) GO TO 50
 40   CONTINUE

*     Squeeze out duplicates.
 50   JC = IC
      DO 90 J = 2, IC
        IF (J.GT.JC) GO TO 100

        DO 60 M = 1, 4
          IF (CACHE(M,J).NE.CACHE(M,J-1)) GO TO 90
 60     CONTINUE

*       This entry is the same as the previous one.
        JC = JC - 1
        DO 80 K = J, JC
          DO 70 M = 1, 4
            CACHE(M,K) = CACHE(M,K+1)
 70       CONTINUE
 80     CONTINUE
 90   CONTINUE

 100  IC = JC


* How do we label the edges of the frame?
*     Determine separability indices.
      NI(1,0) = 0
      NI(1,1) = 0
      NI(1,2) = 0
      NI(1,3) = 0
      NI(1,4) = 0
      NI(2,0) = 0
      NI(2,1) = 0
      NI(2,2) = 0
      NI(2,3) = 0
      NI(2,4) = 0
      DO 110 J = 1, IC
        IWRLD = NINT(CACHE(3,J))
        EDGE  = NINT(CACHE(1,J))

        NI(IWRLD,0) = NI(IWRLD,0) + 1
        NI(IWRLD,EDGE) = NI(IWRLD,EDGE) + 1
 110  CONTINUE

      SI(1) = 0.0
      SI(2) = 0.0
      IF (NI(1,0).GT.0) SI(1) = 2.0*REAL(NI(1,1)+NI(1,3))/NI(1,0) - 1.0
      IF (NI(2,0).GT.0) SI(2) = 2.0*REAL(NI(2,1)+NI(2,3))/NI(2,0) - 1.0

*     Which coordinates go on which edges?
      IF (LABCTL.GT.0) THEN
*       User-defined.
        L = LABCTL
      ELSE
*       Work it out ourselves.
        L = 0
        IF (ABS(SI(1)-SI(2)).GT.1.0) THEN
*         Approximately horizontal/vertical grid lines.
          IF (SI(1).GT.SI(2)) THEN
*           First world coordinate with vertical grid lines.
            IF (NI(1,1).GT.3 .OR. NI(1,1).GE.NI(1,3)) THEN
*             Label bottom of frame.
              L = L + 1
            ELSE
*             Label top of frame.
              L = L + 100
            END IF

*           Second world coordinate with horizontal grid lines.
            IF (NI(2,2).GT.3 .OR. NI(2,2).GE.NI(2,4)) THEN
*             Label left side of frame.
              L = L + 20
            ELSE
*             Label right side of frame.
              L = L + 2000
            END IF
          ELSE
*           First world coordinate with horizontal grid lines.
            IF (NI(1,2).GT.3 .OR. NI(1,2).GE.NI(1,4)) THEN
*             Label left side of frame.
              L = L + 10
            ELSE
*             Label right side of frame.
              L = L + 1000
            END IF

*           Second world coordinate with vertical grid lines.
            IF (NI(2,1).GT.3 .OR. NI(2,1).GE.NI(2,3)) THEN
*             Label bottom of frame.
              L = L + 2
            ELSE
*             Label top of frame.
              L = L + 200
            END IF
          END IF
        ELSE
*         Skew grid lines or worse.
          IF (SI(1).GT.0.5D0) THEN
*           First world coordinate with vertical grid lines.
            IF (NI(1,1).GT.3 .OR. NI(1,1).GT.NI(1,3)) THEN
              L = 1
            ELSE
              L = 100
            END IF

            IF (SI(2).GT.0.5D0) THEN
*             Second world coordinate also with vertical grid lines.
              IF (L.EQ.1) THEN
                L = 201
              ELSE
                IF (NI(2,1).GT.1 .OR. NI(2,1).GT.NI(2,3)) THEN
                  L = 102
                ELSE
                  L = 300
                END IF
              END IF
            ELSE
*             Second world coordinate with diagonal grid lines.
              L = L + 2020
            END IF
          ELSE IF (SI(1).LT.-0.5D0) THEN
*           First world coordinate with horizontal grid lines.
            IF (NI(1,2).GT.3 .OR. NI(1,2).GT.NI(1,4)) THEN
              L = 10
            ELSE
              L = 1000
            END IF

            IF (SI(2).LT.-0.5D0) THEN
*             Second world coordinate also with horizontal grid.
              IF (L.EQ.10) THEN
                L = 2010
              ELSE
                IF (NI(2,2).GT.1 .OR. NI(2,2).GT.NI(2,4)) THEN
                  L = 1020
                ELSE
                  L = 3000
                END IF
              END IF
            ELSE
*             Second world coordinate with diagonal grid lines.
              L = L + 202
            END IF
          ELSE IF (SI(2).GT.0.5D0) THEN
*           Second world coordinate with vertical grid lines.
            IF (NI(2,1).GT.3 .OR. NI(2,1).GT.NI(2,3)) THEN
              L = 1012
            ELSE
              L = 1210
            END IF
          ELSE IF (SI(2).LT.-0.5D0) THEN
*           Second world coordinate with horizontal grid lines.
            IF (NI(2,2).GT.3 .OR. NI(2,2).GT.NI(2,4)) THEN
              L = 121
            ELSE
              L = 2101
            END IF
          ELSE
*           Desperation stakes!  Label all four axes.
            K1 = NI(1,3) + NI(1,1)
            K2 = NI(2,4) + NI(2,2)
            L = 2121

            M1 = NI(1,4) + NI(1,1)
            M2 = NI(2,3) + NI(2,2)
            IF (M1.GE.K1 .AND. M2.GE.K2) THEN
              L  = 1221
              K1 = M1
              K2 = M2
            END IF

            M1 = NI(1,2) + NI(1,1)
            M2 = NI(2,4) + NI(2,3)
            IF (M1.GE.K1 .AND. M2.GE.K2) THEN
              L  = 2211
              K1 = M1
              K2 = M2
            END IF

            M1 = NI(1,4) + NI(1,2)
            M2 = NI(2,3) + NI(2,1)
            IF (M1.GE.K1 .AND. M2.GE.K2) THEN
              L  = 1212
              K1 = M1
              K2 = M2
            END IF

            M1 = NI(1,3) + NI(1,2)
            M2 = NI(2,4) + NI(2,1)
            IF (M1.GE.K1 .AND. M2.GE.K2) THEN
              L  = 2112
              K1 = M1
              K2 = M2
            END IF

            M1 = NI(1,4) + NI(1,3)
            M2 = NI(2,2) + NI(2,1)
            IF (M1.GE.K1 .AND. M2.GE.K2) THEN
              L  = 1122
              K1 = M1
              K2 = M2
            END IF
          END IF
        END IF
      END IF

*     Mark labels as unwanted by setting their edges negative.
      DOLAB(1) = MOD(L,10)
      DOLAB(2) = MOD(L/10,10)
      DOLAB(3) = MOD(L/100,10)
      DOLAB(4) = MOD(L/1000,10)
      DO 120 J = 1, IC
        EDGE  = NINT(CACHE(1,J))
        IWRLD = NINT(CACHE(3,J))
        IF (IWRLD.EQ.1) THEN
          IF (MOD(DOLAB(EDGE),2).NE.1) CACHE(1,J) = -EDGE
        ELSE
          IF (MOD(DOLAB(EDGE)/2,2).NE.1) CACHE(1,J) = -EDGE
        END IF
 120  CONTINUE


*  Determine labelling precision.
*     Order of magnitude for plain numeric world coordinates.
      IMAG(1) = 0
      IMAG(2) = 0

      IF (FTYPE(1).EQ.' ' .OR. FTYPE(2).EQ.' ') THEN
        OMAG(1) = 0.0
        OMAG(2) = 0.0
        DO 130 J = 1, IC
          IWRLD = NINT(CACHE(3,J))
          IF (FTYPE(IWRLD).EQ.' ') THEN
*           Plain numeric.
            IF (CACHE(4,J).EQ.0D0) GO TO 130
            OMAG(IWRLD) = OMAG(IWRLD) + LOG10(ABS(REAL(CACHE(4,J))))
            IMAG(IWRLD) = IMAG(IWRLD) + 1
          END IF
 130    CONTINUE

        IF (IMAG(1).GT.0) IMAG(1) = INT(OMAG(1)/IMAG(1))
        IF (IMAG(1).GE.-2 .AND. IMAG(1).LE.4) IMAG(1) = 0

        IF (IMAG(2).GT.0) IMAG(2) = INT(OMAG(2)/IMAG(2))
        IF (IMAG(2).GE.-2 .AND. IMAG(2).LE.4) IMAG(2) = 0

*       Renormalize grid values.
        IF (IMAG(1).NE.0 .OR. IMAG(2).NE.0) THEN
          DO 140 J = 1, IC
            IWRLD = NINT(CACHE(3,J))
            CACHE(4,J) = CACHE(4,J)/10D0**IMAG(IWRLD)
 140      CONTINUE
        END IF
      END IF

*     Sexagesimal labelling.
      SEXA(1) = INDEX('DEFGHITy', FTYPE(1)).NE.0
      SEXA(2) = INDEX('DEFGHITy', FTYPE(2)).NE.0

      IF (SEXA(1) .OR. SEXA(2)) THEN
        DO 150 K = -2, 6
          NLABS(1,K) = 0
          NLABS(2,K) = 0
 150    CONTINUE

        DO 180 J = 1, IC
*         Use this label?
          EDGE = NINT(CACHE(1,J))
          IF (EDGE.LT.0) GO TO 180

*         Skip non-sexagesimal coordinates.
          IWRLD = NINT(CACHE(3,J))
          IF (.NOT.SEXA(IWRLD)) GO TO 180

*         Defeat rounding errors.
          IF (FTYPE(IWRLD).EQ.'y') THEN
            TMP = ABS(MOD(CACHE(4,J),1D0)*86400D0) + 5D-7
          ELSE
            TMP = ABS(CACHE(4,J)*3600D0) + 5D-7
          END IF

          LV = INT(MOD(TMP, 1D0)*1D6)
          IF (LV.NE.0) THEN
*           Sub-arcsec/second resolution.
            M = 1
            DO 160 K = 1, 6
              M = M*10
              IF (MOD(LV,M).NE.0) THEN
                L = 7 - K
                GO TO 170
              END IF
 160        CONTINUE
          ELSE
            LS = INT(TMP)
            IF (MOD(LS,60).NE.0) THEN
              L =  0
            ELSE IF (MOD(LS,3600).NE.0) THEN
              L = -1
            ELSE
              L = -2
            END IF
          END IF

*         Use CACHE(1,J) temporarily to hold L.
 170      NLABS(IWRLD,L) = NLABS(IWRLD,L) + 1
          CACHE(1,J) = CACHE(1,J) + 0.1 + L/100.0
 180    CONTINUE

*       How many fields are needed to get enough labels?
        DO 200 IWRLD = 1, 2
          NLAB = 0
          DO 190 K = -2, 6
            NLAB = NLAB + NLABS(IWRLD,K)
            IF (NLAB.GT.3 .OR. K.EQ.6) THEN
              LMAG(IWRLD) = K
              GO TO 200
            END IF
            NLABS(IWRLD,K+1) = NLABS(IWRLD,K) + NLABS(IWRLD,K+1)
 190      CONTINUE
 200    CONTINUE

*       Disable unwanted labels.
        DO 210 J = 1, IC
*         Use this label?
          EDGE = NINT(CACHE(1,J))
          IF (EDGE.LT.0) GO TO 210

*         Skip non-sexagesimal coordinates.
          IWRLD = NINT(CACHE(3,J))
          IF (.NOT.SEXA(IWRLD)) GO TO 210

          L = NINT(100*MOD(CACHE(1,J),1D0)) - 10
          IF (L.LE.LMAG(IWRLD)) THEN
*           Wanted.
            CACHE(1,J) = EDGE
          ELSE
*           Not wanted.
            CACHE(1,J) = -EDGE
          END IF
 210    CONTINUE
      END IF


*  Produce labels.
      XW1 = BLC(1)
      XW2 = TRC(1)
      YW1 = BLC(2)
      YW2 = TRC(2)

*     These will define a box that just contains the labels.
      BNDRY(1) = YW1
      BNDRY(2) = XW1
      BNDRY(3) = YW2
      BNDRY(4) = XW2

*     These will record the edges on which labels were actually written.
      SKOP(1) = 0
      SKOP(2) = 0
      SKOP(3) = 0
      SKOP(4) = 0

*     Calendar date range.
      MJD1(1) =  1D99
      MJD1(2) =  1D99
      MJD2(1) = -1D99
      MJD2(2) = -1D99

*     Backslash.
      ESCAPE = CHAR(92)

*     Character height.
      CALL PGQCS (4, XCH, YCH)
      PRVEDG = 0

*     Loop through the axis crossing table.
      DO 340 J = 1, IC
*       Determine the position.
        IWRLD = NINT(CACHE(3,J))
        CALL PGSCI (CI(IWRLD+2))

        EDGE = ABS(NINT(CACHE(1,J)))
        IF (EDGE.NE.PRVEDG) THEN
*         Start of new edge.

          IF (SEXA(1) .OR. SEXA(2)) THEN
*           Sexagesimal field suppression policy.
            PRVDEG(1) = -1
            PRVMIN(1) = -1
            PRVDEG(2) = -1
            PRVMIN(2) = -1

            SEXSUP(1) = 0
            SEXSUP(2) = 0

*           Vertical sides.
            IF (MOD(EDGE,2).EQ.0) THEN
              DO 220 K = J, IC
                EDJE = ABS(NINT(CACHE(1,K)))
                IF (EDJE.NE.EDGE) GO TO 230

                KWRLD = NINT(CACHE(3,K))
                IF (SEXSUP(KWRLD).EQ.1) GO TO 220

                IF (FTYPE(KWRLD).EQ.'y') THEN
                  TMP = ABS(MOD(CACHE(4,K),1D0)*24D0)
                ELSE
                  TMP = ABS(CACHE(4,K))
                END IF

                LV = INT(TMP*3600D0 + 5D-7)
                LD =  LV/3600
                LM = (LV - LD*3600)/60
                LS =  LV - LD*3600 - LM*60
                TMP = TMP - LD

                IF (TMP.LT.5D-7) THEN
*                 Write deg/hr field only when min/sec are zero.
                  SEXSUP(KWRLD) = 1
                ELSE IF (TMP*60-LM.LT.3D-5) THEN
*                 Write min field only when sec is zero; only
*                 write the deg/hr field when min is written.
                  SEXSUP(KWRLD) = 2
                END IF
 220          CONTINUE
            END IF
          END IF
 230      CONTINUE

          PRVYR(1) = -1
          PRVYR(2) = -1

          XL = -999.0
          YL = -999.0
        END IF
        PRVEDG = EDGE
        LFORCE = .FALSE.

*       Fix up edge encoding.
        EDGE = NINT(CACHE(1,J))
        CACHE(1,J) = ABS(EDGE)

*       Use this label?
        IF (EDGE.LT.0) GO TO 340

        IF (EDGE.EQ.1) THEN
*         Bottom.
          FJUST = 0.5
          X = REAL(CACHE(2,J))
          Y = YW1 - 1.5*YCH
        ELSE IF (EDGE.EQ.2) THEN
*         Left.
          FJUST = 1.0
          X = XW1 - 0.5*XCH
          Y = REAL(CACHE(2,J)) - YCH/2.0
        ELSE IF (EDGE.EQ.3) THEN
*         Top.
          FJUST = 0.5
          X = REAL(CACHE(2,J))
          Y = YW2 + 0.5*YCH
        ELSE IF (EDGE.EQ.4) THEN
*         Right.
          FJUST = 0.0
          X = XW2 + 0.5*XCH
          Y = REAL(CACHE(2,J)) - YCH/2.0
        END IF

*       Format the numeric label.
        IF (INDEX('ABC', FTYPE(IWRLD)).NE.0) THEN
*         Decimal angle; allow up to 6 decimal digits.
          TMP = ABS(CACHE(4,J)) + 5D-7
          LD  = INT(TMP)

          K = 1
          IF (CACHE(4,J).LT.0D0) THEN
*           Insert a minus sign.
            TEXT(1:1) = '-'
            K = 2
          END IF

          CALL PGNUMB (LD, 0, 1, TEXT(K:), NCH)
          K = K + NCH
          TEXT(K:) = ESCAPE // 'uo' // ESCAPE // 'd'
          K = K + 4

          LV = INT(MOD(TMP,1D0)*1D6)
          IF (LV.NE.0) CALL PGNUMB (LV, -6, 1, TEXT(K:), NCH)
          TEXT(K:K) = 'd'

        ELSE IF (SEXA(IWRLD)) THEN
*         Sexagesimal format; angle or time?
          ANGLE = INDEX('DEF', FTYPE(IWRLD)).NE.0
          L = LMAG(IWRLD)

*         Use integer arithmetic to avoid rounding problems.
          IF (FTYPE(IWRLD).EQ.'y') THEN
            TMP = ABS(MOD(CACHE(4,J),1D0)*24D0)

*           Determine date range.
            IF (CACHE(4,J).LT.MJD1(IWRLD)) MJD1(IWRLD) = CACHE(4,J)
            IF (CACHE(4,J).GT.MJD2(IWRLD)) MJD2(IWRLD) = CACHE(4,J)
          ELSE
            TMP = ABS(CACHE(4,J))
          END IF
          VS = TMP*3600D0 + 5D-7
          LV = INT(VS)

*         Sexagesimal fields.
          LD =  LV/3600
          LM = (LV - LD*3600)/60
          LS =  LV - LD*3600 - LM*60

*         Field suppression policy.
          IF (SEXSUP(IWRLD).GT.0) THEN
            TMP = TMP - LD

            IF (TMP.LT.5D-7) THEN
              DODEG = .TRUE.
              DOMIN = .TRUE.
            ELSE IF (SEXSUP(IWRLD).EQ.2) THEN
              DOMIN = TMP*60-LM.LT.3D-5
              DODEG = DOMIN .AND. LD.NE.PRVDEG(IWRLD)
            ELSE
              DODEG = .FALSE.
              DOMIN = .FALSE.
            END IF
          ELSE
            DODEG = LD.NE.PRVDEG(IWRLD)
            DOMIN = LM.NE.PRVMIN(IWRLD)
          END IF

          K = 1
          IF (L.EQ.-2 .OR. DODEG) THEN
*           Write the degree/hour field.
            DODEG = .TRUE.

            IF (CACHE(4,J).LT.0D0) THEN
*             Insert a minus sign.
              TEXT(1:1) = '-'
              K = 2
            END IF

            IF (ANGLE) THEN
*             Angle.
              CALL PGNUMB (LD, 0, 1, TEXT(K:), NCH)
              K = K + NCH
              TEXT(K:) = ESCAPE // 'uo' // ESCAPE // 'd'
              K = K + 5
            ELSE
*             Time.
              IF (LD.LE.9 .AND. INDEX('Ty',FTYPE(IWRLD)).EQ.0) THEN
*               Write leading zeroes in the hour field.
                WRITE (TEXT(K:), '(I2.2)') LD
                K = K + 2
              ELSE
                CALL PGNUMB (LD, 0, 1, TEXT(K:), NCH)
                K = K + NCH
              END IF
              TEXT(K:) = ESCAPE // 'uh' // ESCAPE // 'd'
              K = K + 5
            END IF
          END IF

          IF (L.GE.-1 .AND.
     :      .NOT.(L.LE.0 .AND. K.GT.1 .AND. LM.EQ.0 .AND. LS.EQ.0)) THEN
*           Write arcminute/minute field.
            IF (L.EQ.-1 .OR. K.GT.1 .OR. DOMIN) THEN
              DOMIN = .TRUE.
              IF (ANGLE) THEN
                WRITE (TEXT(K:), '(I2.2,A)') LM, ''''
                K = K + 3
              ELSE
                WRITE (TEXT(K:), '(I2.2,A)') LM,
     :            ESCAPE // 'um' // ESCAPE // 'd'
                K = K + 7
              END IF
            END IF

            IF (L.GE.0) THEN
*             Arcsec/second field.
              IF (ANGLE) THEN
                WRITE (TEXT(K:), '(I2.2,A)') LS, '"'
                K = K + 3
              ELSE
                WRITE (TEXT(K:), '(I2.2,A)') LS,
     :            ESCAPE // 'us' // ESCAPE // 'd'
                K = K + 7
              END IF

              IF (L.GT.0) THEN
*               Sub-arcsec/second field.
                WRITE (FMT, '(A,I1,A,I1,A)') '(A,I', L, '.', L, ')'
                LV = INT(MOD(VS,1D0)*10**L)
                WRITE (TEXT(K:), FMT) '.', LV
              END IF
            END IF
          END IF

        ELSE IF (FTYPE(IWRLD).EQ.'L') THEN
*         Logarithmic.
          TMP = MOD(CACHE(4,J),1D0)
          IF (TMP.LT.0D0) TMP = TMP + 1D0
          MM = NINT(10D0**TMP)
          IF (MM.EQ.10) THEN
            TMP = TMP - 1D0
            MM = 1
          END IF

          PP = NINT(CACHE(4,J) - TMP)

          IF (MM.NE.1) THEN
            WRITE (TEXT, '(I1)') MM
          ELSE
*           Fortran is really abysmal sometimes.
            WRITE (TEXT, '(I8)') PP
            DO 240 K = 1, 8
              IF (TEXT(K:K).NE.' ') GO TO 250
 240        CONTINUE
 250        TEXT = '10' // ESCAPE // 'u' // TEXT(K:8)

            LFORCE = .TRUE.
          END IF

        ELSE IF (FTYPE(IWRLD).EQ.'Y') THEN
*         Convert MJD to Gregorian calendar date, YYYY/MM/DD.
          CALL PGMJD(0, CACHE(4,J), IY, IM, ID)
          DOYEAR = IY.NE.PRVYR(IWRLD)

          IF (DOYEAR) THEN
            WRITE (TEXT, 260) IY, IM, ID
 260        FORMAT (I12,'/',I2.2,'/',I2.2)

            DO 270 K = 1, 12
              IF (TEXT(K:K).NE.' ') GO TO 280
 270        CONTINUE
 280        TEXT = TEXT(K:18)

          ELSE
            WRITE (TEXT, 290) IM, ID
 290        FORMAT (I2.2,'/',I2.2)
          END IF

        ELSE
*         Plain number; allow up to six significant digits.
          IF (CACHE(4,J).NE.0D0) THEN
            PP = INT(LOG10(ABS(CACHE(4,J)))) - 6
            MM = NINT(CACHE(4,J)/10D0**PP)
          ELSE
            PP = 0
            MM = 0
          END IF

          CALL PGNUMB (MM, PP, 0, TEXT, NCH)
        END IF

*       Write the label if it doesn't overlap the previous one.
        CALL PGQTXT (X, Y, 0.0, FJUST, TEXT, XBOX, YBOX)
        IF (LFORCE .OR. XBOX(1).GT.XL .OR. YBOX(1).GT.YL) THEN
          IF (IWRLD.EQ.1) THEN
            CALL PGSCI (CI(3))
          ELSE
            CALL PGSCI (CI(4))
          END IF

          CALL PGPTXT (X, Y, 0.0, FJUST, TEXT)
          XL = XBOX(4) + 0.5*XCH
          YL = YBOX(2) + 0.5*YCH

*         Sexagesimal formatting.
          IF (SEXA(IWRLD)) THEN
            IF (DODEG) PRVDEG(IWRLD) = LD
            IF (DOMIN) PRVMIN(IWRLD) = LM
          END IF

*         Calendar formatting.
          IF (FTYPE(IWRLD).EQ.'Y') THEN
            IF (DOYEAR) PRVYR(IWRLD) = IY
          END IF

*         Record the fact.
          IF (IWRLD.EQ.1) THEN
            SKOP(EDGE) = 2*(SKOP(EDGE)/2) + 1
          ELSE
            SKOP(EDGE) = 2 + MOD(SKOP(EDGE),2)
          END IF

*         Boundary within which the numeric labels lie.
          IF (YBOX(1).LT.BNDRY(1)) BNDRY(1) = YBOX(1)
          IF (XBOX(1).LT.BNDRY(2)) BNDRY(2) = XBOX(1)
          IF (YBOX(3).GT.BNDRY(3)) BNDRY(3) = YBOX(3)
          IF (XBOX(3).GT.BNDRY(4)) BNDRY(4) = XBOX(3)

*         Check the distance to the previous grid line.
          TICKIT = .FALSE.
          K = J - 1
          IF (DOLAB(EDGE).NE.3) THEN
*           Only one coordinate element labelled on this edge, no need
*           to worry about grid lines belonging to the other.
            DO 300 K = J-1, 1, -1
              IF (IWRLD.EQ.NINT(CACHE(3,K))) GO TO 310
 300        CONTINUE
          END IF

 310      IF (K.GE.1) THEN
            EDJE = ABS(NINT(CACHE(1,K)))
            IF (EDJE.EQ.EDGE) THEN
              IF (EDGE.EQ.1 .OR. EDGE.EQ.3) THEN
                IF (XBOX(1).LT.CACHE(2,K)) TICKIT = .TRUE.
              ELSE
                IF (YBOX(1).LT.CACHE(2,K)) TICKIT = .TRUE.
              END IF
            END IF
          END IF

*         Check the distance to the next grid line.
          K = J + 1
          IF (DOLAB(EDGE).NE.3) THEN
*           Only one coordinate element labelled on this edge, no need
*           to worry about grid lines belonging to the other.
            DO 320 K = J+1, IC
              IF (IWRLD.EQ.NINT(CACHE(3,K))) GO TO 330
 320        CONTINUE
          END IF

 330      IF (K.LE.IC) THEN
            EDJE = ABS(NINT(CACHE(1,K)))
            IF (EDJE.EQ.EDGE) THEN
              IF (EDGE.EQ.1 .OR. EDGE.EQ.3) THEN
                IF (XBOX(3).GT.CACHE(2,K)) TICKIT = .TRUE.
              ELSE
                IF (YBOX(3).GT.CACHE(2,K)) TICKIT = .TRUE.
              END IF
            END IF
          END IF

*         Density of grid lines is high.
          IF (TICKIT) THEN
*           Draw outside pip mark to disambiguate grid lines.
            Z = REAL(CACHE(2,J))
            IF (EDGE.EQ.1) THEN
              CALL PGMOVE (Z, YW1-0.3*YCH)
              CALL PGDRAW (Z, YW1)
            ELSE IF (EDGE.EQ.2) THEN
              CALL PGMOVE (XW1-0.3*XCH, Z)
              CALL PGDRAW (XW1, Z)
            ELSE IF (EDGE.EQ.3) THEN
              CALL PGMOVE (Z, YW2+0.3*YCH)
              CALL PGDRAW (Z, YW2)
            ELSE IF (EDGE.EQ.4) THEN
              CALL PGMOVE (XW2+0.3*XCH, Z)
              CALL PGDRAW (XW2, Z)
            END IF
          END IF
        END IF
 340  CONTINUE


*  Write the identification strings.
*     World coordinates.
      DO 470 EDGE = 1, 4
        TEXT = ' '

        DO 440 IWRLD = 1, 2
          TXT(IWRLD) = ' '

          IF (MOD(SKOP(EDGE)/IWRLD,2).EQ.0) GO TO 440

*         Strip off leading blanks.
          L = LEN(IDENTS(IWRLD))
          DO 350 K = 1, L
            IF (IDENTS(IWRLD)(K:K).NE.' ') THEN
              TXT(IWRLD) = IDENTS(IWRLD)(K:L)
              GO TO 360
            END IF
 350      CONTINUE

 360      IF (IMAG(IWRLD).NE.0 .OR. FTYPE(IWRLD).EQ.'y') THEN
*           Find the last non-blank.
            DO 370 K = 40, 1, -1
              IF (TXT(IWRLD)(K:K).NE.' ') GO TO 380
 370        CONTINUE
 380        K = K + 1

            IF (IMAG(IWRLD).NE.0) THEN
*             Add scaling information.
              CALL PGNUMB (IMAG(IWRLD), 0, 1, EXPONT, NCH)
              TXT(IWRLD)(K:) = '  x10' // ESCAPE // 'u' // EXPONT
            ELSE
*             Add calendar date range.
              CALL PGMJD(0, MJD1(IWRLD), IY, IM, ID)

              WRITE (TEXT, 390) IY, IM, ID
 390          FORMAT (I12,'/',I2.2,'/',I2.2)
              DO 400 L = 1, 12
                IF (TEXT(L:L).NE.' ') GO TO 410
 400          CONTINUE
 410          TXT(IWRLD)(K:) = ' (' // TEXT(L:18)
              K = K + 21 - L

              CALL PGMJD(0, MJD2(IWRLD), IY2, IM2, ID2)
              WRITE (TEXT, 390) IY2, IM2, ID2
              IF (IY2.EQ.IY) THEN
                IF (IM2.EQ.IM) THEN
                  IF (ID2.EQ.ID) THEN
                    TXT(IWRLD)(K:) = ')'
                  ELSE
                    TXT(IWRLD)(K:) = ' - ' // TEXT(17:18) // ')'
                  END IF
                ELSE
                  TXT(IWRLD)(K:) = ' - ' // TEXT(14:18) // ')'
                END IF
              ELSE
                DO 420 L = 1, 12
                  IF (TEXT(L:L).NE.' ') GO TO 430
 420            CONTINUE
 430            TXT(IWRLD)(K:) = ' - ' // TEXT(L:18) // ')'
              END IF
            END IF
          END IF

 440    CONTINUE

        K = 0
        IF (TXT(1).NE.' ') THEN
*         Identify first world coordinate...
          TEXT = TXT(1)
          CALL PGSCI (CI(5))

          IF (TXT(2).NE.' ') THEN
*           ...and also second world coordinate.
            DO 450 K = 40, 1, -1
              IF (TEXT(K:K).NE.' ') GO TO 460
 450        CONTINUE
 460        K = K + 1

            TEXT(K:) = ',  ' // TXT(2)(:76)
          END IF
        ELSE IF (TXT(2).NE.' ') THEN
*         Identify second world coordinate only.
          TEXT = TXT(2)
          CALL PGSCI (CI(6))
        ELSE
*         No text to write.
          GO TO 470
        END IF

        IF (EDGE.EQ.1) THEN
          X = (XW1 + XW2)/2.0
          Y = BNDRY(1) - 1.5*YCH
          ANGL = 0.0
        ELSE IF (EDGE.EQ.2) THEN
          IF (TEXT(2:).EQ.' ') THEN
*           One character, write upright.
            X = BNDRY(2) - 1.0*XCH
            Y = (YW1 + YW2)/2.0
            ANGL = 0.0
          ELSE
            X = BNDRY(2) - 0.5*XCH
            Y = (YW1 + YW2)/2.0
            ANGL = 90.0
          END IF
        ELSE IF (EDGE.EQ.3) THEN
          X = (XW1 + XW2)/2.0
          Y = BNDRY(3) + 0.5*YCH
          ANGL = 0.0
        ELSE IF (EDGE.EQ.4) THEN
          IF (TEXT(2:).EQ.' ') THEN
*           One character, write upright.
            X = BNDRY(4) + 1.0*XCH
            Y = (YW1 + YW2)/2.0
            ANGL = 0.0
          ELSE
            X = BNDRY(4) + 0.5*XCH
            Y = (YW1 + YW2)/2.0
            ANGL = -90.0
          END IF
        END IF

        CALL PGQTXT (X, Y, ANGL, 0.5, TEXT, XBOX, YBOX)
        IF (K.EQ.0) THEN
          CALL PGPTXT (X, Y, ANGL, 0.5, TEXT)
        ELSE
*         Two-colour annotation.
          CALL PGPTXT (XBOX(1), YBOX(1), ANGL, 0.0, TEXT(:K))
          CALL PGSCI (CI(6))
          CALL PGPTXT (XBOX(4), YBOX(4), ANGL, 1.0, TEXT(K+1:))
        END IF

*       Update the boundary.
        IF (YBOX(1).LT.BNDRY(1)) BNDRY(1) = YBOX(1)
        IF (YBOX(3).LT.BNDRY(1)) BNDRY(1) = YBOX(3)
        IF (XBOX(1).LT.BNDRY(2)) BNDRY(2) = XBOX(1)
        IF (XBOX(3).LT.BNDRY(2)) BNDRY(2) = XBOX(3)
        IF (YBOX(1).GT.BNDRY(3)) BNDRY(3) = YBOX(1)
        IF (YBOX(3).GT.BNDRY(3)) BNDRY(3) = YBOX(3)
        IF (XBOX(1).GT.BNDRY(4)) BNDRY(4) = XBOX(1)
        IF (XBOX(3).GT.BNDRY(4)) BNDRY(4) = XBOX(3)
 470  CONTINUE

*     Title.
      IF (IDENTS(3).NE.' ') THEN
        CALL PGSCI (CI(7))
        X = (XW1 + XW2)/2.0
        Y = BNDRY(3) + 0.5*YCH
        CALL PGQTXT (X, Y, 0.0, 0.5, IDENTS(3), XBOX, YBOX)
        CALL PGPTXT (X, Y, 0.0, 0.5, IDENTS(3))

*       Update the boundary.
        IF (XBOX(1).LT.BNDRY(2)) BNDRY(2) = XBOX(1)
        IF (YBOX(3).GT.BNDRY(3)) BNDRY(3) = YBOX(3)
        IF (XBOX(3).GT.BNDRY(4)) BNDRY(4) = XBOX(3)
      END IF


*     Return margin widths in Cartesian coordinates.
      CACHE(1,NC) = YW1 - BNDRY(1)
      CACHE(2,NC) = XW1 - BNDRY(2)
      CACHE(3,NC) = BNDRY(3) - YW2
      CACHE(4,NC) = BNDRY(4) - XW2


      RETURN
      END


*=======================================================================
* MJD to/from Gregorian calendar date.
*
* Given:
*   CODE      I         If 1, compute MJD from IY,IM,ID, else vice
*                       versa.
*
* Given and/or returned:
*   MJD       D         Modified Julian date, (MJD = JD - 2400000.5).
*   IY        I         Year.
*   IM        I         Month (for CODE.EQ.1 may exceed 12, or be zero,
*                       or negative).
*   ID        I         Day of month (for CODE.EQ.1, may exceed the
*                       legitimate number of days in the month, or be
*                       zero, or negative).
*
* Notes:
*   These algorithms are from D.A. Hatcher, QJRAS 25, 53-55, as modified
*   by P.T. Wallace for use in SLALIB (subroutines CLDJ and DJCL).
*
* Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
*-----------------------------------------------------------------------
      SUBROUTINE PGMJD (CODE, MJD, IY, IM, ID)
*-----------------------------------------------------------------------
      INTEGER   CODE, DD, ID, IM, IY, JD, JM, JY, N4
      DOUBLE PRECISION MJD
*-----------------------------------------------------------------------
      IF (CODE.EQ.1) THEN
*       Calendar date to MJD.
        IF (IM.LT.1) THEN
          JY = IY - 1 + IM/12
          JM = 12 + MOD(IM,12)
        ELSE
          JY = IY + (IM-1)/12
          JM = MOD(IM-1,12) + 1
        END IF

        MJD =DBLE((1461*(JY - (12-JM)/10 + 4712))/4
     :          +(306*MOD(JM+9, 12) + 5)/10
     :          -(3*((JY - (12-JM)/10 + 4900)/100))/4
     :          + ID - 2399904)

      ELSE
*       MJD to calendar date.
        JD = 2400001 + INT(MJD)

        N4 =  4*(JD + ((2*((4*JD - 17918)/146097)*3)/4 + 1)/2 - 37)
        DD = 10*(MOD(N4-237, 1461)/4) + 5

        IY = N4/1461 - 4712
        IM = MOD(2 + DD/306, 12) + 1
        ID = MOD(DD, 306)/10 + 1
      END IF

      RETURN
      END



*=======================================================================
* This Fortran wrapper on PGSBOX exists solely to define fixed-length
* CHARACTER arguments for cpgsbox().
*-----------------------------------------------------------------------
      SUBROUTINE PGSBOK (BLC, TRC, IDENTS, OPT, LABCTL, LABDEN, CI,
     :  GCODE, TIKLEN, NG1, GRID1, NG2, GRID2, DOEQ, NLFUNC, NLC, NLI,
     :  NLD, NLCPRM, NLIPRM, NLDPRM, NC, IC, CACHE, IERR)
*-----------------------------------------------------------------------
      LOGICAL   DOEQ
      INTEGER   CI(7), GCODE(2), IC, IERR, LABCTL, LABDEN, NC, NG1, NG2,
     :          NLC, NLD, NLI, NLIPRM(NLI)
      REAL      BLC(2), TRC(2)
      DOUBLE PRECISION CACHE(4,0:NC), GRID1(0:NG1), GRID2(0:NG2),
     :          NLDPRM(NLD), TIKLEN
      CHARACTER IDENTS(3)*80, NLCPRM(NLC)*1, OPT(2)*1

      EXTERNAL NLFUNC
*-----------------------------------------------------------------------
      CALL PGSBOX (BLC, TRC, IDENTS, OPT, LABCTL, LABDEN, CI, GCODE,
     :  TIKLEN, NG1, GRID1, NG2, GRID2, DOEQ, NLFUNC, NLC, NLI, NLD,
     :  NLCPRM, NLIPRM, NLDPRM, NC, IC, CACHE, IERR)

      RETURN
      END



*=======================================================================
* This Fortran wrapper on PGLBOX exists solely to define fixed-length
* CHARACTER arguments for cpglbox().
*-----------------------------------------------------------------------
      SUBROUTINE PGLBOK (IDENTS, OPT, LABCTL, LABDEN, CI, GCODE, TIKLEN,
     :  NG1, GRID1, NG2, GRID2, DOEQ, NC, IC, CACHE, IERR)
*-----------------------------------------------------------------------
      LOGICAL   DOEQ
      INTEGER   CI(7), GCODE(2), IC, IERR, LABCTL, LABDEN, NC, NG1, NG2
      DOUBLE PRECISION CACHE(4,0:NC), GRID1(0:NG1), GRID2(0:NG2), TIKLEN
      CHARACTER IDENTS(3)*80, OPT(2)*1
*-----------------------------------------------------------------------
      CALL PGLBOX (IDENTS, OPT, LABCTL, LABDEN, CI, GCODE, TIKLEN, NG1,
     :  GRID1, NG2, GRID2, DOEQ, NC, IC, CACHE, IERR)

      RETURN
      END
@


8.6
log
@WCSLIB 8.6
@
text
@d3 1
a3 1
* PGSBOX 8.6 - draw curvilinear coordinate axes for PGPLOT.
d23 1
a23 1
* $Id: pgsbox.f,v 8.5.1.3 2026/03/29 13:36:20 mcalabre Exp mcalabre $
@


8.6.1.1
log
@WCSLIB 8.6 development branch.
@
text
@d23 1
a23 1
* $Id: pgsbox.f,v 8.6 2026/03/29 13:53:57 mcalabre Exp $
@


8.5
log
@WCSLIB 8.5
@
text
@d3 2
a4 2
* PGSBOX 8.5 - draw curvilinear coordinate axes for PGPLOT.
* Copyright (C) 1997-2025, Mark Calabretta
d22 2
a23 2
* http://www.atnf.csiro.au/people/Mark.Calabretta
* $Id: pgsbox.f,v 8.4.1.2 2025/12/06 13:37:20 mcalabre Exp mcalabre $
d463 4
a466 3
      REAL      BLC(2), BLC_(2), RTIKLN, S, TRC(2), TRC_(2), WXY(4), X1,
     :          X2, XPOINT, XR(BUFSIZ), XSCL, XSPAN, XTOL, XVP1, XVP2,
     :          Y1, Y2, YR(BUFSIZ), YSCL, YSPAN, YTOL, YVP1, YVP2
d471 1
a471 1
     :          WMIN(2), WORLD(9), XY(9)
d1254 2
d1259 77
d1358 56
@


8.5.1.1
log
@WCSLIB 8.5 development branch.
@
text
@d23 1
a23 1
* $Id: pgsbox.f,v 8.5 2025/12/06 13:47:42 mcalabre Exp $
@


8.5.1.2
log
@PGSBOX now accounts for the possibility that the coordinate system is not
defined outside the frame.  Previously this was important for determining
axis crossings and hence axis labelling.  However, it is not valid for -TAB
coordinates in FITS for which extrapolation is strictly limited to half a
pixel.
@
text
@d22 2
a23 2
* http://www.atnf.csiro.au/computing/software/wcs
* $Id: pgsbox.f,v 8.5.1.1 2025/12/06 14:05:17 mcalabre Exp mcalabre $
d463 3
a465 4
      REAL      BLC(2), BLC_(2), RHO, RTIKLN, S, TAU, TRC(2), TRC_(2),
     :          WXY(4), X1, X2, XPOINT, XR(BUFSIZ), XSCL, XSPAN, xSTEP,
     :          XTOL, XVP1, XVP2, Y1, Y2, YR(BUFSIZ), YSCL, YSPAN,
     :          YSTEP, YTOL, YVP1, YVP2
d470 1
a470 1
     :          WMIN(2), WORLD(9), WRLD(9), XY(9)
a1252 2

*               On the frame is outside; gives a crossing-point.
a1255 77
*               Account for coordinate systems that are not defined
*               outside the frame.
                IF (INSIDE .AND. IWK.GT.0) THEN
*                 If the first point (IWK.EQ.0) is valid and already
*                 inside the frame, then the grid line begins inside
*                 the frame.  However, if there were invalid points
*                 before it (IWK.GT.0) and the first valid point is
*                 already inside the frame then look for a crossing
*                 point.
                  WRLD(J) = WORLD(J)
                  WRLD(K) = WORLD(K) + SW(K)

                  IF (DOLBOX) THEN
                    XY(1) = (WRLD(1) - WXY(1))/XSPAN
                    XY(2) = (WRLD(2) - WXY(3))/YSPAN
                  ELSE
                    CALL NLFUNC (1, NLC, NLI, NLD, NLCPRM, NLIPRM,
     :                NLDPRM, WRLD, XY, CONTRL, CONTXT, IERR)
                  END IF

                  IF (IERR.LE.0) THEN
                    X2 = REAL(XY(1))
                    Y2 = REAL(XY(2))

                    RHO = 999.0
                    XSTEP = X2 - X1
                    YSTEP = Y2 - Y1

                    IF (XSTEP.NE.0.0) THEN
*                     Proximity to left edge of frame.
                      TAU = (X1 - BLC(1)) / XSTEP
                      IF (ABS(TAU).LT.RHO) THEN
                        XY(1) = BLC(1)
                        XY(2) = Y1 - TAU*YSTEP
                        RHO = ABS(TAU)
                      END IF

*                     Proximity to right edge of frame.
                      TAU = (X1 - TRC(1)) / XSTEP
                      IF (ABS(TAU).LT.RHO) THEN
                        XY(1) = TRC(1)
                        XY(2) = Y1 - TAU*YSTEP
                        RHO = ABS(TAU)
                      END IF
                    END IF

                    IF (YSTEP.NE.0.0) THEN
*                     Proximity to bottom edge of frame.
                      TAU = (Y1 - BLC(2)) / YSTEP
                      IF (ABS(TAU).LT.RHO) THEN
                        XY(1) = X1 - TAU*XSTEP
                        XY(2) = BLC(2)
                        RHO = ABS(TAU)
                      END IF

*                     Proximity to top edge of frame.
                      TAU = (Y1 - TRC(2)) / YSTEP
                      IF (ABS(TAU).LT.RHO) THEN
                        XY(1) = X1 - TAU*XSTEP
                        XY(2) = TRC(2)
                        RHO = ABS(TAU)
                      END IF
                    END IF

*                   Check that it really is a crossing point.
                    IF (RHO.LT.3.0) THEN
                      CALL NLFUNC (-1, NLC, NLI, NLD, NLCPRM, NLIPRM,
     :                  NLDPRM, WRLD, XY, CONTRL, CONTXT, IERR)
                      IF (IERR.LE.0) THEN
                        X1 = REAL(XY(1))
                        Y1 = REAL(XY(2))
                        INSIDE = .FALSE.
                      END IF
                    END IF
                  END IF
                END IF

a1277 56
*               Account for coordinate systems that are not defined
*               outside the frame.
                IF (NP.GT.1 .AND. .NOT.GETEND) THEN
*                 Look for a crossing point.
                  RHO = 999.0
                  XSTEP = XR(NP) - XR(NP-1)
                  YSTEP = YR(NP) - YR(NP-1)

                  IF (XSTEP.NE.0.0) THEN
*                   Proximity to left edge of frame.
                    TAU = (BLC(1) - XR(NP)) / XSTEP
                    IF (ABS(TAU).LT.RHO) THEN
                      XY(1) = BLC(1)
                      XY(2) = YR(NP) + TAU*YSTEP
                      RHO = ABS(TAU)
                    END IF

*                   Proximity to right edge of frame.
                    TAU = (TRC(1) - XR(NP)) / XSTEP
                    IF (ABS(TAU).LT.RHO) THEN
                      XY(1) = TRC(1)
                      XY(2) = YR(NP) + TAU*YSTEP
                      RHO = ABS(TAU)
                    END IF
                  END IF

                  IF (YSTEP.NE.0.0) THEN
*                   Proximity to bottom edge of frame.
                    TAU = (BLC(2) - YR(NP)) / YSTEP
                    IF (ABS(TAU).LT.RHO) THEN
                      XY(1) = XR(NP) + TAU*XSTEP
                      XY(2) = BLC(2)
                      RHO = ABS(TAU)
                    END IF

*                   Proximity to top edge of frame.
                    TAU = (TRC(2) - YR(NP)) / YSTEP
                    IF (ABS(TAU).LT.RHO) THEN
                      XY(1) = XR(NP) + TAU*XSTEP
                      XY(2) = TRC(2)
                      RHO = ABS(TAU)
                    END IF
                  END IF

*                 Check that it really is a crossing point.
                  IF (RHO.LT.3.0) THEN
                    CALL NLFUNC (-1, NLC, NLI, NLD, NLCPRM, NLIPRM,
     :                NLDPRM, WRLD, XY, CONTRL, CONTXT, IERR)
                    IF (IERR.LE.0) THEN
                      NP = NP + 1
                      XR(NP) = REAL(XY(1))
                      YR(NP) = REAL(XY(2))
                    END IF
                  END IF
                END IF

@


8.5.1.3
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
* Copyright (C) 1997-2026, Mark Calabretta
d23 1
a23 1
* $Id: pgsbox.f,v 8.5.1.2 2026/03/29 13:21:35 mcalabre Exp mcalabre $
@


8.4
log
@WCSLIB 8.4
@
text
@d3 2
a4 2
* PGSBOX 8.4 - draw curvilinear coordinate axes for PGPLOT.
* Copyright (C) 1997-2024, Mark Calabretta
d23 1
a23 1
* $Id: pgsbox.f,v 8.3.1.1 2024/05/13 16:35:40 mcalabre Exp mcalabre $
@


8.4.1.1
log
@WCSLIB 8.4 development branch.
@
text
@d23 1
a23 1
* $Id: pgsbox.f,v 8.4 2024/10/28 13:56:18 mcalabre Exp $
@


8.4.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
* Copyright (C) 1997-2025, Mark Calabretta
d23 1
a23 1
* $Id: pgsbox.f,v 8.4.1.1 2024/10/28 13:58:42 mcalabre Exp mcalabre $
@


8.3
log
@WCSLIB 8.3
@
text
@d3 1
a3 1
* PGSBOX 8.3 - draw curvilinear coordinate axes for PGPLOT.
d23 1
a23 1
* $Id: pgsbox.f,v 8.2.1.3 2024/05/06 09:26:06 mcalabre Exp mcalabre $
@


8.3.1.1
log
@WCSLIB 8.3 development branch.
@
text
@d23 1
a23 1
* $Id: pgsbox.f,v 8.3 2024/05/13 16:33:01 mcalabre Exp $
@


8.2
log
@WCSLIB 8.2
@
text
@d3 2
a4 2
* PGSBOX 8.2 - draw curvilinear coordinate axes for PGPLOT.
* Copyright (C) 1997-2023, Mark Calabretta
d23 1
a23 1
* $Id: pgsbox.f,v 8.1.1.1 2023/07/05 17:15:01 mcalabre Exp mcalabre $
d2460 1
a2460 1
            TEXT(K:) = ',  ' // TXT(2)
a2611 2
*
* Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
a2638 2
*
* Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
@


8.2.1.1
log
@WCSLIB 8.2 development branch.
@
text
@d23 1
a23 1
* $Id: pgsbox.f,v 8.2 2023/11/16 10:00:31 mcalabre Exp $
@


8.2.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
* Copyright (C) 1997-2024, Mark Calabretta
d23 1
a23 1
* $Id: pgsbox.f,v 8.2.1.1 2023/11/16 10:05:59 mcalabre Exp mcalabre $
@


8.2.1.3
log
@In PGSBOX, fixed a nuisance compiler warning.
@
text
@d23 1
a23 1
* $Id: pgsbox.f,v 8.2.1.2 2024/04/02 13:43:15 mcalabre Exp mcalabre $
d2460 1
a2460 1
            TEXT(K:) = ',  ' // TXT(2)(:76)
d2612 2
d2641 2
@


8.1
log
@WCSLIB 8.1
@
text
@d3 1
a3 1
* PGSBOX 8.1 - draw curvilinear coordinate axes for PGPLOT.
d23 1
a23 1
* $Id: pgsbox.f,v 8.0.1.1 2023/07/01 06:22:45 mcalabre Exp mcalabre $
@


8.1.1.1
log
@WCSLIB 8.1 development branch.
@
text
@d23 1
a23 1
* $Id: pgsbox.f,v 8.1 2023/07/05 17:12:07 mcalabre Exp $
@


8.0
log
@WCSLIB 8.0
@
text
@d3 1
a3 1
* PGSBOX 8.0 - draw curvilinear coordinate axes for PGPLOT.
d23 1
a23 1
* $Id: pgsbox.f,v 7.13.1.2 2023/06/15 04:17:22 mcalabre Exp mcalabre $
@


8.0.1.1
log
@WCSLIB 8.0 development branch.
@
text
@d23 1
a23 1
* $Id: pgsbox.f,v 8.0 2023/07/01 06:15:05 mcalabre Exp $
@


7.13
log
@WCSLIB 7.13
@
text
@d3 2
a4 2
* PGSBOX 7.13 - draw curvilinear coordinate axes for PGPLOT.
* Copyright (C) 1997-2022, Mark Calabretta
d23 1
a23 1
* $Id: pgsbox.f,v 7.12.1.1 2022/09/09 05:00:36 mcalabre Exp mcalabre $
@


7.13.1.1
log
@WCSLIB 7.13 development branch.
@
text
@d23 1
a23 1
* $Id: pgsbox.f,v 7.13 2022/10/07 03:43:35 mcalabre Exp $
@


7.13.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
* Copyright (C) 1997-2023, Mark Calabretta
d23 1
a23 1
* $Id: pgsbox.f,v 7.13.1.1 2022/10/07 03:45:47 mcalabre Exp mcalabre $
@


7.12
log
@WCSLIB 7.12
@
text
@d3 1
a3 1
* PGSBOX 7.12 - draw curvilinear coordinate axes for PGPLOT.
d23 1
a23 1
* $Id: pgsbox.f,v 7.11.1.1 2022/04/26 06:15:33 mcalabre Exp mcalabre $
@


7.12.1.1
log
@WCSLIB 7.12 development branch.
@
text
@d23 1
a23 1
* $Id: pgsbox.f,v 7.12 2022/09/09 04:57:58 mcalabre Exp $
@


7.11
log
@WCSLIB 7.11
@
text
@d3 1
a3 1
* PGSBOX 7.11 - draw curvilinear coordinate axes for PGPLOT.
d23 1
a23 1
* $Id: pgsbox.f,v 7.10.1.1 2022/04/23 14:26:55 mcalabre Exp mcalabre $
@


7.11.1.1
log
@WCSLIB 7.11 development branch.
@
text
@d23 1
a23 1
* $Id: pgsbox.f,v 7.11 2022/04/26 06:13:52 mcalabre Exp $
@


7.10
log
@WCSLIB 7.10
@
text
@d3 1
a3 1
* PGSBOX 7.10 - draw curvilinear coordinate axes for PGPLOT.
d23 1
a23 1
* $Id: pgsbox.f,v 7.9.1.1 2022/03/25 15:16:40 mcalabre Exp mcalabre $
@


7.10.1.1
log
@WCSLIB 7.10 development branch.
@
text
@d23 1
a23 1
* $Id: pgsbox.f,v 7.10 2022/04/23 14:25:15 mcalabre Exp $
@


7.9
log
@WCSLIB 7.9
@
text
@d3 1
a3 1
* PGSBOX 7.9 - draw curvilinear coordinate axes for PGPLOT.
d23 1
a23 1
* $Id: pgsbox.f,v 7.8.1.1 2022/03/25 06:14:15 mcalabre Exp mcalabre $
@


7.9.1.1
log
@WCSLIB 7.9 development branch.
@
text
@d23 1
a23 1
* $Id: pgsbox.f,v 7.9 2022/03/25 15:14:49 mcalabre Exp $
@


7.8
log
@WCSLIB 7.8
@
text
@d3 1
a3 1
* PGSBOX 7.8 - draw curvilinear coordinate axes for PGPLOT.
d23 1
a23 1
* $Id: pgsbox.f,v 7.7.1.2 2022/03/25 06:06:01 mcalabre Exp mcalabre $
@


7.8.1.1
log
@WCSLIB 7.8 development branch.
@
text
@d23 1
a23 1
* $Id: pgsbox.f,v 7.8 2022/03/25 06:11:50 mcalabre Exp $
@


7.7
log
@WCSLIB 7.7
@
text
@d3 2
a4 2
* PGSBOX 7.7 - draw curvilinear coordinate axes for PGPLOT.
* Copyright (C) 1997-2021, Mark Calabretta
d23 1
a23 1
* $Id: pgsbox.f,v 7.6.1.2 2021/07/01 14:45:37 mcalabre Exp mcalabre $
@


7.7.1.1
log
@WCSLIB 7.7 development branch.
@
text
@d23 1
a23 1
* $Id: pgsbox.f,v 7.7 2021/07/12 06:36:49 mcalabre Exp $
@


7.7.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
* Copyright (C) 1997-2022, Mark Calabretta
d23 1
a23 1
* $Id: pgsbox.f,v 7.7.1.1 2021/07/12 06:38:28 mcalabre Exp mcalabre $
@


7.6
log
@WCSLIB 7.6
@
text
@d3 1
a3 1
* PGSBOX 7.6 - draw curvilinear coordinate axes for PGPLOT.
d23 1
a23 1
* $Id: pgsbox.f,v 7.5.1.1 2021/03/20 05:56:42 mcalabre Exp mcalabre $
a1579 2
      DATA ESCAPE /'\\'/

d1992 3
@


7.6.1.1
log
@WCSLIB 7.6 development branch.
@
text
@d23 1
a23 1
* $Id: pgsbox.f,v 7.6 2021/04/13 12:57:02 mcalabre Exp $
@


7.6.1.2
log
@Define ESCAPE using the CHAR() function to avoid the confusion that arises
by gfortran interpreting it as a C-style escape character.
@
text
@d23 1
a23 1
* $Id: pgsbox.f,v 7.6.1.1 2021/04/13 13:00:37 mcalabre Exp mcalabre $
d1580 2
a1993 3

*     Backslash.
      ESCAPE = CHAR(92)
@


7.5
log
@WCSLIB 7.5
@
text
@d3 1
a3 1
* PGSBOX 7.5 - draw curvilinear coordinate axes for PGPLOT.
d23 1
a23 1
* $Id: pgsbox.f,v 7.4.1.1 2021/01/31 02:26:24 mcalabre Exp mcalabre $
@


7.5.1.1
log
@WCSLIB 7.5 development branch.
@
text
@d23 1
a23 1
* $Id: pgsbox.f,v 7.5 2021/03/20 05:54:59 mcalabre Exp $
@


7.4
log
@WCSLIB 7.4
@
text
@d3 1
a3 1
* PGSBOX 7.4 - draw curvilinear coordinate axes for PGPLOT.
d23 1
a23 1
* $Id: pgsbox.f,v 7.3.1.3 2021/01/28 12:32:51 mcalabre Exp mcalabre $
@


7.4.1.1
log
@WCSLIB 7.4 development branch.
@
text
@d23 1
a23 1
* $Id: pgsbox.f,v 7.4 2021/01/31 02:24:52 mcalabre Exp $
@


7.3
log
@WCSLIB 7.3
@
text
@d3 2
a4 2
* PGSBOX 7.3 - draw curvilinear coordinate axes for PGPLOT.
* Copyright (C) 1997-2020, Mark Calabretta
a20 2
* Direct correspondence concerning PGSBOX to mark@@calabretta.id.au
*
d23 1
a23 1
* $Id: pgsbox.f,v 7.2.1.1 2020/03/09 07:34:50 mcalabre Exp mcalabre $
@


7.3.1.1
log
@WCSLIB 7.3 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 7.3 2020/06/03 03:37:03 mcalabre Exp $
@


7.3.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
* Copyright (C) 1997-2021, Mark Calabretta
d25 1
a25 1
* $Id: pgsbox.f,v 7.3.1.1 2020/06/03 03:38:11 mcalabre Exp mcalabre $
@


7.3.1.3
log
@Removed my email address from the copyright notice.
@
text
@d21 2
d25 1
a25 1
* $Id: pgsbox.f,v 7.3.1.2 2021/01/19 14:12:19 mcalabre Exp mcalabre $
@


7.2
log
@WCSLIB 7.2
@
text
@d3 1
a3 1
* PGSBOX 7.2 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 7.1.1.1 2019/12/31 13:28:19 mcalabre Exp mcalabre $
@


7.2.1.1
log
@WCSLIB 7.2 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 7.2 2020/03/09 07:31:24 mcalabre Exp $
@


7.1
log
@WCSLIB 7.1
@
text
@d3 1
a3 1
* PGSBOX 7.1 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 6.4.1.2 2019/12/31 03:29:47 mcalabre Exp mcalabre $
@


7.1.1.1
log
@WCSLIB 7.1 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 7.1 2019/12/31 13:25:20 mcalabre Exp $
@


6.4
log
@WCSLIB 6.4
@
text
@d3 2
a4 2
* PGSBOX 6.4 - draw curvilinear coordinate axes for PGPLOT.
* Copyright (C) 1997-2019, Mark Calabretta
d25 1
a25 1
* $Id: pgsbox.f,v 6.3.1.1 2019/07/12 07:34:37 mcalabre Exp mcalabre $
@


6.4.1.1
log
@WCSLIB 6.4 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 6.4 2019/08/15 09:30:18 mcalabre Exp $
@


6.4.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
* Copyright (C) 1997-2020, Mark Calabretta
d25 1
a25 1
* $Id: pgsbox.f,v 6.4.1.1 2019/08/15 09:31:29 mcalabre Exp mcalabre $
@


6.3
log
@WCSLIB 6.3
@
text
@d3 1
a3 1
* PGSBOX 6.3 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 6.2.1.3 2019/07/09 13:47:10 mcalabre Exp mcalabre $
@


6.3.1.1
log
@WCSLIB 6.3 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 6.3 2019/07/12 07:33:40 mcalabre Exp $
@


6.2
log
@WCSLIB 6.2
@
text
@d3 2
a4 2
* PGSBOX 6.2 - draw curvilinear coordinate axes for PGPLOT.
* Copyright (C) 1997-2018, Mark Calabretta
d25 1
a25 1
* $Id: pgsbox.f,v 6.1.1.1 2018/10/19 08:36:15 mcalabre Exp mcalabre $
a1299 16
              IF (.NOT.INSIDE) THEN
*               For tick marks at the left or right edge.
                IF ((X2.EQ.BLC(1) .OR.  X2.EQ.TRC(1)) .AND.
     :               Y2.GT.BLC(2) .AND. Y2.LT.TRC(2)) THEN
                  INSIDE = X2.EQ.XR(NP)
                END IF
              END IF

              IF (.NOT.INSIDE) THEN
*               For tick marks at the bottom or top edge.
                IF ((Y2.EQ.BLC(2) .OR.  Y2.EQ.TRC(2)) .AND.
     :               X2.GT.BLC(1) .AND. X2.LT.TRC(1)) THEN
                  INSIDE = Y2.EQ.YR(NP)
                END IF
              END IF

d1305 16
@


6.2.1.1
log
@WCSLIB 6.2 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 6.2 2018/10/20 10:03:14 mcalabre Exp $
@


6.2.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
* Copyright (C) 1997-2019, Mark Calabretta
d25 1
a25 1
* $Id: pgsbox.f,v 6.2.1.1 2018/10/20 10:04:15 mcalabre Exp mcalabre $
@


6.2.1.3
log
@Fixed a longstanding out-of-bounds array access uncovered by
-fsanitize=address.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 6.2.1.2 2019/05/10 02:13:12 mcalabre Exp mcalabre $
d1300 16
a1320 16
                IF (.NOT.INSIDE) THEN
*                 For tick marks at the left or right edge.
                  IF ((X2.EQ.BLC(1) .OR.  X2.EQ.TRC(1)) .AND.
     :                 Y2.GT.BLC(2) .AND. Y2.LT.TRC(2)) THEN
                    INSIDE = X2.EQ.XR(NP)
                  END IF
                END IF

                IF (.NOT.INSIDE) THEN
*                 For tick marks at the bottom or top edge.
                  IF ((Y2.EQ.BLC(2) .OR.  Y2.EQ.TRC(2)) .AND.
     :                 X2.GT.BLC(1) .AND. X2.LT.TRC(1)) THEN
                    INSIDE = Y2.EQ.YR(NP)
                  END IF
                END IF

@


6.1
log
@WCSLIB 6.1
@
text
@d3 1
a3 1
* PGSBOX 6.1 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 5.20.1.1 2018/10/05 05:33:33 mcalabre Exp mcalabre $
@


6.1.1.1
log
@WCSLIB 6.1 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 6.1 2018/10/19 08:35:17 mcalabre Exp $
@


5.20
log
@WCSLIB 5.20
@
text
@d3 1
a3 1
* PGSBOX 5.20 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 5.19.1.1 2018/07/26 15:41:42 mcalabre Exp mcalabre $
@


5.20.1.1
log
@WCSLIB 5.20 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.20 2018/10/05 05:32:42 mcalabre Exp $
@


5.19
log
@WCSLIB 5.19
@
text
@d3 1
a3 1
* PGSBOX 5.19 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 5.18.1.1 2018/01/10 08:33:04 mcalabre Exp mcalabre $
@


5.19.1.1
log
@WCSLIB 5.19 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.19 2018/07/26 15:37:05 mcalabre Exp $
@


5.18
log
@WCSLIB 5.18
@
text
@d3 1
a3 1
* PGSBOX 5.18 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 5.17.1.2 2018/01/10 08:27:33 mcalabre Exp mcalabre $
@


5.18.1.1
log
@WCSLIB 5.18 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.18 2018/01/10 08:32:14 mcalabre Exp $
@


5.17
log
@WCSLIB 5.17
@
text
@d3 2
a4 2
* PGSBOX 5.17 - draw curvilinear coordinate axes for PGPLOT.
* Copyright (C) 1997-2017, Mark Calabretta
d25 1
a25 1
* $Id: pgsbox.f,v 5.16.1.1 2017/01/15 04:29:04 mcalabre Exp mcalabre $
@


5.17.1.1
log
@WCSLIB 5.17 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.17 2017/09/18 08:44:25 mcalabre Exp $
@


5.17.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
* Copyright (C) 1997-2018, Mark Calabretta
d25 1
a25 1
* $Id: pgsbox.f,v 5.17.1.1 2017/09/18 08:46:01 mcalabre Exp mcalabre $
@


5.16
log
@WCSLIB 5.16
@
text
@d3 1
a3 1
* PGSBOX 5.16 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 5.15.1.2 2017/01/15 04:08:24 mcalabre Exp mcalabre $
@


5.16.1.1
log
@WCSLIB 5.16 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.16 2017/01/15 04:25:03 mcalabre Exp $
@


5.15
log
@WCSLIB 5.15
@
text
@d3 2
a4 2
* PGSBOX 5.15 - draw curvilinear coordinate axes for PGPLOT.
* Copyright (C) 1997-2016, Mark Calabretta
d25 1
a25 1
* $Id: pgsbox.f,v 5.14.1.1 2016/02/07 10:52:48 mcalabre Exp mcalabre $
@


5.15.1.1
log
@WCSLIB 5.15 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.15 2016/04/05 12:55:13 mcalabre Exp $
@


5.15.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
* Copyright (C) 1997-2017, Mark Calabretta
d25 1
a25 1
* $Id: pgsbox.f,v 5.15.1.1 2016/04/05 12:58:39 mcalabre Exp mcalabre $
@


5.14
log
@WCSLIB 5.14
@
text
@d3 1
a3 1
* PGSBOX 5.14 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 5.13.1.1 2016/01/26 08:54:36 mcalabre Exp mcalabre $
@


5.14.1.1
log
@WCSLIB 5.14 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.14 2016/02/07 10:49:33 mcalabre Exp $
@


5.13
log
@WCSLIB 5.13
@
text
@d3 1
a3 1
* PGSBOX 5.13 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 5.12.1.2 2016/01/25 05:22:41 mcalabre Exp mcalabre $
@


5.13.1.1
log
@WCSLIB 5.13 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.13 2016/01/26 08:51:16 mcalabre Exp $
@


5.12
log
@WCSLIB 5.12
@
text
@d3 2
a4 2
* PGSBOX 5.12 - draw curvilinear coordinate axes for PGPLOT.
* Copyright (C) 1997-2015, Mark Calabretta
d25 1
a25 1
* $Id: pgsbox.f,v 5.11.1.1 2015/10/18 09:16:31 mcalabre Exp mcalabre $
@


5.12.1.1
log
@WCSLIB 5.12 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.12 2015/11/15 02:13:03 mcalabre Exp $
@


5.12.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
* Copyright (C) 1997-2016, Mark Calabretta
d25 1
a25 1
* $Id: pgsbox.f,v 5.12.1.1 2015/11/15 02:16:18 mcalabre Exp mcalabre $
@


5.11
log
@WCSLIB 5.11
@
text
@d3 1
a3 1
* PGSBOX 5.11 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 5.10.1.1 2015/10/09 08:22:40 mcalabre Exp mcalabre $
@


5.11.1.1
log
@WCSLIB 5.11 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.11 2015/10/18 09:13:08 mcalabre Exp $
@


5.10
log
@WCSLIB 5.10
@
text
@d3 1
a3 1
* PGSBOX 5.10 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 5.9.1.1 2015/07/21 09:28:12 mcalabre Exp mcalabre $
@


5.10.1.1
log
@WCSLIB 5.10 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.10 2015/10/09 08:19:18 mcalabre Exp $
@


5.9
log
@WCSLIB 5.9
@
text
@d3 1
a3 1
* PGSBOX 5.9 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 5.8.1.1 2015/07/08 11:07:22 mcalabre Exp mcalabre $
@


5.9.1.1
log
@WCSLIB 5.9 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.9 2015/07/21 09:20:04 mcalabre Exp $
@


5.8
log
@WCSLIB 5.8
@
text
@d3 1
a3 1
* PGSBOX 5.8 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 5.7.1.1 2015/06/29 02:47:27 mcalabre Exp mcalabre $
@


5.8.1.1
log
@WCSLIB 5.8 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.8 2015/07/08 11:04:03 mcalabre Exp $
@


5.7
log
@WCSLIB 5.7
@
text
@d3 1
a3 1
* PGSBOX 5.7 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 5.6.1.1 2015/06/14 07:14:48 mcalabre Exp mcalabre $
@


5.7.1.1
log
@WCSLIB 5.7 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.7 2015/06/29 02:44:19 mcalabre Exp $
@


5.6
log
@WCSLIB 5.6
@
text
@d3 1
a3 1
* PGSBOX 5.6 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 5.5.1.1 2015/05/05 13:21:04 mcalabre Exp mcalabre $
@


5.6.1.1
log
@WCSLIB 5.6 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.6 2015/06/14 07:11:26 mcalabre Exp $
@


5.5
log
@WCSLIB 5.5
@
text
@d3 1
a3 1
* PGSBOX 5.5 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 5.4.1.1 2015/04/21 14:44:32 mcalabre Exp mcalabre $
@


5.5.1.1
log
@WCSLIB 5.5 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.5 2015/05/05 13:16:34 mcalabre Exp $
@


5.4
log
@WCSLIB 5.4
@
text
@d3 1
a3 1
* PGSBOX 5.4 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 5.3.1.1 2015/04/21 02:54:06 mcalabre Exp mcalabre $
@


5.4.1.1
log
@WCSLIB 5.4 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.4 2015/04/21 14:41:08 mcalabre Exp $
@


5.3
log
@WCSLIB 5.3
@
text
@d3 1
a3 1
* PGSBOX 5.3 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 5.2.1.1 2015/04/15 12:39:18 mcalabre Exp mcalabre $
@


5.3.1.1
log
@WCSLIB 5.3 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.3 2015/04/21 02:50:54 mcalabre Exp $
@


5.2
log
@WCSLIB 5.2
@
text
@d3 1
a3 1
* PGSBOX 5.2 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 5.1.1.1 2015/04/07 11:01:13 mcalabre Exp mcalabre $
@


5.2.1.1
log
@WCSLIB 5.2 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.2 2015/04/15 12:35:10 mcalabre Exp $
@


5.1
log
@WCSLIB 5.1
@
text
@d3 1
a3 1
* PGSBOX 5.1 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 5.0.1.1 2015/04/05 12:28:04 mcalabre Exp mcalabre $
@


5.1.1.1
log
@WCSLIB 5.1 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.1 2015/04/07 10:56:39 mcalabre Exp $
@


5.0
log
@WCSLIB 5.0
@
text
@d3 1
a3 1
* PGSBOX 5.0 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 4.25.1.3 2015/03/06 11:56:51 mcalabre Exp mcalabre $
@


5.0.1.1
log
@WCSLIB 5.0 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 5.0 2015/04/05 12:25:03 mcalabre Exp $
@


4.25
log
@WCSLIB 4.25
@
text
@d3 2
a4 2
* PGSBOX 4.25 - draw curvilinear coordinate axes for PGPLOT.
* Copyright (C) 1997-2014, Mark Calabretta
d25 1
a25 1
* $Id: pgsbox.f,v 4.24.1.1 2014/09/18 15:28:12 mcalabre Exp mcalabre $
d1961 1
a1961 1
          L = NINT(100*MOD(CACHE(1,J),1.0)) - 10
@


4.25.1.1
log
@WCSLIB 4.25 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 4.25 2014/12/14 14:29:38 mcalabre Exp $
@


4.25.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
* Copyright (C) 1997-2015, Mark Calabretta
d25 1
a25 1
* $Id: pgsbox.f,v 4.25.1.1 2014/12/14 14:32:48 mcalabre Exp mcalabre $
@


4.25.1.3
log
@In PGCRLB, fixed an incorrect used of the MOD intrinsic.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 4.25.1.2 2015/01/06 01:03:14 mcalabre Exp mcalabre $
d1961 1
a1961 1
          L = NINT(100*MOD(CACHE(1,J),1D0)) - 10
@


4.24
log
@WCSLIB 4.24
@
text
@d3 1
a3 1
* PGSBOX 4.24 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 4.23.1.1 2014/05/13 05:53:52 mcalabre Exp mcalabre $
@


4.24.1.1
log
@WCSLIB 4.24 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 4.24 2014/09/18 15:25:02 mcalabre Exp $
@


4.23
log
@WCSLIB 4.23
@
text
@d3 1
a3 1
* PGSBOX 4.23 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 4.22.1.1 2014/04/12 15:06:34 mcalabre Exp mcalabre $
@


4.23.1.1
log
@WCSLIB 4.23 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 4.23 2014/05/13 05:50:53 mcalabre Exp $
@


4.22
log
@WCSLIB 4.22
@
text
@d3 1
a3 1
* PGSBOX 4.22 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 4.21.1.1 2014/03/24 05:15:31 mcalabre Exp mcalabre $
@


4.22.1.1
log
@WCSLIB 4.22 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 4.22 2014/04/12 15:03:54 mcalabre Exp $
@


4.21
log
@WCSLIB 4.21
@
text
@d3 1
a3 1
* PGSBOX 4.21 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 4.20.1.2 2014/03/21 06:45:26 mcalabre Exp mcalabre $
@


4.21.1.1
log
@WCSLIB 4.21 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 4.21 2014/03/24 05:12:29 mcalabre Exp $
@


4.20
log
@WCSLIB 4.20
@
text
@d3 2
a4 2
* PGSBOX 4.20 - draw curvilinear coordinate axes for PGPLOT.
* Copyright (C) 1997-2013, Mark Calabretta
d25 1
a25 1
* $Id: pgsbox.f,v 4.19.1.2 2013/12/10 23:13:17 mcalabre Exp mcalabre $
@


4.20.1.1
log
@WCSLIB 4.20 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 4.20 2013/12/18 05:42:51 mcalabre Exp $
@


4.20.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
* Copyright (C) 1997-2014, Mark Calabretta
d25 1
a25 1
* $Id: pgsbox.f,v 4.20.1.1 2013/12/18 05:46:57 mcalabre Exp mcalabre $
@


4.19
log
@WCSLIB 4.19
@
text
@d3 1
a3 1
* PGSBOX 4.19 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 4.18.1.1 2013/07/13 10:02:40 mcalabre Exp mcalabre $
d465 2
a466 2
      REAL      BLC(2), BLC_(2), S, TRC(2), TRC_(2), WXY(4), X1, X2,
     :          XPOINT, XR(BUFSIZ), XSCL, XSPAN, XTOL, XVP1, XVP2,
d482 2
a483 2
      DOUBLE PRECISION TOL
      PARAMETER (TOL = 1D-8)
d1114 1
a1114 1
        NSTEP(J) = ANINT(DW(J)/SW(J))
d1151 1
d1386 2
a1387 2
                        XR(NP) = XR(NP-1) + (X2-X1)*TIKLEN/S
                        YR(NP) = YR(NP-1) + (Y2-Y1)*TIKLEN/S
d1480 2
a1481 2
                        XR(NP-1) = X1 + (X2-X1)*TIKLEN/S
                        YR(NP-1) = Y1 + (Y2-Y1)*TIKLEN/S
d1865 1
a1865 1
            OMAG(IWRLD) = OMAG(IWRLD) + LOG10(ABS(CACHE(4,J)))
d2074 1
a2074 1
          X = CACHE(2,J)
d2080 1
a2080 1
          Y = CACHE(2,J) - YCH/2.0
d2084 1
a2084 1
          X = CACHE(2,J)
d2090 1
a2090 1
          Y = CACHE(2,J) - YCH/2.0
@


4.19.1.1
log
@WCSLIB 4.19 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 4.19 2013/09/29 14:17:53 mcalabre Exp $
@


4.19.1.2
log
@Fixed a few nuisance warnings from gfortran 4.7.2 relating to implicit
type conversions.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 4.19.1.1 2013/09/29 14:20:41 mcalabre Exp mcalabre $
d465 2
a466 2
      REAL      BLC(2), BLC_(2), RTIKLN, S, TRC(2), TRC_(2), WXY(4), X1,
     :          X2, XPOINT, XR(BUFSIZ), XSCL, XSPAN, XTOL, XVP1, XVP2,
d482 2
a483 2
      REAL    TOL
      PARAMETER (TOL = 1E-8)
d1114 1
a1114 1
        NSTEP(J) = NINT(DW(J)/SW(J))
a1150 1
      RTIKLN = REAL(TIKLEN)
d1385 2
a1386 2
                        XR(NP) = XR(NP-1) + (X2-X1)*RTIKLN/S
                        YR(NP) = YR(NP-1) + (Y2-Y1)*RTIKLN/S
d1479 2
a1480 2
                        XR(NP-1) = X1 + (X2-X1)*RTIKLN/S
                        YR(NP-1) = Y1 + (Y2-Y1)*RTIKLN/S
d1864 1
a1864 1
            OMAG(IWRLD) = OMAG(IWRLD) + LOG10(ABS(REAL(CACHE(4,J))))
d2073 1
a2073 1
          X = REAL(CACHE(2,J))
d2079 1
a2079 1
          Y = REAL(CACHE(2,J)) - YCH/2.0
d2083 1
a2083 1
          X = REAL(CACHE(2,J))
d2089 1
a2089 1
          Y = REAL(CACHE(2,J)) - YCH/2.0
@


4.18
log
@WCSLIB 4.18
@
text
@d3 1
a3 1
* PGSBOX 4.18 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 4.17.1.1 2013/01/29 05:32:33 cal103 Exp cal103 $
@


4.18.1.1
log
@WCSLIB 4.18 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 4.18 2013/07/13 10:00:06 mcalabre Exp $
@


4.17
log
@WCSLIB 4.17
@
text
@d3 1
a3 1
* PGSBOX 4.17 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 4.16.1.2 2013/01/29 05:11:32 cal103 Exp cal103 $
@


4.17.1.1
log
@WCSLIB 4.17 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 4.17 2013/01/29 05:29:22 cal103 Exp $
@


4.16
log
@WCSLIB 4.16
@
text
@d3 2
a4 2
* PGSBOX 4.16 - draw curvilinear coordinate axes for PGPLOT.
* Copyright (C) 1997-2012, Mark Calabretta
d25 1
a25 1
* $Id: pgsbox.f,v 4.15.1.1 2012/09/26 14:27:53 cal103 Exp cal103 $
@


4.16.1.1
log
@WCSLIB 4.16 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 4.16 2012/11/07 04:42:45 cal103 Exp $
@


4.16.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
* Copyright (C) 1997-2013, Mark Calabretta
d25 1
a25 1
* $Id: pgsbox.f,v 4.16.1.1 2012/11/07 04:45:58 cal103 Exp cal103 $
@


4.15
log
@WCSLIB 4.15
@
text
@d3 1
a3 1
* PGSBOX 4.15 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 4.14.1.2 2012/07/31 10:48:02 cal103 Exp cal103 $
@


4.15.1.1
log
@WCSLIB 4.15 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 4.15 2012/09/26 14:26:06 cal103 Exp $
@


4.14
log
@WCSLIB 4.14
@
text
@d3 1
a3 1
* PGSBOX 4.14 - draw curvilinear coordinate axes for PGPLOT.
d25 1
a25 1
* $Id: pgsbox.f,v 4.13.1.2 2012/07/13 03:43:52 cal103 Exp cal103 $
d447 1
a447 1
*      example, NLDPRM(2,NLD).  (The FORTRAN standard requires that
a663 1
                IYPREV = IY
a682 1
                IYPREV = IY
d685 2
d2238 1
a2238 1
*           FORTRAN is really abysmal sometimes.
d2610 1
a2610 1
* This FORTRAN wrapper on PGSBOX exists solely to define fixed-length
d2639 1
a2639 1
* This FORTRAN wrapper on PGLBOX exists solely to define fixed-length
@


4.14.1.1
log
@WCSLIB 4.14 development branch.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 4.14 2012/07/13 10:02:47 cal103 Exp $
@


4.14.1.2
log
@Bug fix in PGSBOX for handling cycles in anglular coordinates, reported
by Thomas Robitaille.
@
text
@d25 1
a25 1
* $Id: pgsbox.f,v 4.14.1.1 2012/07/13 10:05:05 cal103 Exp cal103 $
d447 1
a447 1
*      example, NLDPRM(2,NLD).  (The Fortran standard requires that
d664 1
d684 1
a686 2
              IYPREV = IY

d2238 1
a2238 1
*           Fortran is really abysmal sometimes.
d2610 1
a2610 1
* This Fortran wrapper on PGSBOX exists solely to define fixed-length
d2639 1
a2639 1
* This Fortran wrapper on PGLBOX exists solely to define fixed-length
@


4.13
log
@WCSLIB 4.13
@
text
@d3 1
a3 1
* PGSBOX 4.13 - draw curvilinear coordinate axes for PGPLOT.
d21 5
a25 11
* Correspondence concerning PGSBOX may be directed to:
*   Internet email: mcalabre@@atnf.csiro.au
*   Postal address: Dr. Mark Calabretta
*                   Australia Telescope National Facility, CSIRO
*                   PO Box 76
*                   Epping NSW 1710
*                   AUSTRALIA
*
* Author: Mark Calabretta, Australia Telescope National Facility
* http://www.atnf.csiro.au/~mcalabre/index.html
* $Id: pgsbox.f,v 4.12.1.1 2012/02/29 07:59:11 cal103 Exp cal103 $
d1562 1
a1562 1
* Author: Mark Calabretta, Australia Telescope National Facility
d2570 1
a2570 1
*   Author: Mark Calabretta, Australia Telescope National Facility
d2613 1
a2613 1
* Author: Mark Calabretta, Australia Telescope National Facility
d2642 1
a2642 1
* Author: Mark Calabretta, Australia Telescope National Facility
@


4.13.1.1
log
@WCSLIB 4.13 development branch.
@
text
@d31 1
a31 1
* $Id: pgsbox.f,v 4.13 2012/03/14 07:39:31 cal103 Exp $
@


4.13.1.2
log
@Changed contact details.
@
text
@d21 11
a31 5
* Direct correspondence concerning PGSBOX to mark@@calabretta.id.au
*
* Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
* http://www.atnf.csiro.au/people/Mark.Calabretta
* $Id: pgsbox.f,v 4.13.1.1 2012/03/14 07:40:39 cal103 Exp cal103 $
d1568 1
a1568 1
* Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
d2576 1
a2576 1
* Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
d2619 1
a2619 1
* Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
d2648 1
a2648 1
* Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
@


4.12
log
@WCSLIB 4.12
@
text
@d3 1
a3 1
* PGSBOX 4.12 - draw curvilinear coordinate axes for PGPLOT.
d31 1
a31 1
* $Id: pgsbox.f,v 4.11.1.1 2012/02/20 23:31:14 cal103 Exp cal103 $
@


4.12.1.1
log
@WCSLIB 4.12 development branch.
@
text
@d31 1
a31 1
* $Id: pgsbox.f,v 4.12 2012/02/29 07:57:57 cal103 Exp $
@


4.11
log
@WCSLIB 4.11
@
text
@d3 1
a3 1
* PGSBOX 4.11 - draw curvilinear coordinate axes for PGPLOT.
d31 1
a31 1
* $Id: pgsbox.f,v 4.10.1.1 2012/02/05 23:42:47 cal103 Exp cal103 $
@


4.11.1.1
log
@WCSLIB 4.11 development branch.
@
text
@d31 1
a31 1
* $Id: pgsbox.f,v 4.11 2012/02/20 23:30:03 cal103 Exp $
@


4.10
log
@WCSLIB 4.10
@
text
@d3 1
a3 1
* PGSBOX 4.10 - draw curvilinear coordinate axes for PGPLOT.
d31 1
a31 1
* $Id: pgsbox.f,v 4.9.1.1 2012/01/24 05:41:46 cal103 Exp cal103 $
@


4.10.1.1
log
@WCSLIB 4.10 development branch.
@
text
@d31 1
a31 1
* $Id: pgsbox.f,v 4.10 2012/02/05 23:41:45 cal103 Exp $
@


4.9
log
@WCSLIB 4.9
@
text
@d3 1
a3 1
* PGSBOX 4.9 - draw curvilinear coordinate axes for PGPLOT.
d31 1
a31 1
* $Id: pgsbox.f,v 4.8.1.2 2012/01/24 05:24:50 cal103 Exp cal103 $
@


4.9.1.1
log
@WCSLIB 4.9 development branch.
@
text
@d31 1
a31 1
* $Id: pgsbox.f,v 4.9 2012/01/24 05:40:30 cal103 Exp $
@


4.8
log
@WCSLIB 4.8
@
text
@d3 2
a4 2
* PGSBOX 4.8 - draw curvilinear coordinate axes for PGPLOT.
* Copyright (C) 1997-2011, Mark Calabretta
d31 1
a31 1
* $Id: pgsbox.f,v 4.7.1.1 2011/02/07 07:04:23 cal103 Exp cal103 $
@


4.8.1.1
log
@WCSLIB 4.8 development branch.
@
text
@d31 1
a31 1
* $Id: pgsbox.f,v 4.8 2011/08/15 08:05:55 cal103 Exp $
@


4.8.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
* Copyright (C) 1997-2012, Mark Calabretta
d31 1
a31 1
* $Id: pgsbox.f,v 4.8.1.1 2011/08/15 08:07:07 cal103 Exp cal103 $
@


4.7
log
@WCSLIB 4.7
@
text
@d3 1
a3 1
* PGSBOX 4.7 - draw curvilinear coordinate axes for PGPLOT.
d31 1
a31 1
* $Id: pgsbox.f,v 4.6.1.3 2011/01/25 00:50:51 cal103 Exp cal103 $
@


4.7.1.1
log
@WCSLIB 4.7 development branch.
@
text
@d31 1
a31 1
* $Id: pgsbox.f,v 4.7 2011/02/07 07:03:43 cal103 Exp $
@


4.6
log
@WCSLIB 4.6
@
text
@d3 2
a4 2
* PGSBOX 4.6 - draw curvilinear coordinate axes for PGPLOT.
* Copyright (C) 1997-2010, Mark Calabretta
d31 1
a31 1
* $Id: pgsbox.f,v 4.5.1.1 2010/07/16 07:05:33 cal103 Exp cal103 $
d292 1
a292 1
*      specified by the caller (e.g. via NG1 = 0, GRID1(0) != 0) or as
d590 2
a592 1
*  SW(1:2)    ...increment in world coordinate between steps.
d801 2
a802 2
      IF (NG1.EQ.0) G0(1) = GRID1(0)
      IF (NG2.EQ.0) G0(2) = GRID2(0)
d811 7
a817 1
        IF (NG(J).EQ.0 .AND. G0(J).NE.0D0) THEN
d819 2
a820 1
        ELSE IF (DOEQ .AND. NG(K).EQ.0 .AND. G0(K).NE.0D0) THEN
d823 4
d1197 6
a1202 2
            WORLD(1) = GRID1(IWJ)
            WORLD(2) = GRID2(IWJ)
d1513 2
a1514 2
90          CONTINUE
100       CONTINUE
d1517 1
a1517 1
110     CONTINUE
@


4.6.1.1
log
@WCSLIB 4.6 development branch.
@
text
@d31 1
a31 1
* $Id: pgsbox.f,v 4.6 2010/11/16 06:15:32 cal103 Exp $
@


4.6.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
* Copyright (C) 1997-2011, Mark Calabretta
d31 1
a31 1
* $Id: pgsbox.f,v 4.6.1.1 2010/11/16 06:16:20 cal103 Exp cal103 $
@


4.6.1.3
log
@Bug fix for the case where NG1 == 0 and GRID1(0) < 0, and likewise for
NG2 and GRID2.  Avoid potentially (but harmlessly) overindexing the
GRID1 or GRID2 arrays when setting the world coordinate of each grid
line.
@
text
@d31 1
a31 1
* $Id: pgsbox.f,v 4.6.1.2 2011/01/14 06:35:20 cal103 Exp cal103 $
d292 1
a292 1
*      specified by the caller (e.g. via NG1 = 0, GRID1(0) > 0) or as
a589 2
*  DW(1:2)    ...span from WMIN to WMAX.
*  SW(1:2)    ...increment in world coordinate between plotting steps.
d591 1
d800 2
a801 2
      IF (NG(1).EQ.0) G0(1) = GRID1(0)
      IF (NG(2).EQ.0) G0(2) = GRID2(0)
d810 1
a810 7
        IF (NG(J).EQ.0 .AND. G0(J).LT.0D0) THEN
*         Defeat grid lines and tick marks.
          GCODE(J) = 0
        END IF

        IF (NG(J).EQ.0 .AND. G0(J).GT.0D0) THEN
*         User-specified, directly.
d812 1
a812 2
        ELSE IF (DOEQ .AND. NG(K).EQ.0 .AND. G0(K).GT.0D0) THEN
*         User-specified, indirectly.
a814 4
*         Left to us to choose.  Even if grid lines are not drawn for
*         coordinate J, i.e. NG(J) = 0 and G0(J) < 0, GSTEP(J) is still
*         needed because it is used to deduce SW(J) which is used for
*         drawing grid lines for the other coordinate.
d1185 2
a1186 6
            IF (J.EQ.1) THEN
              WORLD(1) = GRID1(IWJ)
            ELSE
              WORLD(2) = GRID2(IWJ)
            END IF

d1497 2
a1498 2
 90         CONTINUE
 100      CONTINUE
d1501 1
a1501 1
 110    CONTINUE
@


4.5
log
@WCSLIB 4.5
@
text
@d3 1
a3 1
* PGSBOX 4.5 - draw curvilinear coordinate axes for PGPLOT.
d31 1
a31 1
* $Id: pgsbox.f,v 4.4.1.2 2010/01/19 03:45:24 cal103 Exp cal103 $
@


4.5.1.1
log
@WCSLIB 4.5 development branch.
@
text
@d31 1
a31 1
* $Id: pgsbox.f,v 4.5 2010/07/16 07:01:27 cal103 Exp $
@


4.4
log
@WCSLIB 4.4
@
text
@d3 2
a4 2
* PGSBOX 4.4 - draw curvilinear coordinate axes for PGPLOT.
* Copyright (C) 1997-2009, Mark Calabretta
d31 1
a31 1
* $Id: pgsbox.f,v 4.3.1.5 2009/08/04 08:12:29 cal103 Exp cal103 $
@


4.4.1.1
log
@WCSLIB 4.4 development branch.
@
text
@d31 1
a31 1
* $Id: pgsbox.f,v 4.4 2009/08/06 07:54:40 cal103 Exp $
@


4.4.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
* Copyright (C) 1997-2010, Mark Calabretta
d31 1
a31 1
* $Id: pgsbox.f,v 4.4.1.1 2009/08/10 08:55:45 cal103 Exp cal103 $
@


4.3
log
@PGSBOX 4.3
@
text
@d3 2
a4 2
*   PGSBOX 4.3 - an implementation of the FITS WCS standard.
*   Copyright (C) 1997-2007, Mark Calabretta
d6 1
a6 1
*   This file is part of PGSBOX.
d8 24
a31 24
*   PGSBOX is free software: you can redistribute it and/or modify
*   it under the terms of the GNU Lesser General Public License as
*   published by the Free Software Foundation, either version 3 of
*   the License, or (at your option) any later version.
*
*   PGSBOX is distributed in the hope that it will be useful, but
*   WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*   GNU Lesser General Public License for more details.
*
*   You should have received a copy of the GNU Lesser General Public
*   License along with PGSBOX.  If not, see http://www.gnu.org/licenses.
*
*   Correspondence concerning PGSBOX may be directed to:
*      Internet email: mcalabre@@atnf.csiro.au
*      Postal address: Dr. Mark Calabretta
*                      Australia Telescope National Facility, CSIRO
*                      PO Box 76
*                      Epping NSW 1710
*                      AUSTRALIA
*
*   Author: Mark Calabretta, Australia Telescope National Facility
*   http://www.atnf.csiro.au/~mcalabre/index.html
*   $Id: pgsbox.f,v 4.2.1.4 2007/12/03 05:41:29 cal103 Exp cal103 $
d34 313
a346 317
*   PGSBOX draws and labels a curvilinear coordinate grid.  The caller
*   must provide a separate external function, NLFUNC, to define the
*   non-linear coordinate transformation.
*
*   PGLBOX, a simplified ENTRY point to PGSBOX, has been provided for
*   drawing simple linear axes without the need to specify NLFUNC.
*   PGLBOX allows simplified access to formatting control for labelling
*   world coordinate axes that is not provided by the standard PGPLOT
*   routines, PGBOX or PGTBOX.  PGLBOX uses the world coordinate range
*   set by a prior call to PGSWIN and omits the following arguments:
*
*      BLC, TRC, NLFUNC, NLC, NLI, NLD, NLCPRM, NLIPRM, NLDPRM
*
*   The remaining arguments are specified in the same order as PGSBOX.
*
*   Given:
*      BLC      R(2)     Cartesian coordinates of the bottom left-hand
*      TRC      R(2)     corner and top right-hand corner of the frame.
*                        Any convenient Cartesian system may be used in
*                        conjunction with the non-linear transformation
*                        function, NLFUNC, described below.
*
*                        For example, FITS images have pixel coordinate
*                        (1,1) at the centre of the pixel in the bottom
*                        left-hand corner.  Thus it would be
*                        appropriate to set BLC to (0.5,0.5) and TRC to
*                        (NAXIS1+0.5, NAXIS2+0.5).
*
*      IDENTS   C(3)*(*) Identification strings:
*                           1: Name of the first world coordinate
*                              element used for axis labelling.
*                           2: Name of the second world coordinate.
*                           3: Title, written at top.
*
*      OPT      C(2)*(*) Formatting control for the world coordinates,
*                        used for axis labelling (see notes 1 and 2):
*                           ' ': plain numeric
*                           'A': angle in degrees expressed in
*                                decimal notation normalized in the
*                                range [0,360).
*                           'B': as 'A' but normalized in the range
*                                (-180,180].
*                           'C': as 'A' but unnormalized.
*                           'D': angle in degrees expressed in
*                                sexagesimal notation, DD^MM'SS".S,
*                                normalized in the range [0,360).
*                           'E': as 'D' but normalized in the range
*                                (-180,180].
*                           'F': as 'D' but unnormalized.
*                           'G': angle in degrees expressed in
*                                hms notation, HHhMMmSSs.S, normalized
*                                in the range [0,24) hours.
*                           'H': as 'G' but normalized in the range
*                                (-12,12] hours.
*                           'I': as 'G' but unnormalized.
*                           'L': logarithmic (see note 2)
*                           'T': time in hours expressed as HH:MM:SS.S
*                           'Y': Modified Julian Date to be expressed as
*                                a Gregorian calendar date, YYYY/MM/DD.
*                                (MJD = JD - 2400000.5.)
*
*                        For the angular types, NLFUNC is assumed to
*                        return the angle in degrees whereupon it will
*                        be formatted for display in the specified way.
*                        For example, an angle of -417.2958 degrees
*                        (returned by NLFUNC):
*
*                            'A':  302^.7042
*                            'B':  -57^.2958
*                            'C': -417^.2958
*                            'D':  302^42'15"
*                            'E':  -57^17'45"
*                            'F': -417^17'45"
*                            'H':   20h10m49s
*                            'I':   -3h49m11s
*                            'J':  -27h49m11s
*
*                        These are properly superscripted.
*
*      LABCTL   I        Decimal encoded grid labelling control:
*                             -1: Accumulate information on grid labels
*                                 (see note 3) but do not write them.
*                              0: Let PGSBOX decide what edges to label.
*                              1: Label bottom of frame with the first
*                                 world coordinate.
*                              2: Label bottom of frame with the second
*                                 world coordinate.
*                             10: ... left side of frame.
*                             20: ... left side of frame.
*                            100: ... top of frame.
*                            200: ... top of frame.
*                           1000: ... right side of frame.
*                           2000: ... right side of frame.
*                          10000: Write labels from information
*                                 accumulated in previous calls without
*                                 drawing grid lines or tick marks.
*
*                        LABCTL = 0 usually gets what you want.
*                        LABCTL = 3333 labels all sides with both world
*                        coordinates.
*
*      LABDEN   I        Decimal encoded labelling density control for
*                        use where PGSBOX is called upon to determine a
*                        suitable grid spacing (e.g. via NG1 = 0,
*                        GRID1(0) = 0).  LABDEN = 100*D2 + D1 where
*                        D1, and D2 are the approximate number of grid
*                        lines for the first and second world
*                        coordinate.  LABDEN = 0 is effectively the same
*                        as LABDEN = 808.
*
*      CI       I(7)     Table of predefined colours established by
*                        calls to PGSCR.  This is used to control the
*                        colour used for different parts of the plot.
*                        CI table entries are used as follows:
*
*                                                 world
*                                               coordinate
*                        Index      usage        element
*                        -----  --------------  ----------
*                          1      grid lines        1
*                          2      grid lines        2
*                          3    numeric labels      1
*                          4    numeric labels      2
*                          5    axis annotation     1
*                          6    axis annotation     2
*                          7        title           -
*
*                        For example, CI(3) is used for numeric labels
*                        for the first world coordinate.
*
*                        Colour selection is disabled for component J
*                        if CI(J) < 0.
*
*      GCODE(2) I        Code for the type of grid to draw for each
*                        world coordinate:
*                           0: No grid or tick marks.
*                           1: Tick marks (on all edges).
*                           2: Full coordinate grid.
*
*                        Tick marks can be restricted to particular
*                        edges of the frame; a negative GCODE is
*                        interpreted as a decimal encoded control
*                        variable:
*                             -1: bottom
*                            -10: left
*                           -100: top
*                          -1000: right
*
*                        The digit scales the basic tick length.  For
*                        example, GCODE(1) = -102 restricts tick marks
*                        for the first world coordinate to the bottom
*                        and top edges of the frame.  Those on the
*                        bottom will be twice the length specified by
*                        TIKLEN.
*
*      TIKLEN   D        Tick length, in mm.  Negative values produce
*                        outside tick marks.
*
*      NG1      I        Upper array index for GRID1.
*
*      GRID1    D(0:NG1) Grid values in WORLD(1) in the same units as
*                        returned by NLFUNC.
*
*                        If NG1 is zero, then
*                           a) if GRID1(0) is greater than zero it
*                              defines a uniform grid spacing.
*                           b) if GRID1(0) is zero a suitable spacing
*                              will be determined (see LABDEN).
*                           c) if GRID1(0) is less than zero then no
*                              grid lines will be drawn.
*
*                        If NG1 is greater than zero, then GRID1(0) is
*                        ignored.
*
*      NG2      I        Upper array index for GRID2.
*
*      GRID2    D(0:NG2) Grid values in WORLD(2) in the same units as
*                        returned by NLFUNC, interpreted the same way
*                        as GRID1.
*
*      DOEQ     L        If NG1 = NG2 = 0, and GRID1(0) = 0D0 and/or
*                        GRID2(0) = 0D0, then choose the same grid
*                        spacing for each world coordinate.
*
*      NLFUNC   Ext      Non-linear coordinate function, see below.
*
*      NLC      I        Number of elements in NLCPRM (must be >0).
*
*      NLI      I        Number of elements in NLIPRM (must be >0).
*
*      NLD      I        Number of elements in NLDPRM (must be >0).
*
*   Given and/or returned:
*      NLCPRM   C(NLC)*1 Character coefficients for NLFUNC.
*
*      NLIPRM   I(NLI)   Integer coefficients for NLFUNC.
*
*      NLDPRM   D(NLD)   Double precision coefficients for NLFUNC.
*
*      NC       I        Upper array index for CACHE (see note 3).
*
*      IC       I        Current number of entries in the CACHE table.
*                        Should be set to -1 on the first call to
*                        PGSBOX (see note 3).
*
*      CACHE    D(4,0:NC)
*                        Table of points where the tick marks or grid
*                        lines cross the frame (see note 3).
*                           1: Frame segment
*                              1: bottom
*                              2: left
*                              3: top
*                              4: right
*                           2: X or Y-Cartesian coordinate.
*                           3: World coordinate element (1 or 2).
*                           4: Value.
*
*                        CACHE(,0) is used to cache the extrema of the
*                        coordinate values between calls.  CACHE(1,NC-1)
*                        is also used to store related information.
*
*                        CACHE(,NC) will contain the margin widths in
*                        Cartesian coordinates when the labels are
*                        produced (i.e. the same Cartesian system used
*                        for BLC and TRC).
*
*   Returned:
*      IERR     I        Status return value:
*                           0: Success
*                           1: Initialization error
*                           2: Invalid coordinate system
*                           3: Cache overflow (see note 3).
*
*   Notes on PGSBOX
*   ---------------
*
*    1) Where a logarithmic world coordinate type is indicated PGSBOX
*       chooses grid lines and labels on the basis that the value
*       returned by NLFUNC is a base 10 logarithm.  PGSBOX does not
*       itself take logarithms or antilogarithms.  For example, if the
*       range of values returned by NLFUNC were 0.9 - 2.5, then PGSBOX
*       would draw a subset of the following set of grid lines and
*       labels:
*
*                   value          label
*            ------------------    -----
*            0.9031 = log10(8)      8
*            0.9542 = log10(9)      9
*            1.0000 = log10(10)    10**1
*            1.3010 = log10(20)     2
*            1.4771 = log10(30)     3
*            1.6021 = log10(40)     4
*            1.6990 = log10(50)     5
*            1.7782 = log10(60)     6
*            1.8451 = log10(70)     7
*            1.9031 = log10(80)     8
*            1.9542 = log10(90)     9
*            2.0000 = log10(100)   10**2
*            2.3010 = log10(200)    2
*            2.4771 = log10(300)    3
*
*       The subset chosen depends on the coordinate increment as
*       specified by the caller (e.g. via NG1 = 0, GRID1(0) != 0) or as
*       deduced by PGSBOX from the required density of grid lines
*       specified in the LABDEN argument.  The selection is made
*       according to the following table:
*
*            increment          grid lines
*           (0.00,0.12]   1, 2, 3, 4, 5, 6, 7, 8, 9
*           (0.12,0.18]   1, 2, 3, 4, 5,    7
*           (0.18,0.23]   1, 2, 3,    5,    7
*           (0.23,0.28]   1, 2, 3,    5
*           (0.28,0.40]   1, 2,       5
*           (0.40,0.70]   1, 3
*           (0.70,1.00]   1
*
*       For increments greater than 1 the nearest integer is used.
*
*    2) PGSBOX will attempt to handle discontinuities in angle, such as
*       may occur when cycling through 360 degrees, wherever the
*       discontinuity may occur, for example
*
*          359 -> 0 -> 1
*
*       or
*
*          179 -> 180 -> -179
*
*       Only single cycles are detected, so the sequence
*
*          -360 -> 0 -> ... -> 359 -> 0 -> ... -> 359
*
*       would not be handled properly.  In such cases NLFUNC should be
*       changed to return a normalized angle, or else a continuous
*       sequence.
*
*    3) PGSBOX maintains a table of axis crossings, CACHE, in which it
*       stores information used for axis labelling.  The caller need not
*       normally be concerned about the use of this table other than to
*       provide sufficient space.  Typically, NC = 256 should be enough;
*       if not, IERR = 3 will be returned.
*
*       However, a coordinate grid may be produced via multiple calls to
*       PGSBOX with deferment of axis labelling.  This might be done to
*       change the pen colour and/or thickness for different sets of
*       grid lines.  The table accumulates information from each
*       successive call until the labels are produced.  The table index,
*       IC, may be reset to zero by the caller to discard the
*       information collected.
*
*       The extrema of the world coordinate elements are stored in
*       CACHE(,0).  When a coordinate grid is plotted with multiple
*       calls to PGSBOX the initial call should always have IC set to -1
*       to signal that PGSBOX needs to determine the extrema.  On
*       subsequent calls with IC non-negative PGSBOX uses the extrema
*       cached from the first call.  This can speed up execution
*       considerably.
d350 2
a351 2
*   The curvilinear coordinate grid is defined by external function
*   NLFUNC whose interface is defined as follows:
d353 102
a454 103
*   Given:
*      OPCODE   I        Transformation code:
*                           +2: Compute a set of Cartesian coordinates
*                               that describe a path between this and
*                               the previous pair of world coordinates
*                               remembered from the last call with
*                               OPCODE = +1 or +2.  Usually only takes
*                               a single step unless traversing a
*                               discontinuity or some other
*                               irregularity (see explanation below).
*                           +1: Compute Cartesian coordinates from world
*                               coordinates.
*                            0: Initialize.
*                           -1: Compute world coordinates from Cartesian
*                               coordinates.
*
*                        N.B. NLFUNC must not change the input
*                        coordinates; that is the world coordinates for
*                        OPCODEs = +2 and +1, or the Cartesian
*                        coordinates for OPCODE = -1.
*
*      NLC      I        Number of elements in NLCPRM (must be >0).
*
*      NLI      I        Number of elements in NLIPRM (must be >0).
*
*      NLD      I        Number of elements in NLDPRM (must be >0).
*
*   Given and/or returned:
*      NLCPRM   C(NLC)*1 Character array.
*
*      NLIPRM   I(NLI)   Integer coefficients.
*
*      NLDPRM   D(NLD)   Double precision coefficients.
*
*      WORLD    D(2)     World coordinates.  Given if OPCODE > 0,
*                        returned if OPCODE < 0.
*
*      XY       D(2)     Cartesian coordinates.  Given if OPCODE < 0,
*                        returned if OPCODE > 0.
*
*      CONTRL   I        Control flag for OPCODE = +2:
*                           0: Normal state.
*                           1: Force PGSBOX to flush its plotting buffer
*                              and call NLFUNC again with the same world
*                              coordinates.
*                           2: Force PGSBOX to call NLFUNC again with
*                              the same world coordinates (without
*                              flushing its plotting buffer).
*
*      CONTXT   D(20)    Context elements for OPCODE = +2.
*
*   Returned:
*      IERR     I        Status return value:
*                           0: Success.
*                           1: Invalid parameters.
*                           2: Invalid world coordinate.
*                           3: Invalid Cartesian coordinate.
*
*                        The following status returns are recognized for
*                        opcodes +2 and +1
*                          -1: Accept the returned (x,y) coordinates but
*                              do not consider this as one end of a
*                              crossing segment for labelling world
*                              coordinate 1.
*                          -2: Ditto for world coordinate 2.
*                          -3: Ditto for world coordinates 1 and 2.
*
*   PGSBOX passes its NLCPRM, NLIPRM, and NLDPRM adjustable size array
*   arguments of length NLC, NLI, and NLD to NLFUNC without
*   modification.  Comments within NLFUNC should specify the parameters
*   it wants passed to it via these arrays.
*
*   PGSBOX first calls NLFUNC with OPCODE = 0 to cause it to initialize
*   its work arrays (if necessary).  It then uses OPCODE = -1 to
*   determine the range of world coordinate values.  It anchors the
*   start of each coordinate grid line with a call with OPCODE = +1, and
*   then tracks it with OPCODE = +2.
*
*   The CONTXT array is also passed to NLFUNC without modification to
*   allow it to preserve state information between calls for OPCODE = 2.
*   In particular, NLFUNC can use this to detect discontinuities in the
*   grid lines.
*
*   The CONTRL argument is provided so that NLFUNC can force PGSBOX to
*   call it again with or without flushing its plotting buffer.  This
*   may be needed when plotting a grid line through a discontinuity.
*   PGSBOX does not modify CONTRL.
*
*   Notes on NLFUNC
*   ---------------
*    1) NLFUNC must not change the input coordinates; that is the world
*       coordinates for OPCODEs = +1 and +2, or the Cartesian coordinates
*       for OPCODE = -1.
*
*    2) NLFUNC must define a single-valued function, that is, each
*       Cartesian coordinate (x,y) must map to a unique world coordinate
*       pair (xi,eta).
*
*    3) Notwithstanding the fact that PGSBOX declares NLCPRM, NLIPRM,
*       and NLDPRM as single dimension arrays of length NLC, NLI, and
*       NLD, NLFUNC may treat these as higher-dimensional arrays, for
*       example, NLDPRM(2,NLD).  (The FORTRAN standard requires that
*       only the last dimension is adjustable.)
d458 2
a459 2
     :   GCODE, TIKLEN, NG1, GRID1, NG2, GRID2, DOEQ, NLFUNC, NLC, NLI,
     :   NLD, NLCPRM, NLIPRM, NLDPRM, NC, IC, CACHE, IERR)
d512 1
a512 1
     :   XY, CONTRL, CONTXT, IERR)
d515 2
a516 2
         IERR = 1
         RETURN
d530 1
a530 1
     :   GRID1, NG2, GRID2, DOEQ, NC, IC, CACHE, IERR)
d548 2
a549 2
         IERR = 3
         RETURN
d570 5
a574 5
         IF (CI(J).GE.0) THEN
            CJ(J) = CI(J)
         ELSE
            CJ(J) = CI0
         END IF
d586 6
a591 1
*  Find world coordinate ranges.
d596 5
a600 5
*        Use extrema cached from a previous call.
         WMIN(1) = CACHE(1,0)
         WMAX(1) = CACHE(2,0)
         WMIN(2) = CACHE(3,0)
         WMAX(2) = CACHE(4,0)
d603 45
a647 68
*        Do a coarse search to find approximate ranges.
         WMIN(1) =  1D99
         WMAX(1) = -1D99
         WMIN(2) =  1D99
         WMAX(2) = -1D99

*        Need to consider cycles in angle through 360 degrees.
         ISANGL(1) = INDEX('ABCDEFGHI',FTYPE(1)).NE.0
         ISANGL(2) = INDEX('ABCDEFGHI',FTYPE(2)).NE.0
         VMIN(1,1) =  1D99
         VMIN(1,2) =  1D99
         VMAX(1,1) = -1D99
         VMAX(1,2) = -1D99
         VMIN(2,1) =  1D99
         VMIN(2,2) =  1D99
         VMAX(2,1) = -1D99
         VMAX(2,2) = -1D99

*        Sample coordinates on a 50 x 50 grid.
         NX = 50
         NY = 50
         DX = DBLE(TRC(1)-BLC(1))/NX
         DY = DBLE(TRC(2)-BLC(2))/NY

         K = 0
         IYPREV = -1
         DO 40 IY = 0, NY
            XY(2) = BLC(2) + IY*DY

*           Sample the edges only?
            KX = 1
            IF (DOEDGE) THEN
               IF (IY.NE.0 .AND. IY.NE.NY) KX = NX
            END IF

            DO 30 IX = 0, NX, KX
               XY(1) = BLC(1) + IX*DX

               IF (DOLBOX) THEN
                  WORLD(1) = WXY(1) + XY(1)*XSPAN
                  WORLD(2) = WXY(3) + XY(2)*YSPAN
               ELSE
                  CALL NLFUNC (-1, NLC, NLI, NLD, NLCPRM, NLIPRM,
     :               NLDPRM, WORLD, XY, CONTRL, CONTXT, IERR)
               END IF

               IF (IERR.EQ.0) THEN
                  K = K + 1

                  IF (ISANGL(1)) THEN
                     IF (K.EQ.1) W1X0 = WORLD(1)

                     IF (IY.NE.IYPREV) THEN
                        W1PREV = W1X0
                        W1X0 = WORLD(1)
                     END IF

*                    Iron out jumps.
                     WJUMP = WORLD(1) - W1PREV
                     IF (ABS(WJUMP).GT.180D0) THEN
                        WJUMP = WJUMP + SIGN(180D0,WJUMP)
                        WJUMP = 360D0*INT(WJUMP/360D0)
                        WORLD(1) = WORLD(1) - WJUMP
                     END IF

                     W1PREV = WORLD(1)
                     IYPREV = IY
                  END IF
d649 2
a650 2
                  IF (ISANGL(2)) THEN
                     IF (K.EQ.1) W2X0 = WORLD(2)
d652 131
a782 12
                     IF (IY.NE.IYPREV) THEN
                        W2PREV = W2X0
                        W2X0 = WORLD(2)
                     END IF

*                    Iron out jumps.
                     WJUMP = WORLD(2) - W2PREV
                     IF (ABS(WJUMP).GT.180D0) THEN
                        WJUMP = WJUMP + SIGN(180D0,WJUMP)
                        WJUMP = 360D0*INT(WJUMP/360D0)
                        WORLD(2) = WORLD(2) - WJUMP
                     END IF
d784 1
a784 97
                     W2PREV = WORLD(2)
                     IYPREV = IY
                  END IF

                  IF (WORLD(1).LT.WMIN(1)) WMIN(1) = WORLD(1)
                  IF (WORLD(1).GT.WMAX(1)) WMAX(1) = WORLD(1)
                  IF (WORLD(2).LT.WMIN(2)) WMIN(2) = WORLD(2)
                  IF (WORLD(2).GT.WMAX(2)) WMAX(2) = WORLD(2)

                  IF (ISANGL(1)) THEN
*                    Normalize to the range [0,360).
                     WORLD(1) = MOD(WORLD(1), 360D0)
                     IF (WORLD(1).LT.0D0) WORLD(1) = WORLD(1) + 360D0
                     IF (WORLD(1).LT.VMIN(1,1)) VMIN(1,1) = WORLD(1)
                     IF (WORLD(1).GT.VMAX(1,1)) VMAX(1,1) = WORLD(1)

*                    Normalize to the range (-180,180].
                     IF (WORLD(1).GT.180D0) WORLD(1) = WORLD(1) - 360D0
                     IF (WORLD(1).LT.VMIN(1,2)) VMIN(1,2) = WORLD(1)
                     IF (WORLD(1).GT.VMAX(1,2)) VMAX(1,2) = WORLD(1)
                  END IF

                  IF (ISANGL(2)) THEN
*                    Normalize to the range [0,360).
                     WORLD(2) = MOD(WORLD(2), 360D0)
                     IF (WORLD(2).LT.0D0) WORLD(2) = WORLD(2) + 360D0
                     IF (WORLD(2).LT.VMIN(2,1)) VMIN(2,1) = WORLD(2)
                     IF (WORLD(2).GT.VMAX(2,1)) VMAX(2,1) = WORLD(2)

*                    Normalize to the range (-180,180].
                     IF (WORLD(2).GT.180D0) WORLD(2) = WORLD(2) - 360D0
                     IF (WORLD(2).LT.VMIN(2,2)) VMIN(2,2) = WORLD(2)
                     IF (WORLD(2).GT.VMAX(2,2)) VMAX(2,2) = WORLD(2)
                  END IF
               END IF
 30         CONTINUE
 40      CONTINUE

         IF (K.EQ.0) THEN
*           No valid coordinates found within the frame.
            IERR = 2
            GO TO 999
         END IF

*        Check for cycles in angle.
         DO 50 J = 1, 2
            IF (ISANGL(J)) THEN
               IF (WMAX(J)-WMIN(J).LT.360D0 .AND.
     :             WMAX(J)-WMIN(J).GT.VMAX(J,1)-VMIN(J,1)+TOL) THEN
*                 Must have a cycle, preserve the sign.
                  IF (WMAX(J).GE.0D0) THEN
                     WMIN(J) = VMIN(J,1)
                     WMAX(J) = VMAX(J,1)
                  ELSE
                     WMIN(J) = VMIN(J,1) - 360D0
                     WMAX(J) = VMAX(J,1) - 360D0
                  END IF
               END IF

               IF (WMAX(J)-WMIN(J).LT.360D0 .AND.
     :             WMAX(J)-WMIN(J).GT.VMAX(J,2)-VMIN(J,2)+TOL) THEN
*                 Must have a cycle, preserve the sign.
                  IF (WMAX(J).GE.0D0) THEN
                     IF (VMAX(J,2).GE.0D0) THEN
                        WMIN(J) = VMIN(J,2)
                        WMAX(J) = VMAX(J,2)
                     ELSE
                        WMIN(J) = VMIN(J,2) + 360D0
                        WMAX(J) = VMAX(J,2) + 360D0
                     END IF
                  ELSE
                     IF (VMAX(J,2).LT.0D0) THEN
                        WMIN(J) = VMIN(J,2)
                        WMAX(J) = VMAX(J,2)
                     ELSE
                        WMIN(J) = VMIN(J,2) - 360D0
                        WMAX(J) = VMAX(J,2) - 360D0
                     END IF
                  END IF
               END IF
            END IF
 50      CONTINUE

*        Cache extrema for subsequent calls.
         CACHE(1,0) = WMIN(1)
         CACHE(2,0) = WMAX(1)
         CACHE(3,0) = WMIN(2)
         CACHE(4,0) = WMAX(2)

*        Was full sampling done?
         IF (DOEDGE) THEN
            CACHE(1,NC-1) = 0D0
         ELSE
            CACHE(1,NC-1) = 1D0
         END IF

         IC = 0
d789 5
a793 5
*        User specified grid density.
         DENS(1) = MOD(LABDEN,100)
         DENS(2) = LABDEN/100
         IF (DENS(1).EQ.0) DENS(1) = DENS0
         IF (DENS(2).EQ.0) DENS(2) = DENS0
d795 3
a797 3
*        Default grid density.
         DENS(1) = DENS0
         DENS(2) = DENS0
d804 53
a856 109
         IF (J.EQ.1) THEN
            K = 2
         ELSE
            K = 1
         END IF

         IF (NG(J).EQ.0 .AND. G0(J).NE.0D0) THEN
            GSTEP(J) = G0(J)
         ELSE IF (DOEQ .AND. NG(K).EQ.0 .AND. G0(K).NE.0D0) THEN
            GSTEP(J) = G0(K)
         ELSE
            DW(J) = WMAX(J) - WMIN(J)
            STEP = DW(J)/DENS(J)

            FACT = 1D0
            IF (INDEX('GHI',FTYPE(J)).NE.0) THEN
*              Rescale degrees to hours.
               FACT = 1D0/15D0
               STEP = STEP*FACT
            ELSE IF (FTYPE(J).EQ.'Y' .AND. STEP.LT.0.5D0) THEN
*              Calendar increment of less than 12h; use time format.
               FTYPE(J) = 'y'

*              Rescale days to hours.
               FACT = 24D0
               STEP = STEP*FACT
            END IF

            IF (INDEX('ABCDEF',FTYPE(J)).NE.0 .AND. STEP.GE.1D0) THEN
*              Angle with multi-degree increment.
               IF (STEP.LT.1.5D0) THEN
                  STEP = 1D0
               ELSE IF (STEP.LT.3D0) THEN
                  STEP = 2D0
               ELSE IF (STEP.LT.7D0) THEN
                  STEP = 5D0
               ELSE IF (STEP.LT.12D0) THEN
                  STEP = 10D0
               ELSE IF (STEP.LT.20D0) THEN
                  STEP = 15D0
               ELSE IF (STEP.LT.40D0) THEN
                  STEP = 30D0
               ELSE IF (STEP.LT.70D0) THEN
                  STEP = 45D0
               ELSE IF (STEP.LT.120D0) THEN
                  STEP = 90D0
               ELSE IF (STEP.LT.270D0) THEN
                  STEP = 180D0
               ELSE IF (STEP.LT.520D0) THEN
                  STEP = 360D0
               ELSE
                  STEP = 360D0*INT(STEP/360D0 + 0.5)
               END IF

            ELSE IF (INDEX('GHITy',FTYPE(J)).NE.0 .AND.
     :         STEP.GE.1D0) THEN
*              Angle or time in hms format with multi-hour increment.
               IF (STEP.LT.1.5D0) THEN
                  STEP = 1D0
               ELSE IF (STEP.LT.2.5D0) THEN
                  STEP = 2D0
               ELSE IF (STEP.LT.3.5D0) THEN
                  STEP = 3D0
               ELSE IF (STEP.LT.5D0) THEN
                  STEP = 4D0
               ELSE IF (STEP.LT.7D0) THEN
                  STEP = 6D0
               ELSE IF (STEP.LT.10D0) THEN
                  STEP = 8D0
               ELSE IF (STEP.LT.15D0) THEN
                  STEP = 12D0
               ELSE IF (STEP.LT.21D0) THEN
                  STEP = 18D0
               ELSE IF (STEP.LT.36D0) THEN
                  STEP = 24D0
               ELSE
                  STEP = 24D0*INT(STEP/24D0 + 0.5)
               END IF

               STEP = STEP/FACT

            ELSE IF (INDEX('DEFGHITy',FTYPE(J)).NE.0 .AND.
     :         STEP.LT.1D0) THEN
*              Angle or time in sexagesimal format with sub-degree/hour
*              increment.
               FACT = FACT*60D0
               STEP = STEP*60D0
               IF (STEP.LT.1D0) THEN
*                 Sub-minute increment.
                  FACT = FACT*60D0
                  STEP = STEP*60D0
               END IF

               IF (STEP.LT.1D0) THEN
*                 Sub-second increment.
                  TMP = 10D0**(INT(LOG10(STEP))-1)
                  IF (1.5*TMP.GE.STEP) THEN
                     STEP = TMP
                  ELSE
                     IF (3D0*TMP.GE.STEP) THEN
                        STEP = 2D0*TMP
                     ELSE
                        IF (7D0*TMP.GE.STEP) THEN
                           STEP = 5D0*TMP
                        ELSE
                           STEP = 10D0*TMP
                        END IF
                     END IF
                  END IF
d858 24
a881 29
               ELSE
                  IF (STEP.LT.1.5D0) THEN
                     STEP = 1D0
                  ELSE IF (STEP.LT.2.5D0) THEN
                     STEP = 2D0
                  ELSE IF (STEP.LT.3.5D0) THEN
                     STEP = 3D0
                  ELSE IF (STEP.LT.4.5D0) THEN
                     STEP = 4D0
                  ELSE IF (STEP.LT.5.5D0) THEN
                     STEP = 5D0
                  ELSE IF (STEP.LT.8D0) THEN
                     STEP = 6D0
                  ELSE IF (STEP.LT.11D0) THEN
                     STEP = 10D0
                  ELSE IF (STEP.LT.14D0) THEN
                     STEP = 12D0
                  ELSE IF (STEP.LT.18D0) THEN
                     STEP = 15D0
                  ELSE IF (STEP.LT.25D0) THEN
                     STEP = 20D0
                  ELSE IF (STEP.LT.45D0) THEN
                     STEP = 30D0
                  ELSE
                     STEP = 60D0
                  END IF
               END IF

               STEP = STEP/FACT
d883 1
a883 14
            ELSE IF (FTYPE(J).EQ.'Y') THEN
*              Calendar axis: use coded steps.
               IF (STEP.LT.15D0) THEN
*                 Timespan of a few months; use multi-day increments.
                  STEP = ANINT(STEP)
                  IF (STEP.LT.1D0) THEN
                     STEP = 1D0
                  ELSE IF (STEP.GT.9D0) THEN
*                    Fortnightly.
                     STEP = 14D0
                  ELSE IF (STEP.GT.4D0) THEN
*                    Weekly.
                     STEP = 7D0
                  END IF
d885 23
a907 11
               ELSE IF (STEP.LT.270D0) THEN
*                 Timespan of a few years; use multi-month increments.
                  STEP = ANINT(STEP/30.44D0)
                  IF (STEP.LT.1.5D0) THEN
                     STEP = 1D0
                  ELSE IF (STEP.LT.2.5D0) THEN
                     STEP = 2D0
                  ELSE IF (STEP.LT.3.5D0) THEN
                     STEP = 3D0
                  ELSE IF (STEP.LT.4.5D0) THEN
                     STEP = 4D0
d909 1
a909 1
                     STEP = 6D0
d911 2
d914 59
a972 25
*                 Coding for multi-month increments.
                  STEP = 100D0*STEP

               ELSE
*                 Multi-year increments.
                  STEP = ANINT(DW(J)/DENS(J)/365.25D0)
                  IF (STEP.LT.1D0) THEN
                     STEP = 1D0
                  ELSE
                     TMP = 10D0**INT(LOG10(STEP))

                     IF (1.5D0*TMP.GE.STEP) THEN
                        STEP = TMP
                     ELSE
                        IF (3D0*TMP.GE.STEP) THEN
                           STEP = 2D0*TMP
                        ELSE
                           IF (7D0*TMP.GE.STEP) THEN
                              STEP = 5D0*TMP
                           ELSE
                              STEP = 10D0*TMP
                           END IF
                        END IF
                     END IF
                  END IF
d974 2
a975 3
*                 Coding for multi-year increments.
                  STEP = 10000D0*STEP
               END IF
d978 6
a983 3
*              Just numbers.
               TMP = 10D0**INT(LOG10(STEP))
               IF (STEP.LT.1D0) TMP = TMP/10D0
d985 1
a985 1
               IF (1.5D0*TMP.GE.STEP) THEN
d987 1
a987 1
               ELSE
d989 1
a989 1
                     STEP = 2D0*TMP
d991 17
a1007 7
                     IF (7D0*TMP.GE.STEP) THEN
                        STEP = 5D0*TMP
                     ELSE
                        STEP = 10D0*TMP
                     END IF
                  END IF
               END IF
d1009 33
a1041 19
*              Adjust the step size for logarithmic values.
               IF (FTYPE(J).EQ.'L') THEN
                  IF (STEP.GT.0.7D0) THEN
                     LDIV(J) = 1
                     STEP = NINT(STEP)
                  ELSE
                     IF (STEP.GT.0.4D0) THEN
                        LDIV(J) = 2
                     ELSE IF (STEP.GT.0.28D0) THEN
                        LDIV(J) = 3
                     ELSE IF (STEP.GT.0.23D0) THEN
                        LDIV(J) = 4
                     ELSE IF (STEP.GT.0.18D0) THEN
                        LDIV(J) = 5
                     ELSE IF (STEP.GT.0.12D0) THEN
                        LDIV(J) = 6
                     ELSE
                        LDIV(J) = 9
                     END IF
d1043 2
a1044 3
                     STEP = 1D0/LDIV(J)
                  END IF
               END IF
d1046 1
d1048 2
a1049 2
            GSTEP(J) = STEP
         END IF
d1054 8
a1061 8
         IF (GRID1(0).EQ.0D0 .AND. GRID2(0).EQ.0D0) THEN
            GSTEP(1) = MIN(GSTEP(1), GSTEP(2))
            GSTEP(2) = GSTEP(1)
         ELSE IF (GRID1(0).EQ.0D0) THEN
            GSTEP(1) = GSTEP(2)
         ELSE IF (GRID2(0).EQ.0D0) THEN
            GSTEP(2) = GSTEP(1)
         END IF
d1066 8
a1073 2
         IF (FTYPE(J).EQ.'L') THEN
            WMIN(J) = AINT(WMIN(J)-1D0)
d1075 34
a1108 40
         ELSE IF (FTYPE(J).EQ.'Y') THEN
*           Calendar axis.
            IF (GSTEP(J).LT.100D0) THEN
*              Daily increments.
               WMIN(J) = AINT(WMIN(J))
               WMAX(J) = AINT(WMAX(J)+1D0)
            ELSE
*              Start on Jan/01.
               CALL PGMJD (0, WMIN(J), IY, IM, ID)
               CALL PGMJD (1, WMIN(J), IY, 1, 1)

               CALL PGMJD (0, WMAX(J), IY, IM, ID)
               IF (GSTEP(J).LT.10000D0) THEN
*                 Monthly increments.
                  CALL PGMJD (1, WMAX(J), IY, 12, 1)
               ELSE
*                 Yearly increments.
                  CALL PGMJD (1, WMAX(J), IY+1, 1, 1)
               END IF
            END IF

         ELSE
            TMP = AINT(WMIN(J)/GSTEP(J))*GSTEP(J)
            IF (TMP.GE.WMIN(J)) TMP = TMP - GSTEP(J)
            WMIN(J) = TMP
            TMP = AINT(WMAX(J)/GSTEP(J))*GSTEP(J)
            IF (TMP.LE.WMAX(J)) TMP = TMP + GSTEP(J)
            WMAX(J) = TMP
         END IF

         DW(J) = WMAX(J) - WMIN(J)
         SW(J) = DW(J)/NSTEP(J)

*        Adjust NSTEP so that SW divides GSTEP.
         IF (SW(J).LT.GSTEP(J)) THEN
            SW(J) = GSTEP(J)/ANINT(GSTEP(J)/SW(J))
         ELSE
            SW(J) = GSTEP(J)
         END IF
         NSTEP(J) = ANINT(DW(J)/SW(J))
d1120 22
a1141 22
         IF (GCODE(J).EQ.2) THEN
            TCODE(J,1) = -1
            TCODE(J,2) = -1
            TCODE(J,3) = -1
            TCODE(J,4) = -1
         ELSE IF (GCODE(J).EQ.1) THEN
            TCODE(J,1) = 1
            TCODE(J,2) = 1
            TCODE(J,3) = 1
            TCODE(J,4) = 1
         ELSE IF (GCODE(J).LT.0) THEN
            K = ABS(GCODE(J))
            TCODE(J,1) = MOD(K,10)
            TCODE(J,2) = MOD(K/10,10)
            TCODE(J,3) = MOD(K/100,10)
            TCODE(J,4) = MOD(K/1000,10)
         ELSE
            TCODE(J,1) = 0
            TCODE(J,2) = 0
            TCODE(J,3) = 0
            TCODE(J,4) = 0
         END IF
d1147 1
a1147 1
         IF (GCODE(J).EQ.0) GO TO 120
d1149 50
a1198 7
         IF (J.EQ.1) THEN
            CALL PGSCI (CJ(1))
            K = 2
         ELSE
            CALL PGSCI (CJ(2))
            K = 1
         END IF
d1200 2
a1201 2
         IF (NG(J).GT.0) THEN
            NWJ = NG(J)
d1203 13
a1215 35
         ELSE IF (FTYPE(J).EQ.'Y' .AND. GSTEP(J).GE.100D0) THEN
*           Calendar axis.
            CALL PGMJD (0, WMAX(J), IY, IM, ID)
            IF (GSTEP(J).LT.10000D0) THEN
               NWJ = 12*IY + IM
               CALL PGMJD (0, WMIN(J), IY, IM, ID)
               NWJ = (NWJ - (12*IY + IM))/INT(GSTEP(J)/100D0)
            ELSE
               NWJ = IY
               CALL PGMJD (0, WMIN(J), IY, IM, ID)
               NWJ = (NWJ - IY)/INT(GSTEP(J)/10000D0)
            END IF

         ELSE
            NWJ = NINT(DW(J)/GSTEP(J))
            IW0 = NINT(WMIN(J)/GSTEP(J))
         END IF

         DO 110 IWJ = 0, NWJ
            MAJOR = .FALSE.

*           Determine the world coordinate of the grid line.
            IF (NG(J).GT.0) THEN
*              User-specified.
               IF (IWJ.EQ.0) GO TO 110
               WORLD(1) = GRID1(IWJ)
               WORLD(2) = GRID2(IWJ)
            ELSE
*              Internally computed.
               IF (FTYPE(J).EQ.'Y' .AND. GSTEP(J).GE.100D0) THEN
*                 Calendar axis.
                  CALL PGMJD (0, WMIN(J), IY, IM, ID)
                  IF (GSTEP(J).LT.10000D0) THEN
                     IM = IM + IWJ*INT(GSTEP(J)/100D0)
                     CALL PGMJD (1, WORLD(J), IY, IM, ID)
d1217 1
a1217 2
                     IY = IY + IWJ*INT(GSTEP(J)/10000D0)
                     CALL PGMJD (1, WORLD(J), IY, IM, ID)
d1220 143
a1362 16
               ELSE
                  WORLD(J) = (IW0 + IWJ)*GSTEP(J)

*                 Logarithmic?
                  IF (FTYPE(J).EQ.'L') THEN
                     TMP = MOD(WORLD(J),1D0)
                     IF (TMP.LT.0D0) TMP = TMP + 1D0
                     L = NINT(TMP*LDIV(J))

                     IF (L.EQ.0) THEN
*                       Major tick mark.
                        MAJOR = .TRUE.
                     ELSE
*                       Adjust logarithmic scales.
                        IF (LDIV(J).LE.6) THEN
                           L = LTABL(L,LDIV(J))
d1364 2
a1365 1
                           L = L + 1
d1367 1
d1369 85
a1453 261
                        WORLD(J) = WORLD(J) - TMP + LOG10(DBLE(L))
                     END IF
                  END IF
               END IF
            END IF

            NP = 0
            GETEND = .TRUE.
            DO 100 IWK = 0, NSTEP(K)
               WORLD(K) = WMIN(K) + IWK*SW(K)

               IF (GETEND) THEN
*                 Get end-point context.
                  IF (DOLBOX) THEN
                     XY(1) = (WORLD(1) - WXY(1))/XSPAN
                     XY(2) = (WORLD(2) - WXY(3))/YSPAN
                  ELSE
                     CALL NLFUNC (1, NLC, NLI, NLD, NLCPRM, NLIPRM,
     :                  NLDPRM, WORLD, XY, CONTRL, CONTXT, IERR)
                  END IF

                  IF (IERR.LE.0) THEN
                     X1 = REAL(XY(1))
                     Y1 = REAL(XY(2))
                     INSIDE = X1.GT.BLC(1) .AND. X1.LT.TRC(1) .AND.
     :                        Y1.GT.BLC(2) .AND. Y1.LT.TRC(2)

                     NP = 1
                     XR(1) = X1
                     YR(1) = Y1

                     PREVIN = INSIDE
                     GETEND = .FALSE.

                     LABLOK = IERR.NE.-J .AND. IERR.NE.-3
                  END IF
                  GO TO 100
               END IF

               DO 90 ISTEP = 1, 1000
                  IF (DOLBOX) THEN
                     XY(1) = (WORLD(1) - WXY(1))/XSPAN
                     XY(2) = (WORLD(2) - WXY(3))/YSPAN
                  ELSE
                     CALL NLFUNC (2, NLC, NLI, NLD, NLCPRM, NLIPRM,
     :                  NLDPRM, WORLD, XY, CONTRL, CONTXT, IERR)
                  END IF

                  IF (IERR.GT.0) THEN
*                    Flush buffer.
                     IF (NP.GT.1) CALL PGLINE(NP, XR, YR)
                     NP = 0
                     GETEND = .TRUE.
                     GO TO 100
                  END IF

                  IF (NP.EQ.BUFSIZ) THEN
*                    Recycle buffer.
                     CALL PGLINE(NP, XR, YR)
                     XR(1) = XR(NP)
                     YR(1) = YR(NP)
                     NP = 1
                  END IF

                  X2 = REAL(XY(1))
                  Y2 = REAL(XY(2))
                  INSIDE = X2.GT.BLC(1) .AND. X2.LT.TRC(1) .AND.
     :                     Y2.GT.BLC(2) .AND. Y2.LT.TRC(2)

                  IF (.NOT.INSIDE) THEN
*                    For tick marks at the left or right edge.
                     IF ((X2.EQ.BLC(1) .OR.  X2.EQ.TRC(1)) .AND.
     :                    Y2.GT.BLC(2) .AND. Y2.LT.TRC(2)) THEN
                        INSIDE = X2.EQ.XR(NP)
                     END IF
                  END IF

                  IF (.NOT.INSIDE) THEN
*                    For tick marks at the bottom or top edge.
                     IF ((Y2.EQ.BLC(2) .OR.  Y2.EQ.TRC(2)) .AND.
     :                    X2.GT.BLC(1) .AND. X2.LT.TRC(1)) THEN
                        INSIDE = Y2.EQ.YR(NP)
                     END IF
                  END IF

                  IF (NP.EQ.0) THEN
                     NP = 1
                     XR(1) = X2
                     YR(1) = Y2
                  ELSE
                     IF (INSIDE) THEN
*                       This point is inside the frame...
                        IF (.NOT.PREVIN) THEN
*                          ...but the previous one was outside.
                           X1 = XR(NP)
                           Y1 = YR(NP)

                           FSEG = 0
                           XPOINT = 0.0
                           IF (ABS(X2-X1).GT.XTOL) THEN
                              S = (Y2-Y1)/(X2-X1)
                              IF (XR(NP).LE.BLC(1)) THEN
                                 FSEG = 2
                                 XR(NP) = BLC(1)
                                 XPOINT = Y1 + (XR(NP) - X1)*S
                                 YR(NP) = XPOINT
                              ELSE IF (XR(NP).GE.TRC(1)) THEN
                                 FSEG = 4
                                 XR(NP) = TRC(1)
                                 XPOINT = Y1 + (XR(NP) - X1)*S
                                 YR(NP) = XPOINT
                              END IF
                           END IF

                           IF (ABS(Y2-Y1).GT.YTOL) THEN
                              S = (X2-X1)/(Y2-Y1)
                              IF (YR(NP).LE.BLC(2)) THEN
                                 FSEG = 1
                                 YR(NP) = BLC(2)
                                 XPOINT = X1 + (YR(NP) - Y1)*S
                                 XR(NP) = XPOINT
                              ELSE IF (YR(NP).GE.TRC(2)) THEN
                                 FSEG = 3
                                 YR(NP) = TRC(2)
                                 XPOINT = X1 + (YR(NP) - Y1)*S
                                 XR(NP) = XPOINT
                              END IF
                           END IF


                           IF (FSEG.EQ.0) THEN
*                             The crossing is too oblique.
                              INSIDE = .FALSE.

                           ELSE
*                             Record this crossing point.
                              IF (TCODE(J,FSEG).NE.0 .AND. LABLOK) THEN
                                 IF (IC.LT.NC-1) THEN
                                    IC = IC + 1
                                    CACHE(1,IC) = FSEG
                                    CACHE(2,IC) = XPOINT
                                    CACHE(3,IC) = J
                                    CACHE(4,IC) = WORLD(J)
                                 ELSE
*                                   Cache overflow.
                                    OVERFL = .TRUE.
                                 END IF
                              END IF

                              IF (TCODE(J,FSEG).GT.0) THEN
*                                Just want tick marks.
                                 S = (XSCL*(X2-X1))**2 +
     :                               (YSCL*(Y2-Y1))**2
                                 S = SQRT(S)/TCODE(J,FSEG)
                                 IF (MAJOR) S = S/1.5
                                 NP = NP + 1
                                 XR(NP) = XR(NP-1) + (X2-X1)*TIKLEN/S
                                 YR(NP) = YR(NP-1) + (Y2-Y1)*TIKLEN/S

                                 CALL PGLINE(NP, XR, YR)
                                 NP = 1
                              END IF
                           END IF
                        END IF

                        IF (INSIDE .AND. GCODE(J).EQ.2) THEN
*                          Full grid.
                           NP = NP + 1
                        END IF
                        XR(NP) = X2
                        YR(NP) = Y2
                     ELSE
*                       This point is outside the frame...
                        IF (PREVIN) THEN
*                          ...but the previous one was inside.
                           X1 = XR(NP)
                           Y1 = YR(NP)

                           NP = NP + 1
                           XR(NP) = X2
                           YR(NP) = Y2

                           FSEG = 0
                           XPOINT = 0.0
                           IF (ABS(X2-X1).GT.XTOL) THEN
                              S = (Y2-Y1)/(X2-X1)
                              IF (XR(NP).LE.BLC(1)) THEN
                                 FSEG = 2
                                 XR(NP) = BLC(1)
                                 XPOINT = Y1 + (XR(NP) - X1)*S
                                 YR(NP) = XPOINT
                              ELSE IF (XR(NP).GE.TRC(1)) THEN
                                 FSEG = 4
                                 XR(NP) = TRC(1)
                                 XPOINT = Y1 + (XR(NP) - X1)*S
                                 YR(NP) = XPOINT
                              END IF
                           END IF

                           IF (ABS(Y2-Y1).GT.YTOL) THEN
                              S = (X2-X1)/(Y2-Y1)
                              IF (YR(NP).LE.BLC(2)) THEN
                                 FSEG = 1
                                 YR(NP) = BLC(2)
                                 XPOINT = X1 + (YR(NP) - Y1)*S
                                 XR(NP) = XPOINT
                              ELSE IF (YR(NP).GE.TRC(2)) THEN
                                 FSEG = 3
                                 YR(NP) = TRC(2)
                                 XPOINT = X1 + (YR(NP) - Y1)*S
                                 XR(NP) = XPOINT
                              END IF
                           END IF


                           IF (FSEG.EQ.0) THEN
*                             The crossing is too oblique.
                              INSIDE = .TRUE.

                              IF (GCODE(J).EQ.2) THEN
*                                Full grid.
                                 NP = NP + 1
                              END IF
                              XR(NP) = X2
                              YR(NP) = Y2

                           ELSE
*                             Record this crossing point.
                              IF (TCODE(J,FSEG).NE.0 .AND. LABLOK) THEN
                                 IF (IC.LT.NC-1) THEN
                                    IC = IC + 1
                                    CACHE(1,IC) = FSEG
                                    CACHE(2,IC) = XPOINT
                                    CACHE(3,IC) = J
                                    CACHE(4,IC) = WORLD(J)
                                 ELSE
*                                   Cache overflow.
                                    OVERFL = .TRUE.
                                 END IF
                              END IF

                              IF (TCODE(J,FSEG).GT.0) THEN
*                                Just want tick marks.
                                 X1 = XR(NP)
                                 Y1 = YR(NP)
                                 X2 = XR(NP-1)
                                 Y2 = YR(NP-1)
                                 S = (XSCL*(X2-X1))**2 +
     :                               (YSCL*(Y2-Y1))**2
                                 S = SQRT(S)/TCODE(J,FSEG)
                                 IF (MAJOR) S = S/1.5
                                 XR(NP-1) = X1 + (X2-X1)*TIKLEN/S
                                 YR(NP-1) = Y1 + (Y2-Y1)*TIKLEN/S
                              END IF

*                             Flush buffer.
                              IF (TCODE(J,FSEG).NE.0) THEN
                                 CALL PGLINE(NP, XR, YR)
                              END IF
                              NP = 0
                           END IF
d1455 2
a1456 3
*                          The previous point was also outside.
                           XR(NP) = X2
                           YR(NP) = Y2
d1458 1
a1458 2
                     END IF
                  END IF
d1460 39
a1498 12
                  PREVIN = INSIDE
                  LABLOK = IERR.NE.-J .AND. IERR.NE.-3

                  IF (CONTRL.EQ.0) THEN
                     GO TO 100
                  ELSE IF (CONTRL.EQ.1) THEN
*                    Flush buffer.
                     IF (NP.GT.1) CALL PGLINE(NP, XR, YR)
                     NP = 0
                  END IF
 90            CONTINUE
 100        CONTINUE
d1500 2
a1501 2
            IF (NP.GT.1) CALL PGLINE(NP, XR, YR)
 110     CONTINUE
d1510 1
a1510 1
     :   CJ, NC, IC, CACHE)
d1524 3
a1526 3
*   PGCRLB is a helper routine for PGSBOX, not meant to be called
*   directly since it expects the viewport and window to be scaled to
*   the full extent; it labels a curvilinear coordinate grid.
d1528 5
a1532 5
*   Given:
*      BLC      R(2)     Cartesian coordinates of the bottom left-hand
*                        corner.
*      TRC      R(2)     Cartesian coordinates of the top right-hand
*                        corner.
d1534 1
a1534 1
*      IDENTS   C(3)*(*) Identification strings (see PGSBOX).
d1536 2
a1537 2
*      FTYPE    C(2)*1   Axis types, used for axis labelling (see
*                        PGSBOX).
d1539 2
a1540 2
*      LABCTL   I        Decimal encoded grid labelling control (see
*                        PGSBOX).
d1542 1
a1542 1
*      CI       I(7)     Colour table (see PGSBOX).
d1544 2
a1545 2
*   Given and/or returned:
*      NC       I        Upper array index for CACHE.
d1547 1
a1547 1
*      IC       I        Current number of entries in the CACHE table.
d1549 2
a1550 3
*      CACHE    D(4,0:NC)
*                        Table of points where the tick marks or grid
*                        lines cross the frame (see PGSBOX).
d1552 1
a1552 1
*   Author: Mark Calabretta, Australia Telescope National Facility
d1558 6
a1563 5
      INTEGER   CI(7), EDGE, IC, ID, ID2, IM, IM2, IMAG(2), ITER, IWRLD,
     :          IY, IY2, J, JC, K, K1, K2, KWRLD, L, LABCTL, LD, LM,
     :          LMAG(2), LS, LV, M, M1, M2, MM, NC, NCH, NI(2,0:4),
     :          NSWAP, PP, PRVDEG(2), PRVMIN(2), PRVEDG, PRVYR(2),
     :          SEXSUP(2), SKIP(4), SKOP(4)
d1580 2
a1581 2
         DO 10 J = 1, IC
            IWRLD = NINT(CACHE(3,J))
d1583 17
a1599 17
            IF (INDEX('ADG', FTYPE(IWRLD)).NE.0) THEN
               CACHE(4,J) = MOD(CACHE(4,J), 360D0)
               IF (CACHE(4,J).LT.0D0) CACHE(4,J) = CACHE(4,J) + 360D0
            ELSE IF (INDEX('BEH', FTYPE(IWRLD)).NE.0) THEN
               CACHE(4,J) = MOD(CACHE(4,J), 360D0)
               IF (CACHE(4,J).LE.-180D0) THEN
                  CACHE(4,J) = CACHE(4,J) + 360D0
               ELSE IF (CACHE(4,J).GT.180D0) THEN
                  CACHE(4,J) = CACHE(4,J) - 360D0
               END IF
            END IF

            IF (INDEX('GHI', FTYPE(IWRLD)).NE.0) THEN
*              Angle expressed as time.
               CACHE(4,J) = CACHE(4,J)/15D0
            END IF
 10      CONTINUE
d1606 14
a1619 14
         NSWAP = 0
         DO 30 J = 1, IC-1
            IF (CACHE(1,J).LT.CACHE(1,J+1)) GO TO 30
            IF (CACHE(1,J).EQ.CACHE(1,J+1) .AND.
     :          CACHE(2,J).LE.CACHE(2,J+1)) GO TO 30

            NSWAP = NSWAP + 1
            DO 20 M = 1, 4
               TMP = CACHE(M,J)
               CACHE(M,J) = CACHE(M,J+1)
               CACHE(M,J+1) = TMP
 20         CONTINUE
 30      CONTINUE
         IF (NSWAP.EQ.0) GO TO 50
d1625 1
a1625 1
         IF (J.GT.JC) GO TO 100
d1627 11
a1637 11
         DO 60 M = 1, 4
            IF (CACHE(M,J).NE.CACHE(M,J-1)) GO TO 90
 60      CONTINUE

*        This entry is the same as the previous one.
         JC = JC - 1
         DO 80 K = J, JC
            DO 70 M = 1, 4
               CACHE(M,K) = CACHE(M,K+1)
 70         CONTINUE
 80      CONTINUE
d1643 1
a1643 1
*  How do we label the edges of the frame?
d1656 2
a1657 2
         IWRLD = NINT(CACHE(3,J))
         EDGE  = NINT(CACHE(1,J))
d1659 2
a1660 2
         NI(IWRLD,0) = NI(IWRLD,0) + 1
         NI(IWRLD,EDGE) = NI(IWRLD,EDGE) + 1
d1670 2
a1671 2
*        User-defined.
         L = LABCTL
d1673 147
a1819 148
*        Work it out ourselves.
         L = 0
         IF (ABS(SI(1)-SI(2)).GT.1.0) THEN
*           Approximately horizontal/vertical grid lines.
            IF (SI(1).GT.SI(2)) THEN
*              First world coordinate with vertical grid lines.
               IF (NI(1,1).GT.3 .OR. NI(1,1).GE.NI(1,3)) THEN
*                 Label bottom of frame.
                  L = L + 1
               ELSE
*                 Label top of frame.
                  L = L + 100
               END IF

*              Second world coordinate with horizontal grid lines.
               IF (NI(2,2).GT.3 .OR. NI(2,2).GE.NI(2,4)) THEN
*                 Label left side of frame.
                  L = L + 20
               ELSE
*                 Label right side of frame.
                  L = L + 2000
               END IF
            ELSE
*              First world coordinate with horizontal grid lines.
               IF (NI(1,2).GT.3 .OR. NI(1,2).GE.NI(1,4)) THEN
*                 Label left side of frame.
                  L = L + 10
               ELSE
*                 Label right side of frame.
                  L = L + 1000
               END IF

*              Second world coordinate with vertical grid lines.
               IF (NI(2,1).GT.3 .OR. NI(2,1).GE.NI(2,3)) THEN
*                 Label bottom of frame.
                  L = L + 2
               ELSE
*                 Label top of frame.
                  L = L + 200
               END IF
            END IF
         ELSE
*           Skew grid lines or worse.
            IF (SI(1).GT.0.5D0) THEN
*              First world coordinate with vertical grid lines.
               IF (NI(1,1).GT.1 .OR. NI(1,1).GT.NI(1,3)) THEN
                  L = 1
               ELSE
                  L = 100
               END IF

               IF (SI(2).GT.0.5D0) THEN
*                 Second world coordinate also with vertical grid lines.
                  IF (L.EQ.1) THEN
                     L = 201
                  ELSE
                     IF (NI(2,1).GT.1 .OR. NI(2,1).GT.NI(2,3)) THEN
                        L = 102
                     ELSE
                        L = 300
                     END IF
                  END IF
               ELSE
*                 Second world coordinate with diagonal grid lines.
                  L = L + 2020
               END IF
            ELSE IF (SI(1).LT.-0.5D0) THEN
*              First world coordinate with horizontal grid lines.
               IF (NI(1,2).GT.1 .OR. NI(1,2).GT.NI(1,4)) THEN
                  L = 10
               ELSE
                  L = 1000
               END IF

               IF (SI(2).LT.-0.5D0) THEN
*                 Second world coordinate also with horizontal grid.
                  IF (L.EQ.10) THEN
                     L = 2010
                  ELSE
                     IF (NI(2,2).GT.1 .OR. NI(2,2).GT.NI(2,4)) THEN
                        L = 1020
                     ELSE
                        L = 3000
                     END IF
                  END IF
               ELSE
*                 Second world coordinate with diagonal grid lines.
                  L = L + 202
               END IF
            ELSE IF (SI(2).GT.0.5D0) THEN
*              Second world coordinate with vertical grid lines.
               IF (NI(2,1).GT.1 .OR. NI(2,1).GT.NI(2,3)) THEN
                  L = 1012
               ELSE
                  L = 1210
               END IF
            ELSE IF (SI(2).LT.-0.5D0) THEN
*              Second world coordinate with horizontal grid lines.
               IF (NI(2,2).GT.1 .OR. NI(2,2).GT.NI(2,4)) THEN
                  L = 121
               ELSE
                  L = 2101
               END IF
            ELSE
*              Desperation stakes!  Label all four axes.
               K1 = NI(1,3) + NI(1,1)
               K2 = NI(2,4) + NI(2,2)
               L = 2121

               M1 = NI(1,4) + NI(1,1)
               M2 = NI(2,3) + NI(2,2)
               IF (M1.GE.K1 .AND. M2.GE.K2) THEN
                  L  = 1221
                  K1 = M1
                  K2 = M2
               END IF

               M1 = NI(1,2) + NI(1,1)
               M2 = NI(2,4) + NI(2,3)
               IF (M1.GE.K1 .AND. M2.GE.K2) THEN
                  L  = 2211
                  K1 = M1
                  K2 = M2
               END IF

               M1 = NI(1,4) + NI(1,2)
               M2 = NI(2,3) + NI(2,1)
               IF (M1.GE.K1 .AND. M2.GE.K2) THEN
                  L  = 1212
                  K1 = M1
                  K2 = M2
               END IF

               M1 = NI(1,3) + NI(1,2)
               M2 = NI(2,4) + NI(2,1)
               IF (M1.GE.K1 .AND. M2.GE.K2) THEN
                  L  = 2112
                  K1 = M1
                  K2 = M2
               END IF

               M1 = NI(1,4) + NI(1,3)
               M2 = NI(2,2) + NI(2,1)
               IF (M1.GE.K1 .AND. M2.GE.K2) THEN
                  L  = 1122
                  K1 = M1
                  K2 = M2
               END IF
d1821 2
a1822 1
         END IF
d1825 14
a1838 5
*     Extract the information in a more usable form.
      SKIP(1) = MOD(L,10)
      SKIP(2) = MOD(L/10,10)
      SKIP(3) = MOD(L/100,10)
      SKIP(4) = MOD(L/1000,10)
d1847 21
a1867 3
         OMAG(1) = 0.0
         OMAG(2) = 0.0
         DO 120 J = 1, IC
d1869 3
a1871 21
            IF (FTYPE(IWRLD).EQ.' ') THEN
*              Plain numeric.
               IF (CACHE(4,J).EQ.0D0) GO TO 120
               OMAG(IWRLD) = OMAG(IWRLD) + LOG10(ABS(CACHE(4,J)))
               IMAG(IWRLD) = IMAG(IWRLD) + 1
            END IF
 120     CONTINUE

         IF (IMAG(1).GT.0) IMAG(1) = INT(OMAG(1)/IMAG(1))
         IF (IMAG(1).GE.-2 .AND. IMAG(1).LE.4) IMAG(1) = 0

         IF (IMAG(2).GT.0) IMAG(2) = INT(OMAG(2)/IMAG(2))
         IF (IMAG(2).GE.-2 .AND. IMAG(2).LE.4) IMAG(2) = 0

*        Renormalize grid values.
         IF (IMAG(1).NE.0 .OR. IMAG(2).NE.0) THEN
            DO 130 J = 1, IC
               IWRLD = NINT(CACHE(3,J))
               CACHE(4,J) = CACHE(4,J)/10D0**IMAG(IWRLD)
 130        CONTINUE
         END IF
d1879 38
a1916 11
         LMAG(1) = -2
         LMAG(2) = -2

         DO 150 J = 1, IC
*           Skip non-sexagesimal coordinates.
            IWRLD = NINT(CACHE(3,J))
            IF (.NOT.SEXA(IWRLD)) GO TO 150

*           Defeat rounding errors.
            IF (FTYPE(IWRLD).EQ.'y') THEN
               TMP = ABS(MOD(CACHE(4,J),1D0)*86400D0) + 5D-7
d1918 1
a1918 1
               TMP = ABS(CACHE(4,J)*3600D0) + 5D-7
d1920 1
d1922 37
a1958 20
            LS = INT(TMP)
            LV = INT(MOD(TMP, 1D0)*1D6)
            IF (LV.NE.0) THEN
*              Sub-arcsec/second resolution.
               M = 1
               DO 140 K = 1, 6
                  M = M*10
                  IF (MOD(LV,M).NE.0) THEN
                     LMAG(IWRLD) = MAX(LMAG(IWRLD), 7-K)
                     GO TO 150
                  END IF
 140           CONTINUE
            ELSE IF (LMAG(IWRLD).LT.0) THEN
               IF (MOD(LS,60).NE.0) THEN
                  LMAG(IWRLD) = MAX(LMAG(IWRLD), 0)
               ELSE IF (MOD(LS,3600).NE.0) THEN
                  LMAG(IWRLD) = MAX(LMAG(IWRLD), -1)
               END IF
            END IF
 150     CONTINUE
d1991 103
a2093 202
      DO 230 J = 1, IC
*        Determine the position.
         IWRLD = NINT(CACHE(3,J))
         CALL PGSCI (CI(IWRLD+2))

         EDGE = NINT(CACHE(1,J))
         IF (EDGE.NE.PRVEDG) THEN
*           Start of new edge.

            IF (SEXA(1) .OR. SEXA(2)) THEN
*              Sexagesimal field suppression policy.
               PRVDEG(1) = -1
               PRVMIN(1) = -1
               PRVDEG(2) = -1
               PRVMIN(2) = -1

               SEXSUP(1) = 0
               SEXSUP(2) = 0

*              Vertical sides.
               IF (MOD(NINT(CACHE(1,J)),2).EQ.0) THEN
                  DO 160 K = J, IC
                     IF (NINT(CACHE(1,K)).NE.EDGE) GO TO 170

                     KWRLD = NINT(CACHE(3,K))
                     IF (SEXSUP(KWRLD).EQ.1) GO TO 160

                     IF (FTYPE(KWRLD).EQ.'y') THEN
                        TMP = ABS(MOD(CACHE(4,K),1D0)*24D0)
                     ELSE
                        TMP = ABS(CACHE(4,K))
                     END IF

                     LV = INT(TMP*3600D0 + 5D-7)
                     LD =  LV/3600
                     LM = (LV - LD*3600)/60
                     LS =  LV - LD*3600 - LM*60
                     TMP = TMP - LD

                     IF (TMP.LT.5D-7) THEN
*                       Write deg/hr field only when min/sec are zero.
                        SEXSUP(KWRLD) = 1
                     ELSE IF (TMP*60-LM.LT.3D-5) THEN
*                       Write min field only when sec is zero; only
*                       write the deg/hr field when min is written.
                        SEXSUP(KWRLD) = 2
                     END IF
 160              CONTINUE
               END IF
            END IF
 170        CONTINUE

            PRVYR(1) = -1
            PRVYR(2) = -1

            XL = -999.0
            YL = -999.0
         END IF
         PRVEDG = EDGE
         LFORCE = .FALSE.

         IF (EDGE.EQ.1) THEN
*           Bottom.
            IF (IWRLD.EQ.1) THEN
               IF (MOD(SKIP(1),2).NE.1) GO TO 230
            ELSE
               IF (MOD(SKIP(1)/2,2).NE.1) GO TO 230
            END IF

            FJUST = 0.5
            X = CACHE(2,J)
            Y = YW1 - 1.5*YCH
         ELSE IF (EDGE.EQ.2) THEN
*           Left.
            IF (IWRLD.EQ.1) THEN
               IF (MOD(SKIP(2),2).NE.1) GO TO 230
            ELSE
               IF (MOD(SKIP(2)/2,2).NE.1) GO TO 230
            END IF

            FJUST = 1.0
            X = XW1 - 0.5*XCH
            Y = CACHE(2,J) - YCH/2.0
         ELSE IF (EDGE.EQ.3) THEN
*           Top.
            IF (IWRLD.EQ.1) THEN
               IF (MOD(SKIP(3),2).NE.1) GO TO 230
            ELSE
               IF (MOD(SKIP(3)/2,2).NE.1) GO TO 230
            END IF

            FJUST = 0.5
            X = CACHE(2,J)
            Y = YW2 + 0.5*YCH
         ELSE IF (EDGE.EQ.4) THEN
*           Right.
            IF (IWRLD.EQ.1) THEN
               IF (MOD(SKIP(4),2).NE.1) GO TO 230
            ELSE
               IF (MOD(SKIP(4)/2,2).NE.1) GO TO 230
            END IF

            FJUST = 0.0
            X = XW2 + 0.5*XCH
            Y = CACHE(2,J) - YCH/2.0
         END IF

*        Format the numeric label.
         IF (INDEX('ABC', FTYPE(IWRLD)).NE.0) THEN
*           Decimal angle; allow up to 6 decimal digits.
            TMP = ABS(CACHE(4,J)) + 5D-7
            LD  = INT(TMP)

            K = 1
            IF (CACHE(4,J).LT.0D0) THEN
*              Insert a minus sign.
               TEXT(1:1) = '-'
               K = 2
            END IF

            CALL PGNUMB (LD, 0, 1, TEXT(K:), NCH)
            K = K + NCH
            TEXT(K:) = ESCAPE // 'uo' // ESCAPE // 'd'
            K = K + 4

            LV = INT(MOD(TMP,1D0)*1D6)
            IF (LV.NE.0) CALL PGNUMB (LV, -6, 1, TEXT(K:), NCH)
            TEXT(K:K) = 'd'

         ELSE IF (SEXA(IWRLD)) THEN
*           Sexagesimal format; angle or time?
            ANGLE = INDEX('DEF', FTYPE(IWRLD)).NE.0
            L = LMAG(IWRLD)

*           Use integer arithmetic to avoid rounding problems.
            IF (FTYPE(IWRLD).EQ.'y') THEN
               TMP = ABS(MOD(CACHE(4,J),1D0)*24D0)

*              Determine date range.
               IF (CACHE(4,J).LT.MJD1(IWRLD)) MJD1(IWRLD) = CACHE(4,J)
               IF (CACHE(4,J).GT.MJD2(IWRLD)) MJD2(IWRLD) = CACHE(4,J)
            ELSE
               TMP = ABS(CACHE(4,J))
            END IF
            VS = TMP*3600D0 + 5D-7
            LV = INT(VS)

*           Sexagesimal fields.
            LD =  LV/3600
            LM = (LV - LD*3600)/60
            LS =  LV - LD*3600 - LM*60

*           Field suppression policy.
            IF (SEXSUP(IWRLD).GT.0) THEN
               TMP = TMP - LD

               IF (TMP.LT.5D-7) THEN
                 DODEG = .TRUE.
                 DOMIN = .TRUE.
               ELSE IF (SEXSUP(IWRLD).EQ.2) THEN
                 DOMIN = TMP*60-LM.LT.3D-5
                 DODEG = DOMIN .AND. LD.NE.PRVDEG(IWRLD)
               ELSE
                 DODEG = .FALSE.
                 DOMIN = .FALSE.
               END IF
            ELSE
               DODEG = LD.NE.PRVDEG(IWRLD)
               DOMIN = LM.NE.PRVMIN(IWRLD)
            END IF

            K = 1
            IF (L.EQ.-2 .OR. DODEG) THEN
*              Write the degree/hour field.
               DODEG = .TRUE.

               IF (CACHE(4,J).LT.0D0) THEN
*                 Insert a minus sign.
                  TEXT(1:1) = '-'
                  K = 2
               END IF

               IF (ANGLE) THEN
*                 Angle.
                  CALL PGNUMB (LD, 0, 1, TEXT(K:), NCH)
                  K = K + NCH
                  TEXT(K:) = ESCAPE // 'uo' // ESCAPE // 'd'
                  K = K + 5
               ELSE
*                 Time.
                  IF (LD.LE.9 .AND. INDEX('Ty',FTYPE(IWRLD)).EQ.0) THEN
*                    Write leading zeroes in the hour field.
                     WRITE (TEXT(K:), '(I2.2)') LD
                     K = K + 2
                  ELSE
                     CALL PGNUMB (LD, 0, 1, TEXT(K:), NCH)
                     K = K + NCH
                  END IF
                  TEXT(K:) = ESCAPE // 'uh' // ESCAPE // 'd'
                  K = K + 5
               END IF
            END IF
d2095 42
a2136 49
            IF (L.GE.-1) THEN
*              Write arcminute/minute field.

               IF (L.EQ.-1 .OR. K.GT.1 .OR. DOMIN) THEN
                  DOMIN = .TRUE.
                  IF (ANGLE) THEN
                     WRITE (TEXT(K:), '(I2.2,A)') LM, ''''
                     K = K + 3
                  ELSE
                     WRITE (TEXT(K:), '(I2.2,A)') LM,
     :                  ESCAPE // 'um' // ESCAPE // 'd'
                     K = K + 7
                  END IF
               END IF

               IF (L.GE.0) THEN
*                 Arcsec/second field.
                  IF (ANGLE) THEN
                     WRITE (TEXT(K:), '(I2.2,A)') LS, '"'
                     K = K + 3
                  ELSE
                     WRITE (TEXT(K:), '(I2.2,A)') LS,
     :                  ESCAPE // 'us' // ESCAPE // 'd'
                     K = K + 7
                  END IF

                  IF (L.GT.0) THEN
*                    Sub-arcsec/second field.
                     WRITE (FMT, '(A,I1,A,I1,A)') '(A,I', L, '.', L, ')'
                     LV = INT(MOD(VS,1D0)*10**L)
                     WRITE (TEXT(K:), FMT) '.', LV
                  END IF
               END IF
            END IF

         ELSE IF (FTYPE(IWRLD).EQ.'L') THEN
*           Logarithmic.
            TMP = MOD(CACHE(4,J),1D0)
            IF (TMP.LT.0D0) TMP = TMP + 1D0
            MM = NINT(10D0**TMP)
            IF (MM.EQ.10) THEN
               TMP = TMP - 1D0
               MM = 1
            END IF

            PP = NINT(CACHE(4,J) - TMP)

            IF (MM.NE.1) THEN
               WRITE (TEXT, '(I1)') MM
d2138 2
a2139 8
*              FORTRAN is really abysmal sometimes.
               WRITE (TEXT, '(I8)') PP
               DO 180 K = 1, 8
                  IF (TEXT(K:K).NE.' ') GO TO 190
 180           CONTINUE
 190           TEXT = '10' // ESCAPE // 'u' // TEXT(K:8)

               LFORCE = .TRUE.
d2141 9
d2151 4
a2154 17
         ELSE IF (FTYPE(IWRLD).EQ.'Y') THEN
*           Convert MJD to Gregorian calendar date, YYYY/MM/DD.
            CALL PGMJD(0, CACHE(4,J), IY, IM, ID)
            DOYEAR = IY.NE.PRVYR(IWRLD)

            IF (DOYEAR) THEN
               WRITE (TEXT, 200) IY, IM, ID
 200           FORMAT (I12,'/',I2.2,'/',I2.2)

               DO 210 K = 1, 12
                  IF (TEXT(K:K).NE.' ') GO TO 220
 210           CONTINUE
 220           TEXT = TEXT(K:18)

            ELSE
               WRITE (TEXT, 225) IM, ID
 225           FORMAT (I2.2,'/',I2.2)
d2157 6
a2162 5
         ELSE
*           Plain number; allow up to six significant digits.
            IF (CACHE(4,J).NE.0D0) THEN
               PP = INT(LOG10(ABS(CACHE(4,J)))) - 6
               MM = NINT(CACHE(4,J)/10D0**PP)
d2164 70
a2233 30
               PP = 0
               MM = 0
            END IF

            CALL PGNUMB (MM, PP, 0, TEXT, NCH)
         END IF

*        Write the label if it doesn't overlap the previous one.
         CALL PGQTXT (X, Y, 0.0, FJUST, TEXT, XBOX, YBOX)
         IF (LFORCE .OR. XBOX(1).GT.XL .OR. YBOX(1).GT.YL) THEN
            IF (IWRLD.EQ.1) THEN
               CALL PGSCI (CI(3))
            ELSE
               CALL PGSCI (CI(4))
            END IF

            CALL PGPTXT (X, Y, 0.0, FJUST, TEXT)
            XL = XBOX(4) + 0.5*XCH
            YL = YBOX(2) + 0.5*YCH

*           Sexagesimal formatting.
            IF (SEXA(IWRLD)) THEN
               IF (DODEG) PRVDEG(IWRLD) = LD
               IF (DOMIN) PRVMIN(IWRLD) = LM
            END IF

*           Calendar formatting.
            IF (FTYPE(IWRLD).EQ.'Y') THEN
               IF (DOYEAR) PRVYR(IWRLD) = IY
            END IF
d2235 2
a2236 35
*           Record the fact.
            IF (IWRLD.EQ.1) THEN
               SKOP(EDGE) = 2*(SKOP(EDGE)/2) + 1
            ELSE
               SKOP(EDGE) = 2 + MOD(SKOP(EDGE),2)
            END IF

*           Boundary within which the numeric labels lie.
            IF (YBOX(1).LT.BNDRY(1)) BNDRY(1) = YBOX(1)
            IF (XBOX(1).LT.BNDRY(2)) BNDRY(2) = XBOX(1)
            IF (YBOX(3).GT.BNDRY(3)) BNDRY(3) = YBOX(3)
            IF (XBOX(3).GT.BNDRY(4)) BNDRY(4) = XBOX(3)

*           Check the distance to the previous grid line.
            TICKIT = .FALSE.
            IF (J.GT.1) THEN
               IF (CACHE(1,J).EQ.CACHE(1,J-1)) THEN
                  IF (EDGE.EQ.1 .OR. EDGE.EQ.3) THEN
                     TICKIT = XBOX(1).LT.CACHE(2,J-1)
                  ELSE
                     TICKIT = YBOX(1).LT.CACHE(2,J-1)
                  END IF
               END IF
            END IF

*           Check the distance to the next grid line.
            IF (J.LT.IC) THEN
               IF (CACHE(1,J).EQ.CACHE(1,J+1)) THEN
                  IF (EDGE.EQ.1 .OR. EDGE.EQ.3) THEN
                     TICKIT = XBOX(2).GT.CACHE(2,J+1)
                  ELSE
                     TICKIT = YBOX(2).GT.CACHE(2,J+1)
                  END IF
               END IF
            END IF
d2238 132
a2369 20
*           Density of grid lines is high.
            IF (TICKIT) THEN
*              Draw outside pip mark.
               Z = REAL(CACHE(2,J))
               IF (EDGE.EQ.1) THEN
                  CALL PGMOVE (Z, YW1-0.3*YCH)
                  CALL PGDRAW (Z, YW1)
               ELSE IF (EDGE.EQ.2) THEN
                  CALL PGMOVE (XW1-0.3*XCH, Z)
                  CALL PGDRAW (XW1, Z)
               ELSE IF (EDGE.EQ.3) THEN
                  CALL PGMOVE (Z, YW2+0.3*YCH)
                  CALL PGDRAW (Z, YW2)
               ELSE IF (EDGE.EQ.4) THEN
                  CALL PGMOVE (XW2+0.3*XCH, Z)
                  CALL PGDRAW (XW2, Z)
               END IF
            END IF
         END IF
 230  CONTINUE
d2374 2
a2375 2
      DO 360 EDGE = 1, 4
         TEXT = ' '
d2377 2
a2378 2
         DO 330 IWRLD = 1, 2
            TXT(IWRLD) = ' '
d2380 1
a2380 1
            IF (MOD(SKOP(EDGE)/IWRLD,2).EQ.0) GO TO 330
d2382 23
a2404 8
*           Strip off leading blanks.
            L = LEN(IDENTS(IWRLD))
            DO 240 K = 1, L
               IF (IDENTS(IWRLD)(K:K).NE.' ') THEN
                  TXT(IWRLD) = IDENTS(IWRLD)(K:L)
                  GO TO 250
               END IF
 240        CONTINUE
d2406 14
a2419 35
 250        IF (IMAG(IWRLD).NE.0 .OR. FTYPE(IWRLD).EQ.'y') THEN
*              Find the last non-blank.
               DO 260 K = 40, 1, -1
                  IF (TXT(IWRLD)(K:K).NE.' ') GO TO 270
 260           CONTINUE
 270           K = K + 1

               IF (IMAG(IWRLD).NE.0) THEN
*                 Add scaling information.
                  CALL PGNUMB (IMAG(IWRLD), 0, 1, EXPONT, NCH)
                  TXT(IWRLD)(K:) = '  x10' // ESCAPE // 'u' // EXPONT
               ELSE
*                 Add calendar date range.
                  CALL PGMJD(0, MJD1(IWRLD), IY, IM, ID)

                  WRITE (TEXT, 280) IY, IM, ID
 280              FORMAT (I12,'/',I2.2,'/',I2.2)
                  DO 290 L = 1, 12
                     IF (TEXT(L:L).NE.' ') GO TO 300
 290              CONTINUE
 300              TXT(IWRLD)(K:) = ' (' // TEXT(L:18)
                  K = K + 21 - L

                  CALL PGMJD(0, MJD2(IWRLD), IY2, IM2, ID2)
                  WRITE (TEXT, 280) IY2, IM2, ID2
                  IF (IY2.EQ.IY) THEN
                     IF (IM2.EQ.IM) THEN
                        IF (ID2.EQ.ID) THEN
                           TXT(IWRLD)(K:) = ')'
                        ELSE
                           TXT(IWRLD)(K:) = ' - ' // TEXT(17:18) // ')'
                        END IF
                     ELSE
                        TXT(IWRLD)(K:) = ' - ' // TEXT(14:18) // ')'
                     END IF
d2421 1
a2421 4
                     DO 310 L = 1, 12
                        IF (TEXT(L:L).NE.' ') GO TO 320
 310                 CONTINUE
 320                 TXT(IWRLD)(K:) = ' - ' // TEXT(L:18) // ')'
d2423 47
a2469 32
               END IF
            END IF

 330     CONTINUE

         K = 0
         IF (TXT(1).NE.' ') THEN
*           Identify first world coordinate...
            TEXT = TXT(1)
            CALL PGSCI (CI(5))

            IF (TXT(2).NE.' ') THEN
*              ...and also second world coordinate.
               DO 340 K = 40, 1, -1
                  IF (TEXT(K:K).NE.' ') GO TO 350
 340           CONTINUE
 350           K = K + 1

               TEXT(K:) = ',  ' // TXT(2)
            END IF
         ELSE IF (TXT(2).NE.' ') THEN
*           Identify second world coordinate only.
            TEXT = TXT(2)
            CALL PGSCI (CI(6))
         ELSE
*           No text to write.
            GO TO 360
         END IF

         IF (EDGE.EQ.1) THEN
            X = (XW1 + XW2)/2.0
            Y = BNDRY(1) - 1.5*YCH
d2471 14
a2484 14
         ELSE IF (EDGE.EQ.2) THEN
            IF (TEXT(2:).EQ.' ') THEN
*              One character, write upright.
               X = BNDRY(2) - 1.0*XCH
               Y = (YW1 + YW2)/2.0
               ANGL = 0.0
            ELSE
               X = BNDRY(2) - 0.5*XCH
               Y = (YW1 + YW2)/2.0
               ANGL = 90.0
            END IF
         ELSE IF (EDGE.EQ.3) THEN
            X = (XW1 + XW2)/2.0
            Y = BNDRY(3) + 0.5*YCH
d2486 27
a2512 33
         ELSE IF (EDGE.EQ.4) THEN
            IF (TEXT(2:).EQ.' ') THEN
*              One character, write upright.
               X = BNDRY(4) + 1.0*XCH
               Y = (YW1 + YW2)/2.0
               ANGL = 0.0
            ELSE
               X = BNDRY(4) + 0.5*XCH
               Y = (YW1 + YW2)/2.0
               ANGL = -90.0
            END IF
         END IF

         CALL PGQTXT (X, Y, ANGL, 0.5, TEXT, XBOX, YBOX)
         IF (K.EQ.0) THEN
            CALL PGPTXT (X, Y, ANGL, 0.5, TEXT)
         ELSE
*           Two-colour annotation.
            CALL PGPTXT (XBOX(1), YBOX(1), ANGL, 0.0, TEXT(:K))
            CALL PGSCI (CI(6))
            CALL PGPTXT (XBOX(4), YBOX(4), ANGL, 1.0, TEXT(K+1:))
         END IF

*        Update the boundary.
         IF (YBOX(1).LT.BNDRY(1)) BNDRY(1) = YBOX(1)
         IF (YBOX(3).LT.BNDRY(1)) BNDRY(1) = YBOX(3)
         IF (XBOX(1).LT.BNDRY(2)) BNDRY(2) = XBOX(1)
         IF (XBOX(3).LT.BNDRY(2)) BNDRY(2) = XBOX(3)
         IF (YBOX(1).GT.BNDRY(3)) BNDRY(3) = YBOX(1)
         IF (YBOX(3).GT.BNDRY(3)) BNDRY(3) = YBOX(3)
         IF (XBOX(1).GT.BNDRY(4)) BNDRY(4) = XBOX(1)
         IF (XBOX(3).GT.BNDRY(4)) BNDRY(4) = XBOX(3)
 360  CONTINUE
d2516 10
a2525 10
         CALL PGSCI (CI(7))
         X = (XW1 + XW2)/2.0
         Y = BNDRY(3) + 0.5*YCH
         CALL PGQTXT (X, Y, 0.0, 0.5, IDENTS(3), XBOX, YBOX)
         CALL PGPTXT (X, Y, 0.0, 0.5, IDENTS(3))

*        Update the boundary.
         IF (XBOX(1).LT.BNDRY(2)) BNDRY(2) = XBOX(1)
         IF (YBOX(3).GT.BNDRY(3)) BNDRY(3) = YBOX(3)
         IF (XBOX(3).GT.BNDRY(4)) BNDRY(4) = XBOX(3)
d2528 1
d2541 1
a2541 1
*   MJD to/from Gregorian calendar date.
d2543 16
a2558 17
*   Given:
*      CODE     I        If 1, compute MJD from IY,IM,ID, else vice
*                        versa.
*
*   Given and/or returned:
*      MJD      D        Modified Julian date, (MJD = JD - 2400000.5).
*      IY       I        Year.
*      IM       I        Month (for CODE.EQ.1 may exceed 12, or be zero,
*                        or negative).
*      ID       I        Day of month (for CODE.EQ.1, may exceed the
*                        legitimate number of days in the month, or be
*                        zero, or negative).
*
*   Notes:
*    1) These algorithms are from D.A. Hatcher, QJRAS 25, 53-55, as
*       modified by P.T. Wallace for use in SLALIB (subroutines CLDJ
*       and DJCL).
d2568 13
a2580 13
*        Calendar date to MJD.
         IF (IM.LT.1) THEN
            JY = IY - 1 + IM/12
            JM = 12 + MOD(IM,12)
         ELSE
            JY = IY + (IM-1)/12
            JM = MOD(IM-1,12) + 1
         END IF

         MJD =DBLE((1461*(JY - (12-JM)/10 + 4712))/4
     :            +(306*MOD(JM+9, 12) + 5)/10
     :            -(3*((JY - (12-JM)/10 + 4900)/100))/4
     :            + ID - 2399904)
d2583 2
a2584 2
*        MJD to calendar date.
         JD = 2400001 + INT(MJD)
d2586 2
a2587 2
         N4 =  4*(JD + ((2*((4*JD - 17918)/146097)*3)/4 + 1)/2 - 37)
         DD = 10*(MOD(N4-237, 1461)/4) + 5
d2589 3
a2591 3
         IY = N4/1461 - 4712
         IM = MOD(2 + DD/306, 12) + 1
         ID = MOD(DD, 306)/10 + 1
d2600 2
a2601 2
*   This FORTRAN wrapper on PGSBOX exists solely to define fixed-length
*   CHARACTER arguments for cpgsbox().
d2603 1
a2603 1
*   Author: Mark Calabretta, Australia Telescope National Facility
d2606 2
a2607 2
     :   GCODE, TIKLEN, NG1, GRID1, NG2, GRID2, DOEQ, NLFUNC, NLC, NLI,
     :   NLD, NLCPRM, NLIPRM, NLDPRM, NC, IC, CACHE, IERR)
d2620 2
a2621 2
     :   TIKLEN, NG1, GRID1, NG2, GRID2, DOEQ, NLFUNC, NLC, NLI, NLD,
     :   NLCPRM, NLIPRM, NLDPRM, NC, IC, CACHE, IERR)
d2629 2
a2630 2
*   This FORTRAN wrapper on PGLBOX exists solely to define fixed-length
*   CHARACTER arguments for cpglbox().
d2632 1
a2632 1
*   Author: Mark Calabretta, Australia Telescope National Facility
d2635 1
a2635 1
     :   NG1, GRID1, NG2, GRID2, DOEQ, NC, IC, CACHE, IERR)
d2643 1
a2643 1
     :   GRID1, NG2, GRID2, DOEQ, NC, IC, CACHE, IERR)
@


4.3.1.1
log
@PGSBOX 4.3 development branch.
@
text
@d3 2
a4 2
*   PGSBOX 4.4 - an implementation of the FITS WCS standard.
*   Copyright (C) 1997-2008, Mark Calabretta
d31 1
a31 1
*   $Id: pgsbox.f,v 4.3 2007/12/27 05:49:14 cal103 Exp cal103 $
@


4.3.1.2
log
@Changed indentation.
@
text
@d3 2
a4 2
* PGSBOX 4.4 - draw curvilinear coordinate axes for PGPLOT.
* Copyright (C) 1997-2009, Mark Calabretta
d6 1
a6 1
* This file is part of PGSBOX.
d8 24
a31 24
* PGSBOX is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PGSBOX is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with PGSBOX.  If not, see http://www.gnu.org/licenses.
*
* Correspondence concerning PGSBOX may be directed to:
*   Internet email: mcalabre@@atnf.csiro.au
*   Postal address: Dr. Mark Calabretta
*                   Australia Telescope National Facility, CSIRO
*                   PO Box 76
*                   Epping NSW 1710
*                   AUSTRALIA
*
* Author: Mark Calabretta, Australia Telescope National Facility
* http://www.atnf.csiro.au/~mcalabre/index.html
* $Id: pgsbox.f,v 4.3.1.1 2007/12/27 13:26:31 cal103 Exp cal103 $
d34 317
a350 313
* PGSBOX draws and labels a curvilinear coordinate grid.  The caller
* must provide a separate external function, NLFUNC, to define the
* non-linear coordinate transformation.
*
* PGLBOX, a simplified ENTRY point to PGSBOX, has been provided for
* drawing simple linear axes without the need to specify NLFUNC.
* PGLBOX allows simplified access to formatting control for labelling
* world coordinate axes that is not provided by the standard PGPLOT
* routines, PGBOX or PGTBOX.  PGLBOX uses the world coordinate range
* set by a prior call to PGSWIN and omits the following arguments:
*
*   BLC, TRC, NLFUNC, NLC, NLI, NLD, NLCPRM, NLIPRM, NLDPRM
*
* The remaining arguments are specified in the same order as PGSBOX.
*
* Given:
*   BLC       R(2)      Cartesian coordinates of the bottom left-hand
*   TRC       R(2)      corner and top right-hand corner of the frame.
*                       Any convenient Cartesian system may be used in
*                       conjunction with the non-linear transformation
*                       function, NLFUNC, described below.
*
*                       For example, FITS images have pixel coordinate
*                       (1,1) at the centre of the pixel in the bottom
*                       left-hand corner.  Thus it would be
*                       appropriate to set BLC to (0.5,0.5) and TRC to
*                       (NAXIS1+0.5, NAXIS2+0.5).
*
*   IDENTS    C(3)*(*)  Identification strings:
*                         1: Name of the first world coordinate
*                            element used for axis labelling.
*                         2: Name of the second world coordinate.
*                         3: Title, written at top.
*
*   OPT       C(2)*(*)  Formatting control for the world coordinates,
*                       used for axis labelling (see notes 1 and 2):
*                         ' ': plain numeric
*                         'A': angle in degrees expressed in decimal
*                              notation normalized in the range [0,360).
*                         'B': as 'A' but normalized in the range
*                              (-180,180].
*                         'C': as 'A' but unnormalized.
*                         'D': angle in degrees expressed in sexagesimal
*                              notation, DD^MM'SS".S, normalized in the
*                              range [0,360).
*                         'E': as 'D' but normalized in the range
*                              (-180,180].
*                         'F': as 'D' but unnormalized.
*                         'G': angle in degrees expressed in hms
*                              notation, HHhMMmSSs.S, normalized in the
*                              range [0,24) hours.
*                         'H': as 'G' but normalized in the range
*                              (-12,12] hours.
*                         'I': as 'G' but unnormalized.
*                         'L': logarithmic (see note 2)
*                         'T': time in hours expressed as HH:MM:SS.S
*                         'Y': Modified Julian Date to be expressed as
*                              a Gregorian calendar date, YYYY/MM/DD.
*                              (MJD = JD - 2400000.5.)
*
*                       For the angular types, NLFUNC is assumed to
*                       return the angle in degrees whereupon it will
*                       be formatted for display in the specified way.
*                       For example, an angle of -417.2958 degrees
*                       (returned by NLFUNC):
*
*                         'A':  302^.7042
*                         'B':  -57^.2958
*                         'C': -417^.2958
*                         'D':  302^42'15"
*                         'E':  -57^17'45"
*                         'F': -417^17'45"
*                         'H':   20h10m49s
*                         'I':   -3h49m11s
*                         'J':  -27h49m11s
*
*                       These are properly superscripted.
*
*   LABCTL    I         Decimal encoded grid labelling control:
*                            -1: Accumulate information on grid labels
*                                (see note 3) but do not write them.
*                             0: Let PGSBOX decide what edges to label.
*                             1: Label bottom of frame with the first
*                                world coordinate.
*                             2: Label bottom of frame with the second
*                                world coordinate.
*                            10: ... left side of frame.
*                            20: ... left side of frame.
*                           100: ... top of frame.
*                           200: ... top of frame.
*                          1000: ... right side of frame.
*                          2000: ... right side of frame.
*                         10000: Write labels from information
*                                accumulated in previous calls without
*                                drawing grid lines or tick marks.
*
*                       LABCTL = 0 usually gets what you want.
*                       LABCTL = 3333 labels all sides with both world
*                       coordinates.
*
*   LABDEN    I         Decimal encoded labelling density control for
*                       use where PGSBOX is called upon to determine a
*                       suitable grid spacing (e.g. via NG1 = 0,
*                       GRID1(0) = 0).  LABDEN = 100*D2 + D1 where
*                       D1, and D2 are the approximate number of grid
*                       lines for the first and second world
*                       coordinate.  LABDEN = 0 is effectively the same
*                       as LABDEN = 808.
*
*   CI        I(7)      Table of predefined colours established by
*                       calls to PGSCR.  This is used to control the
*                       colour used for different parts of the plot.
*                       CI table entries are used as follows:
*
*                                                world
*                                              coordinate
*                       Index      usage        element
*                       -----  --------------  ----------
*                         1      grid lines        1
*                         2      grid lines        2
*                         3    numeric labels      1
*                         4    numeric labels      2
*                         5    axis annotation     1
*                         6    axis annotation     2
*                         7        title           -
*
*                       For example, CI(3) is used for numeric labels
*                       for the first world coordinate.
*
*                       Colour selection is disabled for component J
*                       if CI(J) < 0.
*
*   GCODE(2)  I         Code for the type of grid to draw for each
*                       world coordinate:
*                         0: No grid or tick marks.
*                         1: Tick marks (on all edges).
*                         2: Full coordinate grid.
*
*                       Tick marks can be restricted to particular
*                       edges of the frame; a negative GCODE is
*                       interpreted as a decimal encoded control
*                       variable:
*                            -1: bottom
*                           -10: left
*                          -100: top
*                         -1000: right
*
*                       The digit scales the basic tick length.  For
*                       example, GCODE(1) = -102 restricts tick marks
*                       for the first world coordinate to the bottom
*                       and top edges of the frame.  Those on the
*                       bottom will be twice the length specified by
*                       TIKLEN.
*
*   TIKLEN    D         Tick length, in mm.  Negative values produce
*                       outside tick marks.
*
*   NG1       I         Upper array index for GRID1.
*
*   GRID1     D(0:NG1)  Grid values in WORLD(1) in the same units as
*                       returned by NLFUNC.
*
*                       If NG1 is zero, then
*                         a: if GRID1(0) is greater than zero it
*                            defines a uniform grid spacing.
*                         b: if GRID1(0) is zero a suitable spacing
*                            will be determined (see LABDEN).
*                         c: if GRID1(0) is less than zero then no
*                            grid lines will be drawn.
*
*                       If NG1 is greater than zero, then GRID1(0) is
*                       ignored.
*
*   NG2       I         Upper array index for GRID2.
*
*   GRID2     D(0:NG2)  Grid values in WORLD(2) in the same units as
*                       returned by NLFUNC, interpreted the same way
*                       as GRID1.
*
*   DOEQ      L         If NG1 = NG2 = 0, and GRID1(0) = 0D0 and/or
*                       GRID2(0) = 0D0, then choose the same grid
*                       spacing for each world coordinate.
*
*   NLFUNC    Ext       Non-linear coordinate function, see below.
*
*   NLC       I         Number of elements in NLCPRM (must be >0).
*
*   NLI       I         Number of elements in NLIPRM (must be >0).
*
*   NLD       I         Number of elements in NLDPRM (must be >0).
*
* Given and/or returned:
*   NLCPRM    C(NLC)*1  Character coefficients for NLFUNC.
*
*   NLIPRM    I(NLI)    Integer coefficients for NLFUNC.
*
*   NLDPRM    D(NLD)    Double precision coefficients for NLFUNC.
*
*   NC        I         Upper array index for CACHE (see note 3).
*
*   IC        I         Current number of entries in the CACHE table.
*                       Should be set to -1 on the first call to
*                       PGSBOX (see note 3).
*
*   CACHE     D(4,0:NC) Table of points where the tick marks or grid
*                       lines cross the frame (see note 3).
*                         1: Frame segment
*                            1: bottom
*                            2: left
*                            3: top
*                            4: right
*                         2: X or Y-Cartesian coordinate.
*                         3: World coordinate element (1 or 2).
*                         4: Value.
*
*                       CACHE(,0) is used to cache the extrema of the
*                       coordinate values between calls.  CACHE(1,NC-1)
*                       is also used to store related information.
*
*                       CACHE(,NC) will contain the margin widths in
*                       Cartesian coordinates when the labels are
*                       produced (i.e. the same Cartesian system used
*                       for BLC and TRC).
*
* Returned:
*   IERR      I         Status return value:
*                         0: Success
*                         1: Initialization error
*                         2: Invalid coordinate system
*                         3: Cache overflow (see note 3).
*
* Notes:
*   1: Where a logarithmic world coordinate type is indicated PGSBOX
*      chooses grid lines and labels on the basis that the value
*      returned by NLFUNC is a base 10 logarithm.  PGSBOX does not
*      itself take logarithms or antilogarithms.  For example, if the
*      range of values returned by NLFUNC were 0.9 - 2.5, then PGSBOX
*      would draw a subset of the following set of grid lines and
*      labels:
*
*                 value          label
*          ------------------    -----
*          0.9031 = log10(8)      8
*          0.9542 = log10(9)      9
*          1.0000 = log10(10)    10**1
*          1.3010 = log10(20)     2
*          1.4771 = log10(30)     3
*          1.6021 = log10(40)     4
*          1.6990 = log10(50)     5
*          1.7782 = log10(60)     6
*          1.8451 = log10(70)     7
*          1.9031 = log10(80)     8
*          1.9542 = log10(90)     9
*          2.0000 = log10(100)   10**2
*          2.3010 = log10(200)    2
*          2.4771 = log10(300)    3
*
*      The subset chosen depends on the coordinate increment as
*      specified by the caller (e.g. via NG1 = 0, GRID1(0) != 0) or as
*      deduced by PGSBOX from the required density of grid lines
*      specified in the LABDEN argument.  The selection is made
*      according to the following table:
*
*          increment          grid lines
*         (0.00,0.12]   1, 2, 3, 4, 5, 6, 7, 8, 9
*         (0.12,0.18]   1, 2, 3, 4, 5,    7
*         (0.18,0.23]   1, 2, 3,    5,    7
*         (0.23,0.28]   1, 2, 3,    5
*         (0.28,0.40]   1, 2,       5
*         (0.40,0.70]   1, 3
*         (0.70,1.00]   1
*
*      For increments greater than 1 the nearest integer is used.
*
*   2: PGSBOX will attempt to handle discontinuities in angle, such as
*      may occur when cycling through 360 degrees, wherever the
*      discontinuity may occur, for example
*
*        359 -> 0 -> 1
*
*      or
*
*        179 -> 180 -> -179
*
*      Only single cycles are detected, so the sequence
*
*        -360 -> 0 -> ... -> 359 -> 0 -> ... -> 359
*
*      would not be handled properly.  In such cases NLFUNC should be
*      changed to return a normalized angle, or else a continuous
*      sequence.
*
*   3: PGSBOX maintains a table of axis crossings, CACHE, in which it
*      stores information used for axis labelling.  The caller need not
*      normally be concerned about the use of this table other than to
*      provide sufficient space.  Typically, NC = 256 should be enough;
*      if not, IERR = 3 will be returned.
*
*      However, a coordinate grid may be produced via multiple calls to
*      PGSBOX with deferment of axis labelling.  This might be done to
*      change the pen colour and/or thickness for different sets of
*      grid lines.  The table accumulates information from each
*      successive call until the labels are produced.  The table index,
*      IC, may be reset to zero by the caller to discard the
*      information collected.
*
*      The extrema of the world coordinate elements are stored in
*      CACHE(,0).  When a coordinate grid is plotted with multiple
*      calls to PGSBOX the initial call should always have IC set to -1
*      to signal that PGSBOX needs to determine the extrema.  On
*      subsequent calls with IC non-negative PGSBOX uses the extrema
*      cached from the first call.  This can speed up execution
*      considerably.
d354 2
a355 2
* The curvilinear coordinate grid is defined by external function
* NLFUNC whose interface is defined as follows:
d357 103
a459 102
* Given:
*   OPCODE    I         Transformation code:
*                         +2: Compute a set of Cartesian coordinates
*                             that describe a path between this and
*                             the previous pair of world coordinates
*                             remembered from the last call with
*                             OPCODE = +1 or +2.  Usually only takes
*                             a single step unless traversing a
*                             discontinuity or some other
*                             irregularity (see explanation below).
*                         +1: Compute Cartesian coordinates from world
*                             coordinates.
*                          0: Initialize.
*                         -1: Compute world coordinates from Cartesian
*                             coordinates.
*
*                       N.B. NLFUNC must not change the input
*                       coordinates; that is the world coordinates for
*                       OPCODEs = +2 and +1, or the Cartesian
*                       coordinates for OPCODE = -1.
*
*   NLC       I         Number of elements in NLCPRM (must be >0).
*
*   NLI       I         Number of elements in NLIPRM (must be >0).
*
*   NLD       I         Number of elements in NLDPRM (must be >0).
*
* Given and/or returned:
*   NLCPRM    C(NLC)*1  Character array.
*
*   NLIPRM    I(NLI)    Integer coefficients.
*
*   NLDPRM    D(NLD)    Double precision coefficients.
*
*   WORLD     D(2)      World coordinates.  Given if OPCODE > 0,
*                       returned if OPCODE < 0.
*
*   XY        D(2)      Cartesian coordinates.  Given if OPCODE < 0,
*                       returned if OPCODE > 0.
*
*   CONTRL    I         Control flag for OPCODE = +2:
*                         0: Normal state.
*                         1: Force PGSBOX to flush its plotting buffer
*                            and call NLFUNC again with the same world
*                            coordinates.
*                         2: Force PGSBOX to call NLFUNC again with
*                            the same world coordinates (without
*                            flushing its plotting buffer).
*
*   CONTXT    D(20)     Context elements for OPCODE = +2.
*
* Returned:
*   IERR      I         Status return value:
*                         0: Success.
*                         1: Invalid parameters.
*                         2: Invalid world coordinate.
*                         3: Invalid Cartesian coordinate.
*
*                       The following status returns are recognized for
*                       opcodes +2 and +1
*                         -1: Accept the returned (x,y) coordinates but
*                             do not consider this as one end of a
*                             crossing segment for labelling world
*                             coordinate 1.
*                         -2: Ditto for world coordinate 2.
*                         -3: Ditto for world coordinates 1 and 2.
*
* PGSBOX passes its NLCPRM, NLIPRM, and NLDPRM adjustable size array
* arguments of length NLC, NLI, and NLD to NLFUNC without
* modification.  Comments within NLFUNC should specify the parameters
* it wants passed to it via these arrays.
*
* PGSBOX first calls NLFUNC with OPCODE = 0 to cause it to initialize
* its work arrays (if necessary).  It then uses OPCODE = -1 to
* determine the range of world coordinate values.  It anchors the
* start of each coordinate grid line with a call with OPCODE = +1, and
* then tracks it with OPCODE = +2.
*
* The CONTXT array is also passed to NLFUNC without modification to
* allow it to preserve state information between calls for OPCODE = 2.
* In particular, NLFUNC can use this to detect discontinuities in the
* grid lines.
*
* The CONTRL argument is provided so that NLFUNC can force PGSBOX to
* call it again with or without flushing its plotting buffer.  This
* may be needed when plotting a grid line through a discontinuity.
* PGSBOX does not modify CONTRL.
*
* Notes:
*   1: NLFUNC must not change the input coordinates; that is the world
*      coordinates for OPCODEs = +1 and +2, or the Cartesian coordinates
*      for OPCODE = -1.
*
*   2: NLFUNC must define a single-valued function, that is, each
*      Cartesian coordinate (x,y) must map to a unique world coordinate
*      pair (xi,eta).
*
*   3: Notwithstanding the fact that PGSBOX declares NLCPRM, NLIPRM,
*      and NLDPRM as single dimension arrays of length NLC, NLI, and
*      NLD, NLFUNC may treat these as higher-dimensional arrays, for
*      example, NLDPRM(2,NLD).  (The FORTRAN standard requires that
*      only the last dimension is adjustable.)
d463 2
a464 2
     :  GCODE, TIKLEN, NG1, GRID1, NG2, GRID2, DOEQ, NLFUNC, NLC, NLI,
     :  NLD, NLCPRM, NLIPRM, NLDPRM, NC, IC, CACHE, IERR)
d517 1
a517 1
     :  XY, CONTRL, CONTXT, IERR)
d520 2
a521 2
        IERR = 1
        RETURN
d535 1
a535 1
     :  GRID1, NG2, GRID2, DOEQ, NC, IC, CACHE, IERR)
d553 2
a554 2
        IERR = 3
        RETURN
d575 5
a579 5
        IF (CI(J).GE.0) THEN
          CJ(J) = CI(J)
        ELSE
          CJ(J) = CI0
        END IF
d596 5
a600 5
*       Use extrema cached from a previous call.
        WMIN(1) = CACHE(1,0)
        WMAX(1) = CACHE(2,0)
        WMIN(2) = CACHE(3,0)
        WMAX(2) = CACHE(4,0)
d603 165
a767 44
*       Do a coarse search to find approximate ranges.
        WMIN(1) =  1D99
        WMAX(1) = -1D99
        WMIN(2) =  1D99
        WMAX(2) = -1D99

*       Need to consider cycles in angle through 360 degrees.
        ISANGL(1) = INDEX('ABCDEFGHI',FTYPE(1)).NE.0
        ISANGL(2) = INDEX('ABCDEFGHI',FTYPE(2)).NE.0
        VMIN(1,1) =  1D99
        VMIN(1,2) =  1D99
        VMAX(1,1) = -1D99
        VMAX(1,2) = -1D99
        VMIN(2,1) =  1D99
        VMIN(2,2) =  1D99
        VMAX(2,1) = -1D99
        VMAX(2,2) = -1D99

*       Sample coordinates on a 50 x 50 grid.
        NX = 50
        NY = 50
        DX = DBLE(TRC(1)-BLC(1))/NX
        DY = DBLE(TRC(2)-BLC(2))/NY

        K = 0
        IYPREV = -1
        DO 40 IY = 0, NY
          XY(2) = BLC(2) + IY*DY

*         Sample the edges only?
          KX = 1
          IF (DOEDGE) THEN
            IF (IY.NE.0 .AND. IY.NE.NY) KX = NX
          END IF

          DO 30 IX = 0, NX, KX
            XY(1) = BLC(1) + IX*DX

            IF (DOLBOX) THEN
              WORLD(1) = WXY(1) + XY(1)*XSPAN
              WORLD(2) = WXY(3) + XY(2)*YSPAN
            ELSE
              CALL NLFUNC (-1, NLC, NLI, NLD, NLCPRM, NLIPRM,
     :          NLDPRM, WORLD, XY, CONTRL, CONTXT, IERR)
d769 1
d771 12
a782 134
            IF (IERR.EQ.0) THEN
              K = K + 1

              IF (ISANGL(1)) THEN
                IF (K.EQ.1) W1X0 = WORLD(1)

                IF (IY.NE.IYPREV) THEN
                  W1PREV = W1X0
                  W1X0 = WORLD(1)
                END IF

*               Iron out jumps.
                WJUMP = WORLD(1) - W1PREV
                IF (ABS(WJUMP).GT.180D0) THEN
                  WJUMP = WJUMP + SIGN(180D0,WJUMP)
                  WJUMP = 360D0*INT(WJUMP/360D0)
                  WORLD(1) = WORLD(1) - WJUMP
                END IF

                W1PREV = WORLD(1)
                IYPREV = IY
              END IF

              IF (ISANGL(2)) THEN
                IF (K.EQ.1) W2X0 = WORLD(2)

                IF (IY.NE.IYPREV) THEN
                  W2PREV = W2X0
                  W2X0 = WORLD(2)
                END IF

*               Iron out jumps.
                WJUMP = WORLD(2) - W2PREV
                IF (ABS(WJUMP).GT.180D0) THEN
                  WJUMP = WJUMP + SIGN(180D0,WJUMP)
                  WJUMP = 360D0*INT(WJUMP/360D0)
                  WORLD(2) = WORLD(2) - WJUMP
                END IF

                W2PREV = WORLD(2)
                IYPREV = IY
              END IF

              IF (WORLD(1).LT.WMIN(1)) WMIN(1) = WORLD(1)
              IF (WORLD(1).GT.WMAX(1)) WMAX(1) = WORLD(1)
              IF (WORLD(2).LT.WMIN(2)) WMIN(2) = WORLD(2)
              IF (WORLD(2).GT.WMAX(2)) WMAX(2) = WORLD(2)

              IF (ISANGL(1)) THEN
*               Normalize to the range [0,360).
                WORLD(1) = MOD(WORLD(1), 360D0)
                IF (WORLD(1).LT.0D0) WORLD(1) = WORLD(1) + 360D0
                IF (WORLD(1).LT.VMIN(1,1)) VMIN(1,1) = WORLD(1)
                IF (WORLD(1).GT.VMAX(1,1)) VMAX(1,1) = WORLD(1)

*               Normalize to the range (-180,180].
                IF (WORLD(1).GT.180D0) WORLD(1) = WORLD(1) - 360D0
                IF (WORLD(1).LT.VMIN(1,2)) VMIN(1,2) = WORLD(1)
                IF (WORLD(1).GT.VMAX(1,2)) VMAX(1,2) = WORLD(1)
              END IF

              IF (ISANGL(2)) THEN
*               Normalize to the range [0,360).
                WORLD(2) = MOD(WORLD(2), 360D0)
                IF (WORLD(2).LT.0D0) WORLD(2) = WORLD(2) + 360D0
                IF (WORLD(2).LT.VMIN(2,1)) VMIN(2,1) = WORLD(2)
                IF (WORLD(2).GT.VMAX(2,1)) VMAX(2,1) = WORLD(2)

*               Normalize to the range (-180,180].
                IF (WORLD(2).GT.180D0) WORLD(2) = WORLD(2) - 360D0
                IF (WORLD(2).LT.VMIN(2,2)) VMIN(2,2) = WORLD(2)
                IF (WORLD(2).GT.VMAX(2,2)) VMAX(2,2) = WORLD(2)
              END IF
            END IF
 30       CONTINUE
 40     CONTINUE

        IF (K.EQ.0) THEN
*         No valid coordinates found within the frame.
          IERR = 2
          GO TO 999
        END IF

*       Check for cycles in angle.
        DO 50 J = 1, 2
          IF (ISANGL(J)) THEN
            IF (WMAX(J)-WMIN(J).LT.360D0 .AND.
     :          WMAX(J)-WMIN(J).GT.VMAX(J,1)-VMIN(J,1)+TOL) THEN
*             Must have a cycle, preserve the sign.
              IF (WMAX(J).GE.0D0) THEN
                WMIN(J) = VMIN(J,1)
                WMAX(J) = VMAX(J,1)
              ELSE
                WMIN(J) = VMIN(J,1) - 360D0
                WMAX(J) = VMAX(J,1) - 360D0
              END IF
            END IF

            IF (WMAX(J)-WMIN(J).LT.360D0 .AND.
     :          WMAX(J)-WMIN(J).GT.VMAX(J,2)-VMIN(J,2)+TOL) THEN
*             Must have a cycle, preserve the sign.
              IF (WMAX(J).GE.0D0) THEN
                IF (VMAX(J,2).GE.0D0) THEN
                  WMIN(J) = VMIN(J,2)
                  WMAX(J) = VMAX(J,2)
                ELSE
                  WMIN(J) = VMIN(J,2) + 360D0
                  WMAX(J) = VMAX(J,2) + 360D0
                END IF
              ELSE
                IF (VMAX(J,2).LT.0D0) THEN
                  WMIN(J) = VMIN(J,2)
                  WMAX(J) = VMAX(J,2)
                ELSE
                  WMIN(J) = VMIN(J,2) - 360D0
                  WMAX(J) = VMAX(J,2) - 360D0
                END IF
              END IF
            END IF
          END IF
 50     CONTINUE

*       Cache extrema for subsequent calls.
        CACHE(1,0) = WMIN(1)
        CACHE(2,0) = WMAX(1)
        CACHE(3,0) = WMIN(2)
        CACHE(4,0) = WMAX(2)

*       Was full sampling done?
        IF (DOEDGE) THEN
          CACHE(1,NC-1) = 0D0
        ELSE
          CACHE(1,NC-1) = 1D0
        END IF
d784 1
a784 1
        IC = 0
d789 5
a793 5
*       User specified grid density.
        DENS(1) = MOD(LABDEN,100)
        DENS(2) = LABDEN/100
        IF (DENS(1).EQ.0) DENS(1) = DENS0
        IF (DENS(2).EQ.0) DENS(2) = DENS0
d795 3
a797 3
*       Default grid density.
        DENS(1) = DENS0
        DENS(2) = DENS0
d804 137
a940 53
        IF (J.EQ.1) THEN
          K = 2
        ELSE
          K = 1
        END IF

        IF (NG(J).EQ.0 .AND. G0(J).NE.0D0) THEN
          GSTEP(J) = G0(J)
        ELSE IF (DOEQ .AND. NG(K).EQ.0 .AND. G0(K).NE.0D0) THEN
          GSTEP(J) = G0(K)
        ELSE
          DW(J) = WMAX(J) - WMIN(J)
          STEP = DW(J)/DENS(J)

          FACT = 1D0
          IF (INDEX('GHI',FTYPE(J)).NE.0) THEN
*           Rescale degrees to hours.
            FACT = 1D0/15D0
            STEP = STEP*FACT
          ELSE IF (FTYPE(J).EQ.'Y' .AND. STEP.LT.0.5D0) THEN
*           Calendar increment of less than 12h; use time format.
            FTYPE(J) = 'y'

*           Rescale days to hours.
            FACT = 24D0
            STEP = STEP*FACT
          END IF

          IF (INDEX('ABCDEF',FTYPE(J)).NE.0 .AND. STEP.GE.1D0) THEN
*           Angle with multi-degree increment.
            IF (STEP.LT.1.5D0) THEN
              STEP = 1D0
            ELSE IF (STEP.LT.3D0) THEN
              STEP = 2D0
            ELSE IF (STEP.LT.7D0) THEN
              STEP = 5D0
            ELSE IF (STEP.LT.12D0) THEN
              STEP = 10D0
            ELSE IF (STEP.LT.20D0) THEN
              STEP = 15D0
            ELSE IF (STEP.LT.40D0) THEN
              STEP = 30D0
            ELSE IF (STEP.LT.70D0) THEN
              STEP = 45D0
            ELSE IF (STEP.LT.120D0) THEN
              STEP = 90D0
            ELSE IF (STEP.LT.270D0) THEN
              STEP = 180D0
            ELSE IF (STEP.LT.520D0) THEN
              STEP = 360D0
            ELSE
              STEP = 360D0*INT(STEP/360D0 + 0.5)
            END IF
d942 1
a942 24
          ELSE IF (INDEX('GHITy',FTYPE(J)).NE.0 .AND.
     :      STEP.GE.1D0) THEN
*           Angle or time in hms format with multi-hour increment.
            IF (STEP.LT.1.5D0) THEN
              STEP = 1D0
            ELSE IF (STEP.LT.2.5D0) THEN
              STEP = 2D0
            ELSE IF (STEP.LT.3.5D0) THEN
              STEP = 3D0
            ELSE IF (STEP.LT.5D0) THEN
              STEP = 4D0
            ELSE IF (STEP.LT.7D0) THEN
              STEP = 6D0
            ELSE IF (STEP.LT.10D0) THEN
              STEP = 8D0
            ELSE IF (STEP.LT.15D0) THEN
              STEP = 12D0
            ELSE IF (STEP.LT.21D0) THEN
              STEP = 18D0
            ELSE IF (STEP.LT.36D0) THEN
              STEP = 24D0
            ELSE
              STEP = 24D0*INT(STEP/24D0 + 0.5)
            END IF
d944 14
a957 1
            STEP = STEP/FACT
d959 11
a969 23
          ELSE IF (INDEX('DEFGHITy',FTYPE(J)).NE.0 .AND.
     :      STEP.LT.1D0) THEN
*           Angle or time in sexagesimal format with sub-degree/hour
*           increment.
            FACT = FACT*60D0
            STEP = STEP*60D0
            IF (STEP.LT.1D0) THEN
*             Sub-minute increment.
              FACT = FACT*60D0
              STEP = STEP*60D0
            END IF

            IF (STEP.LT.1D0) THEN
*             Sub-second increment.
              TMP = 10D0**(INT(LOG10(STEP))-1)
              IF (1.5*TMP.GE.STEP) THEN
                STEP = TMP
              ELSE
                IF (3D0*TMP.GE.STEP) THEN
                  STEP = 2D0*TMP
                ELSE
                  IF (7D0*TMP.GE.STEP) THEN
                    STEP = 5D0*TMP
d971 1
a971 1
                    STEP = 10D0*TMP
a972 2
                END IF
              END IF
d974 25
a998 59
            ELSE
              IF (STEP.LT.1.5D0) THEN
                STEP = 1D0
              ELSE IF (STEP.LT.2.5D0) THEN
                STEP = 2D0
              ELSE IF (STEP.LT.3.5D0) THEN
                STEP = 3D0
              ELSE IF (STEP.LT.4.5D0) THEN
                STEP = 4D0
              ELSE IF (STEP.LT.5.5D0) THEN
                STEP = 5D0
              ELSE IF (STEP.LT.8D0) THEN
                STEP = 6D0
              ELSE IF (STEP.LT.11D0) THEN
                STEP = 10D0
              ELSE IF (STEP.LT.14D0) THEN
                STEP = 12D0
              ELSE IF (STEP.LT.18D0) THEN
                STEP = 15D0
              ELSE IF (STEP.LT.25D0) THEN
                STEP = 20D0
              ELSE IF (STEP.LT.45D0) THEN
                STEP = 30D0
              ELSE
                STEP = 60D0
              END IF
            END IF

            STEP = STEP/FACT

          ELSE IF (FTYPE(J).EQ.'Y') THEN
*           Calendar axis: use coded steps.
            IF (STEP.LT.15D0) THEN
*             Timespan of a few months; use multi-day increments.
              STEP = ANINT(STEP)
              IF (STEP.LT.1D0) THEN
                STEP = 1D0
              ELSE IF (STEP.GT.9D0) THEN
*               Fortnightly.
                STEP = 14D0
              ELSE IF (STEP.GT.4D0) THEN
*               Weekly.
                STEP = 7D0
              END IF

            ELSE IF (STEP.LT.270D0) THEN
*             Timespan of a few years; use multi-month increments.
              STEP = ANINT(STEP/30.44D0)
              IF (STEP.LT.1.5D0) THEN
                STEP = 1D0
              ELSE IF (STEP.LT.2.5D0) THEN
                STEP = 2D0
              ELSE IF (STEP.LT.3.5D0) THEN
                STEP = 3D0
              ELSE IF (STEP.LT.4.5D0) THEN
                STEP = 4D0
              ELSE
                STEP = 6D0
              END IF
d1000 3
a1002 2
*             Coding for multi-month increments.
              STEP = 100D0*STEP
d1005 3
a1007 6
*             Multi-year increments.
              STEP = ANINT(DW(J)/DENS(J)/365.25D0)
              IF (STEP.LT.1D0) THEN
                STEP = 1D0
              ELSE
                TMP = 10D0**INT(LOG10(STEP))
d1009 1
a1009 1
                IF (1.5D0*TMP.GE.STEP) THEN
d1011 1
a1011 1
                ELSE
d1013 1
a1013 1
                    STEP = 2D0*TMP
d1015 7
a1021 17
                    IF (7D0*TMP.GE.STEP) THEN
                      STEP = 5D0*TMP
                    ELSE
                      STEP = 10D0*TMP
                    END IF
                  END IF
                END IF
              END IF

*             Coding for multi-year increments.
              STEP = 10000D0*STEP
            END IF

          ELSE
*           Just numbers.
            TMP = 10D0**INT(LOG10(STEP))
            IF (STEP.LT.1D0) TMP = TMP/10D0
d1023 19
a1041 33
            IF (1.5D0*TMP.GE.STEP) THEN
              STEP = TMP
            ELSE
              IF (3D0*TMP.GE.STEP) THEN
                STEP = 2D0*TMP
              ELSE
                IF (7D0*TMP.GE.STEP) THEN
                  STEP = 5D0*TMP
                ELSE
                  STEP = 10D0*TMP
                END IF
              END IF
            END IF

*           Adjust the step size for logarithmic values.
            IF (FTYPE(J).EQ.'L') THEN
              IF (STEP.GT.0.7D0) THEN
                LDIV(J) = 1
                STEP = NINT(STEP)
              ELSE
                IF (STEP.GT.0.4D0) THEN
                  LDIV(J) = 2
                ELSE IF (STEP.GT.0.28D0) THEN
                  LDIV(J) = 3
                ELSE IF (STEP.GT.0.23D0) THEN
                  LDIV(J) = 4
                ELSE IF (STEP.GT.0.18D0) THEN
                  LDIV(J) = 5
                ELSE IF (STEP.GT.0.12D0) THEN
                  LDIV(J) = 6
                ELSE
                  LDIV(J) = 9
                END IF
d1043 3
a1045 2
                STEP = 1D0/LDIV(J)
              END IF
a1046 1
          END IF
d1048 2
a1049 2
          GSTEP(J) = STEP
        END IF
d1054 8
a1061 8
        IF (GRID1(0).EQ.0D0 .AND. GRID2(0).EQ.0D0) THEN
          GSTEP(1) = MIN(GSTEP(1), GSTEP(2))
          GSTEP(2) = GSTEP(1)
        ELSE IF (GRID1(0).EQ.0D0) THEN
          GSTEP(1) = GSTEP(2)
        ELSE IF (GRID2(0).EQ.0D0) THEN
          GSTEP(2) = GSTEP(1)
        END IF
d1066 2
a1067 8
        IF (FTYPE(J).EQ.'L') THEN
          WMIN(J) = AINT(WMIN(J)-1D0)
          WMAX(J) = AINT(WMAX(J)+1D0)
        ELSE IF (FTYPE(J).EQ.'Y') THEN
*         Calendar axis.
          IF (GSTEP(J).LT.100D0) THEN
*           Daily increments.
            WMIN(J) = AINT(WMIN(J))
d1069 40
a1108 34
          ELSE
*           Start on Jan/01.
            CALL PGMJD (0, WMIN(J), IY, IM, ID)
            CALL PGMJD (1, WMIN(J), IY, 1, 1)

            CALL PGMJD (0, WMAX(J), IY, IM, ID)
            IF (GSTEP(J).LT.10000D0) THEN
*             Monthly increments.
              CALL PGMJD (1, WMAX(J), IY, 12, 1)
            ELSE
*             Yearly increments.
              CALL PGMJD (1, WMAX(J), IY+1, 1, 1)
            END IF
          END IF

        ELSE
          TMP = AINT(WMIN(J)/GSTEP(J))*GSTEP(J)
          IF (TMP.GE.WMIN(J)) TMP = TMP - GSTEP(J)
          WMIN(J) = TMP
          TMP = AINT(WMAX(J)/GSTEP(J))*GSTEP(J)
          IF (TMP.LE.WMAX(J)) TMP = TMP + GSTEP(J)
          WMAX(J) = TMP
        END IF

        DW(J) = WMAX(J) - WMIN(J)
        SW(J) = DW(J)/NSTEP(J)

*       Adjust NSTEP so that SW divides GSTEP.
        IF (SW(J).LT.GSTEP(J)) THEN
          SW(J) = GSTEP(J)/ANINT(GSTEP(J)/SW(J))
        ELSE
          SW(J) = GSTEP(J)
        END IF
        NSTEP(J) = ANINT(DW(J)/SW(J))
d1120 22
a1141 22
        IF (GCODE(J).EQ.2) THEN
          TCODE(J,1) = -1
          TCODE(J,2) = -1
          TCODE(J,3) = -1
          TCODE(J,4) = -1
        ELSE IF (GCODE(J).EQ.1) THEN
          TCODE(J,1) = 1
          TCODE(J,2) = 1
          TCODE(J,3) = 1
          TCODE(J,4) = 1
        ELSE IF (GCODE(J).LT.0) THEN
          K = ABS(GCODE(J))
          TCODE(J,1) = MOD(K,10)
          TCODE(J,2) = MOD(K/10,10)
          TCODE(J,3) = MOD(K/100,10)
          TCODE(J,4) = MOD(K/1000,10)
        ELSE
          TCODE(J,1) = 0
          TCODE(J,2) = 0
          TCODE(J,3) = 0
          TCODE(J,4) = 0
        END IF
d1147 1
a1147 1
        IF (GCODE(J).EQ.0) GO TO 120
d1149 7
a1155 50
        IF (J.EQ.1) THEN
          CALL PGSCI (CJ(1))
          K = 2
        ELSE
          CALL PGSCI (CJ(2))
          K = 1
        END IF

        IF (NG(J).GT.0) THEN
          NWJ = NG(J)

        ELSE IF (FTYPE(J).EQ.'Y' .AND. GSTEP(J).GE.100D0) THEN
*         Calendar axis.
          CALL PGMJD (0, WMAX(J), IY, IM, ID)
          IF (GSTEP(J).LT.10000D0) THEN
            NWJ = 12*IY + IM
            CALL PGMJD (0, WMIN(J), IY, IM, ID)
            NWJ = (NWJ - (12*IY + IM))/INT(GSTEP(J)/100D0)
          ELSE
            NWJ = IY
            CALL PGMJD (0, WMIN(J), IY, IM, ID)
            NWJ = (NWJ - IY)/INT(GSTEP(J)/10000D0)
          END IF

        ELSE
          NWJ = NINT(DW(J)/GSTEP(J))
          IW0 = NINT(WMIN(J)/GSTEP(J))
        END IF

        DO 110 IWJ = 0, NWJ
          MAJOR = .FALSE.

*         Determine the world coordinate of the grid line.
          IF (NG(J).GT.0) THEN
*           User-specified.
            IF (IWJ.EQ.0) GO TO 110
            WORLD(1) = GRID1(IWJ)
            WORLD(2) = GRID2(IWJ)
          ELSE
*           Internally computed.
            IF (FTYPE(J).EQ.'Y' .AND. GSTEP(J).GE.100D0) THEN
*             Calendar axis.
              CALL PGMJD (0, WMIN(J), IY, IM, ID)
              IF (GSTEP(J).LT.10000D0) THEN
                IM = IM + IWJ*INT(GSTEP(J)/100D0)
                CALL PGMJD (1, WORLD(J), IY, IM, ID)
              ELSE
                IY = IY + IWJ*INT(GSTEP(J)/10000D0)
                CALL PGMJD (1, WORLD(J), IY, IM, ID)
              END IF
d1157 2
a1158 2
            ELSE
              WORLD(J) = (IW0 + IWJ)*GSTEP(J)
d1160 35
a1194 13
*             Logarithmic?
              IF (FTYPE(J).EQ.'L') THEN
                TMP = MOD(WORLD(J),1D0)
                IF (TMP.LT.0D0) TMP = TMP + 1D0
                L = NINT(TMP*LDIV(J))

                IF (L.EQ.0) THEN
*                 Major tick mark.
                  MAJOR = .TRUE.
                ELSE
*                 Adjust logarithmic scales.
                  IF (LDIV(J).LE.6) THEN
                    L = LTABL(L,LDIV(J))
d1196 2
a1197 1
                    L = L + 1
d1200 16
a1215 143
                  WORLD(J) = WORLD(J) - TMP + LOG10(DBLE(L))
                END IF
              END IF
            END IF
          END IF

          NP = 0
          GETEND = .TRUE.
          DO 100 IWK = 0, NSTEP(K)
            WORLD(K) = WMIN(K) + IWK*SW(K)

            IF (GETEND) THEN
*             Get end-point context.
              IF (DOLBOX) THEN
                XY(1) = (WORLD(1) - WXY(1))/XSPAN
                XY(2) = (WORLD(2) - WXY(3))/YSPAN
              ELSE
                CALL NLFUNC (1, NLC, NLI, NLD, NLCPRM, NLIPRM,
     :            NLDPRM, WORLD, XY, CONTRL, CONTXT, IERR)
              END IF

              IF (IERR.LE.0) THEN
                X1 = REAL(XY(1))
                Y1 = REAL(XY(2))
                INSIDE = X1.GT.BLC(1) .AND. X1.LT.TRC(1) .AND.
     :                   Y1.GT.BLC(2) .AND. Y1.LT.TRC(2)

                NP = 1
                XR(1) = X1
                YR(1) = Y1

                PREVIN = INSIDE
                GETEND = .FALSE.

                LABLOK = IERR.NE.-J .AND. IERR.NE.-3
              END IF
              GO TO 100
            END IF

            DO 90 ISTEP = 1, 1000
              IF (DOLBOX) THEN
                XY(1) = (WORLD(1) - WXY(1))/XSPAN
                XY(2) = (WORLD(2) - WXY(3))/YSPAN
              ELSE
                CALL NLFUNC (2, NLC, NLI, NLD, NLCPRM, NLIPRM,
     :            NLDPRM, WORLD, XY, CONTRL, CONTXT, IERR)
              END IF

              IF (IERR.GT.0) THEN
*               Flush buffer.
                IF (NP.GT.1) CALL PGLINE(NP, XR, YR)
                NP = 0
                GETEND = .TRUE.
                GO TO 100
              END IF

              IF (NP.EQ.BUFSIZ) THEN
*               Recycle buffer.
                CALL PGLINE(NP, XR, YR)
                XR(1) = XR(NP)
                YR(1) = YR(NP)
                NP = 1
              END IF

              X2 = REAL(XY(1))
              Y2 = REAL(XY(2))
              INSIDE = X2.GT.BLC(1) .AND. X2.LT.TRC(1) .AND.
     :                 Y2.GT.BLC(2) .AND. Y2.LT.TRC(2)

              IF (.NOT.INSIDE) THEN
*               For tick marks at the left or right edge.
                IF ((X2.EQ.BLC(1) .OR.  X2.EQ.TRC(1)) .AND.
     :               Y2.GT.BLC(2) .AND. Y2.LT.TRC(2)) THEN
                  INSIDE = X2.EQ.XR(NP)
                END IF
              END IF

              IF (.NOT.INSIDE) THEN
*               For tick marks at the bottom or top edge.
                IF ((Y2.EQ.BLC(2) .OR.  Y2.EQ.TRC(2)) .AND.
     :               X2.GT.BLC(1) .AND. X2.LT.TRC(1)) THEN
                  INSIDE = Y2.EQ.YR(NP)
                END IF
              END IF

              IF (NP.EQ.0) THEN
                NP = 1
                XR(1) = X2
                YR(1) = Y2
              ELSE
                IF (INSIDE) THEN
*                 This point is inside the frame...
                  IF (.NOT.PREVIN) THEN
*                   ...but the previous one was outside.
                    X1 = XR(NP)
                    Y1 = YR(NP)

                    FSEG = 0
                    XPOINT = 0.0
                    IF (ABS(X2-X1).GT.XTOL) THEN
                      S = (Y2-Y1)/(X2-X1)
                      IF (XR(NP).LE.BLC(1)) THEN
                        FSEG = 2
                        XR(NP) = BLC(1)
                        XPOINT = Y1 + (XR(NP) - X1)*S
                        YR(NP) = XPOINT
                      ELSE IF (XR(NP).GE.TRC(1)) THEN
                        FSEG = 4
                        XR(NP) = TRC(1)
                        XPOINT = Y1 + (XR(NP) - X1)*S
                        YR(NP) = XPOINT
                      END IF
                    END IF

                    IF (ABS(Y2-Y1).GT.YTOL) THEN
                      S = (X2-X1)/(Y2-Y1)
                      IF (YR(NP).LE.BLC(2)) THEN
                        FSEG = 1
                        YR(NP) = BLC(2)
                        XPOINT = X1 + (YR(NP) - Y1)*S
                        XR(NP) = XPOINT
                      ELSE IF (YR(NP).GE.TRC(2)) THEN
                        FSEG = 3
                        YR(NP) = TRC(2)
                        XPOINT = X1 + (YR(NP) - Y1)*S
                        XR(NP) = XPOINT
                      END IF
                    END IF


                    IF (FSEG.EQ.0) THEN
*                     The crossing is too oblique.
                      INSIDE = .FALSE.

                    ELSE
*                     Record this crossing point.
                      IF (TCODE(J,FSEG).NE.0 .AND. LABLOK) THEN
                        IF (IC.LT.NC-1) THEN
                          IC = IC + 1
                          CACHE(1,IC) = FSEG
                          CACHE(2,IC) = XPOINT
                          CACHE(3,IC) = J
                          CACHE(4,IC) = WORLD(J)
d1217 1
a1217 2
*                         Cache overflow.
                          OVERFL = .TRUE.
a1218 1
                      END IF
d1220 261
a1480 85
                      IF (TCODE(J,FSEG).GT.0) THEN
*                       Just want tick marks.
                        S = (XSCL*(X2-X1))**2 + (YSCL*(Y2-Y1))**2
                        S = SQRT(S)/TCODE(J,FSEG)
                        IF (MAJOR) S = S/1.5
                        NP = NP + 1
                        XR(NP) = XR(NP-1) + (X2-X1)*TIKLEN/S
                        YR(NP) = YR(NP-1) + (Y2-Y1)*TIKLEN/S

                        CALL PGLINE(NP, XR, YR)
                        NP = 1
                      END IF
                    END IF
                  END IF

                  IF (INSIDE .AND. GCODE(J).EQ.2) THEN
*                   Full grid.
                    NP = NP + 1
                  END IF
                  XR(NP) = X2
                  YR(NP) = Y2
                ELSE
*                 This point is outside the frame...
                  IF (PREVIN) THEN
*                   ...but the previous one was inside.
                    X1 = XR(NP)
                    Y1 = YR(NP)

                    NP = NP + 1
                    XR(NP) = X2
                    YR(NP) = Y2

                    FSEG = 0
                    XPOINT = 0.0
                    IF (ABS(X2-X1).GT.XTOL) THEN
                      S = (Y2-Y1)/(X2-X1)
                      IF (XR(NP).LE.BLC(1)) THEN
                        FSEG = 2
                        XR(NP) = BLC(1)
                        XPOINT = Y1 + (XR(NP) - X1)*S
                        YR(NP) = XPOINT
                      ELSE IF (XR(NP).GE.TRC(1)) THEN
                        FSEG = 4
                        XR(NP) = TRC(1)
                        XPOINT = Y1 + (XR(NP) - X1)*S
                        YR(NP) = XPOINT
                      END IF
                    END IF

                    IF (ABS(Y2-Y1).GT.YTOL) THEN
                      S = (X2-X1)/(Y2-Y1)
                      IF (YR(NP).LE.BLC(2)) THEN
                        FSEG = 1
                        YR(NP) = BLC(2)
                        XPOINT = X1 + (YR(NP) - Y1)*S
                        XR(NP) = XPOINT
                      ELSE IF (YR(NP).GE.TRC(2)) THEN
                        FSEG = 3
                        YR(NP) = TRC(2)
                        XPOINT = X1 + (YR(NP) - Y1)*S
                        XR(NP) = XPOINT
                      END IF
                    END IF


                    IF (FSEG.EQ.0) THEN
*                     The crossing is too oblique.
                      INSIDE = .TRUE.

                      IF (GCODE(J).EQ.2) THEN
*                       Full grid.
                        NP = NP + 1
                      END IF
                      XR(NP) = X2
                      YR(NP) = Y2

                    ELSE
*                     Record this crossing point.
                      IF (TCODE(J,FSEG).NE.0 .AND. LABLOK) THEN
                        IF (IC.LT.NC-1) THEN
                          IC = IC + 1
                          CACHE(1,IC) = FSEG
                          CACHE(2,IC) = XPOINT
                          CACHE(3,IC) = J
                          CACHE(4,IC) = WORLD(J)
d1482 3
a1484 2
*                         Cache overflow.
                          OVERFL = .TRUE.
d1486 2
a1487 1
                      END IF
d1489 12
a1500 39
                      IF (TCODE(J,FSEG).GT.0) THEN
*                       Just want tick marks.
                        X1 = XR(NP)
                        Y1 = YR(NP)
                        X2 = XR(NP-1)
                        Y2 = YR(NP-1)
                        S = (XSCL*(X2-X1))**2 + (YSCL*(Y2-Y1))**2
                        S = SQRT(S)/TCODE(J,FSEG)
                        IF (MAJOR) S = S/1.5
                        XR(NP-1) = X1 + (X2-X1)*TIKLEN/S
                        YR(NP-1) = Y1 + (Y2-Y1)*TIKLEN/S
                      END IF

*                     Flush buffer.
                      IF (TCODE(J,FSEG).NE.0) THEN
                        CALL PGLINE(NP, XR, YR)
                      END IF
                      NP = 0
                    END IF
                  ELSE
*                   The previous point was also outside.
                    XR(NP) = X2
                    YR(NP) = Y2
                  END IF
                END IF
              END IF

              PREVIN = INSIDE
              LABLOK = IERR.NE.-J .AND. IERR.NE.-3

              IF (CONTRL.EQ.0) THEN
                GO TO 100
              ELSE IF (CONTRL.EQ.1) THEN
*               Flush buffer.
                IF (NP.GT.1) CALL PGLINE(NP, XR, YR)
                NP = 0
              END IF
90          CONTINUE
100       CONTINUE
d1502 2
a1503 2
          IF (NP.GT.1) CALL PGLINE(NP, XR, YR)
110     CONTINUE
d1512 1
a1512 1
     :  CJ, NC, IC, CACHE)
d1526 3
a1528 3
* PGCRLB is a helper routine for PGSBOX, not meant to be called directly
* since it expects the viewport and window to be scaled to the full
* extent; it labels a curvilinear coordinate grid.
d1530 5
a1534 5
* Given:
*   BLC       R(2)      Cartesian coordinates of the bottom left-hand
*                       corner.
*   TRC       R(2)      Cartesian coordinates of the top right-hand
*                       corner.
d1536 1
a1536 1
*   IDENTS    C(3)*(*)  Identification strings (see PGSBOX).
d1538 2
a1539 2
*   FTYPE     C(2)*1    Axis types, used for axis labelling (see
*                       PGSBOX).
d1541 2
a1542 2
*   LABCTL    I         Decimal encoded grid labelling control (see
*                       PGSBOX).
d1544 1
a1544 1
*   CI        I(7)      Colour table (see PGSBOX).
d1546 2
a1547 2
* Given and/or returned:
*   NC        I         Upper array index for CACHE.
d1549 1
a1549 1
*   IC        I         Current number of entries in the CACHE table.
d1551 3
a1553 2
*   CACHE     D(4,0:NC) Table of points where the tick marks or grid
*                       lines cross the frame (see PGSBOX).
d1555 1
a1555 1
* Author: Mark Calabretta, Australia Telescope National Facility
d1582 2
a1583 2
        DO 10 J = 1, IC
          IWRLD = NINT(CACHE(3,J))
d1585 17
a1601 17
          IF (INDEX('ADG', FTYPE(IWRLD)).NE.0) THEN
            CACHE(4,J) = MOD(CACHE(4,J), 360D0)
            IF (CACHE(4,J).LT.0D0) CACHE(4,J) = CACHE(4,J) + 360D0
          ELSE IF (INDEX('BEH', FTYPE(IWRLD)).NE.0) THEN
            CACHE(4,J) = MOD(CACHE(4,J), 360D0)
            IF (CACHE(4,J).LE.-180D0) THEN
              CACHE(4,J) = CACHE(4,J) + 360D0
            ELSE IF (CACHE(4,J).GT.180D0) THEN
              CACHE(4,J) = CACHE(4,J) - 360D0
            END IF
          END IF

          IF (INDEX('GHI', FTYPE(IWRLD)).NE.0) THEN
*           Angle expressed as time.
            CACHE(4,J) = CACHE(4,J)/15D0
          END IF
 10     CONTINUE
d1608 14
a1621 14
        NSWAP = 0
        DO 30 J = 1, IC-1
          IF (CACHE(1,J).LT.CACHE(1,J+1)) GO TO 30
          IF (CACHE(1,J).EQ.CACHE(1,J+1) .AND.
     :        CACHE(2,J).LE.CACHE(2,J+1)) GO TO 30

          NSWAP = NSWAP + 1
          DO 20 M = 1, 4
            TMP = CACHE(M,J)
            CACHE(M,J) = CACHE(M,J+1)
            CACHE(M,J+1) = TMP
 20       CONTINUE
 30     CONTINUE
        IF (NSWAP.EQ.0) GO TO 50
d1627 1
a1627 1
        IF (J.GT.JC) GO TO 100
d1629 11
a1639 11
        DO 60 M = 1, 4
          IF (CACHE(M,J).NE.CACHE(M,J-1)) GO TO 90
 60     CONTINUE

*       This entry is the same as the previous one.
        JC = JC - 1
        DO 80 K = J, JC
          DO 70 M = 1, 4
            CACHE(M,K) = CACHE(M,K+1)
 70       CONTINUE
 80     CONTINUE
d1645 1
a1645 1
* How do we label the edges of the frame?
d1658 2
a1659 2
        IWRLD = NINT(CACHE(3,J))
        EDGE  = NINT(CACHE(1,J))
d1661 2
a1662 2
        NI(IWRLD,0) = NI(IWRLD,0) + 1
        NI(IWRLD,EDGE) = NI(IWRLD,EDGE) + 1
d1672 2
a1673 2
*       User-defined.
        L = LABCTL
d1675 148
a1822 88
*       Work it out ourselves.
        L = 0
        IF (ABS(SI(1)-SI(2)).GT.1.0) THEN
*         Approximately horizontal/vertical grid lines.
          IF (SI(1).GT.SI(2)) THEN
*           First world coordinate with vertical grid lines.
            IF (NI(1,1).GT.3 .OR. NI(1,1).GE.NI(1,3)) THEN
*             Label bottom of frame.
              L = L + 1
            ELSE
*             Label top of frame.
              L = L + 100
            END IF

*           Second world coordinate with horizontal grid lines.
            IF (NI(2,2).GT.3 .OR. NI(2,2).GE.NI(2,4)) THEN
*             Label left side of frame.
              L = L + 20
            ELSE
*             Label right side of frame.
              L = L + 2000
            END IF
          ELSE
*           First world coordinate with horizontal grid lines.
            IF (NI(1,2).GT.3 .OR. NI(1,2).GE.NI(1,4)) THEN
*             Label left side of frame.
              L = L + 10
            ELSE
*             Label right side of frame.
              L = L + 1000
            END IF

*           Second world coordinate with vertical grid lines.
            IF (NI(2,1).GT.3 .OR. NI(2,1).GE.NI(2,3)) THEN
*             Label bottom of frame.
              L = L + 2
            ELSE
*             Label top of frame.
              L = L + 200
            END IF
          END IF
        ELSE
*         Skew grid lines or worse.
          IF (SI(1).GT.0.5D0) THEN
*           First world coordinate with vertical grid lines.
            IF (NI(1,1).GT.1 .OR. NI(1,1).GT.NI(1,3)) THEN
              L = 1
            ELSE
              L = 100
            END IF

            IF (SI(2).GT.0.5D0) THEN
*             Second world coordinate also with vertical grid lines.
              IF (L.EQ.1) THEN
                L = 201
              ELSE
                IF (NI(2,1).GT.1 .OR. NI(2,1).GT.NI(2,3)) THEN
                  L = 102
                ELSE
                  L = 300
                END IF
              END IF
            ELSE
*             Second world coordinate with diagonal grid lines.
              L = L + 2020
            END IF
          ELSE IF (SI(1).LT.-0.5D0) THEN
*           First world coordinate with horizontal grid lines.
            IF (NI(1,2).GT.1 .OR. NI(1,2).GT.NI(1,4)) THEN
              L = 10
            ELSE
              L = 1000
            END IF

            IF (SI(2).LT.-0.5D0) THEN
*             Second world coordinate also with horizontal grid.
              IF (L.EQ.10) THEN
                L = 2010
              ELSE
                IF (NI(2,2).GT.1 .OR. NI(2,2).GT.NI(2,4)) THEN
                  L = 1020
                ELSE
                  L = 3000
                END IF
              END IF
            ELSE
*             Second world coordinate with diagonal grid lines.
              L = L + 202
d1824 1
a1824 61
          ELSE IF (SI(2).GT.0.5D0) THEN
*           Second world coordinate with vertical grid lines.
            IF (NI(2,1).GT.1 .OR. NI(2,1).GT.NI(2,3)) THEN
              L = 1012
            ELSE
              L = 1210
            END IF
          ELSE IF (SI(2).LT.-0.5D0) THEN
*           Second world coordinate with horizontal grid lines.
            IF (NI(2,2).GT.1 .OR. NI(2,2).GT.NI(2,4)) THEN
              L = 121
            ELSE
              L = 2101
            END IF
          ELSE
*           Desperation stakes!  Label all four axes.
            K1 = NI(1,3) + NI(1,1)
            K2 = NI(2,4) + NI(2,2)
            L = 2121

            M1 = NI(1,4) + NI(1,1)
            M2 = NI(2,3) + NI(2,2)
            IF (M1.GE.K1 .AND. M2.GE.K2) THEN
              L  = 1221
              K1 = M1
              K2 = M2
            END IF

            M1 = NI(1,2) + NI(1,1)
            M2 = NI(2,4) + NI(2,3)
            IF (M1.GE.K1 .AND. M2.GE.K2) THEN
              L  = 2211
              K1 = M1
              K2 = M2
            END IF

            M1 = NI(1,4) + NI(1,2)
            M2 = NI(2,3) + NI(2,1)
            IF (M1.GE.K1 .AND. M2.GE.K2) THEN
              L  = 1212
              K1 = M1
              K2 = M2
            END IF

            M1 = NI(1,3) + NI(1,2)
            M2 = NI(2,4) + NI(2,1)
            IF (M1.GE.K1 .AND. M2.GE.K2) THEN
              L  = 2112
              K1 = M1
              K2 = M2
            END IF

            M1 = NI(1,4) + NI(1,3)
            M2 = NI(2,2) + NI(2,1)
            IF (M1.GE.K1 .AND. M2.GE.K2) THEN
              L  = 1122
              K1 = M1
              K2 = M2
            END IF
          END IF
        END IF
d1840 3
a1842 21
        OMAG(1) = 0.0
        OMAG(2) = 0.0
        DO 120 J = 1, IC
          IWRLD = NINT(CACHE(3,J))
          IF (FTYPE(IWRLD).EQ.' ') THEN
*           Plain numeric.
            IF (CACHE(4,J).EQ.0D0) GO TO 120
            OMAG(IWRLD) = OMAG(IWRLD) + LOG10(ABS(CACHE(4,J)))
            IMAG(IWRLD) = IMAG(IWRLD) + 1
          END IF
 120    CONTINUE

        IF (IMAG(1).GT.0) IMAG(1) = INT(OMAG(1)/IMAG(1))
        IF (IMAG(1).GE.-2 .AND. IMAG(1).LE.4) IMAG(1) = 0

        IF (IMAG(2).GT.0) IMAG(2) = INT(OMAG(2)/IMAG(2))
        IF (IMAG(2).GE.-2 .AND. IMAG(2).LE.4) IMAG(2) = 0

*       Renormalize grid values.
        IF (IMAG(1).NE.0 .OR. IMAG(2).NE.0) THEN
          DO 130 J = 1, IC
d1844 21
a1864 3
            CACHE(4,J) = CACHE(4,J)/10D0**IMAG(IWRLD)
 130      CONTINUE
        END IF
d1872 2
a1873 2
        LMAG(1) = -2
        LMAG(2) = -2
d1875 30
a1904 29
        DO 150 J = 1, IC
*         Skip non-sexagesimal coordinates.
          IWRLD = NINT(CACHE(3,J))
          IF (.NOT.SEXA(IWRLD)) GO TO 150

*         Defeat rounding errors.
          IF (FTYPE(IWRLD).EQ.'y') THEN
            TMP = ABS(MOD(CACHE(4,J),1D0)*86400D0) + 5D-7
          ELSE
            TMP = ABS(CACHE(4,J)*3600D0) + 5D-7
          END IF

          LS = INT(TMP)
          LV = INT(MOD(TMP, 1D0)*1D6)
          IF (LV.NE.0) THEN
*           Sub-arcsec/second resolution.
            M = 1
            DO 140 K = 1, 6
              M = M*10
              IF (MOD(LV,M).NE.0) THEN
                LMAG(IWRLD) = MAX(LMAG(IWRLD), 7-K)
                GO TO 150
              END IF
 140        CONTINUE
          ELSE IF (LMAG(IWRLD).LT.0) THEN
            IF (MOD(LS,60).NE.0) THEN
              LMAG(IWRLD) = MAX(LMAG(IWRLD), 0)
            ELSE IF (MOD(LS,3600).NE.0) THEN
              LMAG(IWRLD) = MAX(LMAG(IWRLD), -1)
d1906 1
a1906 2
          END IF
 150    CONTINUE
d1940 293
a2232 118
*       Determine the position.
        IWRLD = NINT(CACHE(3,J))
        CALL PGSCI (CI(IWRLD+2))

        EDGE = NINT(CACHE(1,J))
        IF (EDGE.NE.PRVEDG) THEN
*         Start of new edge.

          IF (SEXA(1) .OR. SEXA(2)) THEN
*           Sexagesimal field suppression policy.
            PRVDEG(1) = -1
            PRVMIN(1) = -1
            PRVDEG(2) = -1
            PRVMIN(2) = -1

            SEXSUP(1) = 0
            SEXSUP(2) = 0

*           Vertical sides.
            IF (MOD(NINT(CACHE(1,J)),2).EQ.0) THEN
              DO 160 K = J, IC
                IF (NINT(CACHE(1,K)).NE.EDGE) GO TO 170

                KWRLD = NINT(CACHE(3,K))
                IF (SEXSUP(KWRLD).EQ.1) GO TO 160

                IF (FTYPE(KWRLD).EQ.'y') THEN
                  TMP = ABS(MOD(CACHE(4,K),1D0)*24D0)
                ELSE
                  TMP = ABS(CACHE(4,K))
                END IF

                LV = INT(TMP*3600D0 + 5D-7)
                LD =  LV/3600
                LM = (LV - LD*3600)/60
                LS =  LV - LD*3600 - LM*60
                TMP = TMP - LD

                IF (TMP.LT.5D-7) THEN
*                 Write deg/hr field only when min/sec are zero.
                  SEXSUP(KWRLD) = 1
                ELSE IF (TMP*60-LM.LT.3D-5) THEN
*                 Write min field only when sec is zero; only
*                 write the deg/hr field when min is written.
                  SEXSUP(KWRLD) = 2
                END IF
 160          CONTINUE
            END IF
          END IF
 170      CONTINUE

          PRVYR(1) = -1
          PRVYR(2) = -1

          XL = -999.0
          YL = -999.0
        END IF
        PRVEDG = EDGE
        LFORCE = .FALSE.

        IF (EDGE.EQ.1) THEN
*         Bottom.
          IF (IWRLD.EQ.1) THEN
            IF (MOD(SKIP(1),2).NE.1) GO TO 230
          ELSE
            IF (MOD(SKIP(1)/2,2).NE.1) GO TO 230
          END IF

          FJUST = 0.5
          X = CACHE(2,J)
          Y = YW1 - 1.5*YCH
        ELSE IF (EDGE.EQ.2) THEN
*         Left.
          IF (IWRLD.EQ.1) THEN
            IF (MOD(SKIP(2),2).NE.1) GO TO 230
          ELSE
            IF (MOD(SKIP(2)/2,2).NE.1) GO TO 230
          END IF

          FJUST = 1.0
          X = XW1 - 0.5*XCH
          Y = CACHE(2,J) - YCH/2.0
        ELSE IF (EDGE.EQ.3) THEN
*         Top.
          IF (IWRLD.EQ.1) THEN
            IF (MOD(SKIP(3),2).NE.1) GO TO 230
          ELSE
            IF (MOD(SKIP(3)/2,2).NE.1) GO TO 230
          END IF

          FJUST = 0.5
          X = CACHE(2,J)
          Y = YW2 + 0.5*YCH
        ELSE IF (EDGE.EQ.4) THEN
*         Right.
          IF (IWRLD.EQ.1) THEN
            IF (MOD(SKIP(4),2).NE.1) GO TO 230
          ELSE
            IF (MOD(SKIP(4)/2,2).NE.1) GO TO 230
          END IF

          FJUST = 0.0
          X = XW2 + 0.5*XCH
          Y = CACHE(2,J) - YCH/2.0
        END IF

*       Format the numeric label.
        IF (INDEX('ABC', FTYPE(IWRLD)).NE.0) THEN
*         Decimal angle; allow up to 6 decimal digits.
          TMP = ABS(CACHE(4,J)) + 5D-7
          LD  = INT(TMP)

          K = 1
          IF (CACHE(4,J).LT.0D0) THEN
*           Insert a minus sign.
            TEXT(1:1) = '-'
            K = 2
          END IF
d2234 5
a2238 42
          CALL PGNUMB (LD, 0, 1, TEXT(K:), NCH)
          K = K + NCH
          TEXT(K:) = ESCAPE // 'uo' // ESCAPE // 'd'
          K = K + 4

          LV = INT(MOD(TMP,1D0)*1D6)
          IF (LV.NE.0) CALL PGNUMB (LV, -6, 1, TEXT(K:), NCH)
          TEXT(K:K) = 'd'

        ELSE IF (SEXA(IWRLD)) THEN
*         Sexagesimal format; angle or time?
          ANGLE = INDEX('DEF', FTYPE(IWRLD)).NE.0
          L = LMAG(IWRLD)

*         Use integer arithmetic to avoid rounding problems.
          IF (FTYPE(IWRLD).EQ.'y') THEN
            TMP = ABS(MOD(CACHE(4,J),1D0)*24D0)

*           Determine date range.
            IF (CACHE(4,J).LT.MJD1(IWRLD)) MJD1(IWRLD) = CACHE(4,J)
            IF (CACHE(4,J).GT.MJD2(IWRLD)) MJD2(IWRLD) = CACHE(4,J)
          ELSE
            TMP = ABS(CACHE(4,J))
          END IF
          VS = TMP*3600D0 + 5D-7
          LV = INT(VS)

*         Sexagesimal fields.
          LD =  LV/3600
          LM = (LV - LD*3600)/60
          LS =  LV - LD*3600 - LM*60

*         Field suppression policy.
          IF (SEXSUP(IWRLD).GT.0) THEN
            TMP = TMP - LD

            IF (TMP.LT.5D-7) THEN
              DODEG = .TRUE.
              DOMIN = .TRUE.
            ELSE IF (SEXSUP(IWRLD).EQ.2) THEN
              DOMIN = TMP*60-LM.LT.3D-5
              DODEG = DOMIN .AND. LD.NE.PRVDEG(IWRLD)
d2240 11
a2250 2
              DODEG = .FALSE.
              DOMIN = .FALSE.
a2251 9
          ELSE
            DODEG = LD.NE.PRVDEG(IWRLD)
            DOMIN = LM.NE.PRVMIN(IWRLD)
          END IF

          K = 1
          IF (L.EQ.-2 .OR. DODEG) THEN
*           Write the degree/hour field.
            DODEG = .TRUE.
d2253 3
a2255 4
            IF (CACHE(4,J).LT.0D0) THEN
*             Insert a minus sign.
              TEXT(1:1) = '-'
              K = 2
d2258 3
a2260 6
            IF (ANGLE) THEN
*             Angle.
              CALL PGNUMB (LD, 0, 1, TEXT(K:), NCH)
              K = K + NCH
              TEXT(K:) = ESCAPE // 'uo' // ESCAPE // 'd'
              K = K + 5
d2262 19
a2280 182
*             Time.
              IF (LD.LE.9 .AND. INDEX('Ty',FTYPE(IWRLD)).EQ.0) THEN
*               Write leading zeroes in the hour field.
                WRITE (TEXT(K:), '(I2.2)') LD
                K = K + 2
              ELSE
                CALL PGNUMB (LD, 0, 1, TEXT(K:), NCH)
                K = K + NCH
              END IF
              TEXT(K:) = ESCAPE // 'uh' // ESCAPE // 'd'
              K = K + 5
            END IF
          END IF

          IF (L.GE.-1) THEN
*           Write arcminute/minute field.

            IF (L.EQ.-1 .OR. K.GT.1 .OR. DOMIN) THEN
              DOMIN = .TRUE.
              IF (ANGLE) THEN
                WRITE (TEXT(K:), '(I2.2,A)') LM, ''''
                K = K + 3
              ELSE
                WRITE (TEXT(K:), '(I2.2,A)') LM,
     :            ESCAPE // 'um' // ESCAPE // 'd'
                K = K + 7
              END IF
            END IF

            IF (L.GE.0) THEN
*             Arcsec/second field.
              IF (ANGLE) THEN
                WRITE (TEXT(K:), '(I2.2,A)') LS, '"'
                K = K + 3
              ELSE
                WRITE (TEXT(K:), '(I2.2,A)') LS,
     :            ESCAPE // 'us' // ESCAPE // 'd'
                K = K + 7
              END IF

              IF (L.GT.0) THEN
*               Sub-arcsec/second field.
                WRITE (FMT, '(A,I1,A,I1,A)') '(A,I', L, '.', L, ')'
                LV = INT(MOD(VS,1D0)*10**L)
                WRITE (TEXT(K:), FMT) '.', LV
              END IF
            END IF
          END IF

        ELSE IF (FTYPE(IWRLD).EQ.'L') THEN
*         Logarithmic.
          TMP = MOD(CACHE(4,J),1D0)
          IF (TMP.LT.0D0) TMP = TMP + 1D0
          MM = NINT(10D0**TMP)
          IF (MM.EQ.10) THEN
            TMP = TMP - 1D0
            MM = 1
          END IF

          PP = NINT(CACHE(4,J) - TMP)

          IF (MM.NE.1) THEN
            WRITE (TEXT, '(I1)') MM
          ELSE
*           FORTRAN is really abysmal sometimes.
            WRITE (TEXT, '(I8)') PP
            DO 180 K = 1, 8
              IF (TEXT(K:K).NE.' ') GO TO 190
 180        CONTINUE
 190        TEXT = '10' // ESCAPE // 'u' // TEXT(K:8)

            LFORCE = .TRUE.
          END IF

        ELSE IF (FTYPE(IWRLD).EQ.'Y') THEN
*         Convert MJD to Gregorian calendar date, YYYY/MM/DD.
          CALL PGMJD(0, CACHE(4,J), IY, IM, ID)
          DOYEAR = IY.NE.PRVYR(IWRLD)

          IF (DOYEAR) THEN
            WRITE (TEXT, 200) IY, IM, ID
 200        FORMAT (I12,'/',I2.2,'/',I2.2)

            DO 210 K = 1, 12
              IF (TEXT(K:K).NE.' ') GO TO 220
 210        CONTINUE
 220        TEXT = TEXT(K:18)

          ELSE
            WRITE (TEXT, 225) IM, ID
 225        FORMAT (I2.2,'/',I2.2)
          END IF

        ELSE
*         Plain number; allow up to six significant digits.
          IF (CACHE(4,J).NE.0D0) THEN
            PP = INT(LOG10(ABS(CACHE(4,J)))) - 6
            MM = NINT(CACHE(4,J)/10D0**PP)
          ELSE
            PP = 0
            MM = 0
          END IF

          CALL PGNUMB (MM, PP, 0, TEXT, NCH)
        END IF

*       Write the label if it doesn't overlap the previous one.
        CALL PGQTXT (X, Y, 0.0, FJUST, TEXT, XBOX, YBOX)
        IF (LFORCE .OR. XBOX(1).GT.XL .OR. YBOX(1).GT.YL) THEN
          IF (IWRLD.EQ.1) THEN
            CALL PGSCI (CI(3))
          ELSE
            CALL PGSCI (CI(4))
          END IF

          CALL PGPTXT (X, Y, 0.0, FJUST, TEXT)
          XL = XBOX(4) + 0.5*XCH
          YL = YBOX(2) + 0.5*YCH

*         Sexagesimal formatting.
          IF (SEXA(IWRLD)) THEN
            IF (DODEG) PRVDEG(IWRLD) = LD
            IF (DOMIN) PRVMIN(IWRLD) = LM
          END IF

*         Calendar formatting.
          IF (FTYPE(IWRLD).EQ.'Y') THEN
            IF (DOYEAR) PRVYR(IWRLD) = IY
          END IF

*         Record the fact.
          IF (IWRLD.EQ.1) THEN
            SKOP(EDGE) = 2*(SKOP(EDGE)/2) + 1
          ELSE
            SKOP(EDGE) = 2 + MOD(SKOP(EDGE),2)
          END IF

*         Boundary within which the numeric labels lie.
          IF (YBOX(1).LT.BNDRY(1)) BNDRY(1) = YBOX(1)
          IF (XBOX(1).LT.BNDRY(2)) BNDRY(2) = XBOX(1)
          IF (YBOX(3).GT.BNDRY(3)) BNDRY(3) = YBOX(3)
          IF (XBOX(3).GT.BNDRY(4)) BNDRY(4) = XBOX(3)

*         Check the distance to the previous grid line.
          TICKIT = .FALSE.
          IF (J.GT.1) THEN
            IF (CACHE(1,J).EQ.CACHE(1,J-1)) THEN
              IF (EDGE.EQ.1 .OR. EDGE.EQ.3) THEN
                TICKIT = XBOX(1).LT.CACHE(2,J-1)
              ELSE
                TICKIT = YBOX(1).LT.CACHE(2,J-1)
              END IF
            END IF
          END IF

*         Check the distance to the next grid line.
          IF (J.LT.IC) THEN
            IF (CACHE(1,J).EQ.CACHE(1,J+1)) THEN
              IF (EDGE.EQ.1 .OR. EDGE.EQ.3) THEN
                TICKIT = XBOX(2).GT.CACHE(2,J+1)
              ELSE
                TICKIT = YBOX(2).GT.CACHE(2,J+1)
              END IF
            END IF
          END IF

*         Density of grid lines is high.
          IF (TICKIT) THEN
*           Draw outside pip mark.
            Z = REAL(CACHE(2,J))
            IF (EDGE.EQ.1) THEN
              CALL PGMOVE (Z, YW1-0.3*YCH)
              CALL PGDRAW (Z, YW1)
            ELSE IF (EDGE.EQ.2) THEN
              CALL PGMOVE (XW1-0.3*XCH, Z)
              CALL PGDRAW (XW1, Z)
            ELSE IF (EDGE.EQ.3) THEN
              CALL PGMOVE (Z, YW2+0.3*YCH)
              CALL PGDRAW (Z, YW2)
            ELSE IF (EDGE.EQ.4) THEN
              CALL PGMOVE (XW2+0.3*XCH, Z)
              CALL PGDRAW (XW2, Z)
d2282 31
a2312 2
          END IF
        END IF
d2319 1
a2319 1
        TEXT = ' '
d2321 2
a2322 2
        DO 330 IWRLD = 1, 2
          TXT(IWRLD) = ' '
d2324 1
a2324 1
          IF (MOD(SKOP(EDGE)/IWRLD,2).EQ.0) GO TO 330
d2326 44
a2369 38
*         Strip off leading blanks.
          L = LEN(IDENTS(IWRLD))
          DO 240 K = 1, L
            IF (IDENTS(IWRLD)(K:K).NE.' ') THEN
              TXT(IWRLD) = IDENTS(IWRLD)(K:L)
              GO TO 250
            END IF
 240      CONTINUE

 250      IF (IMAG(IWRLD).NE.0 .OR. FTYPE(IWRLD).EQ.'y') THEN
*           Find the last non-blank.
            DO 260 K = 40, 1, -1
              IF (TXT(IWRLD)(K:K).NE.' ') GO TO 270
 260        CONTINUE
 270        K = K + 1

            IF (IMAG(IWRLD).NE.0) THEN
*             Add scaling information.
              CALL PGNUMB (IMAG(IWRLD), 0, 1, EXPONT, NCH)
              TXT(IWRLD)(K:) = '  x10' // ESCAPE // 'u' // EXPONT
            ELSE
*             Add calendar date range.
              CALL PGMJD(0, MJD1(IWRLD), IY, IM, ID)

              WRITE (TEXT, 280) IY, IM, ID
 280          FORMAT (I12,'/',I2.2,'/',I2.2)
              DO 290 L = 1, 12
                IF (TEXT(L:L).NE.' ') GO TO 300
 290          CONTINUE
 300          TXT(IWRLD)(K:) = ' (' // TEXT(L:18)
              K = K + 21 - L

              CALL PGMJD(0, MJD2(IWRLD), IY2, IM2, ID2)
              WRITE (TEXT, 280) IY2, IM2, ID2
              IF (IY2.EQ.IY) THEN
                IF (IM2.EQ.IM) THEN
                  IF (ID2.EQ.ID) THEN
                    TXT(IWRLD)(K:) = ')'
d2371 4
a2374 1
                    TXT(IWRLD)(K:) = ' - ' // TEXT(17:18) // ')'
d2376 32
a2407 47
                ELSE
                  TXT(IWRLD)(K:) = ' - ' // TEXT(14:18) // ')'
                END IF
              ELSE
                DO 310 L = 1, 12
                  IF (TEXT(L:L).NE.' ') GO TO 320
 310            CONTINUE
 320            TXT(IWRLD)(K:) = ' - ' // TEXT(L:18) // ')'
              END IF
            END IF
          END IF

 330    CONTINUE

        K = 0
        IF (TXT(1).NE.' ') THEN
*         Identify first world coordinate...
          TEXT = TXT(1)
          CALL PGSCI (CI(5))

          IF (TXT(2).NE.' ') THEN
*           ...and also second world coordinate.
            DO 340 K = 40, 1, -1
              IF (TEXT(K:K).NE.' ') GO TO 350
 340        CONTINUE
 350        K = K + 1

            TEXT(K:) = ',  ' // TXT(2)
          END IF
        ELSE IF (TXT(2).NE.' ') THEN
*         Identify second world coordinate only.
          TEXT = TXT(2)
          CALL PGSCI (CI(6))
        ELSE
*         No text to write.
          GO TO 360
        END IF

        IF (EDGE.EQ.1) THEN
          X = (XW1 + XW2)/2.0
          Y = BNDRY(1) - 1.5*YCH
          ANGL = 0.0
        ELSE IF (EDGE.EQ.2) THEN
          IF (TEXT(2:).EQ.' ') THEN
*           One character, write upright.
            X = BNDRY(2) - 1.0*XCH
            Y = (YW1 + YW2)/2.0
d2409 14
a2422 14
          ELSE
            X = BNDRY(2) - 0.5*XCH
            Y = (YW1 + YW2)/2.0
            ANGL = 90.0
          END IF
        ELSE IF (EDGE.EQ.3) THEN
          X = (XW1 + XW2)/2.0
          Y = BNDRY(3) + 0.5*YCH
          ANGL = 0.0
        ELSE IF (EDGE.EQ.4) THEN
          IF (TEXT(2:).EQ.' ') THEN
*           One character, write upright.
            X = BNDRY(4) + 1.0*XCH
            Y = (YW1 + YW2)/2.0
d2424 32
a2455 26
          ELSE
            X = BNDRY(4) + 0.5*XCH
            Y = (YW1 + YW2)/2.0
            ANGL = -90.0
          END IF
        END IF

        CALL PGQTXT (X, Y, ANGL, 0.5, TEXT, XBOX, YBOX)
        IF (K.EQ.0) THEN
          CALL PGPTXT (X, Y, ANGL, 0.5, TEXT)
        ELSE
*         Two-colour annotation.
          CALL PGPTXT (XBOX(1), YBOX(1), ANGL, 0.0, TEXT(:K))
          CALL PGSCI (CI(6))
          CALL PGPTXT (XBOX(4), YBOX(4), ANGL, 1.0, TEXT(K+1:))
        END IF

*       Update the boundary.
        IF (YBOX(1).LT.BNDRY(1)) BNDRY(1) = YBOX(1)
        IF (YBOX(3).LT.BNDRY(1)) BNDRY(1) = YBOX(3)
        IF (XBOX(1).LT.BNDRY(2)) BNDRY(2) = XBOX(1)
        IF (XBOX(3).LT.BNDRY(2)) BNDRY(2) = XBOX(3)
        IF (YBOX(1).GT.BNDRY(3)) BNDRY(3) = YBOX(1)
        IF (YBOX(3).GT.BNDRY(3)) BNDRY(3) = YBOX(3)
        IF (XBOX(1).GT.BNDRY(4)) BNDRY(4) = XBOX(1)
        IF (XBOX(3).GT.BNDRY(4)) BNDRY(4) = XBOX(3)
d2460 10
a2469 10
        CALL PGSCI (CI(7))
        X = (XW1 + XW2)/2.0
        Y = BNDRY(3) + 0.5*YCH
        CALL PGQTXT (X, Y, 0.0, 0.5, IDENTS(3), XBOX, YBOX)
        CALL PGPTXT (X, Y, 0.0, 0.5, IDENTS(3))

*       Update the boundary.
        IF (XBOX(1).LT.BNDRY(2)) BNDRY(2) = XBOX(1)
        IF (YBOX(3).GT.BNDRY(3)) BNDRY(3) = YBOX(3)
        IF (XBOX(3).GT.BNDRY(4)) BNDRY(4) = XBOX(3)
d2484 1
a2484 1
* MJD to/from Gregorian calendar date.
d2486 17
a2502 16
* Given:
*   CODE      I         If 1, compute MJD from IY,IM,ID, else vice
*                       versa.
*
* Given and/or returned:
*   MJD       D         Modified Julian date, (MJD = JD - 2400000.5).
*   IY        I         Year.
*   IM        I         Month (for CODE.EQ.1 may exceed 12, or be zero,
*                       or negative).
*   ID        I         Day of month (for CODE.EQ.1, may exceed the
*                       legitimate number of days in the month, or be
*                       zero, or negative).
*
* Notes:
*   These algorithms are from D.A. Hatcher, QJRAS 25, 53-55, as modified
*   by P.T. Wallace for use in SLALIB (subroutines CLDJ and DJCL).
d2512 13
a2524 13
*       Calendar date to MJD.
        IF (IM.LT.1) THEN
          JY = IY - 1 + IM/12
          JM = 12 + MOD(IM,12)
        ELSE
          JY = IY + (IM-1)/12
          JM = MOD(IM-1,12) + 1
        END IF

        MJD =DBLE((1461*(JY - (12-JM)/10 + 4712))/4
     :          +(306*MOD(JM+9, 12) + 5)/10
     :          -(3*((JY - (12-JM)/10 + 4900)/100))/4
     :          + ID - 2399904)
d2527 2
a2528 2
*       MJD to calendar date.
        JD = 2400001 + INT(MJD)
d2530 2
a2531 2
        N4 =  4*(JD + ((2*((4*JD - 17918)/146097)*3)/4 + 1)/2 - 37)
        DD = 10*(MOD(N4-237, 1461)/4) + 5
d2533 3
a2535 3
        IY = N4/1461 - 4712
        IM = MOD(2 + DD/306, 12) + 1
        ID = MOD(DD, 306)/10 + 1
d2544 2
a2545 2
* This FORTRAN wrapper on PGSBOX exists solely to define fixed-length
* CHARACTER arguments for cpgsbox().
d2547 1
a2547 1
* Author: Mark Calabretta, Australia Telescope National Facility
d2550 2
a2551 2
     :  GCODE, TIKLEN, NG1, GRID1, NG2, GRID2, DOEQ, NLFUNC, NLC, NLI,
     :  NLD, NLCPRM, NLIPRM, NLDPRM, NC, IC, CACHE, IERR)
d2564 2
a2565 2
     :  TIKLEN, NG1, GRID1, NG2, GRID2, DOEQ, NLFUNC, NLC, NLI, NLD,
     :  NLCPRM, NLIPRM, NLDPRM, NC, IC, CACHE, IERR)
d2573 2
a2574 2
* This FORTRAN wrapper on PGLBOX exists solely to define fixed-length
* CHARACTER arguments for cpglbox().
d2576 1
a2576 1
* Author: Mark Calabretta, Australia Telescope National Facility
d2579 1
a2579 1
     :  NG1, GRID1, NG2, GRID2, DOEQ, NC, IC, CACHE, IERR)
d2587 1
a2587 1
     :  GRID1, NG2, GRID2, DOEQ, NC, IC, CACHE, IERR)
@


4.3.1.3
log
@In PGCRLB, when labelling is separable, prefer labels at the bottom or
left if there are 4 or more (was 2 or more).  Ignore unlabelled edges
when determining how many fields are required in sexagesimal labels.
Minor simplification in skipping unlabelled edges.
@
text
@d31 1
a31 1
* $Id: pgsbox.f,v 4.3.1.2 2009/07/23 04:17:17 cal103 Exp cal103 $
d586 1
a586 6
*  Find world coordinate ranges:
*  WMIN(1:2)  ...lower limit of each world coordinate element.
*  WMAX(1:2)  ...upper limit of each world coordinate element.
*  GSTEP(1:2) ...spacing between grid lines for each element.
*  NSTEP(1:2) ...number of plotting steps between WMIN and WMAX.
*  SW(1:2)    ...increment in world coordinate between steps.
d1712 1
a1712 1
            IF (NI(1,1).GT.3 .OR. NI(1,1).GT.NI(1,3)) THEN
d1735 1
a1735 1
            IF (NI(1,2).GT.3 .OR. NI(1,2).GT.NI(1,4)) THEN
d1758 1
a1758 1
            IF (NI(2,1).GT.3 .OR. NI(2,1).GT.NI(2,3)) THEN
d1765 1
a1765 1
            IF (NI(2,2).GT.3 .OR. NI(2,2).GT.NI(2,4)) THEN
a1859 1
* Need to be a bit smarter here about how many fields to write.
a1871 8
*         Label this edge with this coordinate element?
          EDGE = NINT(CACHE(1,J))
          IF (IWRLD.EQ.1) THEN
            IF (MOD(SKIP(EDGE),2).NE.1) GO TO 150
          ELSE
            IF (MOD(SKIP(EDGE)/2,2).NE.1) GO TO 150
          END IF

a1991 7
*       Label this edge with this coordinate element?
        IF (IWRLD.EQ.1) THEN
          IF (MOD(SKIP(EDGE),2).NE.1) GO TO 230
        ELSE
          IF (MOD(SKIP(EDGE)/2,2).NE.1) GO TO 230
        END IF

d1994 6
d2005 6
d2016 6
d2027 6
d2134 1
a2134 2
          IF (L.GE.-1 .AND.
     :      .NOT.(L.LE.0 .AND. K.GT.1 .AND. LM.EQ.0 .AND. LS.EQ.0)) THEN
d2136 1
@


4.3.1.4
log
@Be a lot smarter about choosing which grid lines will have sexgesimal
labels in order to minimize the number of fields required.
@
text
@d1558 5
a1562 5
      INTEGER   CI(7), EDGE, EDJE, IC, ID, ID2, IM, IM2, IMAG(2), ITER,
     :          IWRLD, IY, IY2, J, JC, K, K1, K2, KWRLD, L, LABCTL, LD,
     :          LM, LMAG(2), LS, LV, M, M1, M2, MM, NC, NCH, NI(2,0:4),
     :          NLAB, NLABS(2,-2:6), NSWAP, PP, PRVDEG(2), PRVMIN(2),
     :          PRVEDG, PRVYR(2), SEXSUP(2), SKIP(4), SKOP(4)
d1824 1
a1824 1
*     Mark labels as unwanted by setting their edges negative.
a1828 9
      DO 120 J = 1, IC
        EDGE  = NINT(CACHE(1,J))
        IWRLD = NINT(CACHE(3,J))
        IF (IWRLD.EQ.1) THEN
          IF (MOD(SKIP(EDGE),2).NE.1) CACHE(1,J) = -EDGE
        ELSE
          IF (MOD(SKIP(EDGE)/2,2).NE.1) CACHE(1,J) = -EDGE
        END IF
 120  CONTINUE
d1839 1
a1839 1
        DO 130 J = 1, IC
d1843 1
a1843 1
            IF (CACHE(4,J).EQ.0D0) GO TO 130
d1847 1
a1847 1
 130    CONTINUE
d1857 1
a1857 1
          DO 140 J = 1, IC
d1860 1
a1860 1
 140      CONTINUE
d1865 1
d1870 2
a1871 9
        DO 150 K = -2, 6
          NLABS(1,K) = 0
          NLABS(2,K) = 0
 150    CONTINUE

        DO 180 J = 1, IC
*         Use this label?
          EDGE = NINT(CACHE(1,J))
          IF (EDGE.LT.0) GO TO 180
d1873 1
d1876 9
a1884 1
          IF (.NOT.SEXA(IWRLD)) GO TO 180
d1893 1
d1898 1
a1898 1
            DO 160 K = 1, 6
d1901 2
a1902 2
                L = 7 - K
                GO TO 170
d1904 2
a1905 3
 160        CONTINUE
          ELSE
            LS = INT(TMP)
d1907 1
a1907 1
              L =  0
d1909 1
a1909 3
              L = -1
            ELSE
              L = -2
d1912 1
a1912 38

*         Use CACHE(1,J) temporarily to hold L.
 170      NLABS(IWRLD,L) = NLABS(IWRLD,L) + 1
          CACHE(1,J) = CACHE(1,J) + 0.1 + L/100.0
 180    CONTINUE

*       How many fields are needed to get enough labels?
        DO 200 IWRLD = 1, 2
          NLAB = 0
          DO 190 K = -2, 6
            NLAB = NLAB + NLABS(IWRLD,K)
            IF (NLAB.GT.3 .OR. K.EQ.6) THEN
              LMAG(IWRLD) = K
              GO TO 200
            END IF
            NLABS(IWRLD,K+1) = NLABS(IWRLD,K) + NLABS(IWRLD,K+1)
 190      CONTINUE
 200    CONTINUE

*       Disable unwanted labels.
        DO 210 J = 1, IC
*         Use this label?
          EDGE = NINT(CACHE(1,J))
          IF (EDGE.LT.0) GO TO 210

*         Skip non-sexagesimal coordinates.
          IWRLD = NINT(CACHE(3,J))
          IF (.NOT.SEXA(IWRLD)) GO TO 210

          L = NINT(100*MOD(CACHE(1,J),1.0)) - 10
          IF (L.LE.LMAG(IWRLD)) THEN
*           Wanted.
            CACHE(1,J) = EDGE
          ELSE
*           Not wanted.
            CACHE(1,J) = -EDGE
          END IF
 210    CONTINUE
d1945 1
a1945 1
      DO 300 J = 1, IC
d1950 1
a1950 1
        EDGE = ABS(NINT(CACHE(1,J)))
d1965 3
a1967 4
            IF (MOD(EDGE,2).EQ.0) THEN
              DO 220 K = J, IC
                EDJE = ABS(NINT(CACHE(1,K)))
                IF (EDJE.NE.EDGE) GO TO 230
d1970 1
a1970 1
                IF (SEXSUP(KWRLD).EQ.1) GO TO 220
d1992 1
a1992 1
 220          CONTINUE
d1995 1
a1995 1
 230      CONTINUE
d2006 6
a2011 6
*       Fix up edge encoding.
        EDGE = NINT(CACHE(1,J))
        CACHE(1,J) = ABS(EDGE)

*       Use this label?
        IF (EDGE.LT.0) GO TO 300
d2183 4
a2186 4
            DO 240 K = 1, 8
              IF (TEXT(K:K).NE.' ') GO TO 250
 240        CONTINUE
 250        TEXT = '10' // ESCAPE // 'u' // TEXT(K:8)
d2197 2
a2198 2
            WRITE (TEXT, 260) IY, IM, ID
 260        FORMAT (I12,'/',I2.2,'/',I2.2)
d2200 4
a2203 4
            DO 270 K = 1, 12
              IF (TEXT(K:K).NE.' ') GO TO 280
 270        CONTINUE
 280        TEXT = TEXT(K:18)
d2206 2
a2207 2
            WRITE (TEXT, 290) IM, ID
 290        FORMAT (I2.2,'/',I2.2)
d2263 1
a2263 2
            EDJE = ABS(NINT(CACHE(1,J-1)))
            IF (EDJE.EQ.EDGE) THEN
d2274 1
a2274 2
            EDJE = ABS(NINT(CACHE(1,J+1)))
            IF (EDJE.EQ.EDGE) THEN
d2285 1
a2285 1
*           Draw outside pip mark to disambiguate grid lines.
d2302 1
a2302 1
 300  CONTINUE
d2307 1
a2307 1
      DO 430 EDGE = 1, 4
d2310 1
a2310 1
        DO 500 IWRLD = 1, 2
d2313 1
a2313 1
          IF (MOD(SKOP(EDGE)/IWRLD,2).EQ.0) GO TO 500
d2317 1
a2317 1
          DO 310 K = 1, L
d2320 1
a2320 1
              GO TO 320
d2322 1
a2322 1
 310      CONTINUE
d2324 1
a2324 1
 320      IF (IMAG(IWRLD).NE.0 .OR. FTYPE(IWRLD).EQ.'y') THEN
d2326 4
a2329 4
            DO 330 K = 40, 1, -1
              IF (TXT(IWRLD)(K:K).NE.' ') GO TO 340
 330        CONTINUE
 340        K = K + 1
d2339 6
a2344 6
              WRITE (TEXT, 350) IY, IM, ID
 350          FORMAT (I12,'/',I2.2,'/',I2.2)
              DO 360 L = 1, 12
                IF (TEXT(L:L).NE.' ') GO TO 370
 360          CONTINUE
 370          TXT(IWRLD)(K:) = ' (' // TEXT(L:18)
d2348 1
a2348 1
              WRITE (TEXT, 350) IY2, IM2, ID2
d2360 4
a2363 4
                DO 380 L = 1, 12
                  IF (TEXT(L:L).NE.' ') GO TO 390
 380            CONTINUE
 390            TXT(IWRLD)(K:) = ' - ' // TEXT(L:18) // ')'
d2368 1
a2368 1
 500    CONTINUE
d2378 4
a2381 4
            DO 410 K = 40, 1, -1
              IF (TEXT(K:K).NE.' ') GO TO 420
 410        CONTINUE
 420        K = K + 1
d2391 1
a2391 1
          GO TO 430
d2445 1
a2445 1
 430  CONTINUE
a2460 1

@


4.3.1.5
log
@Two bug fixes and further refinements for tick marks used to associate
labels with grid lines in high-density regions.
@
text
@d31 1
a31 1
* $Id: pgsbox.f,v 4.3.1.4 2009/08/04 06:48:38 cal103 Exp cal103 $
d1558 5
a1562 6
      INTEGER   CI(7), DOLAB(4), EDGE, EDJE, IC, ID, ID2, IM, IM2,
     :          IMAG(2), ITER, IWRLD, IY, IY2, J, JC, K, K1, K2, KWRLD,
     :          L, LABCTL, LD, LM, LMAG(2), LS, LV, M, M1, M2, MM, NC,
     :          NCH, NI(2,0:4), NLAB, NLABS(2,-2:6), NSWAP, PP,
     :          PRVDEG(2), PRVMIN(2), PRVEDG, PRVYR(2), SEXSUP(2),
     :          SKOP(4)
d1825 4
a1828 4
      DOLAB(1) = MOD(L,10)
      DOLAB(2) = MOD(L/10,10)
      DOLAB(3) = MOD(L/100,10)
      DOLAB(4) = MOD(L/1000,10)
d1833 1
a1833 1
          IF (MOD(DOLAB(EDGE),2).NE.1) CACHE(1,J) = -EDGE
d1835 1
a1835 1
          IF (MOD(DOLAB(EDGE)/2,2).NE.1) CACHE(1,J) = -EDGE
d1990 1
a1990 1
      DO 340 J = 1, IC
d2057 1
a2057 1
        IF (EDGE.LT.0) GO TO 340
d2308 2
a2309 11
          K = J - 1
          IF (DOLAB(EDGE).NE.3) THEN
*           Only one coordinate element labelled on this edge, no need
*           to worry about grid lines belonging to the other.
            DO 300 K = J-1, 1, -1
              IF (IWRLD.EQ.NINT(CACHE(3,K))) GO TO 310
 300        CONTINUE
          END IF

 310      IF (K.GE.1) THEN
            EDJE = ABS(NINT(CACHE(1,K)))
d2312 1
a2312 1
                IF (XBOX(1).LT.CACHE(2,K)) TICKIT = .TRUE.
d2314 1
a2314 1
                IF (YBOX(1).LT.CACHE(2,K)) TICKIT = .TRUE.
d2320 2
a2321 11
          K = J + 1
          IF (DOLAB(EDGE).NE.3) THEN
*           Only one coordinate element labelled on this edge, no need
*           to worry about grid lines belonging to the other.
            DO 320 K = J+1, IC
              IF (IWRLD.EQ.NINT(CACHE(3,K))) GO TO 330
 320        CONTINUE
          END IF

 330      IF (K.LE.IC) THEN
            EDJE = ABS(NINT(CACHE(1,K)))
d2324 1
a2324 1
                IF (XBOX(3).GT.CACHE(2,K)) TICKIT = .TRUE.
d2326 1
a2326 1
                IF (YBOX(3).GT.CACHE(2,K)) TICKIT = .TRUE.
d2350 1
a2350 1
 340  CONTINUE
d2355 1
a2355 1
      DO 470 EDGE = 1, 4
d2358 1
a2358 1
        DO 440 IWRLD = 1, 2
d2361 1
a2361 1
          IF (MOD(SKOP(EDGE)/IWRLD,2).EQ.0) GO TO 440
d2365 1
a2365 1
          DO 350 K = 1, L
d2368 1
a2368 1
              GO TO 360
d2370 1
a2370 1
 350      CONTINUE
d2372 1
a2372 1
 360      IF (IMAG(IWRLD).NE.0 .OR. FTYPE(IWRLD).EQ.'y') THEN
d2374 4
a2377 4
            DO 370 K = 40, 1, -1
              IF (TXT(IWRLD)(K:K).NE.' ') GO TO 380
 370        CONTINUE
 380        K = K + 1
d2387 6
a2392 6
              WRITE (TEXT, 390) IY, IM, ID
 390          FORMAT (I12,'/',I2.2,'/',I2.2)
              DO 400 L = 1, 12
                IF (TEXT(L:L).NE.' ') GO TO 410
 400          CONTINUE
 410          TXT(IWRLD)(K:) = ' (' // TEXT(L:18)
d2396 1
a2396 1
              WRITE (TEXT, 390) IY2, IM2, ID2
d2408 4
a2411 4
                DO 420 L = 1, 12
                  IF (TEXT(L:L).NE.' ') GO TO 430
 420            CONTINUE
 430            TXT(IWRLD)(K:) = ' - ' // TEXT(L:18) // ')'
d2416 1
a2416 1
 440    CONTINUE
d2426 4
a2429 4
            DO 450 K = 40, 1, -1
              IF (TEXT(K:K).NE.' ') GO TO 460
 450        CONTINUE
 460        K = K + 1
d2439 1
a2439 1
          GO TO 470
d2493 1
a2493 1
 470  CONTINUE
@


4.2
log
@PGSBOX 4.2
@
text
@d3 2
a4 2
*   PGSBOX 4.2 - a non-linear coordinate axis plotter for PGPLOT.
*   Copyright (C) 1997-2005, Mark Calabretta
d6 14
a19 13
*   PGSBOX is free software; you can redistribute it and/or modify it under
*   the terms of the GNU General Public License as published by the Free
*   Software Foundation; either version 2 of the License, or (at your option)
*   any later version.
*
*   PGSBOX is distributed in the hope that it will be useful, but WITHOUT ANY
*   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
*   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
*   details.
*
*   You should have received a copy of the GNU General Public License along
*   with PGSBOX; if not, write to the Free Software Foundation, Inc.,
*   59 Temple Place, Suite 330, Boston, MA  02111-1307, USA
d31 1
a31 1
*   $Id: pgsbox.f,v 4.1 2005/08/26 13:03:06 cal103 Exp cal103 $
a266 9
*                        The following status returns are recognized for
*                        opcodes +2 and +1
*                          -1: Accept the returned (x,y) coordinates but
*                              do not consider this as one end of a
*                              crossing segment for labelling world
*                              coordinate 1.
*                          -2: Ditto for world coordinate 2.
*                          -3: Ditto for world coordinates 1 and 2.
*
d415 9
d663 1
a663 1
                        WJUMP = WJUMP + SIGN(WJUMP,180D0)
d683 1
a683 1
                        WJUMP = WJUMP + SIGN(WJUMP,180D0)
d1270 4
a1273 2
                     IF (NP.GT.0) CALL PGLINE(NP, XR, YR)
                     GO TO 110
a1370 2
*                                 X1 = XR(NP)
*                                 Y1 = YR(NP)
@


4.2.1.1
log
@PGSBOX 4.2 development branch.
@
text
@d3 1
a3 1
*   PGSBOX 4.3 - a non-linear coordinate axis plotter for PGPLOT.
d30 1
a30 1
*   $Id: pgsbox.f,v 4.2 2005/09/21 13:27:15 cal103 Exp cal103 $
@


4.2.1.2
log
@When ironing out rotations through 360 degrees in determining the world
coordinate range, the SIGN() intrinsic was called with reversed arguments
and consequently the range could be severely overestimated.
@
text
@d30 1
a30 1
*   $Id: pgsbox.f,v 4.2.1.1 2005/12/05 03:23:34 cal103 Exp cal103 $
d662 1
a662 1
                        WJUMP = WJUMP + SIGN(180D0,WJUMP)
d682 1
a682 1
                        WJUMP = WJUMP + SIGN(180D0,WJUMP)
@


4.2.1.3
log
@If NLFUNC with OPCODE.EQ.2 returns IERR.NE.0 then flush the plotting buffer
(as before) and then return to "get end-point context" to try to pick the
grid line up at a later point; relocated prologue comments for IERR return
from NLFUNC which were incorrectly attached to IERR return from PGSBOX.
@
text
@d30 1
a30 1
*   $Id: pgsbox.f,v 4.2.1.2 2005/12/05 03:26:34 cal103 Exp cal103 $
d266 9
a422 9
*                        The following status returns are recognized for
*                        opcodes +2 and +1
*                          -1: Accept the returned (x,y) coordinates but
*                              do not consider this as one end of a
*                              crossing segment for labelling world
*                              coordinate 1.
*                          -2: Ditto for world coordinate 2.
*                          -3: Ditto for world coordinates 1 and 2.
*
d1269 2
a1270 4
                     IF (NP.GT.1) CALL PGLINE(NP, XR, YR)
                     NP = 0
                     GETEND = .TRUE.
                     GO TO 100
d1368 2
@


4.2.1.4
log
@Switched to LGPL 3.0.
@
text
@d3 2
a4 2
*   PGSBOX 4.3 - an implementation of the FITS WCS standard.
*   Copyright (C) 1997-2007, Mark Calabretta
d6 13
a18 14
*   This file is part of PGSBOX.
*
*   PGSBOX is free software: you can redistribute it and/or modify
*   it under the terms of the GNU Lesser General Public License as
*   published by the Free Software Foundation, either version 3 of
*   the License, or (at your option) any later version.
*
*   PGSBOX is distributed in the hope that it will be useful, but
*   WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*   GNU Lesser General Public License for more details.
*
*   You should have received a copy of the GNU Lesser General Public
*   License along with PGSBOX.  If not, see http://www.gnu.org/licenses.
d30 1
a30 1
*   $Id: pgsbox.f,v 4.2.1.3 2005/12/06 06:46:09 cal103 Exp cal103 $
@


4.1
log
@PGSBOX 4.1: initialized WORLD(9) and XY(9) in a DATA statement so that
purify would not flag accesses to uninitialized memory for WCS that contain
more than two axes; likewise, set CJ() before branching to PGCRLB, and also
don't set G1(0) = GRID1(0) or G0(2) = GRID2(0) if NG1.NE.0 or NG2.NE.0 since
they probably won't have been initialized.
@
text
@d3 1
a3 1
*   PGSBOX 4.1 - a non-linear coordinate axis plotter for PGPLOT.
d30 1
a30 1
*   $Id: pgsbox.f,v 4.0 2005/02/04 12:21:32 cal103 Exp cal103 $
@


4.0
log
@PGSBOX 4.0: changed from LGPL to GPL.
@
text
@d3 1
a3 1
*   PGSBOX 4.0 - a non-linear coordinate axis plotter for PGPLOT.
d30 1
a30 1
*   $Id: pgsbox.f,v 3.6 2004/08/24 08:36:29 cal103 Exp cal103 $
d506 1
d508 3
a510 2
      DATA W1X0, W1PREV, W2X0, W2PREV /4 * 0.0/
      DATA IW0 /0/
d571 10
d628 1
a628 1
         DO 30 IY = 0, NY
d637 1
a637 1
            DO 20 IX = 0, NX, KX
d722 2
a723 2
 20         CONTINUE
 30      CONTINUE
d732 1
a732 1
         DO 40 J = 1, 2
d768 1
a768 1
 40      CONTINUE
d799 4
a802 3
      G0(1) = GRID1(0)
      G0(2) = GRID2(0)
      DO 50 J = 1, 2
d1049 1
a1049 1
 50   CONTINUE
d1064 1
a1064 1
      DO 60 J = 1, 2
d1108 1
a1108 1
 60   CONTINUE
d1118 1
a1118 1
      DO 70 J = 1, 2
a1139 10
         END IF
 70   CONTINUE

*     Determine initial colour.
      CALL PGQCI (CI0)
      DO 80 J = 1, 7
         IF (CI(J).GE.0) THEN
            CJ(J) = CI(J)
         ELSE
            CJ(J) = CI0
@


3.6
log
@PGSBOX 3.6: "error status/code/number" is now referred to consistently as the
"status return value".
@
text
@d3 2
a4 2
*   PGSBOX 3.6 - a non-linear coordinate axis plotter for PGPLOT.
*   Copyright (C) 1997-2004, Mark Calabretta
d6 13
a18 13
*   This library is free software; you can redistribute it and/or modify
*   it under the terms of the GNU Library General Public License as
*   published by the Free Software Foundation; either version 2 of the
*   License, or (at your option) any later version.
*
*   This library is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*   Library General Public License for more details.
*
*   You should have received a copy of the GNU Library General Public
*   License along with this library; if not, write to the Free
*   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
d30 1
a30 1
*   $Id: pgsbox.f,v 3.5 2004/06/28 05:31:36 mcalabre Exp mcalabre $
d40 1
a40 1
*   world coordinate axes which is not provided by the standard PGPLOT
d368 1
a368 1
*                               which describe a path between this and
d1912 1
a1912 1
*     These will define a box which just contains the labels.
@


3.5
log
@PGSBOX 3.5: increased the dimension of the WORLD and XY vectors from 2 to 9
to accomodate higher-dimensional coordinate representations of up to 9
elements; assigned some variables in DATA to stop compiler messages about
uninitialized variables.
@
text
@d3 1
a3 1
*   PGSBOX 3.5 - a non-linear coordinate axis plotter for PGPLOT.
d30 1
a30 1
*   $Id: pgsbox.f,v 3.4 2004/02/10 23:56:37 mcalabre Exp mcalabre $
d260 1
a260 1
*      IERR     I        Error status
d417 1
a417 1
*      IERR     I        Error status
@


3.4
log
@PGSBOX 3.4
@
text
@d3 1
a3 1
*   PGSBOX 3.4 - a non-linear coordinate axis plotter for PGPLOT.
d28 3
a459 2
*   Author: Mark Calabretta, Australia Telescope National Facility
*   $Id: pgsbox.f,v 3.3 2003/10/22 08:30:06 mcalabre Exp mcalabre $
d482 1
a482 1
     :          WMIN(2), WORLD(2), XY(2)
d504 5
d1312 1
d1399 1
d1502 3
a1509 4

*  Clean up.
      IF (OVERFL) IERR = 3

d1570 4
d2268 1
@


3.3
log
@PGSBOX 3.3: now recognizes status returns -1, -2, and -3 from NLFUNC for
opcodes +2 and +1 which cause it to accept the returned (x,y) coordinates
but not consider them as one end of a crossing segment for labelling world
coordinate 1, 2, or both; take care not to lose vertical tick marks (and hence
labels) at the left or right edge of the frame and likewise for horizontal
tick marks at the top or bottom edge of the frame; tightened up the test for
cycles in angle to catch the case where the coordinate value spans a full 360
degrees; no longer accept frame crossings that are too oblique - floating
point rounding errors may cause grid lines that should otherwise track along
the frame to weave down it from side-to-side resulting in spurious crossing
points; rationalized usage of PGQWIN in PGLBOX; adjusted NSTEP for each world
coordinate so that SW(J) divides GSTEP(J) - but why?
@
text
@d3 2
a4 2
*   PGSBOX 3.3 - a non-linear coordinate axis plotter for PGPLOT.
*   Copyright (C) 1997-2003, Mark Calabretta
d458 1
a458 1
*   $Id: pgsbox.f,v 3.2 2003/09/09 08:00:24 mcalabre Exp mcalabre $
@


3.2
log
@PGSBOX 3.2: added an ENTRY point, PGLBOX, that provides a simplified
interface to PGSBOX for linear axes without having to specify an NLFUNC or
the associated parameters; added PGLBOK, a FORTRAN wrapper on PGLBOX that
defines fixed-length CHARACTER arguments for cpglbox().
@
text
@d3 1
a3 1
*   PGSBOX 3.2 - a non-linear coordinate axis plotter for PGPLOT.
d263 9
d329 1
a329 1
*          -360 -> 0 -> 359 -> 0 -> 359
d458 1
a458 1
*   $Id: pgsbox.f,v 3.1 2003/04/28 08:54:22 mcalabre Exp mcalabre $
d468 1
a468 1
     :          MAJOR, OVERFL, PREVIN
d470 4
a473 4
     :          ID, IERR, IM, ISTEP, IW0, IWJ, IWK, IX, IY, J, K, KX, L,
     :          LABCTL, LABDEN, LDIV(2), LTABL(6,2:6), NC, NG(2), NG1,
     :          NG2, NLC, NLD, NLI, NLIPRM(NLI), NP, NWJ, NX, NY,
     :          TCODE(2,4)
d475 2
a476 2
     :          XMIN, XPOINT, XR(BUFSIZ), XSCL, XSPAN, XVP1, XVP2, Y1,
     :          Y2, YMIN, YR(BUFSIZ), YSCL, YSPAN, YVP1, YVP2
d479 3
a481 2
     :          NLDPRM(NLD), STEP, TIKLEN, TMP, VMAX(2,2), VMIN(2,2),
     :          WMAX(2), WMIN(2), WORLD(2), XY(2)
a489 4
*     Number of steps per grid line.
      INTEGER NSTEP
      PARAMETER (NSTEP = 80)

d494 3
d519 1
a519 1
      
a534 4
      CALL PGQWIN (XMIN, XSPAN, YMIN, YSPAN)
      XSPAN = XSPAN - XMIN
      YSPAN = YSPAN - YMIN
      
d567 5
d609 1
d623 2
a624 2
                  WORLD(1) = XMIN + XY(1)*XSPAN
                  WORLD(2) = YMIN + XY(2)*YSPAN
d632 41
d1078 1
d1080 9
d1218 2
a1219 2
            DO 100 IWK = 0, NSTEP
               WORLD(K) = WMIN(K) + IWK*(DW(K)/NSTEP)
d1224 2
a1225 2
                     XY(1) = (WORLD(1) - XMIN)/XSPAN
                     XY(2) = (WORLD(2) - YMIN)/YSPAN
d1231 1
a1231 1
                  IF (IERR.EQ.0) THEN
d1243 2
d1251 2
a1252 2
                     XY(1) = (WORLD(1) - XMIN)/XSPAN
                     XY(2) = (WORLD(2) - YMIN)/YSPAN
d1258 1
a1258 1
                  IF (IERR.NE.0) THEN
d1274 18
a1291 2
                  INSIDE = X2.GE.BLC(1) .AND. X2.LE.TRC(1) .AND.
     :                     Y2.GE.BLC(2) .AND. Y2.LE.TRC(2)
d1305 2
a1306 1
                           IF (X2.NE.X1) THEN
d1321 1
a1321 1
                           IF (Y2.NE.Y1) THEN
d1336 18
a1353 11
*                          Record this crossing point.
                           IF (TCODE(J,FSEG).NE.0) THEN
                              IF (IC.LT.NC-1) THEN
                                 IC = IC + 1
                                 CACHE(1,IC) = FSEG
                                 CACHE(2,IC) = XPOINT
                                 CACHE(3,IC) = J
                                 CACHE(4,IC) = WORLD(J)
                              ELSE
*                                Cache overflow.
                                 OVERFL = .TRUE.
a1354 1
                           END IF
d1356 11
a1366 10
                           IF (TCODE(J,FSEG).GT.0) THEN
*                             Just want tick marks.
*                              X1 = XR(NP)
*                              Y1 = YR(NP)
                              S = SQRT((XSCL*(X2-X1))**2 +
     :                                 (YSCL*(Y2-Y1))**2)/TCODE(J,FSEG)
                              IF (MAJOR) S = S/1.5
                              NP = NP + 1
                              XR(NP) = XR(NP-1) + (X2-X1)*TIKLEN/S
                              YR(NP) = YR(NP-1) + (Y2-Y1)*TIKLEN/S
d1368 3
a1370 2
                              CALL PGLINE(NP, XR, YR)
                              NP = 1
d1374 1
a1374 1
                        IF (GCODE(J).EQ.2) THEN
d1390 3
a1392 1
                           IF (X2.NE.X1) THEN
d1407 1
a1407 1
                           IF (Y2.NE.Y1) THEN
d1422 25
a1446 11
*                          Record this crossing point.
                           IF (TCODE(J,FSEG).NE.0) THEN
                              IF (IC.LT.NC-1) THEN
                                 IC = IC + 1
                                 CACHE(1,IC) = FSEG
                                 CACHE(2,IC) = XPOINT
                                 CACHE(3,IC) = J
                                 CACHE(4,IC) = WORLD(J)
                              ELSE
*                                Cache overflow.
                                 OVERFL = .TRUE.
a1447 1
                           END IF
d1449 13
a1461 12
                           IF (TCODE(J,FSEG).GT.0) THEN
*                             Just want tick marks.
                              X1 = XR(NP)
                              Y1 = YR(NP)
                              X2 = XR(NP-1)
                              Y2 = YR(NP-1)
                              S = SQRT((XSCL*(X2-X1))**2 +
     :                                 (YSCL*(Y2-Y1))**2)/TCODE(J,FSEG)
                              IF (MAJOR) S = S/1.5
                              XR(NP-1) = X1 + (X2-X1)*TIKLEN/S
                              YR(NP-1) = Y1 + (Y2-Y1)*TIKLEN/S
                           END IF
d1463 5
a1467 3
*                          Flush buffer.
                           IF (TCODE(J,FSEG).NE.0) THEN
                              CALL PGLINE(NP, XR, YR)
a1468 1
                           NP = 0
d1478 1
d1952 1
a1952 1
                        TMP = ABS(MOD(CACHE(4,K),1D0)*24D0) 
d1954 1
a1954 1
                        TMP = ABS(CACHE(4,K)) 
d2060 1
a2060 1
               TMP = ABS(MOD(CACHE(4,J),1D0)*24D0) 
d2066 1
a2066 1
               TMP = ABS(CACHE(4,J)) 
@


3.1
log
@PGSBOX 3.1
Do calendar date axes; speedup the max/min search - if only tickmarks are
required there is no need to search the interior of the image; return margin
widths in CACHE(,NC); fixed a buglet which caused ticks at the frame edges to
be skipped; return error 3 if CACHE overflows; renamed variable TYPE (FORTRAN
statement) to FTYPE; updated copyright notice.
@
text
@d3 1
a3 1
*   PGSBOX 3.1 - a non-linear coordinate axis plotter for PGPLOT.
d34 11
d449 1
a449 1
*   $Id: pgsbox.f,v 3.1 2003/04/28 05:02:51 mcalabre Exp $
d451 1
a451 1
      SUBROUTINE PGSBOX (BLC, TRC, IDENTS, OPT, LABCTL, LABDEN, CI,
d458 2
a459 2
      LOGICAL   DOEDGE, DOEQ, FULLSM, GETEND, INSIDE, ISANGL(2), MAJOR,
     :          OVERFL, PREVIN
d465 3
a467 2
      REAL      BLC(2), S, TRC(2), WXY(4), X1, X2, XPOINT, XR(BUFSIZ),
     :          XSCL, XVP1, XVP2, Y1, Y2, YR(BUFSIZ), YSCL, YVP1, YVP2
d496 1
a496 4
      IF (NC.LT.1) THEN
         IERR = 3
         RETURN
      END IF
d506 37
d559 1
a559 1
      IF (LABCTL.GE.10000) GO TO 120
a564 2
      
      DOEDGE = GCODE(1).NE.2 .AND. GCODE(2).NE.2
d599 1
a599 1
         DO 20 IY = 0, NY
d608 1
a608 1
            DO 10 IX = 0, NX, KX
d611 7
a617 2
               CALL NLFUNC (-1, NLC, NLI, NLD, NLCPRM, NLIPRM, NLDPRM,
     :            WORLD, XY, CONTRL, CONTXT, IERR)
d652 2
a653 2
 10         CONTINUE
 20      CONTINUE
d662 1
a662 1
         DO 30 J = 1, 2
d698 1
a698 1
 30      CONTINUE
d731 1
a731 1
      DO 40 J = 1, 2
d978 1
a978 1
 40   CONTINUE
d993 1
a993 1
      DO 50 J = 1, 2
d1027 1
a1027 1
 50   CONTINUE
d1037 1
a1037 1
      DO 60 J = 1, 2
d1060 1
a1060 1
 60   CONTINUE
d1064 1
a1064 1
      DO 70 J = 1, 7
d1070 1
a1070 1
 70   CONTINUE
d1074 2
a1075 2
      DO 110 J = 1, 2
         IF (GCODE(J).EQ.0) GO TO 110
d1106 1
a1106 1
         DO 100 IWJ = 0, NWJ
d1112 1
a1112 1
               IF (IWJ.EQ.0) GO TO 100
d1156 1
a1156 1
            DO 90 IWK = 0, NSTEP
d1161 8
a1168 2
                  CALL NLFUNC (1, NLC, NLI, NLD, NLCPRM, NLIPRM, NLDPRM,
     :               WORLD, XY, CONTRL, CONTXT, IERR)
d1182 1
a1182 1
                  GO TO 90
d1185 9
a1193 3
               DO 80 ISTEP = 1, 1000
                  CALL NLFUNC (2, NLC, NLI, NLD, NLCPRM, NLIPRM, NLDPRM,
     :               WORLD, XY, CONTRL, CONTXT, IERR)
d1197 1
a1197 1
                     GO TO 100
d1374 1
a1374 1
                     GO TO 90
d1380 2
a1381 2
 80            CONTINUE
 90         CONTINUE
d1384 2
a1385 2
 100     CONTINUE
 110  CONTINUE
d1389 1
a1389 1
 120  IF (LABCTL.NE.-1) CALL PGCRLB (BLC, TRC, IDENTS, FTYPE, LABCTL,
d2443 22
@


1.9
log
@Reset viewport and window before returning on error.
@
text
@d3 2
a4 2
*   PGSBOX - a non-linear coordinate axis plotter for PGPLOT.
*   Copyright (C) 1997-2001, Mark Calabretta
d6 4
a9 4
*   This library is free software; you can redistribute it and/or
*   modify it under the terms of the GNU Library General Public
*   License as published by the Free Software Foundation; either
*   version 2 of the License, or (at your option) any later version.
d22 4
a25 4
*      Postal address: Dr. Mark Calabretta,
*                      Australia Telescope National Facility,
*                      P.O. Box 76,
*                      Epping, NSW, 2121,
d76 3
d218 1
a218 1
*      NC       I        Upper array index for CACHE.
d237 7
a243 1
*                        coordinate values between calls.
d250 1
d318 2
a319 1
*       provide sufficient space.
d438 1
a438 1
*   $Id: pgsbox.f,v 1.8 2001/12/07 06:08:27 mcalabre Exp mcalabre $
d447 2
a448 1
      LOGICAL   DOEQ, GETEND, INSIDE, ISANGL(2), MAJOR, PRVIN
d450 4
a453 3
     :          IERR, ISTEP, IW0, IWJ, IWK, IX, J, JX, K, L, LABCTL,
     :          LABDEN, LDIV(2), LTABL(6,2:6), NC, NG(2), NG1, NG2, NLC,
     :          NLD, NLI, NLIPRM(NLI), NP, NW(2), NX, NY, TCODE(2,4)
d460 1
a460 1
      CHARACTER IDENTS(3)*(*), NLCPRM(NLC)*1, OPT(2)*(*), TYPE(2)
d484 5
d500 2
a501 2
      TYPE(1) = OPT(1)(1:1)
      TYPE(2) = OPT(2)(1:1)
d517 7
a523 2
      IF (IC.GE.0) THEN
*        Extrema cached from a previous call.
d528 1
d530 1
a530 1
*        Coarse search to find approximate ranges.
d537 2
a538 2
         ISANGL(1) = INDEX('ABCDEFGHI',TYPE(1)).NE.0
         ISANGL(2) = INDEX('ABCDEFGHI',TYPE(2)).NE.0
d555 8
a562 2
         XY(1) = BLC(1)
         DO 20 IX = 0, NX
d564 3
a566 2
            XY(2) = BLC(2)
            DO 10 JX = 0, NY
a602 2

               XY(2) = XY(2) + DY
a603 2

            XY(1) = XY(1) + DX
d657 7
d696 16
a711 1
            IF (INDEX('ABCDEF',TYPE(J)).NE.0 .AND. STEP.GE.1D0) THEN
d737 2
a738 2
            ELSE IF (INDEX('GHI',TYPE(J)).NE.0 .AND. STEP.GE.15D0 .OR.
     :         TYPE(J).EQ.'T' .AND. STEP.GE.1D0) THEN
a739 8

               FACT = 1D0
               IF (INDEX('GHI',TYPE(J)).NE.0) THEN
*                 Rescale degrees to hours.
                  FACT = FACT/15D0
                  STEP = STEP/15D0
               END IF

d764 2
a765 2
            ELSE IF (INDEX('GHI',TYPE(J)).NE.0 .AND. STEP.LT.15D0 .OR.
     :               INDEX('DEFT',TYPE(J)).NE.0 .AND. STEP.LT.1D0) THEN
a767 8

               FACT = 1D0
               IF (INDEX('GHI',TYPE(J)).NE.0) THEN
*                 Rescale degrees to hours.
                  FACT = FACT/15D0
                  STEP = STEP/15D0
               END IF

d823 60
d903 1
a903 1
               IF (TYPE(J).EQ.'L') THEN
d945 1
a945 1
         IF (TYPE(J).EQ.'L') THEN
d948 21
d1024 1
d1037 15
a1051 1
            NW(J) = NG(J)
d1053 1
a1053 1
            NW(J) = NINT(DW(J)/GSTEP(J))
d1057 1
a1057 1
         DO 100 IWJ = 0, NW(J)
d1068 13
a1080 1
               WORLD(J) = (IW0 + IWJ)*GSTEP(J)
d1082 9
a1090 13
*              Logarithmic?
               IF (TYPE(J).EQ.'L') THEN
                  TMP = MOD(WORLD(J),1D0)
                  IF (TMP.LT.0D0) TMP = TMP + 1D0
                  L = NINT(TMP*LDIV(J))

                  IF (L.EQ.0) THEN
*                    Major tick mark.
                     MAJOR = .TRUE.
                  ELSE
*                    Adjust logarithmic scales.
                     IF (LDIV(J).LE.6) THEN
                        L = LTABL(L,LDIV(J))
d1092 8
a1099 1
                        L = L + 1
a1100 2

                     WORLD(J) = WORLD(J) - TMP + LOG10(DBLE(L))
d1124 1
a1124 1
                     PRVIN  = INSIDE
d1149 2
a1150 2
                  INSIDE = X2.GT.BLC(1) .AND. X2.LT.TRC(1) .AND.
     :                     Y2.GT.BLC(2) .AND. Y2.LT.TRC(2)
d1159 1
a1159 1
                        IF (.NOT.PRVIN) THEN
d1196 1
a1196 1
                              IF (IC.LT.NC) THEN
d1202 3
d1210 2
a1211 2
                              X1 = XR(NP)
                              Y1 = YR(NP)
d1216 2
a1217 2
                              XR(NP) = X1 + (X2-X1)*TIKLEN/S
                              YR(NP) = Y1 + (Y2-Y1)*TIKLEN/S
d1232 1
a1232 1
                        IF (PRVIN) THEN
d1272 1
a1272 1
                              IF (IC.LT.NC) THEN
d1278 3
d1310 1
a1310 1
                  PRVIN = INSIDE
d1328 2
a1329 2
 120  IF (LABCTL.NE.-1) CALL PGCRLB (BLC, TRC, IDENTS, TYPE, LABCTL, CJ,
     :   NC, IC, CACHE)
d1333 2
d1357 1
a1357 1
*      IDENTS   C(3)**   Identification strings (see PGSBOX).
d1359 1
a1359 1
*      TYPE     C(2)*1   Axis types, used for axis labelling (see
d1378 1
a1378 1
      SUBROUTINE PGCRLB (BLC, TRC, IDENTS, TYPE, LABCTL, CI, NC, IC,
d1381 5
a1385 4
      LOGICAL   ANGLE, DODEG, DOMIN, LFORCE, SEXA(2), TICKIT
      INTEGER   CI(7), EDGE, IC, IMAG(2), ITER, IWRLD, J, JC, K, K1, K2,
     :          L, LABCTL, LD, LM, LMAG(2), LS, LV, M, M1, M2, MM, NC,
     :          NCH, NI(2,0:4), NSWAP, PP, PRVD(2), PRVM(2), PRVEDG,
d1390 1
a1390 1
      DOUBLE PRECISION CACHE(4,0:NC), TMP, VS
d1392 1
a1392 1
     :          TYPE(2)*1, TXT(2)*80
d1397 2
a1398 2
      IF (INDEX('ABDEGH',TYPE(1)).NE.0 .OR.
     :    INDEX('ABDEGH',TYPE(2)).NE.0) THEN
d1400 1
a1400 5
            IF (CACHE(3,J).EQ.1D0) THEN
               IWRLD = 1
            ELSE
               IWRLD = 2
            END IF
d1402 1
a1402 1
            IF (INDEX('ADG', TYPE(IWRLD)).NE.0) THEN
d1405 1
a1405 1
            ELSE IF (INDEX('BEH', TYPE(IWRLD)).NE.0) THEN
d1414 1
a1414 1
            IF (INDEX('GHI', TYPE(IWRLD)).NE.0) THEN
d1475 2
a1476 5
         IF (CACHE(3,J).EQ.1D0) THEN
            IWRLD = 1
         ELSE
            IWRLD = 2
         END IF
a1477 2
         EDGE = NINT(CACHE(1,J))

d1656 1
a1656 1
      IF (TYPE(1).EQ.' ' .OR. TYPE(2).EQ.' ') THEN
d1660 2
a1661 7
            IF (CACHE(3,J).EQ.1D0) THEN
               IWRLD = 1
            ELSE
               IWRLD = 2
            END IF

            IF (TYPE(IWRLD).EQ.' ') THEN
d1678 1
a1678 6
               IF (CACHE(3,J).EQ.1D0) THEN
                  IWRLD = 1
               ELSE
                  IWRLD = 2
               END IF

d1685 2
a1686 2
      SEXA(1) = INDEX('DEFGHIT', TYPE(1)).NE.0
      SEXA(2) = INDEX('DEFGHIT', TYPE(2)).NE.0
a1692 6
            IF (CACHE(3,J).EQ.1D0) THEN
               IWRLD = 1
            ELSE
               IWRLD = 2
            END IF

d1694 1
d1698 6
a1703 1
            TMP = ABS(CACHE(4,J)*3600D0) + 5D-7
d1745 6
d1756 1
a1756 1
      DO 200 J = 1, IC
d1758 2
a1759 7
         IF (CACHE(3,J).EQ.1D0) THEN
            IWRLD = 1
            CALL PGSCI (CI(3))
         ELSE
            CALL PGSCI (CI(4))
            IWRLD = 2
         END IF
d1767 4
a1770 4
               PRVD(1) = -1
               PRVM(1) = -1
               PRVD(2) = -1
               PRVM(2) = -1
d1776 1
a1776 1
               IF (MOD(CACHE(1,J),2).EQ.0) THEN
d1779 9
a1787 1
                     IF (SEXSUP(NINT(CACHE(3,K))).EQ.1) GO TO 160
d1789 1
a1789 1
                     LV = INT(ABS(CACHE(4,K))*3600D0 + 5D-7)
d1793 1
a1793 1
                     TMP = ABS(CACHE(4,K)) - LD
d1797 1
a1797 1
                        SEXSUP(NINT(CACHE(3,K))) = 1
d1801 1
a1801 1
                        SEXSUP(NINT(CACHE(3,K))) = 2
d1808 3
d1820 1
a1820 1
               IF (MOD(SKIP(1),2).NE.1) GO TO 200
d1822 1
a1822 1
               IF (MOD(SKIP(1)/2,2).NE.1) GO TO 200
d1831 1
a1831 1
               IF (MOD(SKIP(2),2).NE.1) GO TO 200
d1833 1
a1833 1
               IF (MOD(SKIP(2)/2,2).NE.1) GO TO 200
d1842 1
a1842 1
               IF (MOD(SKIP(3),2).NE.1) GO TO 200
d1844 1
a1844 1
               IF (MOD(SKIP(3)/2,2).NE.1) GO TO 200
d1853 1
a1853 1
               IF (MOD(SKIP(4),2).NE.1) GO TO 200
d1855 1
a1855 1
               IF (MOD(SKIP(4)/2,2).NE.1) GO TO 200
d1864 1
a1864 1
         IF (INDEX('ABC', TYPE(IWRLD)).NE.0) THEN
d1887 1
a1887 1
            ANGLE = INDEX('DEF', TYPE(IWRLD)).NE.0
d1891 10
a1900 1
            VS = ABS(CACHE(4,J))*3600D0 + 5D-7
d1910 1
a1910 1
               TMP = ABS(CACHE(4,J)) - LD
d1917 1
a1917 1
                 DODEG = DOMIN .AND. LD.NE.PRVD(IWRLD)
d1923 2
a1924 2
               DODEG = LD.NE.PRVD(IWRLD)
               DOMIN = LM.NE.PRVM(IWRLD)
d1946 1
a1946 1
                  IF (LD.LE.9 .AND. TYPE(IWRLD).NE.'T') THEN
d1994 1
a1994 1
         ELSE IF (TYPE(IWRLD).EQ.'L') THEN
d2019 19
d2066 2
a2067 2
               IF (DODEG) PRVD(IWRLD) = LD
               IF (DOMIN) PRVM(IWRLD) = LM
d2070 5
d2083 4
a2086 9
            IF (EDGE.EQ.1) THEN
               IF (YBOX(1).LT.BNDRY(1)) BNDRY(1) = YBOX(1)
            ELSE IF (EDGE.EQ.2) THEN
               IF (XBOX(1).LT.BNDRY(2)) BNDRY(2) = XBOX(1)
            ELSE IF (EDGE.EQ.3) THEN
               IF (YBOX(2).GT.BNDRY(3)) BNDRY(3) = YBOX(2)
            ELSE IF (EDGE.EQ.4) THEN
               IF (XBOX(4).GT.BNDRY(4)) BNDRY(4) = XBOX(4)
            END IF
d2129 1
a2129 1
 200  CONTINUE
d2134 1
a2134 1
      DO 280 EDGE = 1, 4
d2137 1
a2137 1
         DO 250 IWRLD = 1, 2
d2140 1
a2140 1
            IF (MOD(SKOP(EDGE)/IWRLD,2).EQ.0) GO TO 250
d2142 1
d2144 1
a2144 1
            DO 210 K = 1, L
d2147 1
a2147 1
                  GO TO 220
d2149 1
a2149 1
 210        CONTINUE
d2151 14
a2164 4
 220        IF (IMAG(IWRLD).NE.0) THEN
               DO 230 K = 40, 1, -1
                  IF (TXT(IWRLD)(K:K).NE.' ') GO TO 240
 230           CONTINUE
d2166 27
a2192 3
*              Add scaling information.
 240           CALL PGNUMB (IMAG(IWRLD), 0, 1, EXPONT, NCH)
               TXT(IWRLD)(K+1:) = '  x10' // ESCAPE // 'u' // EXPONT
d2195 1
a2195 1
 250     CONTINUE
d2205 4
a2208 3
               DO 260 K = 40, 1, -1
                  IF (TEXT(K:K).NE.' ') GO TO 270
 260           CONTINUE
a2209 1
 270           K = K + 1
d2218 1
a2218 1
            GO TO 280
a2239 1
            BNDRY(3) = BNDRY(3) + 1.5*YCH
d2253 1
a2257 1
            CALL PGQTXT (X, Y, ANGL, 0.5, TEXT, XBOX, YBOX)
d2263 10
a2272 1
 280  CONTINUE
d2279 1
d2281 71
d2354 28
@


1.8
log
@Be much smarter about the field-suppression policy in sexagesimal formatting.
@
text
@d427 1
a427 1
*   $Id: pgsbox.f,v 1.7 2001/11/21 00:28:20 mcalabre Exp mcalabre $
d582 1
a582 1
            RETURN
d1186 1
a1186 1
      CALL PGSVP (XVP1, XVP2, YVP1, YVP2)
@


1.7
log
@Added a comment to the prologue regarding the interpretation of GRID1(0) and
GRID2(0) with values less than zero.
@
text
@d348 1
a348 1
*                        coordinates; that is the world coordinates for 
d427 1
a427 1
*   $Id: pgsbox.f,v 1.6 2001/02/23 00:36:34 mcalabre Exp mcalabre $
d1231 1
a1231 1
      LOGICAL   ANGLE, LFORCE, TICKIT
d1234 2
a1235 2
     :          NCH, NI(2,0:4), NSWAP, PP, PRVD(2), PRVH(2), PRVM(2),
     :          PRVEDG, SKIP(4), SKOP(4)
d1239 1
a1239 1
      DOUBLE PRECISION CACHE(4,0:NC), TMP
d1553 4
a1556 2
      IF (INDEX('DEFGHIT', TYPE(1)).NE.0 .OR.
     :    INDEX('DEFGHIT', TYPE(2)).NE.0) THEN
d1568 1
a1568 1
            IF (INDEX('DEFGHIT', TYPE(IWRLD)).EQ.0) GO TO 150
d1571 1
a1571 1
            TMP = ABS(CACHE(4,J)*3600D0) + 0.5D-6
d1618 1
a1618 1
      DO 180 J = 1, IC
d1630 37
a1666 6
            PRVD(1) = -1
            PRVD(2) = -1
            PRVH(1) = -1
            PRVH(2) = -1
            PRVM(1) = -1
            PRVM(2) = -1
d1676 1
a1676 1
               IF (MOD(SKIP(1),2).NE.1) GO TO 180
d1678 1
a1678 1
               IF (MOD(SKIP(1)/2,2).NE.1) GO TO 180
d1687 1
a1687 1
               IF (MOD(SKIP(2),2).NE.1) GO TO 180
d1689 1
a1689 1
               IF (MOD(SKIP(2)/2,2).NE.1) GO TO 180
d1698 1
a1698 1
               IF (MOD(SKIP(3),2).NE.1) GO TO 180
d1700 1
a1700 1
               IF (MOD(SKIP(3)/2,2).NE.1) GO TO 180
d1709 1
a1709 1
               IF (MOD(SKIP(4),2).NE.1) GO TO 180
d1711 1
a1711 1
               IF (MOD(SKIP(4)/2,2).NE.1) GO TO 180
d1722 1
a1722 1
            TMP = ABS(CACHE(4,J)) + 0.5D-6
d1741 1
a1741 1
         ELSE IF (INDEX('DEFGHIT', TYPE(IWRLD)).NE.0) THEN
d1747 2
a1748 2
            TMP = ABS(CACHE(4,J))*3600D0 + 0.5D-6
            LV = INT(TMP)
d1750 23
a1772 2
*           Degree/hour field.
            LD = LV/3600
d1775 1
a1775 1
            IF (L.EQ.-2 .OR. LD.NE.PRVD(IWRLD)) THEN
d1777 2
a1803 1

d1807 1
a1807 3
*              Arcminute/minute field.
               LV = LV - LD*3600
               LM = LV/60
d1809 2
a1810 1
               IF (L.EQ.-1 .OR. K.GT.1 .OR. LM.NE.PRVM(IWRLD)) THEN
a1822 2
                  LS = LV - LM*60

d1835 1
a1835 1
                     LV = INT(MOD(TMP,1D0)*10**L)
d1858 4
a1861 4
               DO 160 K = 1, 8
                  IF (TEXT(K:K).NE.' ') GO TO 170
 160           CONTINUE
 170           TEXT = '10' // ESCAPE // 'u' // TEXT(K:8)
d1889 1
a1889 1
            XL = XBOX(4) + XCH
d1893 4
a1896 2
            PRVD(IWRLD) = LD
            PRVM(IWRLD) = LM
d1957 1
a1957 1
 180  CONTINUE
d1962 1
a1962 1
      DO 260 EDGE = 1, 4
d1965 1
a1965 1
         DO 230 IWRLD = 1, 2
d1968 1
a1968 1
            IF (MOD(SKOP(EDGE)/IWRLD,2).EQ.0) GO TO 230
d1971 1
a1971 1
            DO 190 K = 1, L
d1974 1
a1974 1
                  GO TO 200
d1976 1
a1976 1
 190        CONTINUE
d1978 4
a1981 4
 200        IF (IMAG(IWRLD).NE.0) THEN
               DO 210 K = 40, 1, -1
                  IF (TXT(IWRLD)(K:K).NE.' ') GO TO 220
 210           CONTINUE
d1984 1
a1984 1
 220           CALL PGNUMB (IMAG(IWRLD), 0, 1, EXPONT, NCH)
d1988 1
a1988 1
 230     CONTINUE
d1998 3
a2000 3
               DO 240 K = 40, 1, -1
                  IF (TEXT(K:K).NE.' ') GO TO 250
 240           CONTINUE
d2002 1
a2002 1
 250           K = K + 1
d2011 1
a2011 1
            GO TO 260
d2057 1
a2057 1
 260  CONTINUE
@


1.6
log
@Fixed a problem with the computation of the grid world coordinate value
caused by rounding error; warn that NLFUNC must not change the input
coordinates.
@
text
@d4 1
a4 1
*   Copyright (C) 1997-2000, Mark Calabretta
d180 2
a181 2
*                           a) if GRID1(0) is non-zero it defines a
*                              uniform grid spacing.
d184 2
d193 2
a194 1
*                        returned by NLFUNC.
d427 1
a427 1
*   $Id: pgsbox.f,v 1.5 2001/02/19 02:18:18 mcalabre Exp mcalabre $
@


1.5
log
@PGCRVL -> PGSBOX.
@
text
@d344 5
d409 5
a413 1
*    1) NLFUNC must define a single-valued function, that is, each
d417 1
a417 1
*    2) Notwithstanding the fact that PGSBOX declares NLCPRM, NLIPRM,
d424 1
a424 1
*   $Id: pgsbox.f,v 1.4 2000/11/28 02:19:51 mcalabre Exp mcalabre $
d435 3
a437 3
     :          IERR, ISTEP, IWJ, IWK, IX, J, JX, K, L, LABCTL, LABDEN,
     :          LDIV(2), LTABL(6,2:6), NC, NG(2), NG1, NG2, NLC, NLD,
     :          NLI, NLIPRM(NLI), NP, NW(2), NX, NY, TCODE(2,4)
d922 1
d936 1
a936 1
               WORLD(J) = WMIN(J) + IWJ*GSTEP(J)
d1238 1
a1238 1
     :          TYPE(2)*1, TXT(2)*40
@


1.4
log
@Fixed a labelling problem caused by floating point rounding errors.
@
text
@d316 3
a318 3
*       CACHE(,0).  When a coordinate grid is plotted with multiple calls
*       to PGSBOX the initial call should always have IC set to -1 to
*       signal that PGSBOX needs to determine the extrema.  On
d415 1
a415 1
*   $Id: pgsbox.f,v 1.3 2000/11/16 01:07:29 mcalabre Exp $
@


1.3
log
@In determining the range of world coordinates return IERR = 2 if no pixels on
the test grid had valid coordinates.
@
text
@d415 1
a415 1
*   $Id: pgsbox.f,v 1.2 2000/11/15 06:44:37 mcalabre Exp mcalabre $
d1556 3
a1558 2
            LS = INT(ABS(CACHE(4,J)*3600D0) + 0.5D-6)
            LV = NINT(MOD(ABS(CACHE(4,J)*3600D0), 1D0)*1D6)
@


1.2
log
@Fixed a bug in determining the range of world coordinates when the coordinate
system is undefined in areas of the plot.
@
text
@d237 1
d415 1
a415 1
*   $Id: pgsbox.f,v 1.1 2000/11/13 07:17:22 mcalabre Exp mcalabre $
d518 1
d528 1
d566 6
@


1.1
log
@Initial revision
@
text
@d414 1
a414 1
*   $Id$
a523 1
               IF (IERR.NE.0) GO TO 10
d525 31
a555 29
               IF (WORLD(1).LT.WMIN(1)) WMIN(1) = WORLD(1)
               IF (WORLD(1).GT.WMAX(1)) WMAX(1) = WORLD(1)
               IF (WORLD(2).LT.WMIN(2)) WMIN(2) = WORLD(2)
               IF (WORLD(2).GT.WMAX(2)) WMAX(2) = WORLD(2)

               IF (ISANGL(1)) THEN
*                 Normalize to the range [0,360).
                  WORLD(1) = MOD(WORLD(1), 360D0)
                  IF (WORLD(1).LT.0D0) WORLD(1) = WORLD(1) + 360D0
                  IF (WORLD(1).LT.VMIN(1,1)) VMIN(1,1) = WORLD(1)
                  IF (WORLD(1).GT.VMAX(1,1)) VMAX(1,1) = WORLD(1)

*                 Normalize to the range (-180,180].
                  IF (WORLD(1).GT.180D0) WORLD(1) = WORLD(1) - 360D0
                  IF (WORLD(1).LT.VMIN(1,2)) VMIN(1,2) = WORLD(1)
                  IF (WORLD(1).GT.VMAX(1,2)) VMAX(1,2) = WORLD(1)
               END IF

               IF (ISANGL(2)) THEN
*                 Normalize to the range [0,360).
                  WORLD(2) = MOD(WORLD(2), 360D0)
                  IF (WORLD(2).LT.0D0) WORLD(2) = WORLD(2) + 360D0
                  IF (WORLD(2).LT.VMIN(2,1)) VMIN(2,1) = WORLD(2)
                  IF (WORLD(2).GT.VMAX(2,1)) VMAX(2,1) = WORLD(2)

*                 Normalize to the range (-180,180].
                  IF (WORLD(2).GT.180D0) WORLD(2) = WORLD(2) - 360D0
                  IF (WORLD(2).LT.VMIN(2,2)) VMIN(2,2) = WORLD(2)
                  IF (WORLD(2).GT.VMAX(2,2)) VMAX(2,2) = WORLD(2)
@
