[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Bug in nmap_spfw.c



Steve and Scott,

There is a latent bug in restoring an SPF with CAT_GRD/CAT_SFF/CAT_SNF,
and after fixing, reveals another problem.

The segment of code in nmap_spfw.c starting with line 2213 is:

        /*
         *  Find the latest time string "YYMMDD/HHMM".
         */
        len = sizeof( moslst );
        gd_gcyc ( grdStr, ";", &nn, moslst, &ier, strlen(grdStr), 1, len);
        cst_rmbl ( moslst, moslst, &len, &ier);

The moslst string on return from gd_gcyc is not null terminated. The
cst_rmbl routine requires the string to be null terminated- and
possibly returns some added garbage on the moslst string until a '\0'
is found.

I added the null character following the gd_gcyc call above:
        moslst[len - 1] = '\0';

After fixing that,  you will find that when more than 1 cycle is returned,
the test below (on line 2231) always fails:

        if ( isdigit( (int)moslst[noc2+1] ) &&
             (int)strlen( moslst ) > (noc2 + 12) ) {

This test should be:

        if ( isdigit( (int)moslst[noc2+1] ) &&
             (int)strlen( moslst ) >= (noc2 + 12) ) {
 
In the past, if you were "lucky" enough to get some added garbage tacked
on to the expected time list in cst_rmbl, you could get past this-
and the later usage of just 11 characters worked anyhow.

On several platforms, I didn't get garbage tacked on and could not get
past that condition.

I have attached the routine as described (though strrchr might be easier
to follow).

Steve

#include "geminc.h"
#include "gemprm.h"
#include "nmap_data.h"
#include "Nxm.h"
#include "nmsdef.h"
#include "ctbcmn.h"

#define VISIBLE_ITEM      10 
#define MAX_FILES       1000

#define SORT_BY_NAME       0
#define SORT_BY_DATE       1

#define SAVE_AS_CURRENT    1
#define SAVE_AS_LITERAL    0

#define RESTORE_POPUP      0
#define SAVE_POPUP         1

#define SPF_FILE_EXT    ".spf"
#define FILE_PATTERN    "*.spf"
#define LOCAL_DIR       "./"
#define CWD_TITLE       "Local"

typedef XmFileSelectionBoxCallbackStruct FSBCBS;

static Widget   _fileSelW;
static Widget   _dirSel_listW;
static Widget   _fileSel_listW;
static Widget   _fileSel_txtW;

static Widget   _browsePopup;
static Widget   _sortRadioW;
static Widget   _stimeRadioW;
static WidgetList _sortBtn;
static WidgetList _stimeBtn;


static Widget   _sortPaneW;
static Widget   _selectPaneW;
static Widget   _inputPaneW;
static Widget   _browseBtnPane;
static Widget   _bottomPaneW;
static Widget   _restoreConfW;
static Widget   _rstContentW;
static Widget   _rstConfLblW;
static Widget   _stimePaneW;

static char     _fileName[FILE_NAMESZ]  = "\0";
static char     _dirPath[LLPATH]        = LOCAL_DIR;
static int      _dirPos;

static int      _spfilFunc;     /* RESTORE_SPF,  SAVE_SPF */
static int      _sortBy;        /* SORT_BY_NAME or SORT_BY_DATE  */
static int      _stimeBy;       /* SAVE_AS_CURRENT or SAVE_AS_LITERAL */

/*
 *  SPF user info data struct
 */
typedef struct {
        char    *title;         /* title name */
        char    *usrpath;       /* full path to this user's SPF dir */
} spfusr_ent_t;

/*
 *  SPF user info table struct
 */
typedef struct {
    int                 nitems; /* total # of users*/
    spfusr_ent_t        *items; /* pointer to the array of user items */
} spfutbl_t;

static spfutbl_t        _spfUsrTbl;

/*
 *  private callback functions
 */
void spfw_browseBtnCb ( Widget wid, XtPointer client, XtPointer cbs);
void spfw_browseDoneCb ( Widget wid, XtPointer client, XtPointer cbs );
void spfw_btmCtlBtnCb ( Widget wid, int which, XtPointer call );
void spfw_confirmCb (Widget wid, XtPointer client, XtPointer cbs);
void spfw_selectCb ( Widget wid, XtPointer client, XtPointer call );
void spfw_selectDirCb ( Widget wid, XtPointer client, XtPointer call );
void spfw_sortByCb ( Widget wid, XtPointer client, XtPointer cbs );
void spfw_stimeCb ( Widget wid, XtPointer client, XtPointer cbs );
void spfw_txtCb ( Widget wid, XtPointer client, XtPointer call );
void spfw_rstConfCb( Widget wid, XtPointer client, XtPointer call );

/*
 *  private functions
 */
static void spfw_checkPerms ( char *cfile, Boolean *can_read, 
                                           Boolean *can_write );
static void spfw_managePanes ( int popup_type);
static void spfw_preCheck ( void );
static void spfw_restoreSPF ( void );
static void spfw_saveSPF ( void );  
static void spfw_setFileList ( void );
static void spfw_unmanagePanes ( void );
static void spfw_readUsrTbl ( char      *tblname,
                              spfutbl_t *spfutbl,
                              int       *iret );
void spfw_createConf( Widget parent );
void spfw_popupConf( void );
void spfw_popdownConf( void );
void spfw_formatConf ( long flen, char *spftext, char *filstr, int *iret );
static void spfw_saveSrcAttr ( dsrc_t *datasrc, FILE *fptr, int lp, int srcnum 
);

/************************************************************************
 * nmap_spfw.c                                                          *
 *                                                                      *
 * This module defines the SPF file selection (RESTORE/SAVE) in Data    *
 * Selection.                                                           *
 *                                                                      *
 * CONTENTS:                                                            *
 *  spfw_create()               creates file selection pallette         *
 *  spfw_popup()                popup the palette window                *
 *  spfw_popdown()              put down the palette window             *
 *  spfw_getFileName()          gets the full name of selected SPF file *
 *  spfw_getSource()            gets a specified source in a given loop *
 *                                                                      *
 *  spfw_browseBtnCb()          callback for the browse button          *
 *  spfw_browseDoneCb()         callback for browse OK/Cancel buttons   *
 *  spfw_btmCtlBtnCb()          callback for bottom control buttons     *
 *  spfw_confirmCb()            callback for RESTORE/SAVE confirmation  *
 *  spfw_selectCb()             callback for file list                  *
 *  spfw_selectDirCb()          callback for directory list             *
 *  spfw_sortByCb()             callback for sort by toggles            *
 *  spfw_txtCb()                callback for text input                 *
 *                                                                      *
 *  spfw_checkPerms()           checks file permissions                 *
 *  spfw_managePanes()          manages the appropiate children of pane *
 *  spfw_preCheck()             checks the file before restoring/saving *
 *  spfw_restoreSPF()           restores the specified SPF file         *
 *  spfw_setFileList()          sets the file list for the _dirPath     *
 *  spfw_readUsrTbl()           reads SPF file user table "spf.nmap"    *
 *  spfw_saveSPF()              saves settings into an SPF file         *
 *  spfw_unmanagePanes()        unmanages all the children of pane      *
 *                                                                      *
 *  spfw_createConf()           creates restore confirmation pallette   *
 *  spfw_popupConf()            pops up restore confirmation window     *
 *  spfw_popdownConf()          pops down restore confirmation window   *
 *  spfw_rstConfCb()            callback for restore confirmation       *
 *  spfw_formatConf()           formats source string for restore conf. *
 *  spfw_saveSrcAttr()          saves a data source's attr. settings    *
 ************************************************************************/

/*=====================================================================*/

void spfw_create ( Widget parent )
/************************************************************************
 * spfw_create                                                          *
 *                                                                      *
 * This function creates a file selection dialog box.                   *
 *                                                                      *
 * void spfw_create ( parent )                                          *
 *                                                                      *
 * Input parameters:                                                    *
 *      parent          Widget          Parent widget                   *
 *                                                                      *
 * Output parameters:                                                   *
 * Return parameters:                                                   *
 *                      NONE                                            *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            06/01   revise from pgfilw_create()             *
 * E. Safford/SAIC      11/01   fix interaction problems w/ dataw       *
 * T. Piper/SAIC        10/05   declared ii long                        *
 * C. Bailey/HPC        01/06   Added Save Literal Time Pane            *
 ***********************************************************************/
{
    int                 nn, toff = 5, ier;
    long                ii;
    char                *btm_btnstr[] = {"OK", "Cancel"}; 
    char                *sort_str[] = {"Name", "Date"};
    char                *stime_str[] = {"Constant", "Latest"};
    Widget              pane, label, label2, frame, sort_label, stime_label;
    Arg                 args[10];
    Cardinal            argcnt;
    XmString            xmpattern; 
    XmStringTable       xmfils;
/*---------------------------------------------------------------------*/

    _fileSelW = XmCreateFormDialog( parent, "Save as", NULL, 0 );
    XtVaSetValues(_fileSelW,
                XmNdialogStyle,         XmDIALOG_APPLICATION_MODAL,
                NULL);

    /*
     * create a parent pane widget
     */
    pane = XtVaCreateWidget("spfw_pane",
                    xmPanedWindowWidgetClass, _fileSelW,
                    XmNsashWidth,             1,
                    XmNsashHeight,            1,
                    NULL);

    
    /*
     * ******** SORT PANE ********
     * create a form widget to hold the sort by toggles
     */
    _sortPaneW = XtVaCreateWidget("spfw_form",
                    xmFormWidgetClass,        pane,
                    XmNnoResize,              TRUE,
                    XmNautoUnmanage,          FALSE,
                    NULL );

    sort_label = XmCreateLabel( _sortPaneW, 
                    "Display Files In Order By:", NULL, 0 );
    XtVaSetValues( sort_label,
                    XmNtopAttachment,         XmATTACH_POSITION,
                    XmNtopPosition,           2,
                    XmNleftAttachment,        XmATTACH_POSITION,
                    XmNleftPosition,          1,
                    XmNrightAttachment,       XmATTACH_POSITION,
                    XmNrightPosition,         60,
                    NULL );
    XtManageChild( sort_label );

    _sortRadioW = XtVaCreateManagedWidget ("sort_radio",
                    xmRowColumnWidgetClass,   _sortPaneW,
                    XmNorientation,           XmVERTICAL,
                    XmNradioBehavior,         True,
                    XmNtopAttachment,         XmATTACH_WIDGET,
                    XmNtopWidget,             sort_label,
                    XmNrightAttachment,       XmATTACH_FORM,
                    XmNleftAttachment,        XmATTACH_FORM,
                    NULL);

    nn = XtNumber (sort_str);
    _sortBy = SORT_BY_NAME;
    _sortBtn = (WidgetList)XtMalloc((size_t)nn*sizeof(Widget));

    for (ii = 0; ii < nn; ii++) {
        _sortBtn[ii] = XtVaCreateManagedWidget (sort_str[ii],
                    xmToggleButtonWidgetClass,      _sortRadioW,
                    XmNtraversalOn,                 FALSE,
                    NULL);
        XtAddCallback(_sortBtn[ii], XmNdisarmCallback,
                    spfw_sortByCb, (XtPointer) ii);

        XmToggleButtonSetState (_sortBtn[ii], (_sortBy == ii), FALSE);
    }

    XtManageChild(_sortPaneW); 


    /*
     * ******** SELECT PANE ********
     * create a form widget to hold the directory and file lists
     */
    _selectPaneW = XtVaCreateWidget("spfw_selectform",
                    xmFormWidgetClass,  pane,
                    NULL);
    XtVaSetValues( _selectPaneW,
                    XmNnoResize,     TRUE,
                    XmNautoUnmanage, FALSE,
                    NULL );

    
    /*
     * create the directory list
     */
    label = XmCreateLabel( _selectPaneW, "Select directory:", NULL, 0 );
    XtManageChild( label );
    XtVaSetValues( label,
                    XmNtopAttachment,   XmATTACH_POSITION,
                    XmNtopPosition,     2,
                    XmNleftAttachment,  XmATTACH_POSITION,
                    XmNleftPosition,    1,
                    XmNrightAttachment, XmATTACH_POSITION,
                    XmNrightPosition,   60,
                    NULL );

    frame = XmCreateFrame( _selectPaneW, "_DirSel_frameW", NULL, 0 );
    XtVaSetValues( frame,
                    XmNtopAttachment,    XmATTACH_WIDGET,
                    XmNtopWidget,        label,
                    XmNrightAttachment,  XmATTACH_FORM,
                    XmNleftAttachment,   XmATTACH_FORM,
                    NULL );

    _dirSel_listW = XmCreateScrolledList( frame,
                                          "_DirSel_lstW", NULL, 0 );
    XtVaSetValues( _dirSel_listW,
                    XmNvisibleItemCount, VISIBLE_ITEM,
                    NULL );
    XtAddCallback( _dirSel_listW, XmNbrowseSelectionCallback,
                   spfw_selectDirCb, NULL );


    spfw_readUsrTbl("spf.nmap", &_spfUsrTbl, &ier);

    if ( _spfUsrTbl.nitems > 0) {

        xmfils = (XmStringTable) XtMalloc 
            ((size_t)_spfUsrTbl.nitems * sizeof (XmString *));

        for (ii = 0; ii < _spfUsrTbl.nitems; ii++) {
            xmfils[ii] = XmStringCreateLocalized (_spfUsrTbl.items[ii].title);
        }

        XtVaSetValues (_dirSel_listW,
                       XmNitems,        xmfils,
                       XmNitemCount,    _spfUsrTbl.nitems,
                       NULL);

        for (ii = 0; ii < _spfUsrTbl.nitems; ii++) {
            XmStringFree (xmfils[ii]);
        }
        XtFree ((XtPointer)xmfils);

        /*
         * hi-light the local directory
         */
        _dirPos = _spfUsrTbl.nitems;
    }

    XtManageChild( _dirSel_listW );
    XtManageChild( frame );

    
    /*
     * create the file list
     */
    label = XmCreateLabel( _selectPaneW, "Select SPF File name:", NULL, 0 );
    XtManageChild (label );
    XtVaSetValues (label,
                   XmNtopAttachment,    XmATTACH_WIDGET,
                   XmNtopWidget,        frame,
                   XmNtopOffset,        toff,
                   XmNleftAttachment,   XmATTACH_POSITION,
                   XmNleftPosition,     1,
                   XmNrightAttachment,  XmATTACH_POSITION,
                   XmNrightPosition,    60,
                   NULL );

    frame = XmCreateFrame( _selectPaneW, "_FileSel_frameW", NULL, 0 );
    XtVaSetValues (frame,
                   XmNtopAttachment,    XmATTACH_WIDGET,
                   XmNtopWidget,        label,
                   XmNrightAttachment,  XmATTACH_FORM,
                   XmNleftAttachment,   XmATTACH_FORM,
                   NULL);

    _fileSel_listW = XmCreateScrolledList (frame, "_FileSel_lstW", NULL, 0);

    XtVaSetValues (_fileSel_listW,
                   XmNvisibleItemCount, VISIBLE_ITEM,
                   NULL);

    XtAddCallback (_fileSel_listW, XmNbrowseSelectionCallback,
                   spfw_selectCb, NULL);


    XtManageChild (_fileSel_listW);
    XtManageChild (frame);

    XtManageChild(_selectPaneW);

    
    /*
     * ******** INPUT PANE ********
     * create the file input
     */
    _inputPaneW = XtVaCreateWidget("spfw_inputForm",
                                   xmFormWidgetClass,   pane,
                                   NULL);
    XtVaSetValues( _inputPaneW,
                    XmNnoResize,     TRUE,
                    XmNautoUnmanage, FALSE,
                    NULL );

    label2 = XmCreateLabel (_inputPaneW, "Or enter an SPF file name:", NULL, 0);
    XtManageChild (label2);
    XtVaSetValues (label2,
                   XmNtopAttachment,    XmATTACH_WIDGET,
                   XmNtopWidget,        frame,
                   XmNtopOffset,        toff,
                   XmNleftAttachment,   XmATTACH_POSITION,
                   XmNleftPosition,     3,
                   XmNrightAttachment,  XmATTACH_POSITION,
                   XmNrightPosition,    70,
                   NULL );

    _fileSel_txtW = XmCreateText (_inputPaneW, "spfw_inputText", NULL, 0);
    XtManageChild (_fileSel_txtW);
    XtVaSetValues (_fileSel_txtW,
                   XmNtopAttachment,   XmATTACH_WIDGET,
                   XmNtopWidget,       label2,
                   XmNrightAttachment, XmATTACH_FORM,
                   XmNleftAttachment,  XmATTACH_FORM,
                   NULL);
    XtAddCallback (_fileSel_txtW, XmNactivateCallback,
                   spfw_txtCb, NULL ); 

    XtManageChild (_inputPaneW);


    /*
     * ******** BROWSE PANE ********
     */
    _browseBtnPane = 
        XtVaCreateManagedWidget ("Browse",
                                 xmPushButtonWidgetClass, pane,
                                 NULL);
    XtAddCallback(_browseBtnPane, XmNarmCallback,
                  spfw_browseBtnCb, (XtPointer) NULL); 

    /*
     * ******** SAVE LITERAL TIME PANE ********
     */
    _stimePaneW = XtVaCreateWidget("spfw_stimeform",
                    xmFormWidgetClass,        pane,
                    XmNnoResize,              TRUE,
                    XmNautoUnmanage,          FALSE,
                    NULL );

    stime_label = XmCreateLabel( _stimePaneW,
                    "Save Source Timestamp As:", NULL, 0 );
    XtVaSetValues( stime_label,
                    XmNtopAttachment,         XmATTACH_POSITION,
                    XmNtopPosition,           2,
                    XmNleftAttachment,        XmATTACH_POSITION,
                    XmNleftPosition,          1,
                    XmNrightAttachment,       XmATTACH_POSITION,
                    XmNrightPosition,         60,
                    NULL );
    XtManageChild( stime_label );

    _stimeRadioW = XtVaCreateManagedWidget ("stime_radio",
                    xmRowColumnWidgetClass,   _stimePaneW,
                    XmNorientation,           XmHORIZONTAL,
                    XmNradioBehavior,         True,
                    XmNtopAttachment,         XmATTACH_WIDGET,
                    XmNtopWidget,             stime_label,
                    XmNrightAttachment,       XmATTACH_FORM,
                    XmNleftAttachment,        XmATTACH_FORM,
                    NULL);

    nn = XtNumber (stime_str);
    _stimeBy = SAVE_AS_CURRENT;
    _stimeBtn = (WidgetList)XtMalloc((size_t)nn*sizeof(Widget));

    for (ii = 0; ii < nn; ii++) {
        _stimeBtn[ii] = XtVaCreateManagedWidget (stime_str[ii],
                    xmToggleButtonWidgetClass,      _stimeRadioW,
                    XmNtraversalOn,                 FALSE,
                    NULL);
        XtAddCallback(_stimeBtn[ii], XmNdisarmCallback,
                    spfw_stimeCb, (XtPointer) ii);

        XmToggleButtonSetState (_stimeBtn[ii], (_stimeBy == ii), FALSE);
    }

    XtManageChild(_stimePaneW);

    /*
     * ******** BOTTOM CONTROL PANE ********
     */
    _bottomPaneW = 
        (Widget) NxmCtlBtn_create (pane, 1, "spfw_btm", 
                                   XtNumber(btm_btnstr), btm_btnstr, 
                                   (XtCallbackProc)spfw_btmCtlBtnCb, NULL);

    XtManageChild(pane);

    
    /*
     * browse popup
     */
    argcnt = 0;

    xmpattern  = XmStringCreateLocalized(FILE_PATTERN);

    XtSetArg (args[argcnt], XmNpattern, xmpattern); 
    argcnt++;

    XtSetArg (args[argcnt], XmNtitle, "Browse"); 
    argcnt++;

    _browsePopup = XmCreateFileSelectionDialog(parent, "browseBox", 
                                               args, argcnt);
    XmStringFree(xmpattern);

    XtAddCallback(_browsePopup, XmNcancelCallback,
                  spfw_browseDoneCb, (XtPointer) 0);
    XtAddCallback(_browsePopup, XmNokCallback,
                  spfw_browseDoneCb, (XtPointer) 1);

    XtUnmanageChild(XmFileSelectionBoxGetChild(_browsePopup, 
                                               XmDIALOG_HELP_BUTTON));

    /*
     *  Restoring confirmation popup     
     */
    spfw_createConf( pane );

}

/*=====================================================================*/

void spfw_popup ( int func )
/************************************************************************
 * spfw_popup                                                           *
 *                                                                      *
 * This function loads and displays the SPF file names into the file    *
 * selection dialog box.                                                *
 *                                                                      *
 * void spfw_popup ( func )                                             *
 *                                                                      *
 * Input parameters:                                                    *
 *      func            int             Action function                 *
 *                                          0 - RESTORE_SPF             *
 *                                          1 - SAVE_SPF                *
 *                                                                      *
 * Output parameters:                                                   *
 * Return parameters:                                                   *
 *                      NONE                                            *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            06/01   revise from pgfilw_popup()              *
 ***********************************************************************/
{
    int         ipos;
    XmString    xmstr, dirstr;
/*---------------------------------------------------------------------*/

    _spfilFunc = func;

    /*
     * set the dialog title 
     */
    if ( func == SAVE_SPF ) {
        xmstr = XmStringCreateLocalized("Save To SPF File");
        dirstr = XmStringCreateLocalized(LOCAL_DIR);
        XtVaSetValues(_browsePopup, XmNdirectory, dirstr, NULL);
        XmStringFree (dirstr);

        spfw_managePanes (SAVE_POPUP);
    }
    else {
        xmstr = XmStringCreateLocalized("Restore From SPF File");

        spfw_managePanes (RESTORE_POPUP);
    }

    XtVaSetValues (_fileSelW, XmNdialogTitle, xmstr, NULL);
    XtVaSetValues (_browsePopup, XmNdialogTitle, xmstr, NULL);
    XmStringFree (xmstr);

    /*
     * hi-light the current directory
     */
    ipos = _dirPos;
    XmListSelectPos (_dirSel_listW, ipos, TRUE);

    ipos += (VISIBLE_ITEM / 2);
    if (ipos < VISIBLE_ITEM) ipos = VISIBLE_ITEM;
    if (ipos > _spfUsrTbl.nitems) ipos = _spfUsrTbl.nitems;

    XmListSetBottomPos (_dirSel_listW, ipos);

    /*
     * set input text widget
     */
    XmTextSetString( _fileSel_txtW, _fileName );

    spfw_setFileList ();

    XtManageChild(_fileSelW);

}

/*=====================================================================*/

void spfw_popdown ( void )
/************************************************************************
 * spfw_popdown                                                         *
 *                                                                      *
 * This function puts the file window down.                             *
 *                                                                      *
 * void spfw_popdown ( )                                                *
 *                                                                      *
 * Input parameters:                                                    *
 * Output parameters:                                                   *
 * Return parameters:                                                   *
 *                      NONE                                            *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            06/01   copy from pgfilw_popdown()              *
 * J. Wu/GSC            07/01   call spfw_popdownConf()                 *
 ***********************************************************************/
{
    spfw_popdownConf (); 
    
    if (XtIsManaged (_fileSelW)) {
        XtUnmanageChild (_fileSelW);
    }

    if (XtIsManaged (_browsePopup)) {
        XtUnmanageChild (_browsePopup);
    }

}


/*=====================================================================*/
/* ARGSUSED */
void spfw_selectCb ( Widget wid, XtPointer client, XtPointer call )
/************************************************************************
 * spfw_selectCb                                                        *
 *                                                                      *
 * Callback function for selecting an SPF File.                         *
 *                                                                      *
 * void spfw_selectCb (wid, client, call)                               *
 *                                                                      *
 * Input parameters:                                                    *
 *      wid             Widget          Widget that activated callback  *
 *      client          XtPointer       Pointer to client data (NULL)   *
 *      call            XtPointer       Callback trigger                *
 *                                                                      *
 * Output parameters:                                                   *
 *                      NONE                                            *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            06/01   copy from pgfilw_selectCb()             *
 ***********************************************************************/
{
    XmListCallbackStruct *cbs = (XmListCallbackStruct *) call;
    char * tmp_str;
/*---------------------------------------------------------------------*/

    XmStringGetLtoR (cbs->item, XmFONTLIST_DEFAULT_TAG, &tmp_str);

    strcpy (_fileName, tmp_str);

    XmTextSetString (_fileSel_txtW, _fileName);

    XtFree (tmp_str);

}

/*=====================================================================*/
/* ARGSUSED */
void spfw_selectDirCb ( Widget wid, XtPointer client, XtPointer call )
/************************************************************************
 * spfw_selectDirCb                                                     *
 *                                                                      *
 * Callback function for selecting an SPF File.                         *
 *                                                                      *
 * void spfw_selectDirCb (wid, client, call)                            *
 *                                                                      *
 * Input parameters:                                                    *
 *      wid             Widget          Widget that activated callback  *
 *      client          XtPointer       Pointer to client data (NULL)   *
 *      call            XtPointer       Callback trigger                *
 *                                                                      *
 * Output parameters:                                                   *
 *                      NONE                                            *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            06/01   copy from pgfilw_selectDirCb()          *
 ***********************************************************************/
{

    XmListCallbackStruct *cbs = (XmListCallbackStruct *) call;

/*---------------------------------------------------------------------*/

    _dirPos = cbs->item_position;

    if ( _dirPos == _spfUsrTbl.nitems ) {
        strcpy ( _dirPath, LOCAL_DIR );
    }
    else {
        strcpy ( _dirPath, _spfUsrTbl.items[(_dirPos) - 1].usrpath );
        if ( _dirPath[ ( strlen(_dirPath) - 1 ) ] != '/' ) {
            strcat ( _dirPath, "/" );
        }
    }
    
    spfw_setFileList ( );

}

/*=====================================================================*/
/* ARGSUSED */
void spfw_txtCb ( Widget wid, XtPointer client, XtPointer call )
/************************************************************************
 * spfw_txtCb                                                           *
 *                                                                      *
 * Callback function for text input widget.                             *
 *                                                                      *
 * void spfw_txtCb ( wid, client, call )                                *
 *                                                                      *
 * Input parameters:                                                    *
 *      wid             Widget          Widget that activated callback  *
 *      client          XtPointer       Pointer to client data (NULL)   *
 *      call            XtPointer       Callback trigger                *
 *                                                                      *
 * Output parameters:                                                   *
 *                      NONE                                            *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            06/01   initial coding                          *
 ***********************************************************************/
{
    spfw_btmCtlBtnCb( NULL, 0, NULL ); 
}

/*=====================================================================*/
/* ARGSUSED */ 
void spfw_confirmCb ( Widget wid, XtPointer client, XtPointer cbs )
/************************************************************************
 * spfw_confirmCb                                                       *
 *                                                                      *
 * Callback function for confirming to restore/save an SPF file.        *
 *                                                                      *
 * void spfw_confirmCb (wid, client, cbs)                               *
 *                                                                      *
 * Input parameters:                                                    *
 *      wid             Widget          Widget that activated callback  *
 *      client          XtPointer       Pointer to client data (GrInfo) *
 *      cbs             XtPointer       callback struct                 *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            06/01   initial coding                          *
 * J. Wu/GSC            07/01   load & check SPF file before restoring  *
 * R. Tian/SAIC         01/02   fixed bug when loading large SPF file   *
 * J. Wu/GSC            04/02   fixed crash bug for certain short SPF   *
 *                              files without valid data sources in it  *
 * M. Li/SAIC           12/02   popup Restore Confirmation only in need *
 ***********************************************************************/
{
    int         ier;
    char        spfile[FILE_NAMESZ], *spftext, lblStr[256];
    char        newfil[LLPATH], tmpStr[256];
    char        prefs_tag[MAX_PREF_STR] = "RESTORE_POPUP";
    long        flen = 0;
    XmString    xmstr;
    const int   addFmtLen = 128; /* Additional string length required to
                                    hold the format message */
    Boolean     bal;
                                    
/*---------------------------------------------------------------------*/

    if ( strlen(_fileName) > (size_t)0 ) {
        
        if ( _spfilFunc == RESTORE_SPF ) {
                    
            /*
             *  Retrieve the selected SPF file and load into SPF buffer.
             */
            spfw_getFileName( spfile );
            spf_load ( spfile, &ier );

            /*
             *  Pop up confirmation window with SPF file content in it.
             */
            if ( ier < 0 ) {    
                NxmWarn_show ( _fileSelW, "Failed to load SPF file" );
            }
            else {           
                /*
                 * Query the actual SPF file size in order to deal with a
                 * SPF file with any size.
                 */
                cfl_inqr(spfile, NULL, &flen, newfil, &ier);            

                flen += (long)addFmtLen;
                if ( ier < 0 ) {        
                    NxmWarn_show ( _fileSelW, "Failed to query SPF file size" );
                }
                else {
                    if( ! (spftext = XtMalloc((Cardinal)flen))) {
                        NxmWarn_show ( _fileSelW, 
                                       "Failed to allocate space for SPF file" 
);
                    }
                    else {                              
                        spfw_formatConf( flen, spftext, lblStr, &ier );

                        if ( ier == 0 ) {
                            XmTextSetString( _rstContentW, spftext );
                            xmstr = XmStringCreateLtoR(lblStr, 
                                                       XmFONTLIST_DEFAULT_TAG);
                            XtVaSetValues( _rstConfLblW,
                                          XmNlabelString, xmstr,
                                          XmNalignment,   XmALIGNMENT_BEGINNING,
                                          NULL);
                            XmStringFree( xmstr );               

                            ctb_pfbool(prefs_tag, &bal, &ier);
                            if ( bal ) {
                                spfw_popupConf (); 
                            }
                            else {
                                spfw_popdownConf ();
                                spfw_popdown ();
                                spfw_restoreSPF ();
                            }

                        }
                        else {
                            sprintf ( tmpStr, "No valid data sources found in 
%s\n", 
                                               _fileName ); 
                            NxmWarn_show ( _fileSelW, tmpStr );
                        }
                      
                         XtFree(spftext);
                    }
                }              
            }
            
        }
        else {  
             spfw_popdown ();
             spfw_saveSPF ();
        }            
    }    
    
}

/*=====================================================================*/
/* ARGSUSED */ 
void spfw_browseBtnCb ( Widget wid, XtPointer client, XtPointer cbs )
/************************************************************************
 * spfw_browseBtnCb                                                     *
 *                                                                      *
 * Callback function for the browse button on file selection palette.   *
 *                                                                      *
 * void spfw_browseBtnCb (wid, client, cbs)                             *
 *                                                                      *
 * Input parameters:                                                    *
 *      wid             Widget          Widget that activated callback  *
 *      client          XtPointer       Pointer to client data (GrInfo) *
 *      cbs             XtPointer       callback struct                 *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            06/01   revise from pgfilw_browseBtnCb()        *
 ***********************************************************************/
{
    /*
     *  Browse always starts from the local directory.
     */
    strcpy ( _dirPath, LOCAL_DIR );
    
    XtManageChild ( _browsePopup );

}

/*=====================================================================*/
/* ARGSUSED */ 
void spfw_browseDoneCb ( Widget wid, XtPointer client, XtPointer cbs )
/************************************************************************
 * spfw_browseDoneCb                                                    *
 *                                                                      *
 * Callback function for the Ok/Cancel buttons on the browse palette.   *
 *                                                                      *
 * void spfw_browseDoneCb (wid, client, cbs)                            *
 *                                                                      *
 * Input parameters:                                                    *
 *      wid             Widget          Widget that activated callback  *
 *      client          XtPointer       Pointer to client data (GrInfo) *
 *      cbs             XtPointer       callback struct                 *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            06/01   revise from pgfilw_browseDoneCb()       *
 * E. Safford/SAIC      04/02   use cfl_isdir instead of local version  *
 ***********************************************************************/
{
    int         which, ier;
    char        *text;
    char        filepart[FILE_NAMESZ] = "\0" , pathpart[LLPATH] = "\0";
    Widget      popup;
    FSBCBS      *fcbs;
/*---------------------------------------------------------------------*/

    which = (long) client;
    
    if ( which == 1 ) { /* OK */
        
        fcbs = (FSBCBS *) cbs;
        XmStringGetLtoR ( fcbs->value, XmFONTLIST_DEFAULT_TAG, &text );
        
        if ( cfl_isdir ( text )  ) {
            _fileName[0] = '\0';             
            strcpy ( _dirPath, text );  
        } 
        else {
            cfl_path ( text, pathpart, filepart, &ier ) ;   
            if ( filepart[0] != '\0' ) {
                strcpy ( _fileName, filepart );         
            }   
            if ( pathpart[0] != '\0' ) {
                strcpy ( _dirPath, pathpart );  
            }   
        }
        
        if ( _dirPath[ ( strlen(_dirPath) - 1 ) ] != '/' ) {
            strcat ( _dirPath, "/" );
        }
                       
        XtFree ( text );
        XmTextSetString ( _fileSel_txtW, _fileName );
        XmTextSetInsertionPosition ( _fileSel_txtW, (long)strlen(_fileName) );

        if ( _fileName[0] == '\0' ) {
            popup = ( XtIsManaged (_browsePopup)) ? _browsePopup : _fileSelW;
            NxmWarn_show ( popup, "Please select or input a file name." );
        }
        else {
            spfw_preCheck ( );
        }
       
    }
    else {  /* CANCEL */
        XtUnmanageChild ( _browsePopup );
    }
    
}

/*=====================================================================*/
/* ARGSUSED */ 
void spfw_sortByCb ( Widget wid, XtPointer client, XtPointer cbs )
/************************************************************************
 * spfw_sortByCb                                                        *
 *                                                                      *
 * Callback function for the sort by toggles                            *
 *                                                                      *
 * void spfw_sortByCb ( wid, client, cbs )                              *
 *                                                                      *
 * Input parameters:                                                    *
 *      wid             Widget          Widget that activated callback  *
 *      client          XtPointer       Pointer to client data (GrInfo) *
 *      cbs             XtPointer       callback struct                 *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            06/01   copy from pgfilw_sortByCb()             *
 ***********************************************************************/
{
    int   new_sort;
/*---------------------------------------------------------------------*/

    new_sort = (long) client;

    if (new_sort != _sortBy) {
        _sortBy = new_sort;
        spfw_popdown( );
        spfw_popup( _spfilFunc );
    }
    
}

/*=====================================================================*/

/* ARGSUSED */
void spfw_stimeCb ( Widget wid, XtPointer client, XtPointer cbs )
/************************************************************************
 * spfw_stimeCb                                                         *
 *                                                                      *
 * Callback function for the save literal time toggles                  *
 *                                                                      *
 * void spfw_sortByCb ( wid, client, cbs )                              *
 *                                                                      *
 * Input parameters:                                                    *
 *      wid             Widget          Widget that activated callback  *
 *      client          XtPointer       Pointer to client data (GrInfo) *
 *      cbs             XtPointer       callback struct                 *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * C. Bailey/HPC        12/05           Creation                        *
 ***********************************************************************/
{
    int   new_stime;
/*---------------------------------------------------------------------*/

    new_stime = (long) client;

    if (new_stime != _stimeBy) {
        _stimeBy = new_stime;
    }

}

/*=====================================================================*/

static void spfw_restoreSPF ( void )
/************************************************************************
 * spfw_restoreSPF                                                      *
 *                                                                      *
 * This function restores the data settings from the SPF file.          *
 *                                                                      *
 * spfw_restoreSPF ( void )                                             *
 *                                                                      *
 * Input parameters:                                                    *
 * Output parameters:                                                   *
 * Return parameters:                                                   *
 *                      NONE                                            *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            06/01   initial coding                          *
 * J. Wu/GSC            07/01   add actual functionality                *
 * J. Wu/GSC            07/01   call dataw_clearDataSel() to clear data *
 *                              selections tempaerarily                 *
 * J. Wu/GSC            07/01   move file loading to spfw_confirmCb()   *
 * J. Wu/SAIC           08/01   call nmp_rdeflts() to reset map/overlay *
 ***********************************************************************/
{
    int         lp, ier;

/*---------------------------------------------------------------------*/
       
    /*
     *  Clear all current data settings & set default map/overlay. 
     */
    nmp_rdeflts( &ier );
    for ( lp = 0; lp < MAX_LOOP; lp++ ) {
        dataw_clearDataSel( lp );        
        loop_setDataChngd( lp, TRUE );    
    }
        
    /*
     *  Switch to the first loop and load data settings from SPF file.
     */
    dataw_setLoop( 0 ); 
    dataw_loadsp( ); 

}

/*=====================================================================*/

static void spfw_preCheck ( void )
/************************************************************************
 * spfw_preCheck                                                        *
 *                                                                      *
 * This function gets the file name, checks the file permissions, and   *
 * confirms the name with the user.                                     *
 *                                                                      *
 * void spfw_preCheck( void )                                           *
 *                                                                      *
 * Input parameters:                                                    *
 * Output parameters:                                                   *
 * Return parameters:                                                   *
 *                      NONE                                            *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            06/01   initial coding                          *
 * J. Wu/GSC            07/01   change calling sequence for restoring   *
 ***********************************************************************/
{
    int         ipos, ier;
    char        *ss, fname[FILE_FULLSZ], warning[(FILE_FULLSZ + 80)];
    char        *fptr;
    Boolean     readable, writable;
    Widget      popup;
/*---------------------------------------------------------------------*/

    /*
     *  Retrieve the file name first.
     */
    if ( _spfilFunc == SAVE_SPF ) {
        ss = XmTextGetString ( _fileSel_txtW );
        strcpy ( _fileName, ss );
        XtFree(ss);
    }
    
    if ( strlen( _fileName ) <= (size_t)0 ) {
        NxmWarn_show ( _fileSelW, "No file has been specified" );
        return;    
    }
           
    /*
     *  Retrieve full file name & append .spf extension if necessary.
     */
    strcpy ( fname, _dirPath );
    strcat ( fname, _fileName );
    
    cst_srch ( 0, (int)strlen(_fileName), ".spf", _fileName, &ipos, &ier );
    if ( ier == -4 ) {
        strcat ( fname, ".spf" );
    }
    
    /*
     *  Get an file name without the initial "./" in it if it is under
     *  the local directory.
     */
    if ( strcmp ( _dirPath, LOCAL_DIR ) == 0 ) { 
        fptr = strchr ( fname, '/' );
        fptr ++;
    }
    else {
        fptr = &( fname[0] );
    }
    
    /*
     *  Check file permission before reading/writing and form confirmation.
     *  message.
     */
    spfw_checkPerms ( fname, &readable, &writable );

    popup = ( XtIsManaged (_browsePopup) ) ? _browsePopup : _fileSelW;
    
    if ( _spfilFunc == RESTORE_SPF ) {
        
        if ( readable ) {
            spfw_confirmCb( popup, 0, NULL );
        }
        else { 
            NxmWarn_show ( popup, "SPF File is not readable" );
        }
        
    }
    else {   /* SAVE_SPF */
    
        if ( writable ) {
            sprintf ( warning,
                "Are you sure you want to save the current settings to SPF file 
%s?",
                 fptr );                
            NxmConfirm_show ( popup, warning, spfw_confirmCb, 
                      NULL, NULL, &ier );
        }
        else {
            NxmWarn_show ( _fileSelW, "No permission to write SPF File" );
        }    
    }    
}

/*=====================================================================*/

static void spfw_saveSPF ( void )
/************************************************************************
 * spfw_saveSPF                                                         *
 *                                                                      *
 * This function saves the data settings into the SPF file.             *
 *                                                                      *
 * void spfw_saveSPF ( void )                                           *
 *                                                                      *
 * Input parameters:                                                    *
 * Output parameters:                                                   *
 * Return value:                                                        *
 *                      NONE                                            *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            06/01   initial coding                          *
 * J. Wu/GSC            07/01   add checks to source status & category  *
 * J. Wu/GSC            07/01   check if there are any active sources   *
 *                              & correct source string for GRD/SFF/SNF *
 * J. Wu/SAIC           08/01   number sources consectively at saving   *
 * J. Wu/SAIC           08/01   save off the roam factor                *
 * J. Wu/SAIC           08/01   save off auto-update & map settings     *
 * J. Wu/SAIC           08/01   save off map overlay selections         *
 * J. Wu/SAIC           04/02   save off data source's attributes       *
 * J. Wu/SAIC           04/02   save off map overlay's attributes       *
 * J. Wu/SAIC           05/02   save off "single time mode"             *
 * J. Wu/SAIC           07/03   save off sources' range/interval        *
 * T. Lee/SAIC          04/04   save off delta_rt                       *
 * T. Lee/SAIC          10/04   save off bin hours for certain data type*
 * C. Bailey/HPC        01/06   added save current/latest time option   *
 ***********************************************************************/
{
    int         ier, ipos, hlen, ii, jj, srcNum, domInd, catnum;
    int         noc1, noc2, kk, srcInd, roamFac, autoUpdt;
    int         ovlnum, ovltyp, lastOvlNum, sel_time; 
    char        full_name[FILE_FULLSZ], ovlsep[] = "|", ovlStr[1024];
    char        tagStr[32] = "\0", dataStr[200] = "\0", tmp[20] = "\0";
    char        lpStr[20] = "\0", cycStr[] = "[cycle_time]";
    FILE        *fptr;
    dsrc_t      *domSrc, *dataSrc;
    Boolean     lp_hasImg, ovlflg[MAX_OVL];
    nmpstr_t    map, proj, garea[2];
    nmpovlstr_t ovlnms[MAX_OVL], ovlattr[MAX_OVL]; 
       
/*---------------------------------------------------------------------*/
         
    /*
     *  If there are no active sources, return; otherwise, save them.
     */     
    if ( dataw_noActSrc() ) return;

    if ( strlen(_fileName) > (size_t)0 ) {

        strcpy ( full_name, _dirPath );
        strcat ( full_name, _fileName );
               
        /*
         * Append .spf extension if necessary.
         */
        cst_srch ( 0, (int)strlen(_fileName), ".spf", _fileName, &ipos, &ier );
        if ( ier == -4 ) {
            strcat (full_name, ".spf");
            strcat (_fileName, ".spf");
        }

        /*
         *  Create the SPF file new to wipe out any previous inf.
         */
        fptr = spf_create ( full_name, &hlen, &ier );

        if ( ier < 0 ) {
            
            NxmWarn_show ( _fileSelW, "Failure to write!" );
            return;     

        }
        
        /*
         *  Get map overlay number and names.
         */
        nmp_govlnum( &ovlnum, &ier );
        nmp_govlnms( ovlnms, &ier );
        
        /*
         *  Write the selected data sources into the SPF file.
         */
        for ( ii = 0; ii < MAX_LOOP; ii++ ) {
            
            srcNum = dataw_getNumSrcs( ii );
            srcInd = 0;
            lp_hasImg = False;
            
            if ( srcNum > 0 ) {
            
                domSrc = dataw_getDomSrc( ii );
                                
                sprintf( lpStr, "%s%d%s", "!\n! Loop ", ii+1, "\n!\n" ); 
                cfl_writ( fptr, (int)strlen(lpStr), (unsigned char*)lpStr, &ier 
);
                
                for ( jj = 0; jj < srcNum; jj++ ) {
                    
                    dataSrc = dataw_getDataSrc( ii, jj );
                                        
                    /*
                     *  If the source status is on, write it to SPF file.
                     */
                    if ( dataSrc->src_on ) {
                        
                        srcInd++;
                        
                        if ( dataSrc == domSrc ) { 
                            domInd = srcInd;                    
                        }
                        
                        if ( dataSrc->catg == CAT_IMG && 
                            ( strstr( dataSrc->path, "SAT") != NULL ||
                              strstr( dataSrc->path, "RAD") != NULL ) ) {
                            lp_hasImg = True;     
                        }
                                                
                        sprintf( tagStr, "%s%d%s%d", "loop", ii+1, 
                                                 "_source", srcInd ); 
                        catnum = dataSrc->catg;
                        ctb_dcatitos( &catnum, dataStr, &ier );
                        strcat( dataStr, "|" );
                        strcat( dataStr, dataSrc->path );

                        if ( _stimeBy ) {
                            /*
                             *  If the data category is GRID or surface 
forecast,
                             *  replace the date string with the string 
                             *  "[cycle_time]".
                             */
                            if ( catnum == CAT_GRD || catnum == CAT_SFF ||
                                 catnum == CAT_SNF ) {
                            
                                cst_nocc ( dataStr, '/', 2, 0, &noc1, &ier );
                                cst_nocc ( dataStr, '/', 3, 0, &noc2, &ier );
                            
                                for ( kk = noc1+1; kk < noc2; kk++ )
                                {
                                    tmp[ kk-noc1-1 ] = dataStr[ kk ];       
                                }
                                tmp[ noc2-noc1-1 ] = '\0';
                                cst_rpst( dataStr, tmp, cycStr, dataStr, &ier );
                            }
                        }
                        spf_write( fptr, tagStr, dataStr, &ier );

                        /*
                         *  Write out the source's timeline range & interval.
                         */                                 
                        sprintf( tagStr, "%s%d%s%d%s", "loop", ii+1,
                                                      "_source", srcInd, 
"_interval"); 
                        sprintf( dataStr, "%d", dataSrc->interval );  
                        spf_write( fptr, tagStr, dataStr, &ier );

                        sprintf( tagStr, "%s%d%s%d%s", "loop", ii+1,
                                                      "_source", srcInd, 
"_range"); 
                        sprintf( dataStr, "%d", dataSrc->range );  
                        spf_write( fptr, tagStr, dataStr, &ier );

                        /* 
                         * Write out bin hours for certain data categories.
                         */
                        if ( catnum == CAT_SFC || catnum == CAT_SFF ||
                             catnum == CAT_SND || catnum == CAT_SNF ) {
                            
                            sprintf ( tagStr, "%s%d%s%d%s", "loop", ii+1, 
                                                        "_source", srcInd, 
"_timbin" );
                            ctb_dhrsitos ( &dataSrc->ionoff, &dataSrc->bfhr, 
                                           &dataSrc->afhr, dataStr, &ier );
                            spf_write ( fptr, tagStr, dataStr, &ier );
                        }

                        /*
                         *  Write out the source's attributes.
                         */                                 
                        spfw_saveSrcAttr ( dataSrc, fptr, ii, srcInd );
                    
                    }
                
                } /* end of srcNum loop */
                
                /*
                 *  Write out dominant source index, frame number & skip factor.
                 */                                 
                sprintf( tagStr, "%s%d%s", "loop", ii+1, "_dominant" );
                sprintf( dataStr, "%d", domInd );  
                spf_write( fptr, tagStr, dataStr, &ier );

                sprintf( tagStr, "%s%d%s", "loop", ii+1, "_frames" );
                sprintf( dataStr, "%d", domSrc->num_sel );  
                spf_write( fptr, tagStr, dataStr, &ier );

                sprintf( tagStr, "%s%d%s", "loop", ii+1, "_skip" );
                sprintf( dataStr, "%d", domSrc->skip );  
                spf_write( fptr, tagStr, dataStr, &ier );
                                
                sprintf( tagStr, "%s%d%s", "loop", ii+1, "_delta_rt"); 
                sprintf( dataStr, "%d", domSrc->delta_rt );  
                spf_write( fptr, tagStr, dataStr, &ier );
                /*
                 *  Save off the roam factor.
                 */
                roamFac = dataw_getRoamVal( ii );
                
                if ( roamFac < 0 || ( !lp_hasImg && 
                                      roamFac == SIZE_OF_IMAGE ) ) {
                    roamFac = 0; 
                }
                
                sprintf( tagStr, "%s%d%s", "loop", ii+1, "_roam" );
                sprintf( dataStr, "%d", roamFac );  
                spf_write( fptr, tagStr, dataStr, &ier );
            
                /*
                 *  Save off the auto-update state.
                 */
                autoUpdt = TRUE;
                if ( !loop_getAutoUpdt( ii ) ) autoUpdt = FALSE;
                
                sprintf( tagStr, "%s%d%s", "loop", ii+1, "_auto_update" );
                sprintf( dataStr, "%d", autoUpdt );  
                spf_write( fptr, tagStr, dataStr, &ier );
                                
                /*
                 *  Save off the map settings.
                 */
                nmp_gmapattr( ii, map, proj, garea, &ier );

                if ( ier == 0 ) {
                    sprintf( tagStr, "%s%d%s", "loop", ii+1, "_map" );
                    sprintf( dataStr, "%s", map );  
                    spf_write( fptr, tagStr, dataStr, &ier );
                    
                    sprintf( tagStr, "%s%d%s", "loop", ii+1, "_proj" );
                    sprintf( dataStr, "%s", proj );  
                    spf_write( fptr, tagStr, dataStr, &ier );
                    
                    sprintf( tagStr, "%s%d%s", "loop", ii+1, "_garea" );
                    sprintf( dataStr, "%s|%s", garea[0], garea[1] );  
                    spf_write( fptr, tagStr, dataStr, &ier );
                }
                
                /*
                 *  Save off the map overlay settings.
                 */
                nmp_govlflg( ii, ovlflg, &ier );
                
                if ( ier == 0 ) {
                    
                    sprintf( tagStr, "%s%d%s", "loop", ii+1, "_map_ovl" );
                    ovlStr[0] = '\0';
                    
                    lastOvlNum = 0;
                    for ( kk = 0; kk < ovlnum; kk++ ) {                 
                        if ( ovlflg[kk] ) lastOvlNum = kk;
                    }
                    
                    for ( kk = 0; kk <= lastOvlNum; kk++ ) {
                    
                        if ( ovlflg[kk] ) {                         
                            nmp_govlattr ( kk, ii, &ovltyp, ovlattr[kk], &ier );
                            strcat( ovlStr, ovlnms[kk] );
                            strcat( ovlStr, ":" );
                            strcat( ovlStr, ovlattr[kk] );
                                strcat( ovlStr, ovlsep );
                            if ( kk != lastOvlNum ) {
                                strcat( ovlStr, "\n\t\t\t\t" );
                            }
                        }                                               
                    }
                    
                    spf_write( fptr, tagStr, ovlStr, &ier );

                } /* End of saving overlay attribute */

                /*
                 *  Save off the single time mode if the dominant source
                 *  is GRD.
                 */
                sprintf( tagStr, "%s%d%s", "loop", ii+1, "_single_time" );      
             
                strcpy( dataStr, "0" );  
                
                if ( domSrc->catg == CAT_GRD && loop_getTmMode(ii) ) {
                    
                    sel_time = 1;
                    
                    for ( kk = 0; kk < MAX_FRAME; kk++ ) {
                       if ( domSrc->frm[kk].selected ) {
                           sel_time = kk+1;
                           break;
                       }
                    }
                    
                    sprintf( dataStr, "1|%d", sel_time );                   
                }
                    
                spf_write( fptr, tagStr, dataStr, &ier );                       
        

            } /* end of loop-has-source: srcNum > 0 */  
        
        } /* end of MAX_LOOP loop */

        spf_close( fptr, &ier );

    }
    
}

/*=====================================================================*/

static void spfw_managePanes ( int popup_type )
/************************************************************************
 * spfw_managePanes                                                     *
 *                                                                      *
 * This function manages the appropiate children of the main pane       *
 * widget based on popup_type.                                          *
 *                                                                      *
 * void spfw_managePanes ( popup_type )                                 *
 *                                                                      *
 * Input parameters:                                                    *
 *      popup_type      int     decides which children to use           *
 *                                  0 - RESTORE_POPUP                   *
 *                                  1 - SAVE_POPUP                      *
 *                                                                      *
 * Output parameters:                                                   *
 *                      NONE                                            *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            06/01   copy from pgfilw_managePanes()          *
 * C. Bailey/HPC        12/05   add _stimePaneW to SAVE_POPUP           *
 ***********************************************************************/
{

    spfw_unmanagePanes ();

    switch ( popup_type ) {
        
        case RESTORE_POPUP:
            XtManageChild (_sortPaneW);
            XtManageChild (_selectPaneW);
            XtManageChild (_browseBtnPane);
            XtManageChild (_bottomPaneW);
            break;

        case SAVE_POPUP:
            XtManageChild (_sortPaneW);
            XtManageChild (_selectPaneW);
            XtManageChild (_inputPaneW);
            XtManageChild (_browseBtnPane);
            XtManageChild (_stimePaneW);
            XtManageChild (_bottomPaneW);
            break;

   }
   
}

/*=====================================================================*/

static void spfw_unmanagePanes ( void )
/************************************************************************
 * spfw_unmanagePanes                                                   *
 *                                                                      *
 * This function unmanages all the children of the main pane widget.    *
 *                                                                      *
 * void spfw_unmanagePanes ( void )                                     *
 *                                                                      *
 * Input parameters:                                                    *
 * Output parameters:                                                   *
 *                      NONE                                            *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            06/01   copy from pgfilw_unmanagePanes()        *
 * C. Bailey/HPC        12/05   added stimePaneW                        *
 ***********************************************************************/
{
    
    if ( XtIsManaged (_sortPaneW) ) {
        XtUnmanageChild (_sortPaneW);
    }

    if ( XtIsManaged (_selectPaneW) ) {
        XtUnmanageChild (_selectPaneW);
    }

    if ( XtIsManaged (_inputPaneW) ) {
        XtUnmanageChild (_inputPaneW);
    }

    if ( XtIsManaged (_browseBtnPane) ) {
        XtUnmanageChild (_browseBtnPane);
    }

    if ( XtIsManaged (_bottomPaneW) ) {
        XtUnmanageChild (_bottomPaneW);
    }

    if ( XtIsManaged (_stimePaneW) ) {
        XtUnmanageChild (_stimePaneW);
    }

} 

/*=====================================================================*/

static void spfw_setFileList ( void )
/************************************************************************
 * spfw_setFileList                                                     *
 *                                                                      *
 * This function sets up the list of files for the slected path.        *
 *                                                                      *
 * void spfw_setFileList ()                                             *
 *                                                                      *
 * Input parameters:                                                    *
 * Output parameters:                                                   *
 *                      NONE                                            *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            06/01   copy from pgfilw_setFileList()          *
 ***********************************************************************/
{
    int         ii, nf;
    char        fn_list[MAX_FILES][FILE_NAMESZ];
    XmString    xmstr;
    XmStringTable       xmfils;
/*---------------------------------------------------------------------*/

    /*
     * Wipe the list of .spf filenames       
     */
    XmListDeleteAllItems(_fileSel_listW);

    /*
     *  Get list of file names in the directory & write to the fn_list
     */
    nf = cfl_gfil (_sortBy, MAX_FILES, _dirPath, ".spf", fn_list);

    if ( nf > 0 ) {

        xmfils = (XmStringTable)XtMalloc((size_t)nf*sizeof(XmString *));

        for ( ii = 0; ii < nf; ii++ ) {
            xmfils[ii] = XmStringCreateLocalized( fn_list[ii]);
        }

        XtVaSetValues(_fileSel_listW,
                XmNitems,      xmfils,
                XmNitemCount,  nf,
                NULL);

        for ( ii = 0; ii < nf; ii++ ) {
            XmStringFree(xmfils[ii]);
        }
        XtFree((XtPointer)xmfils);

        /*
         * hi-light the selected item if applicable
         */
        xmstr = XmStringCreateLocalized (_fileName);
        XmListSelectItem (_fileSel_listW, xmstr, FALSE);
        XmListSetBottomItem (_fileSel_listW, xmstr);
        XmStringFree (xmstr);

    }
}

/*=====================================================================*/
/* ARGSUSED */
void spfw_btmCtlBtnCb ( Widget wid, int which, XtPointer call )
/************************************************************************
 * spfw_btmCtlBtnCb                                                     *
 *                                                                      *
 * Callback function for the bottom control buttons on the file         *
 * selection popup window.                                              *
 *                                                                      *
 * void spfw_btmCtlBtnCb  ( wid, which, call )                          *
 *                                                                      *
 * Input parameters:                                                    *
 *      wid             Widget          Widget that activated callback  *
 *      which           int             which button                    *
 *      call            XtPointer       not used                        *
 *                                                                      *
 * Output parameters:                                                   *
 * Return parameters:                                                   *
 *                      NONE                                            *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            06/01   initial coding                          *
 ***********************************************************************/
{
/*---------------------------------------------------------------------*/
    
    switch ( which ) {

        case 0:         /* OK */            
            
            spfw_preCheck();        
            break;

        case 1:         /* CANCEL */
            
            spfw_popdown( ); 
            break;
    
    }

}

/*=====================================================================*/

static void spfw_checkPerms ( char *cfile, Boolean *can_read, Boolean 
*can_write )
/************************************************************************
 * spfw_checkPerms                                                      *
 *                                                                      *
 * This function checks the permissions on the passed in file to see if *
 * the user has read and write permission.  If the file is not found,   *
 * can_read is FALSE, and the write permission of the directory is      *
 * checked.  If the directory is not found, can_write is FALSE. Due to  *
 * policy, the user is only allowed to write in a directory owned by    *
 * user.                                                                *
 *                                                                      *
 * void spfw_checkPerms (cfile, can_read, can_write)                    *
 *                                                                      *
 * Input parameters:                                                    *
 *      *cfile          char    filename to be checked                  *
 *                                                                      *
 * Output parameters:                                                   *
 *      *can_read       Boolean read  permission result                 *
 *      *can_write      Boolean write permission result                 *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            06/01   copy from pgfilw_checkPerms()           *
 ***********************************************************************/
{
    static Boolean      need_ids  = TRUE;
    Boolean             subdir;
    static uid_t        uid;
    static gid_t        gid;
    struct stat         fstat;
    char                cpath[LLPATH], *cptr;
    int                 cnt, ii;
/*---------------------------------------------------------------------*/

    /*
     *  Count the number of '/' found in the cfile string.  
     *  1 = just a file name, >1 = a subdirectory and file name.
     */
    cnt = 0;
    for (ii=(int)strlen(cfile); ii>=0; ii--) {
        if (cfile[ii] == '/') cnt++;
    }
    subdir = (Boolean)((cnt > 1) ? TRUE : FALSE);


    if (need_ids) {
        uid = getuid ();
        gid = getgid ();
        need_ids = FALSE;
    }

    *can_read = *can_write = FALSE;

    /*
     * If the file can be found, check the read and write permissions.
     */
    if (stat (cfile, &fstat) == 0) {

        /*
         * Check read permissions (other, then group, then user).
         */
        if (fstat.st_mode & S_IROTH || 
            (gid == fstat.st_gid && (fstat.st_mode & S_IRGRP)) ||
            (uid == fstat.st_uid && (fstat.st_mode & S_IRUSR))) 
            *can_read = TRUE;

        /*
         * Check write permission (other, then group, then user).
         */
        if (fstat.st_mode & S_IWOTH ||
                (gid == fstat.st_gid && (fstat.st_mode & S_IWGRP)) ||
                (uid == fstat.st_uid && (fstat.st_mode & S_IWUSR)))
            *can_write = TRUE;
    }
    else {

        /*
         *  If the cfile was determined to contain a subdirectory then
         *  pull file name off and test for write permission on the target 
         *  directory.
         */
        if ( subdir ) { 
            strcpy (cpath, cfile);

            /*
             *  locate the last '/' marking the end of the directory string
             *  and terminate the path there (this removes the file name).
             */
            cptr = strrchr (cpath, '/');

            if (cptr != NULL) {
                *cptr = '\0';
            }
        }
        else {  
            /*
             *  If no subdirectory, use _dirPath for the expanded path.
             */
            strcpy (cpath, _dirPath); 
        }
  

        /*
         * If the directory can be found, check the write permissions.
         */
        if (stat (cpath, &fstat) == 0) {
            /*
             * Check write permission (other, then group, then user).
             */
            if (fstat.st_mode & S_IWOTH ||
                    (gid == fstat.st_gid && (fstat.st_mode & S_IWGRP)) ||
                    (uid == fstat.st_uid && (fstat.st_mode & S_IWUSR))) {
                *can_write = TRUE;
            }
        }
    }

}

/*=====================================================================*/

static void spfw_readUsrTbl ( char *tblname, spfutbl_t *spfutbl, int *iret )
/************************************************************************
 * spfw_readUsrTbl                                                      *
 *                                                                      *
 * This routine will read SPF user table and create the data structure  *
 * to store the information.                                            *
 *                                                                      *
 * void spfw_readUsrTbl( tblname, spfutbl, iret)                        *
 *                                                                      *
 * Input parameters:                                                    *
 *      *tblname        char            table name                      *
 *                                                                      *
 * Output parameters:                                                   *
 *      *spfutbl        spfutbl_t       pointer to spf user table struct*
 *      *iret           int             0 - success                     *
 *                                                                      *
 * Return code:                                                         *
 *                      NONE                                            *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            06/01   revise from vtbl_readUsrTbl()           *
 ***********************************************************************/
{
    int         num, ier;
    char        buffer[256], title[60], path[256], cwd[256], format[256];
    char        dum1[256], dum2[256], dum3[256];
    size_t      ii, nn;
    FILE        *fp;

/*---------------------------------------------------------------------*/

    *iret = G_NORMAL; 

    strcpy ( format, "%s %s" );

    fp = cfl_tbop (tblname, "nmap", &ier);

    nn = 0;
    if (fp && ier == 0) { 
        while (!feof(fp)) {
            /*
             * read a record
             */
            cfl_trln (fp, 256, buffer, &ier);

            if  ( ier == 0 )  {

                if  ( nn == (size_t)0 )  {
                    num = sscanf ( buffer, "%s %s %s", dum1, dum2, dum3 );
                    if  ( num == 3 )  {
                        strcpy ( format, "%s %*s %s" );
                    }
                }

                nn++;
            }

        }
    }

    /*
     * allocate one additional item in case the current user
     * has to be added in
     */
    spfutbl->nitems = (int)nn;
    spfutbl->items  = (spfusr_ent_t *) malloc ((nn+1) *sizeof (spfusr_ent_t));

    if (nn > (size_t)0) {
        rewind(fp);

        ii = 0;
        while ( ii < nn ) {
            cfl_trln( fp, 256, buffer, &ier );

            if (ier == 0) {
                sscanf(buffer, format, title, path);

                spfutbl->items[ii].title = (char *) malloc (strlen (title) + 1);
                strcpy( spfutbl->items[ii].title, title );

                spfutbl->items[ii].usrpath = (char *) malloc (strlen(path) + 1);
                strcpy( spfutbl->items[ii].usrpath, path );

                ii++;
            }
        }
    }

    if (fp) fclose(fp);

    /*
     * set default user
     */
    getcwd (cwd, sizeof (cwd));

    ii = (size_t)spfutbl->nitems;
    spfutbl->items[ii].title = (char *) malloc (strlen (CWD_TITLE) + 1);
    strcpy (spfutbl->items[ii].title, CWD_TITLE);

    spfutbl->items[ii].usrpath = (char *) malloc(strlen(cwd) + 1);
    strcpy ( spfutbl->items[ii].usrpath, cwd );

    nn = (size_t)cfl_gfil (0, MAX_FILES, cwd, SPF_FILE_EXT, NULL);

    spfutbl->nitems++;

}

/*=====================================================================*/

void spfw_getFileName ( char *file_name )
/************************************************************************
 * spfw_getFileName                                                     *
 *                                                                      *
 * This function gets the file name, including the full path of the file*
 *                                                                      *
 * void spfw_getFileName ( file_name )                                  *
 *                                                                      *
 * Input parameters:                                                    *
 *      None                                                            *
 *                                                                      *
 * Output parameters:                                                   *
 *      *file_name      char    full name of the selected SPF file      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            07/01   initial coding                          *
 ***********************************************************************/
{
    int         ipos, ier;

/*---------------------------------------------------------------------*/
    
    if ( _fileName == "\0" ) {
    
        file_name[0] = '\0';
        
    }
    else {
        
        strcpy (file_name, _dirPath);
        strcat (file_name, _fileName);
        
        /*
         *  Append .spf extension if necessary.
         */
        cst_srch ( 0, (int)strlen(_fileName), ".spf", _fileName, &ipos, &ier );
        if ( ier == -4 ) {
            strcat ( file_name, ".spf" );
        }
    
    }
            
}

/*=====================================================================*/

void spfw_createConf ( Widget parent )
/************************************************************************
 * spfw_createConf                                                      *
 *                                                                      *
 * This function creates the restore confirmation popup window.         *
 *                                                                      *
 * void spfw_createConf( parent )                                       *
 *                                                                      *
 * Input parameters:                                                    *
 *      parent          Widget          parent widget                   *
 *                                                                      *
 * Output parameters:                                                   *
 *      None                                                            *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            07/01   initial coding                          *
 * J. Wu/GSC            07/01   allow horizontal scrolling              *
 * T. Piper/SAIC        11/01   freed ctl_btns                          *
 * T. Piper/SAIC        10/05   declared ii & nn long                   *
 ***********************************************************************/
{
    Arg         args[10];
    long        ii, nn;
    Cardinal    kk;
    Widget      pane, form, ctl_form;    
    WidgetList  ctl_btns;
    char        spftext[] = "\0", lblStr[] = "\0";
    char        *ctl_btnstr[] = { "OK", "Cancel" };
    
/*---------------------------------------------------------------------*/

    /*
     * create dialog shell
     */
    _restoreConfW = XmCreateFormDialog( parent, "rstconf_popup",
                                       NULL, 0);
    XtVaSetValues( _restoreConfW, 
                   XmNnoResize,        True, 
                   NULL);
    XtVaSetValues( XtParent( _restoreConfW ),
                   XmNtitle, "Restore Confirmation",
                   NULL);
    
    /*
     * create a parent pane widget
     */
    pane = XtVaCreateWidget("resConf_pane",
                            xmPanedWindowWidgetClass, _restoreConfW,
                            XmNsashWidth,             1,
                            XmNsashHeight,            1,
                            NULL);
    
    /*
     * create a scrolled text in a form to list SPF file content
     */
    form = XtVaCreateWidget("form",
                            xmFormWidgetClass,  pane,
                            NULL);

    kk = 0;
    XtSetArg(args[kk], XmNrows,                 10); kk++;
    XtSetArg(args[kk], XmNcolumns,              48); kk++;
    XtSetArg(args[kk], XmNeditable,             False); kk++;
    XtSetArg(args[kk], XmNscrollVertical,       True); kk++;
    XtSetArg(args[kk], XmNscrollHorizontal,     True); kk++;
    XtSetArg(args[kk], XmNcursorPositionVisible,        False); kk++;
    XtSetArg(args[kk], XmNeditMode,         XmMULTI_LINE_EDIT); kk++; 
    XtSetArg(args[kk], XmNvalue,                spftext); kk++; 
    
    _rstContentW = (Widget)XmCreateScrolledText( form, 
                                 "rstConf_text", args, kk );

    XtManageChild( _rstContentW );  
    XtManageChild( form );
    
    /*
     *  Create confirm label & buttons contained in a form
     */
    nn = XtNumber( ctl_btnstr );
    ctl_form  = (Widget)XtVaCreateManagedWidget ("_confCtlForm",
                xmFormWidgetClass,      pane,
                XmNfractionBase,        3*nn+1,
                NULL);

    _rstConfLblW = XtVaCreateManagedWidget(lblStr,
                            xmLabelWidgetClass, ctl_form,
                            XmNtopAttachment,   XmATTACH_FORM,
                            XmNtopOffset,       5,
                            XmNleftAttachment,  XmATTACH_FORM,
                            NULL);

    ctl_btns = (WidgetList) XtMalloc(nn * sizeof(Widget));
    
    for ( ii = 0; ii < nn; ii++) {

        ctl_btns[ii] = XtVaCreateManagedWidget(ctl_btnstr[ii],
                xmPushButtonWidgetClass, ctl_form,
                XmNtopAttachment,       XmATTACH_WIDGET,
                XmNtopWidget,           _rstConfLblW,
                XmNtopOffset,           5,
                XmNleftAttachment,      XmATTACH_POSITION,
                XmNleftPosition,        3*ii+1,
                XmNrightAttachment,     XmATTACH_POSITION,
                XmNrightPosition,       3*ii+3,
                NULL);
        
        XtAddCallback(ctl_btns[ii], XmNactivateCallback,
                spfw_rstConfCb, (XtPointer)ii);
    }
    XtFree((XtPointer)ctl_btns); 
    XtManageChild( pane );

}
/*=====================================================================*/

void spfw_popupConf ( void )
/************************************************************************
 * spfw_popupConf                                                       *
 *                                                                      *
 * This function pops up the SPF restore confirmation window            *
 *                                                                      *
 * void spfw_popupConf ( void )                                         *
 *                                                                      *
 * Input parameters:                                                    *
 * Output parameters:                                                   *
 * Return parameters:                                                   *
 *                      NONE                                            *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            07/01   initial coding                          *
 ***********************************************************************/
{
    
    XtManageChild( _restoreConfW );

}

/*=====================================================================*/

void spfw_popdownConf ( void )
/************************************************************************
 * spfw_popdownConf                                                     *
 *                                                                      *
 * This function puts the restore confirmation down.                    *
 *                                                                      *
 * void spfw_popdownConf ( )                                            *
 *                                                                      *
 * Input parameters:                                                    *
 * Output parameters:                                                   *
 * Return parameters:                                                   *
 *                      NONE                                            *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            07/01   initial coding                          *
 ***********************************************************************/
{

    if (XtIsManaged (_restoreConfW)) {
        XtUnmanageChild (_restoreConfW);
    }
   
}

/*=====================================================================*/
/* ARGSUSED */
void spfw_rstConfCb ( Widget wid, XtPointer client, XtPointer call )
/************************************************************************
 * spfw_rstConfCb                                                       *
 *                                                                      *
 * Callback function for the restore confirmation window.               *
 *                                                                      *
 * void spfw_rstConfCb (wid, client, call )                             *
 *                                                                      *
 * Input parameters:                                                    *
 *      wid             Widget          Widget that activated callback  *
 *      client          XtPointer       Pointer to client data          *
 *      call            XtPointer       callback struct                 *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            07/01   initial coding                          *
 ***********************************************************************/
{
    int         which;
/*---------------------------------------------------------------------*/

    which = (long)client;
    spfw_popdownConf ();
    
    if ( which == 0 ) { 
        spfw_popdown ();
        spfw_restoreSPF ();
    }

}

/*=====================================================================*/

void spfw_getSource ( int lp, int src, int *catn, char *srcstr, int *iret )
/************************************************************************
 * spfw_getSource                                                       *
 *                                                                      *
 * This function gets a specified source for a given loop.              *
 *                                                                      *
 * void spfw_getSource ( lp, src, catn, srcstr, iret )                  *
 *                                                                      *
 * Input parameters:                                                    *
 *    lp        int             Loop number                             *
 *    src       int             Source number                           *
 *                                                                      *
 * Output parameters:                                                   *
 *    *catn     int             Data category number                    *
 *    *srcstr   char            source string with full path            *
 *    *iret     int             Return code                             *
 *                                  0 - Normal                          *
 *                                 -1 - Source doesn't exist in SPF file*
 *                                 -2 - Source is not available         *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            07/01   initial coding                          *
 * J. Wu/GSC            07/01   validate the existence of data src      *
 * J. Wu/SAIC           08/01   Update error message                    *
 * J. Wu/SAIC           08/01   Move error report to spfw_formatConf    *
 ***********************************************************************/
{
    int         ier, catgNum, ii, noc, noc1, noc2, len, nn;
    char        tagStr[32], dataStr[200];
    char        grdStr[16], moslst[1024];
    char        catgStr[8], pathStr[256];
    char        cycTimStr[12], cycStr[] = "[cycle_time]";
                    
/*---------------------------------------------------------------------*/
        
    *iret = G_NORMAL;
        
    /*
     *  Get data string for "loopX_sourceY"
     */
    sprintf( tagStr, "%s%d%s%d", "loop", lp+1, "_source", src+1);
    spf_gtfld ( tagStr, dataStr, &ier );
    
    /*  
     *  If no data is present, quit.
     */                                             
    if ( ier != 0 )  {          
        *catn = 0;
        srcstr[0] = '\0';
        *iret = -1;     
        return;    
    }       

    /*  If data was found, parse and set data source.  For catogories 
     *  GRD/SFF/SNF, replace the "[cycle_time]" with the latest time.
     */                                             
    cst_nocc ( dataStr, '|', 1, 0, &noc, &ier ); 
    cst_ncpy ( catgStr, dataStr, noc, &ier );
    ctb_dcatstoi( catgStr, &catgNum, &ier );
                
    if ( catgNum == CAT_GRD || catgNum == CAT_SFF ||
         catgNum == CAT_SNF ) {

        cst_nocc ( dataStr, '/', 1, 0, &noc1, &ier ); 
        cst_nocc ( dataStr, '/', 2, 0, &noc2, &ier );
                            
        for ( ii = noc1+1; ii < noc2; ii++ ) { 
            grdStr[ ii-noc1-1 ] = dataStr[ ii ];            
        }
        grdStr[ noc2-noc1-1 ] = '\0';

        /* 
         *  Find the latest time string "YYMMDD/HHMM".
         */
        len = sizeof( moslst );
        gd_gcyc ( grdStr, ";", &nn, moslst, &ier, strlen(grdStr), 1, len );
        moslst[len - 1] = '\0';
        cst_rmbl ( moslst, moslst, &len, &ier);
                                    
        nn = 1;
        ier = noc1 = noc2 = 0;
        while ( ier == 0 ) {
            noc2 = noc1;
            cst_nocc ( moslst, ';', nn, 0, &noc1, &ier ); 
            nn++;
        }

        if ( noc2 == 0 ) noc2 = -1;  /* Only one time frame */

        if ( isdigit( (int)moslst[noc2+1] ) && 
             (int)strlen( moslst ) >= (noc2 + 12) ) {
             
            for ( ii = noc2 + 1; ii < noc2 + 12; ii++ ) { 
                cycTimStr[ii - noc2 - 1] = moslst [ii];
            }
            cycTimStr[11] = '\0';

            cst_rpst ( cycTimStr, "/", "_", cycTimStr, &ier );
            cst_rpst( dataStr, cycStr, cycTimStr, dataStr, &ier ); 
        }
        else {
            *iret = -2;
        }
                                    
    }

    for ( ii = noc+1; ii < (int)strlen(dataStr); ii++ ) {
        pathStr[ ii-noc-1 ] = dataStr[ ii ];
    }

    pathStr[ii-noc-1] = '\0';
        
    /*
     * Check if the source is physically valid.
     */        
    if ( !dslw_validSrc( catgNum, pathStr ) ) {    
        *iret = -2;
    }

    *catn = catgNum;
    strcpy( srcstr, pathStr );
            
}

/*=====================================================================*/

Boolean spfw_isUp ( void )
/************************************************************************
 * spfw_isUp                                                            *
 *                                                                      *
 * This function returns true if the spf window is currently managed.   *
 *                                                                      *
 * Boolean spfw_isUp( void )                                            *
 *                                                                      *
 * Input parameters:                                                    *
 * Output parameters:                                                   *
 *     none                                                             *
 *                                                                      *
 * Return:                                                              *
 *      spfw_isUp       Boolean         True if spf window is managed   *
 **                                                                     *
 * Log:                                                                 *
 * E. Safford/SAIC      11/01   initial coding                          *
 ***********************************************************************/
{
    return ( XtIsManaged(_fileSelW) );
}

/*=====================================================================*/

void spfw_formatConf ( long flen, char *spftext, char *filstr, int *iret )
/************************************************************************
 * spfw_formatConf                                                      *
 *                                                                      *
 * This function formats the content of an SPF file into a string to be *
 * displayed in the restore confirmation window.                        *
 *                                                                      *
 * void spfw_formatConf( flen, spftext, filstr, iret )                  *
 *                                                                      *
 * Input parameters:                                                    *
 *     flen             long    Length of spftext                       *
 *                                                                      *
 * Output parameters:                                                   *
 *     *spftext         char    Formated string from SPF file           *
 *     *filstr          char    Formated string containing file name    *
 *     *iret            int     Return code                             *
 *                               1 - No data sources in the SPF file    *
 *                               0  - Normal                            *
 *                                                                      *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/GSC            07/01   initial coding                          *
 * J. Wu/GSC            07/01   validate dom. src                       *
 * J. Wu/SAIC           08/01   report invalid sources                  *
 * R. Tian/SAIC         01/02   fixed bug when loading large SPF file   *
 ***********************************************************************/
{
    int         lp, src, ier, catgNum, dom, ierr;
    char        tagStr[32], dataStr[256]; 
    char        pathStr[256], spfil[FILE_NAMESZ], errStr[256];
    char        tmpStr1[10], *tmpStr2 = NULL, *lpStr = NULL; 
    char        tabStr[] = "    ", domStr[] = "     x   "; 
    Boolean     lp_hasSrc, lp_hasDom, src_exist;

/*---------------------------------------------------------------------*/

    *iret = G_NORMAL;
    src_exist = FALSE;   
    
    /*
     *  Format the "filstr" and the header for "spftext".  
     */
    if ( strcmp (_dirPath, LOCAL_DIR ) == 0 ) {
        strcpy( spfil, _fileName );
    }
    else {      
        spfw_getFileName( spfil );
    }
                
    strcpy( spftext, _fileName );
    strcat( spftext, " contents (x = dominant source):\n" );
    
    strcpy( filstr, "Are you sure you want to restore the settings ");
    strcat( filstr, "from SPF file\n");
    strcat( filstr, spfil );
    strcat( filstr, "?\n" );
    
    /*
     * Allocate the temp char array based on the actual SPF file size
     */
    if( !(tmpStr2 = XtMalloc((Cardinal)flen)) || !(lpStr = 
XtMalloc((Cardinal)flen)) ) {
        XtFree(tmpStr2); XtFree(lpStr);
        *iret = 1;
        return;    
    }
    lpStr[0] = '\0';

    /*
     *  Find data settings in the SPF file.
     */
    for ( lp = 0; lp < MAX_LOOP; lp++ ) {
        
        lp_hasSrc = FALSE;
        lp_hasDom = FALSE;
        
        sprintf( tagStr, "%s%d%s", "loop", lp+1, "_dominant" );
        spf_gtfld ( tagStr, dataStr, &ier );
        dom = atoi(dataStr);
        
        /*
         *  Validate the dominant source first.
         */
        if ( dom > 0 ) {
            
            spfw_getSource( lp, dom-1, &catgNum, pathStr, &ier );
            if ( ier == 0 ) lp_hasDom = TRUE;   

        }
        
        sprintf( tmpStr1, "\n  %s       %d\n", "Loop", lp+1 );          
        strcpy( tmpStr2, "\0" );
        
        for ( src = 0;  src < MAX_FRMSRC; src++ ) {
                    
            spfw_getSource( lp, src, &catgNum, pathStr, &ier );
                            
            if ( ier == 0 )  {
                
                if ( !lp_hasDom ) dom = src + 1;
                if ( !src_exist ) src_exist = TRUE;
                
                lp_hasSrc = TRUE;                               
                lp_hasDom = TRUE;
                                
                if ( (src + 1) == dom ) {
                    strcat( tmpStr2, domStr );
                }
                else {
                    strcat( tmpStr2, tabStr );
                }
                
                strcat( tmpStr2, pathStr );
                strcat( tmpStr2, "\n" );
                
            }       
            else {   
                if ( ier == -2 ) {  /*  Report invalid sources */
                    ierr = -8;
                    sprintf( errStr, "%s%d%s", " Loop ", lp+1, ":  ");
                    strcat( errStr, pathStr );
                    er_wmsg ( "SPF", &ierr, errStr, &ier, 3, strlen(errStr) );
                    NxmErr_update( );
                }
            }
                        
        }
        
        /*
         *  If any sources were found in a loop, format it.
         */    
        if ( lp_hasSrc ) {
            strcat( lpStr, tmpStr1 );
            strcat( lpStr, tmpStr2 );
        }                   
    
    }
    
    /*
     *  If sources exist, add to source string.
     */    
    if ( src_exist ) {  
        strcat( spftext, lpStr );               
    }
    else {
        *iret = 1;
    }
    
    /*
     * Do not forget to free memory
     */
    XtFree(tmpStr2); XtFree(lpStr);
}

/*=====================================================================*/

static void spfw_saveSrcAttr ( dsrc_t *datasrc, FILE *fptr, int lp, 
                               int srcnum )
/************************************************************************
 * spfw_saveSrcAttr                                                     *
 *                                                                      *
 * This function writes a data source's attribute settings to a file.   *
 *                                                                      *
 * static void spfw_saveSrcAttr ( datasrc, fptr, lp, srcnum )           *
 *                                                                      *
 * Input parameters:                                                    *
 *     *datasrc         dsrc_t          Pointer to a data source        *
 *     *fptr            FILE            Pointer to an SPF file          *
 *     lp               int             Loop number                     *
 *     srcnum           int             Source seq. number in a loop    *
 *                                                                      *
 * Output parameters:                                                   *
 *     none                                                             *
 *                                                                      *
 * Return:                                                              *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/SAIC           04/02   initial coding                          *
 * J. Wu/SAIC           05/02   break attr. str. to multiple lines      *
 * H. Zeng/EAI          10/02   added CAT_IMG into switch construct     *
 * R. Tian/SAIC         03/03   added CAT_SNF in dataw_getStnmName call *
 * M. Li/SAIC           04/03   Added the second colors for MISC        *
 * S. Jacobs/NCEP        6/03   Increased size of flgStr from 64 to 256 *
 * F. J. Yen/NCEP        6/04   Added test for change in types[ii].arrw.*
 *                              ityp.  Fixed test for arrw.hdsz (-9999).*
 * T. Lee/SAIC           9/04   added bin hours to calling sequences    *
 * m.gamazaychikov/SAIC 12/04   add dionoff flag to ctb_dtget CS        *
 ***********************************************************************/
{
    int         isbcat, isub, d3, d4, d5, d6, d7, d8, dionoff;
    int         ntype, nflag, ii, ier;
    int         attr_save[4] = { -1, -1, -1, -1 };
    char        parm[123], colors[123], vcoord[73], filnam[81];
    char        level[73], text[40], filter[10], alias[81], cycle[123];
    char        typestr[20], d1[256], d2[256];
    char        imtype[81], iminfo[81], imlutf[81];
    char        tagStr[32], attrStr[512], tmpStr[32], newtagStr[32];
    char        typStr[512], linStr[512], sym1Str[512], sym2Str[512];
    char        arrwStr[512], flgStr[256], fmtStr[] = "\n\t\t\t\t";
    char        fmt1[] = 
"%s|\n\t\t\t\t%s|\n\t\t\t\t%s|\n\t\t\t\t%s|\n\t\t\t\t%s|\n\t\t\t\t%s",
                fmt2[] = "%s|\n\t\t\t\t%s|\n\t\t\t\t%s|\n\t\t\t\t%s";
    NMS_types   types[20];
    NMS_flags   flags[20];

/*---------------------------------------------------------------------*/
        
    tagStr[0]  = '\0';
    attrStr[0] = '\0';
    typStr[0]  = '\0';
    linStr[0]  = '\0';
    sym1Str[0] = '\0'; 
    sym2Str[0] = '\0'; 
    arrwStr[0] = '\0';
    flgStr[0]  = '\0'; 
    
    sprintf( tagStr, "%s%d%s%d%s", "loop", lp+1, "_source", srcnum, "_attr" ); 
    
    switch ( datasrc->catg ) {

        case CAT_IMG:

            sprintf( tagStr, "%s%d%s%d%s", "loop", lp+1, "_source", srcnum, 
                             "_lut" ); 
            nim_qatt (datasrc->attridx, imtype, iminfo, imlutf, &ier); 
            spf_write( fptr, tagStr, imlutf, &ier );
  
            break;

        case CAT_SFC:
        case CAT_SFF:
        case CAT_SND:
        case CAT_SNF:

            dataw_getStnmName ( datasrc->path, 
                (Boolean)(datasrc->catg == CAT_SFF || datasrc->catg == 
CAT_SNF), 
                typestr, alias );
                                                     
            ctb_dtget ( typestr, d1, d2, &d3, &isub, &d4, &d5, &d6, 
                        &dionoff, &d7, &d8, &ier );
 
            if ( isub == SCAT_SND || isub == SCAT_SNF ) {
                nsn_qatt ( datasrc->attridx, alias, &isbcat, cycle, parm, 
                           colors, level, vcoord, filter, text, &ier);
                sprintf( attrStr, fmt1,
                         parm, colors, level, vcoord, filter, text ); 
            }
            else {
                nsf_qatt ( datasrc->attridx, alias, &isbcat, cycle, parm, 
                           colors, filter, text, &ier);
                sprintf( attrStr, fmt2, parm, colors, filter, text ); 
            }
                            
            spf_write( fptr, tagStr, attrStr, &ier );
                    
          break;

        case CAT_VGF:
        case CAT_MSC:
            nms_qatt ( datasrc->attridx, alias, &isbcat, filnam,
                       &ntype, types, &nflag, flags, &ier );
                                    
            sprintf( attrStr, "%s|%d|%d", filnam, ntype, nflag ); 

            spf_write( fptr, tagStr, attrStr, &ier );
            
            /*
             *  Save the basic NMS_types attribute.
             */      
            strcpy ( newtagStr, tagStr );
            strcat ( newtagStr, "_type" );
            
            for ( ii = 0; ii < ntype; ii++ ) {
                sprintf ( tmpStr, "%d|%d|%d|%.2f|",
                          types[ii].ionoff,
                          types[ii].icolr,
                          types[ii].icolr2,
                          types[ii].value );
                if ( ii < (ntype - 1) ) strcat ( tmpStr, fmtStr );
                strcat ( typStr, tmpStr );
            }
            
            spf_write( fptr, newtagStr, typStr, &ier );     
            
            
            /*
             *  Check if the line/symb/arrw attr. have been changed.
             */      
            for ( ii = 0; ii < ntype; ii++ ) {
                if ( types[ii].line.size >= 0.0F ||
                     types[ii].line.iwid >= 0 ) {
                    attr_save[0] = ii;
                }                   
                
                if ( types[ii].symb[0].code >= 0.0F || 
                     types[ii].symb[0].size >= 0.0F ||
                     types[ii].symb[0].iwid >= 0 ) {
                    attr_save[1] = ii;
                }           
            
                if ( types[ii].symb[1].code >= 0.0F ||
                     types[ii].symb[1].size >= 0.0F ||
                     types[ii].symb[1].iwid >= 0 ) {
                    attr_save[2] = ii;
                }           

                if ( types[ii].arrw.size >= 0.0F ||
                     types[ii].arrw.hdsz != -1.0F ||
                     types[ii].arrw.iwid >= 0    ||
                     types[ii].arrw.ityp >= 0 ) {
                    attr_save[3] = ii;
                }           
            }
                
            /*
             *  Save the line/symb/arrw attr. if necessary.
             */      
            if ( attr_save[0] >= 0  ) {

                strcpy ( newtagStr, tagStr );
                strcat ( newtagStr, "_line" );

                for ( ii = 0; ii <= attr_save[0]; ii++ ) {
                    sprintf ( tmpStr, "%.2f|%d|",
                              types[ii].line.size, 
                              types[ii].line.iwid );        
                    if ( ii < attr_save[0] ) strcat ( tmpStr, fmtStr );
                    strcat ( linStr, tmpStr );
                }

                spf_write( fptr, newtagStr, "!", &ier );            
                spf_write( fptr, newtagStr, linStr, &ier );         
            }
            
            if ( attr_save[1] >= 0 ) {

                strcpy ( newtagStr, tagStr );
                strcat ( newtagStr, "_sym1" );

                for ( ii = 0; ii <= attr_save[1]; ii++ ) {
                    sprintf ( tmpStr, "%.2f|%.2f|%d|",
                              types[ii].symb[0].code,
                              types[ii].symb[0].size, 
                              types[ii].symb[0].iwid );
                    if ( ii < attr_save[1] ) strcat ( tmpStr, fmtStr );
                    strcat ( sym1Str, tmpStr );
                }

                spf_write( fptr, newtagStr, "!", &ier );            
                spf_write( fptr, newtagStr, sym1Str, &ier );        
            }

            if ( attr_save[2] >= 0 ) {

                strcpy ( newtagStr, tagStr );
                strcat ( newtagStr, "_sym2" );

                for ( ii = 0; ii <= attr_save[2]; ii++ ) {
                    sprintf ( tmpStr, "%.2f|%.2f|%d|", 
                              types[ii].symb[1].code,
                              types[ii].symb[1].size,
                              types[ii].symb[1].iwid );
                    if ( ii < attr_save[2] ) strcat ( tmpStr, fmtStr );
                    strcat ( sym2Str, tmpStr );
                }

                spf_write( fptr, newtagStr, "!", &ier );            
                spf_write( fptr, newtagStr, sym2Str, &ier );        
            }
            
            if ( attr_save[3] >= 0 ) {

                strcpy ( newtagStr, tagStr );
                strcat ( newtagStr, "_arrw" );

                for ( ii = 0; ii <= attr_save[3]; ii++ ) {
                    sprintf ( tmpStr, "%.2f|%.2f|%d|%d|",
                              types[ii].arrw.size,
                              types[ii].arrw.hdsz,
                              types[ii].arrw.iwid,
                              types[ii].arrw.ityp );
                    if ( ii < attr_save[3] ) strcat ( tmpStr, fmtStr );
                    strcat ( arrwStr, tmpStr );
                }

                spf_write( fptr, newtagStr, "!", &ier );            
                spf_write( fptr, newtagStr, arrwStr, &ier );        
            }
            
            /*
             *  Save the flag attribute.
             */      
            strcpy ( newtagStr, tagStr );
            strcat ( newtagStr, "_flag" );

            for ( ii = 0; ii < nflag; ii++ ) {
                sprintf ( tmpStr, "%d|", flags[ii].iflg ); 
                if ( ii < ( nflag -1 ) ) strcat ( tmpStr, fmtStr );
                strcat ( flgStr, tmpStr );              
            }
            
            spf_write( fptr, newtagStr, "!", &ier );        
            spf_write( fptr, newtagStr, flgStr, &ier );     
            spf_write( fptr, newtagStr, "!", &ier );        
            spf_write( fptr, newtagStr, "!", &ier );        
                            
          break;
            
    }  /* end of switch */
    
}

/*=====================================================================*/

void spfw_getRangeIntv ( int lp, int src, int *rng, int *intv, int *drt,
                         int *iret )
/************************************************************************
 * spfw_getRangeIntv                                                    *
 *                                                                      *
 * This function gets a specified source's timeline range/interval and  *
 * delta reference time.                                                *
 *                                                                      *
 * void spfw_getRangeIntv ( lp, src, rng, intv, drt, iret )             *
 *                                                                      *
 * Input parameters:                                                    *
 *    lp        int             Loop number                             *
 *    src       int             Source seq. number in a loop            *
 *                                                                      *
 * Output parameters:                                                   *
 *    *rng      int             Source's timeline range                 *
 *    *intv     int             Source's timeline interval              *
 *    *drt      int             Source's delta reference time           *
 *    *iret     int             Return code                             *
 *                                  0 - Normal                          *
 **                                                                     *
 * Log:                                                                 *
 * J. Wu/SAIC           07/03   initial coding                          *
 * T. Lee/SAIC          04/04   added drt to calling seq.               *
 ***********************************************************************/
{
    int         range, interval, delrt, ier;
    char        tagStr[32], dataStr[200];                    
/*---------------------------------------------------------------------*/
        
    *iret = G_NORMAL;
    *rng  = -1;
    *intv = -1;
    *drt  = -1;
            
    /*
     *  Retrieve range/interval values saved in the SP file.
     */
    sprintf( tagStr, "%s%d%s%d%s", "loop", lp+1,
                                   "_source", src, "_interval" );
    spf_gtfld ( tagStr, dataStr, &ier );    
    interval = atoi ( dataStr );
    if ( interval > 0 ) *intv = interval;
    
    sprintf( tagStr, "%s%d%s%d%s", "loop", lp+1,
                                   "_source", src, "_range" );
    spf_gtfld ( tagStr, dataStr, &ier );    
    range = atoi ( dataStr );
    if ( range > 0 ) *rng = range;
                
    sprintf( tagStr, "%s%d%s", "loop", lp+1,
                                   "_delta_rt" );
    spf_gtfld ( tagStr, dataStr, &ier );    
    delrt = atoi ( dataStr );
    if ( delrt > 0 ) *drt = delrt;
}
/*=====================================================================*/

void spfw_getTmBin ( int lp, int src, int *ionoff, int *ibfr, 
                                                int *iaftr, int *iret )
/************************************************************************
 * spfw_getTmBin                                                        *
 *                                                                      *
 * This function gets a specified source's bin hours                    *
 *                                                                      *
 * void spfw_getTmBin ( lp, src, ionoff, ibfr, iaftr, iret )            *
 *                                                                      *
 * Input parameters:                                                    *
 *    lp        int             Loop number                             *
 *    src       int             Source seq. number in a loop            *
 *                                                                      *
 * Output parameters:                                                   *
 *    *ionoff   int             Binning on/off flag                     *
 *    *ibfr     int             Source's bin hrs before current time    *
 *    *iaftr    int             Source's bin hrs after current time     *
 *    *iret     int             Return code                             *
 *                                  0 - Normal                          *
 **                                                                     *
 * Log:                                                                 *
 * T. Lee/SAIC          10/04                                           *
 * T. Piper/SAIC        01/05   Added ionoff parameter                  *
 * A. Hardy/NCEP        02/05   changed check for neg. ibfr             *
 ***********************************************************************/
{
    int         ier;
    char        tagStr[32], dataStr[200];                    
/*---------------------------------------------------------------------*/
        
    *ionoff = 0;
    *iret  = G_NORMAL;
    *ibfr  = -99;
    *iaftr = -99;
            
    /*
     *  Retrieve range/interval values saved in the SP file.
     */
    sprintf( tagStr, "%s%d%s%d%s", "loop", lp+1,
                                   "_source", src, "_timbin" );
    spf_gtfld ( tagStr, dataStr, &ier );    
    ctb_dhrsstoi ( dataStr, ionoff, ibfr, iaftr, &ier );
    if ( *ibfr < 0 ) *ibfr = 0;
    if ( *iaftr < 0 ) *iaftr = 0;
}
/*=====================================================================*/