/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * filename: xreader.c                                                     *
 *                                                                         *
 * UTIL C-source: Medical Image Conversion Utility                         *
 *                                                                         *
 * purpose      : file reader                                              *
 *                                                                         *
 * project      : (X)MedCon by Erik Nolf                                   *
 *                                                                         *
 * Functions    : XMdcReadFile()                  - Read selected file     *
 *                XMdcRawReadFinish()             - Finish raw read        *
 *                XMdcRawReadInteractive()        - Interactive raw read   *
 *                XMdcRawReadPredef()             - Read predefined raw    *
 *                XMdcRawReadCancel()             - Raw read break up      *
 *                XMdcRawReadCallbackCancel()     - General Cancel callback*
 *                XMdcGetImageInfoPixelType()     - Get specified pixeltype*
 *                XMdcGetImageInfoCallbackApply() - Img Info Apply callback*
 *                XMdcGetImageInfo()              - Ask Img Info           *
 *                XMdcGetHeaderInfoCallbackApply()- Hdr Info Cont callback *
 *                XMdcGetHeaderInfo()             - Ask Hdr Info           *
 *                                                                         *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
 */

/*
   Copyright (C) 1997-2026 by Erik Nolf

   This program 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, or (at your option) any later
   version.

   This program 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 this program; if not, write to the Free Software Foundation, Inc.,
   59 Place - Suite 330, Boston, MA 02111-1307, USA.  */

/****************************************************************************
                              H E A D E R S
****************************************************************************/

#include "m-depend.h"

#include <stdio.h>
#ifdef LIBMDC_HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef LIBMDC_HAVE_STRING_H
#include <string.h>
#endif
#ifdef LIBMDC_HAVE_STRINGS_H
#ifndef _WIN32
#include <strings.h>
#endif
#endif

#include "xmedcon.h"


/****************************************************************************
                              D E F I N E S
****************************************************************************/
static RawReadSelectionStruct *raw = &sRawReadSelection;
static MdcRawInputStruct *input = &mdcrawinput;
static MdcRawPrevInputStruct *prev = &mdcrawprevinput;


/****************************************************************************
                            F U N C T I O N S
****************************************************************************/

int XMdcReadFile(char *fname)
{

  if (MdcOpenFile(my.fi,fname) != MDC_OK) {
    XMdcDisplayErr("Failure opening file");
    return(MDC_BAD_OPEN);
  }

  if (MdcReadFile(my.fi,0,NULL) != MDC_OK) {
    XMdcDisplayErr("Failure reading file");
    return(MDC_BAD_READ);
  }

  return(MDC_OK);

}

void XMdcRawReadFinish(guint otype)
{
  char *msg;

  /* open the file */
  if ( (my.fi->ifp = fopen(my.fi->ipath,"rb")) == NULL) {
    MdcSplitPath(my.fi->ipath,my.fi->idir,my.fi->ifname);
    sprintf(mdcbufr,"Couldn't open <%s>",my.fi->ifname);
    XMdcRawReadCancel(otype);
    XMdcDisplayErr("Reading: %s",mdcbufr);
    return;
  }else{
    MdcSplitPath(my.fi->ipath,my.fi->idir,my.fi->ifname);
  }

  /* read the file */
  msg = MdcReadRAW(my.fi);
  if (msg != NULL) {
    if (strstr(msg,"Truncated image") == NULL) {
      XMdcRawReadCancel(otype);
      XMdcDisplayErr("Reading: %s",msg);
      XMdcProgressBar(MDC_PROGRESS_END,0.,NULL);
      return;
    }else{
      XMdcDisplayWarn(msg);
    }
  }

 /* warn user about change in MedCon settings */
  if (MDC_NEGATIVE == MDC_NO) {
    sprintf(xmdcstr,"Changed MedCon Pixel Value settings:\n" \
                     "disabled quantifications\n"             \
                     "enabled negative values");
    XMdcDisplayDialog(MDC_OK,"Important Note",xmdcstr);
  }
 /* change MedCon settings: disable quantifications, enable negative */
  MDC_QUANTIFY = MDC_NO; MDC_CALIBRATE = MDC_NO; MDC_NEGATIVE = MDC_YES;


  MdcGetColorMap(sColormapSelection.CurMap,my.fi->palette);
  msg = MdcImagesPixelFiddle(my.fi);
  if (msg != NULL) {
    XMdcRawReadCancel(otype);
    XMdcDisplayErr("Reading: %s",msg);
    XMdcProgressBar(MDC_PROGRESS_END,0.,NULL);
    return;
  }

  XMDC_FILE_OPEN = MDC_YES; XMDC_FILE_TYPE = XMDC_RAW;
  XMdcViewerEnableAutoShrink();
  XMdcDisplayImages();

  XMdcProgressBar(MDC_PROGRESS_END,0.,NULL);

  if (otype == XMDC_RAW)
    gtk_widget_destroy(sRawReadSelection.HdrInfoWindow);

}

void XMdcRawReadInteractive(char *fname)
{

  XMdcMainWidgetsInsensitive();

  XMdcViewerHide();

  XMdcFileReset();

  MdcInitFI(my.fi, fname);

  XMdcGetHeaderInfo();
}

void XMdcRawReadPredef(char *fname)
{
  IMG_DATA *id;
  Uint32 i;

  XMdcMainWidgetsInsensitive();

  XMdcViewerHide();

  XMdcFileReset();

  MdcInitFI(my.fi, fname);

  /* fill in input struct with predef values */
  input->gen_offset = prev->GENHDR;
  input->img_offset = prev->IMGHDR;
  input->DIFF       = prev->DIFF;
  input->REPEAT     = prev->HDRREP;

  /* now fill structs with predef values */
  if (!MdcGetStructID(my.fi,prev->NRIMGS)) {
    XMdcDisplayErr("Bad malloc IMG_DATA structs");
    return;
  }

  for (i=0; i<my.fi->number; i++) {
     id = &my.fi->image[i];
     id->width = prev->XDIM;
     id->height= prev->YDIM;
     id->type  = prev->PTYPE;
     id->bits  = MdcType2Bits(id->type);
  }

  if (prev->PSWAP == MDC_YES) {
    MDC_FILE_ENDIAN = !MDC_HOST_ENDIAN;
  }else{
    MDC_FILE_ENDIAN = MDC_HOST_ENDIAN;
  }

  my.fi->endian = MDC_FILE_ENDIAN;
  my.fi->dim[0] = 3;
  my.fi->dim[3] = my.fi->number;
  my.fi->diff_type = MDC_NO;
  my.fi->diff_size = MDC_NO;
  my.fi->diff_scale= MDC_NO;

  XMdcRawReadFinish(XMDC_PREDEF);

}

void XMdcRawReadCancel(guint otype)
{
  MdcCleanUpFI(my.fi);
  if (otype == XMDC_RAW)
    gtk_widget_destroy(sRawReadSelection.HdrInfoWindow);

  XMdcMainWidgetsResensitive();

}

void XMdcRawReadCallbackCancel(void)
{
  XMdcRawReadCancel(XMDC_RAW);
}

Int16 XMdcGetImageInfoPixelType(void)
{
  MdcDebugPrint("pixel type: ");
  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(raw->typeBIT1))) {
    MdcDebugPrint("\tBIT1"); return(BIT1);
  }else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(raw->typeASCII))) {
    MdcDebugPrint("\tASCII"); return(ASCII);
  }else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(raw->typeBIT8_S))) {
    MdcDebugPrint("\tBIT8_S"); return(BIT8_S);
  }else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(raw->typeBIT8_U))) {
    MdcDebugPrint("\tBIT8_U"); return(BIT8_U);
  }else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(raw->typeBIT16_S))) {
    MdcDebugPrint("\tBIT16_S"); return(BIT16_S);
  }else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(raw->typeBIT16_U))) {
    MdcDebugPrint("\tBIT16_U"); return(BIT16_U);
  }else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(raw->typeBIT32_S))) {
    MdcDebugPrint("\tBIT32_S"); return(BIT32_S);
  }else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(raw->typeBIT32_U))) {
    MdcDebugPrint("\tBT32_U"); return(BIT32_U);
  }else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(raw->typeBIT64_S))) {
    MdcDebugPrint("\tBIT64_S"); return(BIT64_S);
  }else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(raw->typeBIT64_U))) {
    MdcDebugPrint("\tBIT64_U"); return(BIT64_U);
  }else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(raw->typeFLT32))) {
    MdcDebugPrint("\tFLT32"); return(FLT32);
  }else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(raw->typeFLT64))) {
    MdcDebugPrint("\tFLT64"); return(FLT64);
  }else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(raw->typeCOLRGB))) {
    MdcDebugPrint("\tRGB"); return(COLRGB);
  }else{
    XMdcDisplayFatalErr(MDC_BAD_CODE,"Unknown pixeltype encountered");
  }

  return(MDC_BAD_CODE);

}
/* Apply = Finish or Next */
void XMdcGetImageInfoCallbackApply(void)
{
  IMG_DATA *id=NULL;
  const char *entry;
  off_t offset;
  Uint32 i, width, height, imgnr;
  Int16 type;

  imgnr = raw->ImgCounter - 1;

  MdcDebugPrint("image nr    = %u",imgnr);
  entry  = gtk_entry_get_text(GTK_ENTRY(raw->AbsOffset));
  offset = (off_t) atoll(entry); prev->ABSHDR = offset;
  MdcDebugPrint("abs offset  = %jd",(intmax_t)offset);
  entry = gtk_entry_get_text(GTK_ENTRY(raw->ImgWidth));
  width = (Uint32) atol(entry); prev->XDIM = width;
  MdcDebugPrint("image width = %lu",width);
  entry = gtk_entry_get_text(GTK_ENTRY(raw->ImgHeight));
  height= (Uint32) atol(entry); prev->YDIM = height;
  MdcDebugPrint("image height= %lu",height);
  type  = XMdcGetImageInfoPixelType(); prev->PTYPE = type;

  if (width == 0) {
    XMdcDisplayErr("No width specified");
    XMdcRawReadCancel(XMDC_RAW);
    return;
  }
  if (height == 0) {
    XMdcDisplayErr("No height specified");
    XMdcRawReadCancel(XMDC_RAW);
    return;
  }

  if (input->DIFF) {
    id = &my.fi->image[imgnr];
    id->load_location = offset;
    id->width = width;
    id->height= height;
    id->type  = type;
    id->bits  = MdcType2Bits(id->type);

  }else{

    for (i=0; i<my.fi->number; i++) {
       id = &my.fi->image[i];
       id->load_location = offset;
       id->width = width;
       id->height= height;
       id->type  = type;
       id->bits  = MdcType2Bits(id->type);
    }
  }

  if (raw->ImgCounter < my.fi->number) {
    /* next   -> get info for next image */
    raw->ImgCounter += 1;
    XMdcGetImageInfo();
  }else{
    /* finish -> read the file */
    my.fi->endian = MDC_FILE_ENDIAN;
    my.fi->dim[0] = 3;
    my.fi->dim[3] = my.fi->number;
    XMdcRawReadFinish(XMDC_RAW);
  }

}

void XMdcGetImageInfo(void)
{
  GtkWidget *window=NULL;
  GtkWidget *box1;
  GtkWidget *box2;
  GtkWidget *grid;
  GtkWidget *frame;
  GtkWidget *label;
  GtkWidget *button;
  GtkWidget *entry;
  GtkWidget *separator;
  GSList *group;

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  g_signal_connect(window, "destroy",
                     G_CALLBACK(gtk_widget_destroy),NULL);
  gtk_window_set_title(GTK_WINDOW(window),"Input Image Info");
  gtk_container_set_border_width(GTK_CONTAINER(window), 0);

  box1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
  gtk_container_add(GTK_CONTAINER(window),box1);
  gtk_container_set_border_width(GTK_CONTAINER(box1), 0);
  gtk_widget_show(box1);

  if (input->DIFF) {
    sprintf(xmdcstr,"** IMAGE %u/%u **",raw->ImgCounter,my.fi->number);
    label = gtk_label_new(xmdcstr);
  }else{
    label = gtk_label_new("** ALL IMAGES **");
  }
  gtk_box_pack_start(GTK_BOX(box1),label,TRUE,TRUE,0);
  gtk_widget_show(label);

  /* Absolute offset in bytes */
  frame = gtk_frame_new("Absolute Offset to Image");
  gtk_box_pack_start(GTK_BOX(box1),frame,TRUE,TRUE, 5);
  gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
  gtk_widget_show(frame);

  box2 = gtk_box_new(GTK_ORIENTATION_VERTICAL,5);
  gtk_container_add(GTK_CONTAINER(frame),box2);
  gtk_container_set_border_width(GTK_CONTAINER(box2), 5);
  gtk_widget_show(box2);


  grid = gtk_grid_new();
  gtk_container_add(GTK_CONTAINER(box2),grid);
  gtk_widget_show(grid);

  label = gtk_label_new(" Offset in bytes ");
  gtk_label_set_justify(GTK_LABEL(label),GTK_JUSTIFY_RIGHT);
  gtk_widget_set_name(label, "FixedLabel");
  gtk_grid_attach(GTK_GRID(grid),label,0,0,1,1);
  gtk_widget_show(label);

  entry = gtk_entry_new();
  gtk_entry_set_max_length(GTK_ENTRY(entry), 19);
  sprintf(xmdcstr,"%jd",(intmax_t)prev->ABSHDR);
  gtk_entry_set_text(GTK_ENTRY(entry),xmdcstr);
  gtk_editable_select_region(GTK_EDITABLE(entry),0,-1);
  gtk_grid_attach(GTK_GRID(grid),entry,1,0,1,1);
  gtk_widget_show(entry);
  raw->AbsOffset = entry;


  /* Image dimensions */
  frame = gtk_frame_new("Dimensions (pixels)");
  gtk_box_pack_start(GTK_BOX(box1),frame,TRUE,TRUE,5);
  gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
  gtk_widget_show(frame);

  box2 = gtk_box_new(GTK_ORIENTATION_VERTICAL,5);
  gtk_container_add(GTK_CONTAINER(frame),box2);
  gtk_container_set_border_width(GTK_CONTAINER(box2),5);
  gtk_widget_show(box2);

  grid = gtk_grid_new();
  gtk_container_add(GTK_CONTAINER(box2),grid);
  gtk_widget_show(grid);

  label = gtk_label_new(" Columns ");
  gtk_label_set_justify(GTK_LABEL(label),GTK_JUSTIFY_RIGHT);
  gtk_widget_set_name (label, "FixedLabel");
  gtk_grid_attach(GTK_GRID(grid),label,0,0,1,1);
  gtk_widget_show(label);
 
  entry = gtk_entry_new();
  gtk_entry_set_max_length(GTK_ENTRY(entry), 5);
  sprintf(xmdcstr,"%u",prev->XDIM);
  gtk_entry_set_text(GTK_ENTRY(entry),xmdcstr);

  gtk_editable_select_region(GTK_EDITABLE(entry),0,-1);
  gtk_grid_attach(GTK_GRID(grid),entry,1,0,1,1); 
  gtk_widget_show(entry);
  raw->ImgWidth = entry;

  label = gtk_label_new("   Rows ");
  gtk_label_set_justify(GTK_LABEL(label),GTK_JUSTIFY_RIGHT);
  gtk_widget_set_name (label, "FixedLabel");
  gtk_grid_attach(GTK_GRID(grid),label,0,1,1,1);
  gtk_widget_show(label);

  entry = gtk_entry_new();
  gtk_entry_set_max_length(GTK_ENTRY(entry), 5);
  sprintf(xmdcstr,"%u",prev->YDIM);
  gtk_entry_set_text(GTK_ENTRY(entry),xmdcstr);

  gtk_editable_select_region(GTK_EDITABLE(entry),0,-1);
  gtk_grid_attach(GTK_GRID(grid),entry,1,1,1,1);
  gtk_widget_show(entry);
  raw->ImgHeight = entry;

  /* Pixel Type */
  frame = gtk_frame_new("Pixeltype");
  gtk_box_pack_start(GTK_BOX(box1),frame,TRUE,TRUE,5);
  gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
  gtk_widget_show(frame);

  box2 = gtk_box_new(GTK_ORIENTATION_VERTICAL,5);
  gtk_container_add(GTK_CONTAINER(frame),box2);
  gtk_container_set_border_width(GTK_CONTAINER(box2),5);
  gtk_widget_show(box2);

  grid = gtk_grid_new();
  gtk_container_add(GTK_CONTAINER(box2),grid);
  gtk_widget_show(grid);

  button = gtk_radio_button_new_with_label(NULL,"1-bit");
  gtk_grid_attach(GTK_GRID(grid),button,0,0,1,1);
  if (prev->PTYPE == BIT1) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE);
  }
  gtk_widget_show(button);
  raw->typeBIT1=button;
  group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
  button = gtk_radio_button_new_with_label(group,"ASCII");
  gtk_grid_attach(GTK_GRID(grid),button,1,0,1,1);
  if (prev->PTYPE == ASCII) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE);
  }
  gtk_widget_show(button);
  raw->typeASCII=button;
  group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
  button = gtk_radio_button_new_with_label(group,"Int8");
  gtk_grid_attach(GTK_GRID(grid),button,0,1,1,1);
  if (prev->PTYPE == BIT8_S) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE);
  }
  gtk_widget_show(button);
  raw->typeBIT8_S=button;
  group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
  button = gtk_radio_button_new_with_label(group,"Uint8");
  if (prev->PTYPE == BIT8_U) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE);
  }
  gtk_grid_attach(GTK_GRID(grid),button,1,1,1,1);
  gtk_widget_show(button);
  raw->typeBIT8_U=button;
  group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
  button = gtk_radio_button_new_with_label(group,"Int16");
  if (prev->PTYPE == BIT16_S) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE);
  }
  gtk_grid_attach(GTK_GRID(grid),button,0,2,1,1);
  gtk_widget_show(button);
  raw->typeBIT16_S=button;
  group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
  button = gtk_radio_button_new_with_label(group,"Uint16");
  gtk_grid_attach(GTK_GRID(grid),button,1,2,1,1);
  if (prev->PTYPE == BIT16_U) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE);
  }
  gtk_widget_show(button);
  raw->typeBIT16_U=button;
  group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
  button = gtk_radio_button_new_with_label(group,"Int32");
  gtk_grid_attach(GTK_GRID(grid),button,0,3,1,1);
  if (prev->PTYPE == BIT32_S) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE);
  }
  gtk_widget_show(button);
  raw->typeBIT32_S=button;
  group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
  button = gtk_radio_button_new_with_label(group,"Uint32");
  gtk_grid_attach(GTK_GRID(grid),button,1,3,1,1);
  if (prev->PTYPE == BIT32_U) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE);
  }
  gtk_widget_show(button);
  raw->typeBIT32_U=button;
  group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
  button = gtk_radio_button_new_with_label(group,"Int64");
  gtk_grid_attach(GTK_GRID(grid),button,0,4,1,1);
  if (prev->PTYPE == BIT64_S) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE);
  }
  gtk_widget_show(button);
  raw->typeBIT64_S=button;
  group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
  button = gtk_radio_button_new_with_label(group,"Uint64");
  gtk_grid_attach(GTK_GRID(grid),button,1,4,1,1);
  if (prev->PTYPE == BIT64_U) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE);
  }
  gtk_widget_show(button);
  raw->typeBIT64_U=button;
  group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
  button = gtk_radio_button_new_with_label(group,"float");
  gtk_grid_attach(GTK_GRID(grid),button,0,5,1,1);
  if (prev->PTYPE == FLT32) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE);
  }
  gtk_widget_show(button);
  raw->typeFLT32=button;
  group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
  button = gtk_radio_button_new_with_label(group,"double");
  gtk_grid_attach(GTK_GRID(grid),button,1,5,1,1);
  if (prev->PTYPE == FLT64) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE);
  }
  gtk_widget_show(button);
  raw->typeFLT64=button;
  group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
  button = gtk_radio_button_new_with_label(group,"RGB");
  gtk_grid_attach(GTK_GRID(grid),button,0,6,1,1);
  if (prev->PTYPE == COLRGB) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE);
  }
  gtk_widget_show(button);
  raw->typeCOLRGB=button;


  separator = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
  gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, FALSE, 0);
  gtk_widget_show (separator);

  box2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
  gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,2);
  gtk_widget_show(box2);

  if (raw->ImgCounter == my.fi->number) {
    button = gtk_button_new_with_label("Finish");
  }else{
    button = gtk_button_new_with_label ("Next");
  }
  gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 2);
  g_signal_connect_swapped(button, "clicked",
                     G_CALLBACK(gtk_widget_hide),
                     window);
  g_signal_connect(button, "clicked",
                     G_CALLBACK(XMdcGetImageInfoCallbackApply), NULL);
  g_signal_connect_swapped(button, "clicked",
                     G_CALLBACK(gtk_widget_destroy),
                     window);
  gtk_widget_show(button);

  button = gtk_button_new_with_label("Cancel");
  gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 2);
  g_signal_connect(button, "clicked",
                     G_CALLBACK(XMdcRawReadCallbackCancel), NULL);
  g_signal_connect_swapped(button, "clicked",
                     G_CALLBACK(gtk_widget_destroy),
                     window);
  gtk_widget_show(button);

  XMdcShowWidget(window);

}

/* Apply = Continue */
void XMdcGetHeaderInfoCallbackApply(void)
{
  Uint32 number;
  const char *entry = NULL;

  /* total number of images */
  entry = gtk_entry_get_text(GTK_ENTRY(raw->NrImages));
  number = (Uint32) atol(entry); prev->NRIMGS = number;
  MdcDebugPrint("total images = %u",number);
  if (number == 0) {
    XMdcRawReadCancel(XMDC_RAW);
    XMdcDisplayErr("No images specified");
    return;
  }
  if (!MdcGetStructID(my.fi,number)) {
    XMdcRawReadCancel(XMDC_RAW);
    XMdcDisplayErr("Bad alloc IMG_DATA structs");
    return;
  }
  /* general header offset */
  entry = gtk_entry_get_text(GTK_ENTRY(raw->GenOffset));
  input->gen_offset = (off_t) atoll(entry); prev->GENHDR=input->gen_offset;
  MdcDebugPrint("general header offset = %jd",(intmax_t)input->gen_offset);

  /* image   header offset */
  entry = gtk_entry_get_text(GTK_ENTRY(raw->ImgOffset));
  input->img_offset = (off_t) atoll(entry); prev->IMGHDR=input->img_offset;
  MdcDebugPrint("image  header offset = %jd",(intmax_t)input->gen_offset);

  /* image   header repeated */
  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(raw->IhdrRep))) {
    input->REPEAT = MDC_YES; prev->HDRREP = MDC_YES;
    MdcDebugPrint("image  header repeated = yes");
  }else{
    input->REPEAT = MDC_NO;  prev->HDRREP = MDC_NO;
    MdcDebugPrint("image  header repeated = no");
  }

  /* swap pixel bytes */
  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(raw->PixSwap))) {
    MDC_FILE_ENDIAN = !MDC_HOST_ENDIAN; prev->PSWAP = MDC_YES;
    MdcDebugPrint("swap pixels = yes");
  }else{
    MDC_FILE_ENDIAN = MDC_HOST_ENDIAN;  prev->PSWAP = MDC_NO;
    MdcDebugPrint("swap pixels = no");
  }

  /* identical images */
  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(raw->ImgSame))) {
    input->DIFF = MDC_NO; prev->DIFF = MDC_NO;
    MdcDebugPrint("identical images = yes");
    raw->ImgCounter = my.fi->number;
  }else{
    input->DIFF = MDC_YES; prev->DIFF = MDC_YES;
    MdcDebugPrint("identical images = no");
    raw->ImgCounter = 1;
  }

  XMdcGetImageInfo();

}

void XMdcGetHeaderInfo(void)
{
  GtkWidget *window=NULL;
  GtkWidget *box1;
  GtkWidget *box2;
  GtkWidget *box3;
  GtkWidget *frame;
  GtkWidget *grid;
  GtkWidget *label;
  GtkWidget *button;
  GtkWidget *entry;
  GtkWidget *separator;

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  g_signal_connect(window,"destroy",
                     G_CALLBACK(gtk_widget_destroy),NULL);
  gtk_window_set_title(GTK_WINDOW(window),"Input Header Info");
  raw->HdrInfoWindow = window;

  gtk_container_set_border_width(GTK_CONTAINER(window), 0);

  box1 = gtk_box_new(GTK_ORIENTATION_VERTICAL,0);
  gtk_container_add(GTK_CONTAINER(window),box1);
  gtk_container_set_border_width(GTK_CONTAINER(box1),0);
  gtk_widget_show(box1);

  box2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,5);
  gtk_container_add(GTK_CONTAINER(box1),box2);
  gtk_container_set_border_width(GTK_CONTAINER(box2),5);
  gtk_widget_show(box2);

  frame = gtk_frame_new("File Info");
  gtk_box_pack_start(GTK_BOX(box2),frame,TRUE,TRUE,5);
  gtk_widget_show(frame);

  box3 = gtk_box_new(GTK_ORIENTATION_VERTICAL,5);
  gtk_container_add(GTK_CONTAINER(frame),box3);
  gtk_container_set_border_width(GTK_CONTAINER(box3),5);
  gtk_widget_show(box3);

  grid = gtk_grid_new();
  gtk_container_add(GTK_CONTAINER(box3),grid);
  gtk_widget_show(grid);

  label = gtk_label_new("        Total number of images ");
  gtk_label_set_justify(GTK_LABEL(label),GTK_JUSTIFY_RIGHT);
  gtk_widget_set_name (label, "FixedLabel");
  gtk_grid_attach(GTK_GRID(grid),label,0,0,1,1);
  gtk_widget_show(label);

  entry = gtk_entry_new();
  gtk_entry_set_max_length(GTK_ENTRY(entry), 19);
  sprintf(xmdcstr,"%u",prev->NRIMGS);
  gtk_entry_set_text(GTK_ENTRY(entry),xmdcstr);
  gtk_editable_select_region(GTK_EDITABLE(entry),0,-1);
  gtk_grid_attach(GTK_GRID(grid),entry,1,0,1,1);
  gtk_widget_show(entry);
  raw->NrImages = entry;

  label = gtk_label_new(" General header offset (bytes) ");
  gtk_label_set_justify(GTK_LABEL(label),GTK_JUSTIFY_RIGHT);
  gtk_widget_set_name (label, "FixedLabel");
  gtk_grid_attach(GTK_GRID(grid),label,0,1,1,1);
  gtk_widget_show(label);

  entry = gtk_entry_new();
  gtk_entry_set_max_length(GTK_ENTRY(entry), 19);
  sprintf(xmdcstr,"%jd",(intmax_t)prev->GENHDR);
  gtk_entry_set_text(GTK_ENTRY(entry),xmdcstr);
  gtk_editable_select_region(GTK_EDITABLE(entry),0,-1);
  gtk_grid_attach(GTK_GRID(grid),entry,1,1,1,1);
  gtk_widget_show(entry);
  raw->GenOffset = entry;

  label = gtk_label_new(" Image   header offset (bytes) ");
  gtk_label_set_justify(GTK_LABEL(label),GTK_JUSTIFY_RIGHT);
  gtk_widget_set_name (label, "FixedLabel");
  gtk_grid_attach(GTK_GRID(grid),label,0,2,1,1);
  gtk_widget_show(label);

  entry = gtk_entry_new();
  gtk_entry_set_max_length(GTK_ENTRY(entry), 19);
  sprintf(xmdcstr,"%jd",(intmax_t)prev->IMGHDR);
  gtk_entry_set_text(GTK_ENTRY(entry),xmdcstr);
  gtk_grid_attach(GTK_GRID(grid),entry,1,2,1,1);
  gtk_widget_show(entry);
  raw->ImgOffset = entry;

  frame = gtk_frame_new("Data Info");
  gtk_box_pack_start(GTK_BOX(box2),frame,TRUE,TRUE,5);
  gtk_widget_show(frame);

  box3 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
  gtk_container_add(GTK_CONTAINER(frame),box3);
  gtk_container_set_border_width(GTK_CONTAINER(box3),5);
  gtk_widget_show(box3);

  button = gtk_check_button_new_with_label("Repeated image header");
  gtk_box_pack_start(GTK_BOX(box3),button,TRUE,TRUE,0);
  if (prev->HDRREP == MDC_YES)
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE);
  gtk_widget_show(button);
  raw->IhdrRep = button;

  button = gtk_check_button_new_with_label("Swap pixel bytes");
  gtk_box_pack_start(GTK_BOX(box3),button,TRUE,TRUE,0);
  if (prev->PSWAP == MDC_YES)
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE);
  gtk_widget_show(button);
  raw->PixSwap = button;

  button = gtk_check_button_new_with_label("Identical images");
  gtk_box_pack_start(GTK_BOX(box3),button,TRUE,TRUE,0);
  if (prev->DIFF == MDC_NO)
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE);
  gtk_widget_show(button);
  raw->ImgSame = button;

  separator = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
  gtk_box_pack_start(GTK_BOX(box1),separator,FALSE,FALSE,0);
  gtk_widget_show(separator);

  box2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
  gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,2);
  gtk_widget_show(box2);

  button = gtk_button_new_with_label("Continue");
  gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,2);
  g_signal_connect(button, "clicked",
                     G_CALLBACK(XMdcGetHeaderInfoCallbackApply),NULL);
  g_signal_connect_swapped(button, "clicked",
                    G_CALLBACK(gtk_widget_hide),
                    window);
  gtk_widget_show(button);

  button = gtk_button_new_with_label("Cancel");
  gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,2);
  g_signal_connect(button, "clicked",
                    G_CALLBACK(XMdcRawReadCallbackCancel), NULL);
  gtk_widget_show(button);

  XMdcShowWidget(window);

}

