#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Xm/Xm.h>
#include <Xm/CascadeB.h>
#include <Xm/DialogS.h>
#include <Xm/FileSB.h>
#include <Xm/Form.h>
#include <Xm/Label.h>
#include <Xm/List.h>
#include <Xm/PanedW.h>
#include <Xm/PushB.h>
#include <Xm/RowColumn.h>
#include <Xm/ScrollBar.h>
#include <Xm/SelectioB.h>
#ifdef sgimips
#include <Xm/SgiP.h>
#endif
#include <Xm/Text.h>
#include <Xm/TextF.h>
#include <Xm/LabelG.h>
#include <Xm/PushBG.h>
#include <Xm/SeparatoG.h>
#include <stdio.h>
 
#include "grib1profile_externs.c"
#include "grib1profile.h"

#ifdef INTEGER_IS_INT
#define fortint int
#else
#define fortint long
#endif

#ifdef FINAL
/*
// The 'bin' directory for the final utility.
*/
#ifdef __uxp__
static char gDirectory[] = "/home/ma/emos/bin/";
#elif (defined linux)
static char gDirectory[] = "/home/ma/emos/bin/linux";
#elif (defined RS6000)
static char gDirectory[] = "/home/ma/emos/bin/rs6000";
#elif (defined hp)
static char gDirectory[] = "/home/ma/emos/bin/hppa";
#else
static char gDirectory[] = "/home/ma/emos/bin/sgimips";
#endif
#else
/*
// The development directory for the utility.
*/
static char gDirectory[] = ".";
#endif

/*
// Global names begin with "g"
// Callback names end with "_cb"
*/

/*
// Callback prototypes
*/
void file_open_cb ();
void file_quit_cb ();
void help_about_cb ();
void help_about_quit_cb ();
void help_help_cb ();
void help_help_quit_cb ();
void file_select_ok_cb ();
void filenameCreate_cb (int);
XtInputCallbackProc profile_cb( FILE * fin, int * fid, XtInputId * id);
XtInputCallbackProc gentext_cb( int * , int * , XtInputId * );

/*
// Local prototypes.
*/
int giveNextAvailableWidgetSlot(void) ;
void setInitialFileState( char ** , int );
void setText(char ** , Widget );
void setString(char ** , Widget );
static fortint fileRead(char *, fortint , void * stream);
void setup( char * filename, int);
void genText2( char *, long, int);
void genProfile2( );
XtWorkProc gentextWork( int * );
XtWorkProc profileWork( );
void clearGenProfile(void);
void clearGenText(int next);

static int gFirst = 0;
static int gFirstItem = 0;
static int gInitialise = 0;
static int gNext = -1;
static int gFree[MAXW];
static int gIndex[MAXW];
char * gSelectedGrib;
char * gOpenFile = NULL;
int gOpenFlag;
int gFullPrintFlag = 0;

#define MAX_IN_PROFILE 1000
static long gMaxInProfile;
long gRecNum;
/*
// The following will be dynamically increased if necessary
*/
static long * gRecordOffsets = NULL;
static char * gRecordTypes;

extern XtAppContext app_context;
 
XmTextPosition gTextCount;

char * gText = NULL;
char * gBuffer = NULL;
static char * gTextEmpty = "";
char * gWorking = "Working...";
char * gHeading = NULL;
char * gListLabel =
  "Number Type    Offset   Length Parameter   Level    Date    Time  Step Expver";
char * gBlankLabel = " ";

FILE * gProfileFin = NULL;
FILE * gGentextFin[MAXW];

XtInputId gGentextInput[MAXW];
XtInputId gProfileInput = NULL;
XtWorkProcId gGentextWorkId[MAXW];
XtWorkProcId gProfileWorkId = NULL;


void file_open_cb() {
/*
// Unleash the file select widget
*/
    XtRealizeWidget( file_select);
    XtManageChild( file_select);
} 

void file_quit_cb() {
/*
// Quit from the application.
*/
    exit(0);
}

void file_select_ok_cb(
  Widget w,
  XtPointer client_data,
  XmFileSelectionBoxCallbackStruct * call_data ) {
/*
// Respond to file selection.
*/
Widget file_text;

    switch( call_data->reason ) {

      case XmCR_OK:                             /* Open file */
        if ( gBuffer != NULL ) {
          XtFree( gBuffer );                     /* Free any existing buffer */
          gBuffer = NULL;
        }
        file_text = XmFileSelectionBoxGetChild( w, XmDIALOG_TEXT);
        gText = XmTextGetString( file_text );
        gTextCount = XmTextGetLastPosition( file_text );
        setInitialFileState( &gText , (int) gTextCount);
        XtFree(gText);
        XtUnrealizeWidget( w );
        break;

      case XmCR_CANCEL:                         /* Don't open file */
      case XmCR_HELP:
      case XmCR_NO_MATCH:
        XtUnrealizeWidget( w );
        break;

      default:
        break;
    }
    return;
}

void help_about_cb(
  Widget w,
  XtPointer client_data,
  XmAnyCallbackStruct * call_data) {
/*
// Display information about the application.
*/
    XtRealizeWidget( help_about_dialog);
    XtManageChild( help_about_dialog );
} 

void help_about_quit_cb(
  Widget w,
  XtPointer client_data,
  XmAnyCallbackStruct * call_data0) {
/*
// Quit 'help about'.
*/
    XtUnmanageChild( help_about_dialog );
} 

void help_help_cb(
  Widget w,
  XtPointer client_data,
  XmAnyCallbackStruct * call_data) {
/*
// Display help for the application from a text file.
*/
char * help_news;
FILE * news_in;
long nitems;
/*
// Open text file and read it.
*/
char directory[256];

    strcpy(directory, gDirectory);
    strcat(directory, "/grib1profile_help");
    news_in = fopen( directory, "r");
    if ( news_in == NULL ) {
      perror("help_help_cb failed to open grib1profile_help");
      exit(1);
    }

    help_news = (char *) XtMalloc( HELPNEWSLEN+1 );
    if ( help_news == NULL ) {
      perror("help_help_cb failed in XtMalloc");
      exit(1);
    }

    nitems = fread( help_news, 1, HELPNEWSLEN, news_in);
    help_news[nitems] = '\0';

    fclose( news_in );
/*
// Fire up the help widget.
*/
    setText( &help_news, help_help_text);
    XtFree( help_news );

    XtManageChild( help_help_dialog );
} 

void help_help_quit_cb(
  Widget w,
  XtPointer client_data,
  XmAnyCallbackStruct * call_data) {
/*
// Quit help screen.
*/
    XtUnmanageChild( help_help_dialog );
} 

void setText(char ** text, Widget w) {
/*
// Put text into a text widget.
*/
Arg arg[2];
Cardinal ac;

    if( w == NULL ) return;
    ac = 0;
    XtSetArg( arg[ac], XmNvalue, *text); ac++;
    XtSetValues( w, arg, ac);
    XmUpdateDisplay( w );
 
    return;
}

void setString(char ** text, Widget w) {
/*
// Put string into a label widget.
*/
XmString labeltext;
Arg arg[2];
Cardinal ac;

    if( w == NULL ) return;

    labeltext =
      XmStringCreateLtoR( *text, (XmStringCharSet)XmFONTLIST_DEFAULT_TAG );
    ac = 0;
    XtSetArg( arg[ac], XmNlabelString, labeltext); ac++;
    XtSetValues( w, arg, ac);
    XmStringFree( labeltext );
    XmUpdateDisplay( w );
 
    return;
}

void setInitialFileState( char ** filename, int num_chars ) {
/*
// Prepares widgets after a new file has been 'selected'.
*/
/*
// Clear the list widget showing the one-liners for the individual products.
*/
    XmListDeleteAllItems( list );
/*
// Fill in information for the new file.
*/
    setup( *filename, num_chars );
    clearGenProfile();
    genProfile2( );                           /* Generate the one-liners */
    gText = (char *) XtMalloc( strlen(gOpenFile)+1 );
    strcpy( gText, gOpenFile );
    gOpenFlag = 1;

    return;
}

int giveNextAvailableWidgetSlot(void) {
int loop;
/*
// First time only, set slots to 'unused'
*/
    if( gInitialise == 0 ) {
      for( loop = 0; loop < MAXW ; loop++ ) {
        gFree[loop] = 0;
        gIndex[loop] = loop;
      }
      gInitialise = 1;
    }

    for( loop = 0; loop < MAXW ; loop++ ) {
      if( gFree[loop] == 0 ) {
        gFree[loop] = 1;
        return (int) loop;
      }
    }
/*
// Fall through if all slots are full: use slot 0
*/
    XtDestroyWidget( pgrib1Listing[0] );
    return (int) 0;
}

XtInputCallbackProc profile_cb( FILE * fin, int * fid, XtInputId * id) {
/*
// Fire off the work procedure to fill in the profile of one-liners
// for the selected file.
*/
    clearGenProfile();
    gProfileWorkId =
      XtAppAddWorkProc( app_context, (XtWorkProc) profileWork, NULL);

    return 0; 
}
 
XtWorkProc profileWork( void ) {
/*
// The work procedure to build a profile of one-liners for a selected file.
*/
char buffer[GETLEN];
XmString item;
char * next;
long loop = 0;
char * pfilename = gOpenFile;
/*
//int itemCount;
//Arg al[64];
//register int ac = 0;
*/

/*
// First time through only, allocate space and set headings over list.
*/
    if ( gFirst == 0 ) {
      if( gRecordOffsets == NULL ) {
        gMaxInProfile = MAX_IN_PROFILE;
        gRecordOffsets =
              (long *) XtMalloc( (size_t) gMaxInProfile * sizeof(long));
        gRecordTypes =
              (char *) XtMalloc( (size_t) gMaxInProfile * sizeof(char *));
      }
      gRecNum = 0;
      gFirst = 1;
      setString( &gListLabel, scrolled_list_label);
    }
/*
// Not end of input, so add upto 500 lines a time to profile list.
*/
    if ( gProfileFin != NULL ) {
      while( (loop < 500) &&
             ((next = fgets(buffer, sizeof(buffer), gProfileFin)) != NULL) &&
             !feof(gProfileFin) ) {
        loop++;
        setString( &gWorking, current_filename);
/*
// Store type and offset for each product in the file.
*/
        sscanf( &buffer[6], "%4s%10d",
                    &gRecordTypes[gRecNum*4], &gRecordOffsets[gRecNum]);
        gRecNum++;
        if( gRecNum == gMaxInProfile ) {
          gMaxInProfile = gMaxInProfile * 2;
          gRecordOffsets =
            (long *) XtRealloc((char *) gRecordOffsets,
            (size_t) gMaxInProfile * sizeof(long));
          gRecordTypes =
            (char *) XtRealloc(gRecordTypes, (size_t) gMaxInProfile * 4);
        }
/*
// Add product description to list.
*/
        buffer[strlen(buffer)-1] = '\0';
        item = XmStringCreateSimple( buffer);
        XmListAddItem( list, item, (int) 0);
        if ( gRecNum == 1) XmListSelectItem( list, item, False);
        XmStringFree( item );
      }
/*
// Decode the first product in the list.
*/
      if ( gFirstItem == 0 ) {
        gFirstItem = 1;
        XmListSelectPos(list,gFirstItem,TRUE);
      }
    }
/*
// Check for end of input.
*/
    if( (gProfileFin == NULL) || ( (next == NULL) && feof(gProfileFin) ) ) {
      clearGenProfile();
      gFirst = 0;
      gFirstItem = 0;

      setString( &pfilename, current_filename);
      return (XtWorkProc) True;
    }
    else
      return (XtWorkProc) False;
}

void setup( char * filename, int num_chars) {
/*
// Inintialise for a new 'selected' file.
*/
    if( gOpenFile == NULL )
      gOpenFile = (char *) XtMalloc(num_chars+1);
    else 
      gOpenFile = (char *) XtRealloc(gOpenFile,(num_chars+1));

    if( gOpenFile == NULL ) {
      perror("XtMalloc/XtRealloc failed for gOpenFile");
      exit(1);
    }
    strcpy( gOpenFile, filename );
    gOpenFile[num_chars] = '\0';
    gRecNum = 0;
    gOpenFlag = 1;
  
    return;
}

static fortint fileRead(char * buff, fortint leng, void * file) {
/*  
//  Returns the number of bytes read.
//  On EOF, returns negative value for number of bytes read .
//
//  buff = buffer to fill,
//  leng = size of buff in bytes,
//  file = FILE *.
*/
fortint nbytes;

    nbytes = (fortint) fread( buff, 1, leng, (FILE *) file);
/*
// If EOF, return negative number of bytes read.
*/
    if ( feof((FILE *) file ) ) {
      clearerr( (FILE *) file );
      return (-nbytes);
    }

    return nbytes;
}

void genProfile2( ) {
/*
// Starts a process to generate the file profile.
*/
static char command[512];
/*
// Construct the process command.
*/
    strcpy(command, gDirectory);
    strcat(command, "/GRIB_profile ");
    strcat(command, gOpenFile );
/*
// Start process and a work procedure to receive its output down a pipe.
*/
    if ( gProfileFin != NULL ) pclose( gProfileFin );
    gProfileFin = popen( command, "r");
    gProfileInput =
      XtAppAddInput( app_context, fileno(gProfileFin),
                     (XtPointer)XtInputReadMask,
                     (XtInputCallbackProc)profile_cb,
                     (XtPointer)gProfileFin);

}

void genText2( char * type, long offset, int next) {
/*
// Prepare decoded text for a selected product.
*/
static char command[512];
char digits[20];
/*
// Empty the text widget.
*/
    clearGenText(next);
/*
// Starts a process to generate the decoded product.
*/
    strcpy(command, gDirectory);
    strcat(command, "/pgrib ");
    strcat(command, gOpenFile );

    sprintf(digits, " %10d", offset);
    digits[11] = '\0';
    strcat( command, digits );

    if( gHeading == NULL ) {
      gHeading = (char *) XtMalloc(256);
      if( gHeading == NULL ) {
        perror("XtMalloc failed for gHeading");
        exit(1);
      }
    }
    strcpy(gHeading,gOpenFile);
    strcat(gHeading,"\n\n");
    strcat(gHeading,gListLabel);
    strcat(gHeading,"\n");
    strcat(gHeading,gSelectedGrib);

/*
// Start process and a work procedure to receive its output down a pipe.
*/
    if ( gGentextFin[next] != NULL ) pclose( gGentextFin[next] );
    gGentextFin[next] = popen( command, "r");
    gGentextInput[next] =
      XtAppAddInput( app_context, fileno(gGentextFin[next]),
                     (XtPointer)XtInputReadMask,
                     (XtInputCallbackProc)gentext_cb,
                     (int*) &gIndex[next]  );
}

XtInputCallbackProc gentext_cb(
  int * next,
  int * source,
  XtInputId * id ) {
/*
// Fire off the work procedure to fill text widget with the decoded product.
*/
    gGentextWorkId[*next] =
      XtAppAddWorkProc( app_context, (XtWorkProc) gentextWork, next );

    return 0; 
}

XtWorkProc gentextWork( int * nextWidget ) {
/*
// Work procedure to fill text widget with the decoded product.
*/
char buffer[READLEN+1];
XmTextPosition lastpos;
long loop = 0;
long count;
int next = *nextWidget;
/*
// Not end of input, so add lines to end of text.
*/
    loop = 0;
    while( (loop < 1000) &&
           (gGentextFin[next] != NULL) &&
           (count = fread( buffer, 1, READLEN, gGentextFin[next] ) ) != 0 ) {
      loop++;
      buffer[count] = '\0';
      if( fileListing[next] != NULL ) {
        lastpos = XmTextGetLastPosition( fileListing[next] );
        XmTextInsert( fileListing[next], lastpos, buffer);
        XmTextSetInsertionPosition( fileListing[next], (XmTextPosition) 0);
      }
    }
/*
// Check for end of input.
*/
    if( (gGentextFin[next] == NULL ) || (feof(gGentextFin[next])) ) {
      clearGenText(next);
      setString(&gHeading,filenameLabel[next]);
      {
       char * string = XmTextGetString(fileListing[next]);
       long last = XmTextGetLastPosition(fileListing[next]);
       long loop, start = last - 5;
       char * p;

       for( loop = 0 ; loop < last; loop++ ) {
         if( strncmp("max =",&string[start],5) == 0 ) {
           break;
         }
         start--;
       }
       string[last-1] = '\0';
       p = &string[start];
       setString(&p,maxminLabel[next]);

       XtFree(string);
      }
      return (XtWorkProc) True;
    }
    else {
      return (XtWorkProc) False;
    }
}

void list_select_cb(
  Widget w,
  XtPointer client_data,
  XmListCallbackStruct * call_data) {
/*
// Handle selection of a product by clicking on the list of products.
*/
long current;

    switch( call_data->reason ) {
      case XmCR_SINGLE_SELECT:
        if ( gOpenFlag == 0 ) return;
/*
// Get selected item from list.
*/
        XmListSelectItem( list, call_data->item, False);
        current = (long) call_data->item_position - 1;

        XmStringGetLtoR(call_data->item,
                        (XmStringCharSet)XmFONTLIST_DEFAULT_TAG,
                        &gSelectedGrib);

        if ( current < 0 ) return;
/*
// Generate decoded text for the product.
*/
        gNext = giveNextAvailableWidgetSlot();
        filenameCreate_cb(gNext);
        setText( &gTextEmpty, fileListing[gNext]);
        clearGenText(gNext);
        genText2( &gRecordTypes[current*4], gRecordOffsets[current], gNext);
        break;

        default:
            break;
    }
}

void clearGenProfile(void) {
/*
// Clean up after work procedure generating the file profile.
*/
    if ( gProfileInput != NULL ) XtRemoveInput( gProfileInput );
    gProfileInput = NULL;

    if ( gProfileWorkId != NULL ) XtRemoveWorkProc( gProfileWorkId );
    gProfileWorkId = NULL;

}

void clearGenText(int next) {
/*
// Clean up after work procedure generating the text for a decoded product.
*/
  if ( gGentextInput[next] != NULL ) XtRemoveInput( gGentextInput[next] );
  gGentextInput[next] = NULL;

  if ( gGentextWorkId[next] != NULL ) XtRemoveWorkProc( gGentextWorkId[next] );
  gGentextWorkId[next] = NULL;

}

void filenameCreate_cb (int next) {
char digits[20];
Arg arg[2];
Cardinal ac;
char t[5];
int n, o, len, p, l;

    create_pgrib1Listing (grib1profile, next);

    sscanf(gSelectedGrib,"%d %s %d %d %d %d", &n, t, &o, &len, &p, &l);

    if( strcmp(t,"GRIB") == 0 )
      sprintf(digits, "%d/%d", p, l);
    else
      sprintf(digits,"%s",t);

    ac = 0;
    XtSetArg( arg[ac], XmNiconName, digits); ac++;
    XtSetValues( pgrib1Listing[next], arg, ac);

    XtPopup(pgrib1Listing[next],XtGrabNone);
}

XtCallbackProc textQuit_cb (
  Widget w,
  int * next,
  XmPushButtonCallbackStruct call_data) {

    clearGenText(*next);
    if( gGentextWorkId[*next] != NULL ) XtRemoveWorkProc(gGentextWorkId[*next]);
    gGentextWorkId[*next] = NULL;
    gGentextFin[*next] = NULL;
    fileListing[*next] = NULL;
    XtDestroyWidget( pgrib1Listing[*next]);
    gFree[*next] = 0;

    return (XtCallbackProc) 0;
}

static Widget pgrib1Listing_dialog[MAXW];
static Widget pgrib1Listing[MAXW];
static Widget maxminLabel[MAXW];
static Widget filenameLabel[MAXW];
static Widget fileListing[MAXW];
static Widget textQuit[MAXW];
static Widget scrolledText1[MAXW];


void create_pgrib1Listing (Widget parent, int next)
{
Widget children[5];            /* Children to manage */
Arg al[64];                    /* Arg List */
register int ac = 0;           /* Arg Count */
XmString xmstrings[16];        /* temporary storage for XmStrings */

    XtSetArg(al[ac], XmNallowShellResize, TRUE); ac++;
    XtSetArg(al[ac], XmNminWidth, 400); ac++;
    XtSetArg(al[ac], XmNminHeight, 400); ac++;
    XtSetArg(al[ac], XmNinput, FALSE); ac++;
    XtSetArg(al[ac], XmNbaseWidth, 600); ac++;
    XtSetArg(al[ac], XmNbaseHeight, 400); ac++;


    pgrib1Listing[next] = XtCreatePopupShell (
      "pgrib1Listing",
      topLevelShellWidgetClass,
      parent,
      al, ac );

    ac = 0;
    XtSetArg(al[ac], XmNautoUnmanage, TRUE); ac++;
    XtSetArg(al[ac], XmNinitialResourcesPersistent, FALSE); ac++;
    pgrib1Listing_dialog[next] =
      XmCreateForm ( pgrib1Listing[next], "pgrib1Listing_dialog", al, ac );

    ac = 0;
    xmstrings[0] =
      XmStringCreateLtoR("Working ...",
                         (XmStringCharSet)XmFONTLIST_DEFAULT_TAG);
    XtSetArg(al[ac], XmNlabelString, xmstrings[0]); ac++;
    XtSetArg(al[ac], XmNrecomputeSize, TRUE); ac++;
    filenameLabel[next] =
      XmCreateLabel ( pgrib1Listing_dialog[next], "filenameLabel", al, ac );

    ac = 0;
    xmstrings[0] =
      XmStringCreateLtoR("",
                         (XmStringCharSet)XmFONTLIST_DEFAULT_TAG);
    XtSetArg(al[ac], XmNlabelString, xmstrings[0]); ac++;
    XtSetArg(al[ac], XmNrecomputeSize, TRUE); ac++;
    maxminLabel[next] =
      XmCreateLabel ( pgrib1Listing_dialog[next], "maxminLabel", al, ac );

    ac = 0;
    XtSetArg(al[ac], XmNeditable, FALSE); ac++;
    XtSetArg(al[ac], XmNeditMode, XmMULTI_LINE_EDIT); ac++;
    fileListing[next] =
      XmCreateScrolledText ( pgrib1Listing_dialog[next], "fileListing", al, ac);

    ac = 0;
    scrolledText1[next] = XtParent ( fileListing[next] );

    ac = 0;
    xmstrings[0] =
      XmStringCreateLtoR("Quit", (XmStringCharSet)XmFONTLIST_DEFAULT_TAG);
    XtSetArg(al[ac], XmNlabelString, xmstrings[0]); ac++;
    textQuit[next] =
      XmCreatePushButton ( pgrib1Listing_dialog[next], "textQuit", al, ac );

    ac = 0;
    XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
    XtSetArg(al[ac], XmNbottomOffset, 5); ac++;
    XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
    XtSetArg(al[ac], XmNleftOffset, 5); ac++;
    XtSetValues ( textQuit[next],al, ac );

    ac = 0;
/*
    XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
    XtSetArg(al[ac], XmNtopOffset, 5); ac++;
    XtSetArg(al[ac], XmNtopWidget, scrolledText1[next]); ac++;
*/
    XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
    XtSetArg(al[ac], XmNleftOffset,15); ac++;
    XtSetArg(al[ac], XmNleftWidget, textQuit[next]); ac++;
    XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
    XtSetArg(al[ac], XmNbottomOffset, 10); ac++;
    XtSetValues ( maxminLabel[next],al, ac );

    ac = 0;
    XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
    XtSetArg(al[ac], XmNtopOffset, 5); ac++;
    XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
    XtSetArg(al[ac], XmNleftOffset, 5); ac++;
    XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
    XtSetArg(al[ac], XmNrightOffset, 5); ac++;
    XtSetValues ( filenameLabel[next],al, ac );

    ac = 0;
    XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
    XtSetArg(al[ac], XmNtopOffset, 5); ac++;
    XtSetArg(al[ac], XmNtopWidget, filenameLabel[next]); ac++;
    XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
    XtSetArg(al[ac], XmNbottomOffset, 35); ac++;
    XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
    XtSetArg(al[ac], XmNleftOffset, 5); ac++;
    XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
    XtSetArg(al[ac], XmNrightOffset, 5); ac++;
    XtSetValues ( scrolledText1[next],al, ac );

    ac = 0;
    XtManageChild(pgrib1Listing_dialog[next]);
    XtAddCallback( textQuit[next],
                   XmNactivateCallback ,
                   (XtCallbackProc) textQuit_cb,
                   (int*) &gIndex[next] );
    children[ac++] = textQuit[next];
    children[ac++] = maxminLabel[next];
    children[ac++] = filenameLabel[next];
    children[ac++] = scrolledText1[next];
    XtManageChildren(children, ac);

    ac = 0;
    XtManageChild(scrolledText1[next]);
    children[ac++] = fileListing[next];
    XtManageChildren(children, ac);

    ac = 0;

}

