/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * filename: xinfo.c                                                       *
 *                                                                         *
 * UTIL C-source: Medical Image Conversion Utility                         *
 *                                                                         *
 * purpose      : display info text routines                               *
 *                                                                         *
 * project      : (X)MedCon by Erik Nolf                                   *
 *                                                                         *
 * Functions    : XMdcImagesInfo()          - Display images info          *
 *                XMdcShowFileInfo()        - Display general file 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_STRING_H
#include <string.h>
#endif
#ifdef LIBMDC_HAVE_STRINGS_H
#ifndef _WIN32
#include <strings.h>
#endif
#endif

#include "xmedcon.h"

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

void XMdcImagesInfo(GtkWidget *widget, Uint32 nr)
{
  GtkWidget *window = NULL;
  GtkWidget *vbox;
  GtkWidget *button;
  GtkWidget *separator;
  GtkWidget *scrolled_window;
  GtkWidget *text;
  GtkTextBuffer *buffer;
  GtkTextIter iter;

  IMG_DATA *id;
  Uint32 i;
  float f;

  i  = my.realnumber[nr];
  id = &my.fi->image[i];

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_widget_set_size_request(window, 600, 550);
  gtk_window_set_resizable(GTK_WINDOW(window), TRUE);

  g_signal_connect(window, "destroy",
                     G_CALLBACK(gtk_widget_destroy), NULL);

  gtk_window_set_title(GTK_WINDOW(window),XMdcGetImageLabelIndex(nr));
  gtk_container_set_border_width(GTK_CONTAINER(window),0);

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

  scrolled_window = gtk_scrolled_window_new(NULL, NULL);
  gtk_box_pack_start(GTK_BOX(vbox),scrolled_window,TRUE,TRUE,0);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
                 GTK_POLICY_AUTOMATIC,
                 GTK_POLICY_AUTOMATIC);
  gtk_widget_show(scrolled_window);

  text = gtk_text_view_new();
  gtk_text_view_set_editable(GTK_TEXT_VIEW(text),FALSE);
  gtk_widget_set_name(text, "TextView");
  gtk_container_add(GTK_CONTAINER(scrolled_window),text);
  gtk_widget_show(text);

  /* get the text buffer */
  buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text));

  /* create tag for blue colored titles */
  gtk_text_buffer_create_tag(buffer,"Blue","foreground","Royal Blue",NULL);

  /* create the info text */
  gtk_text_buffer_get_iter_at_offset(buffer, &iter, 0);

  sprintf(xmdcstr,"IMAGE: %02u     PAGE: %02u        NR: %03u\n\n",
          nr+1, my.curpage+1, i+1);
  gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,xmdcstr,-1,"Blue",NULL);

  sprintf(xmdcstr,"\nPixel Dimensions\n");
  gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,xmdcstr,-1,"Blue",NULL);

  sprintf(xmdcstr,"dimension: %ux%u\npixeltype: %s\n",
          id->width, id->height, MdcGetStrPixelType(id->type));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);

  sprintf(xmdcstr,"\nReal Dimensions\n");
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"pixel xsize   : %+e mm\npixel ysize   : %+e mm\n",
          id->pixel_xsize, id->pixel_ysize);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"slice width   : %+e mm\n", id->slice_width);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"slice spacing : %+e mm\n", id->slice_spacing);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"\nct zoom factor: %+e\n", id->ct_zoom_fctr);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);

  sprintf(xmdcstr,"\nRescale Factors\n");
  gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,xmdcstr,-1,"Blue",NULL);
  sprintf(xmdcstr,"rescale slope    : %+e ", id->rescale_slope);
  if (MDC_QUANTIFY == MDC_YES) {
    strcat(xmdcstr,"(= quantification)\n");
  }else if (MDC_CALIBRATE == MDC_YES) {
    strcat(xmdcstr,"(= quantification * calibration)\n");
  }else{
    strcat(xmdcstr,"(= none)\n");
  }
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"rescale intercept: %+e\n", id->rescale_intercept);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"quantification   : %+e\n", id->quant_scale);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"calibration      : %+e\n", id->calibr_fctr);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"intercept        : %+e\n", id->intercept);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);

  sprintf(xmdcstr,"\nPixel Values\n");
  gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,xmdcstr,-1,"Blue",NULL);
  sprintf(xmdcstr,"image  min value: %+e\t\timage  max value: %+e\n",
          id->min, id->max);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"frame  min value: %+e\t\tframe  max value: %+e\n",
          id->fmin, id->fmax);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);

  sprintf(xmdcstr,"\nQuantified Values\n");
  gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,xmdcstr,-1,"Blue",NULL);
  sprintf(xmdcstr,"image qmin value: %+e\t\timage qmax value: %+e\n",
           id->qmin, id->qmax);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"frame qmin value: %+e\t\tframe qmax value: %+e\n",
           id->qfmin, id->qfmax);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);

  sprintf(xmdcstr,"\nTime Specifications\n");
  gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,xmdcstr,-1,"Blue",NULL);
  sprintf(xmdcstr,"frame number  : %u\n",id->frame_number);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"slice start   : %+e [ms] = %s\n"
                 ,id->slice_start,MdcGetStrHHMMSS(id->slice_start));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);

  f = MdcSingleImageDuration(my.fi,id->frame_number-1);
  sprintf(xmdcstr,"slice duration: %+e [ms] = %s (auto-filled)\n"
                 ,f,MdcGetStrHHMMSS(f));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);

  sprintf(xmdcstr,"\nPosition & Orientation\n");
  gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,xmdcstr,-1,"Blue",NULL);

  sprintf(xmdcstr,"image position device     : %+e\\%+e\\%+e\n",
                                                    id->image_pos_dev[0],
                                                    id->image_pos_dev[1],
                                                    id->image_pos_dev[2]);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"image position patient    : %+e\\%+e\\%+e\n",
                                                    id->image_pos_pat[0],
                                                    id->image_pos_pat[1],
                                                    id->image_pos_pat[2]);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"image orientation device  : %+e\\%+e\\%+e\n",
                                                    id->image_orient_dev[0],
                                                    id->image_orient_dev[1],
                                                    id->image_orient_dev[2]);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"                            %+e\\%+e\\%+e\n",
                                                    id->image_orient_dev[3],
                                                    id->image_orient_dev[4],
                                                    id->image_orient_dev[5]);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"image orientation patient : %+e\\%+e\\%+e\n",
                                                    id->image_orient_pat[0],
                                                    id->image_orient_pat[1],
                                                    id->image_orient_pat[2]);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"                            %+e\\%+e\\%+e\n",
                                                    id->image_orient_pat[3],
                                                    id->image_orient_pat[4],
                                                    id->image_orient_pat[5]);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);

  if (id->sdata != NULL) {
    STATIC_DATA *sd = id->sdata;
    sprintf(xmdcstr,"\nStatic Data\n");
    gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,xmdcstr,-1,"Blue",NULL);

    sprintf(xmdcstr,"label            : %s\n",sd->label);
    gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
    sprintf(xmdcstr,"total counts     : %g\n",sd->total_counts);
    gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
    sprintf(xmdcstr,"image duration   : %e [ms] = %s\n"
                   ,sd->image_duration,MdcGetStrHHMMSS(sd->image_duration));
    gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
    sprintf(xmdcstr,"image start time : %02hd:%02hd:%02hd\n"
                                                 ,sd->start_time_hour
                                                 ,sd->start_time_minute
                                                 ,sd->start_time_second);
    gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  }

  /* create separator and close button */
  separator = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
  gtk_box_pack_start(GTK_BOX(vbox),separator,FALSE,TRUE,0);
  gtk_widget_show(separator);

  button = gtk_button_new_with_label("Close");
  g_signal_connect_swapped(button, "clicked",
                            G_CALLBACK(gtk_widget_destroy),
                            window);

  gtk_box_pack_start(GTK_BOX(vbox),button,FALSE,FALSE,0);
  gtk_widget_show(button);

  gtk_widget_show(window);

}

void XMdcShowFileInfo(GtkWidget *widget, gpointer data)
{
  GtkWidget *window = NULL;
  GtkWidget *vbox;
  GtkWidget *scrolled_window;
  GtkWidget *button;
  GtkWidget *separator;
  GtkWidget *text;
  GtkTextBuffer *buffer;
  GtkTextIter iter;
  Uint32 i;
  int v;

  if (XMdcNoFileOpened()) return;

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_widget_set_size_request(window, 550, 550);
  gtk_window_set_resizable(GTK_WINDOW(window), TRUE);

  g_signal_connect(window, "destroy",
                     G_CALLBACK(gtk_widget_destroy), NULL);

  sprintf(mdcbufr,"FileInfo: %s",my.fi->ifname);
  gtk_window_set_title(GTK_WINDOW(window),mdcbufr);
  gtk_container_set_border_width(GTK_CONTAINER(window),0);

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

  scrolled_window = gtk_scrolled_window_new(NULL, NULL);
  gtk_box_pack_start(GTK_BOX(vbox),scrolled_window,TRUE,TRUE,0);
  gtk_widget_show(scrolled_window);

  text = gtk_text_view_new();
  gtk_text_view_set_editable(GTK_TEXT_VIEW(text),FALSE);
  gtk_widget_set_name(text, "TextView");
  gtk_container_add(GTK_CONTAINER(scrolled_window),text);
  gtk_widget_show(text);

  /* get the text buffer */
  buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text));

  /* create tag for blue colored titles */
  gtk_text_buffer_create_tag(buffer,"Blue","foreground","Royal Blue",NULL);

  /* create the general info text */
  gtk_text_buffer_get_iter_at_offset(buffer, &iter, 0);

  sprintf(xmdcstr,"\nGeneral File Information\n");
  gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,xmdcstr,-1,"Blue",NULL);
  sprintf(xmdcstr,"FILE *ifp   : ");
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  if (my.fi->ifp == NULL)
    sprintf(xmdcstr,"<null>\n");
  else
    sprintf(xmdcstr,"%p\n",(void *)my.fi->ifp);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);

  sprintf(xmdcstr,"FILE *ofp   : ");
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  if (my.fi->ofp == NULL)
    sprintf(xmdcstr,"<null>\n");
  else
    sprintf(xmdcstr,"%p\n",(void *)my.fi->ofp);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);

  sprintf(xmdcstr,"ipath       : %s\n",my.fi->ipath);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"opath       : %s\n",my.fi->opath);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  if (my.fi->idir != NULL)
    sprintf(xmdcstr,"idir        : %s\n",my.fi->idir);
  else
    sprintf(xmdcstr,"idir        : <null>\n");
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  if (my.fi->odir != NULL)
    sprintf(xmdcstr,"odir        : %s\n",my.fi->odir);
  else
    sprintf(xmdcstr,"odir        : <null>\n");
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"ifname      : %s\n",my.fi->ifname);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"ofname      : %s\n",my.fi->ofname);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  v = (int)my.fi->iformat;
  sprintf(xmdcstr,"iformat     : %d (= %s)\n",v,FrmtString[v]);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"modality    : %d (= %s)\n",my.fi->modality
                                          ,MdcGetStrModality(my.fi->modality));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  v = (int)my.fi->rawconv;
  sprintf(xmdcstr,"rawconv     : %d (= %s)\n",v,MdcGetStrRawConv(v));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  v = (int)my.fi->endian;
  sprintf(xmdcstr,"endian      : %d (= %s)\n",v,MdcGetStrEndian(v));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  v = (int)my.fi->compression;
  sprintf(xmdcstr,"compression : %d (= %s)\n",v,MdcGetStrCompression(v));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  v = (int)my.fi->truncated;
  sprintf(xmdcstr,"truncated   : %d (= %s)\n",v,MdcGetStrYesNo(v));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  v = (int)my.fi->diff_type;
  sprintf(xmdcstr,"diff_type   : %d (= %s)\n",v,MdcGetStrYesNo(v));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  v = (int)my.fi->diff_size;
  sprintf(xmdcstr,"diff_size   : %d (= %s)\n",v,MdcGetStrYesNo(v));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  v = (int)my.fi->diff_scale;
  sprintf(xmdcstr,"diff_scale  : %d (= %s)\n",v,MdcGetStrYesNo(v));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);

  sprintf(xmdcstr,"\nGeneral Image Information\n");
  gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,xmdcstr,-1,"Blue",NULL);
  sprintf(xmdcstr,"number      : %u\n",my.fi->number);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"mwidth      : %u\n",my.fi->mwidth);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"mheight     : %u\n",my.fi->mheight);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"bits        : %hu\n",my.fi->bits);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  v = (int)my.fi->type;
  sprintf(xmdcstr,"type        : %d (= %s)\n",v,MdcGetStrPixelType(v));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);

  sprintf(xmdcstr,"dim[0]      : %-5hd (= total in use)\n",my.fi->dim[0]);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"dim[1]      : %-5hd (= pixels X-dim)\n",my.fi->dim[1]);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"dim[2]      : %-5hd (= pixels Y-dim)\n",my.fi->dim[2]);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"dim[3]      : %-5hd (= planes | (time) slices)\n"
                                                          ,my.fi->dim[3]);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"dim[4]      : %-5hd (= frames | time slots | phases)\n"
                                                          ,my.fi->dim[4]);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"dim[5]      : %-5hd (= gates  | R-R intervals)\n"
                                                          ,my.fi->dim[5]);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"dim[6]      : %-5hd (= beds   | detector heads)\n"
                                                          ,my.fi->dim[6]);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"dim[7]      : %-5hd (= ...    | energy windows)\n"
                                                          ,my.fi->dim[7]);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"pixdim[0]   : %+e\n",my.fi->pixdim[0]);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"pixdim[1]   : %+e [mm]\n",my.fi->pixdim[1]);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"pixdim[2]   : %+e [mm]\n",my.fi->pixdim[2]);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"pixdim[3]   : %+e [mm]\n",my.fi->pixdim[3]);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  for (i=4; i<MDC_MAX_DIMS; i++) {
     sprintf(xmdcstr,"pixdim[%u]   : %+e\n",i,my.fi->pixdim[i]);
     gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  }
  sprintf(xmdcstr,"glmin       : %+e\n",my.fi->glmin);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"glmax       : %+e\n",my.fi->glmax);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"qglmin      : %+e\n",my.fi->qglmin);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"qglmax      : %+e\n",my.fi->qglmax);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);

  v = (int)my.fi->contrast_remapped;
  sprintf(xmdcstr,"contrast remapped: %d (= %s)\n",v,MdcGetStrYesNo(v));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"window centre    : %g\n",my.fi->window_centre);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"window width     : %g\n",my.fi->window_width);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);

  sprintf(xmdcstr,"\nOrientation Information\n");
  gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,xmdcstr,-1,"Blue",NULL);
  sprintf(xmdcstr,"slice projection          : %d (= %s)\n",
       my.fi->slice_projection,MdcGetStrSlProjection(my.fi->slice_projection));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"patient/slice orientation : %d (= %s)\n",
       my.fi->pat_slice_orient,MdcGetStrPatSlOrient(my.fi->pat_slice_orient));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"patient position          : %s\n",my.fi->pat_pos);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"patient orientation       : %s\n",my.fi->pat_orient);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);

  sprintf(xmdcstr,"\nPatient Information\n");
  gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,xmdcstr,-1,"Blue",NULL);
  sprintf(xmdcstr,"patient_sex   : %s\n",my.fi->patient_sex);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"patient_name  : %s\n",my.fi->patient_name);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"patient_id    : %s\n",my.fi->patient_id);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"patient_dob   : %s\n",my.fi->patient_dob);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"patient_weight: %.2f [kg]\n",my.fi->patient_weight);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"patient_height: %.2f [m]\n",my.fi->patient_height);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);

  sprintf(xmdcstr,"\nStudy Information\n");
  gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,xmdcstr,-1,"Blue",NULL);
  sprintf(xmdcstr,"operator_name    : %s\n",my.fi->operator_name);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"study_descr      : %s\n",my.fi->study_descr);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"study_id         : %s\n",my.fi->study_id);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"study_date_year  : %02d\n",my.fi->study_date_year);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"study_date_month : %d\n",my.fi->study_date_month);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"study_date_day   : %d\n",my.fi->study_date_day);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"study_time_hour  : %02d\n",my.fi->study_time_hour);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"study_time_minute: %02d\n",my.fi->study_time_minute);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"study_time_second: %02d\n",my.fi->study_time_second);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"dose_time_hour   : %02d\n",my.fi->dose_time_hour);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"dose_time_minute : %02d\n",my.fi->dose_time_minute);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"dose_time_second : %02d\n",my.fi->dose_time_second);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"nr_series        : %d\n",my.fi->nr_series);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"nr_acquisition   : %d\n",my.fi->nr_acquisition);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"nr_instance      : %d\n",my.fi->nr_instance);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  v = (int)my.fi->decay_corrected;
  sprintf(xmdcstr,"decay_corrected  : %d (= %s)\n",v,MdcGetStrYesNo(v));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  v = (int)my.fi->flood_corrected;
  sprintf(xmdcstr,"flood_corrected  : %d (= %s)\n",v,MdcGetStrYesNo(v));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  v = (int)my.fi->acquisition_type;
  sprintf(xmdcstr,"acquisition_type : %d (= %s)\n",v,MdcGetStrAcquisition(v));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  v = (int)my.fi->planar;
  sprintf(xmdcstr,"planar           : %d (= %s)\n",v,MdcGetStrYesNo(v));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  v = (int)my.fi->reconstructed;
  sprintf(xmdcstr,"reconstructed    : %d (= %s)\n",v,MdcGetStrYesNo(v));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"recon_method     : %s\n",my.fi->recon_method);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"institution      : %s\n",my.fi->institution);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"manufacturer     : %s\n",my.fi->manufacturer);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"series_descr     : %s\n",my.fi->series_descr);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"radiopharma      : %s\n",my.fi->radiopharma);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"filter_type      : %s\n",my.fi->filter_type);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"organ_code       : %s\n",my.fi->organ_code);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"isotope_code     : %s\n",my.fi->isotope_code);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"isotope_halflife : %+e [sec] or %g [hrs]\n"
                                          ,my.fi->isotope_halflife
                                          ,my.fi->isotope_halflife/3600.);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"injected_dose    : %+e [MBq]\n",my.fi->injected_dose);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"gantry_tilt      : %+e [degrees]\n",my.fi->gantry_tilt);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);

  if ((my.fi->gatednr > 0) && (my.fi->gdata != NULL)) {
    sprintf(xmdcstr,"\nGated (SPECT) Data\n");
    gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,xmdcstr,-1,"Blue",NULL);
    sprintf(xmdcstr,"gatednr          : %u\n",my.fi->gatednr);
    gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
    for (i=0; i<my.fi->gatednr; i++) {
      GATED_DATA *gd = &my.fi->gdata[i];
      sprintf(xmdcstr,"------- [ %.3u ] --------\n",i+1);
      gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
      v = (int)gd->gspect_nesting;
      sprintf(xmdcstr,"gspect_nesting   : %d (= %s)\n",gd->gspect_nesting
                     ,MdcGetStrGSpectNesting(gd->gspect_nesting));
      gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
      sprintf(xmdcstr,"nr_projections   : %g\n",gd->nr_projections);
      gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
      sprintf(xmdcstr,"extent_rotation  : %g\n",gd->extent_rotation);
      gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
      sprintf(xmdcstr,"study_duration   : %+e [ms] = %s\n"
                     ,gd->study_duration,MdcGetStrHHMMSS(gd->study_duration));
      gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
      sprintf(xmdcstr,"image_duration   : %+e [ms] = %s\n"
                     ,gd->image_duration,MdcGetStrHHMMSS(gd->image_duration));
      gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
      sprintf(xmdcstr,"time_per_proj    : %+e [ms] = %s\n"
                     ,gd->time_per_proj,MdcGetStrHHMMSS(gd->time_per_proj));
      gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
      sprintf(xmdcstr,"limit window_low : %+e [ms] = %s\n"
                     ,gd->window_low,MdcGetStrHHMMSS(gd->window_low));
      gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
      sprintf(xmdcstr,"limit window_high: %+e [ms] = %s\n"
                     ,gd->window_high,MdcGetStrHHMMSS(gd->window_high));
      gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
      sprintf(xmdcstr,"cycles_observed  : %+e\n",gd->cycles_observed);
      gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
      sprintf(xmdcstr,"cycles_acquired  : %+e\n\n",gd->cycles_acquired);
      gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
      sprintf(xmdcstr,"heart rate (observed): %d [bpm] (auto-filled)\n"
                     ,(int)MdcGetHeartRate(gd,MDC_HEART_RATE_OBSERVED));
      gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
      sprintf(xmdcstr,"heart rate (acquired): %d [bpm] (auto-filled)\n"
                     ,(int)MdcGetHeartRate(gd,MDC_HEART_RATE_ACQUIRED));
      gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
    }
  }
  if ((my.fi->acqnr > 0) && (my.fi->acqdata != NULL)) {
    sprintf(xmdcstr,"\nAcquisition Data\n");
    gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,xmdcstr,-1,"Blue",NULL);
    sprintf(xmdcstr,"acqnr              : %u\n",my.fi->acqnr);
    gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
    for (i=0; i<my.fi->acqnr; i++) {
     ACQ_DATA *acq = &my.fi->acqdata[i];
     sprintf(xmdcstr,"-------- [ %.3u ] --------\n",i+1);
     gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
     v = (int)acq->rotation_direction;
     sprintf(xmdcstr,"rotation_direction : %d (= %s)\n",v,MdcGetStrRotation(v));
     gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
     v = (int)acq->detector_motion;
     sprintf(xmdcstr,"detector_motion    : %d (= %s)\n",v,MdcGetStrMotion(v));
     gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
     sprintf(xmdcstr,"rotation_offset    : %g [mm]\n",acq->rotation_offset);
     gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
     sprintf(xmdcstr,"radial_position    : %g [mm]\n",acq->radial_position);
     gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
     sprintf(xmdcstr,"angle_start        : %g [degrees]\n",acq->angle_start);
     gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
     sprintf(xmdcstr,"angle_step         : %g [degrees]\n",acq->angle_step);
     gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
     sprintf(xmdcstr,"scan_arc           : %g [degrees]\n",acq->scan_arc);
     gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
    }
  }
  if ((my.fi->dynnr > 0) && (my.fi->dyndata != NULL)) {
    sprintf(xmdcstr,"\nDynamic Data\n");
    gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,xmdcstr,-1,"Blue",NULL);
    sprintf(xmdcstr,"dynnr              : %u\n",my.fi->dynnr);
    gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
    for (i=0; i<my.fi->dynnr; i++) {
     DYNAMIC_DATA *dd = &my.fi->dyndata[i];
     sprintf(xmdcstr,"-------- [ %.3u ] --------\n",i+1);
     gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
     sprintf(xmdcstr,"nr_of_slices       : %u\n",dd->nr_of_slices);
     gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
     sprintf(xmdcstr,"time_frame_start   : %+e [ms] = %s\n"
            ,dd->time_frame_start,MdcGetStrHHMMSS(dd->time_frame_start));
     gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
     sprintf(xmdcstr,"time_frame_delay   : %+e [ms] = %s\n"
            ,dd->time_frame_delay,MdcGetStrHHMMSS(dd->time_frame_delay));
     gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
     sprintf(xmdcstr,"time_frame_duration: %+e [ms] = %s\n"
            ,dd->time_frame_duration,MdcGetStrHHMMSS(dd->time_frame_duration));
     gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
     sprintf(xmdcstr,"delay_slices       : %+e [ms] = %s\n"
            ,dd->delay_slices,MdcGetStrHHMMSS(dd->delay_slices));
     gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
    }
  }
  if ((my.fi->bednr > 0) && (my.fi->beddata != NULL)) {
    sprintf(xmdcstr,"\nBed Data\n");
    gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,xmdcstr,-1,"Blue",NULL);
    sprintf(xmdcstr,"bednr              : %u\n",my.fi->bednr);
    gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
    for (i=0; i<my.fi->bednr; i++) {
     BED_DATA *bd = &my.fi->beddata[i];
     sprintf(xmdcstr,"-------- [ %.3u ] --------\n",i+1);
     gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
     sprintf(xmdcstr,"bed horiz. offset  : %+e [mm]\n",bd->hoffset);
     gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
     sprintf(xmdcstr,"bed vert.  offset  : %+e [mm]\n", bd->voffset);
     gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
    }
  }
  sprintf(xmdcstr,"\nInternal Information\n");
  gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,xmdcstr,-1,"Blue",NULL);
  sprintf(xmdcstr,"map         : %u (= %s)\n",my.fi->map,
                                      MdcGetStrColorMap((int)my.fi->map));
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"comm_length : %u\n",my.fi->comm_length);
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  sprintf(xmdcstr,"comment     : ");
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);
  if (my.fi->comm_length != 0 && my.fi->comment != NULL) {
    strncpy(xmdcstr,my.fi->comment,my.fi->comm_length);
    xmdcstr[my.fi->comm_length]='\0';
  }else{
    sprintf(xmdcstr,"<null>\n");
  }
  gtk_text_buffer_insert(buffer,&iter,xmdcstr,-1);

  /* create separator and close button */
  separator = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
  gtk_box_pack_start(GTK_BOX(vbox),separator,FALSE,TRUE,0);
  gtk_widget_show(separator);

  button = gtk_button_new_with_label("Close");
  g_signal_connect_swapped(button, "clicked",
                            G_CALLBACK(gtk_widget_destroy),
                            window);

  gtk_box_pack_start(GTK_BOX(vbox),button,FALSE,FALSE,0);
  gtk_widget_show(button);

  gtk_widget_show(window);

}

