/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * Copyright by the Board of Trustees of the University of Illinois.         *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of HDF.  The full HDF copyright notice, including       *
 * terms governing use, modification, and redistribution, is contained in    *
 * the COPYING file, which can be found at the root of the source code       *
 * distribution tree, or in https://support.hdfgroup.org/ftp/HDF/releases/.  *
 * If you do not have access to either file, you may request a copy from     *
 * help@hdfgroup.org.                                                        *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/*-----------------------------------------------------------------------------
 * File:    mfsdf.c
 * Purpose: C stubs for Fortran GR routines
 * Invokes: mfgr.c
 * Contents:
 *  mgstart:    Call GRstart to initialize the GR interface for a file
 *  mgfinfo:    Call GRfileinfo for information about the file
 *  mgend:      Call GRend to close down the GR interface to a file
 *  mgcreat:    Call GRcreate to create a raster image
 *  mgselct:    Call GRselect to select an existing raster image for I/O
 *  mgn2ndx:    Call GRnametoindex to map an image's name into a index in a file
 *  mggiinf:    Call GRgetiminfo to get information about an image
 *  mgwrimg:    Call GRwriteimage to write image data to the file
 *  mgrdimg:    Call GRreadimage to read image data from the file
 *  mgendac:    Call GRendaccess to end access to a raster image
 *  mggdid:     Call GRgetdimid to get a dimension ID for an image [Later]
 *  mgsdnam:    Call GRsetdimname to set a dimension's name [Later]
 *  mggdinf:    Call GRgetdiminfo to get information about a dimension [Later]
 *  mgid2rf:    Call GRidtoref to map an RI ID into a ref. # for annotating
 *  mgr2idx:    Call GRreftoindex to map a ref. # into an index for the image
 *  mgrltil:    Call GRreqlutil to request the interlace of the next LUT read
 *  mgrimil:    Call GRreqimageil to request the interlace of the next image read
 *  mggltid:    Call GRgetlutid to get a palette ID for an image
 *  mgglinf:    Call GRgetlutinfo to get information about a palette
 *  mgwrlut:    Call GRwritelut to write a palette to the file
 *  mgwclut:    Call GRwritelut to write a character palette to the file
 *  mgrdlut:    Call GRreadlut to read a palette from the file
 *  mgrclut:    Call GRreadlut to read a character palette from the file
 *  mgsxfil:    Call GRsetexternalfile to move an image into an external file
 *  mgsactp:    Call GRsetaccesstype to set the access type for an image
 *  mgscomp:    Call GRsetcompress to compress an image in the file
 *  mggcomp:    Call GRgetcompinfo to get image compression information
 *  mgisattr:    Call GRsetattr to write an attribute for an object
 *  mgiscatt:   Call GRsetattr to write a char attribute for an obj.
 *  mgatinf:    Call GRattrinfo get information about an attribute
 *  mggcatt:    Call GRgetattr to read a char attribute from the file
 *  mggnatt:    Call GRgetattr to read a numeric attribute from the file
 *  mggattr:    Call GRgetattr to read an attribute from the file
 *  mgfndat:    Call GRfindattr to get the index of an attribute for a name
 *  mglut2ref:  Call GRluttoref to get reference number for a palette specified
 *                   by palette identifier
 *---------------------------------------------------------------------------*/

#include "hdf_priv.h"
#include "hproto_fortran.h"

/* Local pre-processor macros */
#define XDIM 0
#define YDIM 1

/*-----------------------------------------------------------------------------
 * Name:    mgstart
 * Purpose: Call GRstart to initialize the GR interface for a file
 * Inputs:  fid: HDF file ID of file to initialize
 * Returns: GR ID on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRstart
 *---------------------------------------------------------------------------*/

intf
nmgstart(intf *fid)
{
    return (intf)GRstart((int32)*fid);
} /* end mgstart() */

/*-----------------------------------------------------------------------------
 * Name:    mgfinfo
 * Purpose: Call GRfileinfo to get information about the images in a file
 * Inputs:  grid: GR ID of file for information
 *          n_datasets: # of raster images in the file
 *          n_attrs: # of "global" GR attributes
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRfileinfo
 *---------------------------------------------------------------------------*/

intf
nmgfinfo(intf *grid, intf *n_datasets, intf *n_attrs)
{
    int32 n_data, n_attr;
    intf  ret;

    ret         = (intf)GRfileinfo((int32)*grid, &n_data, &n_attr);
    *n_datasets = (intf)n_data;
    *n_attrs    = (intf)n_attr;
    return ret;
} /* end mgfinfo() */

/*-----------------------------------------------------------------------------
 * Name:    mgend
 * Purpose: Call GRend to close the GR interface for a file
 * Inputs:  grid: GR ID of interface to close
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRend
 *---------------------------------------------------------------------------*/

intf
nmgend(intf *grid)
{
    return (intf)GRend((int32)*grid);
} /* end mgend() */

/*-----------------------------------------------------------------------------
 * Name:    mgicreat
 * Purpose: Call GRcreate to create a raster image.
 * Inputs:
 *      grid: GR ID of interface to create image in
 *      name: name of raster image
 *      ncomp: number of components per pixel
 *      nt: number-type of each component
 *      il: interlace scheme to use
 *      dimsizes[2]: dimensions of the image to create
 *      nlen: length of the name string
 * Returns: RI ID on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRcreate
 *---------------------------------------------------------------------------*/

intf
nmgicreat(intf *grid, _fcd name, intf *ncomp, intf *nt, intf *il, intf dimsizes[2], intf *nlen)
{
    char *fn;
    int32 cdims[2];
    intf  ret;

    /* Convert the FORTRAN string into a C string */
    fn = HDf2cstring(name, (intn)*nlen);
    if (fn == NULL)
        return FAIL;

    /* Copy the array of dimensions into an array of the proper type */
    cdims[XDIM] = (int32)dimsizes[XDIM];
    cdims[YDIM] = (int32)dimsizes[YDIM];
    ret         = (intf)GRcreate((int32)*grid, fn, (int32)*ncomp, (int32)*nt, (int32)*il, cdims);
    free(fn);

    return ret;
} /* end mgicreat() */

/*-----------------------------------------------------------------------------
 * Name:    mgselct
 * Purpose: Call GRselect to choose an existing raster image.
 * Inputs:
 *      grid: GR ID of interface
 *      index: the index of the image to select
 * Returns: RI ID on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRselect
 *---------------------------------------------------------------------------*/

intf
nmgselct(intf *grid, intf *index)
{
    return (intf)GRselect((int32)*grid, (int32)*index);
} /* end mgselct() */

/*-----------------------------------------------------------------------------
 * Name:    mgin2ndx
 * Purpose: Call GRnametoindex to map a raster image name to an index
 * Inputs:
 *      grid: GR ID of interface
 *      name: the name of the raster image to find
 *      nlen: the length of the name
 * Returns: image index on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRnametoindex
 *---------------------------------------------------------------------------*/

intf
nmgin2ndx(intf *grid, _fcd name, intf *nlen)
{
    char *fn;
    intf  ret;

    /* Convert the FORTRAN string into a C string */
    fn = HDf2cstring(name, (intn)*nlen);
    if (fn == NULL)
        return FAIL;

    /* Copy the array of dimensions into an array of the proper type */
    ret = (intf)GRnametoindex((int32)*grid, fn);
    free(fn);

    return ret;
} /* end mgin2ndx() */

/*-----------------------------------------------------------------------------
 * Name:    mggiinf
 * Purpose: Call GRgetiminfo to get information about an image
 * Inputs:
 *      riid: RI ID of the image
 *      name: the name of the raster image to find
 *      ncomp: the number of components each pixel has
 *      nt: the number type of each component
 *      il: the interlace of the image components
 *      dimsizes: the dimensions of the image
 *      nattr: the number of attributes the image has
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRgetiminfo
 *---------------------------------------------------------------------------*/

intf
nmggiinf(intf *riid, _fcd name, intf *ncomp, intf *nt, intf *il, intf *dimsizes, intf *nattr)
{
    int32 t_ncomp, t_nt, t_il, t_dimsizes[2], t_nattr;
    intf  ret;

    /* Copy the array of dimensions into an array of the proper type */
    ret =
        (intf)GRgetiminfo((int32)*riid, (char *)_fcdtocp(name), &t_ncomp, &t_nt, &t_il, t_dimsizes, &t_nattr);
    *ncomp         = (intf)t_ncomp;
    *nt            = (intf)t_nt;
    *il            = (intf)t_il;
    dimsizes[XDIM] = t_dimsizes[XDIM];
    dimsizes[YDIM] = t_dimsizes[YDIM];
    *nattr         = (intf)t_nattr;

    return ret;
} /* end mggiinf() */

/*-----------------------------------------------------------------------------
 * Name:    mgwcimg
 * Purpose: Call mgwrimg to write char type image data to the file
 * Inputs:
 *      riid: RI ID of the image
 *      start: the starting location of the image data to write
 *      stride: the stride of image data to write
 *      count: the number of pixels in each dimension to write
 *      data: the image data (pixels) to write out
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRwriteimage
 *---------------------------------------------------------------------------*/

intf
nmgwcimg(intf *riid, intf *start, intf *stride, intf *count, _fcd data)
{
    return nmgwrimg(riid, start, stride, count, (void *)_fcdtocp(data));
} /* end mgwcimg() */

/*-----------------------------------------------------------------------------
 * Name:    mgwrimg
 * Purpose: Call GRwriteimage to write image data to the file
 * Inputs:
 *      riid: RI ID of the image
 *      start: the starting location of the image data to write
 *      stride: the stride of image data to write
 *      count: the number of pixels in each dimension to write
 *      data: the image data (pixels) to write out
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRwriteimage
 *---------------------------------------------------------------------------*/

intf
nmgwrimg(intf *riid, intf *start, intf *stride, intf *count, void *data)
{
    int32 t_start[2], t_stride[2], t_count[2];

    /* Copy the array of dimensions into an array of the proper type */
    t_start[XDIM]  = (int32)start[XDIM];
    t_start[YDIM]  = (int32)start[YDIM];
    t_stride[XDIM] = (int32)stride[XDIM];
    t_stride[YDIM] = (int32)stride[YDIM];
    t_count[XDIM]  = (int32)count[XDIM];
    t_count[YDIM]  = (int32)count[YDIM];

    return (intf)GRwriteimage((int32)*riid, t_start, t_stride, t_count, data);
} /* end mgwrimg() */

/*-----------------------------------------------------------------------------
 * Name:    mgrcimg
 * Purpose: Call mgrdimg to read char type image data from a file
 * Inputs:
 *      riid: RI ID of the image
 *      start: the starting location of the image data to read
 *      stride: the stride of image data to read
 *      count: the number of pixels in each dimension to read
 *      data: the image data (pixels) to read out
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRreadimage
 *---------------------------------------------------------------------------*/

intf
nmgrcimg(intf *riid, intf *start, intf *stride, intf *count, _fcd data)
{
    return nmgrdimg(riid, start, stride, count, (void *)_fcdtocp(data));
} /* end mgrcimg() */

/*-----------------------------------------------------------------------------
 * Name:    mgrdimg
 * Purpose: Call GRreadimage to read image data from a file
 * Inputs:
 *      riid: RI ID of the image
 *      start: the starting location of the image data to read
 *      stride: the stride of image data to read
 *      count: the number of pixels in each dimension to read
 *      data: the image data (pixels) to read out
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRreadimage
 *---------------------------------------------------------------------------*/

intf
nmgrdimg(intf *riid, intf *start, intf *stride, intf *count, void *data)
{
    int32 t_start[2], t_stride[2], t_count[2];

    /* Copy the array of dimensions into an array of the proper type */
    t_start[XDIM]  = (int32)start[XDIM];
    t_start[YDIM]  = (int32)start[YDIM];
    t_stride[XDIM] = (int32)stride[XDIM];
    t_stride[YDIM] = (int32)stride[YDIM];
    t_count[XDIM]  = (int32)count[XDIM];
    t_count[YDIM]  = (int32)count[YDIM];

    return (intf)GRreadimage((int32)*riid, t_start, t_stride, t_count, data);
} /* end mgrdimg() */

/*-----------------------------------------------------------------------------
 * Name:    mgendac
 * Purpose: Call GRendaccess to terminate access to a raster image
 * Inputs:
 *      riid: RI ID of the image
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRendaccess
 *---------------------------------------------------------------------------*/

intf
nmgendac(intf *riid)
{
    return (intf)GRendaccess((int32)*riid);
} /* end mgendac() */

/*-----------------------------------------------------------------------------
 * Name:    mgid2rf
 * Purpose: Call GRidtoref to map a RI index into a reference #
 * Inputs:
 *      riid: RI ID of the image
 * Returns: ref. # on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRidtoref
 *---------------------------------------------------------------------------*/

intf
nmgid2rf(intf *riid)
{
    return (intf)GRidtoref((int32)*riid);
} /* end mgid2rf() */

/*-----------------------------------------------------------------------------
 * Name:    mgr2idx
 * Purpose: Call GRreftoindex to map a reference # into a ri index
 * Inputs:
 *      grid: GR ID of the file
 *      ref: ref. # of the image
 * Returns: a valid index # on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRreftoindex
 *---------------------------------------------------------------------------*/

intf
nmgr2idx(intf *grid, intf *ref)
{
    return (intf)GRreftoindex((int32)*grid, (uint16)*ref);
} /* end mgr2idx() */

/*-----------------------------------------------------------------------------
 * Name:    mgrltil
 * Purpose: Call GRreqlutil to request the interlacing scheme for the next LUT
 * Inputs:
 *      riid: RI ID of the image
 *      il: interlace scheme for next read
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRreqlutil
 *---------------------------------------------------------------------------*/

intf
nmgrltil(intf *riid, intf *il)
{
    return (intf)GRreqlutil((int32)*riid, (intn)*il);
} /* end mgrltil() */

/*-----------------------------------------------------------------------------
 * Name:    mgrimil
 * Purpose: Call GRreqimageil to request the interlacing scheme for the next image
 * Inputs:
 *      riid: RI ID of the image
 *      il: interlace scheme for next read
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRreqimageil
 *---------------------------------------------------------------------------*/

intf
nmgrimil(intf *riid, intf *il)
{
    return (intf)GRreqimageil((int32)*riid, (intn)*il);
} /* end mgrimil() */

/*-----------------------------------------------------------------------------
 * Name:    mggltid
 * Purpose: Call GRgetlutid to get the palette ID for an image
 * Inputs:
 *      riid: RI ID of the image
 *      lut_index: index of the palette to select
 * Returns: value LUT ID on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRgetlutid
 *---------------------------------------------------------------------------*/

intf
nmggltid(intf *riid, intf *lut_index)
{
    return (intf)GRgetlutid((int32)*riid, (intn)*lut_index);
} /* end mggltid() */

/*-----------------------------------------------------------------------------
 * Name:    mgglinf
 * Purpose: Call GRgetlutinfo to get information about a palette
 * Inputs:
 *      lutid: LUT ID of the image
 *      ncomp: number of components per palette entry
 *      nt: number-type of components in palette entry
 *      il: interlace of components in palette entry
 *      nentries: number of palette entries
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRgetlutinfo
 *---------------------------------------------------------------------------*/

intf
nmgglinf(intf *lutid, intf *ncomp, intf *nt, intf *il, intf *nentries)
{
    int32 t_ncomp, t_nt, t_il, t_nentries;
    intf  status;

    status    = (intf)GRgetlutinfo((int32)*lutid, &t_ncomp, &t_nt, &t_il, &t_nentries);
    *ncomp    = (intf)t_ncomp;
    *nt       = (intf)t_nt;
    *il       = (intf)t_il;
    *nentries = (intf)t_nentries;
    return status;
} /* end mgglinf() */

/*-----------------------------------------------------------------------------
 * Name:    mgwclut
 * Purpose: Call GRwritelut to write data into a character palette
 * Inputs:
 *      lutid: LUT ID of the image
 *      ncomp: number of components per palette entry
 *      nt: number-type of components in palette entry
 *      il: interlace of components in palette entry
 *      nentries: number of palette entries
 *      data: data to write
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRwritelut
 *---------------------------------------------------------------------------*/

intf
nmgwclut(intf *lutid, intf *ncomp, intf *nt, intf *il, intf *nentries, _fcd data)
{
    return (intf)GRwritelut((int32)*lutid, (int32)*ncomp, (int32)*nt, (int32)*il, (int32)*nentries,
                            (void *)_fcdtocp(data));
} /* end mgwrlut() */

/*-----------------------------------------------------------------------------
 * Name:    mgwrlut
 * Purpose: Call GRwritelut to write data into a palette
 * Inputs:
 *      lutid: LUT ID of the image
 *      ncomp: number of components per palette entry
 *      nt: number-type of components in palette entry
 *      il: interlace of components in palette entry
 *      nentries: number of palette entries
 *      data: data to write
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRwritelut
 *---------------------------------------------------------------------------*/

intf
nmgwrlut(intf *lutid, intf *ncomp, intf *nt, intf *il, intf *nentries, void *data)
{
    return (intf)GRwritelut((int32)*lutid, (int32)*ncomp, (int32)*nt, (int32)*il, (int32)*nentries, data);
} /* end mgwrlut() */

/*-----------------------------------------------------------------------------
 * Name:    mgrclut
 * Purpose: Call GRreadlut to read data from a character palette
 * Inputs:
 *      lutid: LUT ID of the image
 *      data: data to read
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRreadlut
 *---------------------------------------------------------------------------*/

intf
nmgrclut(intf *lutid, _fcd data)
{
    return (intf)GRreadlut((int32)*lutid, (void *)_fcdtocp(data));
} /* end mgrclut() */

/*-----------------------------------------------------------------------------
 * Name:    mgrdlut
 * Purpose: Call GRreadlut to read data from a palette
 * Inputs:
 *      lutid: LUT ID of the image
 *      data: data to read
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRreadlut
 *---------------------------------------------------------------------------*/

intf
nmgrdlut(intf *lutid, void *data)
{
    return (intf)GRreadlut((int32)*lutid, data);
} /* end mgrdlut() */

/*-----------------------------------------------------------------------------
 * Name:    mgisxfil
 * Purpose: Call GRsetexternalfile to convert an image into an external image
 * Inputs:
 *      riid: RI ID of the image
 *      filename: filename of the external file
 *      offset: offset in the external file to place image at
 *      nlen: the length of the name
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRsetexternalfile
 *---------------------------------------------------------------------------*/

intf
nmgisxfil(intf *riid, _fcd filename, intf *offset, intf *nlen)
{
    char *fn;
    intf  ret;

    /* Convert the FORTRAN string into a C string */
    fn = HDf2cstring(filename, (intn)*nlen);
    if (fn == NULL)
        return FAIL;

    ret = (intf)GRsetexternalfile((int32)*riid, fn, (int32)*offset);
    free(fn);

    return ret;
} /* end mgisxfil() */

/*-----------------------------------------------------------------------------
 * Name:    mgsactp
 * Purpose: Call GRsetaccesstype to determine access mode for an image
 * Inputs:
 *      riid: RI ID of the image
 *      accesstype: the type of access to image data
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRsetaccesstype
 *---------------------------------------------------------------------------*/

intf
nmgsactp(intf *riid, intf *accesstype)
{
    return (intf)GRsetaccesstype((int32)*riid, (uintn)*accesstype);
} /* end mgsactp() */

/*-----------------------------------------------------------------------------
 * Name:    mgiscatt
 * Purpose: Call mgisatt to store a char attribute about an image
 * Inputs:
 *      riid: RI ID of the image
 *      name: the name of the attribute
 *      nt: the number-type of the attribute
 *      count: the number of values in the attribute
 *      data: the data for the attribute
 *      nlen: the length of the name
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRsetattr
 *---------------------------------------------------------------------------*/
intf
nmgiscatt(intf *riid, _fcd name, intf *nt, intf *count, _fcd data, intf *nlen)
{
    return nmgisattr(riid, name, nt, count, (void *)_fcdtocp(data), nlen);
} /* end mgiscatt() */
/*-----------------------------------------------------------------------------
 * Name:    mgisattr
 * Purpose: Call GRsetattr to store an attribute about an image
 * Inputs:
 *      riid: RI ID of the image
 *      name: the name of the attribute
 *      nt: the number-type of the attribute
 *      count: the number of values in the attribute
 *      data: the data for the attribute
 *      nlen: the length of the name
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRsetattr
 *---------------------------------------------------------------------------*/

intf
nmgisattr(intf *riid, _fcd name, intf *nt, intf *count, void *data, intf *nlen)
{
    char *fn;
    intf  ret;

    /* Convert the FORTRAN string into a C string */
    fn = HDf2cstring(name, (intn)*nlen);
    if (fn == NULL)
        return FAIL;

    ret = (intf)GRsetattr((int32)*riid, fn, (int32)*nt, (int32)*count, data);
    free(fn);

    return ret;
} /* end mgisattr() */

/*-----------------------------------------------------------------------------
 * Name:    mgatinf
 * Purpose: Call GRattrinfo to get information about an attribute
 * Inputs:
 *      riid: RI ID of the image
 *      index: the index of the attribute
 *      name: the name of the attribute
 *      nt: the number-type of the attribute
 *      count: the number of values in the attribute
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRattrinfo
 *---------------------------------------------------------------------------*/

intf
nmgatinf(intf *riid, intf *index, _fcd name, intf *nt, intf *count)
{
    int32 t_nt, t_count;
    intf  ret;

    ret    = (intf)GRattrinfo((int32)*riid, (int32)*index, (char *)_fcdtocp(name), &t_nt, &t_count);
    *nt    = (intf)t_nt;
    *count = (intf)t_count;

    return ret;
} /* end mgatinf() */

/*-----------------------------------------------------------------------------
 * Name:    mggcatt
 * Purpose: Call mggnatt to get a char attribute
 * Inputs:
 *      riid: RI ID of the image
 *      index: the index of the attribute
 *      data: the data for the attribute
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRgetattr
 *---------------------------------------------------------------------------*/

intf
nmggcatt(intf *riid, intf *index, _fcd data)
{
    return nmggnatt(riid, index, (void *)_fcdtocp(data));
} /* end mggcatt() */

/*-----------------------------------------------------------------------------
 * Name:    mggnatt
 * Purpose: Call GRgetattr to get a numeric attribute
 * Inputs:
 *      riid: RI ID of the image
 *      index: the index of the attribute
 *      data: the data for the attribute
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRgetattr
 *---------------------------------------------------------------------------*/

intf
nmggnatt(intf *riid, intf *index, void *data)
{
    return (intf)GRgetattr((int32)*riid, (int32)*index, data);
} /* end mggnatt() */

/*-----------------------------------------------------------------------------
 * Name:    mggattr
 * Purpose: Call GRgetattr to get an attribute
 * Inputs:
 *      riid: RI ID of the image
 *      index: the index of the attribute
 *      data: the data for the attribute
 * Returns: SUCCEED on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRgetattr
 * Remarks: This routine is replaced by mggcatt and mggmatt
 *---------------------------------------------------------------------------*/

intf
nmggattr(intf *riid, intf *index, void *data)
{
    return (intf)GRgetattr((int32)*riid, (int32)*index, data);
} /* end mggattr() */

/*-----------------------------------------------------------------------------
 * Name:    mgifndat
 * Purpose: Call GRfindattr to locate an attribute
 * Inputs:
 *      riid: RI ID of the image
 *      name: the name for the attribute
 *      nlen: the length of the name for the attribute
 * Returns: attribute index on success, FAIL on failure
 * Users:   HDF Fortran programmers
 * Invokes: GRfindattr
 *---------------------------------------------------------------------------*/

intf
nmgifndat(intf *riid, _fcd name, intf *nlen)
{
    char *fn;
    intf  ret;

    /* Convert the FORTRAN string into a C string */
    fn = HDf2cstring(name, (intn)*nlen);
    if (fn == NULL)
        return FAIL;

    ret = (intf)GRfindattr((int32)*riid, fn);
    free(fn);

    return ret;
} /* end mgifndat() */

/*-------------------------------------------------------------------------
 * Name:    mgcgichnk
 * Puporse: Call GRgetchunkinfo
 * Inputs:  id: access id to GR
 * Outputs: dim_length: chunk dimensions
 *          flags:            -1 - GR is nonchunked
 *                             0 - GR is chunked, no compression
 *                             1 - GR is chunked and compressed
 * Returns: 0 on success, -1 on failure with error set
 * Users:   HDF Fortran programmers
 *-------------------------------------------------------------------------*/
intf
nmgcgichnk(intf *id, intf *dim_length, intf *flags)
{

    HDF_CHUNK_DEF chunk_def; /* Chunk definition set */
    int32         riid;      /* GR id               */
    int           i;
    int32         rank, status, cflags;
    intf          ret;

    riid = *id;
    rank = 2;

    /* Get GR info */
    status = GRgetchunkinfo(riid, &chunk_def, &cflags);
    if (status == FAIL)
        return FAIL;

    switch (cflags)

    {

        case HDF_NONE: /* Non-chunked GR */

            *flags = -1;
            ret    = 0;
            return ret;

        case HDF_CHUNK: /* Chunked, noncompressed GR */

            *flags = 0;
            for (i = 0; i < rank; i++)
                dim_length[rank - i - 1] = chunk_def.chunk_lengths[i];
            ret = 0;
            return ret;

        case (HDF_CHUNK | HDF_COMP): /* Chunked and compressed GR */

            *flags = 1;
            for (i = 0; i < rank; i++)
                dim_length[rank - i - 1] = chunk_def.comp.chunk_lengths[i];
            ret = 0;
            return ret;

        default:

            return FAIL;
    }
}
/*-----------------------------------------------------------------------------
 * Name:     mgcrcchnk
 * Purpose:  read the specified chunk of CHARACTER data to the buffer
 * Inputs:   id        - access ID to GR
 *           start     - origin of chunk to read
 * Outputs:  char_data  - buffer the data will be read into
 * Calls:    scrchnk
 * Reamrks:  dimensions will be flipped in scrchnk function
 * Returns:  0 on success, -1 on failure with error set
 *----------------------------------------------------------------------------*/
intf
nmgcrcchnk(intf *id, intf *start, _fcd char_data)
{
    intf ret;

    ret = nmgcrchnk(id, start, (void *)_fcdtocp(char_data));

    return ret;
}

/*-----------------------------------------------------------------------------
 * Name:     mgcrchnk
 * Purpose:  read the specified chunk of NUMERIC data to the buffer
 * Inputs:   id        - access ID to GR
 *           start     - origin of chunk to read
 * Outputs:  num_data  - buffer the data will be read into
 * Calls:    GRreadchunk
 * Remarks:  need to flip the dimensions to account for array ordering
 *           differences (start --> cstart)
 *           If performance becomes an issue, use static cstart
 * Returns:  0 on success, -1 on failure with error set
 *----------------------------------------------------------------------------*/
intf
nmgcrchnk(intf *id, intf *start, void *num_data)
{
    intf   ret;
    int32  rank, i;
    int32 *cstart;

    rank = 2;
    /* Allocate memory for cstart array; use static array, if performance
           becomes an issue */

    cstart = (int32 *)malloc(sizeof(int32) * rank);
    if (!cstart)
        return FAIL;

    /* Flip an array to account for array ordering in Fortran and C */

    for (i = 0; i < rank; i++)
        cstart[i] = start[rank - i - 1] - 1;

    /* Call GRreadchunk function to read the data */

    ret = GRreadchunk(*id, cstart, num_data);

    /* Free memory */

    free(cstart);
    return ret;
}

/*-----------------------------------------------------------------------------
 * Name:     mgcscchnk
 * Purpose:  set the maximum number of chunks to cache
 * Inputs:   id        - access ID to GR
 *           maxcache  - max number of chunks to cache
 *           flags     - flags= 0, HDF_CACHEALL
 *                       Currently only 0 can be passed
 * Calls:    GRsetchunkcache
 * Returns:  0 on success, -1 on failure with error set
 *----------------------------------------------------------------------------*/
intf
nmgcscchnk(intf *id, intf *maxcache, intf *flags)
{
    intf ret;

    ret = GRsetchunkcache(*id, *maxcache, *flags);

    return ret;
}

/*-------------------------------------------------------------------------
 * Name:    mgcschnk
 * Puporse: Call GRsetchunk
 * Inputs:  id: access id to GR
 *          dim_length: chunk dimensions
 *          comp_type:  type of compression
 *                              COMP_CODE_NONE    (0)
 *                              COMP_CODE_RLE     (1)
 *                              COMP_CODE_SKPHUFF (3)
 *                              COMP_CODE_DEFLATE (4)
 *                              COMP_CODE_INVALID (5)
 *          comp_prm:   compression parameters array
 *          comp_prm[0] = skphuff_skp_size: size of individual elements for
 *                            Adaptive Huffman compression algorithm
 *          comp_prm[0] = deflate_level:    GZIP  compression parameter
 * Returns: 0 on success, -1 on failure with error set
 * Users:   HDF Fortran programmers
 *-------------------------------------------------------------------------*/
intf
nmgcschnk(intf *id, intf *dim_length, intf *comp_type, intf *comp_prm)
{

    HDF_CHUNK_DEF chunk_def; /* Chunk definition set */
    int32         riid;      /* GR id               */
    int32         cflags;    /* chunk flags          */
    int           i, CASE;
    int32         rank;
    intf          ret;

    rank   = 2;
    CASE   = *comp_type;
    riid   = *id;
    cflags = HDF_CHUNK | HDF_COMP;

    switch (CASE) {

        case 0: /* No compression */
            cflags = HDF_CHUNK;
            for (i = 0; i < rank; i++)
                chunk_def.chunk_lengths[i] = dim_length[rank - i - 1];
            break;

        case 1: /* RLE compression */
            for (i = 0; i < rank; i++)
                chunk_def.comp.chunk_lengths[i] = dim_length[rank - i - 1];

            chunk_def.comp.comp_type = COMP_CODE_RLE;

            break;

#ifdef GRsetchunk_does_not_support_NBIT

        case 2: /* N-bit encoding */
            for (i = 0; i < rank; i++)
                chunk_def.comp.chunk_lengths[i] = dim_length[rank - i - 1];

            chunk_def.comp.comp_type            = COMP_CODE_NBIT;
            chunk_def.comp.cinfo.nbit.sign_ext  = comp_prm[0];
            chunk_def.comp.cinfo.nbit.fill_one  = comp_prm[1];
            chunk_def.comp.cinfo.nbit.start_bit = comp_prm[2];
            chunk_def.comp.cinfo.nbit.bit_len   = comp_prm[3];

            break;

#endif
        case 3: /* Skipping Huffman encoding */
            for (i = 0; i < rank; i++)
                chunk_def.comp.chunk_lengths[i] = dim_length[rank - i - 1];

            chunk_def.comp.comp_type              = COMP_CODE_SKPHUFF;
            chunk_def.comp.cinfo.skphuff.skp_size = comp_prm[0];

            break;

        case 4: /* GZIP compression */
            for (i = 0; i < rank; i++)
                chunk_def.comp.chunk_lengths[i] = dim_length[rank - i - 1];

            chunk_def.comp.comp_type           = COMP_CODE_DEFLATE;
            chunk_def.comp.cinfo.deflate.level = comp_prm[0];

            break;

        default:

            return FAIL;
    }

    ret = GRsetchunk(riid, chunk_def, cflags);

    return ret;
}
/*-----------------------------------------------------------------------------
 * Name:     mgcwcchnk
 * Purpose:  write the specified chunk of CHARACTER data to the GR
 * Inputs:   id        - access ID to GR
 *           start     - origin of chunk to read
 * Outputs:  char_data  - buffer the data will be read into
 * Calls:    mgcwchnk
 * Reamrks:  dimensions will be flipped in scrchnk function
 * Returns:  0 on success, -1 on failure with error set
 *----------------------------------------------------------------------------*/
intf
nmgcwcchnk(intf *id, intf *start, _fcd char_data)
{
    intf ret;

    ret = nmgcwchnk(id, start, (void *)_fcdtocp(char_data));

    return ret;
}

/*-----------------------------------------------------------------------------
 * Name:     mgcwchnk
 * Purpose:  write the specified chunk of NUMERIC data to the GR
 * Inputs:   id        - access ID to GR
 *           start     - origin of chunk to write
 *           num_data  - buffer for data
 * Calls:    GRwritechunk
 * Remarks:  need to flip the dimensions to account for array ordering
 *           differences (start --> cstart)
 *           If performance becomes an issue, use static cstart
 * Returns:  0 on success, -1 on failure with error set
 *----------------------------------------------------------------------------*/
intf
nmgcwchnk(intf *id, intf *start, void *num_data)
{
    intf   ret;
    int32  rank, i;
    int32 *cstart;

    rank = 2;
    /* Allocate memory for cstart array; use static array, if performance
           becomes an issue */

    cstart = (int32 *)malloc(sizeof(int32) * rank);
    if (!cstart)
        return FAIL;

    /* Flip an array */

    for (i = 0; i < rank; i++)
        cstart[i] = start[rank - i - 1] - 1;

    /* Call GRwritechunk function to write the data */

    ret = GRwritechunk(*id, cstart, num_data);

    /* Free memory */

    free(cstart);

    return ret;
}
/*-------------------------------------------------------------------------
 * Name:    mgcscompress
 * Puporse: Call GRsetcompress
 * Inputs:  id: access id to GR
 *          comp_type:  type of compression
 *                      COMP_CODE_NONE = 0
 *                      COMP_CODE_RLE  = 1
 *                      COMP_CODE_SKPHUFF = 3
 *                      COMP_CODE_DEFLATE = 4
 *                      COMP_CODE_JPEG    = 7
 *          comp_prm:   compression parameters array
 *          comp_prm[0]=skphuff_skp_size: size of individual elements for
 *                            Adaptive Huffman compression algorithm
 *          comp_prm[0]=deflate_level:    GZIP  compression parameter
 *          comp_prm[0]=quality           JPEG parameters
 *          comp_prm[1]=baseline
 * Returns: 0 on success, -1 on failure with error set
 * Users:   HDF Fortran programmers
 *-------------------------------------------------------------------------*/
intf
nmgcscompress(intf *id, intf *comp_type, intf *comp_prm)
{
    int32        riid;   /*  GR id               */
    comp_info    c_info; /* compression info     */
    comp_coder_t c_type; /* compression type definition */

    int  CASE;
    intf ret;

    CASE = *comp_type;
    riid = *id;
    switch (CASE) {

        case COMP_CODE_NONE: /* No compression */
            c_type = COMP_CODE_NONE;
            break;

        case COMP_CODE_RLE: /* RLE compression */
            c_type = COMP_CODE_RLE;
            break;

        case COMP_CODE_SKPHUFF: /* Skipping Huffman encoding */
            c_type                  = COMP_CODE_SKPHUFF;
            c_info.skphuff.skp_size = comp_prm[0];
            break;

        case COMP_CODE_DEFLATE: /* GZIP compression */
            c_type               = COMP_CODE_DEFLATE;
            c_info.deflate.level = comp_prm[0];
            break;

        case COMP_CODE_JPEG: /* JPEG compression */
            c_type                     = COMP_CODE_JPEG;
            c_info.jpeg.quality        = comp_prm[0];
            c_info.jpeg.force_baseline = comp_prm[1];
            break;

        default:

            return FAIL;
    }

    ret = GRsetcompress(riid, c_type, &c_info);
    return ret;
}
/*-------------------------------------------------------------------------
 * Name:    mgcgcompress
 * Puporse: Call GRgetcompinfo
 * Inputs:  id: access id to GR
 * Outputs: comp_type:  type of compression
 *                      COMP_CODE_NONE = 0
 *                      COMP_CODE_RLE  = 1
 *                      COMP_CODE_SKPHUFF = 3
 *                      COMP_CODE_DEFLATE = 4
 *                      COMP_CODE_JPEG    = 7
 *          comp_prm:   compression parameters array
 *          comp_prm[0]=skphuff_skp_size: size of individual elements for
 *                            Adaptive Huffman compression algorithm
 *          comp_prm[0]=deflate_level:    GZIP  compression parameter
 * Returns: 0 on success, -1 on failure with error set
 * Users:   HDF Fortran programmers
 *-------------------------------------------------------------------------*/
intf
nmgcgcompress(intf *id, intf *comp_type, intf *comp_prm)
{
    comp_info    c_info; /* compression info     */
    comp_coder_t c_type; /* compression type definition */

    int  CASE;
    intf ret = -1;
    intn c_ret;

    c_ret = GRgetcompinfo(*id, &c_type, &c_info);

    if (c_ret == 0) {
        CASE = (int)c_type;
        switch (CASE) {

            case COMP_CODE_NONE: /* No compression */
                *comp_type = 0;
                ret        = 0;
                break;

            case COMP_CODE_RLE: /* RLE compression */
                *comp_type = 1;
                ret        = 0;
                break;

            case COMP_CODE_SKPHUFF: /* Skipping Huffman encoding */
                *comp_type  = 3;
                comp_prm[0] = (intf)c_info.skphuff.skp_size;
                ret         = 0;
                break;

            case COMP_CODE_DEFLATE: /* GZIP compression */
                *comp_type  = 4;
                comp_prm[0] = (intf)c_info.deflate.level;
                ret         = 0;
                break;

            case COMP_CODE_JPEG: /* JPEG compression */
                *comp_type = 7;
                ret        = 0;
                break;

            default:

                return FAIL;

        } /*end CASE */
    }     /*end if */
    return ret;
}
/*-------------------------------------------------------------------------
 * Name:    mglt2rf
 * Puporse: Call GRluttoref
 * Inputs:  id: LUT id returned by GRgetlutid(mggltid)
 * Returns: valid reference number if a palette exists or 0 (DFREF_WILDCARD)
 *          if one doesn't / FAIL
 * Users:   HDF Fortran programmers
 *-------------------------------------------------------------------------*/
intf
nmglt2rf(intf *id)
{
    intf ret;

    ret = GRluttoref(*id);
    return ret;
}
/*-------------------------------------------------------------------------
 * Name:    mgcgnluts
 * Puporse: Call GRgetnluts
 * Inputs:  id: image identifier
 * Returns: number of palettes on success and -1 if fails.
 * Users:   HDF Fortran programmers
 *-------------------------------------------------------------------------*/
intf
nmgcgnluts(intf *id)
{
    intf ret = -1;
    intn c_ret;

    c_ret = GRgetnluts(*id);
    if (c_ret >= 0)
        ret = c_ret;
    return ret;
}
