/* Menu routines for fitting maps and bones
21may99:  Tried to run extension as workfunc that can be interupted
           However, did not work because once calls extend it does
           not return until finished, thus cannot quit.
         Need to modify extendfit so that it return freqencty before
           it is finished - and allow it to be interrupted

  When running torsional dynamics - called as a "work" routine
 see motifman/ch21 for details
     This procedure is adapted from working.c sample program.
       It calls a pushbutton that is never used - I am sure
        this can be avoid, but do not know how
Define  1=ca,2=c,3=o;4=n,5=cb; 6=cb2 in geo.pos[i]...
*/

#include "drawwindow.h"  // also calls global.h
#include "screen.h"
#include "fit.h"
#include "menu.h"
//#include "core.h"
#include "bone.h"
#include "trace.h"
#include "tordyn.h"
#include "peptide.h"
#include "extendfit.h"
#include "pdbtolev.h"
#include "assignseq.h"
#include "math.h"
#include "fittopdb.h"
#include "rankside.h"
#include "checkfit.h"
#include "editbones.h"
#include "combine.h"

extern struct screenvalue  sc;
extern struct griddata map[NMAPS]; // all the map (denfile),contour data associated with map
extern struct bonedata bone[NMAPS];
extern struct geometry geo;
extern struct tordyn tordata;
extern struct tordyn tordata2;
extern struct pepfit fit[NFIT]; // defined in peptide.h, see trace.c++ for definitin
extern struct pepset fitset;
extern struct maiddatafile maidfile;
extern int fitnum[NFIT];// see trace.c++ for definition
extern struct rotomer rot[30];// rotomer data for each amino acid
extern float rotpos[NROT][NATOMS][3];// position of atoms in rotomer
extern int rottype;  // Type of rotomer to draw
extern int verbose; // if = 1,print some stuff;  = 2 print a lot of stuff
extern Widget toplevel;

Widget  fitmenu,buildmenu; // Global since needed in fit_cb
Widget button;

extern  struct st ss;  // Define before in menu.c++
float torconstorig;
float rfororig;
float origmaxside;

static XtWorkProcId  work_id;


/* done () -- user pressed "Stop" or "Done" in WorkingDialog. */
void dyndone(Widget dialog,XtPointer  client_data,XtPointer  call_data)
{
tordata.torconst=torconstorig;
tordata2.torconst=torconstorig;   
tordata.rfor=rfororig; //-BE CAREFUL - MUST BE SURE rfororig defined/geo.maxside = origmaxside;   
geo.maxside = origmaxside;   
    if (&client_data) {
        XtRemoveWorkProc (work_id);
    }
#if 1 // if = 0 then do not merge the two fits
    if(geo.fixend==3){ //NOTE - THIS WILL RETURN FINAL FUSED geo - WHICH MAY BE SHORTER THAN THE FIT IF THEY ARE VERY LONG
       copyavefpostopos(geo,geo.fnum);
       geo.fixend=0; // set back to default - necessary because if fixend = 3 draw dpllicate end residues
    }
#endif
    geo.fuse[0]= -1;  // set back to default
#if 0//DO NOT USE SINCE SIDE CHAINS ARE REFINED IN TORDYN Find optimal number of side chain atoms - also delete term residue if long side chain
//   sidenum(0,map[1],geo);//OLD - does not find "best" positon"0" means do not delete end if long side chian  map[1] passed as = den1
   sidenumreg(geo.begend[0],geo.begend[1],map[1],geo); // finds sidenum also defines geo.cbden = 1 or 0 if include Cb in denity in avedenreg
#endif
#if 1
float finalden,avecb2,aveco;
int nbad;
int resbad[NAFIT];
#if 0
float dist;
   dist=distv(geo.pos[geo.nend[0]][1],geo.pos[geo.nend[0]+4][1]);
   printf(" N term end Ca-Ca dist = %5.3f\n",dist);
   dist=distv(geo.pos[geo.nend[1]-4][1],geo.pos[geo.nend[1]][1]);
   printf(" C term end Ca-Ca dist = %5.3f\n",dist);
#endif
   aveden(map[1],geo,geo.pos,&finalden,&avecb2,&aveco,&nbad,resbad); // Find average density (ave)  
//   avedenreg(map[1],geo,geo.pos,&finalden,&avecb2,&nbad,
//                  geo.nend[1]-1,geo.nend[1]); // Find average density for last cterm residue additions
#if 0
   printf(" Length =%d   finalden = %5.3f avecb2 = %5.3f nbad = %d \n",
      geo.nend[1]-geo.nend[0],finalden,avecb2,nbad);
#endif
#if 0
float phimin,phimax,psimin,psimax,phi,psi;
   for(i=geo.nend[0];i<=geo.nend[1]-2;i++){
      findphipsi(geo.pos,i,&phi,&psi);
      if(checkangrange(geo,phi,psi,geo.rtype[i],&phimin,&phimax,&psimin,&psimax)==0)
          printf(" ERROR IN RES. # %d: PHI= %6.3f/PSI=%6.3f NOT IN RANGE (type = %d: %5.3f %5.3f %5.3f %5.3f)\n",
             i-geo.nend[0]+1,phi*180.0/PI,psi*180.0/PI,geo.rtype[i],phimin*180.0/PI,phimax*180.0/PI,psimin*180.0/PI,psimax*180.0/PI);
   }
   printf(" Length =%d   finalden = %5.3f avecb2 = %5.3f aveco = %5.3f nbad = %d npoor = %d\n",
      geo.nend[1]-geo.nend[0],finalden,avecb2,aveco,nbad,geo.npoor);
#endif
#endif
    XtDestroyWidget (dialog);
    XtDestroyWidget(button);
}


Boolean  dynloop(XtPointer client_data)
/* This is called as work process so can be interrupted
If return False, loop keeps being called until interrupted by
   pushing button - which then calls done()
If return True (commented out) then quits after one call to tordyn
   and calls done()
*/
{
Widget dialog = (Widget) client_data;

//     if(tordata.adata[1]>2) //This restarts interactive tor dyn each time called   
//       tordata.adata[1] = 2; 


    tordyn(map[1],geo,tordata); // Master routine for torsiona dynamics (tordata.adata[3] steps)
    draw_screen(client_data);
#if 1 // This is standard procedure - repeats loop until push quit
    return False;
#endif
#if 0   // debug - runs one time and quits 
XtPointer  call_data;
dyndone(dialog,client_data,call_data);
    return True;
#endif
}

#if 1
void dynworkfunc(XtPointer  client_data)
/* This is a generic routine to call routine in the
    the form of work function that can be interrupted
Procedure:
  1) client_data is an XtAppContext value  (e.g. sc.appctx)
  2) The only part that needs to be modified for each function
      is the line:
        work_id = XtAppAddWorkProc (app,dynloop, dialog);
     Substitute for "dynloop" what ever function you want where
      function of must be of form:
            Boolean  dynloop(XtPointer client_data)
     And it must return value False to keep running.
 3) Need also:
      a) subroutine "done" defined above
      b) and globally defined:
             extern Widget toplevel;
             Widget button;
             static XtWorkProcId  work_id;
Note:
     This procedure is adapted from working.c sample program.
       It calls a pushbutton ("button") that is never appears - I am sure
        this can be avoid, but do not know how.  "label" is
       the label that would appear on the button if it did appear.
    see motifman/ch21 for details
    Also see fit.cworktest - for a fuller, earlier version of this routine.
*/
{
    XtAppContext  app = (XtAppContext) client_data;
    Widget        dialog;
    XmString      stop_txt;
    Arg           args[5];
    int           n;
//    Boolean       count();
    int truefalse=1;

    XmString label = XmStringCreateLocalized (""); // 
    button = XtVaCreateManagedWidget ("button",
        xmPushButtonWidgetClass,toplevel,
        XmNlabelString,          label,
        NULL);
    /* Create the dialog -- the "cancel" button says "Stop" */
    n = 0;
    stop_txt = XmStringCreateLocalized ("Stop");
    XtSetArg(args[n], XmNcancelLabelString, stop_txt); n++;
    dialog = XmCreateWorkingDialog (button, "working", args, n);
    XmStringFree (stop_txt);

    work_id = XtAppAddWorkProc (app,dynloop, dialog);
    XtUnmanageChild (XmMessageBoxGetChild (dialog, XmDIALOG_OK_BUTTON));
    XtUnmanageChild (XmMessageBoxGetChild (dialog, XmDIALOG_HELP_BUTTON));

    /* Use cancel button to stop counting. True = remove work proc */

    XtAddCallback (dialog, XmNcancelCallback, dyndone,&truefalse);

    XtManageChild (dialog);
    XtPopup (XtParent (dialog), XtGrabNone);
}
#endif


void fuse_ok_pushed(Widget w,XtPointer  client_data,XtPointer  call_data)
/*  called from routines in drawwindow.c++
fuse 2 fits files
    geo.fuse[1] = # of nterm;  geo.fuse[2] = # of cterm
*/
{
   int i,istart;
   float dist;

if(verbose>=2)
  printf(" geo.fuse[0]==%d:  nterm = %d  cterm = %d\n",geo.fuse[0],geo.fuse[1],geo.fuse[2]);
   geo.fixend = 3;  // Indicates dynamcis about center
   geo.quit = 0;
   copyreg2fitstogeo(geo,fit[ geo.fuse[1] ],fit[ geo.fuse[2] ],&istart);
//   copy2fitstogeo(geo,fit[ geo.fuse[1] ],fit[ geo.fuse[2] ]);
//   maxdist = 3.0; // maximum allowed distance between atoms to be fused
   dist = distv(geo.fpos[0][1],geo.fpos[1][1]); // check Ca dist
   if(dist> geo.maxfusedist){
       geo.fuse[0]=geo.fuse[1]=geo.fuse[2] = -1;
       errormessage(toplevel,"ERROR1: ATOMS TWO FAR APART TO FUSE - QUITTING");
       goto quitrout;
   }
   dist = distv(geo.fpos[0][6],geo.fpos[1][6]); // check Ca dist
   if(dist> geo.maxfusedist){
       geo.fuse[0]=geo.fuse[1]=geo.fuse[2] = -1;
       errormessage(toplevel,"ERROR2: ATOMS TWO FAR APART TO FUSE - QUITTING");
       goto quitrout;
    }
    for(i=2;i<=4;i++){ // C, O and N atoms
        dist = distv(geo.fpos[0][i],geo.fpos[1][i]); // check Ca dist
        if(dist> geo.maxfusedist){
           geo.fuse[0]=geo.fuse[1]=geo.fuse[2] = -1;
           errormessage(toplevel,"ERROR3: ATOMS TWO FAR APART TO FUSE - QUITTING");
           goto quitrout;
        }
     } // i
   if(geo.fuse[0]!= -1){ // If atoms close enough to fuse
      Widget shell = (Widget) client_data;
      XtDestroyWidget (shell);
      if(tordata.adata[1]>2) //This restarts interactive tor dyn each time called   
         tordata.adata[1] = 2; 
      if(tordata2.adata[1]>2) //This restarts interactive tor dyn each time called   
         tordata2.adata[1] = 2; 
      sc.drawgeo = 1;  
      sc.drawfit = -1;
      dynworkfunc(sc.appctx); // workfunc that calls tordyn
   }
   quitrout:;
//   geo.fnum = -1; // Indicates have not picked a current geo residues
}


static void inputfit_ok_pushed(Widget w,XtPointer  client_data,XtPointer  call_data)
/* New on 27apr99  - input fit # that want to convert to geo
*/
{
    printf(" OK pushed\n");
    char* text[5];
    int fitn;

    text[0] =   XmTextFieldGetString (ss.w[0]);
    fitn = atoi(text[0]);
    if( (fitn <= fitnum[0])&&(fitn>=1) ){ // if  text[0]==null , fitnum = 0       
      copyfittogeo(geo,fit[fitn]);
      if(geo.badfit==0) // fit is  too long
        errormessage(toplevel,"ERROR: THIS FIT IS TOO LONG TO MAKE 'ACTIVE' - CUT FIT INTO 40 RESIDUE SECTIONS");
      else{
        sc.drawgeo=1;
        geo.pickfitnum = fitn;
        geo.fitn = fitn;  // this is used in extendfit 
#if 1 // run aveden
float avecb2,aveco,finalden,phi,psi;
float psimin,psimax,phimin,phimax;
int i,resbad[NAFIT],nbad,rtype;
   aveden(map[1],geo,geo.pos,&finalden,&avecb2,&aveco,&nbad,resbad); // Find average density (ave) for initial orientation 
   for(i=geo.nend[0];i<=geo.nend[1]-2;i++){
      findphipsi(geo.pos,i,&phi,&psi);
      rtype = geo.rtype[ i+1 ];
      if(checkangrange(geo,phi,psi,rtype,&phimin,&phimax,&psimin,&psimax)==0)
         printf(" PHI= %6.3f/PSI=%6.3f GREATER THAN LIMIT (2PI = 360)\n",
             phi*180.0/PI,psi*180.0/PI);
   }
   printf("In input fit:  finalden = %5.3f avecb2 = %5.3f avecb = %5.3f nbad = %d \n",
      finalden,avecb2,aveco,nbad);
#endif
     } // fit is not too long
   } // fitnum!=0
    Widget shell = (Widget) client_data;
    XtDestroyWidget (shell);
}


void inputfit_dialog(Widget w)  // Dialog for inputting fit #
{
    Widget dialog, rc;
    XmString string;
    Arg args[5];
    int n = 0;
    static ActionAreaItem action_items[] = {
        { "OK",     inputfit_ok_pushed,     NULL          },
        { "Clear",  clear_pushed,  NULL          },
        { "Cancel", close_dialog,  NULL          },
        { "Help",   help,          "Help Button" },
    };
    /* Create a TemplateDialog that will contain the control area
     * and the action area buttons for the dialog
     */ 
    string = XmStringCreateLocalized ("Dialog Shell");
    XtSetArg (args[n], XmNdialogTitle, string); n++;
    XtSetArg (args[n], XmNautoUnmanage, False); n++;
    dialog = XmCreateTemplateDialog (toplevel, "dialog", args, n);
    XmStringFree (string);

    /* now that the dialog is created, set the Cancel button's
     * client data, so close_dialog() will know what to destroy.
     */
    action_items[0].data=action_items[2].data = (XtPointer) dialog;

    /* create the control area which contains a
     * Label gadget and a TextField widget.
     */
    rc = XtVaCreateWidget ("control_area", 
        xmRowColumnWidgetClass, dialog, NULL);
    ss.num = 1;
    string = XmStringCreateLocalized ("ENTER FIT NUMBER:");
    XtVaCreateManagedWidget ("label", xmLabelGadgetClass, rc,
        XmNlabelString,    string,
        NULL);
    XmStringFree (string);
    ss.w[0] = XtVaCreateManagedWidget ("text-field",xmTextFieldWidgetClass, rc, NULL);
   /* RowColumn is full -- now manage */
    XtManageChild (rc);
  
    /* Create the action area. */
    CreateActionArea (dialog, action_items, XtNumber (action_items));

    /* callback for Return in TextField.  Use dialog as client data */
//    XtAddCallback (ss.w[0], XmNactivateCallback,activate_cb, dialog);

    XtManageChild (dialog);
    XtPopup (XtParent (dialog), XtGrabNone);
    glClearColor(backcolv[0],backcolv[1],backcolv[2],0);//background color :red, green, blue, and alpha = black
}

void build_cb(Widget widget,XtPointer client_data,XtPointer  call_data)
{
   int item_no = (int) client_data;
   int nrank;
   char fitpdbfile[300];
#if 1
torconstorig = tordata.torconst;
rfororig = tordata.rfor;
origmaxside = geo.maxside;
#endif
  if(item_no==0){ // Call trace bones routines
     tracepep(map[1],geo,bone[1]);
     sc.drawfit = 1;
     if (widget = XtNameToWidget (buildmenu,"button_3")) //  Turn on check box for drawfit
            XtVaSetValues (widget, XmNset,TRUE, NULL);
     printf( " CPU time = %d\n",clock());  // start clock
   }
   else if(item_no==1){ // Extend the "fit" peptides
//      extendfit(fitset,map[1],geo);
        extendandfusebatch(fitset,map[1],geo); // Tries to extend and fuse all fits
  }
  else if(item_no==2){ // fuse two picked fits
     geo.fuse[0]=0; // Indicates start picking fits to fuse
     geo.fuse[1]=geo.fuse[2]= -1; // indicates not yet assigned
     errormessage(toplevel,"PICK NEAR ENDS OF 2 FITS YOU WANT TO FUSE");
  }
  else if(item_no==3){ //  recallfit
   readfit(geo,maidfile.fitfile);
   if(fitnum[0]>0){
     fitset.rank[0][0] = 0;  // set back to zero when ever read - indicates ranked set is not used
     sc.drawfit = 1; // turn on drawing of fit
     if (widget = XtNameToWidget (fitmenu,"button_10")) //  Turn on check box for drawing fit
            XtVaSetValues (widget, XmNset,TRUE, NULL);
#if 1 // Turn on routines to test and debug the fits
#include "testfit.inc"
#endif
   }// fitnum>0
  } // recallfit
  else if(item_no==4){ //  recall backup fit
     readfit(geo,"fit.backup");
     if(fitnum[0]>0){
       sc.drawfit = 1; // turn on drawing of fit
       if (widget = XtNameToWidget (fitmenu,"button_10")) //  Turn on check box for drawing fit
            XtVaSetValues (widget, XmNset,TRUE, NULL);
     }
  }
  else if(item_no==5) //  drawfit on/off
     sc.drawfit = -sc.drawfit; 
  else if(item_no==6){ //  pickfit
     sc.pickfit = -sc.pickfit; 
     if(geo.fuse[0] == -1) // if fusion turned off, reset
        geo.fuse[1]=geo.fuse[2] = -1;
  }
  else if(item_no==7){ //  inputfit
     if(geo.fuse[0] == -1) // if fusion turned off, reset
        geo.fuse[1]=geo.fuse[2] = -1;
     inputfit_dialog(toplevel);
  }
  else if(item_no==8){ // draw one ranked fit
     sc.drawfit = 1; // turn on drawing of fit
     readrankfit("rankedfitfile",&nrank,fit,1); // "1" means start with fit[1]
//     fitnum[0] = nrank; // Now read in readset

#if 1 // run avedenreg
float avecb2,lastden;
int ii,nbad;
   for(ii=1;ii<=fitnum[0];ii++){
     copyfittogeo(geo,fit[ii]);
     avedenreg(map[1],geo,geo.pos,&lastden,&avecb2,&nbad,
                  geo.nend[1]-2,geo.nend[1]); // Find average density for last 2 (nend-2) or  4 (nend -4) additions
     printf("In  fit %d: Length =%d   lastden = %5.3f  aveco = %5.3f nbad = %d\n",
         ii,geo.nend[1]-geo.nend[0],lastden,avecb2,nbad);
   } // ii
#endif
  } 
  else if(item_no==9){ // draw ranked fitss
     sc.drawfit = 1; // turn on drawing of fit
#if 0 // remove segments identification from file
 int ii;
   for(ii=1;ii<=fitnum[0];ii++){
      fit[ii].val2= -1;
   }
   savefit(); //save the val2 segment unassignments
#endif;          
#if 0
     strcpy(ranknum,"rank1fit");
     readset("set1",fitset);
#endif
#if 0
     strcpy(ranknum,"rank");
     strcat(ranknum,geo.setnum);
     strcat(ranknum,"fit");
     strcat(set,
     strcpy(ranknum,"rank2fit");
#endif
     readset(geo.setfile,fitset);
#if 0
int nlap;
float maxdist;
checkoverlap(geo,fit[22],fit[15],&nlap,&maxdist);
#endif
//     fitnum[0] = nrank; // Now read in readset

#if 0 // run avedenreg
float avecb2,lastden;
int ii,nbad;
   for(ii=1;ii<=fitnum[0];ii++){
     copyfittogeo(geo,fit[ii]);
     avedenreg(map[1],geo,geo.pos,&lastden,&avecb2,&nbad,
                  geo.nend[1]-2,geo.nend[1]); // Find average density for last 2 (nend-2) or  4 (nend -4) additions
     printf("In  fit %d: Length =%d   lastden = %5.3f  aveco = %5.3f nbad = %d\n",
         ii,geo.nend[1]-geo.nend[0],lastden,avecb2,nbad);
   } // ii
#endif
  } // 8 
  else if(item_no==10){ // fittopdb
     strcpy(fitpdbfile,maidfile.name);
     strcat(fitpdbfile,"_model.pdb");
//     writefittopdb(map[1],geo,fit,fitnum,fitpdbfile); // Use this version if segment not assigned
//     writefittopdbassign(map[1],geo,fit,fitnum,fitpdbfile);// This writes sequence assingnd fits in order
     writefittopdbgen(map[1],geo,fit,fitnum,fitpdbfile);//Calls either of above This writes sequence assingnd fits in order
  }
  else if(item_no==11){ // remove fit/On/off
     geo.removefit = -geo.removefit;
     errormessage(toplevel,"PICK FIT THAT YOU WANT DELETED");
  }
}

void fit_cb(Widget widget,XtPointer client_data,XtPointer  call_data)
//Define  1=ca,2=c,3=o;4=n,5=cb; 6=cb2 in geo.pos[i]...
{
   int item_no = (int) client_data;
   int j;
   int origuserank,orignmaxext;
#if 1
torconstorig = tordata.torconst;
rfororig = tordata.rfor;
origmaxside = geo.maxside;
#endif
#if 0
geo.maxside = 1;
printf(" SETTING  geo.maxside = 1 to mimic extendfit\n");
#endif
#if 0
tordata.rfor= 0.0*rfororig; /*Force constant for density force in torsional dyn*/
printf(" Multiplying rfor by factor of %5.3f\n",tordata.rfor/rfororig);
#endif
   if( (geo.nend[1]==0)&&(item_no<9) ){
       errormessage(toplevel,"ERROR: MUST FIRST PICK A FIT");
       goto quitcb;
   }
    else if(item_no==0){ // Start torsiondyn  -all
     if(tordata.adata[1]>2) //This restarts interactive tor dyn each time called   
       tordata.adata[1] = 2; 
     geo.fixend = 0;  // Indicates allow all to move
     geo.quit = 0;
     geo.oneside = 0;  // run on all residues, not just one side
     dynworkfunc(sc.appctx); // workfunc that calls tordyn
  }
   else if(item_no==1){ // Start torsiondyn - N end move, C end fixed
     if(tordata.adata[1]>2) //This restarts interactive tor dyn each time called   
       tordata.adata[1] = 2; 
     geo.fixend = 1;  // Indicates C end fixed
     geo.quit = 0;
     geo.oneside = 0;  // run on all residues, not just one side
//    tordyn(map[1],geo,tordata); // debug  just run once
     dynworkfunc(sc.appctx); // workfunc that calls tordyn
  }
   else if(item_no==2){ // Start torsiondyn - C end
     if(tordata.adata[1]>2) //This restarts interactive tor dyn each time called   
       tordata.adata[1] = 2; 
     geo.fixend = 2;  //  Indicates N end fixed
     geo.quit = 0;
     geo.oneside = 0;  // run on all residues, not just one side
     dynworkfunc(sc.appctx); // workfunc that calls tordyn
  }
  else if(item_no==3){ // Start torsiondyn  about center atom = geo.fnum
     if(tordata.adata[1]>2) //This restarts interactive tor dyn each time called   
       tordata.adata[1] = 2; 
     if(tordata2.adata[1]>2) //This restarts interactive tor dyn each time called   
       tordata2.adata[1] = 2; 
     geo.fixend = 3;  // Indicates dynamcis about center
     geo.quit = 0;
     geo.oneside = 0;  // run on all residues, not just one side
     for(j=0;j<=1;j++){ // j=0 is nterm end, j=1 is cterm end
       copypostofpos(geo,geo.fnum,j);
     } // j
     dynworkfunc(sc.appctx); // workfunc that calls tordyn
  }
  else if(item_no==6){ // REmove cterm residue 
    geo.nafit=geo.nafit-1; // use last added residue
    geo.nend[1] = geo.nend[1]-1;
  }
  else if(item_no==7){ //  REmove nterm residue
    geo.nafit=geo.nafit-1; // use last added residue
    geo.nend[0] = geo.nend[0]+1;
printf("nend[0] = %d\n",geo.nend[0]);
  }
  else if(item_no==8){ // Extend picked residue at cterm
printf("Extending geo by one residue at c term end\n");
    origuserank = geo.userank;
    orignmaxext = geo.nmaxext;
    geo.nmaxext = 1;
//    extworkfunc(sc.appctx); // workfunc that calls tordyn DOES NOT WORK - SEE NOTE AT TOP
    geo.userank=2; // this will now extend on edited bones
#if 1
    if(fitset.rank[0][0]==0) // this indicates are calling extend for an original fit
        geo.extendfitnum = geo.pickfitnum;  // The fit num that is being extended
#endif
//    extendfit(fitset,map[1],geo);
    sc.drawfit = 1; // turn on drawing of fit
    sc.drawgeo = -1; // turn off drawing of geo
//    readset(geo.setfile,fitset); // now called in extendfit.c++ 
    geo.userank=origuserank;
    geo.nmaxext=orignmaxext;
  }
  else if(item_no==9) //  drawgeo on/off
     sc.drawgeo = -sc.drawgeo; 
  else if(item_no==10){ // save new geo to fitfile and reads fit again to display new fit
#if 0
     if(fitset.rank[0][0]!=0) // this indicates have extended a fit
        geo.pickfitnum = geo.extendfitnum;
#endif
     savepick(geo);  // this replaces pickfitnum by geo and just stores orignal set of fits
     readfit(geo,maidfile.fitfile);
  } 
  else if(item_no==11){ // drawrotomer - NOW (28jul99 - finds best side chain for picked fit- using know aa sequence
     if(geo.seqnum== -1){ // indicats pdb sequence not yet read - call readsequence
        if(readsequence(geo,maidfile.pdbsequence)!=1){ // indicates not successfully read
           errormessage(toplevel,"ERROR: one letter sequence file 'maidfile.pdbsequence' is missing");
           goto skiprot;
        }
     }
#if 1 // Just call assignsegment using current fit
    assignseqment(map[1],geo,"expand");
#endif
#if 0 // analyze and rank a.a. - reads file maidfile.resqual - made by testseq
    geo.seqnum = -1; // indicates pdbsequence not read
    rankseq(geo,maidfile.resqual);
#endif
#if 0  // assigns fit.val1 to each fit
   assignval1();
#endif
 // Call testseq routine that prints qual for each residue type 
// Prints out file resqual - used by rankseq()
// NOTE - if picfitnum not define - the use fit = 1,.. totfitnum in testseq

#if 0 // If debug =1 in testseq(), then writes out for all fits that have sequence assigned
     geo.pickfitnum = 2; // fit number - not used if debug = 1
     geo.resnum = 180;// sequence  number for fit 1 res 1  - not used if debug = 1
     geo.fnum = 1; // res. number in fit
     testseq(map[1],geo,rot);
#if 0 // run rankseq after
     geo.seqnum = -1; // indicates pdbsequence not read
    rankseq(geo,maidfile.resqual);
#endif
#endif

#if 0// Debug - check direct call of buildseg
     geo.pickfitnum = 1; // fit number
     geo.resnum = -fit[geo.pickfitnum].val1 ; // pdb sequence number
     geo.fnum = 1; // res. number in fit
     buildseq(map[1],geo,rot);
#endif

#if 0 // routine to run interactive picking and assigning of sidechaind
     geo.resnum = -1000; //This is signal to turn on assign routine when pick geo
     errormessage(toplevel,"PICK A 'FIT' RESIDUE WHOSE SEQEUNCE NUMBER IS KNOWN\n");
#endif
#if 0 // if = 1 used to drawrotomer and check dynamics
   int i,i0,resnum,fitn;
//     sc.drawfit = 1; // turn on drawing of fit
     sc.drawrot = 1;// turn on drawing of rotomer
     readfit(geo,maidfile.fitfile);
     setuprotomer(rot);
     resnum = 2;
     resnum = 5;
     fitn = 4;
     fitn = 3;
     fitn = 2;
     fitn = 1;
     resnum = 1;
     for(i=1;i<=rot[rottype].rotnum;i++)
         buildrot(geo,fit[fitn].pos[resnum][4],fit[fitn].pos[resnum][1],
              fit[fitn].pos[resnum][5],rottype,rot[rottype].chiang[i],rotpos[i]);
printf("chiang 1,2 = %5.3f  %5.3f\n",
   rot[rottype].chiang[1][0],rot[rottype].chiang[1][1] );
#if 1 // do dynamics
//     copyonerottofit(rotpos[2],fit[4],11,rottype);// copy rotomer side chain to fit
//     copyonerottofit(rotpos[1],fit[fitn],resnum,rottype);// copy rotomer side chain to fit
     sc.drawgeo= -1; // turn of drawing of geo - just drawfit
     sc.drawrot= -1;
     geo.pickfitnum = fitn; 
     copyfittogeo(geo,fit[fitn]);
     i0 = geo.nend[0];
     copyonerottogeo(rotpos[2],geo,i0+resnum,rottype);// copy rotomer side chain to geo
     geo.oneside = resnum;  //= GLN run dynamics just on this residue side chain
#endif
#endif

#if 0 // just run assignseq - NOTE this is old routine - not in current assignseg.c++ (see assignseq.c5aug99)
     assignsequence(map[1],geo,rot);
     sc.drawgeo=1;
#endif
     skiprot:;
  } // 11
 quitcb:; 
}

void addc_cb(Widget widget,XtPointer client_data,XtPointer  call_data)
{
    int item_no = (int) client_data;
    if(geo.nend[1]==0){
       errormessage(toplevel,"ERROR: MUST FIRST PICK A FIT");
       goto quitaddc;
    }
printf(" constraint number = %d\n",item_no);
     addcterm(geo,map[1],item_no);
#if 1 // den for last residue
float avecb2,finalden;
int nbad;
   avedenreg(map[1],geo,geo.pos,&finalden,&avecb2,&nbad,
                  geo.nend[1]-1,geo.nend[1]); // Find average density for last cterm residue additions
   printf(" Length =%d   finalden = %5.3f avecb2 = %5.3f nbad = %d \n",
      geo.nend[1]-geo.nend[0],finalden,avecb2,nbad);
#endif
     quitaddc:;
}

void addn_cb(Widget widget,XtPointer client_data,XtPointer  call_data)
{
    int item_no = (int) client_data;
    if(geo.nend[1]==0){
       errormessage(toplevel,"ERROR: MUST FIRST PICK A FIT");
       goto quitaddn;
    }
printf(" constraint number = %d\n",item_no);
//     addnterm(geo,map[1],item_no);
     naddnterm(geo,map[1],item_no);// New version - use findstrongphipsi
     quitaddn:;
}

void buildpulldown(Widget menubar)
{
   XmString traceonoff,extend,recallfit,drawfit,inputfit;
   XmString pickfit,fusepicks,fittopdb,recallbackupfit;
   XmString  drawrankset,drawrankfit,deletefit;

   traceonoff = XmStringCreateLocalized ("AUTO TRACE");
   extend = XmStringCreateLocalized ("EXTEND ALL FITS");
   fusepicks=  XmStringCreateLocalized("FUSE 2 FITS");
   recallfit=  XmStringCreateLocalized("READ FIT FILE");
   recallbackupfit=  XmStringCreateLocalized("READ BACKUP FIT FILE");
   drawfit=  XmStringCreateLocalized("DRAW FIT ON/OFF");
   pickfit=  XmStringCreateLocalized("PICK ACTIVE ON/OFF");
   inputfit =  XmStringCreateLocalized("INPUT FIT # TO ACTIVE");
   drawrankset = XmStringCreateLocalized("DRAW SET OF RANKED FITS");
   drawrankfit = XmStringCreateLocalized("DRAW ONE RANKED FIT");
   fittopdb = XmStringCreateLocalized("WRITE FIT AS PDB");
   deletefit = XmStringCreateLocalized("DELETE ONE FIT");
   buildmenu=XmVaCreateSimplePulldownMenu (menubar, "build_menu", 3, build_cb,
        XmVaPUSHBUTTON,traceonoff,'T', NULL, NULL,  // button_0
        XmVaPUSHBUTTON,extend,'T', NULL, NULL,  // button_1
        XmVaPUSHBUTTON,fusepicks,'FP', NULL, NULL,  // button_2
        XmVaPUSHBUTTON,recallfit,'F', NULL, NULL,  // button_3
        XmVaPUSHBUTTON,recallbackupfit,'F', NULL, NULL,  // button_4
        XmVaCHECKBUTTON,drawfit,'DF', NULL, NULL,  // button_5
        XmVaCHECKBUTTON,pickfit,'DF', NULL, NULL,  // button_6
        XmVaPUSHBUTTON,inputfit,'DF', NULL, NULL,  // button_7
        XmVaPUSHBUTTON,drawrankfit,'DR', NULL, NULL,  // button_8
        XmVaPUSHBUTTON,drawrankset,'DR', NULL, NULL,  // button_9
        XmVaPUSHBUTTON,fittopdb,'DR', NULL, NULL,  // button_10
        XmVaPUSHBUTTON,deletefit,'DR', NULL, NULL,  // button_11
        NULL);
#if 1
    XmStringFree (traceonoff);   
    XmStringFree (extend);   
    XmStringFree (drawfit);   
    XmStringFree (recallfit);   
    XmStringFree (recallbackupfit);   
    XmStringFree (pickfit);   
    XmStringFree (inputfit);   
    XmStringFree (drawrankfit);   
    XmStringFree (drawrankset);
    XmStringFree (fusepicks);   
    XmStringFree (fittopdb);   
    XmStringFree (deletefit);   
#endif   
}
 
void fitpulldown(Widget menubar)
{
   XmString tordynallonoff,tordyncend,tordynnend;
   XmString addcresidue,addnresidue,remcresidue,remnresidue;
   XmString savepickfit,extendpickcterm;
   XmString  stype[10],drawrotomer,drawgeo;
   XmString tordyncen;
   Widget addcpullright,addnpullright;
   Widget widget;

   tordynallonoff= XmStringCreateLocalized ("TOR DYNAMICS ALL ");
   tordyncend= XmStringCreateLocalized ("TOR DYNAMICS C END ");
   tordynnend= XmStringCreateLocalized ("TOR DYNAMICS N END ");
   tordyncen= XmStringCreateLocalized ("TOR DYNAMICS ABOUT PICK ");
   addcresidue=  XmStringCreateLocalized("ADD RESIDUE - C TERM");
   addnresidue=  XmStringCreateLocalized("ADD RESIDUE - N TERM");
   remcresidue=  XmStringCreateLocalized("REMOVE RESIDUE - C TERM");
   remnresidue=  XmStringCreateLocalized("REMOVE RESIDUE - N TERM");
   extendpickcterm=  XmStringCreateLocalized("EXTEND ACTIVE - C TERM");
   drawgeo=  XmStringCreateLocalized("DRAW ACTIVE ON/OFF");
   savepickfit = XmStringCreateLocalized("SAVE ACTIVE");
   drawrotomer = XmStringCreateLocalized("DRAW ROTOMER");
//   constraintst = XmStringCreateLocalized("PICK CONSTRINT TYPE"); 
   stype[0] = XmStringCreateLocalized ("NONE");
   stype[1] = XmStringCreateLocalized ("HELIX (1)");
   stype[2] = XmStringCreateLocalized ("SHEET (2)");
   stype[3] = XmStringCreateLocalized ("LEFT HELIX (3)");
   stype[4] = XmStringCreateLocalized ("EPSILON (4)");
   stype[5] = XmStringCreateLocalized ("DELTA (5)");
   stype[6] = XmStringCreateLocalized ("GAMMAR (6)");
   fitmenu=XmVaCreateSimplePulldownMenu (menubar, "fit_menu", 4, fit_cb,
        XmVaPUSHBUTTON,tordynallonoff,'D', NULL, NULL,  // button_0
        XmVaPUSHBUTTON,tordynnend,'N', NULL, NULL,  // button_1
        XmVaPUSHBUTTON,tordyncend,'C', NULL, NULL,  // button_2
        XmVaPUSHBUTTON,tordyncen,'M', NULL, NULL,  // button_3
        XmVaCASCADEBUTTON,addcresidue,'W',   // button_4
        XmVaCASCADEBUTTON,addnresidue,'W',   // button_5
        XmVaPUSHBUTTON,remcresidue,'RC', NULL, NULL,  // button_6
        XmVaPUSHBUTTON,remnresidue,'RN', NULL, NULL,  // button_7
        XmVaPUSHBUTTON,extendpickcterm,'RN', NULL, NULL,  // button_8
        XmVaCHECKBUTTON,drawgeo,'DF', NULL, NULL,  // button_9
        XmVaPUSHBUTTON,savepickfit,'DF', NULL, NULL,  // button_10
        XmVaPUSHBUTTON,drawrotomer,'DR', NULL, NULL,  // button_11
        NULL);

  addcpullright = XmVaCreateSimplePulldownMenu (fitmenu,
            "pullright", 4 ,addc_cb,
             XmVaPUSHBUTTON,stype[0],NULL, NULL, NULL,
             XmVaPUSHBUTTON,stype[1],NULL, NULL, NULL,
             XmVaPUSHBUTTON,stype[2],NULL, NULL, NULL,
             XmVaPUSHBUTTON,stype[3],NULL, NULL, NULL,
             XmVaPUSHBUTTON,stype[4],NULL, NULL, NULL,
             XmVaPUSHBUTTON,stype[5],NULL, NULL, NULL,
             XmVaPUSHBUTTON,stype[6],NULL, NULL, NULL,
             NULL);
  addnpullright = XmVaCreateSimplePulldownMenu (fitmenu,
            "pullright", 5 ,addn_cb,
             XmVaPUSHBUTTON,stype[0],NULL, NULL, NULL,
             XmVaPUSHBUTTON,stype[1],NULL, NULL, NULL,
             XmVaPUSHBUTTON,stype[2],NULL, NULL, NULL,
             XmVaPUSHBUTTON,stype[3],NULL, NULL, NULL,
             XmVaPUSHBUTTON,stype[4],NULL, NULL, NULL,
             XmVaPUSHBUTTON,stype[5],NULL, NULL, NULL,
             XmVaPUSHBUTTON,stype[6],NULL, NULL, NULL,
             NULL);
    XmStringFree (tordynallonoff);   
    XmStringFree (tordynnend);   
    XmStringFree (tordyncend);   
    XmStringFree (addcresidue);   
    XmStringFree (addnresidue);   
    XmStringFree (remcresidue);   
    XmStringFree (remnresidue);   
    XmStringFree (savepickfit);   
    XmStringFree (extendpickcterm);   
    XmStringFree (drawrotomer);
    XmStringFree (tordyncen);   
    XmStringFree (drawgeo);   
    // Note these value must be set = -1 (or 1) in initializescreen.c++   
    if (widget = XtNameToWidget (fitmenu,"button_10")) //  Turn on check box for drawfit
            XtVaSetValues (widget, XmNset,FALSE, NULL);
    if (widget = XtNameToWidget (fitmenu,"button_11")) //  Turn off check box for picking fit
            XtVaSetValues (widget, XmNset,FALSE, NULL);
    if (widget = XtNameToWidget (fitmenu,"button_12")) //  Turn off check box for drawing picked fit (geo)
            XtVaSetValues (widget, XmNset,FALSE, NULL);
}
