/*****************************************************************************
#   Copyright (C) 1994-2008 by David Gordon.
#   All rights reserved.                           
#                                                                           
#   This software is part of a beta-test version of the Consed/Autofinish
#   package.  It should not be redistributed or
#   used for any commercial purpose, including commercially funded
#   sequencing, without written permission from the author and the
#   University of Washington.
#   
#   This software is provided ``AS IS'' and any express or implied
#   warranties, including, but not limited to, the implied warranties of
#   merchantability and fitness for a particular purpose, are disclaimed.
#   In no event shall the authors or the University of Washington be
#   liable for any direct, indirect, incidental, special, exemplary, or
#   consequential damages (including, but not limited to, procurement of
#   substitute goods or services; loss of use, data, or profits; or
#   business interruption) however caused and on any theory of liability,
#   whether in contract, strict liability, or tort (including negligence
#   or otherwise) arising in any way out of the use of this software, even
#   if advised of the possibility of such damage.
#
#   Building Consed from source is error prone and not simple which is
#   why I provide executables.  Due to time limitations I cannot
#   provide any assistance in building Consed.  Even if you do not
#   modify the source, you may introduce errors due to using a
#   different version of the compiler, a different version of motif,
#   different versions of other libraries than I used, etc.  For this
#   reason, if you discover Consed bugs, I can only offer help with
#   those bugs if you first reproduce those bugs with an executable
#   provided by me--not an executable you have built.
# 
#   Modifying Consed is also difficult.  Although Consed is modular,
#   some modules are used by many other modules.  Thus making a change
#   in one place can have unforeseen effects on many other features.
#   It may takes months for you to notice these other side-effects
#   which may not seen connected at all.  It is not feasable for me to
#   provide help with modifying Consed sources because of the
#   potentially huge amount of time involved.
#
#*****************************************************************************/
#include    "guiFindRestrictionEnzymeSites.h"
#include    "consedParameters.h"
#include    "handleWindowManagerDelete2.h"
#include    "guiapp.h"
#include    <Xm/Form.h>
#include    <Xm/Label.h>
#include    <Xm/Xm.h>
#include    <Xm/PushB.h>
#include    <Xm/List.h>
#include    <Xm/TextF.h>
#include    "restrictionEnzyme.h"
#include    "contig.h"
#include    "consed.h"
#include    <Xm/ToggleB.h>
#include    <Xm/RowColumn.h>
#include    "popupErrorMessage.h"
#include    "guiDisplayDigest.h"
#include    "digestForOneEnzyme.h"
#include    "rwctokenizer.h"
#include    "hp_exception_kludge.h"
#include    "popupErrorMessage2.h"
#include    "please_wait.h"
#include    "bIsNumericMaybeWithWhitespace.h"
#include    "consed.h"
#include    "bGuiGetAnswerYesNo.h"
#include    "clScaffold.h"
#include    <Xm/MainW.h>
#include    <Xm/CascadeB.h>
#include    "complement_so.h"




static void cbGuiShowDocumentationForRestrictionDigest( Widget wid,
                                                        XtPointer pClientData,
                                                        XtPointer pCallData ) {

   TRY_CATCH_WRAPPER( guiDisplayDigest::showDocumentationForRestrictionDigest() );

}






static void cbWhatToDigest( Widget wid,
                            XtPointer pClientData,
                            XtPointer pCallData ) {

   guiFindRestrictionEnzymeSites* pGuiFind =
      (guiFindRestrictionEnzymeSites*) pClientData;

   TRY_CATCH_WRAPPER( 
    pGuiFind->radioButtonChanged( wid, pCallData );
                     );

}




static void cbUserPushedCancel( Widget wid,
                                XtPointer pClientData,
                                XtPointer pCallData ) {

   guiFindRestrictionEnzymeSites* pGuiFind =
      ( guiFindRestrictionEnzymeSites* ) pClientData;
   delete pGuiFind;
}


static void cbUserPushedOK( Widget wid,
                            XtPointer pClientData,
                            XtPointer pCallData ) {

   guiFindRestrictionEnzymeSites* pGuiFind =
      ( guiFindRestrictionEnzymeSites* ) pClientData;

   TRY_CATCH_WRAPPER( pGuiFind->userPushedOK() );
}



guiFindRestrictionEnzymeSites :: guiFindRestrictionEnzymeSites() :
   pGuiDisplayDigest_( NULL ) {

   aSelectedEnzymeNames_.soName_ = "aSelectedEnzymeNames_";
   aSelectedEnzymeBases_.soName_ = "aSelectedEnzymeBases_";


}





void guiFindRestrictionEnzymeSites :: getUsersAnswers() {

   pCP->makeListOfRestrictionEnzymes();

   widPopupShell_ = XtVaCreatePopupShell(
      "guiFindRestrictionSites",
      topLevelShellWidgetClass,
      GuiApp::pGetGuiApp()->widGetTopLevel(),
      XmNtitle, (char*) "Select Enzyme and Contigs",
      XmNtransient, False,
      XmNdeleteResponse, XmDO_NOTHING,
      NULL );


   handleWindowManagerDelete2( widPopupShell_, cbUserPushedCancel, this );



   // the immediate child of the application shell is a main window (so
   // there can be a menu bar)

   Widget widMainWin = XtVaCreateManagedWidget( "mainwin",
                                                xmMainWindowWidgetClass,
                                                widPopupShell_,
                                                XmNancestorSensitive, True,
                                                NULL );

   // put menu bar on the main window

   int nArgs = 0;
   Arg aArg[ 50 ];

   Widget widMenuBar = XmCreateMenuBar( widMainWin, "menubar", aArg, nArgs );
   XtManageChild( widMenuBar );

   // create help menu button

   nArgs = 0;
   Widget widHelpMenu = XmCreatePulldownMenu( widMenuBar,
                                              "Help",
                                              aArg,
                                              nArgs );

   nArgs = 0;
   XtSetArg( aArg[ nArgs ],
             XmNsubMenuId,
             widHelpMenu ); ++nArgs;

   Widget widHelpCascade = XmCreateCascadeButton( widMenuBar,
                                                  "Help",
                                                  aArg,
                                                  nArgs );

   XtManageChild( widHelpCascade );

   XtVaSetValues( widMenuBar,
                  XmNmenuHelpWidget, widHelpCascade,
                  NULL );

   // now add help menu item

   Widget widShowDocumentation =
      XtVaCreateManagedWidget( "Show Documentation for Restriction Digest",
                               xmPushButtonWidgetClass,
                               widHelpMenu,
                               NULL );

   XtAddCallback( widShowDocumentation,
                  XmNactivateCallback,
                  cbGuiShowDocumentationForRestrictionDigest,
                  this );
   



   Widget widForm = XtVaCreateManagedWidget( "form",
                                             xmFormWidgetClass,
                                             widMainWin,
                                             XmNancestorSensitive, True,
                                             NULL );

   
   // put buttons on the bottom

   widOKButton_ = XtVaCreateManagedWidget( 
       "OK",
       xmPushButtonWidgetClass,
       widForm,
       XmNbottomAttachment, XmATTACH_FORM,  
       XmNbottomOffset, 10,
       XmNleftAttachment, XmATTACH_POSITION,
       XmNleftPosition, 35,
       XmNrightAttachment, XmATTACH_POSITION,
       XmNrightPosition, 45,
       NULL );

   XtAddCallback( widOKButton_,
                  XmNactivateCallback,
                  (XtCallbackProc ) cbUserPushedOK,
                  this );

   Widget widCancelButton = XtVaCreateManagedWidget( 
       "Cancel",
       xmPushButtonWidgetClass,
       widForm,
       XmNbottomAttachment, XmATTACH_FORM,
       XmNbottomOffset, 10,
       XmNleftAttachment, XmATTACH_POSITION,
       XmNleftPosition, 55,
       XmNrightAttachment, XmATTACH_POSITION,
       XmNrightPosition, 65,
       NULL );

   XtAddCallback( widCancelButton,
                  XmNactivateCallback,
                  (XtCallbackProc ) cbUserPushedCancel,
                  this );

   // build up from the bottom

   widPathnameOfVectorSequence_ = XtVaCreateManagedWidget(
       "Vector",
       xmTextFieldWidgetClass,
       widForm,
       XmNtraversalOn, True,
       XmNbottomAttachment, XmATTACH_WIDGET,
       XmNbottomWidget, widOKButton_,
       XmNbottomOffset, 10,
       XmNleftAttachment, XmATTACH_FORM,
       XmNleftOffset, 10,
       XmNrightAttachment, XmATTACH_FORM,
       XmNrightOffset, 10,
       XmNvalue, pCP->filDefaultVectorPathnameForRestrictionFragments_.data(),
       NULL );

   Widget widPathnameOfVectorSequenceLabel = XtVaCreateManagedWidget(
       "Full Pathname of File of Vector Sequence:",
       xmLabelWidgetClass,
       widForm,
       XmNbottomAttachment, XmATTACH_WIDGET,
       XmNbottomWidget, widPathnameOfVectorSequence_,
       XmNbottomOffset, 10,
       XmNleftAttachment, XmATTACH_FORM,
       XmNleftOffset, 10,
       NULL );


   Widget widBottomSoFar = widPathnameOfVectorSequenceLabel;


   
   widPathnameOfSizesFile_ = XtVaCreateManagedWidget(
       "Sizes",
       xmTextFieldWidgetClass,
       widForm,
       XmNtraversalOn, True,
       XmNbottomAttachment, XmATTACH_WIDGET,
       XmNbottomWidget, widBottomSoFar,
       XmNbottomOffset, 10,
       XmNleftAttachment, XmATTACH_FORM,
       XmNleftOffset, 10,
       XmNrightAttachment, XmATTACH_FORM,
       XmNrightOffset, 10,
       XmNvalue, pCP->filRestrictionEnzymesActualFragmentsFile_.data(),
       NULL );

   widBottomSoFar = widPathnameOfSizesFile_;

   Widget widPathnameOfSizesFileLabel = XtVaCreateManagedWidget(
       "Full Pathname of Actual Gel Sizes File:",
       xmLabelWidgetClass,
       widForm, 
       XmNbottomAttachment, XmATTACH_WIDGET,
       XmNbottomWidget, widBottomSoFar,
       XmNbottomOffset, 10,
       XmNleftAttachment, XmATTACH_FORM,
       XmNleftOffset, 10,
       NULL );

   widBottomSoFar = widPathnameOfSizesFileLabel;





   
   widContigOrderAndOrientation_ = XtVaCreateManagedWidget(
       "Contigs",
       xmTextFieldWidgetClass,
       widForm,
       XmNtraversalOn, True,
       XmNbottomAttachment, XmATTACH_WIDGET,
       XmNbottomWidget, widBottomSoFar,
       XmNbottomOffset, 10,
       XmNleftAttachment, XmATTACH_FORM,
       XmNleftOffset, 10,
       XmNrightAttachment, XmATTACH_FORM,
       XmNrightOffset, 10,
       NULL );

   widBottomSoFar = widContigOrderAndOrientation_;


   RWCString soMessage = "Contig order and orientation:";


   XmString xms = XmStringCreateLtoR( (char*) soMessage.data(),
                                                  XmFONTLIST_DEFAULT_TAG );

   
   Widget widContigOrderAndOrientationLabel = XtVaCreateManagedWidget(
       "ContigLabel",
       xmLabelWidgetClass,
       widForm,
       XmNlabelString, xms,
       XmNalignment, XmALIGNMENT_BEGINNING,
       XmNbottomAttachment, XmATTACH_WIDGET,
       XmNbottomWidget, widBottomSoFar,
       XmNbottomOffset, 10,
       XmNleftAttachment, XmATTACH_FORM,
       XmNleftOffset, 10,
       NULL );

   widBottomSoFar = widContigOrderAndOrientationLabel;

   XmStringFree( xms );



   // now build down from the top
   

   XmString xmsCommonEnzymes = XmStringCreateLtoR(
       "Commonly Used\nRestriction\nEnzymes",
       XmFONTLIST_DEFAULT_TAG );


   Widget widLabelCommonEnzymes = 
      XtVaCreateManagedWidget( "common",
                               xmLabelWidgetClass,
                               widForm,
                               XmNlabelString, xmsCommonEnzymes,
                               XmNtopAttachment, XmATTACH_FORM,
                               XmNtopOffset, 20,
                               XmNleftAttachment, XmATTACH_FORM,
                               XmNleftOffset, 20,
                               NULL );


   XmStringFree( xmsCommonEnzymes );


   // build short list


   XmStringTable ppXtStringCommonEnzymes =
      (XmStringTable) XtMalloc( pCP->aCommonRestrictionEnzymes_.length() *
                                sizeof( XmString ) );


   int n;
   for( n = 0; n < pCP->aCommonRestrictionEnzymes_.length(); ++n ) {
      ppXtStringCommonEnzymes[ n ] = 
         XmStringCreateLocalized( pCP->aCommonRestrictionEnzymes_[ n ].data() );

   }



   XtSetArg( aArg[ nArgs ], XmNtopAttachment, XmATTACH_WIDGET ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNtopWidget, widLabelCommonEnzymes ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNtopOffset, 10 ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNbottomAttachment, XmATTACH_WIDGET ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNbottomWidget, widBottomSoFar ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNbottomOffset, 40 ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNleftWidget, widLabelCommonEnzymes ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNrightWidget, widLabelCommonEnzymes ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNvisibleItemCount, 20 ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNtraversalOn, True ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNitems, ppXtStringCommonEnzymes ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNitemCount, 
             pCP->aCommonRestrictionEnzymes_.length() ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNselectionPolicy, XmMULTIPLE_SELECT ); ++nArgs;

   widCommonEnzymesList_ = XmCreateScrolledList(
       widForm,
       "commonList",
       aArg,
       nArgs );

   XtManageChild( widCommonEnzymesList_ );


   // pre-select any items
   
   RWTValOrderedVector<RWCString> aPreselectedEnzymes;
   RWCTokenizer tokPreselected( pCP->soDefaultSelectedRestrictionEnzymes_ );

   RWCString soOnePreselectedEnzyme;
   while( !(soOnePreselectedEnzyme = tokPreselected()).isNull() ) {
      aPreselectedEnzymes.insert( soOnePreselectedEnzyme );
   }



   for( n = 0; n < pCP->aCommonRestrictionEnzymes_.length(); ++n ) {

      for( int n2 = 0; n2 < aPreselectedEnzymes.length(); ++n2 ) {
         if ( pCP->aCommonRestrictionEnzymes_[n] == aPreselectedEnzymes[n2] ) {
            // found a preselected enzyme.  Select it in the list
            int nListIndex = n + 1;
            XmListSelectPos( widCommonEnzymesList_, nListIndex, False );
            break;
         }
      }
   }






   // label for huge list


   XmString xmsHugeList = XmStringCreateLtoR(
      "Huge List of\nRestriction\nEnzymes",
      XmFONTLIST_DEFAULT_TAG );

   Widget widLabelHugeList =
      XtVaCreateManagedWidget( "huge",
                               xmLabelWidgetClass,
                               widForm,
                               XmNlabelString, xmsHugeList,
                               XmNtopAttachment, XmATTACH_FORM,
                               XmNtopOffset, 20,
                               XmNleftAttachment, XmATTACH_WIDGET,
                               XmNleftWidget, widLabelCommonEnzymes,
                               XmNleftOffset, 40,
                               NULL );



   // now build huge list

   XmStringTable ppXtStringAllEnzymes =
      (XmStringTable) XtMalloc( pCP->aRestrictionEnzymes_.length() *
                                sizeof( XmString ) );

   for( n = 0; n < pCP->aRestrictionEnzymes_.length(); ++n ) {
      ppXtStringAllEnzymes[ n ] =
         XmStringCreateLocalized( pCP->aRestrictionEnzymes_[ n ]->soName_.data() );
   }


   nArgs = 0;
   
   XtSetArg( aArg[ nArgs ], XmNtopAttachment, XmATTACH_WIDGET ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNtopWidget, widLabelCommonEnzymes ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNtopOffset, 10 ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNbottomAttachment, XmATTACH_WIDGET ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNbottomWidget, widBottomSoFar ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNbottomOffset, 40 ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNleftWidget, widLabelHugeList ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNvisibleItemCount, 20 ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNtraversalOn, True ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNitems, ppXtStringAllEnzymes ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNitemCount, 
             pCP->aRestrictionEnzymes_.length() ); ++nArgs;
   XtSetArg( aArg[ nArgs ], XmNselectionPolicy, XmMULTIPLE_SELECT ); ++nArgs;

  widHugeEnzymesList_ = XmCreateScrolledList(
       widForm,
       "hugeList",
       aArg,
       nArgs );



   XtManageChild(widHugeEnzymesList_ );


   // radio box of digesting the entire clone or a portion of 
   // the clone

   XmString xmsWhatToDigest = XmStringCreateLtoR(
      "What do you want to digest?",
      XmFONTLIST_DEFAULT_TAG );

   Widget widWhatToDigestLabel =
      XtVaCreateManagedWidget( "whatToDigestLabel",
                               xmLabelWidgetClass,
                               widForm,
                               XmNlabelString, xmsWhatToDigest,
                               XmNtopAttachment, XmATTACH_FORM,
                               XmNtopOffset, 20,
                               XmNleftAttachment, XmATTACH_WIDGET,
                               XmNleftWidget, widLabelHugeList,
                               XmNleftOffset, 40,
                               NULL );

   XmStringFree( xmsWhatToDigest );

   
   Widget widWhatToDigestRadioBox = XmCreateRadioBox(
                               widForm,
                               "whatToDigestRadio",
                               NULL,
                               0 );

   XtVaSetValues( widWhatToDigestRadioBox,
                  XmNtraversalOn, False,
                  XmNtopAttachment, XmATTACH_WIDGET,
                  XmNtopWidget, widWhatToDigestLabel,
                  XmNtopOffset, 10,
                  XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
                  XmNleftWidget, widWhatToDigestLabel,
                  XmNorientation, XmVERTICAL,
                  NULL );

   widDigestEntireClone_ = XtVaCreateManagedWidget(
                  "Entire Clone",
                  xmToggleButtonWidgetClass,
                  widWhatToDigestRadioBox,
                  XmNset, ( pCP->cFindRestrictionEnzymeSitesLastUsedWholeCloneOrPartOfCloneOrWholeContig_ == cWHOLE_CLONE ? True : False ),
                  NULL );

   XtAddCallback( widDigestEntireClone_,
                  XmNvalueChangedCallback,
                  cbWhatToDigest,
                  this );

   widDigestJustPartOfClone_ = XtVaCreateManagedWidget(
                  "Just Part of Clone",
                  xmToggleButtonWidgetClass,
                  widWhatToDigestRadioBox,
                  XmNset, ( pCP->cFindRestrictionEnzymeSitesLastUsedWholeCloneOrPartOfCloneOrWholeContig_ == cPART_OF_CLONE ? True : False ),
                  NULL );

   XtAddCallback( widDigestJustPartOfClone_,
                  XmNvalueChangedCallback,
                  cbWhatToDigest,
                  this );

   widDigestSingleContig_ = XtVaCreateManagedWidget(
                  "Entire Single Contig",
                  xmToggleButtonWidgetClass,
                  widWhatToDigestRadioBox,
                  XmNset, ( pCP->cFindRestrictionEnzymeSitesLastUsedWholeCloneOrPartOfCloneOrWholeContig_ == cWHOLE_CONTIG ? True : False ),
                  NULL );

   XtAddCallback( widDigestSingleContig_,
                  XmNvalueChangedCallback,
                  cbWhatToDigest,
                  this );

   XtManageChild( widWhatToDigestRadioBox );


   // now the box for the user to enter the portion of the clone to 
   // be digested

   XmString xmsWhatToDigest2 = XmStringCreateLtoR( 
                                                  //                     "Enter scaffold of contigs in same\nformat as the contig order\nand orientation map (below)",
                     "Enter scaffold of contigs in\nsame format as the contig\norder and orientation map (below)",
                     XmFONTLIST_DEFAULT_TAG );

   widWhatToDigestLabel2_ = XtVaCreateManagedWidget(
                     "whatToDigestLabel2",
                     xmLabelWidgetClass,
                     widForm,
                     XmNlabelString, xmsWhatToDigest2,
                     XmNtopAttachment, XmATTACH_WIDGET,
                     XmNtopWidget, widWhatToDigestRadioBox,
                     XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,   
                     XmNleftWidget, widWhatToDigestRadioBox,
                     XmNalignment, XmALIGNMENT_BEGINNING,
                     XmNsensitive, ( pCP->cFindRestrictionEnzymeSitesLastUsedWholeCloneOrPartOfCloneOrWholeContig_ == cPART_OF_CLONE ? True : False ),
                     NULL );

   XmStringFree( xmsWhatToDigest2 );
   
   widWhatToDigest_ = XtVaCreateManagedWidget(
                     "whatToDigest",
                     xmTextFieldWidgetClass,
                     widForm,
                     XmNtopAttachment, XmATTACH_WIDGET,
                     XmNtopWidget, widWhatToDigestLabel2_,
                     XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
                     XmNleftWidget, widWhatToDigestLabel2_,
                     XmNrightAttachment, XmATTACH_FORM,
                     XmNrightOffset, 10,
                     XmNsensitive, ( pCP->cFindRestrictionEnzymeSitesLastUsedWholeCloneOrPartOfCloneOrWholeContig_ == cPART_OF_CLONE ? True : False ),
                     XmNvalue,  ( pCP->cFindRestrictionEnzymeSitesLastUsedWholeCloneOrPartOfCloneOrWholeContig_ == cPART_OF_CLONE ? pCP->soFindRestrictionEnzymeSitesLastUsedUserEnteredContigMap_.data() : "" ),
                     NULL );

   XmString xmsLeftContigStartPos = XmStringCreateLtoR(
                     "Leftmost Contig\nStart Pos:",
                     XmFONTLIST_DEFAULT_TAG );

   widLeftContigStartPosLabel_ = XtVaCreateManagedWidget(
                     "LeftContigStartPosLabel",
                     xmLabelWidgetClass,
                     widForm,
                     XmNtopAttachment, XmATTACH_WIDGET,
                     XmNtopWidget, widWhatToDigest_,
                     XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
                     XmNleftWidget, widWhatToDigest_,
                     XmNlabelString, xmsLeftContigStartPos,
                     XmNsensitive, ( pCP->cFindRestrictionEnzymeSitesLastUsedWholeCloneOrPartOfCloneOrWholeContig_ == cPART_OF_CLONE ? True : False ),
                     XmNalignment, XmALIGNMENT_BEGINNING,
                     NULL );

   XmStringFree( xmsLeftContigStartPos );

   widLeftContigStartPos_ = XtVaCreateManagedWidget(
                     "LeftContigStartPos",
                     xmTextFieldWidgetClass,
                     widForm,
                     XmNtopAttachment, XmATTACH_WIDGET,
                     XmNtopWidget, widLeftContigStartPosLabel_,
                     XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
                     XmNleftWidget, widLeftContigStartPosLabel_,
                     XmNcolumns, 6,
                     XmNsensitive, ( pCP->cFindRestrictionEnzymeSitesLastUsedWholeCloneOrPartOfCloneOrWholeContig_ == cPART_OF_CLONE ? True : False ),
                     NULL );

   if ( pCP->cFindRestrictionEnzymeSitesLastUsedWholeCloneOrPartOfCloneOrWholeContig_ == cPART_OF_CLONE ) {
      RWCString soLeftContigStartPos( 
        (long) pCP->nFindRestrictionEnzymeSitesLastUsedStartUnpaddedConsPos_ );
      
      XtVaSetValues( widLeftContigStartPos_,
                     XmNvalue, soLeftContigStartPos.data(),
                     NULL );

   }

   XmString xmsRightContigEndPos = XmStringCreateLtoR(
                     "Rightmost Contig\nEnd Pos:",
                     XmFONTLIST_DEFAULT_TAG );

   widRightContigEndPosLabel_ = XtVaCreateManagedWidget(
                     "RightContigEndPosLabel",
                     xmLabelWidgetClass,
                     widForm,
                     XmNtopAttachment, XmATTACH_WIDGET,
                     XmNtopWidget, widWhatToDigest_,
                     XmNleftAttachment, XmATTACH_WIDGET,
                     XmNleftWidget, widLeftContigStartPosLabel_,
                     XmNleftOffset, 1,
                     XmNrightOffset, 5, // to fix shadow
                     XmNlabelString, xmsRightContigEndPos,
                     XmNalignment, XmALIGNMENT_BEGINNING,
                     XmNsensitive, ( pCP->cFindRestrictionEnzymeSitesLastUsedWholeCloneOrPartOfCloneOrWholeContig_ == cPART_OF_CLONE ? True : False ),
                     NULL );

   XmStringFree( xmsRightContigEndPos );

   widRightContigEndPos_ = XtVaCreateManagedWidget(
                     "RightContigEndPos",
                     xmTextFieldWidgetClass,
                     widForm,
                     XmNtopAttachment, XmATTACH_WIDGET,
                     XmNtopWidget, widRightContigEndPosLabel_,
                     XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
                     XmNleftWidget, widRightContigEndPosLabel_,
                     XmNcolumns, 6,
                     XmNsensitive, ( pCP->cFindRestrictionEnzymeSitesLastUsedWholeCloneOrPartOfCloneOrWholeContig_ == cPART_OF_CLONE ? True : False ),
                     NULL );


   if ( pCP->cFindRestrictionEnzymeSitesLastUsedWholeCloneOrPartOfCloneOrWholeContig_ == cPART_OF_CLONE ) {

      RWCString soRightContigEndPos( (long) pCP->nFindRestrictionEnzymeSitesLastUsedEndUnpaddedConsPos_ );

      XtVaSetValues( widRightContigEndPos_,
                     XmNvalue, soRightContigEndPos.data(),
                     NULL );

   }

   // option menu for selecting which single contig 

   Widget widSingleEntireContigForm = 
      XtVaCreateManagedWidget(
         "single_entire_contig_form",
         xmFormWidgetClass,
         widForm,
         XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
         XmNleftWidget, widWhatToDigestRadioBox,
         XmNtopAttachment, XmATTACH_WIDGET,
         XmNtopWidget, widLeftContigStartPos_,
         XmNrightAttachment, XmATTACH_FORM,
         NULL );

   widSingleEntireContigLabel_ =
      XtVaCreateManagedWidget(
         "Single entire contig:",
         xmLabelWidgetClass,
         widSingleEntireContigForm,
         XmNleftAttachment, XmATTACH_FORM,
         XmNtopAttachment, XmATTACH_FORM,
         XmNbottomAttachment, XmATTACH_FORM,
         NULL );

   widSingleEntireContig_ = 
      XtVaCreateManagedWidget(
         "single_entire_contig",
         xmTextFieldWidgetClass,
         widSingleEntireContigForm,
         XmNleftAttachment, XmATTACH_WIDGET,
         XmNleftWidget, widSingleEntireContigLabel_,
         XmNtopAttachment, XmATTACH_FORM,
         XmNbottomAttachment, XmATTACH_FORM,
         XmNcolumns, 10,
         XmNvalue, ( pCP->cFindRestrictionEnzymeSitesLastUsedWholeCloneOrPartOfCloneOrWholeContig_ == cWHOLE_CONTIG ? pCP->soFindRestrictionEnzymeSitesLastUsedContigAbbreviatedName_.data() : "" ),

         NULL );



   if ( pCP->cFindRestrictionEnzymeSitesLastUsedWholeCloneOrPartOfCloneOrWholeContig_ != cWHOLE_CONTIG ) {

      XtVaSetValues( widSingleEntireContigLabel_,
                  XmNsensitive, False,
                  NULL );

      XtVaSetValues( widSingleEntireContig_,
                  XmNsensitive, False,
                  NULL );
   }


   XtPopup( widPopupShell_, XtGrabNone );
   
   // clean up memory

   for( n = 0; n < pCP->aCommonRestrictionEnzymes_.length(); ++n ) {
      XmStringFree( ppXtStringCommonEnzymes[ n ] );
   }

   XtFree( (char*) ppXtStringCommonEnzymes );


   for( n = 0; n < pCP->aRestrictionEnzymes_.length(); ++n ) {
      XmStringFree( ppXtStringAllEnzymes[ n ] );
   }

   XtFree( (char*) ppXtStringAllEnzymes );

   fillInContigBox();


}



guiFindRestrictionEnzymeSites :: ~guiFindRestrictionEnzymeSites() {

   XtPopdown( widPopupShell_ );
   XtDestroyWidget( widPopupShell_ );
}
                                                           


void guiFindRestrictionEnzymeSites :: fillInContigBox() {

   // fill in order and orientation of contig


   PleaseWait* pPleaseWait = new PleaseWait( widPopupShell_ );
   RWCString soDiagram = ConsEd::pGetAssembly()->soGetContigMap();
   delete pPleaseWait;

   cerr << "contig map: " << soDiagram << endl;

   XtVaSetValues( widContigOrderAndOrientation_,
                 XmNvalue,
                 soDiagram.data(),
                 NULL );
}




bool guiFindRestrictionEnzymeSites :: bGetUsersChoices() {
        


   int* pPositionListCommon;
   int nNumberOfSelectedEnzymesCommon;
   if ( !XmListGetSelectedPos( widCommonEnzymesList_, &pPositionListCommon,
                               &nNumberOfSelectedEnzymesCommon ) ) {
      nNumberOfSelectedEnzymesCommon = 0;
   }

   int* pPositionListHuge;
   int nNumberOfSelectedEnzymesHuge;
   if ( !XmListGetSelectedPos( widHugeEnzymesList_, &pPositionListHuge,
                               &nNumberOfSelectedEnzymesHuge ) ) {
      nNumberOfSelectedEnzymesHuge = 0;
   }

   int nNumberOfSelectedEnzymes = nNumberOfSelectedEnzymesCommon +
      nNumberOfSelectedEnzymesHuge;

   if ( nNumberOfSelectedEnzymes == 0 ) {
      popupErrorMessage( "You must select at least 1 enzyme" );
      return( false );
   }

   aSelectedEnzymeNames_.clear();
   aSelectedEnzymeBases_.clear();



   aSelectedEnzymeNames_.resize( 
      (size_t) nNumberOfSelectedEnzymes );

   aSelectedEnzymeBases_.resize(
      (size_t) nNumberOfSelectedEnzymes ); 

   int nSelected;
   for( nSelected = 0; nSelected < nNumberOfSelectedEnzymesCommon; 
        ++nSelected ) {

      int nPositionInDisplayedList = pPositionListCommon[ nSelected ];
      RWCString soSelectedEnzymeName = 
         pCP->aCommonRestrictionEnzymes_[ nPositionInDisplayedList - 1 ];

      // find the bases in the huge list

      restrictionEnzyme res;
      res.soName_ = soSelectedEnzymeName;
      int nIndex = 
         pCP->aRestrictionEnzymes_.nFindIndexOfMatchOrSuccessor( &res );

      if ( nIndex != RW_NPOS && 
           pCP->aRestrictionEnzymes_[ nIndex ]->soName_ == soSelectedEnzymeName ) {
         
         RWCString soSelectedEnzymeBases = 
            pCP->aRestrictionEnzymes_[ nIndex ]->soBases_;

         aSelectedEnzymeNames_.insert( soSelectedEnzymeName );
         aSelectedEnzymeBases_.insert( soSelectedEnzymeBases );
      }
      else {
         popupErrorMessage( "something wrong with common enzyme %s",
                            soSelectedEnzymeName.data() );
         return( false );
      }
   }

   for( nSelected = 0; nSelected < nNumberOfSelectedEnzymesHuge; 
        ++nSelected ) {

      int nPositionInDisplayedList = pPositionListHuge[ nSelected ];
      RWCString soSelectedEnzymeName =
         pCP->aRestrictionEnzymes_[ nPositionInDisplayedList - 1 ]->soName_;
      RWCString soSelectedEnzymeBases =
         pCP->aRestrictionEnzymes_[ nPositionInDisplayedList - 1 ]->soBases_;
      aSelectedEnzymeNames_.insert( soSelectedEnzymeName );
      aSelectedEnzymeBases_.insert( soSelectedEnzymeBases );
   }


   assert( aSelectedEnzymeNames_.length() == aSelectedEnzymeBases_.length() );


   // clean up memory

   XtFree( (char*) pPositionListCommon );
   XtFree( (char*) pPositionListHuge );


   if ( XmToggleButtonGetState( widDigestJustPartOfClone_ ) == True )
      cWholeCloneOrPartOfCloneOrWholeContig_ = cPART_OF_CLONE;
   else if ( XmToggleButtonGetState( widDigestEntireClone_ ) == True )
      cWholeCloneOrPartOfCloneOrWholeContig_ = cWHOLE_CLONE;
   else if ( XmToggleButtonGetState( widDigestSingleContig_ ) == True )
      cWholeCloneOrPartOfCloneOrWholeContig_ = cWHOLE_CONTIG;
   else
      assert( false );


   if ( cWholeCloneOrPartOfCloneOrWholeContig_ == cPART_OF_CLONE ) {
      char* szValue = XmTextFieldGetString( widWhatToDigest_ );
      soUserEnteredContigMap_ = szValue;
      XtFree( szValue );

      // let's do some elementary syntax checking first

      soUserEnteredContigMap_.stripAllWhitespaceIncludingInternal();

      RWCString soUsage = "To do a digest of less than the entire assembly, you must enter the contigs in the order that you want them connected to be digested, as in 3-5c-2 where 3 means Contig3 and 5c means Contig5 is complemented and 2 means Contig2, connected in this order";

      if ( soUserEnteredContigMap_.isNull() ) {
         popupErrorMessage2( widPopupShell_, "%s", soUsage.data() );
         return( false );
      }
      
      // now check that all the contigs exist

      RWCTokenizer tokContig( soUserEnteredContigMap_ );

      Contig* pFirstContig = NULL;
      Contig* pLastContig = NULL;

      RWCString soContigAbb;
      while( !( soContigAbb = tokContig( '-' )).isNull() ) {
         if ( soContigAbb.cGetLastChar() == 'c' ) 
            soContigAbb.remove( soContigAbb.length() - 1 );

         // now let's see if what is left matches the abbreviated contig
         // name of some contig.  This is probably a job for the Assembly
         // object

         Contig* pContig = 
            ConsEd::pGetAssembly()->pGetContigByAbbreviatedName( soContigAbb );
         
         if ( !pContig ) {
            popupErrorMessage2( widPopupShell_, 
                             "cannot find contig %s in the assembly. %s",
                             soContigAbb.data(),
                             soUsage.data() );
            return( false );
         }

         if ( !pFirstContig )
            pFirstContig = pContig;

         pLastContig = pContig;
      }

      // check that the start and end positions are valid

      szValue = XmTextFieldGetString( widLeftContigStartPos_ );
      RWCString soLeftmostContigStartPos = szValue;
      XtFree( szValue );

      szValue = XmTextFieldGetString( widRightContigEndPos_ );
      RWCString soRightmostContigEndPos = szValue;
      XtFree( szValue );

      if ( !bIsNumericMaybeWithWhitespace( soLeftmostContigStartPos,
                                           nStartUnpaddedConsPos_ ) ) {
         popupErrorMessage2( widPopupShell_,
                             "leftmost contig start pos must be numeric" );
         return( false );
      }

      if ( !bIsNumericMaybeWithWhitespace( soRightmostContigEndPos,
                                           nEndUnpaddedConsPos_ ) ) {
         
         popupErrorMessage2( widPopupShell_,
                             "rightmost contig end pos must be numeric" );
         return( false );
      }

      if ( nStartUnpaddedConsPos_ < pFirstContig->nGetUnpaddedStartIndex() ||
           pFirstContig->nGetUnpaddedEndIndex() < nStartUnpaddedConsPos_ ) {
         popupErrorMessage2( widPopupShell_,
                             "leftmost contig start pos must be between %d and %d, the range of positions of contig %s",
                             pFirstContig->nGetUnpaddedStartIndex(),
                             pFirstContig->nGetUnpaddedEndIndex(),
                             pFirstContig->soGetName().data() );
         return( false );
      }

      if ( nEndUnpaddedConsPos_ < pLastContig->nGetUnpaddedStartIndex() ||
           pLastContig->nGetUnpaddedEndIndex() < nEndUnpaddedConsPos_ ) {
         popupErrorMessage2( widPopupShell_,
                             "rightmost contig end pos must be between %d and %d, the range of positions of contig %s", 
                             pLastContig->nGetUnpaddedStartIndex(),
                             pLastContig->nGetUnpaddedEndIndex(),
                             pLastContig->soGetName().data() );

         return( false );
      }

      RWTPtrOrderedVector<clScaffold> aScaffoldArray;

      RWCString soErrorMessage;
      ConsEd::pGetAssembly()->createScaffoldsFromUserContigMap( 
                                      soUserEnteredContigMap_,
                                      nStartUnpaddedConsPos_,
                                      nEndUnpaddedConsPos_,
                                      &aScaffoldArray,
                                      soErrorMessage );

      // we will create this all over again in doSearch--we just
      // created it to see what the problems were

      aScaffoldArray.clearAndDestroy();

      if ( !soErrorMessage.isNull() ) {
         RWCString soQuestion = soErrorMessage +
            " Do you want to proceed (Yes) or not proceed (No) and modify your contig map?";

         if ( !bGuiGetAnswerYesNo( soQuestion ) )
            return( false );
      }
   } //  if ( cWholeCloneOrPartOfCloneOrWholeContig_ == cPART_OF_CLONE ) {
   else if ( cWholeCloneOrPartOfCloneOrWholeContig_ == cWHOLE_CONTIG ) {

      char* szContigName = XmTextFieldGetString( widSingleEntireContig_ );
      RWCString soContigName( szContigName );
      XtFree( szContigName );
      
      Assembly* pAssembly = ConsEd::pGetAssembly();
      Contig* pContig = pAssembly->pGetContigByName( soContigName );
      
      if ( pContig == NULL ) {
         RWCString soTryAnother = "Contig" + soContigName;
         pContig = pAssembly->pGetContigByName( soTryAnother );
         if ( pContig == NULL ) {
            popupErrorMessage2( widPopupShell_,
                                "could not find contig %s",
                                soContigName.data() );
            return( false );
         }
      }

      soUserEnteredContigMap_ = pContig->soGetAbbreviatedName();

      nStartUnpaddedConsPos_ = pContig->nGetUnpaddedStartIndex();
      nEndUnpaddedConsPos_ = pContig->nGetUnpaddedEndIndex();


      // we will create this all over again in doSearch--we just
      // created it to see what the problems were

      RWTPtrOrderedVector<clScaffold> aScaffoldArray;

      RWCString soErrorMessage;
      ConsEd::pGetAssembly()->createScaffoldsFromUserContigMap( 
                                      soUserEnteredContigMap_,
                                      nStartUnpaddedConsPos_,
                                      nEndUnpaddedConsPos_,
                                      &aScaffoldArray,
                                      soErrorMessage );

      aScaffoldArray.clearAndDestroy();

      if ( !soErrorMessage.isNull() ) {
         RWCString soQuestion = soErrorMessage +
            " Do you want to proceed (Yes) or not proceed (No) and modify your contig map?";

         if ( !bGuiGetAnswerYesNo( soQuestion ) )
            return( false );
      }

   }


   // save these answers for next time the user wants to bring up
   // a digest:

   pCP->cFindRestrictionEnzymeSitesLastUsedWholeCloneOrPartOfCloneOrWholeContig_ = cWholeCloneOrPartOfCloneOrWholeContig_;


   if ( cWholeCloneOrPartOfCloneOrWholeContig_ == cPART_OF_CLONE ) {
      pCP->soFindRestrictionEnzymeSitesLastUsedUserEnteredContigMap_ =
         soUserEnteredContigMap_;

      pCP->nFindRestrictionEnzymeSitesLastUsedStartUnpaddedConsPos_ =
         nStartUnpaddedConsPos_;

      pCP->nFindRestrictionEnzymeSitesLastUsedEndUnpaddedConsPos_ =
         nEndUnpaddedConsPos_;

   }
   else if ( cWholeCloneOrPartOfCloneOrWholeContig_ == cWHOLE_CONTIG ) {
      pCP->soFindRestrictionEnzymeSitesLastUsedContigAbbreviatedName_ =
         soUserEnteredContigMap_; // this actually is the abbreviated name

   }



   return( true );
}



void guiFindRestrictionEnzymeSites :: userPushedOK() {


   if ( pGuiDisplayDigest_ ) 
      delete pGuiDisplayDigest_;

   pGuiDisplayDigest_ = new guiDisplayDigest();

   if (!bGetUsersChoices() )
      return;

   try {
      readVectorSequence();
   }
   catch( InputDataError eb) {
      popupErrorMessage2( widPopupShell_,
                          eb.szGetDesc());
      
      return;
   }


   createListOfDigestForOneEnzyme();

   try {
      readActualGelSizesFile();
   }
   catch( InputDataError eb ) {
      popupErrorMessage2( widPopupShell_,
                          eb.szGetDesc() );
      return;
   }

   // point of no return

   bool bUseUserEnteredContigMap;
   if ( cWholeCloneOrPartOfCloneOrWholeContig_ == cPART_OF_CLONE ||
        cWholeCloneOrPartOfCloneOrWholeContig_ == cWHOLE_CONTIG )
      bUseUserEnteredContigMap = true;
   else
      bUseUserEnteredContigMap = false;


   pGuiDisplayDigest_->createWindow(
                                    aSelectedEnzymeNames_,
                                    aSelectedEnzymeBases_,
                                    bUseUserEnteredContigMap,
                                    soUserEnteredContigMap_,
                                    nStartUnpaddedConsPos_,
                                    nEndUnpaddedConsPos_ 
                                    );

   pGuiDisplayDigest_->doSearch( );
   
   delete this;
}




void guiFindRestrictionEnzymeSites :: readVectorSequence() {


   pGuiDisplayDigest_->soVectorSequence_ = "";
   FileName filVectorPathname;

   char* szValue = XmTextFieldGetString( widPathnameOfVectorSequence_ );

   filVectorPathname = szValue;

   XtFree( szValue );

   if ( filVectorPathname.isNull() ) {
      RWCString soError = "you must specify a vector sequence file";
      THROW_ERROR( soError );
   }
   

   FILE* pVectorFile =
      fopen( filVectorPathname.data(), "r" );

   if ( ! pVectorFile ) {
      if ( errno == 2 ) {
         RWCString soError = "there is no file " +
            filVectorPathname;

         THROW_ERROR( soError );
      }
      else {
         RWCString soError = "could not open file " +
            filVectorPathname + "\nsince error = " + 
            RWCString( (long) errno ) + " which means " +
            strerror( errno );

         THROW_ERROR( soError );
      }
   }

   // if we could open the file, save its name in case the user
   // used some file other than the default and will want to use
   // it again

   pCP->filDefaultVectorPathnameForRestrictionFragments_ = filVectorPathname;

   const int SZLINE_SIZE = 2000;

   RWCString soLine( (size_t) SZLINE_SIZE );


   // first line must be of the form:
   // >name of sequence
   // We will just throw that away.

   if ( fgets( soLine.data(), SZLINE_SIZE, pVectorFile ) == NULL ) {
      RWCString soError = "file " + filVectorPathname + " is empty";
      THROW_ERROR( soError );
   }


   if ( soLine.data()[0] != '>' ) {
      RWCString soError = "vector file " + filVectorPathname +
         " must be in fasta format which means the first line must be of the form " +
         ">(name of vector\nand subsequent lines must just contain acgt";
      
      THROW_ERROR( soError );
   }


   while( fgets( soLine.data(), SZLINE_SIZE, pVectorFile ) != NULL ) {
      soLine.nCurrentLength_ = strlen( soLine.data() );

      // chop off the trailing newline

      soLine.stripAllWhitespaceIncludingInternal();

      soLine.toLower();

      if ( strcspn( soLine.data(), "acgt" ) != 0 ) {
         RWCString soError;
         soError = "Vector data in " + filVectorPathname +
            " must just be acgt's, but instead contains " +
            soLine;
         if ( soLine.data()[0] == '>' ) {
            soError += "\nCould there be more than one vector in this file?  There shouldn't be.";

            THROW_ERROR( soError );
         }
      }

      pGuiDisplayDigest_->soVectorSequence_ += soLine;
   }

   fclose( pVectorFile );

   pGuiDisplayDigest_->soComplementedVectorSequence_ =
      soComplementSO( pGuiDisplayDigest_->soVectorSequence_ );

}


void guiFindRestrictionEnzymeSites :: createListOfDigestForOneEnzyme() {

   for( int nEnzyme = 0; nEnzyme < aSelectedEnzymeBases_.length(); 
        ++nEnzyme ) {

      digestForOneEnzyme* pDigest = new digestForOneEnzyme();
      pGuiDisplayDigest_->aDigests_.insert( pDigest );
      pDigest->soEnzymeName_ = aSelectedEnzymeNames_[ nEnzyme ];

      pDigest->soEnzymeBases_ = aSelectedEnzymeBases_[ nEnzyme ];
      pDigest->pGuiDisplayDigest_ = pGuiDisplayDigest_;

   }
}



void guiFindRestrictionEnzymeSites :: readActualGelSizesFile() {

   char* szValue = XmTextFieldGetString( widPathnameOfSizesFile_ );

   FileName filActualGelSizesFilePathname( szValue );

   XtFree( szValue );

   if ( filActualGelSizesFilePathname.isNull() )
        return;

   FILE* pSizesFile = fopen( filActualGelSizesFilePathname.data(), "r" );

   if ( !pSizesFile ) {
      if ( errno == 2 ) {
         RWCString soError = "there is no file " +
            filActualGelSizesFilePathname;

         THROW_ERROR( soError );
      }
      else {
         RWCString soError = "could not open file " +
            filActualGelSizesFilePathname + "\nsince error = " +
            RWCString( (long) errno ) + " which means " +
            strerror( errno );
         
         THROW_ERROR( soError );
      }
   }

   // if the file could be opened, save it in case the user wants to use
   // the same file again

   pCP->filRestrictionEnzymesActualFragmentsFile_ =
      filActualGelSizesFilePathname;


   const int SZLINE_SIZE = 2000;
   
   RWCString soLine( (size_t) SZLINE_SIZE );

   // we will only get the fragments for the particular enzymes we are
   // interested in.  Those are in aSelectedEnzymeNames_.  Some of
   // these may have aliases, however, so we should probably create a
   // list of those as well.  Should we be concerned that the same
   // enzyme might be more than once in the file?  


   RWTValOrderedVector<RWCString> aTempSelectedEnzymeNames = 
      aSelectedEnzymeNames_;


   // make lower case

   for( int nEnzyme = 0; nEnzyme < aTempSelectedEnzymeNames.length(); 
        ++nEnzyme ) {
      aTempSelectedEnzymeNames[ nEnzyme ].toLower();
   }
   

   while( fgets( soLine.data(), SZLINE_SIZE, pSizesFile ) != NULL ) {
      soLine.nCurrentLength_ = strlen( soLine.data() );
      if ( soLine.length() > 0 && soLine[0] == '>' ) {
         // found a header.  Is it an enzyme we want?
         
         // get rid of > at beginning
         soLine = soLine.soGetRestOfString( 1 );

         RWCTokenizer tok( soLine );

         // there might be other data on the enzyme line, such as:
         // >EcoRI b48N4 44 532
         
         RWCString soEnzyme = tok();
         RWCString soEnzymeLowerCase = soEnzyme;
         soEnzymeLowerCase.toLower();

         if ( aTempSelectedEnzymeNames.index( soEnzymeLowerCase ) == RW_NPOS )
            continue;

         cerr << "found " << soEnzyme << " in aTempSelectedEnzymeNames " <<
            endl;


         aTempSelectedEnzymeNames.removeAt( 
              aTempSelectedEnzymeNames.index( soEnzymeLowerCase ) );

         // found an enzyme we want.  Find the corresponding 
         // digestForOneEnzyme in aDigests_

         digestForOneEnzyme* pDigestInFile = NULL;
         for( int nDigest = 0; nDigest < pGuiDisplayDigest_->aDigests_.length(); 
              ++nDigest ) {
            digestForOneEnzyme* pDigest = 
               pGuiDisplayDigest_->aDigests_[ nDigest ];

            if ( pDigest->soEnzymeName_.returnToLower() == 
                 soEnzymeLowerCase ) {
               pDigestInFile = pDigest;
               break;
            }
         }

         if ( !pDigestInFile ) {
            RWCString soError = 
               "program inconsistency for enzyme " + 
               soEnzyme + " in file " +  filActualGelSizesFilePathname;
            
            THROW_ERROR( soError );
         }

         // now start reading the lines for the fragment sizes until
         // we get to the -1 delimiter

         pDigestInFile->aActualRestrictionFragments_.clearAndDestroy();

         while( fgets( soLine.data(), SZLINE_SIZE, pSizesFile ) != NULL ) {
            soLine.nCurrentLength_ = strlen( soLine.data() );

            soLine = soLine.stripWhitespace( RWCString::BOTH );
            if ( soLine == "-1" )
               break;

            int nFragmentSize;
            if ( !bIsNumericMaybeWithWhitespace( soLine, nFragmentSize ) ) {
               RWCString soError = soLine + 
                  " is not numeric but should be the fragment size in file " +
                  filActualGelSizesFilePathname;
               THROW_ERROR( soError );
            }

            restrictionFragment* pActualFrag = new restrictionFragment(
               restrictionFragment::ACTUAL_FRAGMENT );

            pActualFrag->nSize_ = nFragmentSize;

            pActualFrag->fPositionOnGel_ = 
               ConsEd::fGetPositionOnGelFromRestrictionFragmentSize( 
                   nFragmentSize );

            pDigestInFile->aActualRestrictionFragments_.insert( pActualFrag );
         }
      } //  if ( soLine.length() > 0 && soLine[0] == '>' ) {
   } // while( fgets( soLine.data(), SZLINE_SIZE, pSizesFile ) != NULL ) {


   fclose( pSizesFile );

   if ( aTempSelectedEnzymeNames.length() != 0 ) {
      RWCString soError = "problem: the actual fragment sizes file " +
         filActualGelSizesFilePathname + 
         " did not contain data for the following enzymes: ";

      for( int n = 0; n < aTempSelectedEnzymeNames.length(); ++n ) {
         soError += aTempSelectedEnzymeNames[n];
         soError += " ";
      }

      THROW_ERROR( soError );
   }


   for( int nDigest = 0; nDigest < pGuiDisplayDigest_->aDigests_.length(); 
        ++nDigest ) {
      digestForOneEnzyme* pDigest = pGuiDisplayDigest_->aDigests_[ nDigest ];

      pDigest->aActualRestrictionFragments_.sortFragmentsBySize();
   }


}



void guiFindRestrictionEnzymeSites :: radioButtonChanged( 
                                            Widget wid,
                                            XtPointer pCallData ) {


   if ( wid == widDigestJustPartOfClone_ ) {

      Boolean bSensitiveFlag =
         XmToggleButtonGetState( widDigestJustPartOfClone_ );

      XtVaSetValues( widWhatToDigestLabel2_,
                  XmNsensitive, bSensitiveFlag,
                  NULL );

      XtVaSetValues( widWhatToDigest_,
                  XmNsensitive, bSensitiveFlag,
                  NULL );

      XtVaSetValues( widLeftContigStartPosLabel_,
                  XmNsensitive, bSensitiveFlag,
                  NULL );

      XtVaSetValues( widLeftContigStartPos_,
                  XmNsensitive, bSensitiveFlag,
                  NULL );

      XtVaSetValues( widRightContigEndPosLabel_,
                  XmNsensitive, bSensitiveFlag,
                  NULL );

      XtVaSetValues( widRightContigEndPos_,
                  XmNsensitive, bSensitiveFlag,
                  NULL );

   }
   else if ( wid == widDigestSingleContig_ ) {

      Boolean bSensitiveFlag =
         XmToggleButtonGetState( widDigestSingleContig_ );


      XtVaSetValues( widSingleEntireContigLabel_,
                      XmNsensitive, bSensitiveFlag,
                      NULL );

      XtVaSetValues( widSingleEntireContig_,
                      XmNsensitive, bSensitiveFlag,
                      NULL );
   }
}